Step 5. Deliver products
When receipt verification is complete, the app server delivers the product to the user, and the app client finalizes the purchase for the PG payment and then records the delivery result in the Hive Axyl server. The hiveAxylTransactionId that the app client uses in this step is the value that the app server received in the receipt verification response and passed on.
1. Deliver products
After checking the receipt verification result, the app server delivers the product to the user who paid. Your app implements product delivery, and the delivery method can differ from app to app.
Finalize the purchase only after the app server finishes delivering the product. Retrieving undelivered orders finds only orders that are not closed, so if you close an order by finalizing the purchase before delivery, you cannot find that order again when the app stops during delivery.
2. Finalize the purchase
Perform the final purchase finalization for the PG payment. This changes the payment status to completed and updates the related data.
Purchase finalization puts the order in the consumed state. If you skip this step, the paid order remains in the unconsumed state and keeps appearing in the undelivered order results of Restore purchases.
FinalizePurchaseAsync
To implement purchase finalization, call FinalizePurchaseAsync() provided by the Hive Axyl SDK. It performs the final purchase finalization of the PG payment, changes the payment status to completed, and updates the related data.
Call parameters
| Field name | Type | Required | Description |
|---|---|---|---|
| request | PurchaseFinalizeRequest | Required | The request data for purchase finalization. |
| context | ApiCallContext | Optional | Per-call settings object that specifies the idempotency key, cancellation token, and request policy. If omitted, the default values are used. |
PurchaseFinalizeRequest
| Field name | Type | Required | Description |
|---|---|---|---|
AxylReceipt | string | Required | Pass the AxylReceipt of the undelivered order returned by Get completed payment information exactly as is. It is the same value as the sealed receipt that you passed when you requested receipt verification from the app server. The server decrypts this value to find the order to finalize, so if you modify the value, the request is rejected. |
ProviderId | PurchaseFinalizeRequestProviderId | Required | The market identifier. Because this request is for PG purchase finalization only, specify only Pg. |
Call example
Check the success result of PaymentsFinalizePurchaseResult 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 (see the Install the module, initialize, and log in guide)
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();
var request = new PurchaseFinalizeRequest
{
AxylReceipt = axylReceipt, // AxylReceipt returned by the undelivered order query. The same value that was passed when requesting verification from the app server
ProviderId = PurchaseFinalizeRequestProviderId.Pg
};
PaymentsFinalizePurchaseResult result = await payments.FinalizePurchaseAsync(request);
switch (result)
{
case PaymentsFinalizePurchaseResult.Success success:
// Purchase finalized. Check the PG order number and the Axyl transaction number
Debug.Log($"orderId: {success.Data.OrderId}, storeTransactionId: {success.Data.StoreTransactionId}");
break;
case PaymentsFinalizePurchaseResult.PaymentBadRequest:
// The request cannot be processed. Check the request values and call conditions
break;
case PaymentsFinalizePurchaseResult.PaymentInvalidParameter:
// Invalid parameter. Check the request values
break;
// Handle common Failure
case PaymentsFinalizePurchaseResult.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 (PurchaseFinalizeResponseData) of PaymentsFinalizePurchaseResult.Success.
| Field name | Type | Required | Description |
|---|---|---|---|
Data.OrderId | string | Optional | The PG order number. It is a string that starts with H. |
Data.StoreTransactionId | string | Optional | The Hive Axyl transaction number. |
Data.Meta | string? | Optional | Response meta information. |
Response example
Response status
The following table summarizes the success result of PaymentsFinalizePurchaseResult 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 payment status was changed to completed. | Check the order number and transaction ID, and then proceed to the next step |
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 |
3. Save product delivery results
After the app server completes product delivery, record the delivery result, such as success or cancellation, in the Hive Axyl server.
ItemResultAsync
To implement saving delivery results for consumable products, call ItemResultAsync() provided by the Hive Axyl SDK. It records the result in the Hive Axyl server after product delivery is complete. This method does not confirm the payment or decide whether to deliver the product.
- When to call: After the app server completes product delivery
AxylTransactionIdvalue: ThehiveAxylTransactionIdthat the app server received in the receipt verification response and passed on- Cancellation handling: If delivery fails, set a cancellation status value in
Status
Call parameters
| Field name | Type | Required | Description |
|---|---|---|---|
| request | ItemResultBody | Required | The request data object for saving consumable product delivery results. |
| context | ApiCallContext | Optional | Per-call settings object that specifies the idempotency key, cancellation token, and request policy. If omitted, the default values are used. |
ItemResultBody
| Field name | Type | Required | Description |
|---|---|---|---|
AxylTransactionId | string | Required | The Hive Axyl payment transaction ID (the prefix identifies the market). Use the hiveAxylTransactionId value that the app server received in the receipt verification response and passed on. |
Status | int | Required | The delivery result status. 1: delivery succeeded, 2: canceled without reclaiming the product, 3: canceled and the product reclaimed. Any other value is invalid. |
Assets | IReadOnlyList<ItemResultAsset> | Optional | The list of products actually delivered. If there are no items to record, omit this field. |
ProjectPayloadInfo | string | Optional | App-specific free-form JSON data (JSON string) |
ItemResultAsset
| Field name | Type | Required | Description |
|---|---|---|---|
AssetId | string | Optional | Unique ID of the product in the app |
AssetName | string | Optional | Name of the product in the app |
Quantity | int | Optional | The delivered quantity. If specified, it must be 1 or more. |
Call example
Check the success result of PaymentsItemResultResult 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>();
// After product delivery is complete, create the request object with the delivery result
var request = new ItemResultBody
{
AxylTransactionId = axylTransactionId, // hiveAxylTransactionId from the receipt verification response passed by the app server
Status = 1, // 1: Delivery succeeded
Assets = new[]
{
new ItemResultAsset { AssetId = "item_gold_100", AssetName = "골드 100개", Quantity = 1 }
},
ProjectPayloadInfo = "{\"serverId\":\"server01\"}" // (Optional) App-specific free-form JSON data
};
PaymentsItemResultResult result = await payments.ItemResultAsync(request);
switch (result)
{
case PaymentsItemResultResult.Success success:
// Delivery result recorded. You can check success.Data.Meta.
break;
// Request value problem — check the required values, quantity, and status value
case PaymentsItemResultResult.PaymentInvalidParameter:
case PaymentsItemResultResult.PaymentBadRequest:
Debug.LogError("Check the request parameters.");
break;
// Handle common Failure
case PaymentsItemResultResult.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 response meta information is contained in Data (SuccessResponseData) of PaymentsItemResultResult.Success.
| Field name | Type | Required | Description |
|---|---|---|---|
Data.Meta | string? | Optional | Response meta information. |
Response example
Response status
The following table summarizes the success result of PaymentsItemResultResult 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 | Delivery result recorded | Proceed with the next payment processing |
InvalidQuantity | The delivered quantity is invalid. | Check the delivered quantity |
InvalidStatus | The delivery result status value is invalid. | Check the Status value |
PaymentBadRequest | The request cannot be processed. | Check the request values and call conditions |
PaymentInvalidParameter | When a parameter is invalid (for example, AxylTransactionId is missing) | Check the required parameter settings |
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 |
Learn more
If a product could not be delivered during the payment process because of a network error or a similar problem, implement Restore purchases.