18 KiB
18 KiB
1. 文档目的与读者
本文件为 内部使用 的完整说明,用于:
- 梳理积分商城与 PlayX 之间的 全量业务流程(含当前选型与备选方案)。
- 统一后台实现口径(资产计算、订单状态机、幂等、重试、对账)。
- 为后续版本扩展(实时 webhook、同步按钮、PlayX 拉取模式)预留空间。
对外给 PlayX 的精简版请参考:PlayX-对接文档(积分商城).md。
2. 当前选型概览(V1.0)
- 主键标识:
user_id(贯穿每日推送、资产、订单、发放接口)。 - 集成方式:
- 前端:商城 H5 以 Iframe 嵌入 PlayX,postMessage 传 token/session。
- 后端:商城独立服务,通过 REST API 与 PlayX 通讯。
- 数据来源:
- 资产池:仅使用 每日 Cron 推送(T+1) 的历史输赢与充值数据。
- 不引入实时充值/流水 webhook 作为资产来源。
- 发放模式:
- 商城在红利/提现下单后,直接调用 PlayX 发放接口(Bonus Grant / Balance Credit)。
- PlayX 侧每 10 分钟 Cron 执行 5.9 adjustment / 最终入账。
- 幂等责任分工(方案 A,与对外文档一致):
- PlayX:对 Bonus Grant / Balance Credit 按
externalTransactionId严格幂等——同一单号重复请求不得产生第二笔发放;须返回与首次受理一致或可识别的幂等结果(具体 HTTP 体字段由联调约定)。 - 商城:为每笔红利/提现生成全局唯一
externalTransactionId;收到 HTTP 200 且status="accepted"后不再向发放接口重放;对网络超时等“未知是否受理”场景,可在有限次内重试同一externalTransactionId,依赖 PlayX 幂等保证不双发(见第 6 章)。
- PlayX:对 Bonus Grant / Balance Credit 按
3. 角色、系统与对象
3.1 角色
- 会员:在 PlayX 内通过 Iframe 使用积分商城。
- 运营/客服:使用商城后台管理商品、订单、调账。
- PlayX 平台:数据源与权益发放执行方。
3.2 主要对象与前端看板展示映射
- 目前可提现(现金):
- 前端展示专用虚拟字段,由可用积分按固定比例折算(如:10 分 = 1 元),用于给玩家呈现直观价值,非底层独立资产。
- 待领取积分 (LockedPoints):
- 定义:基于昨日玩家亏损转化来的“保障池”,未领取前不可消费。
- 数据源:PlayX 每日推送的
Yesterday Player Win loss(取绝对值 × 返还比例)。
- 可用积分 (AvailablePoints):
- 定义:玩家当前拥有的、可立即抵扣兑换和提现的真实积分资产。
- 交互消耗:所有兑换、提现操作均扣减该字段。
- 今日可领取上限 (TodayLimit):
- 定义:限制玩家当日最多能“挽回”多少积分。
- 数据源:PlayX 每日推送的
Yesterday Total Deposit(昨日总充值 × 解锁比例)。
- 今日已领取 (TodayClaimed):
- 定义:记录玩家当日累计已领取的积分规模,辅助校验上限,每日重置。
- 订单 (Order):
- 类型:BONUS / PHYSICAL / WITHDRAW
- 状态:PENDING / COMPLETED / SHIPPED / REJECTED
4. 端到端流程(内部视角)
4.1 登录与会话建立
- 会员在 PlayX 点击“积分商城”入口。
- 父页面加载 Iframe,商城前端进入“连接中/鉴权中”态。
- PlayX 前端通过 postMessage 发送:
token或 session 标识。
- 商城前端将 token 传给后端,后端调用 PlayX 的 Token Verification API 验证身份:
- 请求参数:
token:接收到的用户会话凭证。request_id:系统发起的鉴权校验流水号。
- 响应参数:
user_id:解析出的玩家在平台的唯一标识主键。username:仅用于前端展示的昵称。token_expire_at:用于判断并在濒临过期时触发换取新 Token(无感续期)。
- 请求参数:
- 商城根据
user_id加载本地资产与订单数据,渲染首页。
安全与会话续期要点:
- 安全拦截:不信任前端传入的
user_id,必须通过 Token Verification API 获取可信user_id。 - Token 续期:如果用户在商城停留过久导致 Token 过期(接口返回
401 / INVALID_TOKEN),商城前端需通过postMessage通知 PlayX 父页面重新派发新 Token 以实现静默续期;若无法自动续期,则需弹窗引导用户重新进入商城。
4.2 每日 T+1 数据推送与资产入池
数据来源:PlayX 每日 Cron。
- 交互字段说明(T+1 核心输入):
date:归属业务定日(用于限定该批数据的生效周期)。user_id:玩家平台唯一标识主键。yesterday_win_loss_net:昨日净输赢金额(核心数据源:负数绝对值作为计算新增保障积分类的基准)。yesterday_total_deposit:昨日总充值(核心数据源:作为计算今日领取该积分上限的阈值基准)。lifetime_total_deposit/lifetime_total_withdraw/username:非运算强制性字段,用于冗余显示或阶层判断预留。
商城处理逻辑:
- 按
user_id + date幂等入库,避免重复处理。(注:需与 PlayX 明确date的时区定义,如 UTC+8 等)。 - 根据业务规则计算:
新增保障金 = ABS(yesterday_win_loss_net) * 返还比例(仅当 yesterday_win_loss_net < 0 时产生)。今日可领取上限 = yesterday_total_deposit * 解锁比例。注意:今日上限每日独立计算,不结转至次日。
- 将新增保障金累加到
LockedPoints,更新TodayLimit。
数据修正机制:
- T+1 推送不支持覆盖更新(冲正)。如果 PlayX 上游数据算错导致推送有误,商城在二次推送时会触发去重拦截(
deduped)。此类异常数据统一由商城后台人工调账处理。
4.3 领取流程(从待挽回转化为可用)
触发:会员在首页核心看板上查看领取进度(基于 昨日充值 计算),如果进度符合预期,点击“立即领取”。
- 前端交互:
- 判断逻辑:若
昨日充值(即 TodayLimit)均不足导致上限不够,按钮可能置灰并提示“昨日存款不足,无法全额领取”。 - 操作反馈:点击后从底部呼出二次确认层(“将待领取积分划转为可用积分后,即可兑换或提现。确定领取?”)。
- 确认层点击“确定”后发出后端请求。
- 判断逻辑:若
- 后端校验条件:
LockedPoints > 0TodayLimit - TodayClaimed > 0
- 后端计算与执行:
canClaim = min(LockedPoints, TodayLimit - TodayClaimed)- 原子更新数据库:
LockedPoints -= canClaimAvailablePoints += canClaimTodayClaimed += canClaim
- 防重与幂等:
- 接口入参包含
claim_request_id,同一claim_request_id重复提交不重复扣减。
- 接口入参包含
- 前端成功响应:
- 后端处理完成后,前端弹出“领取成功,积分已到账”状态框。
- 即时刷新看板中的
待领取积分与可用积分与目前可提现现金。
- 积分有效期说明:
- V1.0 版本积分无有效期限制,
LockedPoints和AvailablePoints永久有效并持续累加,后续视财务成本压力再引入年底清零/周期过期机制。
- V1.0 版本积分无有效期限制,
4.4 红利兑换(BONUS)
- 会员在前端选择红利商品(配置来自后台商品管理)。
- 前端展示二次确认弹层(金额、流水倍数、说明),并需在 UI 上显式提示会员:“发放预计需等待约 10 分钟内到账”。
- 提交后,前端进入“兑换中”类似状态,不可直接提示“兑换成功”,随后商城后端执行:
- 校验积分余额是否足够。
- 校验商品状态(上架、库存)。
- 校验订单状态(防重复提交)。
- 创建订单:
type = BONUSstatus = PENDINGuser_id- 商品信息 & 消耗积分
- 原子扣减
AvailablePoints。 - 生成
externalTransactionId(例如BONUS_ORD{订单号})。 - 调用 PlayX Bonus Grant API(核心透传字段,详见外部对接文档):
externalTransactionId:本单派发流水号(防重:用于要求下游强制幂等拦截)。user_id:玩家标示。amount:红利发放切实的现金面值。multiplier:这笔款项后续提款的流水约束倍数。rewardName:展示给玩家此笔红利来源名称。category:便于平台统计对账的红利业务大类。
- PlayX 返回:
- 若 HTTP 200 且
status = "accepted":- 记录
playx_transaction_id。 - 订单保持 PENDING(等待对方系统最终发放)。
- 发起请求动作不再重试。但商城侧需定时调用 PlayX 提供的 交易状态查询 API 轮询确认该订单最终结果,成功则转
COMPLETED,失败则转REJECTED并退分。
- 记录
- 否则:
- 记录失败原因。
- 进入“可重试队列”(自动/人工重试,见第 6 章)。
- 若 HTTP 200 且
4.5 实物兑换(PHYSICAL)
- 会员选择实物商品并填写收货信息。
- 商城后端:
- 校验库存/积分。
- 创建 PENDING 订单,扣减
AvailablePoints。
- 后台处理:
- 发货:录入物流公司与单号,状态 → SHIPPED。(可选:调用 PlayX Inbox API 给用户发送发货通知站内信)。
- 驳回:录入驳回原因,状态 → REJECTED,并退回积分。(可选:调用 PlayX Inbox API 告知用户驳回原因)。
4.6 提现回平台余额(WITHDRAW 操作逻辑)
本流程旨在将兑换所得的虚拟积分,按照规定“提现”为充入 PlayX 平台账户的真实金额。
- 前端选择与展示:
- 会员在首页或“提现到平台”类别列表中选择特定提现档位(如:提现 100 元,需要 1000 积分,1倍流水要求)。
- 点击“提现”按钮后,前端唤出底部二次确认弹层。
- 弹层内容展示所选档位所需消耗的积分值以及对应的流水要求倍数,等待二次确认提交。
- (前端同时需在弹层或说明中向用户提示:提现申请预计约 10 分钟在平台入账)。
- 后端可用性校验:
- 用户确认后,前端请求后端。商城后端比较当前用户的
AvailablePoints是否>= item.points。如果不足,阻断流程并返回前端积分不足的报错浮层。
- 用户确认后,前端请求后端。商城后端比较当前用户的
- 资产扣减与订单落库:
- 原子扣减数据库内该会员的
AvailablePoints。 - 创建 WITHDRAW 暂挂订单(状态
PENDING),记录该单提现对应的amount与multiplier。 - 生成外部交易单号
externalTransactionId(如WITHDRAW_ORD{订单号})。
- 原子扣减数据库内该会员的
- 调用 PlayX API 发放(核心参数解析):
- 商城发包调用 PlayX 的 Balance Credit API:
externalTransactionId:本提现申请的订单号(提现防重唯一拦截键)。user_id:发起提现的玩家 ID。amount:要充入平台余额池的真金面值。multiplier/turnover_rule:该笔提现资金入账后锁定的打码流水倍数条件。
- 商城发包调用 PlayX 的 Balance Credit API:
- 异步等待终态与 UI 回显:
- 收到 API
accepted响应后,商城将不间断返回前端“提交成功,预计 10 分钟内处理”。 - 商城内部保持该订单为 PENDING,并进入定时轮询状态,监控 PlayX 10 分钟 Cron 执行后的“最终业务发货结果”,闭环完成后才转入 COMPLETED 或对失败按规则退分。
- 收到 API
5. 扩展与备选方案(暂不对外)
本章为 扩展设计/备选方案,当前版本不对 PlayX 提出实现要求,只在内部保留。
5.1 实时充值 webhook(备选)
用途:让“今日可领取上限”不仅依赖 T+1 数据,还能实时响应充值行为。
示例设计:
- PlayX 在充值成功后,调用商城的充值 webhook:
- 字段:
user_id、amount、transaction_id、occurred_at。
- 字段:
- 商城:
- 以
transaction_id幂等入库。 - 更新“当日实时充值统计”,供风控或前端展示使用。
- 以
当前状态:
- V1.0 不启用此对接;所有领取逻辑仅基于每日推送(T+1)。
5.2 外部积分来源 webhook(任务/轮盘)
用途:把 PlayX 任务、幸运轮盘等活动产出的积分汇总到商城。
示例设计:
- PlayX 调用 webhook:
- 字段:
user_id、points、source、transaction_id。
- 字段:
- 商城:
- 以
transaction_id幂等增加AvailablePoints或某个“活动积分池”。
- 以
当前状态:
- V1.0 不做接入;防止资产口径复杂化。
5.3 “同步额度”交互逻辑(手动拉取实时充值)
功能目的:由于积分商城的基础计算依赖的是 T+1 每日推送,如果不做任何补充,今日充值的玩家将无法即刻提升“今日可领取上限(TodayLimit)”。因此原型中设置了“同步额度”按钮,作为手动拉取实施更新的一种补救路径。
前端交互逻辑:
- 用户在首页面板点击“同步额度”次要操作按钮。
- 前端短暂 loading,调用后端接口拉取后,弹出轻量级反馈:“已同步最新额度”。
- 页面数据看板数字重新渲染刷新。
后端业务逻辑选型推荐:
- 方案 A(建议,商城做拉取请求):
- 会员点击同步按钮,商城后端拦截并向 PlayX 系统调用一个**“查询今日实时余额/重算存款 API”**。
- 获取到最新存款后,累加或覆盖当前的
TodayLimit。
- 方案 B(PlayX 控制权):
- 点击后,通过 iframe 的
postMessage向父级 PlayX 窗口发送同步指令。 - PlayX 在自身域内统计今日所有游戏存款流水进行汇总归集(甚至一键转账入主钱包的操作)。
- 处理完成后 PlayX 主动请求积分商城的
更新 webhook来给TodayLimit加额,最后前端获取成功事件刷新。
- 点击后,通过 iframe 的
- 当前定案落地方向:
- 根据原型要求,本功能必须落地。推荐使用方案 A。商城侧需准备一个接受通知的 API,或 PlayX 需要支持实时提供玩家当日总存款的只读 API,以供点击拉取。对于 V1.0 对外文档里若不打算实现,需与 PlayX 进一步交涉决定是否阉割掉此按钮。
5.4 发放模式备选:PlayX 定时拉取
备选方案:
- 由 PlayX 每 10 分钟调用商城查询接口,拉取待发放订单列表,然后自行发放。
需要新增:
- 商城提供“待发放订单列表”接口(分页、过滤、幂等标记)。
- 双方需要就“已拉取但未发放”、“重复拉取”等边界做严格定义。
当前选型:
- 考虑到复杂度与 PlayX 当前发放系统形态,最终选择 商城主动调用 PlayX 发放 API 的模式,拉取模式仅保留在内部文档中作为备选。
6. 幂等、重试与状态机(内部实现口径)
6.1 幂等键
- 每日推送:
user_id + date。 - 充值/外部积分 webhook(如启用):
transaction_id。 - 领取:
claim_request_id。 - 红利/提现发放:
externalTransactionId。
6.2 发放请求状态机(商城内部)
针对每个订单(BONUS/WITHDRAW),在商城内部维护发放子状态,例如:
NOT_SENT:未发送给 PlayX。SENT_PENDING:已发送,等待 PlayX 响应。ACCEPTED:收到 HTTP 200 且status = "accepted"。FAILED_RETRYABLE:失败且可重试(如超时、上游错误)。FAILED_FINAL:最终失败(达到重试上限或 PlayX 返回不可恢复错误)。
关键规则:
- 只有在
NOT_SENT或FAILED_RETRYABLE状态下才允许“再次发送”。 - 一旦进入
ACCEPTED,不得再发请求(自动或人工)。 - 订单业务状态(PENDING/COMPLETED/REJECTED)与发放子状态之间要有清晰映射:
ACCEPTED+ 对账确认成功 →COMPLETED。FAILED_FINAL→REJECTED(并退积分)。
6.3 重试策略(内部)与防重底线
- 前提:PlayX 已承诺按
externalTransactionId严格幂等(方案 A)。在此前提下,读超时后使用同一externalTransactionId的有限次自动重试是安全的。 - 自动重试:
- 仅针对网络错误、Read Timeout(读超时)、
PLAYX_UPSTREAM_ERROR等,且尚未收到 HTTP 200 +status="accepted"。 - 建议间隔:1min / 5min / 15min,最多 3 次;每次重试必须使用原订单的同一
externalTransactionId,不得生成新单号冒充新单。
- 仅针对网络错误、Read Timeout(读超时)、
- 人工重试:
- 仅允许在
FAILED_RETRYABLE状态下触发。 - 每次需记录
retry_request_id、操作者、原因。若自动重试耗尽仍失败,可先通过 交易终态查询 API 核对再决定是否人工干预。
- 仅允许在
- 绝不重试场景:
- 发放请求已明确收到
status = "accepted"(后续只走 5.5 轮询与客诉流程,不向发放接口重放)。 - 明确业务拒绝类错误(如参数非法、规则不满足)。
- 发放请求已明确收到
7. 对账与问题排查
- 对账来源:
- 商城订单表(含 externalTransactionId、playx_transaction_id)。
- PlayX 提供的对账/流水查询(如有)。
- 常见问题场景:
- 商城显示 REJECTED 但会员反馈已收到红利:需检查是否在“发放后回滚积分”链路出错。
- 商城显示 PENDING 时间过长:需排查 PlayX 侧 10 分钟 Cron 是否正常。
8. 与对外文档的关系
- 本文档:覆盖“能想到的所有对接与流程设计”,供产品、后端、运营、商务内部统一认识。
PlayX-对接文档(积分商城).md:- 仅暴露 PlayX V1.0 必须提供/实现的部分。
- 承诺最小闭环,不在主文中提及实时 webhook、同步按钮、拉取模式。
- 同步额度等能力若产品仍要落地,以本文 5.3 与商务/PlayX 结论为准;对外文档不写不代表产品一定不做。