StakeGO TestKit — Seamless Test Cases

The Seamless (single wallet) test suite contains 14 test cases, executed by the TestKit in the selected order. API reference: https://doc.sgo-extension.com/swam/

Merchant callbacks support two request formats. Use the switch above to view the request examples for your integration — JSON is shown by default. Responses and assertions are identical in both formats.

General Conventions

Endpoints

Step typeDirectionEndpoint
loginTestKit → StakeGO platform (STG){SGO_API_URL}/api/login (GET, params in query string)
balance / deduct / deposit / rollbackTestKit (acting as the platform) → merchant callbacksThe Balance / Deduct / Deposit / Rollback URLs configured on the page

Request format (JSON mode). Every callback is a POST with Content-Type: application/json and a JSON body. The bets field is a native JSON array. When a token is configured, every callback request also carries the token field (which is included in the signature); the examples below use token=mock_123. The login request never carries a token.

Request format (Form mode). Callbacks are POST with Content-Type: application/x-www-form-urlencoded, except balance, which becomes a GET with the parameters in the query string. Form values are strings, so the bets array is serialized to a JSON string inside the bets field — the merchant must JSON-parse it again. Form mode never sends a token field. The form examples below show the decoded field values; on the wire they are URL-encoded.

Signature (identical in both formats). Every request carries a sign parameter (MD5): lowercase the key names, drop empty values plus the sign and bets fields, sort keys in ascending ASCII order, join as k=v&...&key={secretKey} (values are not URL-encoded), then take the MD5 hex digest.

Assertions

• Each step asserts Number(response.result) === expected_result_code (every step in this suite expects 0).
• For steps with an expected balance change, the executor calls the merchant Balance endpoint before and after the step and asserts the delta (tolerance 0.005).
login additionally requires a non-empty openurl; balance additionally requires a numeric balance field.

Identifiers

• All steps within one test case share the same serialnumber (they refer to the same bet). Each entry in bets has its own id/serialnumber; gameroundno equals the case's serialnumber.
• Every notification carries a fresh notifyid. Duplicate-notification cases (the second send in 004, 006, and 011) resend the same notifyid.
• A rollback notification uses its own new notifyid and locates the original transaction via serialnumber + type.

All examples below use appid=your_appid, username=player01, currency=THB; sign and the id fields are placeholders. A full request body is shown only the first time it appears; later cases describe the differences.

001 Login

Verify that /api/login returns the game lobby link. If login fails, subsequent tests may also fail. The login request is the same in both formats.

Request (GET query string)
{
  "appid": "your_appid",
  "username": "player01",
  "iscreate": "1",
  "clienttype": "1",
  "language": "2",
  "currency": "THB",
  "sign": "0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b"
}
Expected response (result = 0 and a non-empty openurl)
{
  "result": 0,
  "openurl": "https://stg-lobby.example.com/?token=xxxx"
}

002 Get Player Balance

The platform calls the merchant Balance endpoint; expect result = 0 and a numeric balance.

Request (POST application/json)
{
  "appid": "your_appid",
  "username": "player01",
  "token": "mock_123",
  "notifyid": "25081111203512345",
  "sign": "0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b"
}
Request (GET query string)
GET {Balance_url}?appid=your_appid&username=player01&notifyid=25081111203512345&sign=0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b
Expected response
{
  "result": 0,
  "balance": 100.00
}

003 Bet Deduct

The platform notifies the merchant to deduct a bet (type=1, negative amount).

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
Request (POST application/json)
{
  "appid": "your_appid",
  "username": "player01",
  "token": "mock_123",
  "notifyid": "25081111203512345",
  "type": "1",
  "amount": "-1.00",
  "currency": "THB",
  "serialnumber": "1754882501123456",
  "bets": [
    {
      "id": "1754882501123888",
      "serialnumber": "1754882501123888",
      "userid": "0",
      "username": "player01",
      "gametype": 4,
      "gameid": 1,
      "gameroundno": "1754882501123456",
      "choosebankpoint": "",
      "betpoint": "PLAYER",
      "betamount": "1.00",
      "winlost": "0",
      "commamount": "0",
      "commratio": "",
      "createtime": "2026-08-11 11:20:35",
      "state": 0
    }
  ],
  "sign": "0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b"
}
Request body (POST application/x-www-form-urlencoded, decoded)
appid=your_appid
username=player01
notifyid=25081111203512345
type=1
amount=-1.00
currency=THB
serialnumber=1754882501123456
bets=[{"id":"1754882501123888","serialnumber":"1754882501123888","userid":"0","username":"player01","gametype":4,"gameid":1,"gameroundno":"1754882501123456","choosebankpoint":"","betpoint":"PLAYER","betamount":"1.00","winlost":"0","commamount":"0","commratio":"","createtime":"2026-08-11 11:20:35","state":0}]
sign=0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b
Expected response (balance after the deduction, plus the merchant order number)
{
  "result": 0,
  "balance": 99.00,
  "orderno": "M20260811001"
}

