# 杜康好客 · preV1 编码手册(Mock 联调版) > **V3 交付提示**:preV1 不再作为交付验收标准。核销规则以 [`杜康好客-v3编码手册.md`](./杜康好客-v3编码手册.md) §3 为准(无 ¥500 上限)。 > **版本**:preV1(在 V2 完整规格之上的**裁剪实现阶段**) > **完整规格(V2)**:[`杜康好客-V2编码手册.md`](./杜康好客-V2编码手册.md) — PRD、DB v3.1、API、任务卡均以 V2 为准 > **原则**:**不删表、不删 V2 API 路径、不改 V2 字段语义**;preV1 用 Mock / Feature Flag / Seed 跳过外部依赖,开关关闭即切回 V2 真实流程。 --- ## 文档索引 | 章节 | 内容 | |------|------| | §0 | 版本关系(preV1 vs V2) | | §1 | preV1 范围:六条裁剪规则 | | §2 | 三端 H5 与仓库结构 | | §3 | 认证 Mock(无微信) | | §4 | 支付 Mock | | §5 | 配送与订单状态 Mock | | §6 | 无总部端:能力替代 | | §7 | preV1 功能清单 | | §8 | Feature Flag 与 V2 切换 | | §9 | preV1 里程碑与任务卡 | | §10 | API / 数据行为差异速查 | --- # §0、版本关系 | 维度 | preV1(本文) | V2(完整版) | |------|---------------|--------------| | 定位 | 三端 H5 联调,跑通购酒→发券→核销主链路 | 四端小程序/H5 + 真实微信/物流/支付 | | 客户端 | **用户 / 门店 / 合伙人 均为 H5** | C端+合伙人+总部小程序,门店 H5 | | 总部 HQ | **无独立端** | `pages/hq/` + AdminAuth | | 登录 | **仅手机号 + 固定验证码** | 短信 + 微信授权/绑定 | | 支付 | **Mock 即时成功** | 微信 JSAPI + 回调 | | 配送 | **Mock 状态推进** | 小飞侠/物流回调 | | 数据库 | **同 V2 v3.1(28 表)** | 同左 | | API 路径 | **同 V2 §六**(行为可 Mock) | 完整实现 | **升级路径**:preV1 完成后,按 §8 逐项打开 Flag、补小程序端与 HQ 端,**无需重构表结构**。 --- # §1、preV1 范围:六条裁剪规则 ### 1.1 删掉 HQ 端 - **不做**:`apps/mini-hq`、`pages/hq/` 任何页面、AdminAuth 前端。 - **保留**:`hq_account` 表、§六 全部 `/admin/*` 路由(preV1 可不实现 Controller,或仅内部/脚本调用)。 - **替代**:见 §6。 ### 1.2 用户 / 门店 / 合伙人 均改为 H5 | V2 端 | preV1 App | `X-Client-App` | 原型参照 | |-------|-----------|----------------|----------| | C端小程序 | `apps/h5-user` | `USER_H5` | `pages/user/` | | 门店 H5 | `apps/h5-shop` | `SHOP_H5` | `pages/shop/` | | 合伙人小程序 | `apps/h5-partner` | `PARTNER_H5` | `pages/partner/` | - JWT `actorType` 不变:`USER` / `STORE` / `PARTNER`。 - V2 的 `USER_MINI` / `PARTNER_MINI` / `HQ_MINI` 枚举**保留**,preV1 不用即可。 ### 1.3 微信登录与授权暂不走 - **不调用**:微信 `code2session`、获取手机号组件、微信 OAuth。 - **不写入**:`wx_open_id` / `wx_union_id`(保持 NULL)。 - **仅实现**:`POST /auth/sms/send` + `POST /auth/login/sms`(及三端等价路径 `/shop/auth/*`、`/partner/auth/*`)。 - V2 的 `POST /auth/login/wechat`、`/auth/wechat/bind-phone`:**保留路由**,preV1 返回 `501 FEATURE_DISABLED` 或 Flag 关闭时不注册。 ### 1.4 手机号验证固定 Mock | 项 | preV1 约定 | |----|------------| | 验证码 | 固定 **`123456`**(全端、全 scene 通用) | | 开关 | `MOCK_SMS=true` 时:不调用短信网关,不写入 `log_third_party(SMS)` 真实外呼 | | 校验 | `AuthService.verifyCode(phone, code)` 内:`if (MOCK_SMS && code === '123456') return ok` | | 限流 | preV1 可放宽;V2 打开真实短信后启用频率限制 | **测试账号(Seed,见 §6.1)** | 角色 | 手机号 | 表 | |------|--------|-----| | C端用户 | `13800000001` | `user_user` | | 门店 | `13900000001` | `store_account` | | 合伙人主账号 | `13700000001` | `partner_account` | ### 1.5 配送与订单状态 Mock(跳过第三方) - **不调用**:小飞侠 API、物流查询 API;`log_third_party` 的 `XFX` / `LOGISTICS` 在 preV1 可不写入(或写 MOCK 占位)。 - **仍创建**:支付成功后 `user_order_delivery` 空壳(与 V2 一致 1:1)。 - **状态推进**(任选其一,推荐 A+B): - **A. 自动任务**:`MOCK_DELIVERY_AUTO=true` 时,支付成功 30s 后 BullMQ 任务:`PENDING_SHIP → OUT_WAREHOUSE → SHIPPING → PENDING_RECEIVE → COMPLETED`,并写 `common_event(ORDER_STATUS)`。 - **B. 合伙人手动**:`POST /partner/orders/:id/mock-advance-delivery`(preV1 专用,V2 可保留为内部测试接口或 Flag 保护)。 - **user_order** 冗余时间字段 `shipped_at` / `completed_at` 与 `user_order_delivery.shipping_at` / `delivered_at` **双写**(同 V2)。 ### 1.6 跳过支付 - **不调用**:微信统一下单、支付回调验签。 - **用户侧**:确认订单页按钮文案可为「提交订单(Mock 支付)」;仍调用 **`POST /trade/orders/:id/pay`**(路径与 V2 相同)。 - **服务端**:`MOCK_PAY=true` 时 `PayService` 同步: 1. `user_order.pay_status=PAID`,`paid_at=NOW()`,`pay_external_no='MOCK-{orderNo}'` 2. 可选写 `log_third_party(WECHAT_PAY, scene=ORDER_PAY, status=SUCCESS, external_no=MOCK-...)` 3. 订单 `status=PENDING_SHIP` + `common_event(ORDER_STATUS)` 4. 调用 `BenefitService.grantOnOrderPaid(orderId)`(**真实发券逻辑,非 Mock**) 5. 预创建 `user_order_delivery` - V2 切换:`MOCK_PAY=false` 时走 `wechatpay-node-v3` + `/callbacks/wechat/pay`。 --- # §2、三端 H5 与仓库结构 preV1 Monorepo(在 V2 目标结构上演进,**暂不建 mini-* / mini-hq**): ``` dukang/ ├── apps/ │ ├── h5-user/ # C端 H5(Taro H5 或 Vite+React,与 V2 技术栈一致即可) │ ├── h5-shop/ # 门店 H5 │ └── h5-partner/ # 合伙人 H5 ├── packages/ │ ├── shared-types/ # 含 USER_H5 / PARTNER_H5 / SHOP_H5 │ └── domain/ ├── server/dukang-api/ # 同 V2 单体 NestJS ├── pages/{user,shop,partner}/ # UI 参照(hq 仅 V2 用) ├── 杜康好客-V2编码手册.md └── 杜康好客-preV1编码手册.md # 本文 ``` **请求头**:各 H5 固定 `X-Client-App: USER_H5 | SHOP_H5 | PARTNER_H5`。 **页面实现**:字段、Tab、跳转以 V2 手册 §二、§三 原型为准;C 端订单 **5 Tab(含待发货)** 不变。 --- # §3、认证 Mock(无微信) ### 3.1 实现的登录路径 | 端 | 发送验证码 | 登录 | |----|------------|------| | C端 | `POST /auth/sms/send` scene=`USER_LOGIN` | `POST /auth/login/sms` | | 门店 | `POST /auth/sms/send` scene=`STORE_LOGIN` | `POST /shop/auth/login/sms` | | 合伙人 | `POST /auth/sms/send` scene=`PARTNER_LOGIN` | `POST /partner/auth/login/sms` | ### 3.2 preV1 不实现的登录路径 | 路径 | preV1 行为 | |------|------------| | `POST /auth/login/wechat` | 501 或 Flag 关闭 | | `POST /auth/wechat/bind-phone` | 501 | | `POST /shop/auth/login/wechat` | 501 | | `POST /partner/auth/login/wechat` | 501 | | `POST /admin/auth/*` | 不暴露给前端(无 HQ 端) | ### 3.3 实现要点(便于 V2 切换) ```typescript // packages/shared-types 或 server config export const AppConfig = { mockSms: process.env.MOCK_SMS === 'true', mockSmsCode: process.env.MOCK_SMS_CODE ?? '123456', mockPay: process.env.MOCK_PAY === 'true', mockDeliveryAuto: process.env.MOCK_DELIVERY_AUTO === 'true', }; // AuthService — 单一验证码入口,V2 只改内部实现 async verifySmsCode(phone: string, code: string, scene: string) { if (AppConfig.mockSms && code === AppConfig.mockSmsCode) return; // V2: 查 Redis / log_third_party / 真实短信平台 } ``` --- # §4、支付 Mock ### 4.1 用户流程(与 V2 UI 一致,跳过收银台) ``` 确认订单 → POST /trade/orders(锁单 PENDING_PAY) → POST /trade/orders/:id/pay [MOCK_PAY=true] 同步成功,无跳转微信 → 订单列表可见「待发货」 → 权益页可见新券 ``` ### 4.2 字段与表(与 V2 相同) | 写入 | 说明 | |------|------| | `user_order.pay_status` | `PAID` | | `user_order.paid_at` | 当前时间 | | `user_order.pay_external_no` | `MOCK-{orderNo}` | | `user_order.status` | `PENDING_SHIP` | | `log_third_party` | 可选 MOCK 记录,便于 V2 对账逻辑联调 | | `user_benefit_coupon` + `common_event(BENEFIT_LEDGER,GRANT)` | **真实业务**,非 Mock | ### 4.3 preV1 不做的支付相关能力 - 微信 prepay 参数、支付回调、`/callbacks/wechat/pay` 验签(路由保留,Mock 模式不触发)。 - 退款微信 API:preV1 **整模块可跳过**(§7);表与 `common_ticket(REFUND)` 仍保留。 --- # §5、配送与订单状态 Mock ### 5.1 自动推进状态机(推荐默认开启) `MOCK_DELIVERY_AUTO=true` 时,支付成功后注册延时任务: | 延时 | from → to | 配送表 | |------|-----------|--------| | T+0 | `PENDING_SHIP` → `OUT_WAREHOUSE` | `out_warehouse_at` | | T+10s | → `SHIPPING` | `shipping_at`,`user_order.shipped_at` | | T+30s | → `PENDING_RECEIVE` | — | | T+60s | → `COMPLETED` | `delivered_at`,`user_order.completed_at` | 每次 transition 写 `common_event(ORDER_STATUS)`;`provider` 填 `MANUAL` 或 `MOCK`。 ### 5.2 合伙人端手动推进(可选) `POST /partner/orders/:id/mock-advance-delivery` - Guard:`PartnerAuth` + 订单 `city_id` 属合伙人辖区。 - Body:`{ targetStatus: 'SHIPPING' | 'COMPLETED' | ... }` - preV1 专用;V2 生产环境 `MOCK_DELIVERY=false` 时返回 403。 ### 5.3 改址拦截(preV1 简化) - V2 PRD:用户改址 → 合伙人拦截配送。 - preV1:`PUT /trade/orders/:id/address` **仅更新** `user_order` 收货字段 + `common_event`;**不**调第三方、不建复杂 intercept 表(V2 仍用 `common_ticket(ALERT)`,preV1 可省略工单)。 --- # §6、无总部端:能力替代 HQ 能力在 preV1 通过 **Seed + 合伙人 H5 子集 + 可选内部 API** 覆盖,**表结构不删**。 ### 6.1 启动 Seed(`prisma/seed-prev1.ts` 或 SQL) | 数据 | 内容 | |------|------| | `common_city` | 郑州 `ACTIVE`,`local_min_qty=2`,`cross_min_qty=6` | | `common_city_commission_rule` | 默认佣金比例 | | `common_product_item` | 4 款清香型 `ON_SALE`,含 `barcode_69` | | `common_store_category` | 火锅/地方菜等 | | `partner_partner` + `partner_account` | 郑州合伙人 + 主账号 `13700000001` | | `store_store` + `store_account` | 至少 2 家 `OPEN` 门店 | | `user_user` | 测试用户 `13800000001` | | `hq_account` | 可 Seed 1 条供未来 V2,preV1 无 UI | 商品图/门头图:preV1 可用 **占位 URL** 或 `common_resource` 写死 CDN;V2 换 OSS 上传流程即可。 ### 6.2 原 HQ 功能 → preV1 替代 | V2 HQ 功能 | preV1 替代 | |------------|------------| | 开城 / 商品 CRUD | **Seed 固定**;变更改 Seed 或直连 DB(开发环境) | | 门店审核 | 合伙人提交后 **`AUTO_APPROVE_STORE=true` 自动通过**,写 `common_event(STORE_AUDIT,APPROVED)` | | 订单中心 / 发货 | 合伙人 H5 看辖区订单;跨城发货 preV1 跳过或 Mock 运单号 | | 推广码 | **跳过 UI**;`channel_source` 可手填或 Seed 一条 `common_promo_code` | | 退款 / 客服工单 | **跳过**(或合伙人 H5 仅查看,不发起微信退款) | | 结算中心 T+1/T+30 | **Mock 状态**:核销后 `store_payout.status=PENDING`;合伙人 `partner_bill` 可 Seed 一条 `CONFIRMED` 演示 | | 数据报表 / 埋点 | 埋点 **可写 `log_user_analytics`**;总部报表 **不做** | ### 6.3 合伙人 H5 在 preV1 的扩展(承接部分 HQ) 在 V2 合伙人 API 基础上,preV1 **额外开放**(Flag 保护): | 能力 | 说明 | |------|------| | 门店审核自动通过 | 配置项,非新表 | | Mock 推进配送 | §5.2 | | 查看辖区订单 | V2 已有 `GET /partner/orders` | --- # §7、preV1 功能清单 ### 7.1 必做(跑通主链路) | 模块 | 功能 | V2 预留 | |------|------|---------| | IAM | 三端短信 Mock 登录 | 微信登录路由保留 | | Catalog | 读商品/开城(Seed) | `/admin/products` 未实现 | | Trade | 预览、下单、Mock 支付、5 Tab 订单、改址 | 真实微信支付 | | Benefit | 发券、券列表、明细 | 同 V2 | | Redeem | Redis 核销码、门店扫码确认、评价 | 同 V2 | | Store | C 端门店列表/详情;合伙人录店;**自动审核** | HQ 人工审核 | | Settlement | 核销后 `store_payout` PENDING | T+1 打款任务可 Mock 为手动改 PAID | | Analytics | 可选:批量写 `log_user_analytics` | 同 V2 | ### 7.2 preV1 明确跳过(V2 补) | 模块 | 跳过内容 | |------|----------| | HQ 端 | 全部页面与 AdminAuth 前端 | | 微信 | 登录、支付、退款、订阅消息 | | 第三方 | 小飞侠、物流、真实短信 | | 运营 | 退款工单、推广码管理 UI、总部报表 | | 合伙人 | 拦截配送完整流程、T+30 真实打款、提现 | | 小程序 | 全部(preV1 仅 H5) | ### 7.3 业务规则(与 V2 相同,Mock 不减免) - 同城起购 **2 瓶** / 跨城 **6 瓶**(`packages/domain`) - 权益金额 `benefit_amount ?? price` - 核销上限 **¥500**,Redis 码 **5 分钟** - C 端门店仅 **`OPEN`** - 订单 **5 Tab**(含 `pending_ship`) --- # §8、Feature Flag 与 V2 切换 ### 8.1 环境变量(`.env.example`) ```bash # preV1 Mock 开关(true = Mock 模式) MOCK_SMS=true MOCK_SMS_CODE=123456 MOCK_PAY=true MOCK_DELIVERY_AUTO=true AUTO_APPROVE_STORE=true # V2 就绪后逐项 false,并配置真实密钥 WECHAT_PAY_ENABLED=false WECHAT_AUTH_ENABLED=false XFX_ENABLED=false SMS_PROVIDER=mock ``` ### 8.2 切换检查表(preV1 → V2) | 步骤 | 动作 | |------|------| | 1 | `MOCK_PAY=false`,配置商户号,启用 `/callbacks/wechat/pay` | | 2 | `MOCK_SMS=false`,接入短信,`log_third_party(SMS)` | | 3 | `MOCK_DELIVERY_AUTO=false`,对接小飞侠/物流回调 | | 4 | `AUTO_APPROVE_STORE=false`,上线 `apps/mini-hq` + 门店审核 | | 5 | 新增 `apps/mini-user`、`apps/mini-partner`,`X-Client-App` 改 MINI | | 6 | `WECHAT_AUTH_ENABLED=true`,实现 wechat 登录/bind-phone | | 7 | 启用退款、结算 Job、推广码 HQ 页面 | ### 8.3 代码组织(避免 Mock 散落) ``` server/dukang-api/src/ ├── integrations/ │ ├── sms/ │ │ ├── sms.interface.ts # ISmsProvider │ │ ├── sms.mock.provider.ts # preV1 │ │ └── sms.aliyun.provider.ts # V2 │ ├── pay/ │ │ ├── pay.interface.ts │ │ ├── pay.mock.provider.ts │ │ └── pay.wechat.provider.ts │ └── delivery/ │ ├── delivery.interface.ts │ ├── delivery.mock.provider.ts │ └── delivery.xfx.provider.ts ``` `TradeModule` / `AuthModule` 只依赖 **interface**,由 `ConfigModule` 注入 Mock 或 Real 实现。 --- # §9、preV1 里程碑与任务卡 > 详细 API/表结构见 V2 手册 §五、§六;任务 ID 前缀 **`P1-`**,与 V2 `M0~M6` 并行命名空间。 | 里程碑 | 交付 | 出口标准 | |--------|------|----------| | **P1-M0** | Monorepo 三 H5 + API 骨架 + Seed | 三端登录页、`GET /health`、Seed 郑州+4 SKU | | **P1-M1** | IAM Mock + 商品/门店读 | 三端 Mock 登录;C 端首页 4 款酒 | | **P1-M2** | 下单 + Mock 支付 + 5 Tab 订单 | 2 瓶起购;支付后待发货+发券 | | **P1-M3** | 权益 + 核销 + 门店 H5 | 端到端核销;`store_payout` PENDING | | **P1-M4** | 合伙人录店 + 自动审核 | C 端可见新门店 | | **P1-M5** | Mock 配送自动推进 | 订单可到已完成 | | **P1-M6** | 埋点可选 + 联调修复 | 主链路冒烟通过 | ### 任务卡(精简) | ID | 任务 | 验收 | |----|------|------| | P1-M0-001 | pnpm workspace + `h5-user/shop/partner` | 三端 `dev` 可编译 | | P1-M0-002 | `shared-types` + Mock Flags | 导出 `AppConfig` | | P1-M0-003 | NestJS + Prisma + `init_v3.sql` | `prisma validate` | | P1-M0-004 | `seed-prev1.ts` | 郑州/4SKU/测试账号 | | P1-M1-001 | `SmsMockProvider` + 三端 login/sms | 123456 登录 | | P1-M1-002 | C 端首页/详情 Public catalog | 对照 `pages/user/2,3` | | P1-M2-001 | preview + create order | 起购校验 | | P1-M2-002 | `PayMockProvider` + grant benefit | Mock 支付发券 | | P1-M2-003 | 订单 5 Tab | `pending_ship` 有数据 | | P1-M3-001 | 权益页 + redeem token | ¥500 上限 | | P1-M3-002 | 门店扫码核销 | `pages/shop/3~5` | | P1-M4-001 | 合伙人录店 + AUTO_APPROVE | C 端门店可见 | | P1-M5-001 | `DeliveryMockProvider` 自动推进 | 订单 COMPLETED | --- # §10、API / 数据行为差异速查 | API / 行为 | V2 | preV1 | |------------|-----|-------| | `X-Client-App` | USER_MINI / … | USER_H5 / SHOP_H5 / PARTNER_H5 | | `/admin/*` | AdminAuth 小程序 | 无前端;Seed/脚本 | | `/auth/login/wechat` | 实现 | 501 或 Flag 关 | | `/auth/sms/send` | 真实短信 | 固定码,不外呼 | | `/trade/orders/:id/pay` | 微信 prepay | 同步 Mock 成功 | | `/callbacks/wechat/pay` | 验签回调 | 不触发 | | `/callbacks/xfx/delivery` | 配送回调 | 不触发 | | `log_third_party` | 真实流水 | 可选 MOCK 行或跳过 | | 门店审核 | HQ 审 | `AUTO_APPROVE_STORE` | | 退款 | HQ 工单+微信退款 | **跳过** | | 推广码 UI | HQ | **跳过** | | 核销 / 权益 / 订单表 | 真实 | **真实(同 V2)** | --- ## 原型参照(preV1 仍用 V2 映射) | H5 App | 原型目录 | |--------|----------| | h5-user | `pages/user/` | | h5-shop | `pages/shop/` | | h5-partner | `pages/partner/` | C 端订单列表:**5 Tab(含待发货)**;个人中心无会员标签;城市示例以 **郑州** 为准。 --- *preV1 为 V2 的 Mock 联调阶段;完整 PRD、DB DDL、全量 API 见 [`杜康好客-V2编码手册.md`](./杜康好客-V2编码手册.md)。*