amBrain
iGamingSep 17, 2026阅读需 11 分钟

自有娱乐场后端的游戏供应商聚合层:会话、余额回调与回合历史

娱乐场后端游戏聚合单一钱包幂等性
图片加载失败

一个接入众多供应商的老虎机、真人荷官和桌面游戏的娱乐场后端,需要一个聚合层:由运营商签发的会话、经得住重试和回滚的余额回调、可能在会话之后才结束的回合,以及与每家供应商自己的报表进行的每日对账。本文讲这一层怎样划分,以及供应商集成通常在哪里出问题。

一家自建娱乐场后端、接入众多供应商的老虎机、真人荷官和桌面游戏的运营商,最终会有和供应商一样多的集成契约:不同的启动流程、不同的钱包调用、对回合是什么各有不同的理解。聚合层把它们变成一套内部契约,这样钱包、大厅、奖金、限额和报表都只需编写一次,每家供应商都去适配它们。

下文讲这一层通常怎样划分:哪些留在供应商那边、会话如何签发、余额回调如何经得住重试和回滚、回合在会话之后才结束时如何记录,以及结果如何与供应商自己的数字对账。

简短的答案是:一套内部契约,每家供应商配一个适配器。运营商签发会话;每一笔扣款、加款和回滚都携带供应商的交易 ID,作为按供应商和调用类型限定范围的幂等键;针对钱包从未见过的交易的回滚会被保存下来,因此迟到的原始交易会被拒绝;回合以状态的形式记录,而且可能在会话结束之后才结束;每家供应商自己的报表每天都与钱包账本对账。

聚合层负责什么,什么留在供应商那边

供应商负责运行游戏:随机数生成、游戏数学、游戏客户端及其由检测实验室完成的认证。运营商保留一切涉及玩家和资金的部分:身份、余额、限额、奖金、大厅,以及监管机构或玩家争议可能要求提供的记录。聚合层位于两者之间,并且应当是唯一对接各家供应商 API 的服务端代码。

  • 启动:针对某一玩家、游戏、币种、语言和设备的游戏 URL 或令牌,以及永远不会触达钱包的试玩模式
  • 钱包:来自每家供应商的余额、扣款、加款和回滚调用,都通过同一个内部账本来应答
  • 回合:每家供应商的回合 ID 和状态,包括含多笔投注的回合和较晚才完成的回合
  • 目录:供应商的游戏 ID、分类和支持的设备映射到同一个大厅,并按每款游戏可以在哪里提供进行过滤
  • 奖金:如果供应商有自己的奖金接口,就通过它发放免费回合,其派彩记为奖金
  • 报表:按供应商汇总的总额,其形式与供应商开票所依据的一致

单一钱包还是转账钱包

供应商以两种方式之一接入运营商的资金。在单一钱包(seamless wallet)模式下,余额留在运营商这边,每一次投注和派彩,供应商都要调用运营商的钱包。在转账钱包(transfer wallet)模式下,运营商在游戏开始前把资金转入供应商一侧持有的余额,并且只有在运营商发起请求时才把资金转回。

  • 单一钱包在所有游戏之间只保留一份余额,因此限额、奖金以及玩家看到的自己的资金都保持一致,同时它也把运营商钱包的延迟和可用性放进了每一次旋转
  • 转账钱包把游戏过程与运营商的钱包隔离开,并拆分了余额:停留在供应商会话中的资金在其他任何地方都不可用,而每一次转入和转出都是又一条需要对账的分录
  • 同时支持两种方式的聚合层,仍然只有一个内部账本;转账适配器把会话的开始和结束分别变成一笔扣款和一笔加款

本文余下部分以单一钱包为前提,因为在这种模式下,每一次投注和派彩都是一次钱包调用。

会话:令牌由运营商签发

游戏启动从运营商一侧开始。后端检查这名玩家此刻可否玩这款游戏,检查范围包括账户状态、自我排除、限额,以及这款游戏可否在玩家所在的司法辖区提供。随后它创建一个与玩家、游戏和币种绑定的会话,并在启动时把一个不透明令牌传给供应商。当供应商的服务器发起回调时,这个令牌标明该调用涉及的是谁的余额。

  • 令牌标识的是一个会话,而不是永久地标识一名玩家:它会过期,而且当玩家在游戏过程中自我排除或触及限额时,运营商可以吊销它
  • 新的投注需要有效的会话;而已被接受的投注所产生的派彩,即使会话在此期间已经结束,也必须加款
  • 一名玩家可以同时持有多个游戏会话,所以余额变更按账户串行化,而不是按会话
  • 币种在会话内固定不变;玩家切换币种就要开启一个新会话
  • 试玩拿到的令牌会被钱包直接拒绝,这样一次被错误路由的调用永远碰不到真钱

