# DLBDI Backend

统一后端服务，覆盖用户 Web、小程序、管理端、智能体员工端、咨询顾问端和专家端。

## Stack

- Node.js 22+
- NestJS
- PostgreSQL
- Prisma

## Quick Start

```bash
cp .env.example .env
npm install
npm run prisma:generate
npm run start:dev
```

默认服务地址：

- API: `http://localhost:4000/api`
- Health: `http://localhost:4000/api/health`

本机空间不足或 npm 安装依赖很慢时，可以先启动零依赖健康检查服务：

```bash
npm run db:migrate:lite
npm run start:lite
```

轻量模式已实现第一批 P0 API：

- `POST /api/auth/phone/send-code`
- `POST /api/auth/phone/login`
- `POST /api/staff-auth/phone-login`
- `GET /api/staff-auth/me`
- `GET /api/account/me`
- `PATCH /api/account/profile`
- `POST /api/account/onboarding`
- `GET /api/products`
- `GET /api/products/:slug`
- `POST /api/checkout/preview`
- `POST /api/orders`
- `POST /api/payment-orders`
- `GET /api/payment-orders/:paymentNo/status`
- `POST /api/payments/wechat/notify`
- `POST /api/dev/payment-orders/:paymentNo/succeed`
- `GET /api/account/orders`
- `GET /api/account/entitlements`
- `GET /api/admin/products`
- `POST /api/admin/products`
- `PATCH /api/admin/products/:id`
- `POST /api/admin/products/:id/publish`
- `POST /api/admin/products/:id/offline`
- `GET /api/admin/coupons`
- `POST /api/admin/coupons`
- `PATCH /api/admin/coupons/:id`
- `GET /api/admin/orders`
- `GET /api/admin/settlements`
- `GET /api/staff/tasks`
- `PATCH /api/staff/tasks/:id`

轻量模式会优先使用阿里云短信配置发送真实验证码：`ALIBABA_CLOUD_ACCESS_KEY_ID`、`ALIBABA_CLOUD_ACCESS_KEY_SECRET`、`ALIBABA_CLOUD_SMS_SIGN_NAME`、`ALIBABA_CLOUD_SMS_TEMPLATE_CODE`。未配置短信时，开发环境可通过 `ENABLE_DEV_AUTH_CODE=true` 返回 `DEV_AUTH_CODE`，默认 `123456`；生产环境默认关闭开发验证码，未接真实短信时发码接口会返回明确错误。当前默认使用本机 PostgreSQL 数据库 `dlbdi_dev`，表结构在：

- `db/migrations/001_lite_core.sql`
- `db/migrations/002_admin_payment_staff.sql`
- `db/migrations/003_coupon_settlement.sql`

管理端和员工端统一使用手机号验证码登录，认证头为 `Authorization: Bearer <staff_token>`。本地开发令牌 `x-admin-token: dev-admin-token` 仅在非生产环境且 `ENABLE_DEV_ADMIN_TOKEN=true` 时默认可用，也可通过环境变量 `ADMIN_TOKEN` 显式覆盖。

本地初始化账号：

- `15842430688`：默认 active `super_admin`，使用手机号验证码登录。
- `13900000001` 至 `13900000008`：历史演示员工号会在 bootstrap 后禁用。

当前已跑通的本地闭环：

1. 管理端创建草稿商品，用户端商品列表不可见。
2. 管理端发布商品，用户端商品列表可见。
3. 用户登录后下单，付费商品进入 `pending_payment`。
4. 本地创建 `dev` 支付单，通过 `/api/dev/payment-orders/:paymentNo/succeed` 模拟支付成功。
5. 支付成功后订单变为 `paid`，发放权益，并为智能体/专家类商品生成员工任务。
6. 员工端可查询任务并更新任务状态。

已补上的关键业务细节：

- 优惠码由后台维护，支持固定金额/百分比、总数量、剩余数量、使用门槛、起止时间和状态。
- 用户下单预览时按后台优惠码实时计算，不再写死固定优惠码。
- 支付成功后才核销优惠码并扣减剩余数量。
- 专家咨询支付成功后写入 `settlement_records`，当前默认 8/2 分成，专家收益和平台收益分别落库。

## WeChat Pay

后端已经接入微信支付 APIv3：

- 小程序：`wechat_jsapi`，后端下单后返回 `timeStamp / nonceStr / package / signType / paySign`。
- PC Web：`wechat_native`，后端下单后返回 `codeUrl`，前端生成微信扫码支付二维码。
- 本地开发：默认仍走 `dev` 支付模拟，不依赖公网回调。
- 生产环境：只认微信支付回调 `/api/payments/wechat/notify` 验签解密后的成功结果，前端支付成功回调只做刷新状态。

本地建议：

```env
NODE_ENV=development
ENABLE_DEV_PAYMENT=true
WECHAT_PAY_ENABLED=false
```

生产建议：

```env
NODE_ENV=production
ENABLE_DEV_PAYMENT=false
WECHAT_PAY_ENABLED=true
WECHAT_PAY_MCH_ID=1113738320
WECHAT_PAY_APP_ID=wxf3a0398a84cbffe1
WECHAT_PAY_MCH_SERIAL_NO=3C95A466A3D4B0F8B02A2BB03EB41D6D724B8E7A
WECHAT_PAY_PUBLIC_KEY_ID=PUB_KEY_ID_0111137383202026060800191516001401
WECHAT_PAY_NOTIFY_URL=https://bigdata.dtacloud.cn/api/payments/wechat/notify
WECHAT_PAY_API_BASE_URL=https://api.mch.weixin.qq.com
```

还需要配置 `WECHAT_PAY_API_V3_KEY`、商户私钥和微信支付公钥。密钥支持两种加载方式：

- 传统服务器路径：`WECHAT_PAY_PRIVATE_KEY_PATH`、`WECHAT_PAY_PUBLIC_KEY_PATH`
- 云平台 Secret：`WECHAT_PAY_PRIVATE_KEY_BASE64`、`WECHAT_PAY_PUBLIC_KEY_BASE64`

优先级是 `BASE64 > PATH`。本地证书可以放在不进 Git 的 `secrets/wechatpay/`：

```text
secrets/wechatpay/apiclient_key.pem
secrets/wechatpay/apiclient_cert.pem
secrets/wechatpay/pub_key.pem
```

生产环境不要使用本机 `/Volumes/...` 路径；如果是容器/服务器，就挂载到类似 `/app/secrets/wechatpay/...`，如果是云平台，就把 pem 内容 base64 后写入 Secret。

## First Milestone

M0 先完成：

- 项目骨架
- Prisma schema
- 健康检查
- 统一配置

后续按 `../后端落地实施蓝图_权限ERD接口优先级.md` 的 M1-M8 继续推进。

## Notes

如果在外接盘上安装依赖很慢，建议把 `backend` 临时放到本机磁盘执行 `npm install`，或使用已经配置好缓存的开发环境安装后再回到本目录开发。
