Non-Renewing Subscriptions are a special iOS product type where Apple does not manage auto-renewals. The developer is responsible for syncing subscription status across devices and prompting users to renew.
Important Requirements from Apple:
- Manual Renewal: You must prompt users to renew before expiration.
- Time Addition: If a user buys a new subscription before the old one expires, you must add the new time to the existing remaining time.
- Syncing: You must sync subscription status across all devices using the same Apple ID (or your own custom auth system).
Implementation Details:
- Use
store.NON_RENEWING_SUBSCRIPTION when registering the product. - These products trigger lifecycle events every time the app starts, so you must implement logic to handle these events (e.g., checking if you need to update your own server).
- Always call
p.finish() after a successful purchase to allow the product to be purchased again.
// Register the non-renewing subscription product with the store.
store.register({
id: "my_product_id",
alias: "My Product",
type: store.NON_RENEWING_SUBSCRIPTION
});
// Called when store.order("my_product_id") is executed.
store.when("my_product_id").initiated(function(p) {
my_app_utils.setIsProductPurchaseInitiated("my_product_id", true);
});
// Called when the user has cancelled purchasing.
store.when("my_product_id").cancelled(function(p) {
my_app_utils.setIsProductPurchaseInitiated("my_product_id", false);
});
// Called when the product purchase is finished (triggers on app start for non-renewing).
store.when("my_product_id").approved(function(p) {
my_product_id.purchaseNonRenewingSubscription(p.id, function success() {
// Must call finish to charge the user and allow repurchase.
p.finish();
my_app_utils.setIsProductPurchaseInitiated("my_product_id", false);
}, function error(err)) {
// Handle server error (do NOT call finish so it retries next launch)
my_app_utils.alertUserAboutServerError({
title: 'Subscription Purchase Error',
template: 'We could not store your new subscription status on our server.'
});
my_app_utils.setIsProductPurchaseInitiated("my_product_id", false);
});
});
// Handle StoreKit errors
store.error(function(e){
console.log("storekit ERROR " + e.code + ": " + e.message);
});
store.refresh();