当前游戏余额增量同步
当包网已经通过 Bet Push、充值或冲正更新主钱包,但玩家仍在另一个游戏中时,使用本接口把同一笔金额增减同步到当前在线游戏钱包。Hub 使用 event_id 幂等处理,并通过 source_session_id 判断来源与当前 session 是否共用物理钱包:不同钱包才执行增减;相同钱包表示 hub-system 已经反映该流水,只记录事件而不重复改变余额。
接口信息
| 属性 | 值 |
|---|---|
| 路径 | POST /papi/v1/player/balance-adjust |
| 认证 | Agent Token(Bearer) |
| Content-Type | application/json 或 application/x-www-form-urlencoded |
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
member_id | string | 是 | 包网玩家 ID |
currency | string | 是 | 当前游戏币种 |
session_id | string | 是 | 当前在线游戏的 Hub session ID |
event_id | string | 是 | 该业务变动的稳定幂等键;超时重试必须原样复用 |
event_type | string | 是 | 如 settlement、deposit、void、rollback |
delta | decimal | 是 | 非零增量;入账为正数,冲正为负数,最多按 4 位小数处理 |
source_session_id | string | 否 | 跨游戏流水的来源 session;提供后 Hub 会保存来源钱包及 Brand 快照 |
reverses_event_id | string | 负数必填 | 冲正所对应的原正向 event_id |
正向例子:
json
{
"member_id": "player001",
"currency": "MYR",
"session_id": "uu-current-session",
"event_id": "CMD_SETTLED_84000010943916399_v1",
"event_type": "settlement",
"delta": 50.00,
"source_session_id": "cmd-old-session"
}冲正例子:
json
{
"member_id": "player001",
"currency": "MYR",
"session_id": "uu-current-session",
"event_id": "CMD_VOID_84000010943916399_v1",
"event_type": "void",
"delta": -50.00,
"reverses_event_id": "CMD_SETTLED_84000010943916399_v1"
}成功响应
json
{
"status": true,
"code": 0,
"data": {
"member_id": "player001",
"currency": "MYR",
"event_id": "CMD_SETTLED_84000010943916399_v1",
"event_type": "settlement",
"delta": 50,
"applied_delta": 50,
"same_wallet": false,
"session_id": "uu-current-session",
"provider": "gsc",
"balance_before": 100,
"balance_after": 150,
"idempotent": false,
"status": "applied"
},
"msg": "success"
}相同参数和相同 event_id 重试时仍返回成功,idempotent=true,余额不会再次变化。相同 ID 携带不同金额、类型、来源或冲正关系会返回 event_id_conflict。
同一 Provider 下两个 Brand 共用物理钱包时,成功响应会返回 same_wallet=true、applied_delta=0,且 balance_before 等于 balance_after。事件仍被幂等记录;对应冲正同样不会再次扣减。包网不需要知道 Brand 背后的 Platform 或钱包关系。
处理规则
- Hub 通过来源与目标 session binding 比较实际
wallet_id。不同钱包时修改当前在线游戏钱包;相同钱包时不重复增减。 delta是包网请求的业务金额,applied_delta是 Hub 本次实际改变钱包的金额;包网应以applied_delta判断是否发生镜像。- 负数请求必须关联一个已成功应用的正向事件,累计冲正不可超过原增额,且当前钱包结果不可小于零。
session_mismatch:第一次请求使用了旧 session。取得最新 active session 后,以同一个event_id重试。no_active_game_session:当前没有在线游戏。不要把该事件稍后盲目追加到新 session;玩家下次启动时由/callback/balance返回已经包含该事件的完整主钱包余额。player_settlement_in_progress:Hub 正在原子清空同币种钱包;稍后用同一个 event 重试。source_session_binding_not_found:Hub 没有来源 session 的钱包/Brand 绑定。不要删除 event 或改用新的 ID;先核对来源 session。insufficient_balance_for_adjustment:冲正会使当前游戏钱包小于零。reversal_amount_exceeded:累计冲正超过原正向事件。
推荐时序
包网在同一个本地数据库事务中完成主钱包流水和 outbox。事务提交后、Bet Push 返回 success 前可以尝试调用 Hub;调用超时不回滚已提交的主钱包流水,也不重复派奖,而是由 outbox 使用同一个 event_id 重试。只有非当前游戏产生的变动以及充值/外部冲正需要调用本接口;当前游戏下注与派彩继续走原游戏账务。
AI 开发提示词(可直接复制)
text
请在包网项目实现 VCT POST /papi/v1/player/balance-adjust。
本地资金流水与 outbox 必须在同一数据库事务提交。每一笔跨游戏迟到派彩、充值或冲正生成稳定且全局唯一的 event_id;网络失败、超时和业务重试必须复用同一个 event_id,禁止生成新 ID。
正向变动传 delta>0。冲正传 delta<0,并用新的 event_id 和 reverses_event_id 关联原正向事件。请求携带当前在线 session_id;跨游戏流水同时携带 source_session_id。Hub 会比较来源和目标实际 wallet_id:不同钱包才原子增减当前游戏钱包;相同钱包只登记事件。响应的 applied_delta 是实际钱包变动,same_wallet 表示是否共用钱包。
HTTP 200 仍须检查 code。成功或 idempotent=true 都可把 outbox 标记完成。session_mismatch 时刷新当前 active session 后用同一个 event_id 重试;no_active_game_session 时停止向旧/新 session 追加该 delta,保留本地已完成流水,等待下次游戏启动通过完整主钱包余额初始化;player_settlement_in_progress 暂缓并以相同 event 重试。event_id_conflict、冲正超额和余额不足进入人工对账,不能更换 event_id 绕过。
Offline callback 的 mirrored_adjustments 只列出已成功镜像的 event_id;每项的 mirrored_amount 明确该事件的镜像金额。最终扣重总额以 Hub 按来源钱包实际余额封顶后的 mirrored_delta_total 为准。wallet_cleared_total 是 Hub 物理清空总额,可能包含来源钱包和已镜像到当前钱包的重复金额。使用 mirrored_adjustments.event_id 去重,并以 net_balance_to_reconcile 对账;不要把 reclaimed_amount 或 wallet_cleared_total 再次直接加到主钱包。
增加测试:正向增量、同 event 超时重试、不同参数复用 ID、同 Provider 不同 Brand 共用钱包跳过重复增量及冲正、切换 session 后重试已成功 event、旧 session 首次请求、无在线 session、部分/完整冲正、累计超额、余额不足、Offline 两钱包与镜像事件对账。