Skip to main content

Web Payment — Standard Contract (Co-publishing)

Applies toNewly onboarded co-publishing games
Endpointscheck_uid, create_order, payment_notify, plus optional get_server_list and get_character_list
SignatureHMAC-SHA256 for a new integration. Two MD5 variants exist for already-integrated titles but are being deprecated — see Authentication.
ErrorsDepends on your algorithm — errcode in a 200 OK body under HMAC-SHA256 (assumed by the examples below), HTTP status codes under either MD5 variant.

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 account-linked character list. There is no getUserList equivalent and you never receive an Alogame userId: the player types their UID on the top-up screen and Alogame validates it with check_uid. If one UID of yours can own several characters, there is an optional per-UID picker — API 3 — Get Character List — but it is keyed by uid, never by an Alogame account.
  • Errors are carried in the response body, not the HTTP status. Every response is 200 OK with an errcode field. Alogame treats errcode: 0 as success and anything else as failure.
Which pickers does your game need?

Both are optional and independent. Alogame never calls either unless your Alogame Operations contact has turned it on for your game.

  • get_server_list — if your UIDs are only unique within a server (two servers can each have a character 100002078), implement it so the player picks a server before typing their UID, and every subsequent call carries server_id alongside uid. Skip it if UIDs are globally unique.
  • get_character_list — if one UID can own more than one character, implement it so the player picks which character receives the top-up after their UID is validated, and create_order carries character_id. Skip it if a UID identifies exactly one character (the common case).

So the full step order for a game that implements both is: pick server → type UID → pick character → pay.

Flow​

Steps highlighted in green are implemented by your game server; everything else is handled by Alogame.

Step-by-step breakdown​

#Who actsWhat happensYour responsibility
1UserPlayer opens the top-up screen—
2–3Game Server(only if server-scoped) Alogame calls get_server_listReturn the list of servers the player can pick from
4–6Alogame + UserPlayer picks a server (if any) and types their in-game UID—
7–8Game ServerAlogame calls check_uid with the UID (and server_id, if server-scoped)Return the character for this UID, or a not-found error
9AlogameCharacter name shown for confirmation—
10–11Game Server(only if a UID owns several characters) Alogame calls get_character_listReturn every character this UID owns
12–14Alogame + UserPlayer picks a character (if any), then the package and payment method—
15Alogame BackendAlogame generates plat_order_num (its own order code)—
16–18Game ServerAlogame calls create_orderCreate a local order record; return your own order_num
19–22Alogame + User + Payment ProviderPlayer pays; provider notifies Alogame via IPN—
23Alogame BackendAlogame verifies the IPN and marks the order paid—
24–26Game ServerAlogame calls payment_notify with both order codesGrant the item; return errcode: 0
27–28AlogamePlayer receives success notification—

Authentication​

Use HMAC-SHA256 for a new co-pub integration — this page's examples assume it: requests are signed 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. Two MD5 variants exist for titles already integrated on them, but they're being deprecated — do not build a new integration against either.

Response envelope​

Under HMAC-SHA256 (this page's examples), all three endpoints answer 200 OK with the same wrapper:

{
"errcode": 0,
"msg": "success",
"data": { }
}
FieldTypeDescription
errcodeinteger0 = success. Any other value is treated as a failure by Alogame.
msgstringHuman-readable result. Also used for not-found detection on check_uid — see below.
dataobjectEndpoint-specific payload. Required on check_uid and create_order.
Respond within 8 seconds

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 5).

API 1 — Get Server List (optional)​

Only called for a game Alogame Operations has configured as server-scoped — skip this entirely if your game has one shared pool of UIDs. Called once, when the player opens the top-up screen, before check_uid.

Method: POST
Reference path: /get_server_list (any path may be registered)

Request body: empty JSON object ({}), still signed like every other call.

Response — success

{
"errcode": 0,
"data": [
{ "serverId": "1", "name": "Server 1" },
{ "serverId": "2", "name": "Server 2" }
]
}
FieldTypeDescription
data[].serverIdstringYour server's identifier. id is also accepted as an alias.
data[].namestringDisplay name shown in the picker. A server with a missing/blank name is dropped from the list.

Any errcode other than 0, or a non-array data, is treated the same as an empty list — the player sees no server picker rather than an error, so a transient failure here degrades gracefully instead of blocking the top-up screen from loading. There is no "not found" case to handle.

API 2 — Check UID​

Called when the player enters their UID on the top-up screen (after picking a server, if API 1 applies to your game).

Method: POST
Reference path: /check_uid (any path may be registered)

Request body

FieldTypeDescription
uidstringIn-game character UID as typed by the player
server_idstringOnly sent if your game implements API 1. The serverId the player picked.
{
"uid": "100002078",
"server_id": "1"
}

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"
}
How "not found" is detected

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 3 — Get Character List (optional)​

Only called for a game Alogame Operations has configured as character-scoped — skip this entirely if a UID identifies exactly one character in your game. Called once, right after check_uid succeeds, so it can rely on the uid having already been validated.

Not the same as expub's "Get Character List"

