Skip to content

Record purchase information

For consumable product payments, record the purchase attempt information before opening the store payment window, and record the receipt and transaction information after the payment is completed. Based on these two records, receipt verification and product delivery are processed as the same purchase. For subscription products, follow the procedure for saving subscription purchase information in Apple payment and Google payment.

Calling the store payment window, receipt verification, and product delivery are handled in the payment flow of each payment provider. The app server requests receipt verification by calling the Hive Axyl Server API with the receipt that the app client passed. For the roles of the payment confirmation request and delivery result recording, see Confirm payments and record delivery results.

Processing order

1. Save purchase attempt information before payment

CreatePrePurchaseAsync() saves the product the user selected, the expected payment amount, the currency, the country and language, the app server, and IapPayload as a pre-purchase tracking record. Call it right before opening the store payment window.

Method

CreatePrePurchaseAsync

Call parameters

Field name Type Required Description
request PrePurchase Required The request data object for saving pre-purchase information.
context ApiCallContext Optional Per-call settings object that specifies the idempotency key, cancellation token, and request policy. If omitted, the default values are used.

The PrePurchase request data is as follows.

Field name Type Required Description
Country string Required Country code (ISO 3166-1, two letters)
Currency string Required Payment currency (ISO 4217, three letters)
Language string Required Language code (ISO 639-1, two letters)
Price decimal Required The expected payment amount. Depending on the currency, it may include decimals.
ProductId string Required In-app product ID registered in the market
ProviderId PrePurchaseProviderId Required Market and payment method identifier (enum). Members: Apple (Apple App Store), Google (Google Play), Steam (Steam), Pg (web payment PG: PortOne, MyCard, and Xsolla)
ServerId string Optional Server ID that you check on the App Server tab after you register the app server in App Info > App Server by referring to Hive Console app server
AccountUuid string Optional The UUIDv5 value generated from the logged-in user's playerId. Pass it before opening the store payment window. See Generate an AccountUuid.
IapPayload string Optional Payload (JSON string) that the developer attaches to the market payment. It is passed as is to the app server callback after the purchase is completed.
RequestDate DateTimeOffset Optional The request time (UTC). If omitted, the server's current time is used.

Call example

Check the success result of PaymentsCreatePrePurchaseResult and the domain-specific results (Outcome) defined by this method in the following example 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 System;
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>();

// Create the request object with the product information at the time the user selected the payment button
var request = new PrePurchase
{
    Country = "KR",
    Currency = "KRW",
    Language = "ko",
    Price = 1200.0m,
    ProductId = "com.game.item.gold_100",
    ProviderId = PrePurchaseProviderId.Google,
    ServerId = "server01",
    RequestDate = DateTimeOffset.UtcNow,
    AccountUuid = accountUuid // Value that identifies the paying user
};

PaymentsCreatePrePurchaseResult result = await payments.CreatePrePurchaseAsync(request);

switch (result)
{
    case PaymentsCreatePrePurchaseResult.Success success:
        // Pre-save succeeded. No data is returned. Proceed to open the store payment window.
        break;

    // Problem with request values — check required values and formats
    case PaymentsCreatePrePurchaseResult.PaymentBadRequest:
    case PaymentsCreatePrePurchaseResult.PaymentInvalidParameter:
        Debug.LogError("Check the request parameters.");
        break;

    case PaymentsCreatePrePurchaseResult.UnknownOutcome unknownOutcome:
        Debug.LogWarning($"Unknown result: {unknownOutcome.Code}");
        break;

    // Handle common Failure
    case PaymentsCreatePrePurchaseResult.Failure failure:
        HiveError err = failure.Problem;
        Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
        break;

    // Safety net: unhandled results
    default:
        Debug.LogWarning($"Unhandled result: {result.GetType().Name}");
        break;
}

Response data

No data is returned on success.

Response example

// In the Success branch, proceed to the next payment step without any data.

Response status

The following table summarizes the success result of PaymentsCreatePrePurchaseResult 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. No data is returned on success.

Response case Description App client handling
Success Pre-save succeeded Proceed to open the store payment window
PaymentBadRequest The payment request cannot be processed. Check the request values and call conditions
PaymentInvalidParameter The payment request parameters are invalid. Check the request field values
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. Save store payment results

RecordStorePurchaseAsync() saves the payment result, such as the receipt and transaction ID, right after the store payment is completed. Because it records the original fact of payment before receipt verification, you can use it as the basis for verification, product delivery, customer support, and settlement even if a later step is interrupted.

Method

RecordStorePurchaseAsync

Call parameters

Field name Type Required Description
request PurchaseRequest Required The request data object for saving the payment result.
context ApiCallContext Optional Per-call settings object that specifies the idempotency key, cancellation token, and request policy. If omitted, the default values are used.

