Omnichannel subscription
This feature is currently in the EA phase. We are seeking feedback from a select group of users before making it available to all customers. If you have questions or would like to provide feedback, please contact Zuora Product Management.
Overview
This guide details the process for creating and managing omnichannel subscriptions using the Zuora Omnichannel Subscription API. Omnichannel subscriptions refer to subscriptions managed by external platforms, such as the Apple App Store and Google Play Store, where Zuora handles only certain aspects.
Connector Setup
This section details the credentials required to integrate Zuora with third-party applications. Zuora will collect the following credentials for integration.
Apple Integration
When working with Apple services and integrations, certain credentials and identifiers are essential to ensure secure and efficient communication. Key components include the following:
- .p8 Certificate: A private key file used for authenticating requests to Apple services.
- Key ID: A unique identifier for the key associated with the .p8 certificate.
- Issue ID: Identifies the specific issue or problem related to the Apple integration.
- Bundle ID: A unique identifier for the application or service in Apple's ecosystem.
- Apple ID: The user account used to access Apple services and manage app-related settings.
To obtain credentials for Apple Notification, follow these steps:
1. Obtain the .p8 Certificate, Key ID, and Issue ID:
- Navigate to App Store Connect and log in.
- Go to Users and Access.
- Click on Integrations in the top navigation tab.
- Select In-App Purchases from the left-hand navigation.
- Click Create a new Token. Download the .p8 certificate once generated (this action can only be done once).
- Note the Key ID and Issue ID provided on this page.
2. Retrieve the Apple ID and Bundle ID:
- Return to the Home Screen and select the Apps tile.
- Choose the app for which you need to generate credentials.
- Navigate to General -> App Information on the left-hand navigation.
- Record the Apple ID and Bundle ID found on this page.
Required Values for Apple:
- Apple ID
- Bundle ID
- Key ID
- Issue ID
- .p8 Certificate
Google Integration
When working with Google services and integrations, certain credentials and identifiers are essential to ensure secure and efficient communication. Key components include the following:
- Audience: The target audience for the API or service, often specifying who can use the credentials.
- Email: The email address associated with the service account for Google Cloud.
- Key Info (JSON format): Configuration data for the service account in JSON format.
- Type: The type of credentials or service account being used.
- Project ID: A unique identifier for the Google Cloud project.
- Private Key ID: A unique identifier for the private key used in the service account.
- Private Key: The private key used for authentication and signing requests.
- Client Email: The email address of the client or service account used for authentication.
- Client ID: A unique identifier for the client application in Google's API.
- Auth URL: The URL for obtaining authentication tokens from Google.
- Token URL: The URL for exchanging authentication codes for tokens.
- Auth Provider CERT URL: The URL for the certificate used by the authentication provider.
- Client CERT URL: The URL for the client's certificate used in the authentication process.
To obtain credentials for Google RTDN, follow these steps:
-
Ensure RTDN and Service Account Setup: This guide assumes you have a Pub/Sub for RTDN set up and a service account linked to the Notification Pub/Sub. If not, follow the guide at Purple Publish Setup Guide.
-
Gather Required Information:
- Navigate to Google Developer Console and log in.
- Go to the Pub/Sub page by searching for it in the top search bar.
- Locate and edit the Subscription representing your notification Pub/Sub.
- Configure Authentication:
- On the Subscription page, toggle Enable Authentication.
- Add the Service Account for authentication and set an audience value (e.g., "3pp.rdnt"). This value helps distinguish between different subscriptions.
- Note the audience value and the title of the service account, as both need to be shared with the Appstore Connector.
-
Generate Service Account Token:
- Navigate to IAM & Admin by searching the top bar.
- Go to Service Accounts on the left-hand navigation.
- Find the Service Account linked to the Pub/Sub Subscription and go to the Keys tab.
- Click Add Key and select Create JSON Key to generate a JSON key file.
Required Values for Google:
- Audience
- Service Account Email
- Key JSON file
- Project ID
- Subscription Name
- Topic Name
Roku Integration
When working with Roku services and integrations, specific credentials and identifiers are essential to ensure secure and effective communication with Roku's platform, especially for channel development and publishing. Key components include the following:
- Developer Account Email: The email address associated with the Roku developer account, used for channel management and access to the developer portal.
- Developer ID: A unique identifier associated with the developer's account, required for packaging and signing Roku channels.
- Channel ID: A unique identifier for the Roku channel that distinguishes the app in the Roku ecosystem.
- Package Signing Key: A private key used for securely signing the channel package before uploading it to Roku. This key is essential for deploying updates to the channel.
- Access Token: A token for accessing Roku APIs and managing channels programmatically via the Roku API (if needed for advanced automation or integrations).
- Publishing Information: Includes the title, description, and icon assets, part of the channel publishing process.
To obtain credentials for Roku, follow these steps:
-
Create a Roku developer account
- Go to Roku Developer Portal and sign up or log in with your Roku developer account.
- Note the Developer Account Email used, which will be required for channel management.
-
Obtain developer ID and channel ID
- From the Roku Developer Dashboard, navigate to Manage My Channels.
- Select your channel or create a new one.
- Channel ID is listed on this page and is unique to each channel.
- The Developer ID is generated when you set up your Roku device in Developer Mode and link it to your account to sign channel packages.
-
Enable developer mode and generate package signing key
- To develop and test channels, enable Developer Mode on your Roku device:
- Press the following buttons on your Roku remote: Home (3x), Up (2x), Right, Left, Right, Left, Right.
- Follow the prompts to enable Developer Mode and set a password.
- After enabling Developer Mode, the device will generate a Developer ID and Package Signing Key. Use this Package Signing Key to sign your channel’s packaged ZIP file before uploading it.
-
Generate an access token (optional, for API access)
To programmatically manage channels or perform automation, you may need an Access Token for the Roku API. This token can be obtained by contacting Roku developer support, as Roku’s API access is typically granted for advanced use cases like billing integrations or large-scale management. -
Prepare publishing information
- Gather Publishing Information for the channel, such as:
- Title and Description: This appears in the Roku Channel Store.
- Icon and Screenshots: Required images for store listings.
- Content Feed URL (if using Direct Publisher): A URL that provides the content structure for the channel in JSON format, used by Roku's Direct Publisher.
Required values for Roku:
- Developer Account Email
- Developer ID
- Channel ID
- Package Signing Key
- Access Token (if applicable)
- Publishing Information
Connector processing logic and field mapping
This table provides a detailed mapping of Zuora subscription fields with values derived from Apple App Store notifications for both V1 and V2 payloads. It serves as a reference guide for configuring Zuora’s subscription object fields based on data received from the Apple App Store server. Key attributes such as identifiers, subscription statuses, and renewal details are defined, along with the conditions and values for each field based on the version of the payload.
Zuora target object and field mappings
Zuora Target Object |
Zuora Target Field |
Description |
Field Type |
Required During Initial Subscription Creation (by Customer Mobile App) |
Apple App Store v1 |
Apple App Store v2 |
Google Play Store |
Roku Pay |
---|---|---|---|---|---|---|---|---|
Subscription |
Channel |
Identifies the source app store from which the subscription originated. |
string |
Optional |
Set to value to `Apple App Store` |
Set to value to `Apple App Store` |
Google Play Store |
Roku Pay |
Subscription |
External Application ID |
Unique identifier of the application associated with the subscription in the external system. |
string |
Optional |
Set to value from server notification. V1 field: n/a |
Set to value from server notification. V2 field: data.appAppleId |
Set to value from notification: packageName |
Set to value from push notification: channelName |
Subscription |
External Bundle ID |
Unique identifier of the application bundle associated with the subscription in the external system. |
string |
Optional |
Set to value from server notification. V1 field: bid |
Set to value from server notification. V2 field: data.bundleId |
n/a |
n/a |
Subscription |
External Subscriber ID |
Unique identifier of the subscriber associated with the subscription in the external system. |
string |
Optional |
Set to value from server notification. V1 field: unified_receipt.Latest_receipt_info.app_account_token |
Set to value from server notification. V2 field: data.TransactionPayload.appAccountToken |
Set to value from REST Resource: purchases.subscriptionsv2: ExternalAccountIdentifiers.externalAccountId |
Set to value from push notification: customerId |
Subscription |
External Subscription ID |
Unique identifier of the subscription in the external system. |
string |
Required |
Match following value from server notification. V1 field: original_transaction_id |
Match following value from server notification. V2 field: data.TransactionPayload.originalTransactionId |
Match server notification value: subscriptionNotification.purchaseToken |
Set to value from push notification: originalTransactionId |
Subscription |
Organization ID |
Unique identifier of the Zuora Organization associated with the subscription (for Multi-Org customers). |
string |
Required (for Zuora Multi-Org customers) |
n/a |
n/a |
n/a |
n/a |
Subscription |
External Product ID |
Unique identifier of the product or plan associated with the subscription in the external system. |
string |
Optional |
Set to value from server notification. |
Set to value from server notification. |
Set to value from REST Resource: purchases.subscriptionsv2: SubscriptionPurchaseLineItem.productId |
Set to value from push notification: productName |
Subscription |
Currency |
Currency in which the subscription is billed. |
string |
Optional |
Set to value from server notification. V1 field: n/a |
Set to value from server notification. V2 field: data.TransactionPayload.currency |
Set to value from REST Resource: purchases.subscriptionsv2: SubscriptionPurchaseLineItem.SubscriptionItemPriceChangeDetails.newPrice.Money.currencyCode |
Set to value from push notification: currency |
Subscription |
External Price |
Price of the subscription in the external system, with the currency indicated. |
decimal |
Optional |
Set to value from server notification. V1 field: n/a |
Set to value from server notification. V2 field: data.TransactionPayload.price / 1000 |
Set to value from REST Resource: purchases.subscriptionsv2: SubscriptionPurchaseLineItem.SubscriptionItemPriceChangeDetails.newPrice.Money.units + SubscriptionPurchaseLineItem.SubscriptionItemPriceChangeDetails.newPrice.Money.nanos/10000000 |
Set to value from push notification: price |
Subscription |
External Purchase Type |
Type of purchase in the external system. |
string |
Optional |
If V1 server notification, infer purchase type (there is no direct purchase type in v1 as there is in v2) according to the following logic: Auto-Renewable Subscription: If auto_renew_status exists and is set to true, and unified_receipt.Latest_receipt_info.expires_date is in the future, it indicates an 'Auto-Renewable Subscription'. Non-Renewing Subscription: If unified_receipt.Latest_receipt_info.expires_date exists but auto_renew_status is either false or doesn't exist, it can be inferred as a 'Non-Renewing Subscription'. Consumable and Non-Consumable: These typically don't have expires_date or auto_renew_status. They are one-time purchases and should be ignored for V1 notifications. |
If V1 server notification, infer purchase type (there is no direct purchase type in v1 as there is in v2) according to the following logic: Auto-Renewable Subscription: If auto_renew_status exists and is set to true, and unified_receipt.Latest_receipt_info.expires_date is in the future, it indicates an 'Auto-Renewable Subscription'. Non-Renewing Subscription: If unified_receipt.Latest_receipt_info.expires_date exists but auto_renew_status is either false or doesn't exist, it can be inferred as a 'Non-Renewing Subscription'. If V2 server notification data.TransactionPayload.type = 'Auto-Renewable Subscription' then set value to 'Auto-Renewable Subscription' Else if V2 server notification data.TransactionPayload.type = 'Non-Renewing Subscription' then set value to 'Non-Renewing Subscription' Else if V2 server notification data.TransactionPayload.type = 'Consumable' or 'Non-Consumable' ignore event |
Set to value from REST Resource: purchases.subscriptionsv2: SubscriptionPurchaseLineItem.autoRenewingPlan present ? 'Subscription' : SubscriptionPurchaseLineItem.prepaidPlan present ? 'Pre-Paid Plan' : 'ignore event' |
n/a |
Subscription |
External State |
Current state of the subscription in the external system. |
string |
Optional |
If V1 server notification: If auto_renew_status is true and unified_receipt.Latest_receipt_info.expires_date is in the future, set value to 'Active' If unified_receipt.Latest_receipt_info.expires_date is in the past and unified_receipt.Pending_renewal_info.is_in_billing_retry_period is 0 and unified_receipt.Pending_renewal_info.grace_period_expires_date is null or in the past, set value to 'Expired' If unified_receipt.Pending_renewal_info.grace_period_expires_date is non-null and in the future, set value to 'In Grace' If unified_receipt.Pending_renewal_info.is_in_billing_retry_period is 1, set value to 'In Billing Retry' Else set to Null |
If V2 server notification data.TransactionPayload.type = 'Auto-Renewable Subscription', then set value to V2 server notification data.status Values should be string enumerations (e.g. 'Expired') not integer values (e.g. 2) See: https://developer.apple.com/document...cations/status Else set to Null |
Set to value from REST Resource: purchases.subscriptionsv2: subscriptionState See: Google API Reference |
Set to value from REST Validate Transaction API: purchaseStatus |
Subscription |
Status |
Status of the subscription. |
string |
Optional |
If V1 server notification: If auto_renew_status is true and unified_receipt.Latest_receipt_info.expires_date is in the future, set value to 'Active' Else if (unified_receipt.Latest_receipt_info.expires_date is in the past and unified_receipt.Pending_renewal_info.is_in_billing_retry_period is 0 and unified_receipt.Pending_renewal_info.grace_period_expires_date is null or in the past) or (unified_receipt.Pending_renewal_info.expires_date.auto_renew_status is 0), set value to 'Cancelled' Else if unified_receipt.Pending_renewal_info.grace_period_expires_date is non-null and in the future, set value to 'Active' If unified_receipt.Pending_renewal_info.is_in_billing_retry_period is 1, set value to 'Active' Else set 'Cancelled'' |
If V2 server notification data.TransactionPayload.type = 'Auto-Renewable Subscription': If data.status = 'Active', then set to 'Active' Else if data.status = 'Expired', then set to 'Cancelled' Else if data.status = 'Billing Retry' then set to 'Active' Else if data.status = 'Grace Period' then set to 'Active' Else if data.status = 'Revoked' then set to 'Cancelled' Else set to 'Cancelled' If V2 server notification data.TransactionPayload.type = 'Non-Renewing Subscription': If data.Transaction.expiresDate is in the past, then set to 'Cancelled' Else if data.Transaction.expiresDate is in the future, then set to 'Active' |
From REST Resource: purchases.subscriptionsv2: subscriptionState Else, map subscriptionState values to: 'Draft', 'Pending Activation', 'Active', 'Suspended', 'Cancelled' or 'Expired'. |
From REST Validate Transaction API: purchaseStatus Map values to: 'Active', 'Cancelled', 'Pending Activation'. |
Subscription |
Type |
Indicates the type of subscription. |
string |
n/a |
n/a |
n/a |
n/a |
n/a |
Subscription |
Auto Renew |
Indicates if the subscription automatically renews at the end of the term. |
boolean |
Optional |
If V1 server notification, use: auto_renew_status If auto_renew_status is true, then Auto Renew should be TRUE. If auto_renew_status is false or not present, then Auto Renew should be FALSE. Note: Consumables and non-consumables type events do have effect omni-channel subscriptions and are n/a to this field. |
If V2 server notification data.TransactionPayload.type = 'Auto-Renewable Subscription', set to TRUE; Else set to FALSE Note: Consumables and non-consumables type events do have effect omni-channel subscriptions and are n/a to this field. |
Set to value from REST Resource: purchases.subscriptionsv2: SubscriptionPurchaseLineItem.AutoRenewingPlan.autoRenewEnabled |
Set to TRUE |
Subscription |
Subscription Start Date |
Date when the subscription term starts. |
date |
Optional |
Set to value from server notification. V1 field: unified_receipt.Latest_receipt_info.original_purchase_date Value in date format. |
Set to value from server notification. V2 field: data.TransactionPayload.originalPurchaseDate Value in date format. |
Set to value from REST Resource: purchases.subscriptionsv2: startTime |
Set to value from push notification: originalPurchaseDate |
Subscription |
Last Renewal Date |
Date when the subscription last renewed. |
date |
Optional |
If V1 server notification, find latest notification received with notification_type = DID_RENEW, then set the value to purchase_date; Else do nothing |
If V2 server notification type = 'DID_RENEW' then set to value from: data.TransactionPayload.purchaseDate; Else do nothing |
If server notification type is (2) SUBSCRIPTION_RENEWED, set to eventTimeMillis. |
If push notification comment is 'Recurring subscription processed', set to eventDate. |
Subscription |
Next Renewal Date |
Date when the subscription is scheduled to renew. |
date |
Optional |
Set to value from server notification. V1 field: If auto_renew_status is true, and unified_receipt.Latest_receipt_info.expires_date is a future date, then unified_receipt.Latest_receipt_info.expires_date; if current or past date: null Value in date format. |
Set to value from server notification. V2 field: data.RenewalInfoPayload.renewalDate Value in date format. |
If value from REST Resource purchases.subscriptionsv2: subscriptionState is SUBSCRIPTION_STATE_UNSPECIFIED or SUBSCRIPTION_STATE_EXPIRED, set value to null. Otherwise, set to SubscriptionPurchaseLineItem.expiryTime. |
If REST Validate Transaction API: purchaseStatus is 'Active', set to expirationDate; otherwise, set to null. |
Subscription |
Expiration Date |
Date when the subscription expired or is scheduled to expire. |
string |
Optional |
Set to value from server notification. V1 field: unified_receipt.Latest_receipt_info.expires_date Value in date format. |
Set to value from server notification. V2 field: data.TransactionPayload.expiresDate Value in date format. |
If value from REST Resource purchases.subscriptionsv2: subscriptionState is SUBSCRIPTION_STATE_EXPIRED or SUBSCRIPTION_STATE_CANCELED, set value to SubscriptionPurchaseLineItem.expiryTime. |
If REST Validate Transaction API: purchaseStatus is 'Inactive', set to expirationDate; otherwise, set to null. |