Skip to main content
Version: 5.17.0

IsValidateApplePurchase

public BackendReturnObject IsValidateApplePurchase(string receipt, string receiptDescription);

Note on replacing iapPrice data for certain countries\

Some countries use commas (,) instead of periods (.) to represent decimal numbers.\ In such countries, the iapPrice value provided by each store may also include commas (,).\ Since BACKND's receipt validation can only process numeric data, using iapPrice values that include commas (,) as-is may cause the amount to be processed incorrectly as 0.\ Please replace commas(,) with periods (.) in iapPrice data before use.\

Invalid special characters

Special CharacterName
'Single quotation mark
\ Backslash

Valid special characters

Special CharacterName
.Period
,Comma
"Double quotation mark
()Parentheses
!Exclamation mark
?Question mark
~Tilde
@At sign
*Asterisk
+Plus
-Hyphen
/Slash

If you are using special characters that are not listed above, manually check that the receipt verification works properly before applying.

Parameters

ValueTypeDescription
receiptstringPurchasing.PurchaseEventArgs.purchasedProduct.receipt
receiptDescriptionstringAdditional details to be stored

Description

IStoreListener.ProcessPurchase() in the IAP service supported by Unity accepts the receipt for the purchased product and verifies it via the BACKND server.

  • BACKND verifies the validity of the receipt itself and the purchased productId.
  • You must be logged in to BACKND to use its receipt verification function.
  • Apple receipt verification supports normal product receipts only. It does not support subscription product receipts.

To verify Apple receipts, Apple Console must be configured. For more information, please refer to the Apple Payment Console Settings documentation.

Display amount of purchase (optional)

To display the transaction price in the receipt verification section of the BACKND Console, you must include the parameters iapPrice and iapCurrency.

 private void GetCheckGoogleReceiptWithPrice(PurchaseEventArgs purchaseEvent)
{
string receiptToken = purchaseEvent.purchasedProduct.receipt;
var bro = Backend.Receipt.IsValidateApplePurchase(
json: receiptToken,
receiptDescription: "Purchased",
isSubscription: false,
iapPrice: purchaseEvent.purchasedProduct.metadata.localizedPrice,
iapCurrency: purchaseEvent.purchasedProduct.metadata.isoCurrencyCode);
}

Example

// example
// unity iap servcie process
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
string receiptJson = args.purchasedProduct.receipt;

/*
Processing BACKND receipt verification
*/
BackendReturnObject validation = Backend.Receipt.IsValidateApplePurchase(receiptJson, "receiptDescription");

// When displaying the amount in the console
decimal iapPrice = args.purchasedProduct.metadata.localizedPrice;
string iapCurrency = args.purchasedProduct.metadata.isoCurrencyCode;
BackendReturnObject validation = Backend.Receipt.IsValidateGooglePurchase(receiptJson, "receiptDescription", iapPrice, iapCurrency);

// When receipt verification is successful
if(validation.IsSuccess())
{
// Checks the product ID and provides rewards accordingly
// A consumable product has been purchased by this user.
if(string.Equals(args.purchasedProduct.definition.id, kProductIDConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
// The consumable item has been successfully purchased, add 100 coins to the player's in-game score.
ScoreManager.score += 100;
}
// Or ... a non-consumable product has been purchased by this user.
else if(string.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
// TODO: The non-consumable item has been successfully purchased, grant this item to the player.
}
// Or ... a subscription product has been purchased by this user.
else if(string.Equals(args.purchasedProduct.definition.id, kProductIDSubscription, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
// TODO: The subscription item has been successfully purchased, grant this to the player.
}
}
// When receipt verification fails
else
{
// Or ... an unknown product has been purchased by this user. Fill in additional products here....
Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
}

// Return a flag indicating whether this product has completely been received, or if the application needs
// to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still
// saving purchased products to the cloud, and when that save is delayed.
return PurchaseProcessingResult.Complete;
}

ReturnCase

Success cases

When successful\ statusCode : 201\ message : Success\ returnValue : {"usedDate":"2018-10-15T05:17:49Z"}

Error cases

Expired receipt token\ statusCode : 400\ errorCode : BadParameterException\ message : bad token, Invalid token

Tampered/forged receipt token\ statusCode : 400\ errorCode : BadParameterException\ message : bad token, Invalid token

Receipt of refund/cancellation\ statusCode : 402\ errorCode : AbnormalReceipt\ message : This receipt has changed status. purchaseState: cancelled

Already used receipt token\ statusCode : 409\ errorCode : UsedReceipt\ message : This receipt has already been used. usedDate: 2018-02-15T04:01:50.000Z