基于官方开放平台提供的PHP Demo进行钉钉业务事件回调接口注册时常见问题及解决: 1、注册业务事件回调接口请求参数配置说明
call_back_tag:需要监听的事件类型,如:["bpms_task_change", "bpms_instance_change"]
token:加解密需要用到的token,自定义
aes_key:数据加密密钥。用于回调数据的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,可以随机生成
url:接收事件回调的url,必须是公网可以访问的url地址
**2、接收事件回调的url页面加解密配置说明-测试回调URL** ```php //企业内部应用开发可以忽略该项 define("CREATE_SUITE_KEY", "suite4xxxxxxxxxxxxxxx"); //套件key。企业内部应用开发请填写corpid define("SUITE_KEY", "dingxxxxxxxxxxxxxxxx"); //企业内部应用开发可以忽略该项 define("SUITE_SECRET", ""); //加解密需要用到的token,自定义,保持和注册业务事件回调接口register_call_back传递的token值相同即可 define("TOKEN", "123456"); //企业内部应用可以忽略该项 define("APPID", ""); //数据加密密钥。自定义,用于回调数据的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,可以随机生成。保持和注册业务事件回调接口register_call_back传递的AES_KEY值相同即可 define("ENCODING_AES_KEY", "6g5j67qlyl3zvetqxz9jiocdr586fn2zvjp78zls3il"); ```
**3、post请求头(不是json格式)/请使用json格式上传数据** ```php public function curl_post_json($url, $jsonStr){ $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($jsonStr) ) ); $reponse = curl_exec($ch); return json_decode($reponse,1); } PS:如提示post参数需要json类型,请对参数进行json_encode编码下 ```
**4、官方开放平台提供的PHP Demo:pkcs7Encoder.php文件修改** ```php function Prpcrypt($k) { $this->key = base64_decode($k . "="); } 修改为构造函数形式: function __construct($k){ $this->key = base64_decode($k . "="); } ```
**5、官方开放平台提供的PHP Demo:DingtalkCrypt.php文件修改** ```php class DingtalkCrypt { private $m_token; private $m_encodingAesKey; private $m_suiteKey; //注意这里修改为构造函数 function __construct($token, $encodingAesKey, $suiteKey) { $this->m_token = $token; $this->m_encodingAesKey = $encodingAesKey; $this->m_suiteKey = $suiteKey; }
public function EncryptMsg($plain, $timeStamp, $nonce, &$encryptMsg)
{
$pc = new Prpcrypt($this->m_encodingAesKey);
$array = $pc->encrypt($plain, $this->m_suiteKey);
$ret = $array[0];
if ($ret != 0) {
//return $ret;
return ['ErrorCode'=>$ret, 'data' => ''];
}
if ($timeStamp == null) {
$timeStamp = time();
}
$encrypt = $array[1];
$sha1 = new SHA1;
$array = $sha1->getSHA1($this->m_token, $timeStamp, $nonce, $encrypt);
$ret = $array[0];
if ($ret != 0) {
//return $ret;
return ['ErrorCode'=>$ret, 'data' => ''];
}
$signature = $array[1];
$encryptMsg = json_encode(array(
"msg_signature" => $signature,
"encrypt" => $encrypt,
"timeStamp" => $timeStamp,
"nonce" => $nonce
));
//return ErrorCode::$OK;
return ['ErrorCode'=>ErrorCode::$OK, 'data' => $encryptMsg];
}
public function DecryptMsg($signature, $timeStamp = null, $nonce, $encrypt, &$decryptMsg)
{
if (strlen($this->m_encodingAesKey) != 43) {
//return ErrorCode::$IllegalAesKey;
return ['ErrorCode'=>ErrorCode::$IllegalAesKey, 'data' => ''];
}
$pc = new Prpcrypt($this->m_encodingAesKey);
if ($timeStamp == null) {
$timeStamp = time();
}
$sha1 = new SHA1;
$array = $sha1->getSHA1($this->m_token, $timeStamp, $nonce, $encrypt);
$ret = $array[0];
if ($ret != 0) {
//return $ret;
return ['ErrorCode'=>$ret, 'data' => ''];
}
$verifySignature = $array[1];
if ($verifySignature != $signature) {
//return ErrorCode::$ValidateSignatureError;
return ['ErrorCode'=>ErrorCode::$ValidateSignatureError, 'data' => ''];
}
$result = $pc->decrypt($encrypt, $this->m_suiteKey);
if ($result[0] != 0) {
//return $result[0];
return ['ErrorCode'=>$result[0], 'data' => ''];
}
$decryptMsg = $result[1];
//return ErrorCode::$OK;
return ['ErrorCode'=>ErrorCode::$OK, 'data' => $decryptMsg];
}
}
<br>
#### 【注册回调 示例代码】
```php
public function regcallback() {
$post_data = json_encode(array(
'call_back_tag' => ["bpms_task_change", "bpms_instance_change"],
'token' => '123456',
'aes_key' => '6g5j67qlyl3zvetqxz9jiocdr586fn2zvjp78zls3il',
'url' => 'https://www.fity.cn/dingtalk/eventnotice/index',
));
$rs = $this->curl_post_json($this->apihost."/call_back/register_call_back?access_token=".$this->token, $post_data);
var_dump($rs);die;
}
【测试回调URL 示例代码】 ```php public function index(){ define("SUITE_KEY", "dingxxxxxxxxxxxxxxxx"); define("TOKEN", "123456"); define("ENCODING_AES_KEY", "6g5j67qlyl3zvetqxz9jiocdr586fn2zvjp78zls3il");
$signature = $_GET["signature"];
$timeStamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$postdata = file_get_contents("php://input");
$postList = json_decode($postdata,true);
$encrypt = $postList['encrypt'];
$crypt = new DingtalkCrypt(TOKEN, ENCODING_AES_KEY, SUITE_KEY);
$msg = "";
$res = $crypt->DecryptMsg($signature, $timeStamp, $nonce, $encrypt, $msg);
if ($res['ErrorCode'] != 0){//当解密失败记录
Log::e("ErrorCode:" . $res['ErrorCode']);
Log::e(json_encode($_GET));
Log::e(json_encode($encrypt));
Log::e('------------------------------------------------------------------------------------------');
}else{
Log::e("SuccessCode:" . $res['ErrorCode']);
if(!$res['data']){//当返回值为空记录加密字符串信息
Log::e(json_encode($_GET));
Log::e(json_encode($encrypt));
}
Log::e(json_encode($res['data']));
Log::e('------------------------------------------------------------------------------------------');
//创建成功后的回调推送
$eventMsg = json_decode($res['data']);
$eventType = $eventMsg->EventType;
//工作流变动:审批任务开始,结束,转交
if("bpms_task_change" === $eventType){
}
//工作流变动:审批实例开始,结束
if("bpms_instance_change" === $eventType){
}
//注册回调接口 回调URL返回值调试
$res = "success";
$encryptMsg = "";
$encryData = $crypt->EncryptMsg($res, $timeStamp, $nonce, $encryptMsg);
if($encryData['ErrorCode'] != 0){
Log::e("ERR:" . $encryData);
}else{
echo $encryData['data'];
}
}
}
<br>
**【以上问题主要出现在如下API使用过程】**
1、钉钉业务事件回调 - 回调管理API说明
https://ding-doc.dingtalk.com/doc#/serverapi2/pwz3r5
2、回调事件消息体加密
https://ding-doc.dingtalk.com/doc#/faquestions/ltr370