Files
junhong_cmp_fiber/openspec/specs/order-refund-exchange/spec.md
break 67893617fe
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m33s
feat(退款): AUG26-006 补充当前退款套餐已用量与总量
补齐 PRD §2.3.1「退款管理补充字段」:退款列表、详情与导出新增
「当前退款套餐已用量」与「当前退款套餐总量」两个纯展示字段。

- 套餐定位口径与退款套餐失效保持一致,按优先级取唯一一条:
  冻结的 package_usage_id(且属于该订单)→ 订单主套餐 → 订单任一套餐,
  同级按标识升序。不按当前世代或当前生效套餐推断;不按套餐状态过滤,
  使退款后套餐转已失效时仍能回看用量。
- 列表与详情用固定两次查询批量解析(按标识、按订单),查询次数不随条数增长;
  详情复用同一函数。解析不到套餐或记录已物理删除时返回 0,不阻断读取。
- 导出新增两列并改用同一优先级的 LATERAL 取法,不再依赖只按 r.package_usage_id
  的 join——生产库 1296 条退款仅 157 条带该字段,旧取法会让多数行显示零值。
- 不改变退款金额校验、冻结实收、套餐失效、接续、停机与佣金回溯任何规则。

验证:测试库 junhong_cmp_test 实测冻结记录、订单主套餐回退、记录缺失返回 0 三项
解析场景与「4 条退款固定 2 次查询」;并以同批 43 条退款对拍 Go 解析器与导出 SQL,
口径不一致 0 条;导出 43 行列数与表头一致。无迁移、无接口路径变化。
2026-09-14 12:11:55 +08:00

