VerifyPurchase
Used to verify a purchase receipt for Apple AppStore, Google Play, Facebook or Windows. The contents passed into receiptData are store-specific. On success, the player will be awarded the associated currencies.
ReceiptData formats
Apple AppStore
Use "itunes" as the storeId.
StoreKit 2 receiptData format
{
"transactionId": "TRANSACTION-ID",
"excludeOldTransactions": false
}
Note: This would be the TransactionID you receive in your App Store receipts, not to be confused with OriginalTransactionID.
Legacy receipts receiptData format
{
"receipt": "ENCODED-RECEIPT-DATA",
"excludeOldTransactions": false
}
Google Play Store
Use "googlePlay" as the storeId.
Ensure that the parameter includeSubscriptionCheck setting is set to true for Product Type as Subscription.
Google Play receiptData format:
{
"productId" : "gems_pack_small",
"orderId" : "GPA.0000-1111-2222-33333",
"token" : "ENCODED_TOKEN_STRING",
"developerPayload" : "STRING_ENCODED_JSON",
"includeSubscriptionCheck" : false
}
Facebook
Use "facebook" as the storeId.
Facebook receiptData format:
{
"signedRequest": "string-of-signedRequest"
}
Amazon Store
Use "amazon" as the storeId.
Amazon receiptData format:
{
"receiptId": "a-receipt-id",
"userId": "a-user-id"
}
Meta Horizon Store
Use "metaHorizon" as the storeId.
Meta Horizon receiptData format:
{
"userId": "META-USER-ID",
"sku": "PURCHASE-SKU",
"transactionId": "PURCHASE-TRANSACTION-ID",
"consumeOnVerify": true
}
Note: consumeOnVerify will consume CONSUMABLE items server-side which we recommend to prevent accidental extra item consumptions from the user.
Response fields
The following fields are included in the json response:
| Field | Description |
|---|---|
| resultCode | the overall status of the operation |
| errorMessage | (optional) message describing non-zero result codes |
| store | the store used for the purchase |
| transactionSummary | the store-specific response details. Contents vary by store-type. |
| rewards | the total currencies being rewarded as a result of the purchases(s). Includes subsections by currency scope. |
| currency | currency balances. |
| parentCurrency | balances of parent currencies (if any) |
| peerCurrency | balances of peer currencies (if any) |
| server_time | utc time on the server (in millis) |
VerifyPurchase responses
The key values of the return to evaluate include:
processedCount- number of transactions successfully processed. To be processed, a transaction receipt must be valid, the product must be found, and the transaction must not have been processed before.unprocessedCount- the number of transactions that were rejected. See thetransactionStatuscode associated with the transaction for details.
| Service | Operation |
|---|---|
| appStore | VERIFY_PURCHASE |
Method Parameters
| Parameter | Description |
|---|---|
| storeId | The store type - "itunes", "googlePlay", "amazon", "facebook", "metaHorizon" or "windows" |
| receiptData | A JSON object with data in the format for the specified store |
Usage
- C#
- C++
- Objective-C
- Java
- JavaScript
- Dart
- Roblox
- Cloud Code
- Raw
string storeId = "hghghsgfh";
string receiptData = "{\"productId\":\"ugfhffhgj\"}";
SuccessCallback successCallback = (response, cbObject) =>
{
Debug.Log(string.Format("Success | {0}", response));
};
FailureCallback failureCallback = (status, code, error, cbObject) =>
{
Debug.Log(string.Format("Failed | {0} {1} {2}", status, code, error));
};
_bc.AppStoreService.VerifyPurchase(storeId, receiptData, successCallback, failureCallback);
const char *storeId = "hghghsgfh";
const char *receiptData = "{\"productId\":\"ugfhffhgj\"}";
_bc->getAppStoreService()->verifyPurchase(storeId, receiptData, this);
NSString *storeId = @"hghghsgfh";
NSString *receiptData = @"{\"productId\":\"ugfhffhgj\"}";
BCCompletionBlock successBlock; // define callback
BCErrorCompletionBlock failureBlock; // define callback
[[_bc appStoreService] verifyPurchase:storeId
receiptData:receiptData
completionBlock:successBlock
errorCompletionBlock:failureBlock
cbObject:nil];
String storeId = "hghghsgfh";
String receiptData = "{\"productId\":\"ugfhffhgj\"}";
this; // implements IServerCallback
_bc.getAppStoreService().verifyPurchase(storeId, receiptData, this);
public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
{
System.out.print(String.format("Success | %s", jsonData.toString()));
}
public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
{
System.out.print(String.format("Failed | %d %d %s", statusCode, reasonCode, jsonError.toString()));
}
var storeId = "hghghsgfh";
var receiptData = {
"productId": "ugfhffhgj"
};
_bc.appStore.verifyPurchase(storeId, receiptData, result =>
{
var status = result.status;
console.log(status + " : " + JSON.stringify(result, null, 2));
});
var storeId = "hghghsgfh";
var receiptData = {
"productId": "ugfhffhgj"
};
ServerResponse result = await _bc.appStoreService.verifyPurchase(storeId:storeId, receiptData:receiptData);
if (result.statusCode == 200) {
print("Success");
} else {
print("Failed ${result.error['status_message'] ?? result.error}");
}
local storeId = "hghghsgfh"
local receiptData = {
productId = "ugfhffhgj"
}
local callback = function(result)
if result.statusCode == 200 then
print("Success")
else
print("Failed | " .. tostring(result.status))
end
end
_bc:getAppStoreService():verifyPurchase(storeId, receiptData, callback)
var storeId = "hghghsgfh";
var receiptData = {
"productId": "ugfhffhgj"
};
var appStoreProxy = bridge.getAppStoreServiceProxy();
var postResult = appStoreProxy.verifyPurchase(storeId, receiptData);
if (postResult.status == 200) {
// Success!
}
{
"service": "appStore",
"operation": "VERIFY_PURCHASE",
"data": {
"storeId": "itunes",
"receiptData": {
"receipt": "a-receipt"
}
}
}
JSON Response
{
"data": {
"resultCode": 0,
"serverTime": 1473325588695,
"store": "itunes",
"transactionSummary": {
"processedCount": 1,
"unprocessedCount": 1,
"transactionDetails": [
{
"raw_in_app_ownership_type": "PURCHASED",
"original_transaction_id": "2000001113677862",
"raw_environment": "Sandbox",
"type": "CONSUMABLE",
"referencePrice": 9999,
"price": 129990,
"product_id": "coins_100",
"currency": "CAD",
"raw_transaction_reason": "PURCHASE",
"transaction_id": "2000001113677862",
"in_app_ownership_type": "PURCHASED",
"transactionResultCode": 100,
"app_account_token": "00000000-0000-0000-0000-000000000000",
"quantity": 1,
"store_front_id": "143455",
"sandbox": true,
"errorMessage": null,
"app_transaction_id": "705242908014669349",
"transaction_reason": "PURCHASE",
"original_purchase_date": 1769884662000,
"store_front": "CAN",
"itemId": "coins_100",
"processed": false,
"environment": "Sandbox",
"raw_type": "Consumable",
"bundle_id": "com.braincloud.newstorekit2bc",
"purchase_date": 1769884662000
}
],
"extra": {
"appleReceipt": "stringified json receipt data"
}
},
"rewards": {
"currency": {
"coins": 1000
},
"parentCurrency": {
"awesomeMaster": {
"rubies": 2000
}
},
"peerCurrency": {
"peerApp": {
"rogerCurrency": 30
}
}
}
},
"status": 200
}
Common Error Code
Status Codes
| Code | Name | Description |
|---|---|---|
| 0 | RESULT_OK | Successfully verified, new currencies awarded. |
| 100 | RESULT_FAILED_ALREADY_PROCESSED | Already verified and awarded currencies. |
| 101 | RESULT_FAILED_APPSTORE_ERROR | Purchase error with the used app store. |
| 102 | RESULT_FAILED_PRODUCT_NOT_FOUND | Cannot locate the product in brainCloud Product Inventory. *This is likely a configuration error in the brainCloud product - double-check the price settings for the product.** |
| 103 | RESULT_FAILED_UNKNOWN_ERROR | Unexpected error. |
| 104 | RESULT_FAILED_CONFIGURATION_ERROR | Configuration error on the used app store. |
| 105 | RESULT_FAILED_REQUEST_ERROR | Credential missing for used app store. Ensure Facebook or Stream credential is correct. |