订单
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
# 甘草订单状态回调功能配置指南
|
||||
|
||||
## 功能说明
|
||||
|
||||
实现甘草订单状态回调功能,当甘草订单状态发生变化时(如审核通过、制作中、发货、完成等),甘草系统会主动回调我们的接口,更新订单状态。
|
||||
|
||||
## 已创建的文件
|
||||
|
||||
### 1. 回调控制器
|
||||
**文件:** `server/app/api/controller/GancaoCallbackController.php`
|
||||
|
||||
**功能:**
|
||||
- 接收甘草订单状态回调
|
||||
- 验证回调签名(防止伪造)
|
||||
- 更新订单状态
|
||||
- 记录回调日志
|
||||
|
||||
**支持的订单状态:**
|
||||
- `10` - 系统审核中
|
||||
- `11` - 系统审核通过
|
||||
- `110` - 订单药房流转制作中(包含:派单、审方、调配、复核、浸泡、煎药、包装、发货等流程)
|
||||
- `20` - 物流中
|
||||
- `30` - 完成(终态)
|
||||
- `90` - 拦截(终止流转:可恢复)
|
||||
- `91` - 主动撤单(退费:终态)
|
||||
- `92` - 驳回(无法制作并退费:终态)
|
||||
|
||||
### 2. 数据库迁移文件
|
||||
**文件:** `add_gancao_callback_fields.sql`
|
||||
|
||||
**新增字段:**
|
||||
- `gancao_order_state` - 甘草订单状态
|
||||
- `gancao_flow_name` - 订单流程名称
|
||||
- `gancao_supplier` - 供应商/药房名称
|
||||
- `gancao_remark` - 订单备注
|
||||
|
||||
## 配置步骤
|
||||
|
||||
### 步骤 1: 执行数据库迁移
|
||||
|
||||
```bash
|
||||
# 连接到数据库
|
||||
mysql -u root -p your_database
|
||||
|
||||
# 执行 SQL 文件
|
||||
source /path/to/add_gancao_callback_fields.sql;
|
||||
|
||||
# 或者直接执行
|
||||
mysql -u root -p your_database < add_gancao_callback_fields.sql
|
||||
```
|
||||
|
||||
### 步骤 2: 添加路由
|
||||
|
||||
在 `server/route/api.php` 文件中添加回调路由:
|
||||
|
||||
```php
|
||||
<?php
|
||||
use think\facade\Route;
|
||||
|
||||
// 甘草订单状态回调(不需要登录验证)
|
||||
Route::post('gancao/callback/order-status', 'GancaoCallbackController@orderStatus');
|
||||
```
|
||||
|
||||
**注意:** 这个路由不需要登录验证,因为是甘草系统主动回调。
|
||||
|
||||
### 步骤 3: 配置回调 URL
|
||||
|
||||
在 `.env` 文件中配置回调地址:
|
||||
|
||||
```env
|
||||
# 甘草回调配置
|
||||
GANCAO_SCM_CALLBACK_URL=https://your-domain.com/api/gancao/callback/order-status
|
||||
|
||||
# 回调签名验证(可选,如果甘草提供了独立的回调密钥)
|
||||
# GANCAO_SCM_CALLBACK_APPKEY=your_callback_appkey
|
||||
# GANCAO_SCM_CALLBACK_SECRET_KEY=your_callback_secret_key
|
||||
```
|
||||
|
||||
**重要:**
|
||||
1. 回调地址必须是 **HTTPS**
|
||||
2. 回调地址必须能从公网访问
|
||||
3. 如果是开发环境,可以使用内网穿透工具(如 ngrok)
|
||||
|
||||
### 步骤 4: 更新配置文件
|
||||
|
||||
在 `server/config/gancao_scm.php` 中添加回调配置:
|
||||
|
||||
```php
|
||||
return [
|
||||
// ... 其他配置
|
||||
|
||||
'callback_url' => (string) zyt_gancao_scm_env('CALLBACK_URL', ''),
|
||||
|
||||
// 回调签名验证(如果甘草提供了独立的密钥)
|
||||
'callback_appkey' => (string) zyt_gancao_scm_env('CALLBACK_APPKEY', ''),
|
||||
'callback_secret_key' => (string) zyt_gancao_scm_env('CALLBACK_SECRET_KEY', ''),
|
||||
];
|
||||
```
|
||||
|
||||
### 步骤 5: 测试回调接口
|
||||
|
||||
#### 方法 A:使用 curl 测试
|
||||
|
||||
```bash
|
||||
# 模拟甘草回调请求
|
||||
curl -X POST https://your-domain.com/api/gancao/callback/order-status \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "access-appkey: your_appkey" \
|
||||
-H "access-nonce: test1234" \
|
||||
-H "access-timestamp: $(date +%s)" \
|
||||
-H "access-sign: calculated_sign" \
|
||||
-d '{
|
||||
"recipel_order_no": "GC202604...",
|
||||
"state": 11,
|
||||
"ext": {
|
||||
"flow_name": "审核通过"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
#### 方法 B:查看日志
|
||||
|
||||
```bash
|
||||
# 查看回调日志
|
||||
tail -f server/runtime/log/$(date +%Y%m%d).log | grep -i "gancao callback"
|
||||
```
|
||||
|
||||
### 步骤 6: 向甘草提供回调地址
|
||||
|
||||
联系甘草技术支持,提供以下信息:
|
||||
1. 回调地址:`https://your-domain.com/api/gancao/callback/order-status`
|
||||
2. 确认回调签名验证方式
|
||||
3. 测试回调是否正常
|
||||
|
||||
## 回调数据格式
|
||||
|
||||
### 请求头
|
||||
|
||||
```
|
||||
access-appkey: ak-xxxxx
|
||||
access-nonce: random_string
|
||||
access-timestamp: 1234567890
|
||||
access-sign: md5_hash
|
||||
```
|
||||
|
||||
### 请求体
|
||||
|
||||
```json
|
||||
{
|
||||
"recipel_order_no": "GC202604...",
|
||||
"state": 110,
|
||||
"ext": {
|
||||
"flow_name": "煎药开始",
|
||||
"supplier": "XX药房"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 状态 110(制作中)的扩展信息
|
||||
|
||||
```json
|
||||
{
|
||||
"recipel_order_no": "GC202604...",
|
||||
"state": 110,
|
||||
"ext": {
|
||||
"flow_name": "派单|审方|调配|复核|浸泡|煎药开始|包装|发货|寄出",
|
||||
"supplier": "XX药房"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 状态 20(物流中)的扩展信息
|
||||
|
||||
```json
|
||||
{
|
||||
"recipel_order_no": "GC202604...",
|
||||
"state": 20,
|
||||
"ext": {
|
||||
"shipping_name": "顺丰速运",
|
||||
"nu": "SF1234567890",
|
||||
"supplier": "XX药房"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 签名验证
|
||||
|
||||
### 签名算法
|
||||
|
||||
```
|
||||
access_sign = md5(access-appkey + secret-key + access-nonce + access-timestamp + request_body)
|
||||
```
|
||||
|
||||
### 示例
|
||||
|
||||
```
|
||||
access-appkey: ak-36b05d5034f13a86b102c97e72f14
|
||||
secret-key: f8c1f3c58b55a61a4d41242016d314ea
|
||||
access-nonce: 1jd4u8ii
|
||||
access-timestamp: 1723014934
|
||||
Body: {"recipel_order_no":"1234","state":10,"ext":{"flow_name":"浸泡开始"}}
|
||||
|
||||
计算:
|
||||
md5("ak-36b05d5034f13a86b102c97e72f14" + "f8c1f3c58b55a61a4d41242016d314ea" + "1jd4u8ii" + "1723014934" + '{"recipel_order_no":"1234","state":10,"ext":{"flow_name":"浸泡开始"}}')
|
||||
= 03b46e3b385d1dceb183cad08e44f31f
|
||||
```
|
||||
|
||||
## 订单状态映射
|
||||
|
||||
### 甘草状态 → 系统履约状态
|
||||
|
||||
| 甘草状态 | 状态名称 | 系统履约状态 | 说明 |
|
||||
|---------|---------|-------------|------|
|
||||
| 10 | 系统审核中 | 保持不变 | 甘草内部审核 |
|
||||
| 11 | 系统审核通过 | 保持不变 | 审核通过,准备制作 |
|
||||
| 110 | 订单药房流转制作中 | 2(履约中) | 药房制作流程 |
|
||||
| 110(发货) | 发货/寄出 | 5(已发货) | 药房已发货 |
|
||||
| 20 | 物流中 | 5(已发货) | 快递运输中 |
|
||||
| 30 | 完成 | 3(已完成) | 订单完成 |
|
||||
| 90 | 拦截 | 保持不变 | 订单被拦截 |
|
||||
| 91 | 主动撤单 | 4(已取消) | 撤单并退费 |
|
||||
| 92 | 驳回 | 4(已取消) | 无法制作并退费 |
|
||||
|
||||
## 日志记录
|
||||
|
||||
### 回调接收日志
|
||||
|
||||
```
|
||||
[info] Gancao callback received: {
|
||||
"headers": {...},
|
||||
"body": {...}
|
||||
}
|
||||
```
|
||||
|
||||
### 回调处理日志
|
||||
|
||||
```
|
||||
[info] Gancao callback processed: {
|
||||
"order_id": 123,
|
||||
"recipel_order_no": "GC202604...",
|
||||
"state": 110,
|
||||
"ext": {...}
|
||||
}
|
||||
```
|
||||
|
||||
### 订单日志
|
||||
|
||||
在 `zyt_prescription_order_log` 表中记录:
|
||||
- `admin_name`: "甘草系统"
|
||||
- `action`: "gancao_callback"
|
||||
- `summary`: "甘草订单状态更新:系统审核通过"
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 签名验证失败
|
||||
|
||||
```
|
||||
[warning] Gancao callback sign verification failed
|
||||
```
|
||||
|
||||
**处理:** 返回 "ok",避免甘草重试
|
||||
|
||||
### 订单不存在
|
||||
|
||||
```
|
||||
[warning] Gancao callback order not found
|
||||
```
|
||||
|
||||
**处理:** 返回 "ok",记录日志
|
||||
|
||||
### 更新失败
|
||||
|
||||
```
|
||||
[error] Gancao callback update order failed
|
||||
```
|
||||
|
||||
**处理:** 返回 "ok",记录错误日志
|
||||
|
||||
## 重试机制
|
||||
|
||||
甘草的重试策略:
|
||||
- 如果回调失败(未返回 "ok" 或超时),会进行重试
|
||||
- 最多重试 10 次
|
||||
- 重试间隔:失败次数 × 5 分钟
|
||||
|
||||
**建议:**
|
||||
1. 接口必须在 5 秒内返回 "ok"
|
||||
2. 使用异步处理复杂逻辑
|
||||
3. 即使处理失败也返回 "ok",避免重复回调
|
||||
|
||||
## 安全建议
|
||||
|
||||
1. **启用签名验证**:防止伪造回调
|
||||
2. **记录所有回调**:便于排查问题
|
||||
3. **限制访问频率**:防止恶意请求
|
||||
4. **使用 HTTPS**:保护数据传输安全
|
||||
5. **IP 白名单**:只允许甘草服务器 IP 访问(可选)
|
||||
|
||||
## 监控和告警
|
||||
|
||||
### 监控指标
|
||||
|
||||
1. 回调接收数量
|
||||
2. 签名验证失败次数
|
||||
3. 订单更新失败次数
|
||||
4. 回调处理耗时
|
||||
|
||||
### 告警规则
|
||||
|
||||
1. 签名验证失败率 > 10%
|
||||
2. 订单更新失败率 > 5%
|
||||
3. 回调处理耗时 > 3 秒
|
||||
|
||||
## 测试清单
|
||||
|
||||
- [ ] 数据库字段已添加
|
||||
- [ ] 路由已配置
|
||||
- [ ] 回调 URL 已配置
|
||||
- [ ] 签名验证正常
|
||||
- [ ] 订单状态更新正常
|
||||
- [ ] 日志记录正常
|
||||
- [ ] 错误处理正常
|
||||
- [ ] 已向甘草提供回调地址
|
||||
- [ ] 已测试真实回调
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 问题 1:收不到回调
|
||||
|
||||
**检查:**
|
||||
1. 回调 URL 是否正确
|
||||
2. 服务器是否能从公网访问
|
||||
3. 防火墙是否开放端口
|
||||
4. 路由是否配置正确
|
||||
|
||||
### 问题 2:签名验证失败
|
||||
|
||||
**检查:**
|
||||
1. appkey 是否正确
|
||||
2. secret-key 是否正确
|
||||
3. 签名算法是否正确
|
||||
4. 请求体是否被修改
|
||||
|
||||
### 问题 3:订单状态未更新
|
||||
|
||||
**检查:**
|
||||
1. 订单是否存在
|
||||
2. 数据库字段是否添加
|
||||
3. 更新逻辑是否正确
|
||||
4. 查看错误日志
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 甘草 API 文档:https://apidoc.igancao.com/service-doc/scm-outer-recipel.html#订单状态回调
|
||||
- ThinkPHP 路由文档:https://www.kancloud.cn/manual/thinkphp6_0/1037493
|
||||
Reference in New Issue
Block a user