Files
xin-procurement-weapp/小程序端API文档.md
T
2026-08-06 15:24:03 +08:00

546 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 订货采购系统 · 小程序端 API 文档
> 版本:V1.0 更新日期:2026-08-06
> 适用:微信小程序门店端 / 供应商端;接口由后端 `app/Http/Controllers/Mini/` 提供(Laravel 12 + Sanctum)。
## 1. 通用说明
### 1.1 基础信息
| 项目 | 说明 |
|------|------|
| Base URL | `http://localhost:8000`(生产域名待定,通常为 HTTPS) |
| 数据格式 | JSON(请求/响应均 `Content-Type: application/json` |
| 金额字段 | 后端统一 `decimal` 字符串返回(如 `"13.00"`),下单/购物车金额**一律服务端重算**,前端传的金额字段会被忽略 |
### 1.2 认证方式
除「登录」接口外,全部接口需携带 `Authorization: Bearer <token>`(登录接口返回的 tokenSanctum plainTextToken)。
```http
Authorization: Bearer 1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
token 附带 `abilities: ["mini"]` 仅作来源标记;后端按 `users` guard 解析用户。
### 1.3 统一响应格式
成功:
```json
{ "success": true, "data": { ... } }
```
成功带提示:
```json
{ "success": true, "data": { ... }, "msg": "下单成功" }
```
失败(业务错误/验证错误均返回 HTTP 200,`success=false`):
```json
{ "success": false, "msg": "尚未绑定门店,请联系客服处理", "showType": 1 }
```
分页数据统一结构(`data` 字段内):
```json
{
"success": true,
"data": {
"data": [ ... ],
"total": 35,
"pageSize": 10,
"current": 1
}
}
```
### 1.4 角色前置校验
| 接口域 | 前置要求 | 未满足时提示 |
|--------|----------|--------------|
| 商品/购物车/订单/对账单/门店设置 | 用户 `type=门店(1)` 且已绑定正常门店 | 「尚未绑定门店,请联系客服处理」 |
| 供应商采购单 | 用户 `type=供应商(2)` 且已绑定正常供应商 | 「尚未绑定供应商,请联系客服处理」 |
| 商品价格展示 | 门店已设置客户等级(`store.level_id > 0`) | 「门店未设置客户等级,无法展示价格,请联系客服」 |
> 登录后未绑定身份的用户 `type=0`(待绑定):可通过绑定手机号自动匹配门店/供应商,或由后台人工绑定。
### 1.5 价格体系
- 商品价格按「门店客户等级」展示,同一商品不同等级价格不同
- 等级价格支持两种计价类型:
- **固定价**`price_type=0`):直接存储实际单价
- **成本百分比**`price_type=1`):实际价 = 成本价 × (100 + 上浮百分点) / 100
- 小程序端接口返回的 `price` 均为**换算后的实际价**;成本价为商业敏感数据,**不会**下发到小程序端
---
## 2. 认证
### 2.1 微信登录(自动注册)
`POST /mini/auth/login`
`wx.login()` 获取的 code 换 openid,已注册用户直接登录,新用户自动注册并返回 token。
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| code | string | 是 | `wx.login` 的临时凭证 |
响应(`data`):
| 字段 | 类型 | 说明 |
|------|------|------|
| token | string | Bearer 令牌(后续请求头携带) |
| user.id | int | 用户ID |
| user.nickname | string | 昵称 |
| user.avatar | string | 头像 |
| user.phone | string | 手机号(未绑定为空) |
| user.type | int | 0 待绑定 / 1 门店 / 2 供应商 |
| user.store | object\|null | 绑定门店信息(含 `level`:客户等级 `{id,name}` |
| user.supplier | object\|null | 绑定供应商信息 |
响应示例:
```json
{
"success": true,
"data": {
"token": "1|abc...",
"user": {
"id": 5, "nickname": "微信用户1", "avatar": "", "phone": "",
"type": 1,
"store": { "id": 2, "name": "菜市场A店", "level": { "id": 1, "name": "一级客户" } },
"supplier": null
}
},
"msg": "登录成功"
}
```
错误:`code` 缺失 → 「缺少登录凭证 code」;账号被停用 → 「账号已被停用,请联系客服」。
### 2.2 绑定手机号
`POST /mini/auth/phone`(需登录)
用微信手机号授权码换手机号,并按手机号自动匹配门店/供应商(均未命中则保持待绑定,由后台处理)。
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| phoneCode | string | 是 | `wx.getPhoneNumber` 授权得到的 code |
响应(`data`):`user` 结构同 2.1。
### 2.3 当前用户信息
`GET /mini/auth/info`(需登录)
响应(`data`):`user` 结构同 2.1(含门店客户等级——小程序全局价格体系的依据)。
---
## 3. 商品
### 3.1 商品分类树
`GET /mini/product/categories`(需登录 + 门店)
返回分类树,**仅包含有上架商品的分类及其全部祖先**(保证树结构完整)。
响应(`data`):分类树数组,节点字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 分类ID |
| parent_id | int | 父级分类ID0 为顶级) |
| name | string | 分类名称 |
| children | array | 子分类(递归) |
### 3.2 商品列表
`GET /mini/product/list?category_id=&keyword=&page=&pageSize=`(需登录 + 门店 + 客户等级)
请求参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|------|------|------|------|------|
| category_id | int | 否 | - | 分类ID过滤 |
| keyword | string | 否 | - | 搜索品名/规格(模糊) |
| page | int | 否 | 1 | 页码 |
| pageSize | int | 否 | 10 | 每页条数 |
响应(`data` 为分页结构),每项字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 商品ID |
| category_id | int | 分类ID |
| supplier_id | int | 默认供应商ID |
| name | string | 品名 |
| spec | string | 规格/包规 |
| unit | string | 计价单位 |
| content | string | 商品图文详情(HTML |
| **price** | string\|null | **当前门店等级的实际销售价**(未设等级价为 null |
| images_arr | array | 商品图片数组(`{id, file_url, ...}` |
| sort / shelf_life / stock / status | - | 排序 / 保质期 / 库存 / 状态(仅返回上架商品) |
> 注意:只返回上架商品;`cost_price`、计价类型、上浮百分点等成本信息不会下发。
---
## 4. 购物车
> 购物车为下单前的编辑容器,同商品重复加购自动合并数量;提交订单复用「5.1 下单」接口。
### 4.1 加购
`POST /mini/cart`(需登录 + 门店 + 客户等级)
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| product_id | int | 是 | 商品ID(须上架且已设本等级价格) |
| quantity | number | 是 | 数量(>0,最多 99999999.99 |
响应(`data`):
```json
{ "id": 12, "quantity": "2.50" }
```
提示:`已加入购物车`。错误:商品未设本等级价格 → 「商品「xx」未设置您所在等级的价格,无法加购」;超上限 → 「该商品在购物车中的数量已达上限」。
### 4.2 购物车列表
`GET /mini/cart`(需登录 + 门店)
响应(`data`):
| 字段 | 类型 | 说明 |
|------|------|------|
| items | array | 购物车项(倒序) |
| total_count | int | 总项数 |
| total_quantity | string | 可购项总数量 |
| total_amount | string | 可购项总金额 |
items 每项:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 购物车项ID |
| product_id | int | 商品ID |
| name / spec / unit | string | 商品快照 |
| image | string | 商品首图 URL |
| **price** | string\|null | **当前等级实际价**(商品下架或未设等级价为 null) |
| quantity | string | 数量 |
| amount | string\|null | 金额 = price × quantity(不可购为 null |
| status | int | 1 可购 / 0 商品下架、缺失或未设等级价 |
### 4.3 修改数量
`PUT /mini/cart/{id}`(需登录)
请求参数:`quantity`number,必填,>0)。
响应:`{ id, quantity }`,提示「已修改数量」。
### 4.4 删除单项
`DELETE /mini/cart/{id}`(需登录)
响应:`success=true`,提示「已删除」;不存在 → 「购物车项不存在」。
### 4.5 清空购物车
`DELETE /mini/cart`(需登录)
仅清空当前用户;响应:`success=true`,提示「购物车已清空」。
---
## 5. 门店订单
### 5.1 下单
`POST /mini/order`(需登录 + 门店 + 客户等级)
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| items | array | 是 | 订单明细(至少 1 行) |
| items[].product_id | int | 是 | 商品ID(须上架) |
| items[].quantity | number | 是 | 数量(>0 |
| remark | string | 否 | 订单备注(≤255 字符) |
> 金额不接受前端传入:服务端按商品当前等级**实际价**逐行快照并重算 `amount` 与 `total_amount`。
响应(`data`):
```json
{ "id": 23, "order_no": "SO202608060001", "total_amount": "39.00" }
```
提示:「下单成功」。错误示例:存在已下架商品 → 「存在已下架或不存在的商品,请刷新后重试」;未设等级价 → 「商品「xx」未设置您所在等级的价格,无法下单」。
### 5.2 历史订单
`GET /mini/order?status=&page=&pageSize=`(需登录 + 门店,强制本店隔离)
请求参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|------|------|------|------|------|
| status | int | 否 | - | 0 待汇总 / 1 已汇总 / 2 配送中 / 3 已完成 / 9 已取消 |
| page / pageSize | - | 否 | 1 / 10 | 分页 |
响应(`data` 分页结构),订单字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 订单ID |
| order_no | string | 单号(SO + 日期 + 序列) |
| order_date | string | 订货日期(Y-m-d |
| total_quantity / total_amount | string | 总数量 / 总金额 |
| status | int | 状态(见上) |
| remark | string | 备注 |
### 5.3 周期汇总
`GET /mini/order/summary?period=day|week|month`(需登录 + 门店)
请求参数:`period`day/week/month,默认 month)。
响应(`data`):
```json
{
"period": "month",
"groups": [
{ "period_label": "2026-07", "total_amount": "1280.50", "total_quantity": "86.00", "order_count": 12 }
]
}
```
> `period_label` 格式:day=`Y-m-d`、week=`Y-W+周数`、month=`Y-m`;不含已取消订单;最多返回 50 组。
### 5.4 订单详情
`GET /mini/order/{id}`(需登录 + 门店,校验本店归属)
响应(`data`):订单对象 + `items` 数组(明细字段见下表)。
明细字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id / order_id | int | 明细ID / 订单ID |
| product_id / product_name / product_spec | - | 商品快照 |
| price | string | 下单时等级实际价快照 |
| quantity / weight | string | 数量 / 称重(默认 0 |
| amount | string | 金额 = price × quantity |
| remark | string | 行备注 |
### 5.5 取消订单
`PUT /mini/order/{id}/cancel`(需登录 + 门店)
仅「待汇总(0)」可取消;响应提示「订单已取消」;非待汇总 → 「仅待汇总的订单可以取消」。
---
## 6. 对账单(门店自助)
### 6.1 对账单列表
`GET /mini/statement?page=&pageSize=`(需登录 + 门店,仅本店)
响应(`data` 分页结构),对账单字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 对账单ID |
| statement_no | string | 单号(ST + 日期 + 序列) |
| period_start / period_end | string | 对账周期 |
| total_amount | string | 总金额 |
| payment_cycle_days | int | 生成时快照的回款周期 |
| settlement_date | string\|null | 应结算日期 = 周期结束 + 回款周期天 |
| status | int | 0 待对账 / 1 已对账 / 2 已结算 |
| reconciled_at / settled_at | string\|null | 对账 / 结算时间 |
| remark | string | 备注 |
### 6.2 生成对账单
`POST /mini/statement/generate`(需登录 + 门店)
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| period_start | string | 是 | 周期开始(Y-m-d |
| period_end | string | 是 | 周期结束(Y-m-d,不早于开始) |
响应(`data`):`{ id, statement_no, total_amount, settlement_date }`,提示「对账单已生成」。
> 快照当前回款周期计算结算日期。业务约束:周期内本店无订单 → 「周期内本店无订单数据,无法生成对账单」;周期内订单均已生成过对账单 → 「周期内的订单明细均已生成过对账单」。
### 6.3 对账单详情
`GET /mini/statement/{id}`(需登录 + 门店,校验归属)
响应(`data`):对账单对象 + `items` 数组,明细字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| order_id / order_item_id | int | 源订单 / 源明细ID |
| product_id / product_name | - | 商品快照 |
| price | string | 单价 |
| quantity / weight / amount | string | 数量 / 称重 / 金额 |
| is_reconciled | int | 0 未对账 / 1 已对账 |
| store_remark | string | 门店备注 |
### 6.4 导出对账单
`GET /mini/statement/{id}/export?format=xlsx|pdf`(需登录 + 门店,校验归属)
- `format` 默认 `xlsx`(支持 `xlsx` / `pdf`
- 返回文件流(附件下载,含中文文件名),非 JSON
---
## 7. 门店设置
### 7.1 修改回款周期
`PUT /mini/store/paymentCycle`(需登录 + 门店)
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| payment_cycle_days | int | 是 | 回款周期天数(≥0,无上限;0 = 当天结算) |
响应(`data`):`{ "payment_cycle_days": 1 }`,提示「回款周期已更新」。
> 该值影响后续生成对账单的 `settlement_date`(周期结束 + 回款周期天)。
---
## 8. 通知
### 8.1 通知列表
`GET /mini/notice?page=&pageSize=`(需登录)
返回本人通知 + 全员广播(本人已读的广播自动隐藏)。响应(`data` 分页结构 + 附加字段):
| 字段 | 类型 | 说明 |
|------|------|------|
| unread_count | int | 未读总数 |
| 分页内字段 | - | 标准分页结构 |
通知字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 通知ID |
| type | string | `order` 订单 / `price` 价格变更 / `system` 系统 |
| title / content | string | 标题 / 内容 |
| data | object | 附加数据(价格变更通知含 `product_ids``level_ids` |
| is_read | int | 0 未读 / 1 已读 |
| read_at | string\|null | 已读时间 |
### 8.2 标记已读
`PUT /mini/notice/{id}/read`(需登录)
- 个人通知:直接标记已读
- 全员广播:复制一条本人专属已读记录(原广播对他人仍为未读)
响应:`success=true`;通知不存在 → 「通知不存在」。
---
## 9. 供应商端
### 9.1 收到的采购单
`GET /mini/supplier/purchases?page=&pageSize=`(需登录 + 供应商)
返回**含本供应商已发送明细**`is_sent=1`)的采购单(去重,按日期倒序)。
响应(`data` 分页结构),采购单字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 采购单ID |
| purchase_no | string | 单号(PO + 日期 + 序列) |
| purchase_date | string | 采购日期 |
| status | int | 0 待发送 / 1 部分发送 / 2 全部发送 / 3 已完成 |
| total_quantity / estimate_amount / actual_amount | string | 总数量 / 估算金额 / 实际金额 |
| remark | string | 备注 |
### 9.2 采购单明细
`GET /mini/supplier/purchases/{id}`(需登录 + 供应商)
仅返回**本供应商且已发送**的明细行。响应(`data`):
```json
{
"id": 3, "purchase_no": "PO202608060001", "purchase_date": "2026-08-06", "remark": "",
"items": [
{ "id": 11, "product_id": 2, "product_name": "大白菜", "product_spec": "10斤/箱",
"price": "4.00", "quantity": "10.00", "weight": "0.000", "amount": "40.00",
"sort": 1, "is_sent": 1, "sent_at": "...", "supplier_confirmed_at": null }
]
}
```
无本供应商明细 → 「该采购单无贵司的采购明细」。
### 9.3 确认接单
`PUT /mini/supplier/purchases/{id}/confirm`(需登录 + 供应商)
批量记录本供应商全部已发送明细的 `supplier_confirmed_at`(幂等,已确认的跳过)。
响应(`data`):`{ "confirmed": 2 }`(本次新确认条数),提示「已确认接单」。
---
## 10. 状态字典汇总
| 枚举 | 值 | 含义 |
|------|-----|------|
| 用户类型 user.type | 0 / 1 / 2 | 待绑定 / 门店 / 供应商 |
| 门店订单 status | 0 / 1 / 2 / 3 / 9 | 待汇总 / 已汇总 / 配送中 / 已完成 / 已取消 |
| 采购单 status | 0 / 1 / 2 / 3 | 待发送 / 部分发送 / 全部发送 / 已完成 |
| 采购明细 is_sent | 0 / 1 | 未发送 / 已发送 |
| 对账单 status | 0 / 1 / 2 | 待对账 / 已对账 / 已结算 |
| 对账明细 is_reconciled | 0 / 1 | 未对账 / 已对账 |
| 通知 type | order / price / system | 订单 / 价格变更 / 系统 |
| 通知 is_read | 0 / 1 | 未读 / 已读 |
| 商品 status | 0 / 1 | 下架 / 上架 |
| 门店/供应商 status | 0 / 1 | 停用 / 正常 |
## 11. 常见错误提示
| 提示语 | 触发场景 |
|--------|----------|
| 尚未绑定门店,请联系客服处理 | 门店端接口但用户未绑定门店 |
| 尚未绑定供应商,请联系客服处理 | 供应商端接口但用户未绑定供应商 |
| 门店未设置客户等级,无法展示价格,请联系客服 | 门店 `level_id=0`(商品/购物车/下单) |
| 商品「xx」未设置您所在等级的价格,无法下单 | 下单商品缺本等级价格 |
| 存在已下架或不存在的商品,请刷新后重试 | 下单商品已下架 |
| 账号不存在或已被停用 | token 用户被停用 |
| 账号已被停用,请联系客服 | 登录时账号被停用 |