The PurchaseRequest request data is as follows.

Field name Type Required Description
AccountUuid string Optional The UUIDv5 value generated from the logged-in user's playerId. Pass it to the purchase result record after the store payment is finished. If you passed it at the payment start step, use the same value. See Generate an AccountUuid.
AxylReceipt string Required The market receipt. For Apple, pass the JWS; for Google, the purchase token (purchaseToken); and for Steam and PG, the sealed receipt issued by the Hive Axyl server.
Country string Required The country code (ISO 3166-1, two letters).
Currency string Optional The payment currency (ISO 4217, three letters). Paired with Price, it is used to compare against the value the server recorded. If you send only one of the two, the currency is not compared and only the amount is compared.
IapPayload string Optional Payload (JSON string) that the developer attached to the market payment. It is passed as is to app server verification and the purchase completion callback.
Language string Required The language code (ISO 639-1, two letters).
OrderId string Optional The Hive Axyl internal order number. Used for Steam/PG.
Price decimal Optional The payment amount. Depending on the currency, it may include decimals. If you send it, the server compares it with the recorded amount; if you omit it, no comparison is made. For Apple, Steam, and PG payments, the request is rejected if the amounts differ; for Google payments, the amount is only recorded. The amount kept in the payment history is the value the server confirmed.
ProductId string Required The in-app product ID registered in the market.
ProjectInfo string Optional A free-form JSON string for each app. The value is only stored and is not passed to the app server. Set values to pass to the app server in IapPayload.
ProviderId PurchaseRequestProviderId Required The market and payment method identifier.
Quantity int Optional Purchase quantity
RequestDate DateTimeOffset Optional The client request time (UTC). If omitted, the server's current time is used.
RequestType int Optional The request type. 1: new purchase, 2: purchase restoration
ServerId string Optional The app server ID registered by referring to Hive Console app server.
StoreTransactionId string Optional The store transaction ID on the market side.

Call example

Check the success result of PaymentsRecordStorePurchaseResult and the domain-specific results (Outcome) defined by this method in the following example 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 System;
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>();

// Right after the store payment is completed, create the request object with the receipt issued by the market
var request = new PurchaseRequest
{
    AxylReceipt = purchaseToken, // Google: purchase token
    ProviderId = PurchaseRequestProviderId.Google,
    ProductId = "com.game.item.gold_100",
    Price = 1200.0m,
    Currency = "KRW",
    Country = "KR",
    Language = "ko",
    Quantity = 1,
    StoreTransactionId = "GPA.3389-9543-8198-17604",
    RequestType = 1, // 1: New purchase
    RequestDate = DateTimeOffset.UtcNow,
    ServerId = "server01",
    AccountUuid = accountUuid // Value that identifies the paying user
};

PaymentsRecordStorePurchaseResult result = await payments.RecordStorePurchaseAsync(request);

switch (result)
{
    case PaymentsRecordStorePurchaseResult.Success success:
        // Save succeeded. You can check success.Data.Meta.
        break;

    // Problem with request values or payment status
    case PaymentsRecordStorePurchaseResult.PaymentBadRequest:
    case PaymentsRecordStorePurchaseResult.PaymentInvalidParameter:
    case PaymentsRecordStorePurchaseResult.PaymentResourceNotFound:
    case PaymentsRecordStorePurchaseResult.PaymentUnauthorized:
    case PaymentsRecordStorePurchaseResult.VerifyError:
        Debug.LogError("Check the request values and the payment status.");
        break;

    case PaymentsRecordStorePurchaseResult.UnknownOutcome unknownOutcome:
        Debug.LogWarning($"Unknown result: {unknownOutcome.Code}");
        break;

    // Handle common Failure
    case PaymentsRecordStorePurchaseResult.Failure failure:
        HiveError err = failure.Problem;
        Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
        break;

    // Safety net: unhandled results
    default:
        Debug.LogWarning($"Unhandled result: {result.GetType().Name}");
        break;
}

Response data

On success, Data (PurchaseResponseData) of PaymentsRecordStorePurchaseResult.Success contains the result.

Field name Type Required Description
Data.Meta string Optional Response meta information

Response example

// You can check success.Data.Meta in the Success branch.

Response status

The following table summarizes the success result of PaymentsRecordStorePurchaseResult 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 Payment result saved successfully Pass the receipt to the app server and proceed to the receipt verification step
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 save cannot be found. Check the receipt and transaction information
PaymentUnauthorized There is no permission for the payment request. Check the app and authentication status
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

Next steps

To implement the purchase flow, see Apple App Store payment, Google Play payment, Steam payment, and PG payment.