Skip to content

Step 3. Purchase a product

Create the payment page URL for the product the user selected, and proceed with the payment in an external browser. After the user returns to the app, retrieve undelivered orders to check the payment result and receipt data.

Follow the steps below to purchase a PG product.

1. Display the in-app store UI

Implement the in-app store UI in the app and display it to users. When a user chooses a product, let them select the payment button. When the user selects the payment button, proceed to the next step.

2. Optional: Save pre-purchase information

After the user selects the payment button and before the payment page opens, save the purchase attempt information. For the full flow, see Record purchase information. This step is optional.

Method

CreatePrePurchaseAsync

CreatePrePurchaseAsync() saves the product, expected payment amount, currency, country and language, app server, and IapPayload as a pre-purchase tracking record.

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.

PrePurchase

Field name Type Required Description
Country string Required Country code (two-letter ISO 3166-1 code)
Currency string Required Payment currency (three-letter ISO 4217 code)
Language string Required Language code (two-letter ISO 639-1 code)
Price decimal Required The expected payment amount. It may include decimals depending on the currency.
ProductId string Required In-app product ID registered in the market
ProviderId PrePurchaseProviderId Required The market and payment method identifier (enum). Because this request is for PG payments only, specify only Pg.
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
AccountUuid string Optional A UUIDv5 value generated from the logged-in user's playerId. Pass it before you start the payment. See Generate an AccountUuid.
IapPayload string Optional The 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.

IapPayload usage example

With IapPayload in PrePurchase, you can include app-specific data in the receipt that is issued after the purchase is completed. The following is one example of using IapPayload.

For example, suppose that in a mobile app with three user profiles, A, B, and C, a user purchases an in-app product with profile A. If you request the purchase with a JSON string such as {"character": "A"} in IapPayload, this value is included in the purchase receipt and passed to the app when the payment completes successfully.

If the payment is completed but the product cannot be delivered because of a network error, you must retrieve the failed delivery, verify its receipt again, and then deliver the product. At this point, you need to know which of the user's profiles A, B, and C should receive the product. With the {"character": "A"} information in the IapPayload included in the purchase receipt, you can confirm that profile A is the delivery target and deliver the product accurately.

This is only one example. You can put information that your app needs, such as the product purchase time and purchasing user information, in IapPayload and attach it to the purchase receipt. Use it to fit your app's situation.

Call example

Check the success result of PaymentsCreatePrePurchaseResult 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 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 selects the payment button
var request = new PrePurchase
{
    Country = "KR",
    Currency = "KRW",
    Language = "ko",
    Price = 1200.0m,
    ProductId = "com.game.item.gold_100",
    ProviderId = PrePurchaseProviderId.Pg,
    ServerId = "server01",
    RequestDate = DateTimeOffset.UtcNow
};

PaymentsCreatePrePurchaseResult result = await payments.CreatePrePurchaseAsync(request);