Web Payment — Expub has an identically-named API 1, but it is a different mechanism: that one is keyed by an Alogame userId and returns every character linked to that account across your game. This one is keyed by a single uid the player typed, and returns only the characters that UID owns. Co-pub games have no Alogame-linked account, so only this form applies here.

Method: POST
Reference path: /get_character_list (any path may be registered)

Request body

FieldTypeDescription
uidstringThe UID already validated by API 2
server_idstringOnly sent if your game also implements API 1. Same value check_uid received.
{
"uid": "100002078",
"server_id": "1"
}

Response — success

{
"errcode": 0,
"data": [
{ "characterId": "c-1001", "name": "DragonSlayer" },
{ "characterId": "c-1002", "name": "IronMage" }
]
}
FieldTypeDescription
data[].characterIdstringYour character's identifier. id is also accepted as an alias. Alogame sends the picked value back as character_id on create_order.
data[].namestringDisplay name shown in the picker. characterName is also accepted as an alias. A character with a missing/blank name and no usable id is dropped from the list.

Any errcode other than 0, or a non-array data, is treated the same as an empty list — the player sees no character picker rather than an error, so a transient failure here degrades gracefully. There is no "not found" case to handle: a UID that does not exist is already rejected by check_uid, and an empty list for a valid UID is a legitimate answer, not an error.

API 4 — Create Order​

Called after the player confirms the package, before the payment UI is shown.

Method: POST
Reference path: /create_order

Request body

FieldTypeDescription
uidstringCharacter UID, already validated by API 2
plat_order_numstringAlogame's order code. Store it — it is the correlation key for API 5
productidstringYour own product ID, exactly as you submitted it to Alogame
amountintegerOrder total in VND
sandboxinteger0 in production, 1 in dev/staging
server_idstringOnly sent if your game implements API 1. Same value check_uid already received.
character_idstringOnly sent if your game implements API 3. The characterId the player picked. Deliver the purchase to this character, not merely to the UID.
{
"uid": "100002078",
"plat_order_num": "260509161539010042",
"productid": "pack_500_gold",
"amount": 49000,
"sandbox": 0,
"server_id": "1",
"character_id": "c-1001"
}

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 5. A response with errcode: 0 but no order_num is treated as a failure and the order is aborted.

Deduplicate on plat_order_num

If 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 5 — Payment Notify​

Called after the payment provider confirms payment. Grant the purchased item.

Method: POST
Reference path: /payment_notify

Request body

FieldTypeDescription
plat_order_numstringAlogame's order code, same as API 4
order_numstringYour order code, returned from API 4
amountintegerOrder total in VND
statusintegerAlways 1 (payment successful)
{
"plat_order_num": "260509161539010042",
"order_num": "PARTNER-ORD-20260315-001",
"amount": 49000,
"status": 1
}

Response — success

{
"errcode": 0,
"msg": "success"
}
Idempotency is required — this call is retried automatically

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 required paths per environment (plus either optional picker, if it applies), and a shared secret_key:

# Production
base_url: https://api.yourgame.com
get_server_list: /get_server_list # only if server-scoped
get_character_list: /get_character_list # only if a UID owns several characters
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.

What identifies a character, and what your UIDs must therefore guarantee

With neither optional picker, check_uid receives nothing but uid, so a uid alone must identify exactly one character — unique across every server, or the same UID matches several characters and the order cannot be routed. Each picker relaxes that in a different direction:

  • API 1 — Get Server List adds server_id to check_uid/create_order, so your UIDs only need to be unique within a server.
  • API 3 — Get Character List adds character_id to create_order, so a uid is allowed to own several characters — the player says which one.

Tell your Alogame Operations contact up front which case applies to your game: it decides which endpoints get wired in, and a game whose UIDs are ambiguous with neither picker enabled cannot deliver reliably.


Implementation checklist​

  • Submitted base URL + 3 required paths, plus either optional picker path that applies (production + dev/staging), to Alogame Operations
  • Told Alogame Operations whether your game is server-scoped, so get_server_list gets wired in and server_id is turned on for check_uid/create_order
  • Told Alogame Operations whether one UID can own several characters, so get_character_list gets wired in and character_id is turned on for create_order
  • Production endpoints use HTTPS with a valid TLS certificate
  • Signature verified against the raw request body, not a re-serialized object
  • x-timestamp treated as milliseconds; requests older than 600000 ms rejected
  • Signature compared with a constant-time function, not ==
  • All endpoints answer 200 OK with { errcode, msg, data }; failures use a non-zero errcode
  • get_server_list (if implemented): returns data[] with serverId/id + name per server
  • check_uid: returns data.nickname (or characterName / name); not-found msg contains not found or not exist
  • get_character_list (if implemented): returns data[] with characterId/id + name/characterName per character
  • create_order: returns data.order_num; a repeated plat_order_num returns the original order_num; delivery is routed to character_id when it is sent
  • payment_notify: grants the item, then returns errcode: 0; a repeat of a delivered order returns errcode: 0 without re-granting
  • All endpoints respond in under 8 seconds
  • Delivery logged with plat_order_num, order_num, uid, productid for CS lookup