PHP 怎么钉钉审批流

wen PHP项目 3

本文目录导读:

PHP 怎么钉钉审批流

  1. 📖 目录导读
  2. 钉钉审批流到底是什么?—— 核心概念与适用场景
  3. PHP对接钉钉审批流的三种主流方案对比
  4. 实战前置准备:创建应用、获取凭证、配置权限
  5. 核心接口详解:发起审批、查询实例、回调通知
  6. 代码实战:PHP封装钉钉审批流SDK(附完整示例)
  7. 高频踩坑与性能优化
  8. 常见问题问答(FAQ)
  9. 总结与延伸学习建议

PHP如何集成钉钉审批流?从零到实战的完整指南(附代码示例)


📖 目录导读

  1. 钉钉审批流到底是什么?—— 核心概念与适用场景
  2. PHP对接钉钉审批流的三种主流方案对比
  3. 实战前置准备:创建应用、获取凭证、配置权限
  4. 核心接口详解:发起审批、查询实例、回调通知
  5. 代码实战:PHP封装钉钉审批流SDK(附完整示例)
  6. 高频踩坑与性能优化(含超时、幂等、签名)
  7. 常见问题问答(FAQ)
  8. 总结与延伸学习建议

钉钉审批流到底是什么?—— 核心概念与适用场景

钉钉审批流是钉钉开放平台提供的一套企业级工作流引擎,允许开发者通过API创建、查询、撤销审批实例,并接收审批结果回调,它解决了企业内部“请假、报销、采购、合同”等场景的线上化流转问题。

对于PHP开发者来说,核心需求通常是:将自建系统(如OA、ERP)中的业务数据,通过钉钉审批流实现多人会签、或签、条件分支等复杂流程

适用场景举例:

  • 员工在自研系统中发起请假,审批人收到钉钉待办。
  • 财务系统推送报销单,部门主管 + 财务总监依次审批。
  • 合同系统发起用印申请,法务与总经理并行审批。

PHP对接钉钉审批流的三种主流方案对比

方案 优点 缺点 适合场景
官方API + 自研封装 灵活、可控、无额外依赖 开发量大需处理细节 有后端团队、需要深度定制
使用开源SDK(如dingtalk-sdk) 开发快、社区维护 依赖第三方,需审查代码 中小型项目、追求效率
低代码/HTTP触发(如钉钉连接器) 零代码、配置即用 灵活性差、数据模型受限 轻量场景、快速验证

本文推荐方案1,因为PHP生态中针对钉钉审批流的成熟SDK较少,且自研封装能让你彻底掌握底层逻辑。


实战前置准备:创建应用、获取凭证、配置权限

在写代码之前,必须完成以下3步:

1 创建企业内部应用

  • 登录 钉钉开放平台 → 开发者后台 → 创建应用。
  • 记录 AppKeyAppSecret(后续获取access_token用)。

2 配置权限范围

  • 在应用权限管理中,必须添加:
    • Contact.User.Read(获取用户信息)
    • Process.Instance.Create(发起审批)
    • Process.Instance.Read(读取实例)
    • Process.Instance.Write(撤销/审批)
  • 申请权限后需要管理员审批,开发阶段可选用“测试企业”。

3 设置服务器出口IP白名单

钉钉API要求请求IP在白名单内,否则返回Forbidden错误,务必在应用安全设置中配置服务器公网IP。


核心接口详解:发起审批、查询实例、回调通知

钉钉审批流最核心的3个接口(基于旧版API v1.0,新版为v2.0,但逻辑一致):

1 获取AccessToken

GET https://oapi.dingtalk.com/gettoken?appkey=xxx&appsecret=xxx

返回access_token,有效期7200秒,需缓存。

