跳至主要内容

Unity

Integrate the Aghanim to start accepting payments for your game items online through a prebuilt checkout page. The Checkout with Unity uses our Unity SDK. For it to work properly, you need:

  • Unity 2022.3.62f2 LTS or later.
  • Android Min API Level 24.
  • EDM4U Min 1.2.184.
  • Gradle 8.11.1 and AGP 8.10.0 with the com.android.tools.build:gradle classpath.
  • Build tools 35.0.0 or higher.
  • JDK version 17.
  • NewtonJson 3.2.1 or higher.
Android. Default browser
Android. Default browser

Android. Default browser

Register with Aghanim and link your game

First, register for an Aghanim account. At the end of registration, add the link to your mobile game. It should be published in Apple App Store or Google Play Store.

Set up environment

If you want to make real payments, you are all set as the live mode is used as default. Otherwise, use a sandbox, an isolated test environment, to simulate the Aghanim events to test payments without real money movement. To turn on the sandbox mode, set the Sandbox toggle to the active position.

While integrating, you will need an SDK key to authenticate requests to the Aghanim. Keep in mind that the sandbox and live modes have different keys. Find the SDK key in Integration → API keys.

Configure game client-side

Configure your game client to work with the Checkout by setting up the SDK and implementing the necessary code to process its methods.

Add SDK scoped registries

Additionally to the Aghanim resources, the SDK uses EDM (External Dependency Manager) for Unity to update and resolve Android (Gradle and Maven) и iOS (CocoaPods) dependencies. Add the registries to Unity settings so it will know where to find their dependencies.

In the Unity Editor:

  1. Select Edit → Project Settings.
  2. Go to Package Manager.
  3. Expand the Scoped Registries pane.
  4. Add the Aghanim registry:
    1. In the pane for a scoped registry name, click +.
    2. Copy and paste the registry details:
      • For the Name filed, use Aghanim Registry.
      • For the URL filed, use https://us-central1-npm.pkg.dev/ag-registry/aghanim.
      • For the Scopes filed, use com.aghanim.
    3. Click Save.
  5. Add the EDM registry:
    1. In the pane for a scoped registry name, click +.
    2. Copy and paste the registry details:
      • For the Name filed, use package.openupm.com.
      • For the URL filed, use https://package.openupm.com.
      • For the Scopes filed, use com.google.external-dependency-manager.
    3. Click Save.

Set Android Minimum API Level

To comply with the SDK software requirements, set Android Minimum API Level 24.

In the Unity Editor:

  1. Select Edit → Project Settings.
  2. Go to Player.
  3. Click the Android settings tab.
  4. Expand the Other Settings pane.
  5. Scroll to the Identification group.
  6. In the Minimum API Level field, select API level 24.

Enable Custom Gradle templates

On Android, Unity handles the project builds by Gradle. To give the SDK full access to Gradle builds, enable some templates to customize the Gradle configuration.

In the Unity Editor:

  1. Select Edit → Project Settings.
  2. Go to Player.
  3. Click the Android settings tab.
  4. Expand the Publishing settings pane.
  5. Scroll to the Build group.
  6. Select the checkboxes:
    • Custom Main Gradle Template.
    • Custom Base Gradle Template.
    • Custom Gradle Properties Template.

Install SDK

Additionally to the Aghanim resources, the SDK uses EDM (External Dependency Manager) for Unity to update and resolve Android (Gradle and Maven) и iOS (CocoaPods) dependencies. Add the registries to Unity settings so it will know where to find their dependencies.

In the Unity Editor:

  1. Select Window → Package Manager.
  2. In the window, select + → Add package by name.
  3. Copy and paste the SDK details:
    • For the Name filed, use com.aghanim.sdk.
    • For the Version field, use 1.11.0.
  4. Click Add.
  5. Wait for the Aghanim SDK and EDM to be installed.
  6. Close the window.

