Files
zyt/GANCAO_CALLBACK_SETUP.md
T
2026-04-15 16:31:25 +08:00

356 lines
8.2 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.
# 甘草订单状态回调功能配置指南
## 功能说明
实现甘草订单状态回调功能,当甘草订单状态发生变化时(如审核通过、制作中、发货、完成等),甘草系统会主动回调我们的接口,更新订单状态。
## 已创建的文件
### 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