Restore purchases
Retrieve again the undelivered purchases whose payment was completed but whose products were not received because of a communication error or an abnormal termination, and deliver the missing products. This reduces payment-related complaints and protects the assets that users purchased.
Follow the steps below to restore unfinished transactions.
1. Restore unfinished transactions
RestorePurchasesAsync
To implement purchase restoration, call RestorePurchasesAsync() provided by the Hive Axyl SDK. It returns the list of purchases whose payment was completed but whose products have not been delivered yet.
Call parameters
| Field name | Type | Required | Description |
|---|---|---|---|
| request | PurchaseRestoreRequest | Required | The request data for purchase restoration. |
| context | ApiCallContext | Optional | Per-call settings object that specifies the idempotency key, cancellation token, and request policy. If omitted, the default values are used. |
PurchaseRestoreRequest
| Field name | Type | Required | Description |
|---|---|---|---|
ProviderId | PurchaseRestoreRequestProviderId | Required | The market identifier. Because this request is for Steam purchase restoration only, specify only Steam. |
AppVersion | string | Optional | The app version. |
Country | string | Required | The country code (two-letter ISO 3166-1 code). Example: KR |
Language | string | Required | The language code (two-letter ISO 639-1 code). Example: ko |
ServerId | string | Optional | The server ID you check on the App Server tab after you register the app server in App Info > App Server by following Hive Console App Server. If specified, only the orders of that server are returned. If omitted, all orders are returned. |
Call example
Check the success result of PaymentsRestorePurchasesResult and the domain-specific results (Outcome) defined by this method in the example below and in the response status. For the result model and handling principles of common failures (Failure) that prevent the request from being performed, see Common error handling.
using Hive.Axyl.Payments;
using Hive.Axyl.Core;
// payments: IPaymentsService registered during initialization (for how to retrieve it, see [Install and initialize the module](../init.md))
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();
var request = new PurchaseRestoreRequest
{
ProviderId = PurchaseRestoreRequestProviderId.Steam,
Country = "KR",
Language = "ko",
ServerId = "server01"
};
PaymentsRestorePurchasesResult result = await payments.RestorePurchasesAsync(request);
switch (result)
{
case PaymentsRestorePurchasesResult.Success success:
// Process the list of restorable purchases
if (success.Data.Restores is { } restores)
{
foreach (var restore in restores)
{
Debug.Log($"orderId: {restore.OrderId}, productId: {restore.ProductId}");
}
}
break;
case PaymentsRestorePurchasesResult.PaymentBadRequest:
// The request cannot be processed. Check the request values and call conditions
break;
case PaymentsRestorePurchasesResult.PaymentInvalidParameter:
// Invalid parameter. Check the request values
break;
// Handle common Failure
case PaymentsRestorePurchasesResult.Failure failure:
HiveError err = failure.Problem;
Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
break;
// Safety net: unhandled results and unknown new results (UnknownOutcome)
default:
Debug.LogWarning($"Unhandled result: {result.GetType().Name}");
break;
}
Response data
On success, the result is contained in Data (PurchaseRestoreResponseData) of PaymentsRestorePurchasesResult.Success.
| Field name | Type | Required | Description |
|---|---|---|---|
Data.Restores | IReadOnlyList<RestorePurchase>? | Optional | The list of restorable purchases. |
Data.Meta | string? | Optional | Response meta information. |
RestorePurchase
| Field name | Type | Required | Description |
|---|---|---|---|
Currency | string | Optional | The currency code. |
GameServerPriceVerifyKey | string | Optional | The key for verifying the payment amount on the app server. |
IapPayload | string | Optional | An additional payload to pass to the app server. |
OrderId | string | Optional | The order ID. |
PaidDateTime | string | Optional | The payment completion time (yyyy-MM-dd HH:mm:ss). |
PaidDateTimeMs | long | Optional | The payment completion time (Unix epoch, in milliseconds). |
Price | decimal | Optional | The payment amount. |
ProductId | string | Optional | The product ID (market_pid). |
ProviderId | RestorePurchaseProviderId | Required | The payment method identifier. This response returns Steam. |
PurchaseDateTime | long | Optional | The purchase date and time (Unix epoch, in milliseconds). |
Quantity | int | Optional | The purchase quantity. |
StartedDateTime | string | Optional | The payment start time (yyyy-MM-dd HH:mm:ss). |
StartedDateTimeMs | long | Optional | The payment start time (Unix epoch, in milliseconds). |
StoreTransactionId | string | Optional | The Steam store transaction ID (transid). It may differ from the order ID. |
AxylReceipt | string | Optional | The sealed receipt that the server issues for tamper verification. For Steam, this value is always returned, so use it as is for axylReceipt in the receipt information you pass to the app server and for AxylReceipt in the purchase finalization request. |
Response example
// Example of success.Data in the Success branch
// success.Data.Restores[0].OrderId = "1000000012345"
// success.Data.Restores[0].ProductId = "com.example.gem.100"
// success.Data.Restores[0].ProviderId = RestorePurchaseProviderId.Steam
// success.Data.Restores[0].Price = 9900.0
// success.Data.Restores[0].Currency = "KRW"
// success.Data.Restores[0].Quantity = 1
// success.Data.Restores[0].PurchaseDateTime = 1717200000000
// success.Data.Restores[0].StoreTransactionId = "421799706624185538"
Response status
The following table summarizes the success result of PaymentsRestorePurchasesResult and the domain-specific results (Outcome) defined by this method. For the result model and handling principles of common failures (Failure) that prevent the request from being performed, see Common error handling.
| Response case | Description | App client handling |
|---|---|---|
Success | The list of restorable purchases was returned. | Pass the AxylReceipt of each purchase to the app server, proceed with receipt verification, and then deliver the product |
PaymentBadRequest | The request cannot be processed. | Check the request values and call conditions |
PaymentInvalidParameter | Invalid parameter (for example, a required value is missing). | Check and fix the required field values |
PaymentResourceNotFound | The payment information cannot be found. | Check the receipt, order number, and payment status |
UnknownOutcome | A domain-specific result that the SDK does not recognize. | Treat it as a failure and log the result code |
Failure | Common Failure. See Common error handling. | Handle it according to the common error handling guidelines |
2. Verify receipts and deliver products
Repeat the steps below with the reacquired receipt, AxylReceipt. A restored purchase is an order whose Steam authorization has already been confirmed, so start from the receipt information preparation step.
- Prepare the receipt information and pass it to the app server. Set
requestTypeof the receipt verification request that the app server sends to2(purchase restoration). - The app server verifies the receipt with the Hive Axyl Server API.
- When verification is complete, deliver the product and finalize the purchase.