面向运营商公开发布的文档把这一点说得很直白。Hub88 的钱包 API 说明,对派彩和回滚不得校验令牌是否有效,因为它们可能在投注已经完成之后才到来。VeliGames 说明,即使会话已经过期,运营商也不得拒绝某个回合的派彩。

余额回调:每个调用都可能到达两次

两台服务器之间的任何调用,都可能在对端已经把工作做完之后才超时。供应商分辨不出是扣款失败了,还是扣款的响应丢了,所以它会重复这次调用,或者取消这笔交易。钱包的职责是让这两种做法都安全。

公开的集成文档表明,这些重复调用有多执着。Hub88 的运营商钱包 API 在收不到 HTTP 200 时就把投注算作失败,生成一个回滚,并以指数退避重试这个回滚,最多 500 次。Gamomat 会把失败的请求重试两次,间隔 500 ms,然后发起回滚,并以从一秒逐步增长到 30 分钟的间隔重试它。Tom Horn Gaming 的钱包超时时间是 10 秒,超时之后会自动发送回滚。一个宕机几分钟的钱包,恢复之后面对的是排着队的重复调用和回滚,而不是一片安静。

  • 幂等键是按供应商和调用类型限定范围的供应商交易 ID,因为两家供应商可能发出相同的 ID,而且有些供应商会用投注的 ID 发送回滚;这个键上的唯一约束把重复调用变成一次查询
  • 重复的扣款绝不会第二次挪动资金,而同一个 ID 带着不同的金额或回合到达,是一个错误,而不是一笔新投注
  • 扣款在一个短事务里锁定账户行、检查余额和限额并写入自己的账本分录,这样同一账户上的两次并发旋转就不可能都花掉同一笔钱
  • 回滚要指明它所取消的交易:已生效的扣款只冲正一次,已经处理过的回滚返回它保存的结果
  • 针对钱包从未收到的交易的回滚,会被记录下来,并以供应商文档规定的返回码应答,这样随后才到达的延迟原始交易就会被拒绝,而不是为一笔供应商已经取消的投注向玩家收钱
  • 错误被映射为各家供应商自己的错误码,因为供应商对余额不足、会话过期和一般性故障的反应各不相同:有的停止游戏,有的重试,有的取消

对重复调用该怎样应答,也没有统一标准。Hub88 要求相同交易 ID 的请求不得被处理两次,并且所有重复请求得到的响应都相同;VeliGames 要求返回一个带 HTTP status 409 和 DUPLICATE_TRANSACTION 的错误;Tom Horn Gaming 为重复的参考号单独设有一个结果码。适配器按每家供应商各自的形式应答,底层的账本保持不变。

针对未知交易的回滚很容易处理错。如果钱包什么都不保存,一笔只是在传输途中被延迟的扣款会在片刻之后到达并成功,玩家就要为一笔供应商已经取消的投注付钱。先把回滚存下来,再在扣款的账户锁之下检查它,就能堵上这个缺口。

供应商在自己的文档里写明了这条规则。St8 的运营商 API 说明:当运营商收到一个取消请求,而其中的交易 ID 是运营商此前没有处理过的,就必须保存这个 ID,以防该 ID 之后被处理。当钱包从未处理过回滚所指向的那笔扣款时,Tom Horn Gaming 期望收到它自己的未知交易结果码。

回合按自己的节奏结束

回合是供应商的游戏单位,它很少恰好对应一笔交易。一次老虎机旋转通常是一笔扣款加一笔加款,有时作为一次调用发送。二十一点可能因分牌或加倍而追加扣款。真人轮盘在一个投注窗口内接收许多玩家的投注,并在结果揭晓时将它们全部结算。免费回合可能产生一连串同属一组的派彩。

  • 在每条账本分录中存储供应商的回合 ID,并单独保存回合的状态:未结束、已结束或已取消
  • 如果 API 提供了供应商自己的信号——显式的回合结束调用或最终标志——就据此结束回合;否则按为每家供应商成文记录的规则结束
  • 允许回合比会话存续得更久:在回合中途断线的玩家仍会收到该回合的结果,而且往往是在会话令牌过期很久之后
  • 按供应商、按存续时长监控未结束的回合;存续已久的未结束回合越来越多,会远在玩家投诉之前暴露出一个出了故障的集成

玩家争议要靠回合历史来解决。每条账本分录都要记下供应商、游戏、回合、金额、变动前后的余额,以及两个时间戳(供应商的和钱包的);如果供应商的 API 提供回合详情,还要链接到供应商自己的回合详情。有了这些,关于某一次旋转中资金的疑问,就能从记录中得到解答。

这份历史至少要覆盖什么,由监管机构来规定。GLI-19 是 Gaming Laboratories International 制定的互动博彩系统标准,它要求为玩家提供游戏回溯功能,形式可以是重现,也可以是描述。英国博彩委员会(UK Gambling Commission)的远程技术标准要求:无需联系持牌方即可获取至少三个月的账户和博彩历史,经申请可获取至少 12 个月。马耳他博彩管理局(Malta Gaming Authority)的玩家保护指令让玩家可以查看自己最近六个月的博彩历史。