For Android, to verify that the SDK is installed in the Unity Editor:

  1. Select Assets → External Dependency Manager → Android Resolver → Force Resolve.
  2. Get the Android Dependencies window with the Resolution Succeeded message.
  3. Close the window.

Configure EDM

To let EDM declare dependencies in the mainTemplate.gradle file rather than download dependency artifacts into the Unity project, configure EDM in the Unity Editor:

  1. Select Assets → External Dependency Manager → Android Resolver → Settings.
  2. In the window:
    1. Clear the Enable Auto-Resolution checkbox.
    2. Select the Patch mainTemplate.gradle checkbox.
    3. Click OK.

Configure SDK API key

All project settings are stored in the Unity configuration file that the SDK has generated. To let Unity authenticate the SDK methods from your project, add the SDK key to this file:

  1. Copy the SDK key from Integration → API keys.
  2. In the Inspector, open the Assets/Aghanim/Configs/Aghanim Settings.asset file.
  3. In the Sdk Api Key field, paste the SDK key.

Initialize SDK

To use the SDK, initialize it once in the lifetime of the game process.

using Aghanim;

private void Awake()
{
Aghanim.Initialize();
}

OptionalAdjust Logger

With the SDK, you can read its logs from one of the supported levels. The SDK writes all log messages into Android logcat, iOS Xcode console, and Unity Editor → Unity Console, the default tools for logging.

The simple usage of the SDK log messages means setting the log level you are interested in the most:

  • DEBUG — detailed debug information on almost every event.
  • INFO — general information on the SDK instance state and its events.
  • WARNING — warnings and recoverable errors.
  • ERROR — critical and fatal errors.
  • NONE — no logging. Used by default.
using Aghanim;

private void Awake()
{
Aghanim.Initialize(minLogLevel: AghanimLogLevel.DEBUG);
}

Configure player ID

Since a mobile game has one instance per device, the SDK allows to set the player ID once to use it in all following method calls.

When your game client has the player ID, set it for the current SDK instance.

Aghanim.SetPlayerId(playerId);

Create item

The integration needs the items to be added to the Dashboard. When creating items, each should have its SKU, a unique identifier for the item within your game backend. You can add their prices, currency, sale configuration, and more.

To add an item to the Dashboard:

  1. Go to SKU Management → Items.
  2. Click Add Item. The site will open the Add Item page.
  3. Enter the item name New item.
  4. Enter the item SKU items.new.ba68a028-2d51-46b4-a854-68fc16af328a.
  5. In the Price block:
    1. Select the Fiat price type for a real money item.
    2. Enter the price 1.99.
  6. Click Add item.

For integration purposes, we have shortened an item setup. Before going live, use every suitable feature while adding items to the Dashboard.

Get items with localized prices

The SDK retrieves items created in the Dashboard with localized prices based on the player's region. Use this to display accurate prices in your in-game store before the player proceeds to checkout.

Aghanim.GetItems(
skus: new List<string> { "items.new.ba68a028-2d51-46b4-a854-68fc16af328a" },
onSuccess: (items) =>
{
foreach (var item in items)
{
// Use item.Name, item.Price.Display, item.ImageUrl to populate your store
Debug.Log($"{item.Name}: {item.Price.Display}");
}
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to get items: {error}");
// TODO: Handle error
}
);

Create Checkout item

It is time to create a variable that represents the items to be purchased.

var items = new List<CheckoutItem>
{
new CheckoutItem("items.new.ba68a028-2d51-46b4-a854-68fc16af328a")
};

As the SDK launches the Checkout in the browser, the player needs to be back to your app once they complete the payment. To return the player to, the SDK needs you to specify deep links for the app.

With Android App Links and iOS Universal Links, the player goes directly to the app without any additional clicks. Links use standard HTTPS URLs and the operating system verifies their domain. It makes this approach secure and more suitable for the production environment. We recommend to use it for better players’ experience.

Let’s configure App Links first. Create a variable for the deep link URL. We will use it later.

string backToGameUrl = "https://<YOUR_DOMAIN>/checkout-complete";

