# 《铜钱弹江湖》技术架构与 6 周开发计划

> 版本：v0.1 · 2026-07-10  
> 目标：微信小游戏优先、抖音小游戏复用核心；H5 Demo 只验证产品因果  
> 正式服务端级别：**L2 轻服务端**，异步社交；不建设强实时 PVP 或同服 SLG

---

## 1. 架构结论

客户端负责输入、表现、可回放的局内模拟和购买意图；服务端负责所有有资产价值或竞争价值的事实：账户、云存档版本、资源结算、侠力、背包、卡池、支付、活动时间、赛季分组/排名与结算。

```text
微信/抖音小游戏客户端
  ├─ Core：固定步长物理、技能链、战斗表现、回放采样
  ├─ Meta：侠客/兵器/经脉/奇物/百侠谱、任务、商店
  ├─ Platform Adapter：登录、实名、防沉迷、支付、广告、分享
  └─ Telemetry：埋点队列、断网缓存、会话/实验上下文
                 │ HTTPS + 平台登录凭证
                 ▼
L2 云函数 / API
  ├─ Auth & Profile       登录换票、账户状态、适龄态
  ├─ Save & Inventory     版本化存档、资产账本、成长事务
  ├─ Battle Settlement    战斗票据、反作弊、幂等结算
  ├─ Payment              下单、回调验签、幂等发货、退款/对账
  ├─ LiveOps              配置、实验、卡池、活动与服务端时间
  ├─ Season               分组、榜单、结算快照、奖励邮件
  └─ Social               D3 协作、可选分享回流、宗门异步事件
                 │
                 ▼
托管数据库 + 对象存储 + 日志/告警
```

### 为什么不是 L3

- 战斗是本地 PvE；试剑榜比较经服务端校验的侠力、关卡与赛季积分，不需要帧同步。
- D3 木人王按玩家贡献快照累计，D7 试剑按 50 人同段位分组，均可由云函数处理。
- L3 的实时通信、常驻服、外挂对抗和人的值守成本没有产生足够新增价值；若未来要做实时组队，必须重新立价值评审，不在首版偷渡。

---

## 2. 客户端模块

| 模块 | 职责 | 权威性 |
|---|---|---|
| `physics` | 固定 60Hz 或 30Hz 逻辑步；圆形碰撞、反弹、阻尼、休眠、边界 | 可重演，不直接发资产 |
| `battle` | 房间状态、敌人、侠客印、队友技能链、掉落表现、撤离/深入 | 服务端最终结算 |
| `meta` | 五维展示、升级预览、侠力变化、欲望物预告 | 只读服务端资产；离线预览不发货 |
| `economy` | 本地报价缓存、消费确认、余额展示 | 服务端账本权威 |
| `save` | 本地快照、待提交命令、版本迁移、冲突提示 | 云端版本权威 |
| `platform` | 微信/抖音/浏览器适配，统一登录/支付/广告/分享接口 | 平台+服务端权威 |
| `telemetry` | 事件排队、批量发送、重试、实验桶 | 分析用途，不作为资产真相 |
| `ui` | 安全区、导航、弹窗、触控/键盘无障碍、降级表现 | 客户端 |

### 2.1 物理确定性

- 使用固定逻辑步长，渲染插值；禁止用每帧真实间隔直接积分。
- 位置、速度、角度和碰撞法线在结算票据中量化为整数或固定精度，降低设备浮点差异。
- 同一房间由 `battleSeed + contentVersion + inputTrace` 重演；服务端只抽查高价值/异常局，不逐帧跑全部普通局。
- 碰撞顺序就是技能顺序：同一逻辑步出现多碰撞时按 `timeOfImpact → entityId` 稳定排序。
- 低端机丢帧不允许改变逻辑步数；追帧设上限，超过则暂停并提示性能降级，不“快进”结算。

### 2.2 输入

