Notification of cancellation of auto-renewal for an in-app purchase - objective-c

I am working on an iPhone app and I want to implement the new model of auto-renewal for in-app purchases. I am able to successfully implement transactions and can even get subscribed to the app, but what if the user cancels the auto renewal subscription?
How will I be able to know that it has been cancelled, and so not continue to allow access (once expired)?

You can find the expiration date of a user's subscription by sending a receipt verification to Apple's servers. Check out figure 1-3 on the In-App Purchase Programming Guide.
Basically the steps are:
On the device, get a transaction receipt for an in-app-purchase. Either one you've saved during a transaction or by calling [SKPaymentQueue restoreCompletedTransactions].
Send that receipt to your server. (This is preferred over trying to do a receipt verification with Apple's servers directly from the app, since that would require you to store your shared secret on the device.)
Send the receipt to Apple's servers from your server, and in the response look for a key named expires_date (expressed in milli seconds since Jan 1, 1970 GMT).
I used this guide to help me on the server side: Verifying Apple App Store Receipts For In App Purchases With PHP and cURL.
There is no way to determine if the user has auto-renewal turned on or off. Apple doesn't give you access to this information. The only way is to wait until the expiration date passes without a renewal.

if the receipt status is 21006 and there is a key named cancellation_date, then it's a cancellation, you can find the new expiration date in that key but it's a formatted date, if you need a better value to parse check for receipt['latest_expired_receipt_info']['cancellation_date_ms'] same as expires_date

Related

How to set trial period in shopify app?

I have created shopify app and setting up billing Api. In the App, I want to apply trial period of 20 days. I have created the charge during the app installation and send customers to confirmation url so that they can accept or decline the charge.. So I want to know that if customer decline the payment charge, then can he uses the app featurs till trial period?
If a customer declines the subscription, you still get the confirmation URL callback. Examine the charge. The status will say declined. At this point you can kill off their DB token and destroy their session. This will ensure they cannot use your App as they declined the terms.
It is one bad aspect of the whole billing scenario. I have lots of customers that are faced with a question they don't read. So they assume the trial you offer for free is activated by declining the subscription. Silly customers... still cannot operate the Internet :)

Receipt does not get updated after purchasing an automatically renewable subscription in a macOS sandbox environment

I am trying to implement StoreKit's ability to have automatically renewable subscriptions in my macOS application.
After reading dozens of pages and checking examples, I understand how everything fits together but fail to get it to work correctly.
What I am trying to do:
As soon as the app starts, check if an active subscription is available by evaluating the local receipt. I'm specifically checking the unavailability of a cancellation date in any of the In-App Purchase field entries of the receipt and whether the subscription expiration date is in the future.
In case no (active) subscription is available, I'm purchasing the subscription using StoreKit's APIs.
Both scenarios are working fine as this flow works perfectly when the subscription is purchased for the first time. However, the receipt does not get updated automatically after the subscription expiration date ends. I'm expecting this receipt to be updated periodically as also shown on Auto-renewing subscription and app receipt. As a result the first step described above fails because the expiration date at some point is in the history and hence, is considered expired.
Two things I find strange:
My SKPaymentTransactionObserver instance only gets called after purchasing the subscription (after a user explicitly buying it). It never gets called when the subscription expires and should automatically renew (as shown in the above blog post);
Explicitly asking my receipt (containing the IAP's expiration date) to be updated using the SKReceiptRefreshRequest API fails by calling it's request:didFailWithError: delegate method. The error object is nil so I cannot see why it fails updating.
I can share code but I have a feeling this is not related to code but instead is some kind of project/environment setting and/or behaviour I do not fully get.
Do you have any suggestions what to try?
After a few days of experimenting I changed the mechanism to use the server-side validation documented on https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW1. Obviously this requires a web service running somewhere and makes your environment more complicated but at least things work in a more stable (and secure) way.

How to let only paid members into my iOS app's some sections with in-app purchase?

I am developing an application where I have a section only for paid users where they purchase for the section using the in-app purhcase system in iOS. I know that I need to keep track of the purchase history myself, and this is where the problem begins. I have a database and I am capable of storing users in my database, with a web service interface. How can I create a system where a URL is pinged only when a user has made the purchase.
As an example, I have the URL:
http://example.com/registerUserPremium/userid=123456
How can I get this to be called only when a purchase is made? The most elegant way seems like Apple pinging the URL with a special user ID upon purchase, but I can't find a way of doing it. It is obviously not a solution to make the user call that URL within the app, as it can be cracked/pirated. What is a good way of providing such a mechanism that is piracy-proof. My service is web-based, so if I can get this part done, the rest relies on my server-side mechanism (the user will just send a special key that is stored in its keychain, to the server) so I'll be able to finish the project. In short, I need a way to call a URL only when a purchase is made. What are some possible solutions?
Thanks,
Can.
I see two solutions:
"Server product model" (doc): the appstore contact your servers every time a user makes a purchase. In this case you have all of the information right away.
"Builtin product model" (same doc) in which the application gets the receipt from the appstore. In this latter case you can contact your server special URL, providing the receipt information, and the server can verify that the receipt has not been tampered with asking the app store to verify (it's a simple post, see here).

Auto Renewing IAP: latest_receipt field

When a user purchases a subscription, I store the receipt on completed transaction on the server alongside a key to identify the user the receipt belongs to. When the app needs to check if the subscription is still active, it queries the server, the server validates the receipt with Apple and returns info to my app wether the subscription is expired or not.
Now the question is:
When the response returns a latest_receipt/_info field, the server should take that receipt and replace the old receipt for future verifications. What happens if there is a gap in the subscription period (e.g. the user subscribed for 1 month, then cancelled, then subscribed again) or the user changed the subscription type (e.g. from 1 month to 3 moths)?
Will the original receipt still validate, and return a latest_receipt/_info field, or do I need to store a new receipt from the new transaction?
I'm really confused on this auto-renewal thing right now, so I'm not even sure if my validation process is right.
I'm not sure about all possibilities you have to verify receipts and maybe it works your way, but we did slightly different and by that don't face your problem.
We store all the receipts on device-side (note that auto-renews result in new receipts as well). Whenever verification is necessary we post the latest device-stored receipt to server where it is verified by calling iTunes. After that the server responds to device about user's rights.
I think that's the way Apple recommends it (or at least this is how I understood Apple's docs).

Getting status on canceled/expired credit cards for recurring billing with authorize.net

We're setting up a system that will use the XML API for Automated Recurring Billing with Authorize.net.
It looks simple enough to set up a recurring billing. But we have two features that do not seem obvious
* providing customers with details on individual payments
* providing notification to customers of expired/canceled cards
Anyone familiar with a mechanism to retrieve this info in automated form? We're considering
* just listing out assumed payments based on our own calculations the start date
* emailing customers based on the expiration date of the ards
But I'm stymed on how to figure out when a transaction failed due to canceled card (and automatically notify the customer).
Can anyone comment on how they handled this issue when implementing a subscription-based service based on Authorize.net?
Authorize.Net has recently published a new ARB method "ARBGetSubscriptionStatus".
You may now easily query the status of a previously submitted ARB subscription without the need to depend on the "Silent Post Method".
Example:
<?xml version="1.0" encoding="utf-8"?> <ARBGetSubscriptionStatusRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"> <merchantAuthentication> <name>mytestacct</name> <transactionKey>112223344</transactionKey> </merchantAuthentication> <refId>Sample</refId> <subscriptionId>100748</subscriptionId> </ARBGetSubscriptionStatusRequest>
You want to use Authorize.Net's silent post feature. It will notify you of all payments made through their system including declines and expired credit cards. Your script will then be able to suspend accounts and/or notify your customers that their payments has failed.
See these link for more info:
Handling Authorize.Net ARB Subscription Failures
All About Authorize.Net’s Silent Post
Handling Authorize.Net Silent Post with PHP
You need to use the Silent POST URL
ARBGetSubscriptionStatusRequest will not work. If the first transaction (or first transaction since the ARB profile was updated, either via API or manually) fails, the status of the subscription is set to suspended. Otherwise, the status of a subscription does not change when a transaction declines or a card expires.
Using the Silent POST URL, you'll be notified of successful transactions and you can use them to update your data such as tracking a next payment due date/expiration date. You can then run a cron job and if this field has not been updated, you will know that the card was cancelled or expired.
In the event that it is still an active card but gets declined, you'll get notified as such at the Silent POST URL