004 Duplicate serialnumber Deduct

The same deduct notification is sent twice (same serialnumber and notifyid). The merchant must not deduct twice and must respond result = 0 both times (idempotency).

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
2Deduct1-1.0000 (no second deduction)

Request/response are identical to 003; step 2 is an exact resend of step 1.

005 Settle Deposit

A bet deduct (type=1) followed by a settle deposit (type=9) for the same serialnumber.

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
2Deposit9+2.000+2.00
Step 2 request (POST application/json; same serialnumber as step 1, new notifyid; the bet now carries the win/loss result)
{
  "appid": "your_appid",
  "username": "player01",
  "token": "mock_123",
  "notifyid": "25081111203698765",
  "type": "9",
  "amount": "2.00",
  "currency": "THB",
  "serialnumber": "1754882501123456",
  "bets": [
    {
      "id": "1754882501123888",
      "serialnumber": "1754882501123888",
      "userid": "0",
      "username": "player01",
      "gametype": 4,
      "gameid": 1,
      "gameroundno": "1754882501123456",
      "choosebankpoint": "",
      "betpoint": "PLAYER",
      "betamount": "1.00",
      "winlost": "1.00",
      "commamount": "1.00",
      "commratio": "",
      "createtime": "2026-08-11 11:20:35",
      "state": 1
    }
  ],
  "sign": "0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b"
}
Step 2 request body (POST application/x-www-form-urlencoded, decoded; same serialnumber as step 1, new notifyid)
appid=your_appid
username=player01
notifyid=25081111203698765
type=9
amount=2.00
currency=THB
serialnumber=1754882501123456
bets=[{"id":"1754882501123888","serialnumber":"1754882501123888","userid":"0","username":"player01","gametype":4,"gameid":1,"gameroundno":"1754882501123456","choosebankpoint":"","betpoint":"PLAYER","betamount":"1.00","winlost":"1.00","commamount":"1.00","commratio":"","createtime":"2026-08-11 11:20:35","state":1}]
sign=0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b
Expected response
{
  "result": 0,
  "balance": 101.00,
  "orderno": "M20260811002"
}

006 Duplicate serialnumber Deposit

The same settle deposit notification is sent twice (same serialnumber and notifyid). The merchant must not credit the winnings twice and must respond result = 0 both times (idempotency).

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
2Deposit9+2.000+2.00
3Deposit9+2.0000 (no second credit)

Request/response are identical to 005; step 3 is an exact resend of step 2.

007 Void Bet Deposit

A bet deduct followed by a void-bet deposit (type=7) returning the stake.

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
2Deposit7+1.000+1.00

Step 2 has the same structure as the Deposit in 005, with these differences: type="7", amount="1.00", and the bet carries winlost="1.00", commamount="1.00", state=1. The response format is the same as Deposit.

008 ReSettle Deposit

Bet deduct, settle deposit, then a re-settle correction deposit (type=10) for the same bet.

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
2Deposit9+2.000+2.00
3Deposit10+0.500(not verified)

Step 3 has the same structure as Deposit, with these differences: type="10", amount="0.50", and the bet carries winlost="1.50", state=2. The response format is the same as Deposit.

009 Rollback Deduct

A deduct notification is assumed lost, so the platform sends a rollback (type=1). The merchant must return the deducted amount and respond result = 0.

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
2Rollback1+1.000+1.00
Step 2 request (POST application/json; rollback uses a new notifyid and locates the original deduct via serialnumber + type; no bets/currency)
{
  "appid": "your_appid",
  "username": "player01",
  "token": "mock_123",
  "notifyid": "25081111204055555",
  "type": "1",
  "amount": "1.00",
  "serialnumber": "1754882501123456",
  "errmsg": "timeout",
  "sign": "0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b"
}
Step 2 request body (POST application/x-www-form-urlencoded, decoded; rollback uses a new notifyid and locates the original deduct via serialnumber + type; no bets/currency)
appid=your_appid
username=player01
notifyid=25081111204055555
type=1
amount=1.00
serialnumber=1754882501123456
errmsg=timeout
sign=0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b
Expected response (current balance after the rollback)
{
  "result": 0,
  "balance": 100.00
}

