公眾號對接核心在于驗證服務器地址有效性并處理消息響應。1.準備備案域名、php服務器、appid、appsecret及自定義Token;2.驗證服務器地址時,微信發送get請求,開發者需用token、timestamp、nonce排序后sha1加密并與signature對比,成功則返回echostr;3.接收消息時解析post的xml數據,構建回復消息格式并根據關鍵詞響應;4.獲取openid可通過用戶消息中的fromusername或網頁授權流程獲取;5.實現自定義菜單需先獲取access_token,構造json菜單數據,再調用微信接口創建菜單;6.簽名錯誤常見原因包括token不一致、參數排序錯誤、字符串排序方式不對、url不可達等,可逐一排查解決。
公眾號對接,說白了,就是讓你的PHP代碼能跟微信服務器“聊”起來。核心在于驗證服務器地址的有效性,然后根據用戶發送的消息,做出相應的響應。
解決方案
-
準備工作:
- 一個備案過的域名(微信要求)。
- 一個能跑PHP代碼的服務器(廢話,但還是要說)。
- 微信公眾號的開發者ID(AppID)和開發者密碼(AppSecret),在公眾號后臺可以找到。
- Token,自己隨便設置一個,但要記住,后面要用到。
-
驗證服務器地址的有效性:
立即學習“PHP免費學習筆記(深入)”;
這是第一步,也是最重要的一步。微信服務器會向你填寫的URL發送一個GET請求,你需要按照微信的要求,返回一個特定的字符串。
<?php // 獲取微信發送過來的參數 $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $echostr = $_GET["echostr"]; $token = "YOUR_TOKEN"; // 替換成你設置的Token // 將token、timestamp、nonce三個參數進行字典序排序 $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr, SORT_STRING); $tmpStr = implode( $tmpArr ); $tmpStr = sha1( $tmpStr ); // 校驗signature,確認請求來自微信 if( $tmpStr == $signature && $echostr){ // 驗證成功,返回echostr echo $echostr; exit; } else { // 驗證失敗 return false; } ?>
- Token: YOUR_TOKEN 替換成你在公眾號后臺設置的Token。
- 排序: sort($tmpArr, SORT_STRING) 這里要注意,要按照字符串排序,否則可能驗證失敗。
- SHA1加密: sha1($tmpStr) 使用SHA1算法加密。
- 驗證: $tmpStr == $signature 比較加密后的字符串和微信發送過來的signature。
- 返回echostr: 驗證成功,直接echo $echostr,然后exit,結束腳本。
把這段代碼放到你的服務器上,比如wechat.php,然后在公眾號后臺的“基本配置”中,填寫你的URL(比如https://yourdomain.com/wechat.php),Token填寫你設置的Token,點擊提交。如果驗證成功,微信會提示你配置成功。
-
接收和回復消息:
驗證服務器地址成功后,微信服務器就會把用戶發送的消息推送到你的URL。你需要解析這些消息,然后根據消息類型,做出相應的回復。
<?php // 引入驗證代碼(省略,就是上面的代碼) // 驗證成功后,開始處理消息 if( $tmpStr == $signature ){ // 獲取POST數據 $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; // 解析XML數據 if (!empty($postStr)){ $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); $fromUsername = $postObj->FromUserName; $toUsername = $postObj->ToUserName; $keyword = trim($postObj->Content); $time = time(); $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> <FuncFlag>0</FuncFlag> </xml>"; // 根據關鍵詞回復消息 if(!empty( $keyword )) { $contentStr = "你發送的消息是:".$keyword; $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr); echo $resultStr; }else{ echo "Input something..."; } }else { echo ""; exit; } } else { echo ""; exit; } ?>
- 獲取POST數據: $postStr = $GLOBALS[“HTTP_RAW_POST_DATA”]; 微信服務器發送的消息是XML格式的,需要獲取POST數據。
- 解析XML數據: simplexml_load_string() 使用這個函數解析XML數據。
- 獲取消息內容: $postObj->Content 獲取用戶發送的消息內容。
- 回復消息: 構建XML格式的回復消息,然后echo出去。
- : XML中需要使用這個包裹文本內容,防止被XML解析器錯誤解析。
如何獲取用戶openid?
OpenID是微信用戶在公眾號內的唯一標識。獲取OpenID的方法主要有兩種:
-
被動回復消息: 在接收到用戶消息的時候,$postObj->FromUserName 就是用戶的OpenID。 這是最簡單直接的方法,但前提是用戶必須主動給你的公眾號發送消息。
-
通過網頁授權獲取: 這種方法可以讓用戶在網頁上授權,然后獲取用戶的OpenID。 這種方法比較復雜,需要用到微信的OAuth2.0授權機制。 簡單來說,你需要:
- 構造一個授權鏈接,讓用戶點擊。
- 用戶點擊授權鏈接后,會跳轉到微信的授權頁面。
- 用戶授權后,微信會跳轉到你設置的回調地址,并攜帶code參數。
- 使用code參數,調用微信的接口,獲取Access_token和openid。
具體步驟可以參考微信官方文檔,搜索“網頁授權獲取用戶基本信息”。
如何實現自定義菜單?
自定義菜單可以讓用戶更方便地使用公眾號的功能。實現自定義菜單的步驟如下:
-
獲取access_token: 調用微信的接口,獲取access_token。 access_token是調用微信接口的憑證,有效期為2小時,需要定期刷新。
<?php $appId = "YOUR_APPID"; $appSecret = "YOUR_APPSECRET"; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appId."&secret=".$appSecret; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); $jsoninfo = json_decode($output, true); $access_token = $jsoninfo["access_token"]; echo $access_token; ?>
-
構造菜單數據: 按照微信的要求,構造JSON格式的菜單數據。
{ "button":[ { "type":"click", "name":"今日歌曲", "key":"V1001_TODAY_MUSIC" }, { "name":"菜單", "sub_button":[ { "type":"view", "name":"搜索", "url":"http://www.soso.com/" }, { "type":"miniprogram", "name":"wxa", "url":"http://mp.weixin.qq.com", "appid":"wx286b93c14b3xxxx", "pagepath":"pages/lunar/index" }, { "type":"click", "name":"贊一下我們", "key":"V1001_GOOD" }] }] }
- type: 菜單類型,常用的有click(點擊事件)、view(跳轉URL)、miniprogram(跳轉小程序)。
- name: 菜單名稱。
- key: click類型菜單的key值,用于在接收消息的時候區分不同的菜單。
- url: view類型菜單的URL。
- appid: miniprogram類型菜單的小程序appid。
- pagepath: miniprogram類型菜單的小程序頁面路徑。
-
調用接口創建菜單: 調用微信的接口,創建自定義菜單。
- YOUR_ACCESS_TOKEN: 替換成你獲取的access_token。
- $data: 替換成你構造的JSON格式的菜單數據。
- Content-Type: application/json: 設置請求頭,告訴微信服務器發送的是JSON數據。
遇到簽名錯誤怎么辦?
簽名錯誤是微信公眾號開發中常見的問題。通常是因為以下原因:
- Token錯誤: 檢查你代碼中的Token和公眾號后臺設置的Token是否一致。
- 參數順序錯誤: 確保按照token、timestamp、nonce的順序排序。
- 字符串排序錯誤: 使用sort($tmpArr, SORT_STRING)進行字符串排序。
- 緩存問題: 有時候微信服務器會有緩存,導致簽名驗證失敗。可以嘗試清除微信服務器的緩存,或者等待一段時間再試。
- URL錯誤: 確保你填寫的URL可以正常訪問,并且能夠正確處理微信服務器發送的GET請求。可以使用在線工具測試URL是否可用。
如果以上方法都不能解決問題,可以嘗試打印出微信發送過來的參數和你的計算結果,進行對比,找出錯誤的原因。 另外,仔細檢查你的代碼,確保沒有語法錯誤或者邏輯錯誤。