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

ThinkPHP 微信開發:安全模式消息加解密失敗問題排查與修復

     編輯:PHP 相關知識

ThinkPHP 微信開發:安全模式消息加解密失敗問題排查與修復

使用 ThinkPHP 官方 WeChat 包時,普通/兼容模式正常,但**安全模式**解密失敗。經對比官方樣例代碼與 WechatCrypt.class.php,邏輯無誤,通過 file_put_contents 落盤分析解密後明文,發現 XML 格式不標準導致 simplexml_load_string 解析失敗。

問題現象

解密後的 XML 字符串包含轉義字符與換行:

<xml>
<ToUserName><![CDATA[gh_249aeb986d99]]><\/ToUserName>\n
<FromUserName><![CDATA[oopVmxHZaeQkDPsRcbpwXKkH-J2Q]]><\/FromUserName>\n
<CreateTime>1448944621<\/CreateTime>\n
<MsgType><![CDATA[text]]><\/MsgType>\n
<Content><![CDATA[\u7ecf\u7406]]><\/Content>\n
<MsgId>6223169761311044588<\/MsgId>\n
<\/xml>

關鍵問題:

  1. <\/Tag> 應為 </Tag>(反斜杠多餘)
  2. >\n 應為 >(多餘換行)
  3. CDATA 內 Unicode 轉義 \u7ecf\u7406 未解碼(simplexml 可處理,但建議預處理)

根因分析

WechatCrypt::decrypt() 返回的明文未做後處理,直接傳給 simplexml_load_string。官方示例中明文本即標準 XML,但實際騰訊服務器返回的加密數據解密後含轉義字符。

修復方案

在 WechatCrypt.class.php 的 decrypt() 方法末尾,返回明文前添加清洗邏輯:

// 明文內容
$text = substr($decrypt, 4, $size);

// 【修復】清洗非標準 XML 轉義
$text = str_replace('<\/', '</', $text);   // 修正閉合標籤
$text = str_replace('>\n', '>', $text);   // 移除標籤後換行

return $text;

完整 decrypt 方法參考

public function decrypt($encrypt) {
    $encrypt = base64_decode($encrypt);
    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
    mcrypt_generic_init($td, $this->cyptKey, substr($this->cyptKey, 0, 16));
    $decrypt = mdecrypt_generic($td, $encrypt);
    $decrypt = self::PKCS7Decode($decrypt, mcrypt_enc_get_key_size($td));
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

    if (strlen($decrypt) < 16) throw new \Exception("非法密文字符串!");
    $decrypt = substr($decrypt, 16); // 去隨機串
    $size = unpack("N", substr($decrypt, 0, 4));
    $size = $size[1];
    $appid = substr($decrypt, $size + 4);
    if ($appid !== $this->appId) throw new \Exception("非法APP_ID!");
    
    $text = substr($decrypt, 4, $size);
    
    // 關鍵修復
    $text = str_replace('<\/', '</', $text);
    $text = str_replace('>\n', '>', $text);
    
    return $text;
}

驗證結果

修復後,安全模式下 simplexml_load_string 正常解析,消息處理流程恢復正常。

避坑提示

  • 調試加解密時,**務必落盤原始明文**對比標準格式
  • 微信服務器推送的加密數據可能隨版本變化,保持兼容性處理
  • ThinkPHP 5.x 以上版本建議使用 overtrue/wechat 等現代庫,原生支援安全模式且維護更活躍
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved