Apple In-App Purchase - SK2 [Beta]

🚧

Beta

Please note that it is a Beta feature.

This tutorial will help you integrate Apple in-app purchases using the StoreKit 2 framework for devices that support universal purchases, including iPhones, iPads, Apple TV devices and Vision Pro.

👉 Please refer to Apple documentation for information about which Apple platforms and versions are supported for StoreKit 2.

Overview

Payments on mobile and TV apps (in-app purchases) enrich your portfolio with one more payment method for your services. Customers can easily buy access to video content directly from inside your native applications, which simplifies the process. It also provides added value to you.

When you enable in-app purchases with Cleeng you gain:

  • entitlement across devices for your customers - they can use your services on many devices
  • rich and consolidated reporting for you - all-in-one-place reporting that can support your subscriber retention analytics and strategy building.

It is important to note that legally and technically it is Apple who handles the actual payments for purchases made in apps. Cleeng acts as an observer and tracks in-app purchase lifecycle events to gather data to make it available for analysis and to control access rights (entitlements).

In short, in-app purchases integration requires the setup on your side, and when ready, calling Cleeng purchase validation endpoint to submit the initial purchase when it happens in the app.

Cleeng takes over from there. We validate the purchase in the store, create a subscription and keep it in sync by listening to server-to-server notifications for subscription status updates. And we take care of the reporting.

This tutorial will show what you need to take care of as a broadcaster to enable Apple in-app purchases with Cleeng, as well as what the user-flow will look like.

If you want to jump straight into details, go to the What you have to do section.

What is Apple StoreKit

As mentioned at the start of this tutorial, it will help you integrate Apple in-app purchases using the StoreKit 2 framework. (The legacy integration based on StoreKit 1 is described here.)

So before we move to integration steps, a few words about StoreKit.

To handle in-App Payments, Apple provides the StoreKit framework. The StoreKit framework connects to the App Store on the app’s behalf to prompt for and securely process payments. The framework then notifies the app, which delivers the purchased products.

StoreKit 2 is an updated framework that developers use to handle in-app purchases, subscriptions, and transactions within apps on Apple’s platforms. It provides tools and APIs to create a seamless buying experience for customers while offering developers more flexibility and efficiency when integrating and managing in-app purchases within their applications.

StoreKit 1 and Storekit 2 differ in some aspects, and one of them is purchase validation. As you can see below, purchase validation was based on receipts with Storekit 1, while now, with StoreKit 2, it is based on Original Transaction ID.

Purchase validation is based on:
Apple StoreKit 1Encrypted receipts

They contain information about what is bought and when, though do not include revenue numbers (actual price paid by the customer). Also the App Store has server-to-server notifications to share information about the subscriber lifecycle and billing information.
Apple StoreKit 2Original Transaction ID

It is the main object used for validating the purchase, using Server APIs and server-to-server notifications.

Now, follow the steps below to integrate in-app purchases using the StoreKit 2 framework.

What you have to do

As a broadcaster you need to be aware and take care of the following:

  1. Architecture Overview
  2. Authorization
  3. Prerequisites
  4. Initial Purchase Submission
  5. Receive Subscriber Status Validation
  6. Keep Subscribers Synchronized

❗️

Important

If you switch to StoreKit 2 and integrate in-app purchases using this new framework, your StoreKit 1-based implementation will stop working.

1. Architecture Overview

Below you can see the overview of the system architecture. It shows the interaction between your app, Apple AppStore, and Cleeng.

Subscriber Cycle Overview

Subscriber Cycle Overview

2. Authorization

Depending on how you integrate with Cleeng, you will use different authorization: either a publisher (X-Publisher-Token) or JWT (Bearer) token. A publisher token will be used for integrations through middleware, while JWT - for direct integrations.

Please note that some integration steps will differ for these two flows.

Also, the purchase validation endpoint that is used in Apple in-app purchase integration accepts either a publisher (X-Publisher-Token) or JWT (Bearer) token for authorization. Please make sure to use the one that matches your current integration.

Please also note that this tutorial focuses on integration where JSON Web Token (JWT) authorization is used so we recommend using MediaStore API (for more information see Getting started), especially for authentication (registration and login).

3. Prerequisites

You need to complete 6 steps in the prerequisites stage:

  1. Set up a developer account with Apple and create an application
  2. Add products within Apple Store Connect
  3. Create Keys in Apple
  4. Configure Server-to-Server notifications
  5. Provide configuration in the Cleeng Dashboard
  6. Contact Cleeng Broadcaster Success Specialists team

