对于微信公众号的文档,呃~ 就不过多的吐槽了。
说起开发流程本身是很简单的,申请公众号 -- 编写代码 -- 配置域名【就是token验证,检查服务器的有效性】。
首先介绍一下在开发中需要的必要操作
(一)编写后台接口
直接上示例代码吧:
class WeiChart
{
protected $TOKEN = 'mytoken';//公众号后台配置url时定义的token 可以为任意符合规定的字符
protected $APPID = 'APPID';//你的appid
protected $SECRETE = 'SECRETE';//你的密钥
// 入口方法
public function wxAction()
{
//判断请求类型 验证token 或 推送事件回调
if (isset($_GET['echostr'])){
if ($this->checkSignature()) {
$echoStr = $_GET["echostr"];
echo $echoStr;
exit;
} else {
echo '失败';
}
}else {
// 事件回调
$this->responseMsg();
}
}
// 验证token 【服务器是否有效】
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = $this->TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr == $signature) {
return true;
} else {
return false;
}
}
// 处理微信相关信息请求和响应
private function responseMsg()
{
// $postStr = $GLOBALS['HTTP_RAW_POST_DATA']; //php7.0以下可用
$postStr = file_get_contents("php://input"); // php7.0以上包括7.0
if (!empty($postStr)){
libxml_disable_entity_loader(true);
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
switch ($postObj->MsgType) {
case 'text':
// 处理文本信息方法
break;
case 'image':
// 处理图片消息
break;
case 'location':
// 处理位置消息
break;
case 'event':
// 处理事件消息
$this->doEvent($postObj);
break;
default:
break;
}
}
}
// 处理事件消息
private function doEvent($postObj)
{
switch (strtolower($postObj->Event)){
case 'subscribe':
// 关注第一次
$this->_subscribe($postObj);
break;
case 'unsubscribe':
// 取消关注
$this->_unsubscribe($postObj);
break;
case 'scan':
// 已关注
$this->_scan($postObj);
break;
case 'click':
// 自定义菜单点击事件
break;
default:
break;
}
}
// 关注公众号
private function _subscribe($postObj)
{
$param['scene_id'] = str_replace("qrscene_", "", $postObj->EventKey);
$param['openid'] = $postObj->FromUserName; // 点击关注的用户openid
$content = '谢谢你关注我';
$str = $this->_msgText($postObj->FromUserName, $postObj->ToUserName, $content);
}
// 定义 回复文字,图片,视频,音乐,新闻等等,相应的回复模板
private $_msg_template = array(
'text' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>',//文本回复XML模板
'image' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[%s]]></MediaId></Image></xml>',//图片回复XML模板
'music' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[music]]></MsgType><Music><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><MusicUrl><![CDATA[%s]]></MusicUrl><HQMusicUrl><![CDATA[%s]]></HQMusicUrl><ThumbMediaId><![CDATA[%s]]></ThumbMediaId></Music></xml>',//音乐模板
'news' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>%s</ArticleCount><Articles>%s</Articles></xml>',// 新闻主体
'news_item' => '<item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item>',//某个新闻模板
);
// 发送文本消息
private function _msgText($to, $from, $content) {
$response = printf($this->_msg_template['text'], $to, $from, time(), $content);
return $response;
}
}
上述代码基本实现了token验证及消息推送;
(二)后台配置url
这里的url要确保可以访问到上述代码的wxAction方法,且这里的Token与代码中定义的$TOKEN值一致;这里我必须要强调一下这里配置的url的作用:1)验证开发者服务器的有效性;2)作为扫码关注公众号的事件推送回调地址;
接下来说一下我开发中踩过的坑,希望对大家有所帮助能够在开发过程中少走弯路。这里我说明一下我开发用的时tp框架。
(一)路由问题
Token验证是get请求而事件推送回调时却是post,此时如果你要是定义路由我想一定会想到用'any',但是我试过了不行。不知道为什么,我反正是蒙了袄。建议开启混合模式路由在公众号后台配置url时用普通路由就欧克了;
(二)获取事件推送回调参数问题
在获取参数时有两个方法$GLOBALS['HTTP_RAW_POST_DATA']、file_get_contents("php://input");
$GLOBALS['HTTP_RAW_POST_DATA'] 在php7以后已经被移除了所以就不再有用;
file_get_contents("php://input") 拼了老命的建议用这个方法,官方也推荐我们使用php://input方式进行读取流。
我开始使用的是第一种死活获取不到,后来换成第二种这才拿到想要的数据。
(三)获取用户信息问题
微信公众号文档中获取access_token 和用户信息的方式都是网页授权的方式而我们这里用到的却不是,所以文档中的提供的接口就不能用了。
此时应该使用下面这种个url
$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='. $this->APPID .'&secret='.$this->SECRETE;
当我们使用上述的方式获取access_token 后已经不可以使用网页授权获取用户信息的方式获取用户信息否则会一直返回40001错误码,因为在许多地方看到有人就是这么写的。我在这里想提醒强调一下,希望大家都不要被误导了。
正确的获取用户信息url如下:
$url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='. $token .'&openid='. $openid .'&lang=zh_CN';
至此我走完了所有的曲折,看见了属于我的光明。特别要说一下就是在回调中该怎么调试file_put_contents() 是个极好用的函数。