Working with Subscriptions
Apps that use subscriptions have some additional behaviors and considerations. Because subscriptions incorporate an element of time, your app needs to have the appropriate logic to determine whether the subscription is currently active and what time periods the subscription was active in the past. Your app also needs to react to new and renewed subscriptions, and properly handle expired subscriptions. Figure 5-1 shows an example subscription timeline, including some of the complexities your app needs to handle.
Calculating a Subscription’s Active Period
Your app needs to determine what content the user has access to based on the period of time the subscription was active. Consider, for example, a user with a subscription to a magazine that publishes a new issue on the first day of each month, following the timeline shown in Table 5-1.
February issue is published. It is not made available because the user has not yet subscribed. (It is made available later, after the user subscribes.)
User subscribes with a duration of one month. The February issue is the most recent issue, so it is made available immediately.
March issue is published. It is made available immediately because the user has an active subscription.
The user’s subscription automatically renews for another month.
April issue is published. It is made available immediately because the user has an active subscription.
The user prevents the subscription from renewing, ending the subscription period.
May issue is published. It is not made available because the user’s subscription has lapsed.
June issue is published. It is not immediately made available because the user’s subscription has lapsed. (It is made available later, after the user resubscribes.)
User resubscribes. June issue is made available immediately.
July issue is published. It is made available immediately because the user has an active subscription.
To implement this logic in your app, keep a record of the date that each piece of content is published. Read the Original Purchase Date and Subscription Expiration Date field from each receipt entry to determine the start and end dates of the subscription. (For information about the receipt, see Receipt Validation Programming Guide.) The user has access to all content published between each start and end date, as well as the content that was initially unlocked when the subscription was purchased. If the subscription lapsed, there will be multiple periods of time during which the subscription was active, and there will be pieces of content unlocked at the beginning of a subscription period.
Continuing the example from Table 5-1, the receipt would show the following start and end dates:
February 20 – March 20
March 20 – April 20
(The lapse from April 20 – June 17 is not recorded explicitly in the receipt.)
June 17 – July 17
The user has access to the February and June issues because they were initially unlocked when the subscription was purchased or restarted.
The user has access to the March, April, June, and July issues because the subscription is active at those times.
Expiration and Renewal
The renewal process begins with a “preflight” check, starting ten days before the expiration date. During those ten days, the App Store checks for any issues that might delay or prevent the subscription from being automatically renewed—for example, if the customer no longer has an active payment method, if the product’s price increased since the user bought the subscription, or if the product is no longer available. The App Store notifies users of any issue so that they can resolve it before the subscription needs to renew, ensuring their subscription isn’t interrupted.
During the 24-hour period before the subscription expires, the App Store starts trying to automatically renew it. The App Store makes several attempts to automatically renew the subscription over a period of time but eventually stops if there are too many failed attempts.
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 would fail. If the user doesn’t update this information until after the subscription expires, there would be a short lapse in the subscription between the expiration date and the date that a subsequent automatic renewal succeeds. The user can also disable automatic renewal and intentionally let the subscription expire, then renew it at a later date, creating a longer lapse in the subscription. Make sure your app’s subscription logic can handle lapses of various durations correctly.
After a subscription is successfully renewed, StoreKit adds a transaction for the renewal to the transaction queue. Your app checks the transaction queue on launch and handles the renewal the same way as any other transaction. Note that if your app is already running when the subscription renews, the transaction observer is not called; your app finds out about the renewal the next time it’s launched.
A subscription is paid for in full when it’s purchased and can be refunded only by contacting Apple customer service. For example, if the user accidentally buys the wrong product, customer support can cancel the subscription and issue a refund. It’s not possible for customers to change their mind in the middle of a subscription period and decide they don’t want to pay for the rest of the subscription.
To check whether a purchase has been canceled, look for the Cancellation Date field in the receipt. If the field has a date in it, regardless of the subscription’s expiration date, the purchase has been canceled—treat a canceled receipt the same as if no purchase had ever been made.
Depending on the type of product, you may be able to check only the currently active subscription, or you may need to check all past subscriptions. For example, a magazine app would need to check all past subscriptions to determine which issues the user had access to.
Product identifiers are associated with a single app. Apps that have both an iOS and macOS version have separate products with separate product identifiers on each platform. You could let users who have a subscription in an iOS app access the content from an macOS app (or vice versa), but implementing that functionality is your responsibility. You would need some system for identifying users and keeping track of what content they’ve subscribed to, similar to what you would implement for an app that uses non-renewable subscriptions.
Letting Users Manage Subscriptions
Rather than needing to code your own subscription management UI, your app can open the following URL:
Opening this URL launches iTunes or iTunes Store, and then displays the Manage Subscription page.
The Test Environment
For the sake of testing, there are some differences in behavior between auto-renewable subscriptions in the production environment and in the test environment.
Renewal happens at an accelerated rate, and auto-renewable subscriptions renew a maximum of six times per day. This lets you test how your app handles a subscription renewal, a subscription lapse, and a subscription history that includes gaps.
Because of the accelerated expiration and renewal rate, the subscription can expire before the system starts trying to renew the subscription, leaving a small lapse in the subscription period. Such lapses are also possible in production for a variety of reasons—make sure your app handles them correctly.