## Zoho Billing - Product, solutions, integrations, support, and resources Index Access the complete documentation index at: https://www.zoho.com/bh/billing/llms.txt Use this file to discover all available documentation pages before proceeding. # Android In-App Purchases SDK Implementation The [Android SDK](https://zoho.github.io/zsinappkit-docs/android/) (`ZSInAppPurchaseKit`) connects your Android app with Zoho Billing for plan sync and subscription lifecycle updates. **Pro Tip:** Before starting, review [Best Practices for SDK Implementation](/bh/billing/help/omnichannel-subscription/sdk-configuration.html). * * * ## Add the SDK to Your App Add the SDK dependency in your app-level `build.gradle` file. ```gradle dependencies { implementation("com.zoho.subscriptions:inapp-billing:7.2.0") } ``` * * * ## Initialise the SDK Initialise the SDK after user information is available. For example: ```kotlin // apiKey - The unique key generated for your organization in Zoho Billing. // It is used for communication between the SDK and the Zoho Billing server. // You can find it on the App Store integration page in Zoho Billing. // zsProductID - The unique ID of the product created in Zoho Billing where your plans are configured. // domain - The data center where your Zoho Billing organization is hosted. // For example, if your organization is in zoho.com, use ZSDomain.COM. val zsAPIConfiguration = ZSAPIConfiguration( apiKey = "YOUR_API_KEY", zsProductID = "YOUR_PRODUCT_ID", zsDCDomain = ZSDomain.COM ) ZSAPIConfigurationCompanion.setAPIConfiguration(zsAPIConfiguration) ZSInAppPurchaseKit.initialize( this, ZSAPIConfigurationCompanion.zsapiConfiguration ) // userId - The unique ID of the user maintained in your server. // For web subscriptions, this field corresponds to the channel_customer_id. // userEmail - The user's email address. // displayName - The user's display name. ZSInAppPurchaseKit.getInstance().setUserDetails( userId = "APP_USER_ID", userEmail = "APP_USER_EMAIL", displayName = "APP_USER_DISPLAY_NAME" ) ``` **Note:** For best practice guidance on the **USER\_ID**, **PRODUCT\_ID**, and **DOMAIN** parameters, see [Match Customers Across Channels](/bh/billing/help/omnichannel-subscription/sdk-configuration.html#match-customers-across-channels), [Map Subscriptions to the Correct Product](/bh/billing/help/omnichannel-subscription/sdk-configuration.html#map-subscriptions-to-the-correct-product), and [Configure the Correct Data Centre](/bh/billing/help/omnichannel-subscription/sdk-configuration.html#configure-the-correct-data-center) in the Best Practices guide. * * * ## Fetch Plans Load available subscription plans. This retrieves only the plans configured in both Zoho Billing and Play Store (common plans) that are available for purchase. ```kotlin val arraylist = arrayListOf().apply { //If you have configured any custom fields in Zoho Billing, you can pass them here if needed. This is totally optional. } ZSInAppPurchaseKit.getInstance().getPlans(object : PlanDetailsListener { override fun onPlanDetailsFetched(zsPlans: ArrayList) { //Update the UI with the list of plans fetched from Zoho Billing and added in Google Play Console. } override fun onError(error: ZSError) { //Handle error logic } }, arraylist) ``` * * * ## Initiate a Purchase Initiate a purchase when a user selects a plan. This starts the Play Store purchase flow and syncs the subscription to Zoho Billing. Before calling `initiateNewPurchase`, extend your activity with the `PurchaseUpdationListener` interface. When the user taps the purchase button in your UI, pass the corresponding `zsPlan` object to `initiateNewPurchase`. ```kotlin ZSInAppPurchaseKit.getInstance().initiateNewPurchase( activity = CURRENT_ACTIVITY_INSTANCE, zsPlan = USER-SELECTED_ZSPLAN, offerId = "", purchasesUpdatedListener = CURRENT_ACTIVITY_INSTANCE, zsCustomFields = customFields) override fun onStorePurchaseCompleted() { //Purchase successfully done in Google Play Store, show a loading bar while the SDK syncs this purchase with Zoho Billing } override fun onPurchaseSyncedWithServer(zsSubscriptionDetail: ZSSubscriptionDetail) { //Purchase successfully synced with Zoho Billing. } override fun onError(zsError: ZSError) { //Purchase failed. zsError.message will give the error message. Handle cases accordingly } ``` If the purchase is successful, the SDK syncs it with Zoho Billing and returns a `ZSSubscriptionDetail` object in the `onPurchaseSyncedWithServer` callback. Use this to verify the customer’s subscription status through your backend before allowing access to paid features. Zoho Billing also delivers the subscription details to your configured webhook. If the purchase fails, the error is returned in the `onError` callback. To include custom fields in the subscription, pass them using the `zsCustomFields` parameter. If you are applying an offer, pass the offer ID as a custom field. ### Offers `zsPlan.productDetails.subscriptionOfferDetails` contains all the offers eligible for the current user and plan. Two types of offers are supported: #### Introductory Offers Introductory offers apply only to users who have not previously subscribed to the plan. Eligibility can be scoped to a specific plan or any plan, depending on your Play Console configuration. When introductory offers are configured, the SDK automatically selects the best eligible offer using this priority: 1. **Longest free trial** - applied first, if available. 2. **Cheapest introductory price** - applied if no free trial is available. 3. **No offer** - applied if neither is available. **Note:** Google Play Store is the sole determinant of introductory offer eligibility. As a best practice, display a message in your UI stating that introductory offers are available only to eligible customers. #### Developer Determined Offers For developer determined offers, your app decides eligibility based on your business logic. When you want to apply one of these offers, pass the `offerId` to `initiateNewPurchase`. If no developer determined offer should be applied, pass an empty string. * * * ## Restore a Purchase Add restore support for users who purchased in Play Store but failed sync due to temporary issues. ```kotlin ZSInAppPurchaseKit.getInstance().restorePurchase(restorePurchaseListener = object :RestorePurchaseListener { override fun onPurchaseRestored(zsSubscriptionDetail: ZSSubscriptionDetail) { //Purchase has been restored successfully and synced with Zoho Billing. } override fun onError(error: ZSError) { //Purchase was not restored. } }, storeOrderId = "") ``` * * * ## Fetch Current Entitlements Retrieve the user’s active subscriptions directly from Play Store. Use this to display current subscription status and entitlements in your app. ```kotlin ZSInAppPurchaseKit.getInstance().getPurchaseMetadataFromStore(object: PurchaseMetadataListener { override fun onPurchaseDetailsFetched(purchases: MutableList) { //Append the purchase details to when user contacts support via mail if necessary } override fun onError(error: ZSError) { //Purchase data could not be fetched. } }) ``` * * * ## Clear User Info Clear the SDK user data when a user logs out or your app terminates the session. This ensures user information is not retained. ```kotlin ZSAPIConfigurationCompanion.clearAPIConfiguration() ZSInAppPurchaseKit.getInstance().clearUserDetails() ``` * * *