PHP 微信公众号基本操作类
目前已集成:
- 接收、回复被动消息
- 创建自定义菜单
- 获取用户基本信息
- 网页授权并获取用户基本信息
- 调用微信JS-SDK
<?php /** * 微信公众号基本操作类 * 作者:何效名 */ class WeChat { private $appId = ''; private $appSecret = ''; private $jsApiList = []; private $jsHtmlList = []; public function __construct($appId, $appSecret) { $this -> appId = $appId; $this -> appSecret = $appSecret; } /** * 被动接收消息 */ public function getMessage() { if($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_GET["signature"])) { $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $tmpArr = array('xmsb520', $timestamp, $nonce); sort($tmpArr, SORT_STRING); $tmpStr = implode($tmpArr); $tmpStr = sha1($tmpStr); if($tmpStr == $signature) { return $_GET['echostr']; } else { return false; } } if($xml = file_get_contents('php://input')) { $this -> writeMsg($xml, 'getMessage'); return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); } return false; } /** * 回复被动消息 */ public function replyMessage($ToUserName, $FromUserName, $ContentArr) { $dataArr = []; $dataArr['ToUserName'] = $ToUserName; $dataArr['FromUserName'] = $FromUserName; $dataArr['CreateTime'] = time(); $dataArr = array_merge($dataArr, $ContentArr); $dataXml = $this -> arr2xml($dataArr); return $dataXml; } /** * 生成消息主体 */ public function createTextMessage($Content) { $messageArr = []; $messageArr['MsgType'] = 'text'; $messageArr['Content'] = $Content; return $messageArr; } public function createImageMessage($MediaId) { $messageArr = []; $messageArr['MsgType'] = 'image'; $messageArr['Image'] = []; $messageArr['Image']['MediaId'] = $MediaId; return $messageArr; } public function createVoiceMessage($MediaId) { $messageArr = []; $messageArr['MsgType'] = 'voice'; $messageArr['Voice'] = []; $messageArr['Voice']['MediaId'] = $MediaId; return $messageArr; } public function createVideoMessage($MediaId, $Title = '', $Description = '') { $messageArr = []; $messageArr['MsgType'] = 'video'; $messageArr['Video'] = []; $messageArr['Video']['MediaId'] = $MediaId; $messageArr['Video']['Title'] = $Title; $messageArr['Video']['Description'] = $Description; return $messageArr; } public function createMusicMessage($ThumbMediaId, $Title = '', $Description = '', $MusicURL = '', $HQMusicUrl = '') { $messageArr = []; $messageArr['MsgType'] = 'music'; $messageArr['Music'] = []; $messageArr['Music']['ThumbMediaId'] = $ThumbMediaId; $messageArr['Music']['Title'] = $Title; $messageArr['Music']['Description'] = $Description; $messageArr['Music']['MusicURL'] = $MusicURL; $messageArr['Music']['HQMusicUrl'] = $HQMusicUrl; return $messageArr; } public function createNewsMessage($Title, $Description, $PicUrl, $Url) { $messageArr = []; $messageArr['MsgType'] = 'news'; $messageArr['Articles'] = []; if(!is_array($Title)) { $messageArr['ArticleCount'] = 1; $messageArr['Articles']['item'] = []; $messageArr['Articles']['item']['Title'] = $Title; $messageArr['Articles']['item']['Description'] = $Description; $messageArr['Articles']['item']['PicUrl'] = $PicUrl; $messageArr['Articles']['item']['Url'] = $Url; } else { $messageArr['ArticleCount'] = count($Title); foreach($Title as $key => $value) { $tmpArr = []; $tmpArr['item'] = []; $tmpArr['item']['Title'] = $Title[$key]; $tmpArr['item']['Description'] = $Description[$key]; $tmpArr['item']['PicUrl'] = $PicUrl[$key]; $tmpArr['item']['Url'] = $Url[$key]; $messageArr['Articles'][] = $tmpArr; } } return $messageArr; } /** * 创建自定义菜单 */ public function createMenu($menuData = []) { $accessToken = $this -> getAccessToken(); $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={$accessToken}"; if(empty($menuData)) { $menuData = [ 'button' => [ [ 'type' => 'click', 'name' => '菜单', 'key' => 'xmsb' ], [ 'name' => '多级菜单', 'sub_button' => [ [ 'type' => 'view', 'name' => '跳转链接', 'url' => 'http://www.baidu.com' ], [ 'type' => 'view', 'name' => '跳转链接', 'url' => 'http://www.soso.com' ] ] ] ] ]; } $menuData = json_encode($menuData, JSON_UNESCAPED_UNICODE); $header = [ 'Content-Type: application/json', 'Content-Length: ' . strlen($menuData) ]; $result = $this -> curl($url, $menuData, $header); $result = json_decode($result, true); if($result['errcode'] == 0) { return true; } else { $this -> writeError($result, 'createMenu'); return false; } } /** * 获取用户基本信息 */ public function getUserInfo($openId) { if($accessToken = $this -> getAccessToken()) { $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$accessToken}&openid={$openId}&lang=zh_CN"; $result = $this -> curl($url); $result = json_decode($result, true); if(empty($result['errcode'])) { return $result; } else { $this -> writeError($result, 'getUserInfo'); return false; } } else { return false; } } /** * 网页授权并获取用户信息 */ public function getWebUserinfo() { if(empty($_GET['code'])) { $appId = $this -> appId; $thisUrl = $this -> getUrl(); $redirectUri = urlencode($thisUrl); $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appId}&redirect_uri={$redirectUri}&response_type=code&scope=snsapi_userinfo#wechat_redirect"; header("Location:" . $url); die(); } else { if($accessToken = $this -> getWebAccessToken($_GET['code'])) { $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$accessToken['access_token']}&openid={$accessToken['openid']}&lang=zh_CN"; $result = $this -> curl($url); $result = json_decode($result, true); if(empty($result['errcode'])) { $result['openid'] = $accessToken['openid']; return $result; } else { $this -> writeError($result, 'getWebUserinfo'); return false; } } else { return false; } } } /** * 调用JS-SDK */ public function addJsApi($jsArea) { $jsArea = trim($jsArea); preg_match("/^wx\.(\w+)/", $jsArea, $result); if(!empty($result[1])) { $this -> jsApiList[] = $result[1]; $this -> jsHtmlList[] = $jsArea; return $this; } else { $this -> writeError('wx.接口正则匹配失败', 'addJsApi'); return false; } } public function createJsHtml($debug = false) { $debug = $debug ? 'true' : 'false'; if(!empty($this -> jsApiList)) { $time = time(); $jsApiListStr = "['" . implode("', '", $this -> jsApiList) . "']"; $jsNonceStr = 'xmsb_' . mt_rand(10000, 99999) . chr(mt_rand(65, 90)); if($signStr = $this -> getJsSign($jsNonceStr)) { $htmlArea = <<<xmsb <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> wx.config( { debug: {$debug}, appId: '{$this -> appId}', timestamp: {$time}, nonceStr: '{$jsNonceStr}', signature: '{$signStr}', jsApiList: {$jsApiListStr} }); wx.ready(function() { xmsb;
foreach($this -> jsHtmlList as $html) { $htmlArea .= "\n" . $html; } $htmlArea .= <<<xmsb }); </script> xmsb; return $htmlArea; } else { return false; } } else { $this -> writeError('未添加要调用的wx.接口', 'createJsHtml'); return false; } } /** * 获取Access token */ private function getAccessToken() { if(empty($_COOKIE['wechat_cookie_' . $_SERVER['SERVER_NAME']])) { if($accessToken = $this -> refreshAccessToken()) { return $accessToken; } else { return false; } } else { return $_COOKIE['wechat_cookie_' . $_SERVER['SERVER_NAME']]; } } /** * 获取网页授权Access token */ private function getWebAccessToken($code) { $appId = $this -> appId; $appSecret = $this -> appSecret; $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appId}&secret={$appSecret}&code={$code}&grant_type=authorization_code"; $result = $this -> curl($url); $result = json_decode($result, true); if(empty($result['errcode'])) { return $result; } else { $this -> writeError($result, 'getWebAccessToken'); return false; } } /** * 获取JS-SDK签名 */ private function getJsSign($jsNonceStr) { if($accessToken = $this -> getAccessToken()) { $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$accessToken}&type=jsapi"; $result = $this -> curl($url); $result = json_decode($result, true); if(empty($result['errcode'])) { $signArr = [ 'noncestr' => $jsNonceStr, 'jsapi_ticket' => $result['ticket'], 'timestamp' => time(), 'url' => $this -> getUrl() ]; ksort($signArr); $signStr = ''; foreach($signArr as $key => $value) { $signStr .= "{$key}={$value}&"; } $signStr = sha1(trim($signStr, '&')); return $signStr; } else { $this -> writeError($result, 'getJsSign'); return false; } } else { return false; } } /** * 刷新Access token */ private function refreshAccessToken() { $appId = $this -> appId; $appSecret = $this -> appSecret; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}"; $result = $this -> curl($url); $result = json_decode($result, true); if(empty($result['errcode'])) { setcookie('wechat_cookie_' . $_SERVER['SERVER_NAME'], $result['access_token'], time() + $result['expires_in'] - 100); return $result['access_token']; } else { $this -> writeError($result, 'refreshAccessToken'); return false; } } /** * 获取当前URL */ private function getUrl() { $url = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; if($_SERVER['SERVER_PORT'] != '80') { $url .= $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI']; } else { $url .= $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; } return $url; } /** * 数组转XML */ private function arr2xml($array, $root = true) { $str = ""; if($root) $str .= "<xml>"; foreach($array as $key => $val) { if(is_array($val)) { if(is_numeric($key)) { $trueKey = key($val); $child = $this -> arr2xml($val[$trueKey], false); $str .= "<{$trueKey}>{$child}</{$trueKey}>"; } else { $child = $this -> arr2xml($val, false); $str .= "<{$key}>{$child}</{$key}>"; } } else { if($key == 'CreateTime') { $str .= "<{$key}>{$val}</{$key}>"; } else { $str .= "<{$key}><![CDATA[{$val}]]></{$key}>"; } } } if($root) $str .= "</xml>"; return $str; } /** * 记录日志 */ private function writeLog($data, $fileName) { $dir = './wechat_log/' . date('Y-m') . '/' . date('d') . '/'; $path = $dir . $fileName . '_' . date('H') . '.txt'; if(!file_exists($dir)) { $res = mkdir(iconv('UTF-8', 'GBK', $dir), 0777, true); } $fp = fopen($path, 'a'); $time = '['.date('Y-m-d H:i:s').'] '; $text = var_export($data, true); fwrite($fp, $time.$text."\r\n"); fclose($fp); } private function writeMsg($msg, $method) { $this -> writeLog("{$method} Info:", 'message_log'); $this -> writeLog($msg, 'message_log'); $this -> writeLog("\n", 'message_log'); } private function writeError($errorMsg, $method) { $this -> writeLog("{$method} Error:", 'error_log'); $this -> writeLog($errorMsg, 'error_log'); $this -> writeLog("\n", 'error_log'); } /** * 发送curl */ private function curl($url, $data = [], $header = []) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); if(!empty($header)) { curl_setopt($curl, CURLOPT_HTTPHEADER, $header); } curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); if(!empty($data)) { curl_setopt($curl, CURLOPT_POST, 1); if(is_array($data)) { curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data)); } else { curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($curl); curl_close($curl); return $result; } }
使用方式:
// 引用文件并实例化 require_once('./WeChat.php'); $weChat = new \WeChat('appid', 'secret');
// 接收、回复被动消息 $getMessage = $weChat -> getMessage(); if($getMessage['MsgType'] == 'event' && $getMessage['EventKey'] == 'jianjie') { $content = '公众号简介'; $message = $weChat -> createTextMessage($content); $data = $weChat -> replyMessage($getMessage['FromUserName'], $getMessage['ToUserName'], $message); return $data; }
// 创建自定义菜单 $menuData = [ 'button' => [ [ 'type' => 'click', 'name' => '公众号简介', 'key' => 'jianjie' ], [ 'type' => 'view', 'name' => '官方网站', 'url' => 'https://www.baidu.com' ] ] ]; $createMenu = $weChat -> createMenu($menuData); var_dump($createMenu);
// 获取用户基本信息 $userInfo = $weChat -> getUserInfo('openid'); var_dump($userInfo);
// 网页授权并获取用户基本信息 $userInfo = $weChat -> getWebUserinfo(); var_dump($userInfo);
// 调用微信JS-SDK $api1 = <<<xmsb wx.updateAppMessageShareData( { title: '标题', desc: '描述描述描述描述', link: 'http://www.baidu.com', imgUrl: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png', success: function() { alert('success1'); } }) xmsb; $api2 = <<<xmsb wx.updateTimelineShareData( { title: '标题', link: 'http://www.baidu.com', imgUrl: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png', success: function() { alert('success2'); } }) xmsb; $js = $weChat -> addJsApi($api1) -> addJsApi($api2) -> createJsHtml(); echo "xmsb <br />"; echo $js;
欢迎转载,转载时请注明来源。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异