在日常企业运营中,审批通过后手动下单快递是一个高频重复劳动。本文记录了如何通过钉钉开放平台,实现审批通过后自动调用中通快递 API 下单并打印电子面单的完整流程。
📝
发起申请
→
👤
主管审批
→
✅
审批通过
→
📦
自动下单
→
🖨
打印面单
一、整体架构设计
整个流程分为三个核心模块:
- 事件监听层:通过钉钉事件订阅,监听审批状态变更
- 业务逻辑层:解析审批表单数据,转换为快递下单参数
- 快递服务层:调用中通快递开放 API 完成下单和面单获取
二、钉钉开放平台配置
2.1 创建企业内部应用
登录钉钉开发者后台,创建企业内部应用,获取 AppKey 和 AppSecret。关键步骤:
- 进入「应用开发」→「企业内部开发」
- 填写应用基本信息,开启「审批」权限
- 在「事件与回调」中配置回调 URL
2.2 事件订阅
我们需要监听的核心事件是 bpms_instance_change,它会在审批实例状态变更时触发。
// 审批事件回调处理
const handleApprovalEvent = async (event) => {
const { EventType, ProcessCode, Result, BusinessId } = event;
if (EventType === 'bpms_instance_change' && Result === 'agree') {
// 审批通过,获取详情
const detail = await getApprovalDetail(BusinessId);
await createExpressOrder(detail);
}
};
三、中通快递 API 对接
| 接口 | 方法 | 说明 |
|---|---|---|
/api/order/create | POST | 创建快递订单 |
/api/waybill/get | POST | 获取电子面单 |
/api/order/trace | GET | 物流轨迹查询 |
/api/order/cancel | POST | 取消订单 |
3.1 下单接口调用
const createExpressOrder = async (approvalData) => {
const payload = {
sender: {
name: approvalData.senderName,
phone: approvalData.senderPhone,
address: approvalData.senderAddress,
},
receiver: {
name: approvalData.receiverName,
phone: approvalData.receiverPhone,
address: approvalData.receiverAddress,
},
cargo: {
name: approvalData.cargoName,
count: approvalData.cargoCount,
weight: approvalData.cargoWeight,
},
// 签名必须按文档要求生成
sign: generateSign(payload, API_SECRET),
};
const res = await axios.post('https://api.zto.com/order/create', payload);
return res.data;
};
四、关键踩坑记录
⚠️ 签名算法注意:中通 API 的签名是将所有参数按 ASCII 排序后拼接,再 MD5 加密。很多人在这里翻车是因为忽略了嵌套对象需要扁平化处理。
另一个常见问题是钉钉回调的加解密。钉钉使用 AES-128-CBC 加密,需要正确配置 EncodingAESKey,并在回调处理中先解密再解析 JSON。
五、部署与监控
生产环境使用 PM2 进行进程管理,配合 Caddy 反向代理提供 HTTPS 访问。关键配置:
# process.json
{
"apps": [{
"name": "dingtalk-express",
"script": "./src/index.js",
"instances": 2,
"env": {
"NODE_ENV": "production",
"DINGTALK_APP_KEY": "your_app_key"
}
}]
}
六、总结
这套方案上线后,快递下单流程从人工 5 分钟/单降到全自动 3 秒/单,错误率从约 8% 降至近 0。核心经验:先理清业务数据流,再对接 API,最后处理边界情况。