The Android SDK can trust the deep links and their domain only when the domain is hosted on a server. The server should have the assetlinks.json file containing this domain information. Host the file at https://<YOUR_DOMAIN>/.well-known/assetlinks.json. The file acts as a bridge to verify the authenticity of the links’ domain and your app by the Android SDK.

[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.<YOUR_COMPANY>.<YOUR_APP>",
"sha256_cert_fingerprints": ["<YOUR_APP_FINGERPRINT>"]
}
}]

The Android SDK needs to know that the deep links lead to your app. To create this connection, add an intent filter in the manifest.

<activity android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<!-- URL parts from backToGameUrl -->
<data
android:scheme="https"
android:host="<YOUR_DOMAIN>"
android:pathPrefix="/checkout"
/>
</intent-filter>
</activity>

Since Unity has the intent filter configuration, no need to handle the deep link in the Activity.

Now, it is Universal Links turn. Since they are iOS mechanism, you need Xcode to enable iOS capability to process Universal Links for your app. You can do it directly in the Unity project:

  1. Open Project Settings → Player.
  2. From the iOS tab, go to Other Settings → Capabilities.
  3. Select the Associated Domains checkbox.
  4. In the domain adding field, copy and paste applinks:<YOUR_DOMAIN>.

iOS has the same requirements to trust the deep links and their domain, just needs a different file. Host the apple-app-site-association file at https://<YOUR_DOMAIN>/.well-known/apple-app-site-association as well.

{
"applinks": {
"apps": [],
"details": [{
"appID": "TEAMID.com.<YOUR_COMPANY>.<YOUR_GAME>",
"paths": ["/checkout*"]
}]
}
}

Create Checkout params

When all data variables are ready, create another one that represents Checkout params. Checkout params are the programmatic representation of what the player sees when they are on the payment form. Checkout params are associated with a player and items, they are crucial for the Checkout to work. You can use the existing player from your game or create them at runtime. At this point, you should have the Price template ID.

Creating Checkout params is simpler for the Default launch mode. Since the Checkout doesn’t use a browser to launch, no need to pass backToGameUrl.

var checkoutParams = new CheckoutParams(
items: items,
// Optional. Custom message in Checkout UI
customMessage: "Holiday Sale!",
// Optional. Locale for texts’ localization. Default is system locale
locale: Locale.en
);

OptionalUse metadata

You can attach custom metadata to the Checkout for item tracking purposes. You can access it through webhooks and in API responses from the Aghanim. Metadata has a structure of “key-value” pairs.

var metadata = new Dictionary<string, string>
{
{ "campaign", "winter_sale" },
{ "source", "mobile_app" },
{ "user_segment", "premium" },
{ "ab_test_variant", "variant_a" },
{ "player_level", "42" }
};

var checkoutParams = new CheckoutParams(
items: items,
backToGameUrl: backToGameUrl,
metadata: metadata
);

OptionalSet post-payment redirect behavior

You can choose the behavior of redirecting the player after they have completed the payment successfully. The difference in the provided by the SDK modes is a delay before redirecting or absence of redirecting.

When the player has completed the payment, the SDK redirects them immediately to the deep link from backToGameUrl.

using Aghanim.Scripts.Models.Orders;

var redirectSettings = new RedirectSettings(
mode: RedirectMode.Immediate
);

var checkoutParams = new CheckoutParams(
items: items,
backToGameUrl: backToGameUrl,
redirectSettings: redirectSettings
);

OptionalSet checkout appearance

You can set the appearance mode for the Checkout UI. The SDK supports automatic detection based on the system setting, or you can force a specific mode.

The SDK automatically detects and applies the appropriate appearance mode based on the system setting.

var uiSettings = new UiSettings(
mode: UiMode.Auto
);

var checkoutParams = new CheckoutParams(
items: items,
uiSettings: uiSettings
);

Launch Checkout

