AI摘要 本文记录了使用PHP对接微信公众平台的开发过程，涵盖了服务器通信验证、access_token的获取与缓存管理、接收用户消息（XML解析）以及被动回复消息（包括文本及超链接）的实现方法，为开发者提供了基础的对接框架与代码示例。 此内容根据文章生成，仅用于文章内容的解释与总结 PHP开发微信公众平台0.微信公众平台官方文档https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.htmlhttps://res.wx.qq.com/op_res/-serEQ6xSDVIjfoOHcX78T1JAYX-pM_fghzfiNYoD8uHVd3fOeC0PC_pvlg4-kmP1.配置与微信服务器的通信1.打开微信公众平台，获取并写入基本信息index.php文件<?php // 微信公众平台基本信息 $token = 'xxxx'; $AppID = 'wx64xxxxxxxxxf014'; $AppSecret = 'd9bxxxxxxxxxxxxxxxxxxxc2'; ?>2.验证消息是否来自微信服务器index.php文件<?php // 微信公众平台基本信息 $token = 'xxxx'; $AppID = 'wx64xxxxxxxxxf014'; $AppSecret = 'd9bxxxxxxxxxxxxxxxxxxxc2'; // 验证消息是否来自微信服务器 // 计算signature微信加密签名，并且与微信请求字段的signature进行值对比，从而证明消息来自微信服务器 if(!empty($_GET['echostr'])){ // 微信通信请求字段 $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $echostr = $_GET['echostr']; // 将token，timestamp，nonce三个字段合为一个数组，并且按照字典排序 $arr = array($token, $timestamp, $nonce); sort($arr,SORT_STRING); // 将数组内容拼接为一个字符串 $str = implode($arr); // 将拼接后的字符串内容进行sha1加密 $sign = sha1($str); // 与微信服务器请求的signature字段内容进行对比，则证明是来自微信服务器的消息 if($sign == $signature){ //将echoStr字段的值返回给微信 echo $echostr; }else{ // 内容不一样则退出 return false; } } ?>3.配置微信公众平台1.登入微信公众平台2.点击基本配置3.在“IP白名单” 点击查看，添加服务器IP地址4.在“服务器配置” 点击修改配置URL：网页地址Token：与php文件中的token一样EncodingAESKey：随机生成一个消息加解密方式：兼容模式5.点击提交-确定6.启用2.获取access_tokenaccess_token有效期为两小时，所以1.5小时就重新刷新获取一次access_tokenaccess_token每天请求上线为2000次，每次请求都获取一次access_token，可以将当前access_token缓存在本地文件1.获取access_token架构：本地没有保存access_token的文件，获取access_token，并且保存在文件本地有保存access_token点文件：判断access_token是否过期：过期了，重新获取access_token，保存替换文件没有过期，直接使用2.创建get_access_token.php文件get_access_token.php文件<?php // 文件名 $file = "access_token.dao"; // access_token获取地址，修改appid和secret $get_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx6xxxxxxxxx014&secret=d9bxxxxxxxxxxxxxxxxxx76c2"; // access_token $access_token = ""; function get_access_token(){ // 引用全局变量 global $file,$get_url,$access_token; // 取网页源码 $html = file_get_contents($get_url); // 取access_token的值 $access_token = json_decode($html)->access_token; // 取当前时间戳 $timer = time(); // 打开access_token保存文件 $fp = fopen($file, "w+"); // 写入时间戳 access_token,以空格分割 fwrite($fp,($timer . " " . $access_token)); // 关闭文件 fclose($fp); return false; } // 如果文件不存在，则执行获取access_token函数 if(!file_exists($file)){ get_access_token(); } // 如果文件存在，则获取当前时间戳减去文本中的时间戳，判断access_token是否超时 $access_token_file = fopen($file,'r'); // 取出文本内容并且按照空格将字符串切割为数组 $text = explode(" ",fread($access_token_file,filesize($file))); fclose($access_token_file); // 取当前时间戳，减去文本中转为整数型的时间戳，如果大于5400（1.5小时），则重新获取一次access_token_file if((time() - ((int)$text[0])) >= 5400){ get_access_token(); } $access_token = $text[1]; return false; ?>3.获取用户发送的消息官方文档：消息事件：https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html推送事件：https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html微信服务器会发送两种消息给开发者服务器get - 验证服务器的有效性post - 微信服务器会将用户发送的数据以post请求都方式发送到服务器，但是不能用post来接收消息调试代码：index.php文件<?php // 执行php文件得到可用access_token include "get_access_token.php"; // 微信公众平台基本信息 $token = 'xxxx'; $AppID = 'wx64xxxxxxxxxf014'; $AppSecret = 'd9bxxxxxxxxxxxxxxxxxxxc2'; // 验证消息是否来自微信服务器 // 计算signature微信加密签名，并且与微信请求字段的signature进行值对比，从而证明消息来自微信服务器 if(!empty($_GET['echostr'])){ // 微信通信请求字段 $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $echostr = $_GET['echostr']; // 将token，timestamp，nonce三个字段合为一个数组，并且按照字典排序 $arr = array($token, $timestamp, $nonce); sort($arr,SORT_STRING); // 将数组内容拼接为一个字符串 $str = implode($arr); // 将拼接后的字符串内容进行sha1加密 $sign = sha1($str); // 与微信服务器请求的signature字段内容进行对比，则证明是来自微信服务器的消息 if($sign == $signature){ //将echoStr字段的值返回给微信 echo $echostr; }else{ // 内容不一样则退出 return false; } } // 接收用户对公众号发送的信息 function get_info(){ // 接收xml数据 $GLOBALS['HTTP_RAW_POST_DATA']，如果用不了就使用file_get_contents('php://input') // 或者找到php.ini配置文件，修改配置为always_populate_raw_post_data = On // $xml = $GLOBALS['HTTP_RAW_POST_DATA']; $xml = file_get_contents('php://input'); // 如果$xml有数据才执行 if(!empty($xml)){ // 临时存放字符串数据 $text = $xml; // 防止xml注入，禁止xml实体解析 libxml_disable_entity_loader(true); // 使用simpleXML解析该xml字符串 $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); // 通过元素MsgType来判断该微信服务器转发的消息类型 switch ($xml->MsgType){ // 接收到事件消息 case 'event': // 公众号订阅事件 if ($xml->Event=='subscribe'){ } // 公众号取消订阅事件 if ($xml->Event=='unsubscribe'){ } break; // 接收到文本消息 case 'text': // 调试是否正常接收文本 $fp = fopen("1.txt","w+"); fwrite($fp,$text); fclose($fp); break; // 接收到图片消息 case 'image': break; //接收到语音消息 case 'voice': break; //接收到视频消息 case 'video': break; //接收到短视频消息 case 'shortvideo': break; //接收到位置消息 case 'location': break; //接收到链接消息 case 'link': break; } } } get_info(); ?>给微信公众号发送一条消息，大概内容如下1.txt gh_5xxxxxxxxxxxxxxe7 oKMn3wXdxxxxxxxxxxxxxxxbrdx2-tqk 1649653429 text 111 2361xxxxxxxx36426 [binary] 精简代码：index.php文件<?php // 执行php文件得到可用access_token include "get_access_token.php"; // 微信公众平台基本信息 $token = 'xxxx'; $AppID = 'wx64xxxxxxxxxf014'; $AppSecret = 'd9bxxxxxxxxxxxxxxxxxxxc2'; // 验证消息是否来自微信服务器 // 计算signature微信加密签名，并且与微信请求字段的signature进行值对比，从而证明消息来自微信服务器 if(!empty($_GET['echostr'])){ // 微信通信请求字段 $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $echostr = $_GET['echostr']; // 将token，timestamp，nonce三个字段合为一个数组，并且按照字典排序 $arr = array($token, $timestamp, $nonce); sort($arr,SORT_STRING); // 将数组内容拼接为一个字符串 $str = implode($arr); // 将拼接后的字符串内容进行sha1加密 $sign = sha1($str); // 与微信服务器请求的signature字段内容进行对比，则证明是来自微信服务器的消息 if($sign == $signature){ //将echoStr字段的值返回给微信 echo $echostr; }else{ // 内容不一样则退出 return false; } } // 接收用户对公众号发送的信息 function get_info(){ // 接收xml数据 $GLOBALS['HTTP_RAW_POST_DATA']，如果用不了就使用file_get_contents('php://input') // 或者找到php.ini配置文件，修改配置为always_populate_raw_post_data = On // $xml = $GLOBALS['HTTP_RAW_POST_DATA']; $xml = file_get_contents('php://input'); // 如果$xml有数据才执行 if(!empty($xml)){ // 防止xml注入，禁止xml实体解析 libxml_disable_entity_loader(true); // 使用simpleXML解析该xml字符串 $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); // 通过元素MsgType来判断该微信服务器转发的消息类型 switch ($xml->MsgType){ // 接收到事件消息 case 'event': // 公众号订阅事件 if ($xml->Event=='subscribe'){ } // 公众号取消订阅事件 if ($xml->Event=='unsubscribe'){ } break; // 接收到文本消息 case 'text': break; // 接收到图片消息 case 'image': break; //接收到语音消息 case 'voice': break; //接收到视频消息 case 'video': break; //接收到短视频消息 case 'shortvideo': break; //接收到位置消息 case 'location': break; //接收到链接消息 case 'link': break; } } } get_info(); ?>4.根据用户发送的消息进行回复官方文档：https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html定义一个全局发消息模板index.php // 全局变量定义消息发送模板 $send_info_array = array( // %s 代表变量，之后可以使用spritf传值 // 文本消息的发送模板 "text" => " %s %s %s text %s " );定义一个发送文本消息的函数，形参$xml接受$xml内容index.php // 定义用户关注公众号函数 function user_subscribe($xml){ // 引用全局变量模板 global $send_info_array; $cont = "此乃缘，妙，不可言"; $res = sprintf($send_info_array['text'],$xml->FromUserName,$xml->ToUserName,time(),$cont); die($res); } // 定义用户取消关注公众号函数 function user_unsubscribe($xml){ // 引用全局变量模板 global $send_info_array; $cont = "天下分久必合，合久必分，无不散之筵席，有缘再相见"; $res = sprintf($send_info_array['text'],$xml->FromUserName,$xml->ToUserName,time(),$cont); die($res); } // 定义一个发送文本消息的函数，形参$xml接受$xml内容 function send_text_info($xml){ // 引用全局变量模板 global $send_info_array; $cont = $xml->Content; $res = sprintf($send_info_array['text'],$xml->FromUserName,$xml->ToUserName,time(),$cont); die($res); }在事件处添加函数index.php // 接收到事件消息 case 'event': // 公众号订阅事件 if ($xml->Event=='subscribe'){ user_subscribe($xml); } // 公众号取消订阅事件 if ($xml->Event=='unsubscribe'){ user_unsubscribe($xml); } break; // 接收到文本消息 case 'text': // 判断为文本消息后，跳转函数 send_text_info($xml); break;完整代码index.php<?php // 执行php文件得到可用access_token include "get_access_token.php"; // 微信公众平台基本信息 $token = 'xxxx'; $AppID = 'wx64xxxxxxxxxf014'; $AppSecret = 'd9bxxxxxxxxxxxxxxxxxxxc2'; // 验证消息是否来自微信服务器 // 计算signature微信加密签名，并且与微信请求字段的signature进行值对比，从而证明消息来自微信服务器 if(!empty($_GET['echostr'])){ // 微信通信请求字段 $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $echostr = $_GET['echostr']; // 将token，timestamp，nonce三个字段合为一个数组，并且按照字典排序 $arr = array($token, $timestamp, $nonce); sort($arr,SORT_STRING); // 将数组内容拼接为一个字符串 $str = implode($arr); // 将拼接后的字符串内容进行sha1加密 $sign = sha1($str); // 与微信服务器请求的signature字段内容进行对比，则证明是来自微信服务器的消息 if($sign == $signature){ //将echoStr字段的值返回给微信 echo $echostr; }else{ // 内容不一样则退出 return false; } } // 全局变量定义消息发送模板 $send_info_array = array( // %s 代表变量，之后可以使用spritf传值 // 文本消息的发送模板 "text" => " %s %s %s text %s " ); // 定义用户关注公众号函数 function user_subscribe($xml){ // 引用全局变量模板 global $send_info_array; $cont = "此乃缘，妙，不可言"; $res = sprintf($send_info_array['text'],$xml->FromUserName,$xml->ToUserName,time(),$cont); die($res); } // 定义用户取消关注公众号函数 function user_unsubscribe($xml){ // 引用全局变量模板 global $send_info_array; $cont = "天下分久必合，合久必分，无不散之筵席，有缘再相见"; $res = sprintf($send_info_array['text'],$xml->FromUserName,$xml->ToUserName,time(),$cont); die($res); } // 定义一个发送文本消息的函数，形参$xml接受$xml内容 function send_text_info($xml){ // 引用全局变量模板 global $send_info_array; $cont = $xml->Content; $res = sprintf($send_info_array['text'],$xml->FromUserName,$xml->ToUserName,time(),$cont); die($res); } // 接收用户对公众号发送的信息 function get_info(){ // 接收xml数据 $GLOBALS['HTTP_RAW_POST_DATA']，如果用不了就使用file_get_contents('php://input') // 或者找到php.ini配置文件，修改配置为always_populate_raw_post_data = On // $xml = $GLOBALS['HTTP_RAW_POST_DATA']; $xml = file_get_contents('php://input'); // 如果$xml有数据才执行 if(!empty($xml)){ // 防止xml注入，禁止xml实体解析 libxml_disable_entity_loader(true); // 使用simpleXML解析该xml字符串 $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); // 通过元素MsgType来判断该微信服务器转发的消息类型 switch ($xml->MsgType){ // 接收到事件消息 case 'event': // 公众号订阅事件 if ($xml->Event=='subscribe'){ user_subscribe($xml); } // 公众号取消订阅事件 if ($xml->Event=='unsubscribe'){ user_unsubscribe($xml); } break; // 接收到文本消息 case 'text': // 判断为文本消息后，跳转函数 send_text_info($xml); break; // 接收到图片消息 case 'image': break; //接收到语音消息 case 'voice': break; //接收到视频消息 case 'video': break; //接收到短视频消息 case 'shortvideo': break; //接收到位置消息 case 'location': break; //接收到链接消息 case 'link': break; } } } get_info(); ?>在公众号回复内容进行验证，如需其他功能自行看官方文档扩展5.回复带有超链接的文本使用HTML5代码格式"