# 快手 Cloud 领取 mock

这份文档用于本地/开发环境验证快手 Cloud 客户领取流程，尤其是套餐商品展示和 91 卡券查询返回领取链接。

mock 流程不会调用 cloudtentacles 发货平台，也不会依赖真实快手小店核销 Cookie。它会直接写入开发数据库，生成一条 91 卡券来源订单、履约任务和领取 token。

## 适用场景

- cloudtentacles 账号过期，想先看领取页是否正常。
- 验证套餐商品是否能展示多条发货明细。
- 验证 91 卡券查询订单接口是否能拿到系统生成的领取链接。
- 演示客户从提交核销码到兑换成功的完整页面流程。

## 生成领取链接

Docker 开发环境使用下面命令：

```bash
docker compose -f docker-compose.dev.yml exec -T backend npm run mock:claim -- --step=ticket
```

执行后会输出类似内容：

```text
已生成快手 Cloud 领取 mock 数据：
  91订单号：MOCK911779929445388
  商品：套餐_1
  当前步骤：ticket
  领取链接：http://221329.cc.cd/#/claim/113bab7dbdbf391d2024e6dfac0af3573a36bc01c629f8f4
  前端本地链接：http://127.0.0.1:5173/#/claim/113bab7dbdbf391d2024e6dfac0af3573a36bc01c629f8f4

页面核销码可填：MOCK
91 查询接口可用这个订单号测试：npm run mock:open91 -- --mode=query --orderNo=MOCK911779929445388
```

打开 `领取链接` 即可测试。如果当前是 Docker + Caddy 开发环境，优先使用输出里的 `领取链接`；`前端本地链接` 只有在本机直接暴露 Vite 端口时才可用。

## 页面怎么操作

默认 `--step=ticket` 会从第 1 步开始：

1. 打开领取链接。
2. 在核销码输入框填 `MOCK`。
3. 点击验证核销码。
4. 页面会进入扫码绑定步骤，并展示 mock 绑定二维码/链接。
5. 点击刷新/确认角色，角色会显示为 `测试角色`、`10001`。
6. 点击兑换，系统会模拟发货成功、退号成功、核销成功。

## 验证 91 查询接口

脚本生成的订单就是 `91kaquan/kuaishou` 来源订单，所以可以用 91 查询接口验证是否返回领取链接。

Docker 开发环境中执行：

```bash
docker compose -f docker-compose.dev.yml exec -T backend npm run mock:open91 -- --baseUrl=http://127.0.0.1:3000 --mode=query --orderNo=MOCK911779929445388
```

正常结果中会看到：

```json
{
  "code": 200,
  "message": "接口调用成功",
  "data": {
    "orderStatus": 20,
    "failCode": 0,
    "cards": "..."
  }
}
```

`orderStatus: 20` 表示订单已发货，`cards` 里是 91 卡券协议要求的加密卡密内容，解密后会包含领取链接。

## 常用参数

### 指定页面步骤

```bash
docker compose -f docker-compose.dev.yml exec -T backend npm run mock:claim -- --step=binding
```

`--step` 支持：

| step | 页面状态 |
| --- | --- |
| `ticket` | 第 1 步，等待提交核销码。默认值 |
| `binding` | 已验证核销码，绑定资源和角色已准备好 |
| `confirm` | 已确认角色，等待兑换 |
| `result` | 已模拟兑换成功，直接看结果页 |

### 指定 91 商品名和快手小店 ID

```bash
docker compose -f docker-compose.dev.yml exec -T backend npm run mock:claim -- --productNo=套餐_1----3676797936
```

`productNo` 中 `----` 后面的 `3676797936` 是快手小店 ID，只跟核销配置有关；91 卡券订单本身统一使用 `shopId=91kaquan`。

### 指定套餐明细

```bash
docker compose -f docker-compose.dev.yml exec -T backend npm run mock:claim -- --items=910001:套餐商品A:1,910002:套餐商品B:2,910003:套餐商品C:1
```

格式是：

```text
cloudSkuId:商品名:数量,cloudSkuId:商品名:数量
```

不传 `--items` 时，默认生成 3 个套餐商品：

| cloudSkuId | 商品名 | 数量 |
| --- | --- | --- |
| `910001` | 套餐商品 A | `1` |
| `910002` | 套餐商品 B | `2` |

### 指定 91 订单号

```bash
docker compose -f docker-compose.dev.yml exec -T backend npm run mock:claim -- --orderNo=MOCK91TEST001
```

订单号不能重复。如果重复，脚本会拒绝写入，避免覆盖已有测试数据。

## 本机直连数据库时怎么跑

如果不是在 Docker 容器里执行，而是在 `apps/backend` 目录直接执行：

```bash
npm run mock:claim -- --step=ticket
```

需要确保 `.env` 里的 `DATABASE_URL` 能从本机访问。例如 Docker Compose 默认给宿主机暴露了 Postgres 端口时，可以使用：

```env
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/order_site
```

如果 `.env` 中是 `postgres://...@postgres:5432/...`，这个主机名只能在 Docker 网络内解析，本机直接跑会报 `getaddrinfo ENOTFOUND postgres`。

## 安全限制

脚本默认拒绝在 `NODE_ENV=production` 下执行，防止误写生产库。只有明确追加 `--force` 才会继续：

```bash
npm run mock:claim -- --force
```

正常不要在生产环境使用 mock 脚本。

## 相关文件

- mock 脚本：`apps/backend/scripts/mock-kuaishou-cloud-claim.ts`
- 91 请求脚本：`apps/backend/scripts/mock-open91-order.ts`
- 领取服务：`apps/backend/src/services/claim/kuaishou-cloud-claim-service.ts`
- 领取页：`apps/frontend/src/pages/claim/ClaimPage.tsx`
- 旧 Vue 领取页：`apps/frontend-vue/src/views/claim/kuaishou-cloud/`
