改变玩家余额
单一钱包回调 —— 下注、派奖、退款、奖励
改变玩家余额
由商户实现,平台调用
POST {MERCHANT_URL}/v1/wallet-transactions,使用交付的 secret 签名,Idempotency-Key 等于 transaction_id。
请求参数(body)
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
transaction_id | 是 | string | 平台交易 ID(UUID),永久唯一,商户按它去重 |
external_player_id | 是 | string | 商户侧玩家 ID |
currency | 是 | string | 币种代码 |
kind | 是 | string | BET(扣款)、PAYOUT、REFUND、GIFT(加款) |
amount | 是 | decimal string | 金额,始终大于 0 |
round_id | BET、PAYOUT、REFUND 必填 | string | 对局 ID |
reference_transaction_id | REFUND 必填 | string | 被退款的原 BET 的 transaction_id |
allocations | PAYOUT 必填 | array | 派奖来源拆分,见下文 |
allocations[] 的每一项:
| 字段 | 类型 | 说明 |
|---|---|---|
source_type | string | BET:来自一笔下注;FREE_ENTITLEMENT:来自免费局权益 |
source_id | string | BET 时为原下注的 transaction_id;FREE_ENTITLEMENT 时为权益 ID |
amount | decimal string | 本项金额。所有项之和等于 amount |
一笔下注可以分几次派奖。免费局派奖不会伪造零金额的 BET。
json
{
"transaction_id": "0192f6b0-8a1d-7c3e-9f20-1a2b3c4d5e6f",
"external_player_id": "merchant-user-1",
"currency": "USD",
"kind": "BET",
"amount": "10.00",
"round_id": "r-20260923-000123"
}响应
响应的 data 必须回显请求中的 transaction_id、external_player_id、currency、kind 和 amount。平台会逐项核对,只要有一项不一致,这次响应就会被当作不可信,平台会继续查单。
| 字段 | 类型 | 说明 |
|---|---|---|
transaction_id | string | 与请求相同 |
external_player_id | string | 与请求相同 |
currency | string | 与请求相同 |
kind | string | 与请求相同 |
amount | decimal string | 与请求相同 |
status | string | SUCCEEDED、FAILED、PENDING 或 UNKNOWN |
balance | decimal string | 处理后的余额。SUCCEEDED 时必填;FAILED 且玩家没有账户时可以省略 |
updated_at | string | UTC RFC3339 |
failure | object | 仅在 FAILED 时出现,格式为 {"code":"..."}。其他状态不要带这个字段 |
HTTP 状态和 status 必须对应:
| HTTP | 允许的 status | 含义 |
|---|---|---|
201 | SUCCEEDED、FAILED | 已得出终态 |
202 | PENDING、UNKNOWN | 已受理,结果待定。平台稍后查单 |
成功:
json
{
"data": {
"transaction_id": "0192f6b0-8a1d-7c3e-9f20-1a2b3c4d5e6f",
"external_player_id": "merchant-user-1",
"currency": "USD",
"kind": "BET",
"amount": "10.00",
"status": "SUCCEEDED",
"balance": "1240.50",
"updated_at": "2026-09-23T08:00:02Z"
},
"request_id": "b3f1c2d4-exec-0001"
}余额不足(HTTP 201):
json
{
"data": {
"transaction_id": "0192f6b0-8a1d-7c3e-9f20-1a2b3c4d5e6f",
"external_player_id": "merchant-user-1",
"currency": "USD",
"kind": "BET",
"amount": "10.00",
"status": "FAILED",
"balance": "5.00",
"updated_at": "2026-09-23T08:00:02Z",
"failure": { "code": "INSUFFICIENT_FUNDS" }
},
"request_id": "b3f1c2d4-exec-0002"
}业务失败要用 FAILED 表示
余额不足、玩家被冻结等已确认没有扣款的业务失败,要返回 201 加 status=FAILED。如果返回错误信封({"error":...}),平台只会把它当作“结果不明”,然后一直查单。
只有请求本身不合法时才返回错误信封,例如签名错误、409 IDEMPOTENCY_CONFLICT。
重复请求
| 场景 | 返回 |
|---|---|
同一个 transaction_id,内容相同 | 原 HTTP 状态和原 data(包括当时的 balance),加响应头 Idempotency-Replayed: true |
同一个 transaction_id,内容不同 | 409 IDEMPOTENCY_CONFLICT |
| 首次请求还在处理中 | 202,status=PENDING |
退款规则
- 退款必须引用一笔已成功的
BET,并且玩家、币种和商户都要一致。 - 同一笔
BET的所有退款(已成功的加上处理中的)加起来,不能超过下注金额。商户要原子地预留和校验这个额度。 - 如果原
BET在商户侧不存在或尚未确定,返回202 UNKNOWN,或返回201 FAILED并带failure.code=INVALID_TRANSACTION_REFERENCE。不要凭空加款。
最后更新于 12小时前