開發者在代替授權公眾號接收和處理消息時,出於安全考慮,必須對消息收發的過程進行加解密。
消息加解密的實現流程如下。
接口程序中需要配置以下參數。
define("AppID", "wx2ae3853dda623211"); define("AppSecret", "df8a05425d4ba95405fb1b048704373e"); define("Token", "weixin"); define("EncodingAESKey", "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG");
當用戶向公眾號發送消息時,微信開放平台應用將會在URL中帶上appid、signature(簽名)、timestamp(時間戳)、nonce(隨機數)、openid、encrypt_type(加密類型)、msg_signature(消息簽名)等參數,具體如下。
http:// open.fangbei.org/wxopen/msg.php?appid=/wx570bc396a51b8ff8&signature=e4195d494e304fbdc19fb4d58e18b967cb5b4b02×tamp=1465799535&nonce=734775080&openid=ozy4qt1eDxSxzCr0aNT0mXCWfrDE&encrypt_type=aes&msg_signature=e5574ec67f7f429b8c7793ebc0b493fd977c682d
同時向該接口推送如下XML消息,即一個已加密的消息。
<xml> <ToUserName><![CDATA[gh_3c884a361561]]></ToUserName> <Encrypt><![CDATA[yCaK/BzoYXNNB8IkHauQqH5ozAmUjm8SLfg29ZMmkavy92e4txPGl5NsKCfGlW yMyWzYRRvlND3rDfXJXr0ddmJ34yolWHgFpLmKDpVlox+3atfzRwPPdqukSqA2XVtVwIKFiSKLdvaagj6 wMWXIsqyvmZXZWfEg9QwR1TSgLH46ZnQS1EyEd7qhYpCMGicYgjEeWw6KKQD9/604QlW3zh8oIKy51Oy9 MaGLiDrZrHC8C5x8iqFH48rhGMDk4f8uDMl3IdA/f+4vdERp0/fGWLSi8ZKWb9P5Z3E8OUBAiEcCQ2nmc PRheJQBIZKH0g1YLNdpr0t08i2LvZniNfPJ/uS+IuPcMjP9RjEz9n4kAnFgiuyB6cocIZfYE8M6I/nrwv VZepQP6vAZaaetrCZn+PdEAhHoWTl/KOHbJ7Vv+F8L2D1pbajgc3IWHBnyNF2dKtp/ctr9ZzQGtyszhAs gTq9W1bbdySFM5ra5k3IUY13EFWX3hFYYubV9SiUhj7r9soVBFwUeMIqJYnWU63M+BYR33rFTBui1kwQS x5LOHlYbWMY+6xjhKEqB5qcKmPhr9x7XHtXCJ4i4bqFPqjvnog==]]></Encrypt> </xml>
這時程序需要從URL中獲得以下參數,以及接收微信傳送的POST內容。
$signature = $_GET['signature']; $timestamp = $_GET['timestamp']; $nonce = $_GET['nonce']; $encrypt_type = $_GET['encrypt_type']; $msg_signature = $_GET['msg_signature']; $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
這些參數將用於加解密過程。
接口程序收到消息後,先進行解密,解密部分代碼如下。
// 解密 if ($encrypt_type == 'aes'){ $pc = new WXBizMsgCrypt(Token, EncodingAESKey, AppID); $this->logger(" D \r\n".$postStr); $decryptMsg = ""; // 解密後的明文 $errCode = $pc->DecryptMsg($msg_signature, $timestamp, $nonce, $postStr, $decryptMsg); $postStr = $decryptMsg; }
解密後的XML如下。
<xml> <ToUserName><![CDATA[gh_3c884a361561]]></ToUserName> <FromUserName><![CDATA[ozy4qt1eDxSxzCr0aNT0mXCWfrDE]]></FromUserName> <CreateTime>1465799534</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[QUERY_AUTH_CODE:queryauthcode@@@cdGgIgvWgYbXn3iqXM2NHkrMF09p sBBScXQoEdLFSnGxmtZlmXknhcImp7jFFDKRx2RBTac2GbLycTnJ1Yo0qQ]]></Content> <MsgId>6295561061426473714</MsgId> </xml>
對消息在自己原有的代碼流程中處理,完成之後,一個要回復的文本消息如下。
<xml> <ToUserName><![CDATA[ozy4qt1eDxSxzCr0aNT0mXCWfrDE]]></ToUserName> <FromUserName><![CDATA[gh_3c884a361561]]></FromUserName> <CreateTime>1465799535</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA]></Content> </xml>
對上述消息進行加密,返回給微信公眾號,加密過程如下。
// 加密 if ($encrypt_type == 'aes'){ $encryptMsg = ''; // 加密後的密文 $errCode = $pc->encryptMsg($result, $timeStamp, $nonce, $encryptMsg); $result = $encryptMsg; $this->logger(" E \r\n".$result); }
加密後的內容如下。
<xml> <Encrypt><![CDATA[h/umYlxmksaCoeNwPIlm65KbTucdBAUFxn10ke/kPmtngKzfQ5J04jgEdZekLeuyy tVJLz1z9jsrPA41n8z7vg==]]></Encrypt> <MsgSignature><![CDATA[e3f0922ff7649f338c49c595d5c39aaa08184bcd]]></MsgSignature> <TimeStamp>1465799531</TimeStamp> <Nonce><![CDATA[734775080]]></Nonce> </xml>
這樣一個安全模式下的加解密消息就完成了。