- 单指按下确定起点，拖动确定反方向蓄力，松手发射；取消区在安全区外。
- 轨迹预览最多显示前两次反弹与首个可碰撞目标，减少技巧上限吞掉侠力。
- 可访问性：提供“瞄准辅助强/标准/关闭”、左手模式、降低动态、震动开关；键盘/鼠标仅用于 H5 评审。

---

## 3. 核心数据模型

所有表含 `createdAt/updatedAt`、审计来源与 schema 版本；金额以最小货币单位整数保存，时间用服务端 UTC 毫秒。

### 3.1 账户与存档

```ts
type PlayerProfile = {
  playerId: string;
  platform: 'wechat' | 'douyin';
  platformOpenIdHash: string;
  ageBand: 'unknown' | 'under8' | '8to15' | '16to17' | 'adult';
  antiAddictionState: string;
  saveVersion: number;
  revision: number;
  createdAt: number;
  lastSeenAt: number;
};

type PlayerSave = {
  playerId: string;
  revision: number;
  currencies: { coin: number; jade: number; stamina: number };
  dimensions: { hero: number; weapon: number; meridian: number; relic: number; codex: number };
  power: number;              // 服务端从资产重算，不信客户端
  roster: Record<string, HeroState>;
  inventory: Record<string, ItemStack>;
  codex: Record<string, CodexEntry>;
  quests: QuestState[];
  entitlements: Entitlement[];
  streak: StreakState;
  season: PlayerSeasonState;
  contentVersion: string;
};
```

### 3.2 资产账本

```ts
type LedgerEntry = {
  ledgerId: string;
  playerId: string;
  idempotencyKey: string;
  resource: 'coin' | 'jade' | 'stamina' | 'hero' | 'item' | 'entitlement';
  delta: number;
  reason: string;
  refType: 'battle' | 'order' | 'payment' | 'season' | 'mail' | 'admin';
  refId: string;
  balanceAfter: number;
  createdAt: number;
};
```

每次结算/购买/升级在同一事务内写账本、资产和新 revision。任何重试使用相同 `idempotencyKey`，返回既有结果，不重复发货。

### 3.3 战斗票据

```ts
type BattleTicket = {
  ticketId: string;
  playerId: string;
  seed: string;
  roomSetId: string;
  contentVersion: string;
  powerSnapshot: number;
  rosterHash: string;
  issuedAt: number;
  expiresAt: number;
  serverNonce: string;
};

type BattleClaim = {
  ticketId: string;
  clientClaimId: string;
  inputDigest: string;
  summary: {
    roomsEntered: number;
    roomsCleared: number;
    launchCount: number;
    allyHits: number;
    damage: number;
    hpRemaining: number;
    extracted: boolean;
    failed: boolean;
  };
  traceSample?: QuantizedInput[];
};
```

服务端根据票据、内容表、侠力快照和边界规则计算可接受奖励上限；异常局要求上传完整量化输入并进入隔离结算。

### 3.4 赛季

```ts
type SeasonGroup = {
  groupId: string;
  seasonId: string;
  week: number;
  tier: string;
  memberIds: string[];        // 正式服只放真人
  startsAt: number;
  endsAt: number;
  status: 'open' | 'locked' | 'settled';
};

type SeasonScore = {
  groupId: string;
  playerId: string;
  verifiedPower: number;
  bestRoom: number;
  contribution: number;
  score: number;
  revision: number;
};
```

锁榜后生成不可变快照，再发奖励邮件；重复结算不重复发奖。训练 AI 只存在 Demo/新手教学，正式榜单不得伪装为真人。

---

## 4. API 草案

