前言
最近在做企业微信开发,踩了一点点坑,但是首先要明确的是官方文档的说明非常详细,遇到了问题要仔细看文档。
对比公众号开发的差异
相比较公众号开发,企业微信要灵活的多的多,它提供了非常丰富的API。和公众号开发时差不多,接入服务器时要验证token。差别是企业微信更像是一个容器,它里有非常多的应用,每个应用都拥有自己的应用ID,都可以做服务器的接入。因此做开发时每个引用都有自己的access_token。
下面是一个新用户自动回复欢迎词的案例
1:验证URL有效性
2:对事件作出响应
通过企业微信API文档->服务端API->外部联系人->变更回调
可以得知,我们需要设置回调服务器地址
1:验证URL有效性。通过官方文档得知参数配置如下
初次接入服务器时企业微信作出以下响应
我们需要做的是对URL作出解密并且返回(打印)出明文告知服务器我们是有效的服务器地址。(对)
以下是解密并且输出明文的代码
<?php
include_once ('WXBizMsgCrypt.php');
include_once ('DataTransform.php');
/**
* 企业微信后台 客户联系->接收事件 设置的参数
* 回调参考文档 https://work.weixin.qq.com/api/doc/90000/90135/92128
* 欢迎语参考文档 https://work.weixin.qq.com/api/doc/90000/90135/92137
*/
// 应用token
$token = "RfnjBvcdDmIppljF2Md2QmKS6";
// 应用AESKey的Base64编码,固定长度43位。
$encodingAesKey = "CWsFeUCkh1bg7YHepktzKumSUxPN15Hou63X41lHuWO";
// 应用ID
$corpId = "ww4dc719d22867134d";
// 应用access_token
$access_token = "g6WEjYCrP6HQa8dmbxwQlCLQHWFn-PhVh7CPmAOK-xZsbnUqYIWW980c4hFJbFmQ6U6jLJGyrR9lY-2Jsx4V9fzv5kSWC5Xb3UTjI07Yx7E9PXs7RfpoWCSfMa0RwuRWD5e-JUYzj5gpO5YPKKKjKAGWoR_I0_XNsC8oHrDeQceExJJc1CJazFmMjGWgp9F7v1L9xuJfP-kFcxzMhEttgg";
// 日志
$logs = "";
// URL参数
$signature = $_GET['msg_signature'];// url的msg_signature 签名
$timestamps = $_GET['timestamp'];// url的timestamp 时间戳
$nonce = $_GET['nonce'];// url的nonce 随机字符串
// 接口接入--- start ----
$echo_str = ''; // 需要返回的明文
$wxcpt = new WXBizMsgCrypt($token, $encodingAesKey, $corpId); // 官方提供工具类
if (isset($_GET['echostr'])) {
$msg_encrypt = $_GET['echostr']; // 初次接入,密文附在URL上
$errCode = $wxcpt->VerifyURL($signature, $timestamps, $nonce, $msg_encrypt, $echo_str); // 获取明文
if ($errCode == 0) {
echo $echo_str; // 返回明文,确认接入
} else {
$logs .= "ERR_CONNECT|" . $errCode ."\n\n";
}
toLog($logs);
return null;
}
// --- end ---
die();
// 处理回调事件 --- start ---
成功接入接口后,企业微信通讯录发生变化,就会以时间的形式通知到我们的URL了。
官方事件回调格式
下面是对新用户发出欢迎信息的代码
// 解析后的明文
$sMsg = "";
// POST XML
$postXML = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
// 验证签名,如假消息直接 return null
$errCode = $wxcpt->DecryptMsg($signature, $timestamps, $nonce, $postXML, $sMsg);
if ($errCode != 0) {
$logs .= "ERR: " . $errCode . "\n\n";
toLog($logs);
return null;
}
// 分类处理
$dt = new DataTransform();
$arr = $dt->xmlToArray($sMsg);
// 事件---添加新用户
if (isset($arr['WelcomeCode'])) {
if($arr['UserID']=='yuo') {
$welcomeCode = $arr['WelcomeCode'];
$url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token=".$access_token;
$content = '您好,很高兴为您服务';
$data = '{
"welcome_code":"'.$welcomeCode.'",
"text": {
"content":"'.$content.'"
}
}';
// 请求官网接口
$res = send_post($url,$data,1);
$logs .= "\nREQUEST\n"."URL|".$url."\n"."RES|".$res."\n\n";
}
}
// 写入日志
$logs .= "原文|".$postXML."\n";
$logs .= "明文|".$sMsg."\n";
toLog($logs);
/**
* 发送
*
* @param $url
* @param $post_data
* @return string
*/
function send_post($url, $data = NULL, $json = false)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
if (!empty($data)) {
if($json && is_array($data)) {
$data = json_encode( $data );
}
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
if($json){ //发送JSON数据
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json; charset=utf-8',
'Content-Length:' . strlen($data)
)
);
}
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$res = curl_exec($curl);
$errorno = curl_errno($curl);
if ($errorno) {
return array('errorno' => false, 'errmsg' => $errorno);
}
curl_close($curl);
return $res;
}
/**
* log
* @param $logs string
*/
function toLog(string $logs)
{
$val = "";
$currentDateTime = date('YmdHis',time());
$currentDate = date('Ymd',time());
$fileName = "ioslog/".$currentDate;//文件名称
@$data = fopen($fileName,'a+');//添加不覆盖,首先会判断这个文件是否存在,如果不存在,则会创建该文件,即每天都会创建一个新的文件记录的信息
$val.= $currentDateTime;
$val .= $logs;
fwrite($data,$val);//写入文本中
fclose($data);
}