Add a checkout button to your game client that launches the payment form. The SDK creates an order from the provided checkout params and opens the Checkout UI. On success, you receive the Order ID to track the order. On failure, you receive an error with debug information for troubleshooting.

For Android and iOS, the Default browser launch mode works in the player default browser. Use the mode when you want to redirect the player outside your app.

Aghanim.StartCheckout(
checkoutParams,
LaunchMode.DefaultBrowser,
onSuccess: (orderId) =>
{
// Order is created and checkout has launched successfully
// TODO: Save order ID for further granting or tracking
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to launch Checkout: {error}");
// TODO: Show user-friendly error message to player
}
);

Check unconsumed Orders

After the Checkout page has launched and the Order ID is ready, the player can leave the page and come back, and pay for the items in the Order or not pay for them. The main goal of the Checkout launch result is to tell whether the player has opened it successfully, closed it, or the launch has failed. So after, you need to know which Orders have been paid for and should be granted to the player. The SDK has functionality to get the list of the player paid Orders. When you know their IDs, you should mark them as consumed and grant to the player.

Aghanim.GetUnconsumedOrders(
onSuccess: (response) =>
{
// Player has paid but not granted items from orders
var unconsumedOrderIds = response.Orders;
// TODO: Save order IDs for further consuming and granting
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Payment failed: {error.debugMessage}");
// TODO: Handle error
}
);

Consume paid Orders

When you know the Order IDs that the player has paid for, you should mark them as consumed and grant to the player withing your game logic.

Aghanim.ConsumeOrder(
orderId: orderId,
onSuccess: (response) =>
{
// Paid orders are marked as consumed
Debug.LogError($"Payment failed: {$orderId}");
// TODO: Grant items in order to player
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Payment failed: {error.debugMessage}");
// TODO: Handle error
}
);

Make payment

Make a payment. If you have set the sandbox mode, use the test card below. In the sandbox, you can make payments only with the test cards. They accept any digits as CVV and any future date as expiry date. Don’t forget to fill in an email address to check the receipt is sent and any postal code as a billing address.

Successful payments

After you complete the payment, you will receive a receipt sent to the specified email address and a transaction record in Aghanim Dashboard → Transactions.

Card BrandCard NumberCVVExpiry dateCountry
VISA (credit)
4242 4242 4242 4242
Any 3 digitsAny future dateGB

Unsuccessful payments

Make unsuccessful payment just in case you are curious. You will see the transaction in Aghanim Dashboard → Transactions as well.

NumberCVVExpiry dateResponse codeDescription
4832 2850 6160 9015
Any 3 digitsAny future date16Payment declined

OptionalAll payment methods

For the live mode, you can find all supported payment methods in Company settings → Payment methods. Turn on or off those you see suitable. Some payment methods are available globally by default. You can’t disable Credit cards, Apple Pay, Google Pay, and PayPal.

In Checkout, the Aghanim evaluates the currency and any restrictions, then dynamically presents only the payment methods available to the player based on evaluation.

OptionalSaving payment method

When you use the live mode, the payment form shows to the player a setting to save their payment method so they can make a one-click payment in the future.

Handle post-payment events on game server-side

To complete the Checkout, handle items’ granting and chargebacks on your game backend. To do so, implement a webhook system that accepts the item.add and item.remove webhooks. See the code example with the implementation.

Comply with the Aghanim requirements for these webhooks:

  • Use HTTPS schema for the single POST webhook endpoint.
  • Check that webhooks are generated and signed by the Aghanim.
  • Handle the idempotency_key field in the webhook payload to prevent processing duplicate webhooks.
  • Respond with the HTTP status codes:
    • 2xx for successfully processed webhooks.
    • 4xx and 5xx for errors.

Grant items to player

The Aghanim sends the item.add webhook to let you know about the purchased items and ask for your permission to grant them to the player.

When the Aghanim has your 2xx answer, it can complete the checkout logic and redirect the player to a deep link if provided.

Support refunds and chargebacks

