IsValidateOneStorePurchase
public BackendReturnObject IsValidateOneStorePurchase(bool isGlobal, string productId, string purchaseToken, string receiptDescription); public BackendReturnObject IsValidateOneStorePurchase(bool isGlobal, string productId, string purchaseToken, string receiptDescription, string iapPrice, string iapCurrency);
Invalid special characters
Special Character | Description |
---|---|
' | Single quotation mark |
\ | Backslash |
Valid special characters
Special Character | Description |
---|---|
. | 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
Value | Type | Description |
---|---|---|
isGlobal | bool | 'true' if the payment occurred overseas, 'false' if the payment occurred in Korea |
productId | string | OneStore.Purchasing.PurchaseData.purchase.ProductId |
purchaseToken | string | OneStore.Purchasing.PurchaseData.purchase.PurchaseToken |
receiptDescription | string | Additional details to be stored |
iapPrice | string | Price of the item |
iapCurrency | string | Currency for the item |
Description
Products purchased from IPurchaseCallback.OnConsumeSucceeded() in the In-app payment service supported by ONE store can have their receipts called and verified 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 verification function.
Display amount (optional)
If you wish to display the amount of relevant purchase details in the BACKND console's receipt verification field, parameter values iapPrice and iapCurrency must be added.
When QueryProductDetails of the PurchaseClientImpl class is called, OnProductDetailsSucceeded is called from the handler of the registered IPurchaseCallback, allowing the amount to be checked.
public class YourCallback: IPurchaseCallback
{
public void OnProductDetailsSucceeded(List<ProductDetail> productDetails)
{
OneStoreReceiptTest.productDetailList = productDetails;
Debug.Log("OnProductDetailsSucceeded ");
foreach (var pro in productDetails)
{
Debug.Log($"{pro.title} / {pro.type} / {pro.price} / {pro.promotionPrice} / {pro.productId}");
}
}
public void OnPurchaseSucceeded(List<PurchaseData> purchases)
{
Debug.Log("OnPurchaseSucceeded ");
foreach (var pro in purchases)
{
OneStoreReceiptTest.purchaseClient.ConsumePurchase(pro);
}
}
public void OnConsumeSucceeded(PurchaseData purchase)
{
Debug.Log("OnConsumeSucceeded ");
string productPrice = "";
string productCurrency = "";
OneStoreReceiptTest.productDetailList.ForEach(productDetail =>
{
if (productDetail.productId == purchase.ProductId)
{
productPrice = productDetail.price;
productCurrency = productDetail.priceCurrencyCode;
}
});
var bro = Backend.Receipt.IsValidateOneStorePurchase(false, purchase.ProductId, purchase.PurchaseToken, data, productPrice, productCurrency);
if (bro.IsSuccess())
{
Debug.Log("ValidateOneStoreReceipt : " + bro);
}
else
{
Debug.LogError("ValidateOneStoreReceipt : " + bro);
}
}
}
public class OldOneStoreReceiptTest : MonoBehavior
{
// Start is called before the first frame update
public static PurchaseClientImpl purchaseClient = null;
public static List<ProductDetail> productDetailList = new List<ProductDetail>();
public static List<string> productList = new List<string>();
public void InitializeOneStore()
{
purchaseClient = new PurchaseClientImpl("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ~~");
purchaseClient.Initialize(new YourCallback());
purchaseClient.LaunchUpdateOrInstallFlow(action =>
{
Debug.Log("LaunchUpdateOrInstallFlow " + action.ToString());
});
productList.Add("onestore_gamepoint");
purchaseClient.QueryProductDetails(productList.AsReadOnly(), ProductType.ALL);
}
private void Purchase()
{
if (purchaseClient == null)
{
Debug.LogError("purchaseClient is null");
return;
}
Debug.Log(" Login with ONE store successful");
var builder = new PurchaseFlowParams.Builder();
builder.SetProductId(productList[0]);
purchaseClient.Purchase(builder.Build());
new OneStoreAuthClientImpl().LaunchSignInFlow(signInResult =>
{
if (signInResult.IsSuccessful())
{
Debug.Log("LaunchSignInFlow Success");
}
else
{
Debug.LogError("LaunchSignInFlow Fail");
}
});
}
}
Example
Synchronous
List<ProductDetail> productDetailList;
public void BuyButton(int i)
{
string productId = "gold";
// Payment logic
ProductType productType = ProductType.INAPP;
var purchaseFlowParams = new PurchaseFlowParams.Builder()
.SetProductId(productId) // Addition necessary
.SetProductType(productType) // Addition necessary
.SetDeveloperPayload("Enter any additional information if necessary") // Optional
.Build();
purchaseClient.Purchase(purchaseFlowParams);
}
public void OnPurchaseSucceeded(List<PurchaseData> purchases)
{
bool isGlobal = false; // When the app has only been released in Korea via ONE store
/*
Process BACKND receipt verification
*/
for(int i = 0; i < purchases.Count; i++) {
BackendReturnObject validation = Backend.Receipt.IsValidateOneStorePurchase(isGlobal, purchases[i].ProductId, purchases[i].PurchaseToken, "receiptDescription");
// When receipt verification is successful
if (validation.IsSuccess()) {
Debug.Log($"ProcessPurchase: PASS. Product: {purchases[i].ProductId}");
if (purchases[i].ProductId == "gold") {
// Hand out Gold
}
} else {
Debug.Log($"ProcessPurchase: FAIL. Unrecognized product: {purchases[i].ProductId}");
}
}
}
Asynchronous
public void BuyButton(int i)
{
string productId = "gold";
// Payment logic
ProductType productType = ProductType.INAPP;
var purchaseFlowParams = new PurchaseFlowParams.Builder()
.SetProductId(productId) // Addition necessary
.SetProductType(productType) // Addition necessary
.SetDeveloperPayload("Enter any additional information if necessary") // Optional
.Build();
purchaseClient.Purchase(purchaseFlowParams);
}
public void OnPurchaseSucceeded(List<PurchaseData> purchases)
{
bool isGlobal = false; // When the app has only been released in Korea via ONE store
/*
Process BACKND receipt verification
*/
for(int i = 0; i < purchases.Count; i++) {
Backend.Receipt.IsValidateOneStorePurchase(isGlobal, purchases[i].ProductId, purchases[i].PurchaseToken, "receiptDescription", (callback) =>
{
// When receipt verification is successful
if (callback.IsSuccess()) {
Debug.Log($"ProcessPurchase: PASS. Product: {purchases[i].ProductId}");
if (purchases[i].ProductId == "gold") {
// Hand out Gold
}
} else {
Debug.Log($"ProcessPurchase: FAIL. Unrecognized product: {purchases[i].ProductId}");
}
});
}
}
ReturnCase
Success cases
When successful
statusCode : 201
message : Success
returnValue : {"usedDate":"2018-10-15T05:17:49Z"}
Error cases
When the ONE store information in the console is incorrect
statusCode : 400
errorCode : UndefinedParameterException
message : undefined onestore client_id, onestore client_id cannot be checked
When receipt verification is not valid
statusCode : 400
errorCode : BadParameterException
message : bad token, Invalid token
When the receipt token is string.Empty
statusCode : 400
errorCode : BadParameterException
message : undefined token, token cannot be checked
When productId is string.Empty
statusCode : 400
errorCode : BadParameterException
message : undefined productId, productId cannot be checked
Tampered/forged receipt token
statusCode : 400
errorCode : BadParameterException
message : bad token, Invalid token
Already used receipt token
statusCode : 409
errorCode : UsedReceipt
message : This receipt has already been used. usedDate: 2018-02-15T04:01:50.000Z