When there is an auto-renewing subscription, consider the following model situation:
user buys 1 month subscription, lets say in January
cancels renewal
then waits until March (>1 month) and buys same subscription again
Does the AppStore return (on receipt verification) a new original_transaction_id for the new purchase? Or rephrased, can original_transaction_id be used for grouping receipts to determine intervals when user had active subscription?
Because in sandbox, when there is a simulated situation like this, it returns always original_transaction_id from the FIRST purchase of given subscription, regardless if there were some intervals where user had not active subscription. When there was multiple purchases of subscription with intervals between, when it was expired, Sandbox receipt verification returns original_purchase_date of first purchase, and expires_date of last purchase.
My problem is, to test it in live enviroment, I would have to wait more than a month to let subscriptions expire to test the exact behaviour.
I have maintained an production app with subscription for several years.
As far as I see, original_transaction_id does not change in that case you mentioned.
Moreover, original_transaction_id belongs to subscription group, not each product_id.
So it remains same in below cases.
User start subscription, stop auto-renew and expire, then start subscription again.
User start subscription and cancel it, but start again.
User start subscription and upgrade or downgrade to subscription in same group.
But this is not a guaranteed result, so you would better prepare in case original_transaction_id changes.
Related
I am facing issues with my auto-renewing subscription for an iOS app that offers auto-renewable subscription.
The Subscription Status URL is at times, not being called when the subscription is renewed. This is making it difficult for us to track the user's subscription status. Funnily, this behaviour is completely arbitrary at times it is called and everything works smoothly, but at times it is not called at all.
Also, once the user's subscription is renewed, at times the user is not charged on his/her credit card instantly. Is this behaviour normal?
You have to follow basic rules for subscription based application.
Whenever you buy any auto renew subscription, in success verify your receipt and verify expiry date.
On every application launch very receipt and verify subscription. On depending result you can notify your server.
In sandbox environment for monthly subscription it will auto renew for every 5 mins. It will auto renew for 5 times. So you can check your test cases. After that it will be expire.
In real world case subscription will auto renew before 24 hours of renew date. So if user cancels subscription before that.
If you are using SwiftyStorekit than it will be very much easy for you to handle each and every steps. Let me know you if you want more coding approach in this case.I will share example code details if you want.
The Subscription Notifications are pretty unreliable and the descriptions of how they work aren't very clear. For example:
RENEWAL events aren’t sent when a subscription renews. ... RENEWAL
is sent when a subscription has expired, then later, the user starts
the subscription again.
CANCEL does not mean a user normally cancelled their subscription. It only is sent when a user cancels their subscription via customer
support. This is also known colloquially as a refund.
Source: RevenueCat (Disclaimer: I work there)
Once I get a receipt from client and validate it by apple server, then I got a transaction id of the new purchase (it's an auto-subscription purchase) in this receipt. After a few days , I get a new receipt from the same client and validate it , strange things happen : the transaction id of that old purchase changes.
I compare the data of this purchase in the old receipt with the data in the new receipt , the only thing changes is the transaction_id field ,the original_transaction_id, purchase_date, expires_date, web_order_line_item_id and other fields are exactly same.
Than I check the database, I found about 1% transaction records have the same situation. And there is a trait, Most of their transaction id were increased or decreased by 1-2 .
I used to think the transaction id is the identifier of a purchase. Does anyone meet the same problem or know the reason?
Yes we see this happen as well. We see this triggered by 'Restore Purchase' button clicks.
If your 'Restore Purchase' button uses the restoreCompletedTransactions API then this will cause your transaction ID's to change. We have confirmed that this with Apple developer support.
Apparently you can call SKReceiptRefreshRequest instead which will just grab the latest receipt instead of replaying all of the transactions. It is my understanding that this will not cause the transaction ids to change.
We have, anecdotally, witnessed that the web_order_line_item_id values do not change across calls to restoreCompletedTransactions. However we only received an ambiguous, at best, response from Apple developer support when we asked for confirmation:
In regards to the web_order_line_item_id field, the value will change on every subsequent renewal.
You can use this, as long as you continue to store the new value as the renewal subscription events come in.
We take this to mean that the web_order_line_item_id is unique per renewal-purchase. Which neither confirms nor denies that it remains constant across calls to restoreCompletedTransactions
Additionally, I found this conference recording on Apple/Google/Amazon recurring billing very helpful (though, not for this particular case):
Rosa Gutierrez - The recurring nightmare. Implementing cross platform in-app subscription purchases
Based on latest Apple developer documentation,
web_order_line_item_id - A unique identifier for purchase events across devices, including subscription-renewal events. This value is the primary key for identifying subscription purchases.
transaction_id - You can use this value to:
Manage subscribers in your account database. Store the transaction_id, original_transaction_id, and product_id for each transaction, as a best practice to store transaction records for each customer. App Store generates a new value for transaction_id every time the subscription automatically renews or is restored on a new device.
Differentiate a purchase transaction from a restore or a renewal transaction. In a purchase transaction, the transaction_id always matches the original_transaction_id. For subscriptions, it indicates the first subscription purchase. For a restore or renewal, the transaction_id does not match the original_transaction_id. If a user restores or renews the same purchase multiple times, each restore or renewal has a different transaction_id.
In ios and amazon - we have a subscription family - example if i have purchased a one month subscription, I cannot purchase a six month subscription of the same family. But it appears that this is not the case in google play. For example a user might have a monthly subscription running with a one year subscription also running simultaneously.
Do we have to handle the logic of not allowing a user to purchase a second subscription if he has already subscribed to one subscription?
In iOS the user can change duration for the same subscription family though their iTunes subscription management page. On android you must implement this in the app using the getBuyIntentToReplaceSkus() method:
This method is used to upgrade or downgrade a subscription purchase. The method is similar to getBuyIntent(), except that it takes a list of already-purchased SKUs that are to be replaced with the SKU being purchased. When the user completes the purchase, Google Play cancels the old SKUs and credits the user with the unused value of their subscription time on a pro-rated basis. Google Play applies this credit to the new subscription, and does not begin billing the user for the new subscription until after the credit is used up.
http://developer.android.com/google/play/billing/billing_reference.html#upgrade-getBuyIntentToReplaceSkus
I am implementing a sample which includes the in-app purchase feature. The subscription is of non-renewal type.
In case of auto-renewal subscription, if the user has made a purchase, and within the validity period if the user retries to make the purchase, the iTunes shows the alert that
You are already subscribed to the purchase
and won't proceed further. The user can restore his subscription using the app restore feature.
But in case of non-renewal subscription type, if a user has made a purchase, and within the validity period if the user retries to make the purchase, the iTunes shows a confirmation alert that
You have already purchased the subscription, to renew or extend the
subscription press buy or press cancel
and if the user presses buy it proceeds further.
So, my doubt is what exactly happens in the later case (non-renewal repeated subscription).
Is the user again charged?
What happens with the user's subscription validity?
Can it be handled and controlled inside the code by me?
In case yes, any idea to proceed with would be highly appreciated and will be very helpful for me.
Thanks in Advance.
For Apple, there is no "within the validity period" for non-renewing subscriptions. The duration of the period, fortunately or unfortunately, is left up to the developer.
Yes, when the user buys a non-renewing subscription a second (or third, etc) time, the are charged again.
Subscription validity is up to the developer.
It seems common for developers to use their own server to track the expiry period of a non-renewing subscription. For example, this helps with the "restore" feature required by Apple.
You can alter the subscription start date from the day of repurchase of the APP. This will enable extended validity.
This validity extension mechanism also serves when the user realizes his subscription is about to expire and renews it before hand rather than letting the subscription end.
From the development perspective, logging the first subscribed time along with the current sub and expire time would serve the purpose.
Yes i am altering the subscription start date obviously, and i am getting this from the transaction. According to this subscription start date i am altering the expiry date as well.
The concern here is to avoid the user from getting charged again in any case if he has already subscribed. And, for that i am using iCloud to support restore functionality in user's multiple devices.
I'm having in-app purchase subscriptions in my app. I'm able to integrate and make subscriptions successfully. There are 3 different subscriptions, monthly, quarter and yearly.
So if user subscribes to monthly user can use that feature for 30 days. There's no server in my case. Only availability of some features will be activated/deactivated according to subscription.
When ever the app starts, i want to check whether user paid for subscription or not. If I'm maintaining some bool value in subscriptions, what if the user has deactivated the subscriptions from settings? How can I detect whether the subscriptions are valid or not?
You can add counter and add that counter value in a database that must be inside your app. Whenever user tries to access subscriptions you can verify from the database.
You have to post the receipt back to apple server and from the response we receive, we can identify the expiry date. Then I'll know whether the subscription is expired or renewed etc.
Visit Apple documentation