IOS6 Transactions Validation

Non-consumables: Set aside the current receipts, perform a restore operation and validate new receipts.

To do this, have a look on RestorePurchases function of PaymentManager class.

Consumables: If you have saved the receipts, either on the device or on your server, revalidate the receipts after implementing your mitigation strategy. If you have not saved the receipts, you cannot validate these past transactions; you should not take any action.

When you get OnTransactionComplete action from the PaymentManager class, it contains PurchaseResult as event data. From  PurchaseResult you can get transaction recipe, send it to your server and validate transaction there.

Note: Apple’s official recommendation to perform receipt validation is to connect to your own server, which then connects to Apple’s servers to validate the receipts.For a number of reasons, this is more secure than connecting to Apple directly.

If you do not want to use your server, you can use apple server for transaction validation.

After you get OnTransactionComplete action and the product state is Purchased or Restored, call

using SA.IOSNative.StoreKit;


The OnVerificationComplete  action will be fired with the VerificationResponse object inside of it.

You will get an action when the request is complete. Action contains IOSStoreKitVerificationResponse data with information about transaction from apple server.

Warning: Use SANDBOX_VERIFICATION_SERVER url ( during app testing  and APPLE_VERIFICATION_SERVER url  ( on production.

So, basically there are 2 scenarios how you can perform the validation for your game:

1. Local Validation.

  • Item was Purchased
  • Use VerifyLastPurchase method
  • If Verifications result is success provide content to your player

You can find a basic sample bellow:

PaymentManager .OnTransactionComplete += OnTransactionComplete;
PaymentManager .OnVerificationComplete += OnVerificationComplete;

PaymentManager .Instance.BuyProduct("");

void OnTransactionComplete (PurchaseResult result) {

        Debug.Log("OnTransactionComplete: " + result.ProductIdentifier);
        Debug.Log("OnTransactionComplete: state: " + result.State);

        switch(result.State) {
        case PurchaseState.Purchased:
		case PurchaseState.Restored:

void OnVerificationComplete (VerificationResponse response) {
	if(response.status == 0) {
		Debug.Log("Transaction is valid");

The validation result is represented as the VerificationResponse object.

If the status field is 0 if the receipt is valid, or one of the error codes listed  bellow:

Status Code



The App Store could not read the JSON object you provided.


The data in the receipt-data property was malformed or missing.


The receipt could not be authenticated.


The shared secret you provided does not match the shared secret on file for your account.

Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions.


The receipt server is not currently available.


This receipt is valid but the subscription has expired. When this status code is returned to your server, the receipt data is also decoded and returned as part of the response.

Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions.


This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.


This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead.


2. Validate on your own server

  • Item was Purchased
  • Send the purchase data to your own server
  • On your server contact Apple server and validate purchase data
  • Listen for reply from your server, and provide the content if validation succeeded

Learn more here