| 方法 | 路径 | 作用 | 关键校验 |
|---|---|---|---|
| POST | `/v1/session/login` | 平台凭证换短期 session | 平台验票、封禁/年龄态、设备风险 |
| GET | `/v1/profile/bootstrap` | 存档、服务端时间、配置版本 | session、ETag |
| POST | `/v1/save/commands` | 提交升级/领取等命令 | revision、余额、幂等键、服务端重算侠力 |
| POST | `/v1/battles/ticket` | 取得房间 seed/内容版本 | 体力、账户态、并发票据上限 |
| POST | `/v1/battles/claim` | 战斗/撤离结算 | 票据、摘要上限、输入摘要、幂等 |
| POST | `/v1/ads/reward-intent` | 申请激励广告 nonce | 场景、频率、年龄/地区、冷却 |
| POST | `/v1/ads/reward-claim` | 广告完成后领奖 | 平台回执、nonce、幂等 |
| POST | `/v1/orders` | 创建平台支付订单 | SKU、年龄态、限购、服务端价格 |
| POST | `/v1/payments/callback/:platform` | 平台回调 | 验签、订单/用户/SKU/金额、重复回调 |
| GET | `/v1/season/group` | 分组、榜单、规则与奖励 | 服务端时间、匿名展示规则 |
| POST | `/v1/season/score` | 上传经校验成绩 | 侠力/战斗结算引用、速率限制 |
| POST | `/v1/social/coop` | 木人王贡献/里程碑 | 战斗结算引用、每日上限、幂等 |
| POST | `/v1/share/claim` | 好友回流后可选奖励 | 邀请关系、防自邀/刷设备、每日上限 |
| GET | `/v1/compliance/disclosure` | 概率、适龄、隐私、退款入口 | 公开可达、版本化 |

### 通用响应

```json
{
  "requestId": "req_xxx",
  "serverTime": 1783651200000,
  "revision": 42,
  "result": {},
  "error": null
}
```

客户端时钟只做动画；活动开始/结束、限购、每日刷新、体力恢复和赛季结算全部使用 `serverTime`。

---

## 5. 云存档与冲突

### 5.1 策略

1. 登录后先拉 bootstrap；本地有未提交命令则按原幂等键重放。
2. 所有命令携带 `expectedRevision`；不匹配返回最新快照与可重放命令列表。
3. 货币/物品/权益不做客户端 last-write-wins；只接受服务端事务。
4. UI 偏好可字段级合并；战斗临时状态最多恢复到房间开始，不恢复任意碰撞帧。
5. 每次 schema 升级保留迁移函数与回滚测试；迁移失败回到最近一份签名快照并告警。

### 5.2 离线边界

- 可浏览已缓存图鉴与练习关；不可产生可竞争资产、领取日常、刷新商店或提交排名。
- 网络中断时战斗可打完，claim 排队；票据过期则服务端按安全上限补发或转客服审计，不能客户端自行加余额。
- H5 Demo 的 `localStorage` 明确标为“本地云存档模拟”，不等同正式 M1。

---

## 6. 支付与发货

### 6.1 正链路

```text
客户端选择 SKU
 → 服务端校验年龄/限购/活动/价格并创建 order
 → 客户端调用平台支付
 → 平台服务端回调
 → Payment 云函数验签 + 核对 order/player/SKU/amount
 → 事务写 paid 状态 + ledger + entitlement/inventory
 → 客户端轮询/推送到账
```

### 6.2 硬规则

- 客户端支付成功回调只改变“等待到账”表现，不发货。
- `platformTransactionId` 与内部 `orderId` 均唯一；回调、轮询、补单共用同一发货幂等键。
- SKU 价格由服务端配置，客户端传入金额仅作显示核对。
- 首充限购、真实到期、月卡时长、战令赛季归属在同一事务内校验。
- 退款/撤销创建反向账本；已消耗虚拟物品走风险策略与人工审计，不静默负余额。
- 每日自动对账：平台流水、订单、账本、权益四方差异；异常 5 分钟告警，24 小时内人工关闭。
- Demo 中所有购买只改本地演示状态，按钮常驻“DEMO 模拟”，绝不调用真实支付。

---

## 7. 抽取与保底

- 概率表、保底规则、重复转化与免费获取路径均由版本化配置下发；客户端一级入口可查。
- 服务端使用可审计 CSPRNG；结果与概率版本、保底前后计数、订单/抽取券引用一起存证。
- 普通招募立项配置：S 级 3%、A 级 17%、B 级 80%，80 抽 S 级硬保底；每 10 抽至少 A 级。数值从经济 CSV 读取，后续调整必须版本化、公示且不清零既有保底。
- 未成年人账号默认关闭付费抽取入口；免费定向碎片和剧情侠客确保核心玩法可进入。
- 不使用“差一点抽中”的虚假轮盘；近失只用于战斗结果，不伪造随机结果轨迹。