295 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 订单、退款与换货当前行为
## Purpose
描述订单、退款、换货及订单套餐失效的当前可观察行为。
## Requirements
### Requirement: 订单、退款与换货状态门禁
系统 SHALL 仅允许待支付订单取消;退款申请按待审批、已通过、已拒绝、已退回、原路退款处理中、原路退款失败流转,仅已拒绝、已退回和原路退款失败申请可修改并重新提交;换货按待填写信息、待发货、已发货、已完成或已取消流转,并拒绝与当前状态或流程类型不匹配的操作。处于待审批、原路退款处理中或原路退款失败的退款申请 MUST 阻止同一订单创建新的退款申请,且 MUST NOT 被再次推进为新的审批实例或第二次渠道退款。
#### Scenario: 重复推进终态
- **GIVEN** 退款或换货已进入不允许当前操作的状态
- **WHEN** 再次审批、发货、完成、取消或重新提交
- **THEN** 系统返回状态冲突且不重复改变资产、余额或业务状态
#### Scenario: 原路退款失败后重提
- **WHEN** 退款申请处于原路退款失败状态且调用方在其数据范围内修改材料后重新提交
- **THEN** 系统新增一条审批尝试记录与一个新的企业微信审批实例并使申请回到待审批,历史尝试与已提交的渠道退款不被覆盖
#### Scenario: 企业微信通过后撤销的申请被再次推进
- **GIVEN** 退款申请已记录企业微信通过后撤销的审批异常
- **WHEN** 调用者再次提交或重提该申请
- **THEN** 系统返回状态冲突,不恢复套餐权益、不取消已提交的渠道退款且不自动重提
### Requirement: 代理退款查询按所属店铺隔离
系统 SHALL 允许代理账号通过 `GET /api/admin/refunds` 查询其当前所属店铺的全部退款申请,并通过 `GET /api/admin/refunds/{id}` 查询其中任一申请详情,不以申请创建账号作为查询条件。该范围 SHALL 不包含下级代理店铺、其他店铺或未关联店铺的退款申请;代理账号未关联店铺时,列表 SHALL 为空且详情 SHALL 返回不存在。平台和超级管理员的既有退款查询范围 SHALL 保持不变。
#### Scenario: 查看同店铺其他账号提交的退款
- **GIVEN** 当前代理所属店铺存在由另一账号创建的退款申请
- **WHEN** 该代理查询退款列表或该申请详情
- **THEN** 系统返回该退款申请
#### Scenario: 查询下级代理店铺的退款
- **GIVEN** 当前代理的下级代理店铺存在退款申请
- **WHEN** 当前代理查询退款列表或该申请详情
- **THEN** 系统不返回该退款申请,详情查询返回不存在
#### Scenario: 未绑定店铺的代理查询退款
- **GIVEN** 当前代理账号未关联店铺
- **WHEN** 该代理查询退款列表或退款申请详情
- **THEN** 系统返回空列表或不存在,且不泄露任何退款申请
### Requirement: 历史待审批退款可主动接入企业微信审批
系统 SHALL 提供 `POST /api/admin/refunds/{id}/trigger-approval`,使具有既有退款管理访问权限的后台账号可为历史退款申请主动创建企业微信审批。系统 MUST 仅在退款申请状态为待审批且 `approval_instance_id` 为空时创建审批;审批发起人 MUST 使用该退款申请的原创建账号。创建成功后,系统 MUST 原子保存唯一审批实例、审批提交请求及退款申请的审批实例关联,并返回更新后的退款申请审批摘要。
#### Scenario: 主动发起历史退款审批成功
- **GIVEN** 退款申请处于待审批状态、未关联审批实例,且其原创建账号和企业微信退款审批场景均可用
- **WHEN** 有既有退款管理访问权限的后台账号请求 `POST /api/admin/refunds/{id}/trigger-approval`
- **THEN** 系统创建以原创建账号为发起人的唯一企业微信审批并返回审批摘要,后续由既有可靠提交流程提交至企业微信
#### Scenario: 非待审批或已发起记录被拒绝
- **WHEN** 请求主动发起的退款申请不是待审批状态或已关联审批实例
- **THEN** 系统返回状态冲突且不创建新的审批实例或提交请求
#### Scenario: 并发主动发起同一退款审批
- **WHEN** 两个请求同时为同一符合条件的退款申请主动发起审批
- **THEN** 系统至多创建一个审批实例和一个审批提交请求,未成功创建关联的请求返回冲突
#### Scenario: 原创建人或审批渠道不可用
- **WHEN** 退款申请原创建账号不可用,或企业微信退款审批场景不可用
- **THEN** 系统返回相应错误,退款申请保持未关联审批实例,修复条件后可再次发起
### Requirement: 退款实收金额与方式矩阵
系统 SHALL 从来源订单或原成功支付记录派生并冻结权威实收金额,提交人不得填写或修改;无法确定权威实收金额或该金额非正时拒绝创建申请。冻结来源为:线上支付取该订单原成功支付记录金额;资产钱包、代理主钱包和后台线下套餐订单取订单实际收款或实际扣款金额。退款金额 MUST 为正分且不得超过冻结实收金额,系统 MUST 在申请创建、审批提交和企业微信通过后的执行前重复校验该上限。一笔订单最多一张最终成功退款申请,成功后该订单不得再申请退款。代理充值预存款业务单不在本期退款范围。
可选方式按来源订单的实际支付方式确定,不匹配的方式返回「该订单不支持此退款方式」:线上微信、支付宝或富友支付仅可选原路退款或客户收款信息退款;资产钱包支付仅退回原资产钱包;代理预存款或主钱包支付仅退回原代理钱包;后台线下和员工代收套餐订单仅可选客户收款信息退款。系统 MUST NOT 为本能力新增人工退款方式开关。客户收款信息退款必须同时提供客户收款信息自由文本和至少一个客户凭证附件,且不得复用公司收款方式字典。
线上订单原路可退条件按渠道契约在创建、提交和执行前重复预检:冻结实际商户的退款必需凭证不完整、服务商类型不具备退款能力、或原交易超出渠道可退时限时禁用原路并说明原因,只允许客户收款信息退款。富友原交易的原始日期必须回传渠道;未回传时仅支持 30 天内原交易,回传后可退 360 天内原交易,超出该范围的申请不得选择原路。
#### Scenario: 无权威实收金额
- **WHEN** 来源订单无法取得权威实收金额,或取得的金额非正
- **THEN** 系统拒绝创建退款申请,不允许提交人以自填金额替代
#### Scenario: 提交人试图修改冻结实收金额
- **WHEN** 创建或重提请求携带与派生值不同的实收金额
- **THEN** 系统仍使用派生值作为冻结实收金额,不接受请求值
#### Scenario: 钱包订单申请退款
- **WHEN** 已支付套餐订单的实际支付方式为资产钱包或代理主钱包
- **THEN** 系统只提供退回对应原钱包方式,不展示原路或客户收款信息退款
#### Scenario: 原路凭证不完整
- **GIVEN** 订单为线上支付且其冻结实际商户缺少该服务商类型退款必需凭证
- **WHEN** 调用者申请退款
- **THEN** 系统禁用原路退款并返回原因,只允许客户收款信息退款
#### Scenario: 富友原交易超出可退时限
- **WHEN** 富友原交易的原始支付时间早于可退时限
- **THEN** 系统禁用原路退款并说明原因,只允许客户收款信息退款
### Requirement: 企业微信唯一终审与审批尝试重提
退款申请 SHALL 保存退款原因、冻结实收金额、唯一关联套餐及其使用情况、方式、金额和当次材料快照。超级管理员、平台用户和代理可在各自订单数据范围内创建、修改并重提未成功申请;企业微信是唯一终审,本地 MUST NOT 人工通过、拒绝或退回已关联审批实例的申请。每次创建或重提 MUST 新增一条不可变的审批尝试记录,并以该尝试记录作为通用审批业务标识;同一申请每次提交各自持有独立审批实例,历史尝试材料与审批结果不被覆盖。退款单 SHALL 仅保存最新尝试与最新审批实例引用用于展示。
同一订单同时至多存在一张待审批、原路退款处理中或原路退款失败的退款申请。企业微信驳回、企业微信关闭、或原路退款明确失败后可修改未成功申请的金额、原因、方式、收款信息和附件并重提;每次重提必须新建审批实例及快照。企业微信提交失败或审批结果未知时申请保持在途,使用既有查询与恢复闭环,不得另建或重提。企业微信通过后撤销时不回滚套餐失效或已启动退款,标记审批异常并禁止自动重提。
审批终态 MUST 以审批实例标识判别业务归属:先按审批尝试记录标识与审批实例匹配,未命中时按退款申请标识与审批实例匹配以兼容尚未切换到尝试模式的存量申请,两者均不匹配时返回稳定冲突错误,不得回落到任一候选业务单。
#### Scenario: 审批通过前结果未知
- **WHEN** 企业微信提交成功性或最终结果暂时未知
- **THEN** 申请保持在途且订单不得创建第二张活动申请,系统通过既有恢复机制确认结果
#### Scenario: 未成功申请重提新建实例
- **GIVEN** 退款申请处于已拒绝、已退回或原路退款失败状态且无审批异常
- **WHEN** 调用者修改材料后重新提交
- **THEN** 系统在同一事务新增审批尝试记录并创建新的企业微信审批实例,原尝试记录与历史审批结果保持不变
#### Scenario: 存量申请审批终态仍被消费
- **GIVEN** 退款申请由本能力上线前创建,其审批实例的业务标识指向退款申请本身
- **WHEN** 该审批实例到达通过或关闭终态
- **THEN** 系统按审批实例标识匹配到该退款申请并幂等推进,不按尝试模式误判为不存在
#### Scenario: 已关联实例的本地人工终审
- **GIVEN** 退款申请已关联审批实例
- **WHEN** 后台账号调用本地通过、拒绝或退回入口
- **THEN** 系统拒绝该操作且不改变退款申请与订单状态
#### Scenario: 存量无实例待审批申请仍可终结
- **GIVEN** 退款申请未关联任何审批实例且处于待审批状态
- **WHEN** 后台账号在既有开关开放时调用本地通过、拒绝或退回入口
- **THEN** 系统按既有语义终结该申请,不要求该申请先接入企业微信审批
### Requirement: 原路退款渠道能力与执行
对线上订单,系统 SHALL 在创建、提交及企业微信通过后的执行前校验原支付单、实际收款商户、原渠道交易流水、可退金额和该商户退款必需凭证;商户停用不得阻断历史单校验。新支付按冻结实际商户标识加载该商户当前有效凭证,历史支付按原支付配置标识读取,不得按当前启用商户池推断历史商户。退款能力判定 MUST 只依据服务商类型与该服务商类型退款必需凭证的完整性,不提供人工退款能力开关:微信直连、富友和支付宝商户具备原路退款能力;微信 v2 商户的退款接口为双向证书接口,故其退款必需凭证含 API 客户端证书,缺少该证书时按其凭证完整性判定为不可用并只允许客户收款信息退款,补录证书后即可用。系统 MUST NOT 提供渠道降级开关。不可用时返回的错误说明 MUST 指明缺少哪一类凭证,避免被误判为功能未实现。
微信 v2 退款申请接口的返回仅代表渠道受理情况MUST NOT 据此判定退款成功:受理成功时退款申请 MUST 保持原路退款处理中并等待退款查询确认,退款查询返回明确成功时才可标记已通过并保存渠道退款流水。
原路退款 MUST 使用冻结金额并调用原实际收款商户,实际收款商户不得改选。每次审批尝试 MUST 持久化一个稳定的记录级渠道退款请求号,提交时按冻结服务商类型的契约规则生成,同一尝试重试复用该值、重提生成新值;系统 MUST 以该请求号作为渠道幂等标识,至多提交一次可确认的退款请求。
仅渠道明确成功留存渠道退款流水后退款单才标记已通过;超时、结果未知、渠道明确拒绝、凭证失效、渠道余额不足或本地原支付事实不可用时不标记成功,写入结构化失败分类并保持原路退款处理中或失败状态。重申资金动作至多提交一次:系统 MUST 在提交前持久化认领该次渠道提交,只有认领成功的执行才可调用渠道退款接口;同一次尝试的重复投递或人工重放 MUST 只查询渠道结果并回填MUST NOT 再次提交资金动作。
恢复任务 MUST 只查询渠道并回填结果,不得重复发起资金动作。本地查询窗口超期且结果仍未知时,系统 MUST 终止本次渠道执行并转人工核对:退款申请 SHALL 转为原路退款失败、渠道退款状态 SHALL 转为已失败、失败分类 SHALL 写为超时或结果未知,且此后 MUST NOT 再查询该渠道。超期 MUST NOT 标记为渠道明确成功。窗口超期后系统 MUST NOT 自动重提该申请(本次渠道请求可能已被受理,重提会以新请求号再次提交资金动作),也 MUST NOT 解除同一订单的活动退款互斥。超期边界为:富友因其契约只支持 3 日内查询而在 72 小时后超期;微信 v2 的受理响应不含退款状态且渠道无查询时限,其本地确认上限为 7 天。需改为客户收款信息退款时必须修改申请材料并重新走企业微信审批。
#### Scenario: 原路渠道调用未知
- **WHEN** 企业微信已通过的原路退款调用超时且无法确认渠道结果
- **THEN** 退款保持原路退款处理中,套餐权益不恢复,系统不得再次提交退款,仅由查询恢复回填结果
#### Scenario: 渠道明确成功
- **WHEN** 渠道返回明确退款成功
- **THEN** 系统保存渠道退款流水号与渠道退款金额快照并把退款申请标记为已通过,同时按方式置订单已退款
#### Scenario: 富友退款查询窗口已过且结果未知
- **GIVEN** 富友原路退款已提交但结果未确认,且已超出其退款查询窗口
- **WHEN** 恢复任务再次处理该退款
- **THEN** 系统不再发起退款调用,保留办理中并记录审批异常供人工核对
#### Scenario: 商户已停用的历史原路退款
- **GIVEN** 原支付单命中的实际商户已被停用
- **WHEN** 该订单执行原路退款
- **THEN** 系统仍按该商户当前凭证调用渠道,商户停用本身不阻断调用
#### Scenario: 微信 v2 补录证书后原路可用
- **GIVEN** 订单原支付单命中的商户服务商类型为微信 v2且其凭证补录了 API 客户端证书与私钥
- **WHEN** 调用者申请原路退款
- **THEN** 系统判定该商户原路退款可用,并以商户退款单号作为渠道路径的幂等标识发起退款
#### Scenario: 微信 v2 退款申请仅代表渠道受理
- **GIVEN** 微信 v2 商户凭证完整且企业微信已通过原路退款
- **WHEN** 渠道退款申请接口返回受理成功但未返回退款状态
- **THEN** 系统保持退款申请为原路退款处理中且订单保持已支付,只由退款查询确认最终结果
#### Scenario: 微信 v2 商户缺少客户端证书
- **GIVEN** 订单原支付单命中的商户服务商类型为微信 v2且其凭证只有 APIv2 密钥
- **WHEN** 调用者申请退款
- **THEN** 系统禁用原路退款并说明缺少 API 客户端证书,只允许客户收款信息退款,且不阻断该商户的支付与查单
#### Scenario: 渠道退款结果不经通知接收
- **WHEN** 系统发起原路退款请求
- **THEN** 系统不传递任何渠道退款结果通知地址、不新增退款通知路由,退款终态只由渠道同步响应、主动查询与恢复任务确认
### Requirement: 退款权益与订单状态时点
企业微信最终通过时,系统 SHALL 在同一事务内写退款申请终态、按方式确定的订单支付状态、原钱包退款回款、员工代收账单冲销和可靠套餐失效事实;企业微信通过后的撤销不回滚上述任何已成立事实。套餐失效、接续下一套餐和停机评估 MUST 由既有可靠机制最终一致执行,不得在资金事务内执行运营商停机等不可回滚的外部调用。
订单支付状态时点按退款方式确定:客户收款信息退款与退回原钱包在企微通过时置为已退款;原路退款仅在渠道明确成功时置为已退款,此前订单保持已支付。原路退款在企微通过后、渠道结果确认前的期间内,同一订单 MUST 由活动退款唯一约束阻止产生第二张活动退款申请。重复或乱序的企业微信终态不得再次失效套餐、再次回款或启动第二次渠道退款。
#### Scenario: 企微通过后的权益时点
- **WHEN** 退款申请到达企业微信最终通过
- **THEN** 系统在同一事务写退款终态与可靠失效事实,套餐失效、接续与停机由既有可靠机制随后完成
#### Scenario: 原路退款在渠道确认前置订单状态
- **GIVEN** 退款方式为原路退款且企业微信已通过
- **WHEN** 渠道结果尚未确认
- **THEN** 订单保持已支付、套餐权益已按企微通过失效,且该订单不得创建新的退款申请
#### Scenario: 渠道最终失败不回滚权益
- **WHEN** 原路退款渠道明确失败
- **THEN** 退款申请标记原路退款失败且不标记已通过,已失效套餐权益不恢复,订单保持已支付
### Requirement: 退款终态事实与失败分类
退款申请 SHALL 保存结构化失败分类、渠道退款状态、渠道退款流水与渠道退款请求号,并在列表、详情和导出中返回冻结实收金额、方式、申请状态、渠道退款状态、失败安全摘要、审批尝试历史和渠道流水,按既有订单数据范围过滤。失败分类 MUST 为稳定枚举,至少覆盖:渠道明确拒绝、渠道凭证失效、渠道余额不足、超时或结果未知、企业微信驳回或关闭、企业微信通过后撤销,以及本地原支付事实不可用。渠道凭证失效与本地原支付事实不可用 MUST 为两个并列分类、语义不得合并:前者指该商户退款必需凭证缺失或失效,后者指本地原支付单、实际收款商户、原渠道流水或可退金额校验不通过。每个分类 MUST 显式标记其是否属于「明确失败」:明确失败表示退款已终结且可进入后续回溯判定,非明确失败表示仍在途或需人工处理。审计 SHALL 记录申请、重提、审批终态、权益处理、渠道调用与恢复,且不得记录凭证内容、完整收款文本或商户密钥。
为后续佣金回溯能力提供稳定事实,退款终态 SHALL 可按退款单与订单定位,并提供:成功退款金额、冻结实收金额、终态时点、结构化失败分类及其明确失败标记,以及区分原路成功与客户收款信息完成的完成事件键。后续回溯判定 MUST 依据上述分类标记而非猜测文本:标记为明确失败的退款才可进入回溯判定,标记为非明确失败的退款(超时或结果未知、企业微信通过后撤销)保持在途或转人工,不得回溯。系统 MUST 保留既有退款佣金回扣事件键的兼容语义;佣金回溯的幂等键为一次退款一次回溯,不依赖退款单上的佣金回扣标记。
#### Scenario: 渠道失败分类可查询
- **WHEN** 原路退款因渠道余额不足失败
- **THEN** 退款详情返回该失败分类与安全摘要,且不返回任何凭证内容或完整收款文本
#### Scenario: 审计不含敏感内容
- **WHEN** 渠道退款调用或恢复完成后写入审计
- **THEN** 审计只记录业务标识、金额、状态与脱敏摘要,不记录商户密钥或凭证原文
### Requirement: 退款展示当前退款套餐用量
退款管理列表、详情与导出 SHALL 返回「当前退款套餐已用量」与「当前退款套餐总量」两个字段,取值为该套餐使用记录当前可取得的真实已用量与真实总量(单位 MB。两个字段 MUST 仅用于展示、查询与导出MUST NOT 参与或改变退款金额校验、冻结实收金额、套餐失效、接续下一套餐、停机评估、佣金回溯或渠道退款任何规则。
「当前退款套餐」MUST 按与退款套餐失效一致的口径解析,且 MUST 按下列优先级取唯一一条:退款申请冻结的套餐使用记录(其 `package_usage_id`);该退款关联订单下 `master_usage_id` 为空的主套餐使用记录;该退款关联订单下任一套餐使用记录。同一优先级内按使用记录标识升序取第一条,保证同一退款每次返回相同结果。解析 MUST NOT 按当前生效套餐或当前世代推断,也 MUST NOT 跨订单取套餐。
套餐使用记录不存在、已被物理删除或字段为空时,两个字段 SHALL 返回 0且 MUST NOT 因此阻断列表、详情或导出。列表返回 MUST NOT 因逐条查询套餐使用记录而放大查询次数。
#### Scenario: 退款申请已冻结套餐使用记录
- **GIVEN** 退款申请记录了套餐使用记录标识,且该记录属于其关联订单
- **WHEN** 查询退款列表、详情或导出
- **THEN** 两个字段返回该套餐使用记录的真实已用量与真实总量
#### Scenario: 退款申请未冻结套餐使用记录
- **GIVEN** 退款申请的套餐使用记录为空,且其关联订单存在主套餐使用记录
- **WHEN** 查询退款列表、详情或导出
- **THEN** 两个字段返回该订单主套餐使用记录的已用量与总量,不返回零值
#### Scenario: 套餐使用记录已不存在
- **GIVEN** 退款申请冻结的套餐使用记录已被物理删除,且解析结果为空
- **WHEN** 查询退款列表、详情或导出
- **THEN** 两个字段返回 0且列表、详情与导出仍正常返回该退款申请
#### Scenario: 列表不因套餐字段放大查询
- **GIVEN** 退款列表一页返回多条退款申请
- **WHEN** 查询该页列表
- **THEN** 系统以批量方式读取套餐使用记录,查询次数不随该页退款申请条数线性增长
#### Scenario: 展示字段不影响资金与权益规则
- **GIVEN** 任一退款申请
- **WHEN** 系统解析并返回这两个展示字段
- **THEN** 退款金额校验、冻结实收金额、套餐失效、接续下一套餐、停机评估与佣金回溯行为均不发生变化
## 可达操作索引
本节只用于入口导航,不是行为 Requirement业务义务以上述 Requirements 为准。
### 订单管理
`GET /api/admin/orders`(获取订单列表);`POST /api/admin/orders`(创建订单);`GET /api/admin/orders/{id}`(获取订单详情);`POST /api/admin/orders/{id}/cancel`(取消订单);`POST /api/admin/orders/purchase-check`(套餐购买预检)。
### 退款管理
`GET /api/admin/refunds`(退款申请列表);`POST /api/admin/refunds`(创建退款申请);`GET /api/admin/refunds/{id}`(退款申请详情);`POST /api/admin/refunds/{id}/trigger-approval`(补发历史退款审批);`POST /api/admin/refunds/{id}/approve`(审批通过退款申请);`POST /api/admin/refunds/{id}/reject`(审批拒绝退款申请);`POST /api/admin/refunds/{id}/resubmit`(重新提交退款申请);`POST /api/admin/refunds/{id}/return`(退回退款申请)。
### 换货管理
`GET /api/admin/exchanges`(获取换货单列表);`POST /api/admin/exchanges`(创建换货单);`GET /api/admin/exchanges/{id}`(获取换货单详情);`POST /api/admin/exchanges/{id}/cancel`(取消换货);`POST /api/admin/exchanges/{id}/complete`(确认换货完成);`POST /api/admin/exchanges/{id}/renew`(旧资产转新);`POST /api/admin/exchanges/{id}/ship`(换货发货)。
### 订单套餐失效
`GET /api/admin/order-package-invalidate-tasks`(查询订单套餐失效任务列表);`POST /api/admin/order-package-invalidate-tasks`(创建订单套餐批量失效任务);`GET /api/admin/order-package-invalidate-tasks/{id}`(查询订单套餐失效任务详情)。