阅读主题
钱包与平台币
平台币适合在同一运营主体的多个游戏间提供统一余额体验。当前实现是本地演示钱包,尚未接通真实收款、提现或独立商户清结算。不能将演示余额当成已收现金。
单位与余额字段
Wallet 返回 {paid, bonus, frozen}。所有字段都是整数最小单位,演示换算为 100 单位 = 1 平台币 = 1 元。例如 paid: 1234 表示 12.34 付费平台币。展示时除以 100,计算与存储时使用整数。
| 字段 | 当前语义 |
|---|---|
paid | 充值或退款形成的付费余额 |
bonus | 充值赠送、月卡每日权益等赠送余额 |
frozen | 冻结余额字段;本版不提供完整冻结、解冻业务接口 |
钱包归属平台账号,同一平台账号跨游戏使用统一钱包;订单、商品、角色与优惠券仍按逻辑游戏隔离。平台共享余额不等于不同游戏可以读取对方角色或订单。
充值、消费与权益
- 从
sdk.center()读取kind: 'wallet_topup'商品。商品的walletCredit与bonusCredit是充值后增加的两类余额,不能从展示标题解析数值。 - 使用
paymentMethod: 'demo'创建并支付充值订单。充值不支持钱包支付和优惠券。 - 查询中心与流水,确认
paid、bonus分别增加对应整数数量。 - 购买游戏商品时可选择
paymentMethod: 'wallet'。服务端先扣赠币,再扣付费币,余额不足则整笔事务回滚。
例如实付 600 单位,付款前赠币 200、付费币 1000,付款后赠币 0、付费币 600。该订单退款时原样返还赠币 200 与付费币 400,不把赠币转成付费币。
月卡按已有有效期与当前时间的较晚者延长 30 天。有效月卡每日可领取 100 赠币,按 Asia/Shanghai 自然日、平台账号去重;在另一游戏或另一端重复领取仍会返回已领取。游戏商品和月卡按实际支付额累计成长值,充值订单不重复累计,避免充值后消费被算两遍。
ts
const before = await sdk.center();
console.log((before.wallet.paid / 100).toFixed(2));
// 用户明确领取后调用,勿在页面刷新时自动重复提交。
await sdk.claimDaily();
const after = await sdk.center();无有效月卡返回 PASS_REQUIRED,当天已领取返回 ALREADY_CLAIMED。页面应根据重新查询的 membership.dailyBenefitClaimed 更新按钮。
流水与核对
center.ledger 的每条记录包含 id、type、description、paidDelta、bonusDelta、orderId、createdAt。type 为 topup、purchase、refund 或 bonus;正数增加、负数扣减。并非所有权益流水都有订单号,orderId 可以为 null。
当前数据库以事务保证订单、余额、流水与资产一起成功或一起回滚,并为流水与审计设置禁止修改/删除的触发器。生产财务仍需增设真实支付通道账单、资金责任归属、差错处理与可审计对账,详见 生产接入。
退款检查
- 钱包消费退款按原扣款来源返还,重复退款不会新增余额。
- 充值退款回收该笔原始付费币和赠币;任一类已不足都拒绝,不能只看总余额。
- 月卡已领取每日赠币后拒绝退款;后续续费改变有效期时须先处理最新订单。
- 当前退款不会向真实支付渠道退现金,也不会调用外部游戏服扣除资产。
验收时记录操作前后钱包、订单与流水。检查余额变化等于本次流水两类增量,重复请求不重复增加流水,故意制造余额不足时订单与余额保持事务前状态。不要通过直接编辑数据库余额模拟正常充值。
实现依据
packages/contracts/src/index.ts:Wallet、LedgerEntry、Membership及整数单位注释。packages/server/src/platform.ts:钱包读写、payOrder、refundOrder、每日权益领取与成长值。packages/server/src/store.ts:SQLite 事务与流水、审计保护。