Please follow the sections below for details:

  1. Set up a developer account with Apple (see more in Apple documentation) and create an application.

  2. Add products within Apple Store Connect - see Apple documentation.
    Products that you add must be compatible with your Cleeng offer.

    📘

    Important notes for setting up products compatible with Cleeng:

    • This Apple in-app purchase integration works only for subscription offers. Hence, use auto-renewable-subscription products for subscriptions.
    • The product price must be set manually in App Store Connect. Be sure to align prices between Apple's product and your Cleeng offer.
    • You can only select price points in App Store Connect.
    • To test the setup, log in to your sandbox account on your phone (Settings -> App Store -> Sandbox account), with one of the sandbox accounts created in App Store Connect -> Users and Access -> Sandbox -> Test Accounts.


      👉 Remember to add your App store product ID in the offer setup in the Cleeng dashboard in order to map the external offer properly in the Cleeng system. For more information, see this article.
  3. Create Keys in Apple.
    Authorization
    Please note that JSON Web Token (JWT) authorization is used for API requests.


    Create API Key
    First, you need to create an API key. Any role is sufficient, but we recommend that the access role is set to “Developer” in Apple Connect -> User and Access -> Integrations.
    Download your private key after generating it. Please note that it can be downloaded only once.
    Important: Store your private key in a secure place as it is used to authorize API requests.


    Data Access Key
    To strengthen reporting we recommend using Data Access Key with the access role set to “Admin” in Apple Connect -> User and Access.

  4. Configure Server-to-Server notifications
    You need to provide a URL address in App Store Connect for server-to-server notifications - see Apple documentation.
    The URL you need to provide is:

    • https://inapp.api.sandbox.cleeng.com/storekit2/notifications/broadcasters/{broadcasterId} - for sandbox environment.
    • For production environment, it will be https://inapp.api.prod.cleeng.com/storekit2/notifications/broadcasters/{broadcasterId}
      👉 Please remember to replace {broadcasterId} with your broadcaster ID (publisher ID) in the URL.
      For more information on Server-to-Server notifications, see the section below.

      🚧

      Note

      When using StoreKit 2 make sure you’re using version 2 notifications. For more information, see Apple documentation - App Store Server Notifications V2.

  5. Provide configuration information in the Cleeng Dashboard

    Once you are ready and have the required information from Apple at hand, log in to Cleeng Dashboard, go to Admin Settings > Integrations > Apple Store.

    Configuration in Cleeng Dashboard

    Configuration in Cleeng Dashboard

    The section consists of mandatory and optional configuration as specified below.

    Mandatory configuration

    You need to fill in configuration information in the Cleeng Dashboard so as to automatically synchronize subscribers between Apple and Cleeng. This way your subscribers get access on any device, and you benefit from consolidated reporting.

    📘

    Note

    Please enter your private key in PEM format. PEM format typically starts with '-----BEGIN PRIVATE KEY-----' and ends with '-----END PRIVATE KEY-----'. Ensure there are no additional spaces or characters before or after the key data.

    Configuration in Cleeng Dashboard

    Configuration in Cleeng Dashboard - Required

    Configure the required fields: bundle id, issuer id, key id, and private key:

    • bundle Id - value taken from the App Store Connect under Apps -> App information -> Bundle ID

      Where to find Bundle ID in App Store Connect

      Where to find Bundle ID in App Store Connect

    • issuer Id - value taken from the the App Store Connect under Users & Accesses -> Integrations -> Issuer ID

    • key id (kid) - value taken from table of generated private keys at the App Store Connect under Users & Accesses -> Integrations -> Key ID

      Where to find Issuer ID and Key ID in App Store Connect

      Where to find Issuer ID and Key ID in App Store Connect

    • private key - value taken from the file, which can be downloaded only once, right after the private key generation.

    Optional configuration

    Configuring data reporting is optional, but recommended in order to have more insights.To configure data reporting you need to provide the Key ID and Private Key in the respective fields using the Data Access Key (with the access role set to “Admin” in Apple Connect under User and Access).

    Cleeng Dashboard - Data Reporting Configuration

    Cleeng Dashboard - Data Reporting Configuration

  6. Contact Cleeng Broadcaster Success Specialists team to complete configuration on Cleeng’s side (add a payment method).

    🚧

    Important

    Make sure that payment method is added and configuration is completed in the Cleeng Dashboard - these are mandatory for the setup to work.

4. Initial Purchase Submission

In-app purchases integration requires calling Cleeng purchase validation endpoint to submit the initial purchase when it happens in the app.

