今天就说下这个回复被动消息超时的解决办法。微信api 机制就是 ,被动消息回复5秒内回复完成,没有回复算超时 ,它重试3次, 回复内容是符合模板格式的,不是随便回复个文本回去就完了,比如文本需要符合 下面的格式,$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> <FuncFlag>0</FuncFlag> </xml>";如果你是随便回复不符合格式的消息回去, 微信会报错 “该公众号未能提供服务,请稍后重试”
如果需要查询数据库,调用第三方接口,等耗时操作,导致回复时间超过5秒钟。
解决办法就是 ,先用被动接口回复一个空消息 ,再用客服接口发送查询结果。
也可以先用被动接口回复一个提示消息,比如“正在查询,请稍后。。。” ,再用客服接口发送查询结果。
这里需要用到异步 ,或者多任务。
如果不使用异步 , 导致 ,超时 , 或者 客服消息 重复发送 。
不同语言 实现的方式 有差别, 这里就说用php 吧,
php 异步,多任务实现的方式 有几种 ,
1 fsockopen 最快,执行时间在0.1-0.2秒之间,有些主机上并不支持fsockopen
2 curl , 需要设置至少1秒的超时,简单也容易理解, 一般的主机,系统默认支持,如果你租的仅仅是空间,你差不多只能用这个方法了
3 threads , win 和linux下可以支持,但是系统不是默认支持, 需要自己安装,配置
4 多进程, 需要linux环境 支持,
5 ignore_user_abort(true); , 这个不是真正的多任务方式, 只能说也能实现 而已 set_time_limit(0);
今天 我就用curl 实现一个 ,
curl 不是需要设置一个url吗, 对,就是在那个 url指向的 网页里面去 查询,然后发送 客服消息 。
curl 可以 post 也 可以 get ,还 可以 在post的时候 同时传递get的参数 。
配上代码 吧 :
//====customerService.php=====
<?php
$openid="";
if(isset($_POST['openid']))
{
if(!empty($_POST['openid'])){
// echo '您好,',$_POST['openid'].'!';$openid= $_POST['openid'];
} }
$keyword ="";
if(isset($_POST['keyword']))
{
if(!empty($_POST['keyword'])){
// echo '您好,',$_POST['keyword'].'!';$keyword = $_POST['keyword'];
} }
$content = QueryImei($keyword) ;
send_mess($openId, $content);return ;
//查询函数
function QueryImei($keyword) { $response = 查询处理, 这里省略200行代码return $response;
}
//客服消息, 48小时内有客户发来信息
function send_mess($openId, $content) { include_once ('get_access_token.php'); //get_access_token,这个函数 就不贴出来了, 其实 我自己写好了才发现 微信官方的sdk 上面 已经实现了,官方的实现当然很规范$access_token = get_access_token();
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$access_token; $data = '{ "touser":"'.$openId.'", "msgtype":"text", "text": { "content":"'.$content.'" } }';$response = my_https_request($url, $data);
}
function my_https_request($url, $data = null)
{ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);if (!empty($data))
{ curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($curl); curl_close($curl); return $response; }?>
//========index.php===== 这个是微信公众号后台设置的url , 是微信的入口文件==
//这个文件 我省略了 很多东西, 这里是示例 ,目的是让人能看懂
<?php
//接受POST过来的XML数据,或file_get_contents('php://input')
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; //为空则脚本终止 if (empty($postStr)){ echo ""; exit; } else{ //解析XML数据为对象 $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); $from = $postObj->FromUserName; //获取XML消息发送方 $to = $postObj->ToUserName; //获取XML消息接收方$msgType = trim($postObj->MsgType); //获取XML消息类型
$event =null;$title="unknown" ;
/***响应文本或表情信息***/
if($msgType == "text") { $keyword =trim($postObj->Content);$imeiPattern='/^[0-9]{15}$/';
$imei=preg_match($imeiPattern, $keyword);if($imei)
{$content = "正在努力查询中,请稍等片刻";
transmitText($postObj, $content);
$data=array (
'openid' => $from, 'keyword' =>$keyword);
post_custom_msg();
}
exit() ;
}
function post_custom_msg($data) { $url ="http://www.dreammm.net/wchat/customerService.php";$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_POST, 1 ); curl_setopt ( $ch, CURLOPT_HEADER, 0 ); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data ); $return = curl_exec ( $ch ); curl_close ( $ch );//echo $return ;
return;
}
function transmitText($object, $content)
{ $xmlTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> <FuncFlag>0</FuncFlag> </xml>";$result = sprintf($xmlTpl,$object->FromUserName, $object->ToUserName, time(), $content);
echo $result; }?>
本文的目的是让后来者不少走弯路