公众号链接:https://mp.weixin.qq.com
开放文档链接:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Explanation_of_interface_privileges.html
需要先注册 - 注册流程不介绍了
1、内网穿透工具
因为需要本地开发和调试,不用线上服务器,所以需要使用内网穿透工具
下载地址:https://natapp.cn
需要实名认真,购买隧道买免费的就行
下载后创建文件config.ini,和natapp.exe放在一个目录里
[default]
# 这里填写 authtoken,购买隧道后可查看
authtoken=XXXXXXXXXXX
loglevel=DEBUG
2、配置apache
在httpd.conf里,搜索Listen,在Listen 80下面,增加Listen 8080,
在httpd-vhosts.conf里,配置
3、重启apache,运行配置
4、启动natapp.exe
Tunnle Status Online表示连接成功
Forwarding 服务器地址->本地地址:端口号
Web Interface 日志地址
5、初次校验
vx.php
php /** * 公众号被动接收处理类 */ $wx = new Wx(); class Wx { // 微信后台设置的token值 const TOKEN = 'tlq'; // 构造方法 public function __construct() { // 判断是否是第一次接入 echostr if (!empty($_GET['echostr'])) { echo $this->checkSign(); } } /** * 初次接入校验 * @return string */ private function checkSign() { // 得到微信公众号发过来的数据 $input = $_GET; // 把echostr放在临时变量中 $echostr = $input['echostr']; $signature = $input["signature"]; // 在数组中删除掉 unset($input['echostr'], $input['signature']); // 在数据中添加一个字段token $input['token'] = self::TOKEN; /*$timestamp = $input["timestamp"]; $nonce = $input["nonce"]; $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr, SORT_STRING);*/ // 进行字段排序 $tmpStr = implode( $input ); // 进行加密操作 $tmpStr = sha1( $tmpStr ); // 进行对比 if( $tmpStr == $signature ){ // 校验成功要返回echostr return $echostr; }else{ return ''; } } }
在微信公众平台-》开发-》基本配置-》服务器配置里,启用或者修改配置
服务器地址(URL):比如我的是http://4cji43.natappfree.cc/wx.php
令牌(Token):这个自己填,要对应代码里的TOKEN
消息加解密密钥:直接生成就好
消息加解密方式:明文
6、测试号申请,https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
知识点:
常用接收消息
# 获取原生请求数据
$xml = file_get_contents('php://input');
# xml转化成对象
$obj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
# sprintf 格式化输出
%s 字符串
%d 数字
全部代码
php /** * 公众号被动接收处理类 */ $wx = new Wx(); class Wx { // 微信后台设置的token值 const TOKEN = 'tlq'; // 构造方法 public function __construct() { // 判断是否是第一次接入 echostr if (!empty($_GET['echostr'])) { echo $this->checkSign(); } else { // 接收处理数据 $this->acceptMsg(); } } /** * 初次接入校验 * @return string */ private function checkSign() { // 得到微信公众号发过来的数据 $input = $_GET; // 把echostr放在临时变量中 $echostr = $input['echostr']; $signature = $input["signature"]; // 在数组中删除掉 unset($input['echostr'], $input['signature']); // 在数据中添加一个字段token $input['token'] = self::TOKEN; /*$timestamp = $input["timestamp"]; $nonce = $input["nonce"]; $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr, SORT_STRING);*/ // 进行字段排序 $tmpStr = implode( $input ); // 进行加密操作 $tmpStr = sha1( $tmpStr ); // 进行对比 if( $tmpStr == $signature ){ // 校验成功要返回echostr return $echostr; }else{ return ''; } } /** * 接收公众号发过来的数据 */ private function acceptMsg() { // 获取原生请求数据 $xml = file_get_contents('php://input'); // 把xml转化为object $obj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); // 写接收日志 $this->writeLog($xml); // 处理回复消息 // 1、判断消息类型 // 2、根据不同的类型,回复不同信息 // 判断类型 $MsgType = $obj->MsgType; /*switch ($MsgType) { case 'text': $str = ''; // 格式化替换输出 $str = sprintf($str, $obj->FromUserName, $obj->ToUserName, time(), '公众号:'.$obj->Content,'123'); // 输出日志 $this->writeLog($str, 2); echo $str; break; }*/ $fun = $MsgType.'Fun'; // 调用方法 //echo $ret = $this->$fun($obj); echo $ret = call_user_func([$this, $fun], $obj); // 写发送日志 $this->writeLog($ret, 2); } // 处理回复文本 private function textFun($obj) { $content = $obj->Content; if ($content == '音乐') { return $this->musicFun($obj); } else { // 回复文本 $content = '公众号:'.$obj->Content; return $this->createText($obj, $content); } } // 回复图片消息 private function imageFun($obj) { $mediaid = $obj->MediaId; return $this->createImage($obj, $mediaid); } // 回复音乐 private function musicFun($obj) { // 图片媒体ID $mediaid = '7Ws_5WHMarFNtPNXH48T5u66AUxC8SbV4jcfbjPJHXhzz5DkTJE-JEGZGywQzlTG'; // 音乐播放地址 $url = 'https://wx.1314000.cn/mp3/ykz.mp3'; return $this->createMusic($obj, $url, $mediaid); } // 生成文本消息XML private function createText($obj, $content) { $xml = ' %s %s %s %s '; // 格式化替换输出 $str = sprintf($xml, $obj->FromUserName, $obj->ToUserName, time(), $content,$obj->MsgId); return $str; } // 生成图片消息XML private function createImage($obj, $mediaid) { $xml = '$s '; // 格式化替换输出 $str = sprintf($xml, $obj->FromUserName, $obj->ToUserName, $mediaid); return $str; } private function createMusic($obj, $url, $mediaid) { $xml = ' %s '; // 格式化替换输出 $str = sprintf($xml, $obj->FromUserName, $obj->ToUserName, time(), '夜空中最亮的星', '一首非常好听的歌', $url, $url, $mediaid); return $str; } /** * @param xml 写入的xml * @param int $flag 标识 1:请求 2:发送 */ private function writeLog($xml, $flag=1) { $flagstr = $flag == 1?'请求':'发送'; $prevstr = '【'.$flagstr.'】'.date('Y-m-d')."-----------------------\n"; $log = $prevstr.$xml."\n-----------------------\n"; // 写日志 FILE_APPEND 追加的形式写 file_put_contents('wx.xml',$log,FILE_APPEND); return true; } }