26 KiB
金字塔活动后端设计
版本:V1.0
日期:2026-09-28
状态:设计对应实现已落地到本地,未上线;实现差异和验证范围见开发说明。
产品依据:金字塔活动 PRD
统一入口修订:为减少 Laf 云函数名额,所有活动请求改为 POST /pyramid/api,请求 JSON 必须包含下文对应的 action,其他业务参数及 response 保持原含义。delivery_save 使用 phase:prepare|save;管理员使用 action:admin,operation:具体操作,adminToken。只部署 pyramid/api 和不开放 HTTP 的 pyramid/jobs,原内部模块合并为 api 文件中的普通函数。支付下单仍走原有两个微信接口。旧拆分路由已移除,测试环境迁移顺序见后端 README。
1. 范围与接入原则
本方案覆盖活动状态、支付机会入账、不放回抽奖、终点领取、前端发货确认和跨期补发。
下单逻辑必须放在现有 /wx/orderPaySig 和 /wx/iosorderPaySig,不新增 /pyramid/order。活动状态合并到 /pyramid/api(action:list),不新增独立 /pyramid/query。
活动后端确定资格、中奖结果和奖励内容;客户端按授权发放道具并保存,再确认到账。本方案不将产品要求擅自改成后端离线直接增加余额。
本文的集合名、模块拆分、错误枚举和时间字段格式为实现建议;已确认的业务规则以 PRD 为准。没有新增跨期次数、自动退款、重复轮次或后台自动代抽。
实现补充:活动进度、请求回执和授权合并到单个 pyramid_players 玩家期次文档,以 revision CAS 完成原子写入;库存收据嵌入 users.pyramidDeliveries。新增 /pyramid/api(action:delivery_save) 承载前端计算后的库存保存与收据原子写入,再调用确认接口,避免保存成功但确认丢失导致重复发奖。具体参数以独立后端 laf-cloud/functions/pyramid/README.md 为准。支付主动渠道查单/关单适配尚未验证,当前持久化回调恢复与人工凭据关单不能视为渠道能力已经验收。
2. 现有代码核查与兼容要求
核查对象为独立后端工作区 C:/Users/NK/Desktop/workspace/server。MatchMaster/server 是另一份目录,实施时应先确认实际部署仓库,不能混用两份实现。
| 现有位置 | 已核查事实及接入要求 |
|---|---|
laf-cloud/functions/wx/orderPaySig.ts |
接收 itemid、itemCount、itemPrice;已有活动分支转交专用支付模块,可增加金字塔分支 |
laf-cloud/functions/wx/iosorderPaySig.ts |
同样接收上述字段;金字塔必须接入此入口,复用现有平台支付路由 |
| 上述两个下单入口 | 当前签名响应为 paySig、signature、signData、outTradeNo;金字塔分支应兼容其结构 |
laf-cloud/functions/wx/getPayInfo.ts |
主要读取本地订单状态;“充值未成功”不能直接解释为支付平台终态失败 |
laf-cloud/functions/goldMiner/service.ts |
存在发奖授权、确认和跨期待发列表的后端参考,不能据此认定客户端已完成接入 |
laf-cloud/functions/login.ts |
有普通订单补发;金字塔需要专门的授权恢复入口,不能当普通商品再次发奖 |
客户端 assets/Script/module/Tool/GameTool.ts |
存在客户端增加余额后上传保存的流程 |
后端 laf-cloud/functions/userCoin.ts |
当前保存客户端完整余额;没有天然提供奖励授权与余额写入的原子去重 |
对既有支付通用分支保持兼容。活动查询返回 itemId,调用现有支付接口时映射为小写 itemid。两者表示同一支付商品,不是奖励格子编号。
3. 服务端不变量
- 每个玩家每期一份进度,从第一层开始,仅完成一轮。
- 同一玩家同一期最多一个未决订单;未决不是失败。
- 每笔成功订单最多记入一次机会,机会绑定订单期次和层数。
- 有可用机会或当前期次待确认发奖时,不能创建新的购买订单。
- 每次抽奖扣一次机会、获得一个格子;一个格子只获得一次。
- 当前层目标格子可有多个,抽中任意一个立即推进层数。
- 扣次数、中奖记录、发奖授权和升级必须构成一次原子状态变化。
- 第六层无购买和抽奖,只能领取剩余奖励。
- 已确认到账的奖励不能再次发放;未确认奖励不能因到期被删除。
- 同一奖励在正常领取、重试、活动结束补发之间只能归属于一个有效授权。
- 支付成功事实与机会是否有效分开保存;过期机会不代表支付失败。
4. 数据设计
4.1 期次配置 activityConfigs
2026-09-29 实现调整:统一复用 activityConfig/store,外层为 activityId:pyramid, recordType:version, configVersion, status:published, enabled, effectiveFrom, publishedAt,下表业务参数存放在 config 内。同一活动版本不可覆盖;同一期更新版本也不改变起止时间或已有玩家快照。enabled:false 仅停止新参与,已参与玩家继续使用 pyramid_players.config。配置发布仍走 /pyramid/api 的管理员 publish 操作;公共 /activityConfig/list 已注册金字塔,列表查询不创建参与记录。
旧 pyramid_periods 不再用于运行时读写;后端提供 pyramid/migrate-config.cjs(默认只读预检)和迁移说明,将旧配置复制到公共集合,保留玩家、订单及发奖记录。此调整仅完成本地开发,环境升级需先迁移旧配置并更新已有云函数。
| 字段 | 含义 |
|---|---|
periodId |
唯一期次编号 |
startAt / endAt |
UTC 毫秒时间戳,全服统一;区间为 [startAt, endAt) |
configVersion |
固定配置版本 |
levels |
六层配置;第一至第五层含支付商品、价格及奖励格子,第六层含固定奖励 |
levels[].rewards[] |
rewardId, goods[{id,count}], up, weight;权重仅用于前五层 |
建议开期后冻结配置,并为订单、授权保存必要快照。校验六层结构、格子 ID 在本期内唯一、道具数量为正整数、金额为正整数分;前五层每层至少有一个可抽中的目标格子。
建议所有参与随机的格子使用正的有限权重,优先采用正整数权重,禁止 NaN、负数、全零奖池。此项为配置约束建议;如未来需要零权重格子,须单独定义其只能终点领取等含义,不静默引入本期。
4.2 玩家进度 pyramid_players
以 (uid, periodId) 为唯一键,建议将该玩家当期的有限状态放入同一记录,便于原子更新:
{
uid, periodId, configVersion,
currentLevel: 1,
revision: 0,
completed: false,
settledAt: null,
pendingOrderId: null,
credits: [{ orderId, level, status, consumedByRequestId }],
rewards: [{ rewardId, gain, deliveryStatus, grantId }],
grants: [{ grantId, source, rewardIds, goods, status, createdAt, confirmedAt }],
operations: [{ requestId, action, payloadHash, resultSnapshot, committedAt }]
}
记录结构是逻辑模型,实施时需核验文档大小、索引及数据库原子更新能力。拆分集合时必须补足事务或可靠恢复机制,不能把原子要求降为顺序写几个集合。
credits.status:available | consumed | expired。是否已记入通过orderId去重,不能只保存一个无法追溯的数字。drawCount是当前期次、当前层有效available机会数量的投影,正常为 0 或 1。gain=false时deliveryStatus=not_eligible。gain=true时deliveryStatus=unclaimed | pending | delivered。- 抽中格子直接变为
gain=true, pending,同时生成授权。 - 到达第六层时,尚无资格的格子变为
gain=true, unclaimed,既有pending/delivered格子保持原状态。 completed仅在第六层且本期全部奖励均为delivered时为 true。未通关玩家的已中奖奖励全部发完,不算完成本期。
4.3 通用订单 order 的活动扩展
复用原订单,不另造一条支付账本。建议扩展:
{
activityType: "pyramid",
uid,
pyramid: { periodId, level, configVersion, startAt, endAt },
itemid, itemCount: 1, goodsPrice,
outTradeNo,
paymentStatus, // pending | succeeded | closed | failed
firstVerifiedAt,
fulfillmentStatus, // pending | credited | expired | exception
creditedAt,
exceptionReason
}
保留现有通用字段,活动状态不能直接复用含义不同的旧 state 数字。credited 表示机会曾经入账,即使之后被使用或到期,也不改成“没有付过款”;具体机会状态从玩家记录读取。
firstVerifiedAt 为服务端首次可信核验成功的持久化时间,不使用客户端时间,也不直接等同于平台付款时间。首次在活动结束后核验成功的,履约为 expired,不产生可用机会。
4.4 发奖授权
{
grantId, periodId,
source: "draw" | "final_claim" | "expiry_settlement",
rewardIds,
goods: [{ id, count }],
status: "pending" | "delivered",
createdAt, confirmedAt
}
授权内容生成后固定。可以合并同种道具数量,但必须保留来源格子列表。不同授权中不得出现同一玩家同一期的同一个格子。补发既有 pending 格子时返回原授权,不另建 expiry_settlement 授权覆盖它。
5. API 公共约定
- 新活动接口建议使用 POST JSON,身份参数为
uid, token;token 与玩家归属由后端校验。 - 沿用返回信封:成功
{ code: 1, data, msg };失败{ code: 0, data: null, msg, errorCode }。支付适配如需其他已有包装,应保持客户端兼容。 - 新状态响应统一提供服务端时间;金额使用整数分,时间使用 UTC 毫秒。
- 下单、抽奖、终点领取携带
requestId。同一业务动作网络重试沿用同一个值,不得每次重试重新生成。 - 幂等范围为
(uid, periodId, action, requestId);同键不同参数返回IDEMPOTENCY_CONFLICT。 - 已成功动作的重试先查原结果,再判断当前时间及层数;不能因已升级或到期而丢失原中奖结果。
- 前端不上传最终中奖格子、随机结果或可信奖励数量;商品价格由后端配置确定。
6. API 契约
6.1 /pyramid/api(action:list):完整活动状态
请求:{ action:"list", uid, token, periodId? }。不传期次返回当前期,或尚未开始的最近一期;没有可展示期次时返回 data=null,不虚构一期。历史期次查询仅用于读取状态,不能恢复已过期机会。
响应主体:
{
periodId, startAt, endAt, serverTime,
status: "not_started" | "active" | "ended",
currentLevel, drawCount, completed,
canPay, canDraw, canClaimFinal,
revision,
pendingOrder: null | { orderId, paymentStatus },
pendingGrants: Grant[],
levels: [{
level,
itemId, // 第六层为 null
itemPrice, // 第六层为 null
rewards: [{
rewardId, goods: [{ id, count }], up,
gain, deliveryStatus
}]
}]
}
操作能力依据同一状态快照计算,前端仍可能拿到过时响应,所以操作接口必须再次校验。权重由后端配置保存,当前契约不要求在列表中返回。
canPay = 活动有效 AND 层数<=5 AND drawCount=0
AND 无未决订单 AND 无本期待确认发奖 AND 未完成
canDraw = 活动有效 AND 层数<=5 AND drawCount>0
AND 无未决订单 AND 无本期待确认发奖
canClaimFinal = 活动有效 AND 层数=6 AND 存在unclaimed奖励
AND 无未决订单 AND 无本期待确认发奖
6.2 /wx/orderPaySig、/wx/iosorderPaySig:下单接入
两个入口识别后端配置登记的金字塔商品后,进入同一活动下单服务;不得依赖可被伪造的客户端活动标记绕过验证。
金字塔分支请求字段:
{
uid, token, activityType: "pyramid",
itemid, itemCount: 1, itemPrice,
periodId, level, requestId
}
itemid 对应列表中的 itemId;itemPrice 即使为兼容旧调用而传入,也不得成为后端签名金额的依据。商品须匹配服务端当前层配置,金额从该配置读取;数量固定为 1。
新增订单前校验活动时间、层数、次数、发货状态及玩家身份。存在未决订单时恢复原订单,不创建第二笔。不同平台重复调用也不能产生两笔有效订单;无法复用支付参数时返回原订单状态并引导查单,不重新开单。
响应保留原 paySig, signature, signData, outTradeNo 等支付字段;可以追加 periodId, level。后续活动接口中的 orderId 统一使用 outTradeNo,不引入另一个客户端订单编号。
幂等重试若原订单已支付成功,返回该订单及恢复提示,不再要求付款。只有可信确认原单失败或关闭后,才允许新的购买动作创建另一订单。
6.3 /pyramid/api(action:query):支付状态与履约查询
请求:{ action:"query", uid, token, orderId }。
{
orderId, periodId, level,
paymentStatus: "pending" | "succeeded" | "closed" | "failed",
fulfillmentStatus: "pending" | "credited" | "expired" | "exception",
creditStatus: null | "available" | "consumed" | "expired",
drawCount, serverTime,
retryAfterMs
}
先验证订单归属,再通过本地持久化状态与必要的渠道主动查单恢复结果。drawCount 仅表示该订单绑定期次和层数在当前时间的有效剩余次数,不能直接覆盖另一期页面;前端必须同时核对期次与层数。
回调和主动查单共用履约服务。网络错误、超时、未收到回调、支付弹窗取消不直接产生 failed。只有渠道适配能证明为不可继续支付的终态,才能返回 closed/failed 并解除未决锁。
前台轮询应退避并遵守 retryAfterMs,退出页面可停止前台请求,但不删除服务端订单锁;重进、重登和后台查单可以继续恢复。具体间隔及后台查单频率作为运行参数确定。
6.4 /pyramid/api(action:draw):抽奖
请求:{ action:"draw", uid, token, periodId, level, requestId }。
响应:{ requestId, rewardId, goods, up, previousLevel, currentLevel, drawCount, grant, revision, serverTime }。
处理顺序:读取已成功的幂等结果;若没有,再检查活动有效、请求层数与当前层一致、有本层机会、无未决订单及待确认发奖。按剩余权重在服务端开奖,一次原子提交完成扣机会、记录中奖、创建授权、升级和保存响应快照。
第五层目标中奖推进至第六层时,在同次状态变化中标记全部剩余格子的领取资格。第五层目标自己的奖励仍通过本次抽奖授权发货,终点领取不能再次包含它。
开奖使用适合付费随机业务的服务端随机源;可用整数权重累计区间抽样,避免浮点累计遗漏尾部。并发竞争失败的计算结果不能返回客户端,必须恢复获胜提交或重新校验状态。
6.5 /pyramid/api(action:claim):第六层领取
请求:{ action:"claim", uid, token, periodId, level:6, requestId }。
响应:{ grant, currentLevel: 6, completed, revision, serverTime }。
校验当前第六层、活动有效、无未决订单及未确认发奖;选择所有 gain=true && deliveryStatus=unclaimed 的格子,一次形成稳定授权并改为 pending。不能用 gain=false 筛选终点奖励,因为到达第六层时资格已建立。
同一请求重试返回原授权。不同请求重复点击也不得生成第二份奖励;已有终点授权时返回已有状态或授权。确认前 completed=false,全部授权到账后才完成。
若第六层未配置固定奖励且所有格子都已抽中,不创建空授权;最后一笔中奖授权确认后直接满足本期完成条件,canClaimFinal=false。
活动到期后不创建新的主动领取,转由结束结算及待发列表恢复;原已成功领取请求仍返回原结果。
6.6 /pyramid/api(action:delivery_list):当前及历史期次待发列表
请求:{ action:"delivery_list", uid, token, cursor?, limit? },不要求传入当前期次。
响应:{ grants: Grant[], nextCursor, serverTime }。
返回该玩家所有期次 pending 授权。列表读取可以触发幂等的到期结算补偿,以覆盖定时任务延迟;不能因为前端未打开旧活动就漏掉奖励。
使用稳定游标顺序,例如 (createdAt, grantId),避免确认前页后集合变短造成偏移分页漏发。处理完一轮后允许从第一页重新拉取,所有授权按 grantId 去重。
登录、活动重连、在线活动到期后查询。补发处理与普通抽奖发货使用同一客户端授权处理队列,不另开一条无去重的加余额流程。
6.7 /pyramid/api(action:delivery_confirm):发货确认
请求:{ action:"delivery_confirm", uid, token, grantId }。无需客户端重传奖励数量。
响应:{ grantId, periodId, status: "delivered", completed, serverTime }。
校验授权归属,幂等地将授权及对应格子标记为 delivered,必要时更新完成状态。重复确认成功,不能再次发放。即使活动已结束也接受合法确认。
该接口记录客户端的到账确认,不凭空证明通用库存接口确实保存成功。严格的到账凭证与一致性方案必须按第 9 节实现和验证。
7. 支付原子性与异常恢复
7.1 下单锁
不能采用“查不到订单就插入”的非原子检查。建议在玩家期次记录上通过条件更新占用 pendingOrderId,预先生成订单号,再持久化订单及签名所需快照。
如果占位成功后进程中断,恢复流程必须根据占位订单号幂等地完成原订单创建或核验原订单,而非超时后换号重开。对外返回支付参数之前,订单和恢复信息必须持久化完成。
7.2 支付机会入账
核验订单身份、商品、金额、渠道与业务归属后,使用统一 fulfillPyramidOrder 服务:
- 持久化可信成功支付事实及首次核验时间;重复通知不得覆盖该首次时间。
- 已有该订单机会记录时返回原结果,不再次增加次数。
- 首次核验时活动已经结束:记录履约
expired,无可用机会。 - 首次核验有效且订单层数仍匹配:原子写入机会记录并解除该订单的未决锁。
- 结束前核验但入账恢复已跨越截止时,不能恢复可用机会;记录到期结果供对账。
- 当前层与订单层不符、额外成功订单或其他不变量破坏:进入
exception,不挪到高层或下一期,也不自动退款;保存证据并提供人工查单处理。这是异常防线,不是允许累积购买的新玩法。
玩家记录内的订单去重与机会写入必须原子完成。订单履约字段可以作为可恢复投影;若与玩家记录分开写入失败,下一次查单依据玩家记录修复订单投影,而不是再加一次机会。
7.3 渠道能力边界
现有通用查询不是可靠的支付终态判定器。实施时必须确认两个签名入口实际对应渠道的主动查单、关闭及签名更新能力;不能直接把其他活动的商户支付分支能力套用到本渠道。
在缺乏可信关闭能力时,未决继续保持,用户可以退出活动。提供订单号、归属期次、最后查询时间、渠道状态和错误信息供查单处理;不得通过“等待若干秒就失败”恢复购买。
8. 活动结束结算
后台扫描已结束期次的已参与玩家;待发列表读取也可以触发同一幂等结算服务。仅靠用户打开活动页面不能保证补发覆盖。
单个玩家结算需要与抽奖、终点领取、确认操作使用同一版本控制或事务边界:
- 将剩余有效机会改为
expired,结束后不自动抽奖。 - 保留全部已有
pending授权。 - 玩家在第六层时,将
unclaimed奖励生成结束补发授权。 - 玩家未到第六层时,不为
not_eligible格子生成授权。 - 已发放格子保持
delivered,设置结算标记,重跑不得新增重复奖励。
到达第六层和获得全部剩余资格必须与第五层目标中奖原子提交。因此,即使最后一次中奖响应丢失,结束结算也能确定应补发全部剩余奖励。
新一期创建独立玩家进度;旧期记录及授权保持可查。旧期未决支付不会转换为新期机会。未解决的旧期发货通过登录恢复队列处理,不把旧订单绑定到新期。
9. 前端发货的一致性要求
推荐客户端处理顺序:领取/恢复授权 → 检查 grantId 是否已处理 → 将奖励变更和处理记录一致地持久化 → 成功同步到账数据 → 调用确认接口。
如果客户端已经处理该授权,则重试保存/确认,不再次增加奖励。保存失败、确认超时、程序崩溃都不得改用新授权。一个授权包含多个道具时,需要整体持久化或记录可恢复的逐项进度,不能重试时重复发放先前已成功的部分。
现有余额整值上传与授权确认是独立操作:
- 仅在后端记录
grantId已确认,不能覆盖“余额已保存但确认丢失”的窗口。 - 仅在本地记录已处理授权,不能天然覆盖缓存丢失、重新安装或服务端保存响应丢失。
- 先确认后发货会导致中断时永久漏发,禁止采用。
实施依赖:需要选择并验证一种能将库存保存与已处理授权记录关联、持久化并恢复的方案,例如扩展保存协议,使授权去重和相关库存写入在同一原子操作中完成,前端仍负责按授权触发发货。不能未经验证就声明严格只到账一次;若保持现有通用保存协议不变,必须明确其保证边界,不能把限制隐藏在确认接口后面。
本次只给出该一致性要求,不把未经确认的通用库存重构当作已完成能力,也不扩展本活动到全游戏库存重构。
10. 错误与客户端行为
| 建议错误码/状态 | 含义及处理 |
|---|---|
AUTH_INVALID |
身份或 token 无效,重新认证 |
PERIOD_NOT_FOUND |
指定期次不存在,刷新活动 |
ACTIVITY_NOT_STARTED / ACTIVITY_ENDED |
禁止新业务动作;已有授权仍可恢复 |
LEVEL_MISMATCH |
请求层数过时,刷新状态 |
PAYMENT_PENDING |
恢复原订单查询,不新建订单 |
DELIVERY_PENDING |
先处理待发授权 |
NO_DRAW_CHANCE / DRAW_CHANCE_EXISTS |
次数不满足抽奖/购买前置条件 |
FINAL_NOT_REACHED |
未到第六层,不能领取全部 |
ALREADY_COMPLETED |
本期已完成,不能重开 |
IDEMPOTENCY_CONFLICT |
同一请求号被用于不同操作参数 |
CONFIG_INVALID |
配置不可用,阻止继续付费并告警 |
PAYMENT_RECONCILE_REQUIRED |
支付或履约异常,需要查单,不能默认为成功机会或失败订单 |
网络故障不是业务失败。幂等重复成功优先返回成功原结果,不使用错误码迫使客户端重新抽奖或重新付款。
11. 实施拆分与运行要求
建议活动内部模块为配置、状态服务、支付适配、授权发货、结束结算。两个现有签名入口只分派到同一金字塔支付服务,回调与主动查单共用同一履约逻辑。
数据库需至少支持玩家期次唯一约束、订单号唯一约束、授权唯一标识,以及玩家状态条件更新/事务。若按集合拆分授权,还需要保证格子到授权的唯一映射与中奖原子性。
审计记录保留:期次与配置版本、订单及层数、首次核验时间、机会入账/使用/作废、开奖候选权重快照或可重建配置、中奖格子、授权、确认及异常。不能输出支付密钥、token 等敏感内容。
监控至少覆盖长期未决订单、支付成功但履约未决、过期机会、长期未确认授权、结束结算失败、重复请求冲突及数据库并发冲突。具体运行周期、告警阈值、历史留存期在部署时确定,不在本次文档中虚构。
12. 验证计划
| 验证项 | 必须成立的结果 |
|---|---|
| 两个签名入口购买同一期同层 | 共用规则及锁,不产生两个未决订单;既有其他商品仍兼容 |
| 篡改价格、商品、数量、层数 | 不按客户端金额签名,不获得错误层机会 |
| 下单占位后崩溃 | 恢复原订单,不通过换订单号重复购买 |
| 回调与主动查单并发 | 同一订单只有一条机会记录 |
| 支付轮询超时/弹窗取消 | 保持未决,仍可退出游戏活动页面 |
| 升级后的旧订单重复通知 | 不给新层加次数 |
| 多目标格子及不放回 | 任一目标都能升级;已获得格子不再参与;概率按剩余权重计算 |
| 同一抽奖请求重试、不同请求并发 | 一次机会只消耗一次,返回的中奖结果与持久化结果一致 |
| 中奖到升级中途进程中断 | 不出现扣次数但无授权、升级但无终点资格的部分状态 |
| 终点领取与结束结算竞争 | 每个剩余格子只属于一个授权 |
| 到账保存响应丢失、确认丢失、多道具部分发放 | 恢复不漏发、不重复发放;按第 9 节验证库存层实际能力 |
| 截止时刻前后边界 | now=endAt 禁止新操作;旧成功操作仍能重放结果 |
| 到期支付成功 | 支付事实为 succeeded,机会为 expired,不挪到新期 |
| 第五层中奖响应丢失后到期 | 根据已提交第六层资格补发全部剩余奖励 |
| 未通关到期 | 只保留已抽中未到账奖励,不补发未获得资格格子 |
| 结束任务重跑、分页期间逐笔确认 | 不生成重复授权,稳定游标不漏掉剩余待发记录 |
| 新一期开始、旧入口关闭 | 新进度独立,登录仍能恢复旧期待发授权 |
13. 待落实的实现事项
- 运营提供首期时间、五层商品与价格、格子、权重及终点奖励配置。
- 确认实际部署仓库,验证数据库唯一约束、条件更新及事务能力。
- 验证实际支付渠道的可信终态和原订单恢复能力。
- 落实授权记录与库存保存的一致性方案,并接入客户端登录恢复队列。
- 配置查单、结束结算、告警与数据留存运行参数。
以上为实施依赖,不改变已经确认的活动规则。本次交付仅为文档,未新增路由、数据库集合、支付逻辑或客户端行为。