010 Rollback Deposit

A settle deposit notification is assumed lost, so the platform sends a rollback (type=9). The merchant must remove the deposited amount and respond result = 0.

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
2Deposit9+2.000+2.00
3Rollback92.000-2.00

Step 3 has the same structure as the Rollback in 009, with these differences: type="9", amount="2.00". The response format is the same.

011 Duplicate Rollback Deduct

The same rollback notification is sent twice (same notifyid, type and serialnumber). The merchant must only return the deducted amount once and must respond result = 0 both times (idempotency).

StepEndpointtypeamountExpected resultBalance change
1Deduct1-1.000-1.00
2Rollback1+1.000+1.00
3Rollback1+1.0000 (no second rollback)

Request/response are identical to 009; step 3 is an exact resend of step 2.

012 Rollback Unknown Serial

A rollback for a serialnumber the merchant never processed. Per the spec the merchant must do nothing and still respond result = 0.

StepEndpointtypeamountExpected resultBalance change
1Rollback11.0000 (no balance movement)

The request has the same structure as the Rollback in 009 (with a brand-new serialnumber).

Expected response
{
  "result": 0,
  "balance": 100.00
}

013 Tips Deduct

The player tips the dealer; the platform notifies the merchant to deduct with type=28 (no bets).

StepEndpointtypeamountExpected resultBalance change
1Deduct28-0.500-0.50
Request (POST application/json)
{
  "appid": "your_appid",
  "username": "player01",
  "token": "mock_123",
  "notifyid": "25081111204233333",
  "type": "28",
  "amount": "-0.50",
  "currency": "THB",
  "serialnumber": "1754882599654321",
  "sign": "0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b"
}
Request body (POST application/x-www-form-urlencoded, decoded)
appid=your_appid
username=player01
notifyid=25081111204233333
type=28
amount=-0.50
currency=THB
serialnumber=1754882599654321
sign=0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b
Expected response
{
  "result": 0,
  "balance": 99.50,
  "orderno": "M20260811003"
}

014 Multi Bets Deduct

One deduct notification carrying multiple bets from the same player; amount equals the total of all bets.

StepEndpointtypeamountExpected resultBalance change
1Deduct1-3.000-3.00
Request (POST application/json; same structure as 003, bets contains 3 entries with betamount 1.00 each, individual id/serialnumber, shared gameroundno)
{
  "appid": "your_appid",
  "username": "player01",
  "token": "mock_123",
  "notifyid": "25081111204577777",
  "type": "1",
  "amount": "-3.00",
  "currency": "THB",
  "serialnumber": "1754882650111222",
  "bets": [
    { "id": "1754882650111001", "serialnumber": "1754882650111001", "betpoint": "PLAYER", "betamount": "1.00", "...": "remaining fields as in 003" },
    { "id": "1754882650111002", "serialnumber": "1754882650111002", "betpoint": "BANKER", "betamount": "1.00", "...": "remaining fields as in 003" },
    { "id": "1754882650111003", "serialnumber": "1754882650111003", "betpoint": "TIED",   "betamount": "1.00", "...": "remaining fields as in 003" }
  ],
  "sign": "0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b"
}
Request body (POST application/x-www-form-urlencoded, decoded; bets is one JSON string containing all 3 entries)
appid=your_appid
username=player01
notifyid=25081111204577777
type=1
amount=-3.00
currency=THB
serialnumber=1754882650111222
bets=[{"id":"1754882650111001","betpoint":"PLAYER","betamount":"1.00",...},{"id":"1754882650111002","betpoint":"BANKER","betamount":"1.00",...},{"id":"1754882650111003","betpoint":"TIED","betamount":"1.00",...}]
sign=0d8f2e0b8a5c4f1e9c7a6b5d4e3f2a1b
Expected response
{
  "result": 0,
  "balance": 97.00,
  "orderno": "M20260811004"
}