Files
wechat_wc/docs/routes/route-r3-order-pay.md

6.7 KiB
Raw Permalink Blame History

R3 订单闭环 + 支付接口占位(feat/r3-order-pay

Goal: 打通“设计清单 → 结算确认 → 创建订单 → 订单列表/详情 → 状态流转”的服务端闭环, 微信支付只留接口与配置位,不填真实密钥;支付不可用时流程能明确回到“待付款/支付未配置”。

Architecture: 前端 api/order.ts 承接下单与查询,checkout/orders/orderDetail 三个页面 改为服务端数据源;后端订单创建在事务内重算金额、快照地址、生成幂等的订单号并创建 PENDING 支付记录;payments 在密钥未配置时返回显式占位响应,不做假成功。

Tech Stack: Taro 3.6 + React 18 + TypeScriptNestJS 11 + Prisma/PostgreSQL + Redis/BullMQ(可选)。

1. 本分支要开发的内容

前端 wechat_wc

文件 职责
src/utils/api/order.ts createOrder/fetchOrders/fetchOrderDetail/payOrder;请求只带商品项、地址 id、designListId,不带金额
src/types/index.ts 服务端 Order 类型:orderNo/status/totalAmount/items/addressSnapshot/createdAt/paidAt
src/pages/checkout/index.tsx 从服务端读设计清单,选择地址(用 R2 的地址接口),提交下单;展示服务端总价;支付未配置时提示后回订单列表
src/pages/orders/index.tsx 订单列表按状态 Tab 拉取;付款/确认收货等按钮调用对应接口或显示未配置
src/pages/orderDetail/index.tsx 按订单 id 拉详情;地址快照、商品、状态条、物流占位
src/utils/store/order.ts 标记 deprecated,仅保留为本地兜底,不再被 checkout 主流程调用
src/pages/profile/index.tsx 状态统计改为基于服务端订单列表(R2/R3 合入后统一收尾)

后端 wxmp_backend

模块 内容
orders POST /api/orders:服务端按 Product/design-list 重算金额、事务创建订单+items+Payment、生成唯一 orderNo、快照地址
orders 查询 GET /api/orders(状态筛选/分页)、GET /api/orders/:id(仅本人)、PATCH /api/orders/:id/confirmPOST /api/orders/:id/cancel(按需)
payments POST /api/payments/:orderId/payPOST /api/payments/notify 保留签名;密钥为空时返回 { configured:false, message:'支付未配置' }
wechat createUnifiedOrder/verifyPayNotify 保持占位,不填入假商户参数
queue 可选:订单创建后入队定制任务,处理器先只更新 CustomizationTask 状态
docs/api-contract-v1.md 订单创建请求/响应、状态机、金额字段精度、错误码、幂等键

词云项目 wordcloud

不参与本分支。

2. 订单状态机

服务端 OrderStatus 与前端展示映射:

后端 前端 Tab 说明
PENDING 待付款 允许取消;支付未配置时长期停留
PAID 待发货 由支付回调推进,占位期不出现
PROCESSING 待发货 定制生产中
SHIPPED 待收货 需要发货/物流数据,本分支可展示占位
COMPLETED 已完成 用户确认收货推进
CANCELLED 已取消 待付款状态用户取消

前端只读状态数组,不做状态转移判断;转移一律走后端接口或支付回调。

3. 接口设计要点

创建订单请求:

{
  designListId: string,
  addressId: string,
  items: [{ productId, quantity }]
}

服务端响应:

{
  id: string,
  orderNo: string,
  status: "PENDING",
  totalAmount: number,
  items: [],
  addressSnapshot: {},
  createdAt: string
}

4. 设计注意事项

DO

  • DO 订单金额、单价、总价全部由服务端计算,前端提交只给 productId + quantity
  • DO 创建订单使用 prisma.$transaction,订单、明细、支付记录任一步失败整体回滚。
  • DO 给创建订单接口支持幂等键(客户端 requestIddesignListId 防重复下单),双击提交只产生一单。
  • DO 订单号 orderNo 唯一,生成规则包含日期与随机位并在冲突时重试。
  • DO 收货地址在创建订单时直接快照到 addressSnapshot,订单创建后不再跟随地址变更。
  • DO 支付占位返回结构化 configured:false,前端据此显示“暂不支持支付”而不是错误弹窗。
  • DO 后端从配置读取微信支付密钥,密钥缺失时支付接口直接返回占位,不使用默认值或硬编码。
  • DO 订单列表/详情都校验当前用户 openid,越权访问返回 403。
  • DO 金额相关字段用 Decimal 精确类型持久化,序列化时统一成字符串或 number,避免浮点误差。

DON'T

  • DON'T 信任前端传的 totalAmount/price,即使前端为了展示计算过也一律忽略。
  • DON'T 让客户端参数直接决定 status,状态只能由服务端接口和支付回调推进。
  • DON'T 在代码里填占位商户号、密钥、证书路径;密钥缺失是合法运行状态而非 bug。
  • DON'T 模拟支付成功,包括开发环境;未配置就是未配置,避免上线前“假流程”掩盖问题。
  • DON'T 支付回调先解锁订单再验签;本分支只留入口,不实现任何未验签的落库逻辑。
  • DON'T 在本分支删除 store/order.ts,把它标记 deprecated 即可,本地兜底退出要留到全链路验证后。
  • DON'T 修改 R2 的地址/设计清单接口签名,R3 只消费。

5. 补充内容

验收标准

  • 指定一个已登录用户,从设计清单进入结算页,选地址后创建订单;服务端返回的 totalAmount 与商品单价×数量一致。
  • 双击提交只生成一单,订单号唯一。
  • 订单列表/详情展示服务端数据,越权用户拿不到他人订单。
  • 支付按钮在密钥未配置时返回 configured:false 并给出明确文案,不调用微信、不写成功记录。
  • 后端 npm run build、前端 npm run build:weapp 通过。

合并与依赖

  • 分支名:前端与后端均为 feat/r3-order-pay
  • 依赖 R1 的商品表和 R2 的地址/设计清单接口,合并顺序放在 R1、R2 之后。
  • 支付实现作为一个独立后续里程碑,不阻塞本分支交付。

风险

  • 微信小程序对订单支付有场景与类目要求,目前未备案时不要尝试真支付,容易触发审核风险。
  • 物流信息当前为假数据,SHIPPED/COMPLETED 的物流时间轴要标注占位。
  • 若 R2 未按约定提供地址接口,checkout 集成会被卡住;R3 开发时先按 api-contract-v1.md 编写,联调阶段再对齐实现。

测试要求

  • 后端:订单创建事务、金额重算、重复提交幂等、越权查询、状态流转、支付未配置占位响应。
  • 前端:结算页创建订单、双击防抖、订单空态、状态 Tab 筛选、越权场景提示、支付未配置提示。