Search code examples
iosin-app-purchasesubscriptionstorekit

StoreKit Subscription with free trial not present in receipt after purchase (tx id off by 1)


I offer a subscription in my application, and after purchase I validate that transaction against the receipt to get its expiration date. I do this by loading the receipt from disk, sending it to Apple for validation/ decryption (I know this is bad practice), and then iterating over the latest_receipt_info in the JSON response looking for a transaction matching the transactionIdentifier of the SKPaymentTransction object.

This works for most subscriptions, but not those offered with a free trial/ introductory offer. Please take a look at my example below:

  1. I purchase a subscription that is returned to my application with a transactionIdentifier of 1000000506350685 and originalTransaction.transactionIdentifier of null.
  2. I get the latest JSON receipt from Apple whose latest entry is one matching my product identifier and timestamp, but the transaction_id is 1000000506350686 and so is original_transaction_id.

Therefore I am unable to validate the purchase.

There are no problems when purchasing a subscription without a free trial/ introductory offer. There are no other objects in the returned receipt that matches the transaction id returned to my application.

This is in the sandbox environment, I am not sure about the behavior in production.

Has anyone had any similar experiences? What can I do to fix this?


Solution

  • I think this is probably due to the fact that you've already purchased that product before in Sandbox, and there's no device receipt in sandbox until you make a purchase (unlike production).

    Either way, what you should be looking at is the latest product_id and expiration_date from the receipt to validate if the subscription is active. Transaction IDs can be keys for your transactions if you're saving them in a database, but shouldn't be used to validate a purchase.

    Here is a really good blog post that goes over what your in-app purchase server should be doing to validate and keep subscription status up-to-date: iOS Subscriptions are Hard

    I do this by loading the receipt from disk, sending it to Apple for validation/ decryption (I know this is bad practice).

    This is actually the recommended approach by Apple.