首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

微信訂閱號開發:Token 驗證通過但消息無回應?三大核心坑點解決

     編輯:PHP 相關知識

現象

Token 驗證成功,但發送消息給訂閱號無任何回復。經排查,核心原因有三:

坑點一:官方 Demo 未調用 responseMsg()

官方示例代碼中僅調用 $wechatObj->valid(),**未調用 $wechatObj->responseMsg()**,自然無法處理用戶消息。

坑點二:Token 驗證代碼殘留干擾 XML 輸出

valid() 方法中有 echo $echoStr,若不註釋掉 $wechatObj->valid(),該輸出會混入 responseMsg() 的 XML 回復,導致微信服務器解析失敗。
Token 僅需驗證一次,驗證通過後務必註釋或刪除該調用。

坑點三:文件編碼必須為 UTF-8(關鍵)

微信要求 XML 回復為 UTF-8 編碼。官方 Demo 默認 ANSI,直接上傳可驗證通過;但改為 UTF-8 後 Token 驗證反而失敗。
**解決:Token 驗證階段用 ANSI 文件通過驗證後,將代碼另存為 UTF-8 覆蓋上傳**,並確保 responseMsg() 輸出的 XML 頭聲明編碼:

$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>";

可直接使用的完整代碼(UTF-8 編碼)

<?php
define('TOKEN', 'your_token_here');

$wechatObj = new WechatCallbackApiTest();
// $wechatObj->valid(); // 驗證通過後註釋掉
$wechatObj->responseMsg();

class WechatCallbackApiTest {
    public function valid() {
        $echoStr = $_GET['echostr'];
        if ($this->checkSignature()) {
            header('Content-Type: text/plain');
            echo $echoStr;
            exit;
        }
    }

    public function responseMsg() {
        $postStr = $GLOBALS['HTTP_RAW_POST_DATA'];
        // $postStr = file_get_contents('php://input'); // 兼容 php://input
        file_put_contents('log.txt', $postStr . "\n", FILE_APPEND); // 日誌調試

        if (!empty($postStr)) {
            libxml_disable_entity_loader(true); // 防 XXE
            $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)) {
                $msgType = 'text';
                $contentStr = 'Welcome to wechat world!';
                $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                echo $resultStr;
            } else {
                echo 'Input something...';
            }
        } else {
            echo '';
            exit;
        }
    }

    private function checkSignature() {
        if (!defined('TOKEN')) throw new Exception('TOKEN not defined!');
        $signature = $_GET['signature'];
        $timestamp = $_GET['timestamp'];
        $nonce = $_GET['nonce'];
        $token = TOKEN;
        $tmpArr = [$token, $timestamp, $nonce];
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        return $tmpStr === $signature;
    }
}

調試建議

  1. 啟用 file_put_contents('log.txt', ...) 記錄原始 POST 數據。
  2. 使用 php://input 替代 $GLOBALS['HTTP_RAW_POST_DATA'](PHP 5.6+ 棄用,7.0+ 移除)。
  3. 微信公眾平台「開發者工具」→「網頁調試」可模擬發送消息查看回包。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved