Confirm payments and record delivery results
After the app server verifies the receipt of a consumable product, the app client sends a payment confirmation request and records the product delivery result. RequestPurchaseAsync() sends the payment confirmation request, and ItemResultAsync() records the product delivery result that the app or app server processed. Of the values these two methods need, the app server passes the values contained in the receipt verification response to the app client.
1. Request payment confirmation
For Apple App Store and Google Play payments, call RequestPurchaseAsync() to send the payment confirmation request after the app server finishes receipt verification. Use this request only for consumable products. The app decides the call order of product delivery and this request, but to prevent product loss, deliver the product first and then send the payment confirmation request. After you send the payment confirmation request, proceed with finishing the transaction for Apple or finishing the consumable product transaction for Google, and then proceed with 2. Record product delivery results. Recording product delivery results is not a prerequisite for finishing the transaction, so do not delay finishing the transaction even if recording fails.
For subscription products, confirm the subscription with Apple subscription completion and Google subscription completion instead of RequestPurchaseAsync(). For the processing flow of PG payments, see PG product delivery. Steam payments use Steam purchase finalization instead of RequestPurchaseAsync().
RequestPurchaseAsync
Call parameters
| Field name | Type | Required | Description |
|---|---|---|---|
| request | PurchasePostRequest | Required | The payment confirmation request data object. |
| context | ApiCallContext | Optional | Per-call settings object that specifies the idempotency key, cancellation token, and request policy. If omitted, the default values are used. |
PurchasePostRequest
| Field name | Type | Required | Description |
|---|---|---|---|
AxylReceipt | string | Required | The receipt of the purchase to confirm. For Apple, pass the StoreKit 2 transaction JWS; for Google, pass the purchase token (purchaseToken). |
FinalizationMsg | string | Optional | The confirmation message of an Apple or Google payment. |
ProductId | string | Optional | The product ID of a Google payment. When you pass a purchase token (purchaseToken) string in AxylReceipt, the token does not contain product information, so you must pass this value. If you do not pass it, the server rejects the request. When you pass the old format that contains purchase_data and signature, the product ID is read from the receipt, so you can omit it. |
ProviderId | PurchasePostRequestProviderId | Required | The market and payment method identifier. |
StoreTransactionId | string | Optional | The store transaction ID of an Apple payment. For Apple, it is the StoreKit 2 re-verification key, so you must pass it. |
PurchasePostRequest has no AccountUuid field. Therefore, do not pass AccountUuid to RequestPurchaseAsync().
Call example
Check the success result of PaymentsRequestPurchaseResult and the domain-specific results defined by this method in the following example and in the response status. For the result model and handling principles of common failures that prevent the request from being performed, see Common error handling.
using Hive.Axyl.Payments;
using Hive.Axyl.Core;
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();
var request = new PurchasePostRequest
{
AxylReceipt = receipt,
ProductId = "com.game.item.gold_100",
ProviderId = PurchasePostRequestProviderId.Google
};
PaymentsRequestPurchaseResult result = await payments.RequestPurchaseAsync(request);
switch (result)
{
case PaymentsRequestPurchaseResult.Success success:
Debug.Log($"Payment confirmation request completed: {success.Data.Meta}");
break;
case PaymentsRequestPurchaseResult.PaymentBadRequest:
case PaymentsRequestPurchaseResult.PaymentInvalidParameter:
case PaymentsRequestPurchaseResult.PaymentResourceNotFound:
case PaymentsRequestPurchaseResult.PaymentUnauthorized:
case PaymentsRequestPurchaseResult.VerifyError:
Debug.LogError("Check the request values and the payment status.");
break;
case PaymentsRequestPurchaseResult.VerifyDuplicated:
Debug.LogError("Check whether the payment has already been processed.");
break;
case PaymentsRequestPurchaseResult.UnknownOutcome unknownOutcome:
Debug.LogWarning($"Unknown result: {unknownOutcome.Code}");
break;
case PaymentsRequestPurchaseResult.Failure failure:
HiveError err = failure.Problem;
Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
break;
default:
Debug.LogWarning($"Unhandled result: {result.GetType().Name}");
break;
}
Response data
On success, Data of PaymentsRequestPurchaseResult.Success contains the response meta information.
| Field name | Type | Required | Description |
|---|---|---|---|
Data.Meta | string | Optional | The response meta information. |
Response status
| Response case | Description | App client handling |
|---|---|---|
Success | The payment confirmation request succeeded | Proceed with the payment processing order that the app defined |
PaymentBadRequest | The payment request cannot be processed. | Check the request values and call conditions |
PaymentInvalidParameter | The payment request parameters are invalid. | Check the request fields, such as AxylReceipt |
PaymentResourceNotFound | The payment information to confirm cannot be found. | Check the receipt and transaction information |
PaymentUnauthorized | There is no permission for the payment request. | Check the app and authentication status |
VerifyDuplicated | The receipt has already been verified. | Check whether it is duplicate processing |
VerifyError | An error occurred during payment verification. | Check the receipt and the market payment status |
UnknownOutcome | A domain-specific result that the SDK does not know. | Treat it as a failure and record the result code |
Failure | A common failure. See Common error handling. | Handle it according to the common error handling criteria |
2. Record product delivery results
After you deliver the product, record the delivery result with ItemResultAsync(). This method is for recording the delivery result. It does not confirm the payment or decide whether to deliver the product. In AxylTransactionId of the request, put the hiveAxylTransactionId that the app server received in the receipt verification response and passed to the app client.
The app or app server handles product delivery restoration and retries. For how to call ItemResultAsync() for each payment provider, see Apple product delivery, Google product delivery, Steam product delivery, and PG product delivery.