前言
我的技术同我说钉钉只能有一个回调,我也看了钉钉给到的示例代码,这些代码确实有一定的误导性;
先放一段代码,等下有用
这个示例代码在:DingtalkCrypt 这个类的构造函数,是理解错误还是什么原因呢?
public function __construct($token, $encodingAesKey, $suiteKey)
{
$this->m_token = $token;
$this->m_encodingAesKey = $encodingAesKey;
$this->m_suiteKey = $suiteKey;
}
$token:应用token,
$encodingAesKey:为应用加密串,
$suiteKey:这个是关键是公司ID 或者应用ID
困惑开始
A:在代码中发起注册事件
$c = new DingTalkClient
(
DingTalkConstant::$CALL_TYPE_OAPI,
DingTalkConstant::$METHOD_POST,
DingTalkConstant::$FORMAT_JSON
);
$req = new OapiCallBackRegisterCallBackRequest;
$req->setUrl("https://×××××.com/api/res/dingtalk/callback"); // 接收事件回调的url,必须是公网可以访问的url地址
$req->setAesKey($this->ENCODING_AES_KEY);
$req->setToken($this->TOKEN);
$req->setCallBackTag(json_encode(['bpms_task_change','user_leave_org'])); // 需要注册的回调事件
$resp = $c->execute($req, $this->getToken(),"https://oapi.dingtalk.com/call_back/register_call_back");
exit();
这里相关参数请查询钉钉文档,上面的注册没有涉及为哪个应用注册回调,钉钉的文档也没有任何说明;
B:接受回调处理,采用钉钉提供的 DingtalkCrypt(上面已经看到了),如果$suiteKey =!公司ID,这个DingtalkCrypt-》DecryptMsg 将返回 900005 表示验证失败;DingtalkCrypt 类的 decrypt 方法
public function decrypt($encrypted, $corpid)
{
try {
$ciphertext_dec = base64_decode($encrypted);
$iv = substr($this->key, 0, 16);
/** 以下注释代码块在PHP7.2环境下不可用
$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($module, $this->key, $iv);
$decrypted = mdecrypt_generic($module, $ciphertext_dec);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
*/
$decrypted = openssl_decrypt($ciphertext_dec, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); # 替代方案
} catch (Exception $e) {
return array($this->$DecryptAESError, null);
}
try {
//去除补位字符
$result = $this->decode($decrypted);
//去除16位随机字符串,网络字节序和AppId
if (strlen($result) < 16)
return "";
$content = substr($result, 16, strlen($result));
$len_list = unpack("N", substr($content, 0, 4));
$xml_len = $len_list[1];
$xml_content = substr($content, 4, $xml_len);
$from_corpid = substr($content, $xml_len + 4);
} catch (Exception $e) {
print $e;
return array($this->$DecryptAESError, null);
}
if ($from_corpid != $corpid)
return array($this->$ValidateSuiteKeyError, null);
return array(0, $xml_content);
}
$from_corpid != $corpid 这个地方对返回的内容和传入的suiteKey 进行了校验;
于是给人误导了:钉钉的回调就是按公司进行回调,而不是按应用回调的
如果事实是这样的,钉钉的产品总监应该下岗;
可以看一下:
钉钉回调接口文档
按文档注册回调
1、在钉钉的后台配置应用的:
$token:应用token, $encodingAesKey:为应用加密串,
和回调接口
2、测试回调接口的正确性
3、后台随时可以调整回调事件;
截图说明一切
钉钉的corpId再次让人困惑
回调方法参数说明
{
"processInstanceId":"2bbfb476-7497-4a33-9f27-c2ad14909838", //审批唯一ID
"corpId":"dinga955c2d77886330a00", //这个其实是AppKey
"EventType":"bpms_task_change",//审批事件
"businessId":"202106011351000448657",
"title":"×××产品工单", //工单标题
"type":"start",//审批发起
"createTime":1622526705000,
"processCode":"PROC-F5D9AFCB-60D7-4724-BDF6-DA0A900DC331",//审批模板
"bizCategoryId":"",
"staffId":"693466673", //审批人
"taskId":68811200154// 审批任务ID
}
我们先来看一下这个截图:注意CorpID指代什么内容,其它忽略;
再来看另外一个截图:注意AppKey指代什么内容,其它忽略;
实际事件返回的数据显示:这个corpID = AppKey,也可以等于 corpID=corpID (你手工注册事件时,就发生);
在不同的地方相同的变量corpID有不同的含义,耐人寻味;
在回调事件中你可以区分不同的AppKey走不同的处理;
钉钉的文档,坑太多!