The Aghanim sends the item.remove webhook when a bank or payment system reverses the transaction, or you have requested refund in Aghanim Dashboard → Transactions. Partial refunds are not supported.

OptionalUse suggested implementation

The suggested implementation handles the webhooks mentioned before:

  • item.add for granting items. You need it for integration.
  • item.remove for refunds and chargebacks. You might need it for integration.
# 使用以下示例代码来处理您集成环境中的 Webhook 事件。
#
# 1. 将此代码复制到新创建的 `server.py` 文件中。
#
# 2. 安装必要的依赖项:
# python -m pip install fastapi[all]
#
# 3. 在 http://localhost:8000 地址上运行服务器
# python server.py

import fastapi, hashlib, hmac, json, typing

app = fastapi.FastAPI()

@app.post("/webhook")
async def webhook(request: fastapi.Request) -> dict[str, typing.Any]:
secret_key = "<YOUR_S2S_KEY>" # 请替换为您的实际 Webhook Secret Key

raw_payload = await request.body()
payload = raw_payload.decode()
timestamp = request.headers["x-aghanim-signature-timestamp"]
received_signature = request.headers["x-aghanim-signature"]

if not verify_signature(secret_key, payload, timestamp, received_signature):
raise fastapi.HTTPException(status_code=403, detail="Invalid signature")

data = json.loads(payload)
event_type = data["event_type"]
event_data = data["event_data"]

if event_type == "item.add":
add_item(event_data)
return {"status": "ok"}

if event_type == "item.remove":
remove_item(event_data)
return {"status": "ok"}

raise fastapi.HTTPException(status_code=400, detail="Unknown event type")

def verify_signature(secret_key: str, payload: str, timestamp: str, received_signature: str) -> bool:
signature_data = f"{timestamp}.{payload}"
computed_hash = hmac.new(secret_key.encode(), signature_data.encode(), hashlib.sha256)
computed_signature = computed_hash.hexdigest()
return hmac.compare_digest(computed_signature, received_signature)

def add_item(event_data: dict[str, typing.Any]) -> None:
# 用于处理事件和添加商品的示例占位代码。
# 在实际应用中,此函数将与您的数据库或库存管理系统进行交互。
player_id = event_data["player_id"]
for item in event_data["items"]:
sku = event_data["sku"]
print(f"Item {sku} have been credited to player's {player_id} account.")

def remove_item(event_data: dict[str, typing.Any]) -> None:
# 用于处理事件和移除商品的示例占位代码。
# 在实际应用中,此函数将与您的数据库或库存管理系统进行交互。
player_id = event_data["player_id"]
for item in event_data["items"]:
sku = event_data["sku"]
print(f"Item {sku} have been removed from player's {player_id} account.")

if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)

Add webhook endpoint to Aghanim

When the webhook handling is ready, add the endpoint to the account so the Aghanim could start sending the events.

  1. Go to Integration → Webhooks.
  2. Click New Webhook. The site will open the Create new webhook window.
  3. Cope and paste the URL https://<YOUR_DOMAIN>/webhook.
  4. Click Select events. The site will open the Select events to send window.
  5. Expand the Main class and select the Item add, Item remove checkboxes.
  6. Click Apply.
  7. Click Add. The site will redirect you to the webhook page.
  8. Click Back.

Test your integration

After you have handled the webhooks, check that the purchased items are in your inventory. That’s all.

Next steps

Troubleshooting

Failed to initialize Aghanim Checkout

Verify that the specified SDK key is correct.

Having dependency issues

  1. Make sure the External Dependency Manager is installed.
  2. Check if all dependencies are resolved in the CheckoutSdkDependencies.xml file.
  1. Verify that the deep link scheme for your app is properly configured in Android Manifest.
  2. Check that the deep link handler is set up in Unity build settings.

FAQ

What platforms does your Unity SDK support?

The Unity SDK is available for both iOS and Android.

需要技术支持?
联系我们的集成技术团队: integration@aghanim.com