今天就说下这个回复被动消息超时的解决办法。微信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;
}
?>
本文的目的是让后来者不少走弯路