2 发起审批实例(processinstance/create

必传参数:

  • process_code:审批流模板编号(在钉钉管理后台-审批模板中获取)
  • originator_user_id:发起人userid
  • dept_id:发起人部门ID
  • form_component_values:表单值数组,格式如:
    [
    {"name":"请假类型","value":"年假"},
    {"name":"开始时间","value":"2025-01-01 09:00"}
    ]
  • approvers:审批人列表(逗号分隔),或使用approvers_v2(支持会签/或签)

3 查询审批实例详情(processinstance/get

传入process_instance_id,返回包括当前审批人、状态(running/completed/terminated)、操作记录等。

4 回调通知

  • 在应用后台配置审批事件回调URL(如https://yourdomain.com/webhook/dingtalk)。
  • 钉钉会推送bpms_instance_change事件,需做加解密(AES + token)+ 响应success字符串。

代码实战:PHP封装钉钉审批流SDK(附完整示例)

我们先写一个基础的DingTalkClient类,包含认证和发起审批方法。

<?php
class DingTalkClient {
    private $appKey;
    private $appSecret;
    private $accessToken;
    private $tokenExpireTime = 0;
    public function __construct($appKey, $appSecret) {
        $this->appKey = $appKey;
        $this->appSecret = $appSecret;
    }
    // 获取access_token(带缓存)
    public function getAccessToken() {
        if ($this->accessToken && time() < $this->tokenExpireTime) {
            return $this->accessToken;
        }
        $url = 'https://oapi.dingtalk.com/gettoken?appkey=' . $this->appKey . '&appsecret=' . $this->appSecret;
        $result = $this->httpRequest($url);
        if (isset($result['access_token'])) {
            $this->accessToken = $result['access_token'];
            $this->tokenExpireTime = time() + 7000; // 提前200秒失效
            return $this->accessToken;
        }
        throw new Exception('获取token失败: ' . json_encode($result));
    }
    // 发起审批
    public function createProcessInstance($processCode, $userId, $deptId, $formData, $approvers) {
        $token = $this->getAccessToken();
        $url = 'https://oapi.dingtalk.com/topapi/processinstance/create?access_token=' . $token;
        $params = [
            'process_code' => $processCode,
            'originator_user_id' => $userId,
            'dept_id' => $deptId,
            'form_component_values' => $formData,
            'approvers_v2' => $approvers // 示例:[{"user_ids":["manager123"],"type":"AND"}]
        ];
        $result = $this->httpRequest($url, json_encode($params), 'POST');
        return $result;
    }
    // 查询审批实例详情
    public function getProcessInstance($instanceId) {
        $token = $this->getAccessToken();
        $url = 'https://oapi.dingtalk.com/topapi/processinstance/get?access_token=' . $token;
        $params = ['process_instance_id' => $instanceId];
        $result = $this->httpRequest($url, json_encode($params), 'POST');
        return $result['process_instance'] ?? null;
    }
    private function httpRequest($url, $postData = null, $method = 'GET') {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
            curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        } else {
            curl_setopt($ch, CURLOPT_HTTPGET, 1);
        }
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
}
// 使用示例
$client = new DingTalkClient('your_appkey', 'your_secret');
$formData = [
    ['name' => '请假事由', 'value' => '生病'],
    ['name' => '请假天数', 'value' => '2']
];
$approvers = [
    ['user_ids' => ['manager001'], 'type' => 'AND']
];
$result = $client->createProcessInstance('PROC-XXXX', 'user123', 123456, $formData, $approvers);
print_r($result);

关键点解释

  • approvers_v2中的AND表示会签(所有人都要审批),OR表示或签(一人通过即可)。
  • 表单控件Name必须与钉钉后台审批模板的控件标识完全一致(通常是中文)。

高频踩坑与性能优化

1 坑1:AccessToken缓存问题

若每个请求都重新获取token,会被限流(每秒最多20次)。必须使用Redis或进程内缓存

2 坑2:审批人userid获取

originator_user_id和审批人必须是userid而非手机号或邮箱,可通过user/getbyunionid接口根据unionid换取。

3 坑3:回调URL需要内网穿透测试

本地开发时使用ngrokcpolar映射公网地址,并确保回调URL能响应success(不带引号)。

4 性能优化建议

  • 开启curl长连接(CURLOPT_TCP_KEEPALIVE),复用TCP。
  • 批量查询审批状态时,使用processinstance/batchget(每次最多50个)。
  • 日志记录请求耗时与钉钉返回的requestid,便于排障。

常见问题问答(FAQ)

Q1:PHP发起审批时报错“审批模板不存在”,怎么排查?

检查process_code是否从钉钉管理后台复制完整,注意大小写,另需确认应用是否有权限访问该模板(在审批模板的“可见范围”中添加应用)。

Q2:如何实现“指定角色”审批,而非指定人?

使用approvers_v2中的type:"AND" + user_ids为空,同时传入cc_position参数?不,正确做法是使用approvers_v2acting_type字段,或者将角色成员通过接口动态拉取并传入具体人员。

Q3:钉钉回调事件验签失败怎么办?

确保正确使用AES密钥解密,且加密方式为官方要求的“加解密库”,PHP实现可参考官方的DingTalkEncryptor类,注意Token和AesKey必须与应用后台完全一致。

Q4:审批完成后如何自动通知业务系统?

在回调事件中监听bpms_instance_change状态为finish,然后写队列触发业务逻辑(如更新订单状态、发送邮件)。


总结与延伸学习建议

通过本文,你已经掌握了PHP对接钉钉审批流的全链路:从创建应用到发起审批,再到处理回调,核心要点是:

  • 使用官方API自研封装,保持灵活性。
  • 妥善处理token缓存和错误重试。
  • 利用回调机制实现状态同步而非轮询。

延伸建议

  • 深入学习钉钉新版API v2.0(路径/v2.0/processes),支持更多高级特性如条件分支。
  • 如果审批流逻辑复杂(并发、驳回重填),考虑引入状态机设计模式管理审批生命周期。
  • 可部署为微服务,通过RabbitMQ解耦审批与业务主链路。

就打开你的IDE,尝试用PHP跑通第一个审批实例吧!如果有具体报错,欢迎在评论区留言讨论。


(文章完)

抱歉,评论功能暂时关闭!