Web Payment — Standard Contract (Co-publishing)
| Applies to | Newly onboarded co-publishing games |
| Endpoints | check_uid, create_order, payment_notify |
| Signature | HMAC-SHA256, x-signature + x-timestamp, timestamp in milliseconds |
| Errors | errcode inside a 200 OK body |
This is the contract for newly onboarded co-publishing (co-pub) games — a separate contract from Web Payment — Expub's 4-API flow, not a newer version of it. Which one applies to your game depends on its publishing model (co-pub vs expub), not on when it was integrated.
Two differences matter most if you have seen the expub contract before:
- No character list. There is no
getUserListequivalent. The player types their UID on the top-up screen and Alogame validates it withcheck_uid. You never receive an AlogameuserId. - Errors are carried in the response body, not the HTTP status. Every response is
200 OKwith anerrcodefield. Alogame treatserrcode: 0as success and anything else as failure.
Flow
Steps highlighted in green are implemented by your game server; everything else is handled by Alogame.
Step-by-step breakdown
| # | Who acts | What happens | Your responsibility |
|---|---|---|---|
| 1–2 | User + Alogame | Player enters their in-game UID on the top-up screen | — |
| 3 | Game Server | Alogame calls check_uid with the UID the player typed | Return the character for this UID, or a not-found error |
| 4–6 | Alogame + User | Character name shown for confirmation; player picks package and payment method | — |
| 7 | Alogame Backend | Alogame generates plat_order_num (its own order code) | — |
| 8 | Game Server | Alogame calls create_order | Create a local order record; return your own order_num |
| 9–11 | Alogame + User + Payment Provider | Player pays; provider notifies Alogame via IPN | — |
| 12 | Alogame Backend | Alogame verifies the IPN and marks the order paid | — |
| 13 | Game Server | Alogame calls payment_notify with both order codes | Grant the item; return errcode: 0 |
| 14 | Alogame | Player receives success notification | — |
Authentication
Requests are signed with HMAC-SHA256 over the raw request body and carry x-timestamp and x-signature headers. The algorithm, the raw-body pitfall, and verification samples in PHP, Python and Node.js are on the Authentication page.
Response envelope
All three endpoints answer 200 OK with the same wrapper:
{
"errcode": 0,
"msg": "success",
"data": { }
}
| Field | Type | Description |
|---|---|---|
errcode | integer | 0 = success. Any other value is treated as a failure by Alogame. |
msg | string | Human-readable result. Also used for not-found detection on check_uid — see below. |
data | object | Endpoint-specific payload. Required on check_uid and create_order. |
Alogame aborts the request after 8 seconds. A slow response is treated as a failure — for payment_notify that triggers a retry, so a request that eventually succeeds after 10 seconds can still be delivered twice. Make delivery idempotent (see API 3).
API 1 — Check UID
Called when the player enters their UID on the top-up screen.
Method: POST
Reference path: /check_uid (any path may be registered)
Request body
| Field | Type | Description |
|---|---|---|
uid | string | In-game character UID as typed by the player |
{
"uid": "100002078"
}
Response — success
{
"errcode": 0,
"msg": "success",
"data": {
"nickname": "DragonSlayer",
"server": "Server 1"
}
}
Alogame displays the character name for confirmation, reading the first field present: nickname, then characterName, then name. Return at least one of them — if all three are absent the order cannot proceed.
Response — UID does not exist
{
"errcode": 1001,
"msg": "user not found"
}
Alogame matches the msg string case-insensitively for the substring not found or not exist, and only then tells the player their UID is invalid so they can correct it. Any other msg is shown as a generic system error instead.
The rest of the wording is free — user not found, The role does not exist and Character not found all work.
API 2 — Create Order
Called after the player confirms the package, before the payment UI is shown.
Method: POST
Reference path: /create_order
Request body
| Field | Type | Description |
|---|---|---|
uid | string | Character UID, already validated by API 1 |
plat_order_num | string | Alogame's order code. Store it — it is the correlation key for API 3 |
productid | string | Your own product ID, exactly as you submitted it to Alogame |
amount | integer | Order total in VND |
sandbox | integer | 0 in production, 1 in dev/staging |
{
"uid": "100002078",
"plat_order_num": "260509161539010042",
"productid": "pack_500_gold",
"amount": 49000,
"sandbox": 0
}
Response — success
{
"errcode": 0,
"msg": "success",
"data": {
"order_num": "PARTNER-ORD-20260315-001"
}
}
data.order_num is required. It is your own order code and Alogame sends it back in API 3. A response with errcode: 0 but no order_num is treated as a failure and the order is aborted.
plat_order_numIf Alogame retries and the same plat_order_num arrives twice, return the original order_num with errcode: 0 rather than creating a second order.
API 3 — Payment Notify
Called after the payment provider confirms payment. Grant the purchased item.
Method: POST
Reference path: /payment_notify
Request body
| Field | Type | Description |
|---|---|---|
plat_order_num | string | Alogame's order code, same as API 2 |
order_num | string | Your order code, returned from API 2 |
amount | integer | Order total in VND |
status | integer | Always 1 (payment successful) |
{
"plat_order_num": "260509161539010042",
"order_num": "PARTNER-ORD-20260315-001",
"amount": 49000,
"status": 1
}
Response — success
{
"errcode": 0,
"msg": "success"
}
Any response other than errcode: 0 — including a timeout — schedules a retry. Alogame makes up to 4 attempts: the initial call, then retries after 60s, 120s, and 120s.
Deduplicate on order_num (or plat_order_num) and return errcode: 0 for a repeat of an order you have already delivered. Do not grant the item again, and do not return an error — an error keeps the retry loop running against an order that is already complete.
Endpoint registration — standard contract
Give your Alogame Operations Manager one base URL and three paths per environment, plus a shared secret_key:
# Production
base_url: https://api.yourgame.com
check_uid: /check_uid
create_order: /create_order
payment_notify: /payment_notify
# Dev / Staging
base_url: http://<dev-host>
Absolute URLs are accepted per endpoint if your paths live on different hosts. Production must use HTTPS with a valid TLS certificate; dev/staging may use HTTP.
The secret_key is issued by Alogame and stored encrypted. Never expose it in a client, a repository, or a log line.
There is no server picker on this contract — the player identifies their character by UID alone, and check_uid receives nothing else. If your UIDs are only unique within a server, the same UID can match several characters and the order cannot be routed. Raise this with Alogame Operations before you start.
Implementation checklist
- Submitted base URL + 3 paths (production + dev/staging) to Alogame Operations
- Production endpoints use HTTPS with a valid TLS certificate
- Signature verified against the raw request body, not a re-serialized object
-
x-timestamptreated as milliseconds; requests older than 600000 ms rejected - Signature compared with a constant-time function, not
== - All endpoints answer
200 OKwith{ errcode, msg, data }; failures use a non-zeroerrcode -
check_uid: returnsdata.nickname(orcharacterName/name); not-foundmsgcontainsnot foundornot exist -
create_order: returnsdata.order_num; a repeatedplat_order_numreturns the originalorder_num -
payment_notify: grants the item, then returnserrcode: 0; a repeat of a delivered order returnserrcode: 0without re-granting - All endpoints respond in under 8 seconds
- Delivery logged with
plat_order_num,order_num,uid,productidfor CS lookup