switch (result)
{
    case PaymentsCreatePrePurchaseResult.Success success:
        // Pre-purchase information saved. No data is returned. Proceed to create the payment page URL.
        break;

    // Request value problem — check the 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, move to the payment page URL creation step without any returned 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-purchase information saved Proceed to create the payment page URL
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 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. Create the payment page URL

Create a payment page URL that the user can access based on the order information. When you open the created URL in an external browser, the payment method selection page provided by Hive Axyl appears.

On this page, the user selects the actual PG payment method and proceeds with the payment.

Method

CreatePaymentUrlAsync

To implement payment page URL creation, call CreatePaymentUrlAsync() provided by the Hive Axyl SDK. It creates and returns a payment page URL that the user can access based on the order information.

Call parameters

Field name Type Required Description
request OrderRequest Required The order (payment page creation) request data.
context ApiCallContext Optional Per-call settings object that specifies the idempotency key, cancellation token, and request policy. If omitted, the default values are used.

OrderRequest

Field name Type Required Description
AppVersion string Optional The app version.
Country string Required The country code (two-letter ISO 3166-1 code).
Language string Required The language code (two-letter ISO 639-1 code). It is used to display payment method names in multiple languages.
Os OrderRequestOs (enum) Required The OS on which the app client is running. Specify the value that matches the build target among Windows, Macos, Android, and Ios.
ProductId string Required The in-app product PID registered in the market.
Quantity int Required The purchase quantity. You can specify a value from 1 to 999.
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.
ProviderId OrderRequestProviderId Required The payment provider. Because this request is for PG payments only, specify only Pg.
CustomPrice string Optional A custom payment amount. Use it to request a payment with an amount that the app server specifies instead of the amount set for the product PID. You must use it together with FixedCurrency and GameServerPriceVerifyKey.
FixedCurrency string Optional The currency to display for the payment method (three-letter ISO 4217 code). Required when you use custom amount (CustomPrice) payments.
GameServerPriceVerifyKey string Optional The key for verifying the payment amount on the app server. The app server issues it to prevent tampering with the amount in custom amount payments, and it is required when you use CustomPrice.
IapPayload string Optional Developer-defined metadata to pass to the app server (JSON string). It is passed as is to the app server callback after the purchase is completed.

Call example

Check the success result of PaymentsCreatePaymentUrlResult 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 OrderRequest
{
    AppVersion = "1.0.0",
    Country = "KR",
    Language = "ko",
    Os = OrderRequestOs.Android,
    ProductId = "com.example.game.gold100",
    Quantity = 1,
    ServerId = "server01",
    ProviderId = OrderRequestProviderId.Pg
};

PaymentsCreatePaymentUrlResult result = await payments.CreatePaymentUrlAsync(request);

switch (result)
{
    case PaymentsCreatePaymentUrlResult.Success success:
        // Payment page URL created. Open PayUrl to display the payment page
        Debug.Log($"payUrl: {success.Data.PayUrl}");
        break;

    case PaymentsCreatePaymentUrlResult.PaymentBadRequest:
    case PaymentsCreatePaymentUrlResult.PaymentInvalidParameter:
        Debug.LogError("Check the request fields and required values.");
        break;

    // Handle common Failure
    case PaymentsCreatePaymentUrlResult.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 (OrderPayUrlResponseData) of PaymentsCreatePaymentUrlResult.Success.

Field name Type Required Description
Data.PayUrl string Optional The payment page URL.
Data.CreatedAt DateTimeOffset Optional The creation date and time.
Data.Meta string? Optional Response meta information.

Response example

// Example of success.Data in the Success branch
// success.Data.PayUrl = "https://payment-gateway.com/order?data=eymadfaqewerqwreasdf"
// success.Data.CreatedAt = 2024-06-01T12:00:00Z

Response status

The following table summarizes the success result of PaymentsCreatePaymentUrlResult 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 page URL was created. Open Data.PayUrl to display the payment page to the user
PaymentBadRequest The request cannot be processed. Check the request values and call conditions
PaymentInvalidParameter Invalid parameter. Check the request fields and send the request again
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

4. Proceed with the payment

Open the created payment page URL in an external browser so that the user can pay. On this page, the user selects a payment method, such as a credit card or micropayment, and then completes the PG payment.

Because PG payments proceed in an external browser, the app is not notified right away that the payment is complete, unlike store payments. When the user finishes the payment and returns to the app, display a UI that indicates the purchase is complete, retrieve undelivered orders, and then request receipt verification from the app server to check the payment result.

5. Optional: Save payment result data

After the user finishes the payment and returns to the app, save the receipt and transaction information that you checked with Get completed payment information. Because this keeps a record of the payment before receipt verification, you can use it for verification, product delivery, customer support, and settlement even if later processing is interrupted. For the full flow, see Record purchase information. This step is optional.

Method

RecordStorePurchaseAsync

RecordStorePurchaseAsync() saves the payment result, such as the receipt and transaction ID, to the Hive Axyl server.

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.

PurchaseRequest

Field name Type Required Description
AccountUuid string Optional A UUIDv5 value generated from the logged-in user's playerId. Pass it when you record the payment result. If you passed it at the payment start step, use the same value. See Generate an AccountUuid.
AxylReceipt string Required The sealed receipt issued by the Hive Axyl server. Pass the AxylReceipt returned by Get completed payment information exactly as is.
Country string Required The country code (two-letter ISO 3166-1 code). Example: KR
Currency string Optional The payment currency (three-letter ISO 4217 code). Paired with Price, it is compared with the values that 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 The payload (JSON string) that the developer attached to the market payment. It is passed as is to app server verification and to the purchase completion callback.
Language string Required The language code (two-letter ISO 639-1 code). Example: ko
OrderId string Optional The Hive Axyl internal order number.
Price decimal Optional The payment amount. It may include decimals depending on the currency. If you send it, the server compares it with the amount it recorded. If you omit it, no comparison is made. For PG payments, the request is rejected if the amounts differ. The amount recorded in the payment history is the value in the order information that the server stores.
ProductId string Required The in-app product ID registered in the market. Because PG payments are processed based on the order information stored on the server, this value is not used for comparison.
ProjectInfo string Optional An app-specific free-form JSON string. 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 Because this request is only for saving PG payment results, specify Pg.
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 following Hive Console App Server.
StoreTransactionId string Optional The PG store transaction ID.

Call example

Check the success result of PaymentsRecordStorePurchaseResult 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 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>();

// After checking the payment result with the undelivered order query, create the request object with the retrieved receipt
var request = new PurchaseRequest
{
    AxylReceipt = axylReceipt, // Sealed receipt returned by the undelivered order query
    ProviderId = PurchaseRequestProviderId.Pg,
    ProductId = "com.game.item.gold_100",
    Price = 1200.0m,
    Currency = "KRW",
    Country = "KR",
    Language = "ko",
    Quantity = 1,
    StoreTransactionId = "imp_448280090638",
    RequestType = 1, // 1: new purchase
    RequestDate = DateTimeOffset.UtcNow,
    ServerId = "server01"
};

PaymentsRecordStorePurchaseResult result = await payments.RecordStorePurchaseAsync(request);

switch (result)
{
    case PaymentsRecordStorePurchaseResult.Success success:
        // Saved successfully. 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, the result is contained in Data (PurchaseResponseData) of PaymentsRecordStorePurchaseResult.Success.

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 Pass the receipt information 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 request fields such as AxylReceipt
PaymentResourceNotFound The payment information to save cannot be found. Check the receipt and transaction information
PaymentUnauthorized You do not have 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 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

Next steps

Proceed to Step 4. Verify receipts.