iOS Post-Implementation Checklist
Once you’ve implemented the In-App Purchase SDK, review the required checks for your iOS integration before going live. These checks should be completed in a sandbox so purchases, subscriptions, entitlements, and App Store notifications are synchronized with Zoho Billing.
Initialize and Manage the SDK
The SDK should be initialized in AppDelegate’s didFinishLaunchingWithOptions.
After a user logs in, the SDK should be set with the current user’s information. When the user logs out, clearUserInfo() should be called.
If multiple users can use the same device, the previous user’s information should be cleared before another user logs in.
Verify the App Store Purchase Association
For verifying purchases from App Store:
Before initiating a purchase or plan change, call isStorePurchaseAssociatedWithCurrentUser().
If the App Store purchase is not associated with the currently logged-in user, do not proceed with the purchase flow. Before displaying the purchase UI, determine whether the user is attempting an upgrade, downgrade, or restore.
For verifying purchases from other channels:
Ensure you only allow one active subscription per customer across all channels. If a user already has an active web or Android subscription and attempts to purchase through iOS, block the iOS purchase.
The App Store has no visibility into web or Play Store purchases. Determine the user’s subscription state through your own backend before showing the purchase UI:
- Have your mobile client request the user’s current subscription status from your server.
- Treat your server as the source of truth. It checks the user’s subscriptions across all channels and queries the Zoho Billing APIs where needed.
- Based on that status:
- If there is no active subscription on any channel, allow the iOS purchase.
- If there is an active subscription on another channel, block the iOS purchase and guide the user to manage the existing subscription on the channel where it was purchased.
Display Eligible Plans and Offers
Show Only Active Plans
Use zsPlan.isActive to display only plans that are currently active in Zoho Billing.
Hide Lower-Tier Plans When Downgrades Are Not Permitted
If your subscription configuration does not allow downgrades, do not display lower-tier plans as available options.
This prevents users from starting a plan-change flow that cannot be completed.
Check Introductory Offer Eligibility
Introductory offer eligibility is determined by the App Store. It is determined by the store at the time of purchase for that plan, and it is the only source that holds this data. Introductory offers are not available to every user. Check eligibility against the store before showing the offer.
Use isUserEligibleForIntroductoryOffer(product:) to check eligibility for a specific product. Refer to Introductory Offers for reference.
Display the App Store Price
Display the localized price returned by the App Store through the skProduct.displayPrice value in the selected plan.
Do not hardcode subscription prices in the app. App Store prices vary by country, currency, and region, so the store-provided price should always be used to show the exact amount the user pays.
Use the plan’s skProduct object when loading plans and show the localized App Store price from skProduct.displayPrice.
Handle Purchases and Restores
Restore App Store Purchases Only
If the restore operation returns no purchases, verify the user’s purchase association before taking further action. This helps distinguish between a user with no eligible purchase and a purchase associated with another user.
Handle Already-Processed Purchases
If purchaseAlreadyProcessed is returned while creating a subscription:
- Read the
subscription_idfrom the error response. - Retrieve the subscription details from Zoho Billing.
- Give the user access to their subscription.
Handle Unacknowledged Purchases
If a user has already paid for a subscription but the purchase has not been acknowledged, call restorePurchase() and give the user access to their subscription.
Include Transaction Details in Support Requests
When a user contacts support about an App Store purchase, include the information required to identify the purchase.
Provide a Contact Support option in your app for subscription-related issues. Where possible, include the purchase, transaction, subscription, and end user’s account information required to investigate the issue.
Use getPurchaseMetadataFromStore() to retrieve the Original Transaction ID and include the App Store receipt and Original Transaction ID in the support request.
Handle Purchase Failures and Edge Cases
Ignore Cancelled App Store Payments
If appStorePaymentCancelled is returned, do not display it as an application error.
A user cancelling an App Store payment is an expected outcome.
Prevent Duplicate Subscriptions
If a duplicate subscription is detected, do not allow another purchase to proceed.
Guide the user to cancel the duplicate subscription through their App Store subscription settings. See Manage subscriptions on iPhone for the relevant App Store steps.