133 lines
6.7 KiB
Markdown
133 lines
6.7 KiB
Markdown
# R3 订单闭环 + 支付接口占位(feat/r3-order-pay)
|
||
|
||
**Goal:** 打通“设计清单 → 结算确认 → 创建订单 → 订单列表/详情 → 状态流转”的服务端闭环,
|
||
微信支付只留接口与配置位,不填真实密钥;支付不可用时流程能明确回到“待付款/支付未配置”。
|
||
|
||
**Architecture:** 前端 `api/order.ts` 承接下单与查询,`checkout/orders/orderDetail` 三个页面
|
||
改为服务端数据源;后端订单创建在事务内重算金额、快照地址、生成幂等的订单号并创建 PENDING
|
||
支付记录;`payments` 在密钥未配置时返回显式占位响应,不做假成功。
|
||
|
||
**Tech Stack:** Taro 3.6 + React 18 + TypeScript;NestJS 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/confirm`、`POST /api/orders/:id/cancel`(按需) |
|
||
| `payments` | `POST /api/payments/:orderId/pay` 与 `POST /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. 接口设计要点
|
||
|
||
创建订单请求:
|
||
|
||
```ts
|
||
{
|
||
designListId: string,
|
||
addressId: string,
|
||
items: [{ productId, quantity }]
|
||
}
|
||
```
|
||
|
||
服务端响应:
|
||
|
||
```ts
|
||
{
|
||
id: string,
|
||
orderNo: string,
|
||
status: "PENDING",
|
||
totalAmount: number,
|
||
items: [],
|
||
addressSnapshot: {},
|
||
createdAt: string
|
||
}
|
||
```
|
||
|
||
## 4. 设计注意事项
|
||
|
||
### DO
|
||
|
||
- DO 订单金额、单价、总价全部由服务端计算,前端提交只给 `productId + quantity`。
|
||
- DO 创建订单使用 `prisma.$transaction`,订单、明细、支付记录任一步失败整体回滚。
|
||
- DO 给创建订单接口支持幂等键(客户端 `requestId` 或 `designListId` 防重复下单),双击提交只产生一单。
|
||
- 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 筛选、越权场景提示、支付未配置提示。
|
||
|