## Zoho Billing - Product, solutions, integrations, support, and resources Index Access the complete documentation index at: https://www.zoho.com/qa/billing/llms.txt Use this file to discover all available documentation pages before proceeding. # 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. **Note:** Complete the [Post-Implementation Checklist](/qa/billing/help/omnichannel-subscription/sdk-checklist.html) alongside this checklist. The common checks apply to both iOS and Android and must be verified before going live. **Note:** Test the complete subscription lifecycle before going live, including purchase, renewal, restore, account switching, and App Store notification flows. ## 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](/qa/billing/help/omnichannel-subscription/ios/ios-sdk-implementation.html#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: 1. Read the `subscription_id` from the error response. 2. Retrieve the subscription details from Zoho Billing. 3. 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](https://support.apple.com/en-in/guide/iphone/iph4e3e7324f/ios) for the relevant App Store steps. * * *