先上失败的图。
微信官方文档地址:
平台型第三方平台全网发布接入检测说明
问题描述
如果你也跟我一样,在公众号反复测试,都正常自动回复TESTCOMPONENT_MSG_TYPE_TEXT_callback
, 根本不明白为什么检测会通不过。
那么我们的问题一致,这篇文章可以对症下药。
这里直接忽略自动回复功能未能正常实现的情况。
原因总结
网上搜索问题,问题比解决方案多。通过自己爬坑之后,参考了多个前辈的分享,终于明白了检测失败的原因:
我们发送消息的server方搞错啦!
看到这里明白过来的小伙伴不用往下看了。
server方
我使用的是EasyWechat集成的微信开发SDK,但是下面我尽量用伪代码+注释说明这个过程的重点。
这是你的消息处理方法:
public function Event($appid){
//appid微信会在每一个消息中带过来,不用管
$server =$openPlatform->server;
$message = $server->getMessage();
$outMessage=''; //假设这是你的回复内容,实际情况根据关键词匹配自己的回复内容
//找到授权到我们第三方平台的公众号
//省略用appid找已授权的公众号 refresh_token 的步骤
$my_official_refresh_token='';
$my_account = $openPlatform->officialAccount($appid, $my_official_refresh_token);
$my_server = $my_account->server;
$my_server->push($outMessage);
$response = $my_server->serve();
$response->send();
die;
}
上面的代码我特意写成$my_server
, 是为了提醒,这是存在于你系统中的公众号提供的服务。server方是Event传过来的$appid对应的公众号。
检测的时候,就是要用微信的测试公众号server去回复这两则消息。
那么解决办法就有思路了。
解决步骤
再看文档:
微信表述实在是不清晰,无力吐槽。其实顺序是这样的:
- 微信测试公众号会先发送
QUERY_AUTH_CODE:$query_auth_code$
这则消息,这里面的$query_auth_code$
,就是授权code呀
if(strpos($message['Content'], 'QUERY_AUTH_CODE') == 0 && strpos($message['Content'], 'QUERY_AUTH_CODE') !== false){
//按要求,先返回一个''空字符串,echo一下就可以了。
echo '';
$query_auth_code = str_replace('QUERY_AUTH_CODE:', '', $message['Content']);
$authorizer =$penPlatform->handleAuthorize($query_auth_code);
$authorizerInfo = $authorizer['authorization_info'];
//一通操作下来,就得到了微信测试账号的 official_refresh_token
$wxTest_appid = $authorizerInfo['authorizer_appid'];
$wxTest_refresh_token = $authorizerInfo['authorizer_refresh_token'];
//缓存下来,后面的 TESTCOMPONENT_MSG_TYPE_TEXT 自动回复还要用
yii::$app->redis->set($wxTest_appid, $wxTest_refresh_token);
//server方:微信测试公共号
$wxTest_account = $openPlatform->officialAccount($wxTest_appid, $wxTest_refresh_token);
$outMessage = $query_auth_code . '_from_api';
//用wx的server回复吧。注意这里用客服消息回复
$wxTest_account->customer_service($outMessage)
->from($message['ToUserName'])
->to($message['FromUserName'])
->send();
die;
//回复结束
}
- 然后,微信测试公众号会发
TESTCOMPONENT_MSG_TYPE_TEXT
过来
if($message['MsgType']=='text' && $message['Content'] == 'TESTCOMPONENT_MSG_TYPE_TEXT'){
//取出Redis里的token
$weTest_refresh_token = yii::$app->redis->get($appid)
$wxTest_account = $this->openPlatform->officialAccount($appid, $weTest_refresh_token)->customer_service;
//回复普通消息。
//形式代码不重要,EasyWechat里面也有不同的写法。重点是回复消息的server要是微信测试账号的
$wxTest_server = $wxTest_account->server;
$wxTest_server->push($message['Content'] . '_callback');
$response = $wxTest_server->serve();
$response->send();
die;
}
至此,这两条验证就能通过了。
调试的一个小建议
建议多打印log,每一步一个log,然后当提交检测的时候,如果没通过,至少知道是挂在哪儿了,方便定位问题,快速修改
示例代码
最后贴上最终代码,供参考:
- 框架:Yii2
- 微信SDK:
EasyWeChat
SDK,版本:overtrue/easywechat
4.x
//通知事件回调
public function actionEvent($appid)
{
$server =$this->openPlatform->server;
$message = $server->getMessage();
$redis = Yii::$app->redis;
Log::success('msg', Json::encode($message));
if ($message['MsgType']=='text') {
if ($message['Content'] == 'TESTCOMPONENT_MSG_TYPE_TEXT') {
Log::success('收到文本', $message['Content']);
Log::success('cache_appid:' . $appid, $redis->get($appid));
$cuservice = $this->openPlatform->officialAccount($appid, $redis->get($appid))->customer_service;
$cuservice->message($message['Content'] . '_callback')
->from($message['ToUserName'])
->to($message['FromUserName'])
->send();
Log::success('回复文本', $message['Content'] . '_callback');
die;
// return new Text($this->message['Content'] . '_callback');
} elseif (strpos($message['Content'], 'QUERY_AUTH_CODE') == 0 && strpos($message['Content'], 'QUERY_AUTH_CODE') !== false) {
echo '';
Log::success('QUERY_AUTH_CODE文本', $message['Content']);
$query_auth_code = str_replace('QUERY_AUTH_CODE:', '', $message['Content']);
$authorizer =$this->openPlatform->handleAuthorize($query_auth_code);
$authorizerInfo = $authorizer['authorization_info'];
Log::success($authorizerInfo['authorizer_appid'], $authorizerInfo['authorizer_refresh_token']);
// 设置信息缓存
$redis->set($authorizerInfo['authorizer_appid'], $authorizerInfo['authorizer_refresh_token']);
Log::success('authorizer test', '111');
$curOfficialAccount = $this->openPlatform->officialAccount(
$authorizerInfo['authorizer_appid'],
$authorizerInfo['authorizer_refresh_token']
);
if (!$curOfficialAccount) {
Log::fail($authorizerInfo['authorizer_appid'], '实例化测试公众号失败');
}
Log::success('发送前', Json::encode($query_auth_code . '_from_api'));
$curOfficialAccount->customer_service->message($query_auth_code . '_from_api')
->from($message['ToUserName'])
->to($message['FromUserName'])
->send();
Log::success('发送结束', $message['FromUserName']);
die;
}
}
// 找到本系统的授权公众号
$data ='本系统的授权公众号Model';
if (!$data) {
Log::fail('普通通知事件回调', '找不到授权公众号' . $appid);
return 'error';
}
$this->_officialAccount = $this->openPlatform->officialAccount($appid, $data['official_refresh_token']);
$server = $this->_officialAccount->server;
// 处理事件,构造回复内容
$outMessage = '匹配代码隐去';
$server->push($outMessage);
$response = $server->serve();
$response->send();
die;
}
鸣谢
- 感谢EasyWeChat集成的SDK。附上easyWechat消息接口的文档:公众号 消息
- 感谢 pbstudy 的文章经验分享,点击链接可以看到大神的原贴
- 感谢 飞山雪豹 的经验分享,点击链接可以查看大神的原贴
希望可以给遇到这个问题的人提供参考。