---

## 8. 反作弊与赛季公正

| 面 | 检查 |
|---|---|
| 侠力 | 从服务端资产重算；客户端上传值永不直接入榜 |
| 战斗 | 票据 seed、配置版本、阵容哈希、合理伤害/速度/发射次数边界 |
| 物理 | 高价值/异常局抽样重演；量化输入；同 seed 差异告警 |
| 经济 | 资源只走账本；单日增量/消费速度/来源分布异常检测 |
| 榜单 | 分数必须引用已结算战斗；频率限制；锁榜快照；异常隔离榜 |
| 分享 | 防自邀、同设备批量、循环邀请、短时高频；奖励日上限 |
| 管理后台 | 双人审批高价值补发；全部操作审计；无直接 SQL 改资产 |

作弊处置分四级：静默采样 → 隔离匹配/榜 → 暂停资产结算 → 人工封禁。避免一次客户端异常直接误封。

---

## 9. LiveOps 配置

```ts
type ConfigBundle = {
  version: string;
  minClientVersion: string;
  startsAt: number;
  endsAt?: number;
  rollout: { percent: number; allowList?: string[] };
  economy: EconomyConfig;
  rooms: RoomSetConfig[];
  heroes: HeroConfig[];
  shops: SkuConfig[];
  pools: PoolConfig[];
  seasons: SeasonConfig[];
  experiments: ExperimentConfig[];
  signature: string;
};
```

- 配置先 schema 校验、经济模拟、内容引用检查、合规扫描，再签名发布。
- 支持 1%→10%→50%→100% 灰度、立即回滚、审计 diff；客户端只接受签名且未过期的 bundle。
- 新活动以填表+配置为主，不要求发版；新增代码能力才发客户端。
- 实验互斥：留存、IAA、IAP 三阶段不能交叉污染；同一玩家固定桶，跨设备一致。

---

## 10. 埋点与可观测性

### 10.1 每事件公共字段

`eventId, eventName, clientTime, serverTime, sessionId, playerIdHash, platform, appVersion, contentVersion, experimentIds, deviceTier, networkType, ageBand, consentVersion`

### 10.2 技术 SLO

| 指标 | 目标 |
|---|---:|
| 登录/Bootstrap P95 | ≤1.5s（不含平台外部耗时） |
| 普通云函数 P95 | ≤800ms |
| 战斗 claim P95 | ≤1.2s |
| 支付回调到可见到账 P95 | ≤10s |
| API 月可用性 | ≥99.9% |
| 结算重复发货 | 0 |
| 未处理对账差异 | 0 过夜 |
| 客户端无崩溃会话 | ≥99.5% |
| 低端机战斗逻辑帧 | ≥30fps，碰撞确定性通过基线回放 |

告警分为支付/资产 P0、登录/配置 P1、榜单/内容 P2。P0 自动关支付入口但保留免费玩法，避免资损扩大。

---

## 11. 性能预算

| 项 | 首版预算 |
|---|---:|
| 初包 | ≤8MB；平台分包后总资源按当期限制复核 |
| 首屏可操作 | 中端机暖启动 ≤2s；冷启动按平台实测 |
| 同屏碰撞实体 | ≤40；常态 ≤20 |
| 粒子 | 低端 ≤120；超预算合批/合并伤害字 |
| 纹理 | 图集化；单张关键背景按设备档降级 |
| 音频 | 短音效复用，长音乐流式/分包 |
| 内存 | 低端目标 ≤180MB；三房切换无持续增长 |
| 网络 | bootstrap gzip 后 ≤200KB；配置增量 ≤50KB |

320×568、390×844、430×932、平板与桌面窗口均做响应式；核心触控目标至少 44×44 CSS px，安全区不遮挡发射区。