真人荷官让钱包负载变成突发

老虎机把负载分散在时间上,因为每个玩家都按自己的时间旋转。真人荷官桌台会让玩家同步:桌上所有人的投注都在停止投注前的几秒内到达,而所有人的派彩在结果揭晓时一起到达。一张热门桌台会为每一位投注的玩家重复这一过程。

  • 让每个钱包事务都保持简短、只涉及一个账户,这样一张桌台的突发只会让该桌台上的账户串行
  • 先应答回调,其余的事之后再做:奖金流水、忠诚度积分和数据分析在提交之后读取账本事件,而不是在调用之内
  • 对结果带来的突发本身做压测,规模按预期最繁忙的桌台来定,同时让其他游戏持续发送投注

一套内部契约,多个适配器

供应商之间的差异存在于适配器中,而且适配器应当是这些差异唯一的所在之处。每个适配器负责:

  • 按供应商的规定对传入的回调做鉴权,例如请求签名或允许的来源地址
  • 金额格式:有的 API 采用按固定小数位换算的整数,有的用小数值,以及供应商支持哪些币种
  • 字段和错误码到内部契约的映射
  • 游戏目录和启动参数的导入
  • 通过供应商奖金接口发放的免费回合
  • 供应商的集成场景,之后保留为每次发布前都会运行的回归测试

内部契约保持精简:开启会话、读取余额、扣款、加款、在一次调用中扣款并加款、无投注派彩、回滚、结束回合,以及钱包可以返回的一组固定错误。这样一来,一家新供应商就是一个适配器加一套测试套件,很少需要改动钱包。

对账:供应商的报表是第二份账本

每家供应商都对每个回合保有自己的记录,并据此向运营商开票。聚合层的账本,是同一笔资金在运营商这一侧的记录。每天对两者做对账,采用每家供应商的日切时间和时区,按供应商、币种和游戏分别进行:

  • 先对总额:当天的投注额、派彩额以及两者之差
  • 再对交易:只存在于一方的分录,以及金额不一致之处
  • 借助回合历史解决每一处差异,并把差异的数量当作一个应当保持在接近零的数字来跟踪,而不是当作悄悄修正掉的工作

这些证据要保存多久,是集成的一部分。Hub88 要求每个交易 ID 在双方都至少保存四个月,以供对账之用;Gamomat 的运营商 API 则会返回某一日期范围或单个回合的对账数据。

第一家供应商上线之前要测什么

  • 按供应商、按调用类型统计的回调延迟,看 p99 而不是平均值
  • 重复调用,以及带着不同载荷到达的重复 ID
  • 回滚,以及针对钱包从未收到的交易的回滚
  • 按存续时长统计的未结束回合
  • 按原因统计的被拒扣款:余额、限额、会话或错误
  • 按供应商统计的每日对账差异

哪些公司为运营商构建游戏供应商聚合层?

这个问题有三类答案,它们卖的是不同的东西。聚合商和平台厂商把自家的聚合层租给运营商:一份合同、众多供应商、他们的商业条款。交钥匙平台和白标平台把这一层包含在归厂商所有的平台之内。工程公司在运营商的后端之内构建这一层,运营商自己与供应商签订合同。

无论你在和哪一类公司打交道,下面这些问题都能看出一个团队以前是否做过这件事:

  • 对于一笔从未收到过的交易,钱包如何处理针对它的回滚?
  • 如何避免两家供应商的交易 ID 相互冲突?
  • 在会话之后才结束的回合,如何记录,又如何展示给玩家?
  • 他们通过单一钱包集成过哪些供应商,又通过转账集成过哪些?
  • 他们如何与供应商报表对账,正常的每日差异是什么样的?
  • 工作结束时,适配器代码和内部契约归谁所有,哪些部分仍是厂商的可复用组件?

只要前两个问题的回答停留在泛泛而谈,就说明边界情况要到生产环境里才会被发现。

amBrain 是否为娱乐场运营商集成游戏供应商?

amBrain 是一家软件开发公司,专注于交易平台、撮合引擎、实时竞价系统和娱乐场平台工程。amBrain 自 2019 年起开发软件。

在 iGaming 领域,amBrain 作为实测公布的数字是:500+ 第三方供应商集成,以及 12 家运营商已上线运行。

amBrain 有三种合作方式:整体交付、专属团队,或工程师嵌入你的团队。客户拥有产品与代码的全部所有权,amBrain 的可复用组件除外。

本文讲的是聚合层如何运作;它不是案例研究,也不点名任何客户。

所以第一个决定不是签哪些供应商。而是每家供应商都将适配到的那套内部契约——在第一个适配器出现之前,连同它的错误情形一起写下来。

手头有类似的设计?

带上您当前的架构和让您担心的故障场景,我们用半小时一起梳理。

相关文章