Native apps

Piano gives you the ability to grant access to users who have purchased subscriptions through the In-App Purchase (IAP) process. The IAP subscriptions that are created in Piano look and feel just like subscriptions that were purchased on the web, with a few notable exceptions.

Upon purchase of a subscription within an app, the app - or your server in between - should submit the encrypted receipt to Piano. Piano will store this receipt, and “replay” it to the subscription provider, getting back the relevant access details and updating the user's subscription and access accordingly.

  • The access that gets granted is just like any other access, available via the API. It also triggers webhooks like subscription_auto_renewed and subscription_canceled.
  • Access will be granted for the full subscription period.
  • The subscription's next bill date will accurately reflect the in-app subscription expiration date.
  • An email will be sent to the publisher every time there is a failure connecting to the Apple validation server (failures only, not rejections of access which is expected).

Requirements and Assumptions

The requirements and assumptions to using Piano for IAP validation are:

  • The user must be logged in at the time of purchase for the cross-device syncing to work, even though Piano's IAP validation works across all types of user integrations - Piano Accounts, Janrain, and Local Users.
  • The IAP purchase process must happen through the app itself, as the name suggests. In-app payment providers don't allow Piano to collect credit card details in the app, and most disallow even redirecting the user to a web page outside of the app.
  • The checkout user experience is much different in-app than on the web. While Piano controls most everything during checkout on desktop - offers, credit card collection, receipt displaying - inside of the app Piano controls little-to-none of the end-user experience. It is only after checkout completes using the in-app payment provider that Piano is notified.

Setup and Configuration

You must have Apple iTunes configured as a supported External API to begin the process of configuring integration with Apple. If you don't have the capability to create an External API in the dashboard, contact your account executive.

Create the External API Configuration

First, click on Manage → External APIs.

 manage external APIs

Then, click the blue New button and enter the relevant details.

 add new external api

The password field should be the shared secret if you are validating auto-renewing subscriptions. Leave it blank if you are not validating auto-renewing subscriptions.

The receipt validation URL should be if you are validating receipts against sandbox for testing, and if you are validating receipts in production.

Create the Term

Click Manage → Terms and click the blue New button to add a new term. Click the External Service icon.

 external server term

Select the Apple iTunes provider and enter the Name and Resource fields.

 create new term

Click Create.

Specify Term-Specific Configuration

Once you have created the External Service term, you must configure the specific details of how Piano should perform the receipt validation and access checking within the receipt. There are three main ways that Piano can check and grant access during receipt validation:

  • Grant access due to the purchase of the app itself (fixed-time)
  • Grant access due to a purchase inside of the app (fixed-time)
  • Grant access due to subscribing inside of the app (subscription)

In each of these cases, you must configure the term accordingly.

Purchase of the App

If you are granting access due to the purchase of the app itself, slide the toggle to NON IN APP on the term.

 purchase of app

This will reveal the two fields you need to configure: Bundle id and Fixed time access period. For anyone that purchases the app, after you submit the receipt to Piano, we will inspect the receipt to ensure that the receipt contains the configured bundle_id property and grant that user the specified access period.

Purchase Inside the App (fixed-time)

If you want to grant access for a fixed period of time to a user who makes a purchase inside of your app, you can configure Piano to look for a specific product_id inside of the receipt and grant access for a set period of time. In this case, slide the toggle to IN APP and the secondary toggle to FIXED TIME, which will reveal the Product id and Fixed time access period that Piano will use.

 fixed time IAP

For anyone that purchases the app, after you submit the receipt to Piano, we will inspect the receipt to ensure that the receipt contains the configured product_id property and grant that user the specified access period.

A subscription will not be created in this case, and Piano will not perform any recurring checks to ensure the user is still an active subscriber.

Subscribing Inside the App (subscription)

If you want to grant access due to someone subscribing inside of the app, slide the toggle to IN APP and the secondary toggle to SUBSCRIPTION. This will reveal the Verification period and Grace period configuration options.

 iap subscription

In this case, after you submit the receipt to Piano, we will inspect to receipt to ensure that the receipt has the specified product_id and expire_date, as per Apple's specifications. This ensures that the user has purchased an auto-renewing subscription inside of the app. Piano will create a subscription that matches the in-app subscription that has been created. Access will be granted to the expire_date on the subscription

The Verification period is the period of time that will lapse in between times that Piano checks the IAP provider. Typically this process is anywhere between 1 day and 7 days. On this schedule, Piano will query the IAP provider to see if the subscription is still valid. In the case of Apple, if there is a cancelation_date in the receipt, we will treat this as a canceled subscription - again, as per Piano.