When a customer successfully buys a subscription offer, a request should be sent to the purchase validation endpoint:
POST https://inapp.api.sandbox.cleeng.com/storekit2/purchase-validation
(or POST https://inapp.api.prod.cleeng.com/storekit2/purchase-validation - once in production environment)

Note:

The value of the originalTransactionId in the purchase validation payload should be taken from Apple StoreKit 2 transactionId.

🚧

Note

Cleeng has mechanisms for retrieving subscriptions that have not been properly verified.

In rare cases it might happen that information about a subscription arrives first via server-to-server notification from Apple and only after that from a broadcaster. It is then important for a broadcaster to send the request to Cleeng through the purchase validation API.

5. Receive Subscriber Status Validation

Once you make a call to Cleeng’s purchase validation endpoint, Cleeng takes over from there.

We validate the purchase in the app, and act on the validation result (e.g. create a subscription).

Subscriber Status Validation

Original transaction identifier is the main object used for validating a purchase, i.e validating a subscriber status, so access to content is based on an originalTransactionId.

Cleeng validates it before access is granted, but it is an asynchronous process. Because it requires validation with an external app store, we are not able to return the outcome synchronously in the API request response. So the first “OK” message that you receive shows only that the request has been successfully queued.

See below for the overview of the process of subscriber status validation for two integration methods:

Direct Integrations (Without Middleware)

For direct integrations where no middleware is used (the request is submitted directly to Cleeng platform from the client app and authenticated with an end user JWT token), the polling approach should be used.

Even though most responses are within 3 seconds, they can take up to 60 seconds on the app store side. Therefore, the application needs to poll the Cleeng API using the Get entitlements endpoint: GET mediastoreapi.cleeng.com/entitlements/{offreId} every five seconds until validation is completed and access is granted.

Subscriber status validation - Direct integration flow

Subscriber status validation - Direct integration flow

Integration With Middleware (Client Backend)

For backend integrations where middleware is used and the request is authenticated with a publisher token, your client backend service should subscribe to Cleeng webhook topics.

If you are subscribed to the topics listed below, you will receive a webhook notification when in-app purchase validation (subscriber status validation) is completed with information about the outcome of the validation result.

Webhooks dedicated for in-app purchase validation:

In addition generic subscription lifecycle topics will also be emitted:

For details of possible outcomes of in-app purchase validation and webhooks sent, please refer to In-app Purchase Validation article.

Subscriber status validation - Integration flow with middleware

Subscriber status validation - Integration flow with middleware

6. Keep Subscribers Synchronized

Cleeng acts as an observer and tracks in-app purchase lifecycle events. But for Cleeng to be able to do this, you need to configure server-to-server notifications to get the subscription status updates and keep subscribers synchronized.

You need to provide a URL address in App Store Connect for server-to-server notifications - as described in the Prerequisites section.

Server-to-Server Notifications

Server-to-Server Notifications is direct one-way communication between Apple App Store and Cleeng. It provides near real-time subscription updates that help to get information about new purchases, renewals, billing issues, etc. This helps to build more accurate analytics, as well as simplifies managing the subscriber’s status.

The table below presents which Apple notifications (version 2) are supported:

Apple NotificationSupported at Cleeng
DID_FAIL_TO_RENEW
EXPIRED
GRACE_PERIOD_EXPIRED
SUBSCRIBED
RENEWAL_EXTENSION
DID_CHANGE_RENEWAL_PREF
DID_CHANGE_RENEWAL_STATUS
REFUND

User Flow

1. Register/Login User

Note: We recommend using MediaStore API (for more information see Getting started), especially for authentication (registration and login).

The application attempts to log in the user. If the user doesn't exist, registration is required. It is recommended that the application uses the Register method to register the customer. For more information, see Registration.

If the user exists, it is recommended that the application uses the Login endpoint to log in. For more information see Login.

2. Purchase an Offer

Once a customer successfully purchases an offer, they get access to the content.

It results in subscription creation - if we do not have a subscription with this originalTransactionId yet.

It is also possible that restore happens and then it can result in subscription transfer or restoring purchase

  • subscription transfer - if we already have an active subscription for the provided originalTransactionId and it belongs to a customer with a different email address. Then a new subscription is created for the "new customer" (the one using the new e-mail address) and the subscription assigned to the "old customer" (the one using the old email address) is terminated. Please note that this process has implications in reporting (one subscription is terminated and another one created).
  • restoring purchase - in some cases your customers who purchased a subscription need to restore their purchase on another device. For example, if a customer has a purchase associated with his appleId but he/she uses a new apple device to log in to the app, it may be required to restore the purchase. In this case the transactionId should be submitted again to Cleeng to validate the purchase and make sure the subscription is created correctly, associated with the corresponding Cleeng account and synced with the app store.

3. Manage Subscription

For subscriptions purchased via in-apps, Cleeng does not handle payments. This also means that subscription lifecycle events like termination, or subscription upgrade/downgrade are managed by external services. Cleeng acts as an observer and tracks in-app purchase lifecycle events to synchronize the status.

So for example, if you are using Cleeng MediaStore SDK Components in your webApp, a subscription purchased via in-apps cannot be managed in MyAccount and your customers will be informed that they need to go to the external store to manage their subscription there.

If you are not using our Components solution, it is recommended that you provide respective information in your specific My Account implementation.

Testing Guidance

When you integrate the above, please follow these steps to test the initial payment configuration:

  1. Configure in-App purchase in App Store Connect - see Apple Documentation.
  2. Create a Cleeng sandbox account (or log in if you already have one) and create a test offer.
  3. Make sure App Store Connect and Cleeng offer in the sandbox environment are compatible - for more information see "Important notes for setting up products compatible with Cleeng" above.
  4. Provide bundle id, issuer id, key id, and private key in the Cleeng Dashboard.
  5. Contact Cleeng Broadcaster Success Specialists team to complete configuration on Cleeng’s side (add a payment method).
  6. Make an initial purchase.
  7. Subscription is added in Apple settings.
  8. Subscription is added in Cleeng.

Test Cases

You should cover the test scenarios below to test your integration more thoroughly:

  • Initial purchase - when a logged-in customer purchases an offer from a list of offers available on the purchase page opened on the iOS mobile application.
  • Recurring payment - when a customer’s subscription reaches a renewal date and the payment for it is processed.
  • Subscription switch (upgrade/downgrade) - when a customer switches a subscription to another one (upgrades or downgrades a subscription).
  • Subscription renewed - when a customer renews a subscription (that he/she has previously canceled) before the end of its grace period is reached.
  • Subscription revival - when a customer buys the same offer as the one that he/she subscribed to previously, but the previous subscription was canceled by the customer and got terminated.
  • Payment failed - when a customer's subscription reaches a renewal date and the payment for it fails.
  • Subscription transfer - when a customer has an active subscription bought with one email address, and then he/she logs in with the second email address (using the same Apple Id) and selects the same previously purchased subscription, the new subscription will be transferred to the customer with the second email account.

👉 You can also refer to offical Apple testing guidelines under this link.

Migrating Existing Subscribers from StoreKit 1 to StoreKit2

In order to migrate from StoreKit 1 to Storekit 2 we recommend aligning with your Cleeng account manager (and project manager) to build a migration plan. High-level It takes 3 steps to migrate to the new framework. It should be coordinated effectively together.

  • Make the changes in the code of your application to synchronize to Cleeng the OriginalTransactionId as described above (instead of receipt Data)
  • Within App Store connect - update the server to server notifications towards the new version and new url (as described in Prerequisites)
  • For Cleeng to route existing Apple subscriptions data to the new Apple handler.

Good to Know

Unidentified User

In certain situations, when a purchase validation request fails to reach our connector due to connectivity issues or other disruptions, our system is designed to maintain transaction continuity. To achieve this, the StoreKit 2 connector will automatically create a temporary user, known as a ‘dummy’ or ‘unidentified’ user, within our system. This user is created with a predefined email pattern: unidentified.customer+${gateway}+${publisherId}+${timestamp}@cleeng.com

This mechanism ensures that the purchase can still be processed and recorded in our system, even if the user’s information is not fully validated at the time. The ‘dummy’ user acts as a placeholder, allowing us to later reconcile the transaction and transfer the subscription once the user's details can be verified.

This approach minimizes disruptions to the customer experience and helps maintain accurate transaction records, even in cases of temporary technical issues.

In such a case the user will not be given entitlements to the content.

In order to be able to identify the user and match the subscription with a named user, Cleeng should receive the initial purchase request. Once we receive the purchase validation request, and we are able to identify the user, the subscription will be transferred to their account. The unidentified user’s account will be removed.

Grace Period - Reducing Involuntary Subscriber Churn

Apple offers the feature of reducing involuntary subscriber churn which is supported by Cleeng. This feature prevents unintentional loss of subscribers due to billing issues. For more detailed information on how it works, please refer to Apple documentation.

Up next

Congratulations! By now you should be all set up to unlock the full potential of this integration in your projects.

As you wrap up, why not explore other integration tutorials for in-app purchases?