---

## 12. 安全与隐私

- 只收集运营必需字段；分析 ID 去标识化；权限与 SDK 清单在隐私政策中逐项说明。
- 登录凭证、支付密钥只在服务端密钥管理，不进仓库/客户端/日志。
- API session 短期有效并轮换；高风险管理端强制 MFA、最小权限和操作审计。
- 日志脱敏 openid、身份证、手机号、支付标识；生产数据不可复制到个人开发机。
- 删除/导出请求有工单与审计；留存期限按法律、平台与财务要求确认。
- 供应链固定依赖版本、生成 SBOM、自动扫描许可证与高危漏洞。

---

## 13. 6 周计划

AI 产能按标准等效 30 人团队；计划的关键路径是产品决策、平台联调与审核，不以“人少”降级内容。

| 周 | 客户端/玩法 | 服务端/数据 | 内容/商业化 | 验收门 |
|---|---|---|---|---|
| W1 Demo | 确定性弹射、两队友技能链、Boss、撤/深入、五维本地原型 | API/数据模型评审；本地 mock | 欲望物、五表、90 天模拟、5 方向素材样片 | 10 秒理解、90 秒闭环、Demo smoke 全过 |
| W2 Alpha | 三章房间、侠客/兵器/经脉、图鉴、任务、性能分档 | 登录、云存档、账本、战斗票据/claim | D1–D7 内容、首充/月卡/战令 UI，不开真付费 | 无商业化留存构建；存档迁移与断网恢复 |
| W3 灰度候选 | 30 天内容最小集、广告 adapter、回放采样 | 赛季分组/榜、D3 协作、LiveOps、埋点 | 12 周配置、素材工厂、合规入口 | 无商业化灰度；D1/D7 决策门 |
| W4 灰度 | 全 90 天表驱动内容、设备/包体优化 | 支付沙箱、验单/幂等/退款、风控与监控 | 只按顺序开启 IAA 单变量；客服 SOP | 灰度版 ≤4 周；支付/资产 P0 演练 |
| W5 联调 | 双平台差异、辅助功能、最终 E2E | 真平台沙箱、对账、灾备、后台权限 | IAP 仍按实验门逐项开启；商店/概率/适龄审查 | 支付、云存档、赛季全链路通过 |
| W6 上线 | 崩溃/性能收口、商店包与回滚包 | 生产容量、告警值班、备份恢复演练 | 审核素材、AIGC台账、首季运营手册 | 正式上线 ≤6 周；平台审核为外部尾项 |

### 13.1 发布门

- W1 未过手感/理解门：停在玩法层，禁止继续堆 meta。
- W3 留存未达门：禁止开 IAA/IAP；修核心循环，每次一个变量。
- 支付幂等、退款、对账任一失败：支付功能不上线，免费/IAA 版本可独立灰度。
- 赛季榜存在可复现作弊：锁榜功能下线，不用本地分数顶替。
- 合规材料/版号/备案/平台资格未齐：不接 IAP，不以“技术已完成”替代外部许可。

---

## 14. Demo 与正式版边界

| 能力 | H5 Demo | 正式版 |
|---|---|---|
| 战斗 | Canvas 本地真实输入/碰撞 | 确定性引擎+票据结算+抽样重演 |
| 存档 | 独立 localStorage，显式模拟 | L1/L2 云存档、revision、迁移/冲突 |
| 榜单 | 明标训练 AI | 50 人真人分组、服务端校验与结算 |
| 支付 | 本地模拟，不联网、不扣款 | 平台下单、服务端回调验单、幂等发货 |
| 广告 | 按钮+延时模拟并标注 | 平台激励回执+服务端 nonce |
| 活动 | 固定演示数据 | 配置化、灰度、回滚、服务端时间 |
| 合规 | 入口与文案占位 | 实名、防沉迷、适龄、概率、隐私、退款全接入 |

Demo 证明“这一套产品因果能交互”，不证明云服务、真人生态、支付资格、留存或收入已经成立。
