一.配置公众号消息加解密方式
在公众号官方管理后台->开发->基本配置->修改配置上有3种方式,如下:
其中,EncodingAESKey可以随机生成.
只有被动回复消息(即粉丝向公众号发送消息,由微信服务器向公众号服务器转发xml结构,同时公众号服务器返回xml结构,由微信服务器转发给粉丝)可以设置加密.其他3种消息(群发消息,客服消息,模板消息)的调用因为是API调用而不是对请求的返回,所以不需要加解密.
加解密方式说明:
1).明文模式:微信服务器向公众号服务器(即我们要处理的http://szuzsq.tunnel.qydev.com/weixin/index.php)发送的xml结构是原始的,没有加密.如下:
1468291653
6306264631030309910
而公众号服务器向微信服务器回复的xml结构也是原始的,没有加密.如下:
12345678
2).安全模式:微信服务器向公众号服务器发送的xml结构是加密之后的,如下:
而公众号服务器向微信服务器回复的xml结构也是加密之后的.如下:
1468291653
3).兼容模式:微信服务器向公众号服务器发送的xml结构即有原始的,也有加密之后的,如下:
1468291484
6306263905180836845
RpdCc4uTCwMMPkcSQ8KJmlx6rFnQPGh6gBqVaQJ20kXNKCYDQGQ1fur4Pbgydet8cDB+cvYitI/aRHo2KrVbXuJyiyuMuWw1zYWaeYmRCKN3+xyCtmtvPDBTW5PIJ7ZnUX0yGyp3J0oOjIJfULoVPqkUDY4W+Vdh0ZTR9eE7o0u9ioVUd+m5W72jsP61A7mivYCZTolCHWMFdhfoSQlxXm8tnTO1gu3v+vzTUCdWuZhpJNuD6X/Ab+vcgKSdopjlMKze8bUUw9CyT/YwEhj6CJRF46LkasUGC/i5wC7ABbTvZpGpMkuylF9pEY0E6PW+PwECsmY/aEcIp1CcsveddVJUeW9flOqgaDOiRvGyuwVMDTJo9inBuZpCRCGDUKpflBlUoD8nMbZzBxxVkUySjvmdj4Pa2V7gN2jRqtfmMtu9FzFcOyKUL/w==]]>
而公众号服务器向微信服务器回复的xml结构,则和安全模式下的回复是一样的.如下:
1468291653
二.微信公众号加解密过程
写之前要狠狠吐槽一下,微信官方文档有2个地方https://mp.weixin.qq.com/wiki和http://mp.weixin.qq.com/wiki/home,这2个地方应该是1份新的,1份旧的.但是,我从微信公众号官方后台管理->开发->开发者工具->开发者文档,进入的是第1个地方,按理说应该是新的才对.但是在消息管理->发送消息-被动回复时加解密,这章节上,有一段话:"请开发者查看接入指引和开发者FAQ来接入消息体签名及加解密功能:接入指引,开发者FAQ,若关注技术实现,可查看技术方案:技术方案"在这段话里面,我怎么都找不着接入指引和开发者FAQ这些相关内容.后来,不记得如何找到了第2个地方,同样地方的同样一句话:"请开发者查看接入指引和开发者FAQ来接入消息体签名及加解密功能:接入指引,开发者FAQ,若关注技术实现,可查看技术方案:技术方案".在这里接入指引,开发者FAQ,技术方案这几处,是有链接的!!!!!!!这里再次鄙视下微信的文档人员!!!!!!!!.
好了,大家去围观接入指引,里面提到在安全和兼容模式下,微信服务器向公众号服务器转发消息的url上,会添加signature,timestamp,nonce,encrypt_type,msg_signature(注意signature和msg_signature不同)参数.例如:
http://szuzsq.tunnel.qydev.com/weixin/index.php?signature=35703636de2f9df2a77a662b68e521ce17c34db4×tamp=1468291653&nonce=1528778891&encrypt_type=aes&msg_signature=59e47c61f82b1ac655ea94a9ad214656f573ba5b
下载微信官方给出的示例代码: http://mp.weixin.qq.com/wiki/static/assets/a5a22f38cb60228cb32ab61d9e4c414b.zip,里面有C++、php、Java、Python和C#版本,我们只需要用到几个文件:errorCode.php,pkcs7Encoder.php,sha1.php,wxBizMsgCrypt.php,xmlparse.php,其中wxBizMsgCrypt.php实现了微信消息加解密的业务逻辑.
1).解密微信服务器向公众号服务器发送的xml.
decryptMsg($msg_signature, $timestamp, $nonce, $postStr, $decryptMsg);
?>
其中,$msg_signature,$timestamp,$nonce要使用微信服务器在url中传进来的.
2).加密公众号服务器向微信服务器回复的xml.
encryptMsg($responseStr, $timestamp, $nonce, $encryptMsg);
?>
其中,$timestamp,$nonce既可以使用微信服务器在url中传进来的,也可以使用自己生成的.
三.完整示例
我的项目目录如下:
源文件如下:
responseMsg();
class wechatCallbackapiTest {
public function responseMsg() {
//微信服务器向公众号服务器发送xml
$timestamp = $_GET['timestamp'];
$nonce = $_GET["nonce"];
$msg_signature = $_GET['msg_signature'];
$encrypt_type = $_GET['encrypt_type'];
$postStr = file_get_contents('php://input'); //$GLOBALS["HTTP_RAW_POST_DATA"];
$pc = new WXBizMsgCrypt(TOKEN, EncodingAESKey, AppID);
$decryptMsg = ""; //解密后的原文
$errCode = $pc->decryptMsg($msg_signature, $timestamp, $nonce, $postStr, $decryptMsg);
error_log("**********************解密**********************\r\ntimestamp:$timestamp\r\nnonce:$nonce\r\nmsg_signature:$msg_signature\r\nencrypt_type:$encrypt_type\r\npostStr:$postStr\r\nerrCode:$errCode\r\ndecryptMsg:$decryptMsg\r\n\r\n", 3, "err.log");
//公众号服务器向微信服务器回复xml
$responseStr = "12345678 ";
$encryptMsg = ''; //加密后的密文
$errCode = $pc->encryptMsg($responseStr, $timestamp, $nonce, $encryptMsg);
error_log("**********************加密**********************\r\nresponseStr:$responseStr\r\nerrCode:$errCode\r\nencryptMsg:$encryptMsg", 3, "err.log");
echo $encryptMsg;
}
}
?>
效果如下:
代码中2处使用error_log打印出来的内容(为了好看,我后期手动排了下版),如下:
**********************解密**********************
timestamp:1468298136
nonce:1156171062
msg_signature:5d7ad0fe355e800ab05092e62489469e27347bb6
encrypt_type:aes
postStr:
errCode:0
decryptMsg:
1468298136
6306292475303292097
**********************加密**********************
responseStr:
12345678
errCode:0
encryptMsg:
1468298136
研究的时候,借鉴了方倍工作室大神的博客<<微信公众平台开发者中心安全模式消息体加解密实现>>: http://www.cnblogs.com/txw1958/p/weixin-aes-encrypt-decrypt.html