Apple will inform the user that their card has expired 24 hours before renewal. Your app can check the intention-to-renew of the user before expiration. If that intention is not ‘cancel’ then it can continue the subscription after it expires for a few days.
From the docs (emphasis mine):
Handle Lapsed Subscriptions
The App Store renews the subscription slightly before it expires, to prevent any lapse in the subscription. However, lapses are still possible. For example, if the user’s payment information is no longer valid, the first renewal attempt fails. Billing-related issues trigger the subscription to enter a billing retry state where the App Store attempts to renew the subscription for up to 60 days. You can check the
is_in_billing_retry_periodvalues to monitor the retry status of the subscription. During this period, your app may optionally offer a grace period to the user and show them a message in the app to update their payment information. Additionally, your app can deep link customers to the payment details page within App Store on their device by opening this URL
The user can also cancel their subscription by disabling auto-renew and intentionally letting their subscription lapse. This action triggers the App Store to send your server a status update notification of type
DID_CHANGE_RENEWAL_STATUS. Your server can parse the
auto_renew_status_change_dateto determine the current renewal status of the subscription.
You can also check the
expiration_intentfield in the receipt to further validate the reason for the subscription to lapse. Make sure your app's subscription logic can handle different values of
expires_dateto show the appropriate message to the user.
If you're asking how to use your own process, instead, I can imagine using a pending renew to trigger a trial period, but I can also imagine that causing issues with the overall process so I would not recommend DIY in this example.
So this is possible (without rolling your own solution) from today, but there's very little information on how to implement and test it apart from "tick the box":
Can anybody from the App Store team let us know if there's a flag that we can set in order to test the grace period? Also, what do we receive in the transaction queue, and what do we receive in the server to server notification to tell us that the user is in the official grace period?
We can of course check for a billing error by looking at the `expiration_intent` value. We can check whether the user
`is_in_billing_retry_period` - a period that I believe is 60 days, and is therefore unrelated to the "grace period" of 16 days for a yearly subscription.
The only way that I can think of that would allow the implementation of the new Grace Period to be as minimal as it appears is if the `expires_date` of the subscription is changed to include the grace period (either from the beginning, or when it kicks in), but in that case, we'd not be able to use the `expires_date` as an indicator that the user is in the grace period. Likewise, we'd not be able to use the `is_in_billing_retry_period` because that period is much longer than the grace period.
All of this leads me to believe that there must be some new property in the receipt and/or server to server notifications that tells us what's going on.
1) rarely, if ever, will you get a response on this forum "from the App Store team".
2) I surmise (I have not experimented with it so this is "IMHGuess") that the only difference between Grace Period on and off is the information that Apple will place in the receipt. With Grace Period on the new expires_date will extend from the previous expiration date. With Grace Period off the new expires_date will extend from the date the subscription was actually renewed if it lapsed for more than a short time. Unclear to me what "a short time" would be. I don't think there will be a new original_transaction_identifier but the community would benefit from any observations of what fields get reset with Grace Period on or off.
>Can anybody from the App Store team let us know if...
Our resident IAP (and other topics) engr./SME seems to be Rich. I'd perhaps ping him with those specific questions...he seems to thankfully participate here* routinely enough/when he has time - good luck.
rich kubota - email@example.com
*See the 'Forums Personnel' disclaimer here: https://developer.apple.com/support/forums/
is_in_billing_retry_periodkeys are not available in the receipt on device as you can see in this documentation: https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html
expiration_dateis the only key that can be used to determine the subscription status when using on device receipt validation.
How does the new grace period setting affect the
expiration_datevalue in the local receipt?
Working with the local receipt isn't recommended in this example, I believe.
I would expect it to be unaffected. The app would be responsible for either terminating subscription rights or allowing them to continue for a grace period after expiration. In exchange for allowing them to continue, any future renewal extends from that expiration date rather than its payment date. ........It might be useful to have some sort of externally available flag to indicate to the app that grace period is on or off. I don’t think the system provides that for on-device verification. But the device can always send the receipt to the Apple servers.
Let me respond to each of your questions specifically:
is_in_billing_retry_periodkeys are not available in the receipt on device
You can send the receipt to the Apple servers and get back these fields. Note that this is not secure - it is subject to a man-in-the-middle attack. But so what - it's only a question of whether or not you will grant the user a grace period.
Or..... just grant the grace period for a set time after expires_date. What exactly are you afraid of losing by doing that?
> How does the new grace period setting affect the
expiration_datevalue in the local receipt?
I assume you mean "expires_date" not "expiration_date". I would assume it has no effect - the subscription has expired. The grace period is something granted after expiration in exchange for not granting a full subscription period should the user choose to continue the subscription after expiration.
It turns out that the answer to this question can be found in the article "Reducing Involuntary Subscriber Churn"
I refer you to the section "Enable Billing Grace Period".
If you choose to enable Billing Grace Period, ensure that you provide full service for the subscription throughout the grace period. You can check the grace_period_expires_date_ms field in the responseBody.Pending_renewal_info array of the receipt to determine the end of this grace period duration.
To see the explanation of the grace_period_expires_date_ms field, I refer you to the declaration of the Object - responseBody.Pending_renewal_info
The presence of the "grace_period_expires_date" fields indicates that the subscription is in a grace period where billing retry is in effect. Once the billing has been resolved, the "grace_period_expires_date" fields will no longer be present. I've asked that the developer documentation be updated to explain the different scenarios which will exist in the "pending_renewal_info" field depending on the billing retry outcome.
rich kubota - firstname.lastname@example.org
developer technical support CoreOS/Hardware/MFI
All good info, Rich - thanks for the research/response.