On the day after the associated access is meant to expire, if Piano has not determined that the user has renewed their subscription, we will apply the first day of grace period. Piano will move the next verification date one day forward, and grant additional access for one day. This mimics the grace period logic of payment terms.

For the duration of the grace period, Piano will continue to check the IAP provider and - assuming the user hasn't renewed inside of the app - grant one additional day of access. After the grace period is over, if the user still hasn't renewed, the subscription is set to ended and the subscription_auto_renewed_failure webhook is sent.

Getting the Receipt

To get the receipt from the app itself, execute this code after successful purchase:

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];

Piano expects the Grand Unified Receipt, not the individual iOS-6 style receipts.

Submitting the Receipt

To submit the receipt, you can use the generated libraries or you can submit the raw request via the command-line.

Using the objective-C client, you can submit the receipt directly to Piano:

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
TPClientApi *api =[TPClientApi initWithBasePath:@"YOUR_URL" apiToken:nil];
ConversionExternalApi *conversionApi = [api getConversionExternalApi];
[conversionApi  externalVerifiedCreate:@"YOUR_AID"
                fields:[NSString stringWithFormat:@"{\"%@\":\"%@\"}", @"receiptData", [receipt base64EncodedDataWithOptions:0]]
                user_token:userToken // this assumes you have gotten the user token from your server
                completionHandler:^(TPAnonTermConversion* output, NSError* error) {
                    if (error) {
                    } else {
                        NSString *termConversionId = [NSString stringWithFormat:@"%@ %@", @"Term conversion id", output.term_conversion_id];
                        NSLog(@"%@", termconversionId);

If you are submitting the Using the java client, you can submit the receipt like this:

        com.tinypass.client.publisher.model.TermConversion termConversion = client(publisher).publisherConversionExternal().externalVerificationCreateRequest()
                .fields("{\"receiptData\":\"<basee64-encoded, encrypted receipt data>\"}")

Using curl, you can perform the same using this syntax:

curl -X POST -d @term-conversion.json

Where term-conversion.json contains the following data:

check_validity=true&uid=1284736193&api_token=YOUR_API_TOKEN&aid=YOUR_AID&term_id=TMLFS01D7IRE&fields={"receiptData":"<base64-encoded, encrypted receipt"}

Note: If you are using curl, ensure that you have URL-encoded the base64-encoded receipt prior to submission. Otherwise, any + characters will be treated as spaces and the receipt will be considered invalid.

Dashboard Updates

There are a few updates that are made in the My Account component and publisher dashboard for in-app subscriptions. These updates are made primarily because most of the administrative functions are not available for in-app subscriptions.

My Account

In the My Account component, the subscriptions that In App Purchase (IAP) users have will be different than regular subscriptions where Piano handles the billing.

  • If the user has an active or expired iOS subscription, clicks on the Cards tab, and has no credit cards, Piano will display an informational message: “If you are attempting to add a credit card for your in-app subscription, please login to your account on your device”
  • The cancel/refund option will not be available for in-app subscriptions
  • The expiration date of the subscription will be the actual expiration date from the in-app purchase
  • Because Piano does not know whether auto-renew is enabled or disabled, we will use consolidated messaging describing the status of the subscription: “Your subscription is valid through Month Day, Year”
  • Turning on and off auto-renew will not be available

Here is an example of how an IAP would appear in a user's My Account component.

Publisher Dashboard

Some customer care functionality will be disabled in the VX Dashboard for users who completed an IAP.

  • The Cards tab will be empty unless the user adds a credit card through the My Account component on desktop
  • Customer care will not be able to cancel, cancel and refund, change the payment method, toggle auto-renew, or update the next bill date for iOS subscriptions

In a user's subscription details, IAP will be identified as an “External” term.

In the subscriptions section of a user profile, IAP will be identified by both the “External” term type, in this case iOS, and the In-app Payment method.

The history section of a user profile will show IAP purchases, but will not list any transaction details. It will merely show the date on which a subscription was renewed in-app.

VX Reports

The New Sales and Subscriptions report will be updated to include IAP subscriptions. From the dropdown in the New Sales report, you will be able to choose more than one term to display as well as group the iOS terms only.

Revenue for IAP subscriptions will be zero.

In the Subscriptions report, IAP subscriptions will be included in total new, growth, canceled and expired.

In-app subscribers will appear in the subscriptions log. Tinypass will update the Charge Count in the subscription log whenever the access expiration is detected to have changed in the IAP receipt, which will allow publishers to track the number of renewals.

IAP transactions will not appear in the transaction log. As transactions will not appear in the Tinypass system, IAP will not be included in the revenue recognition report.