微信公众号开发教程[005]-消息管理-消息加解密

一.配置公众号消息加解密方式

在公众号官方管理后台->开发->基本配置->修改配置上有3种方式,如下:

其中,EncodingAESKey可以随机生成.

加解密方式说明:

1).明文模式:微信服务器向公众号服务器(即我们要处理的http://szuzsq.tunnel.qydev.com/weixin/index.php)发送的xml结构是原始的,没有加密.如下:

<xml>
	<ToUserName><![CDATA[gh_733c42e0aee9]]></ToUserName>
	<FromUserName><![CDATA[oIaodvwZe03Amjb8_jQ0ZHGmr-4w]]></FromUserName>
	<CreateTime>1468291653</CreateTime>
	<MsgType><![CDATA[text]]></MsgType>
	<Content><![CDATA[i love you]]></Content>
	<MsgId>6306264631030309910</MsgId>
</xml>

而公众号服务器向微信服务器回复的xml结构也是原始的,没有加密.如下:

<xml>
	<ToUserName><![CDATA[oIaodvwZe03Amjb8_jQ0ZHGmr-4w]]></ToUserName>
	<FromUserName><![CDATA[gh_733c42e0aee9]]></FromUserName>
	<CreateTime>12345678</CreateTime>
	<MsgType><![CDATA[text]]></MsgType>
	<Content><![CDATA[你好]]></Content>
</xml>

2).安全模式:微信服务器向公众号服务器发送的xml结构是加密之后的,如下:

<xml>
	<ToUserName><![CDATA[gh_733c42e0aee9]]></ToUserName>
	<Encrypt><![CDATA[5iQIChI9SHJ8AygPRlQXg0TjENPp/+gMsL8QWceqRXbmZa9tfwft9JtVMhsd6acMJjq7s/gi6E/dLoaJ5optAJ3ixUoHlsJSiryZC/wkFZkY4++HQEr9sj0wHbsT9UbbW/TfXY0t5pQtM62hQKHO/AUFHiXAJ31kQrcGY4QZHyJjQDS6bchvufhOnm8paDMak3HeTf0vMBzkSZcl78V23uq8wvV1rBx4K9uzPz6AZmfV2rLbaA5u/fsQFcntl8aDK19PZfZreawt0et3AXv1DgFZEciC8vlCxwta6mjuAEIdL81t4mfa8V28iD8ul+AjWEMKcHszBQqQUkG3BTItB/8o+8h6PLYD+ZsHEUBbPttRhrlo+UlfXTehtGPVnd97GZ72ImWXb5wIadKcGSgXzvRRkVv1zav3CTjRRZH5k8kLqIxso9VmjD4Un+IF8vKaJqAu0irYWFMWYIhQZZ9CQQ==]]></Encrypt>
</xml>

而公众号服务器向微信服务器回复的xml结构也是加密之后的.如下:

<xml>
	<Encrypt><![CDATA[lSK3AQg4RCd3GvUpEVQiZSxBWpAgH3MJjoZIGGjd0rcO14H7JasE2O8bzA/0PusNfKuxMmcCsTq3vHlbrdvALSioQKlpl/QrNH15kelS0bG12UMJhxs1CDa+ES9IuZ4wR7Ra/Oa3kCUh9x0RKdxkAWa0+jgT3bOD0OESMWp8Iynx11QiMBSMzAiEneLUCrszUdV6eBUQvdLTXkrRWYWHdMjgbvb8psc3NyxqB7N0GOG6i7ibk/Zd1s8nsDrYYDFI/BDFgl/wOEBSFC5rWgsgCdhuUEDcnU3N1eb/veL+TJ7zDAImUUPMY/auhm7mBVQcWjpCXutIo03esQJaSGiDxfj4VVBoZslPQc3gUKzm1I4QzCVU27J8/mx41I6Zc54k]]></Encrypt>
	<MsgSignature><![CDATA[5b9bff5f6dd7075d4ec2f4bca880d8ada48c6c7d]]></MsgSignature>
	<TimeStamp>1468291653</TimeStamp>
	<Nonce><![CDATA[1528778891]]></Nonce>
</xml>

3).兼容模式:微信服务器向公众号服务器发送的xml结构即有原始的,也有加密之后的,如下:

<xml>
	<ToUserName><![CDATA[gh_733c42e0aee9]]></ToUserName>
	<FromUserName><![CDATA[oIaodvwZe03Amjb8_jQ0ZHGmr-4w]]></FromUserName>
	<CreateTime>1468291484</CreateTime>
	<MsgType><![CDATA[text]]></MsgType>
	<Content><![CDATA[i love you]]></Content>
	<MsgId>6306263905180836845</MsgId>
	<Encrypt><![CDATA[Kd1lnxCrEr4L3qT4De7Rp2nUgbnYj8M http:// <span style="font-family: Arial, Helvetica, sans-serif;">RpdCc4uTCwMMPkcSQ8KJmlx6rFnQPGh6gBqVaQJ20kXNKCYDQGQ1fur4Pbgydet8cDB+cvYitI/aRHo2KrVbXuJyiyuMuWw1zYWaeYmRCKN3+xyCtmtvPDBTW5PIJ7ZnUX0yGyp3J0oOjIJfULoVPqkUDY4W+Vdh0ZTR9eE7o0u9ioVUd+m5W72jsP61A7mivYCZTolCHWMFdhfoSQlxXm8tnTO1gu3v+vzTUCdWuZhpJNuD6X/Ab+vcgKSdopjlMKze8bUUw9CyT/YwEhj6CJRF46LkasUGC/i5wC7ABbTvZpGpMkuylF9pEY0E6PW+PwECsmY/aEcIp1CcsveddVJUeW9flOqgaDOiRvGyuwVMDTJo9inBuZpCRCGDUKpflBlUoD8nMbZzBxxVkUySjvmdj4Pa2V7gN2jRqtfmMtu9FzFcOyKUL/w==]]></Encrypt></span>
</xml>

而公众号服务器向微信服务器回复的xml结构,则和安全模式下的回复是一样的.如下:

<xml>
	<Encrypt><![CDATA[lSK3AQg4RCd3GvUpEVQiZSxBWpAgH3MJjoZIGGjd0rcO14H7JasE2O8bzA/0PusNfKuxMmcCsTq3vHlbrdvALSioQKlpl/QrNH15kelS0bG12UMJhxs1CDa+ES9IuZ4wR7Ra/Oa3kCUh9x0RKdxkAWa0+jgT3bOD0OESMWp8Iynx11QiMBSMzAiEneLUCrszUdV6eBUQvdLTXkrRWYWHdMjgbvb8psc3NyxqB7N0GOG6i7ibk/Zd1s8nsDrYYDFI/BDFgl/wOEBSFC5rWgsgCdhuUEDcnU3N1eb/veL+TJ7zDAImUUPMY/auhm7mBVQcWjpCXutIo03esQJaSGiDxfj4VVBoZslPQc3gUKzm1I4QzCVU27J8/mx41I6Zc54k]]></Encrypt>
	<MsgSignature><![CDATA[5b9bff5f6dd7075d4ec2f4bca880d8ada48c6c7d]]></MsgSignature>
	<TimeStamp>1468291653</TimeStamp>
	<Nonce><![CDATA[1528778891]]></Nonce>
</xml>

二.微信公众号加解密过程

写之前要重头吐槽一下,微信官方文档有2个地方https://mp.weixin.qq.com/wikihttp://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&timestamp=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.

<?php
	$errCode = $pc->decryptMsg($msg_signature, $timestamp, $nonce, $postStr, $decryptMsg);
?>

2).加密公众号服务器向微信服务器回复的xml.

<?php
	$errCode = $pc->encryptMsg($responseStr, $timestamp, $nonce, $encryptMsg);
?>

其中,$timestamp, $nonce即可以使用微信服务器在url中传进来的,也可以使用自己生成的.

三.完整示例

我的项目目录如下:

源文件如下:

<?php
//文件名: http://szuzsq.tunnel.qydev.com/weixin/index.php

require_once('aes/wxBizMsgCrypt.php');

define("TOKEN", "weixin");
define("AppID", "wxc5bc41cb7c73814f");
define("EncodingAESKey", "r0TTQS2o4xxlJcMjCs33leS56rpNJOi12QRldiXS5Lv");

$wechatObj = new wechatCallbackapiTest();
$wechatObj->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 = "<xml><ToUserName><![CDATA[oIaodvwZe03Amjb8_jQ0ZHGmr-4w]]></ToUserName><FromUserName><![CDATA[gh_733c42e0aee9]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[你好]]></Content></xml>";
		$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:
<xml>
	<ToUserName><![CDATA[gh_733c42e0aee9]]></ToUserName>
	<Encrypt><![CDATA[sI7OWIRI1LWe0OSH3aJbg1mIcirMiMQ7Seq8udJ0OAhrIVPKDqX2cf3tD9BPtyEgGIbQcnWIoJ6/JWjRuMSPjEcUgmpSZG1lAFb1YArPXwY2HIoi/n1mPK3E2Mntt55Y2Xp3/GlxuJxH/eg1rdad/98UfBiB5pJcmSM0odJJ+jQ1/ufIAn7fBFWwGpMeEOGtpX7mpMzVMxr5Y3qrNIIT6htnjW2nlwPFatGccHo0ne6BsRDzitLVKKOVUyIRLLcJopLb03GdAQPD3wVvUNtOKxlgvPt0gta09Z5AT6axqyBqB5Po+0TF4gNb8Q3eFJAZkl0fnzCQxnMZytf2NZ9mQjAf1lsTQfc68mCdyJ+y1g4pANvidZYpOKnfl1zI1edbIHKsdKhzWP+LX7neJtL7PNpj6Dzgm6og+z//NYR4JbiMv3DTizGywFbf112yoCiZu/ogeLbarav/5brdsbDZRA==]]></Encrypt>
</xml>

errCode:0
decryptMsg:
<xml>
	<ToUserName><![CDATA[gh_733c42e0aee9]]></ToUserName>
	<FromUserName><![CDATA[oIaodvwZe03Amjb8_jQ0ZHGmr-4w]]></FromUserName>
	<CreateTime>1468298136</CreateTime>
	<MsgType><![CDATA[text]]></MsgType>
	<Content><![CDATA[i love you]]></Content>
	<MsgId>6306292475303292097</MsgId>
</xml>

**********************加密**********************
responseStr:
<xml>
	<ToUserName><![CDATA[oIaodvwZe03Amjb8_jQ0ZHGmr-4w]]></ToUserName>
	<FromUserName><![CDATA[gh_733c42e0aee9]]></FromUserName>
	<CreateTime>12345678</CreateTime>
	<MsgType><![CDATA[text]]></MsgType>
	<Content><![CDATA[你好]]></Content>
</xml>
errCode:0
encryptMsg:
<xml>
	<Encrypt><![CDATA[1XLHOG845Qa3YTE0/TO3bRg1EQCD+bNc93qumuX6tkYqXmlYA4nYhRDRLC8YeoJ19Zm0E5ZvoQ/+7YLNgtxwvj5OfhFoS0GYNLS9ka9rYLwePklKWa6tfbCtln75daHWFtLms95LGC8WZPFzixJhgkWh6cOvyGkMMxWkGc439qNbgbFklG1OGdzh5ae1KP7ywMtr6d5xfM6eEyBV+Mr/Fy0B3pxFMsnx/2yFUW3OCcpPL8PB0StfPgTRoTQbWwj0blxxXRNuQSasMErGd+up8xKe0kHpBZ4Hr4L6cnika+K2BXdR7ToVOGiQ37vRixNiyO34QVIb/I0AGo5LWLJxDP6Y4E7mhgKkJh4rSU6ihJ1YUZHljibKveO5s0syAEZ9]]></Encrypt>
	<MsgSignature><![CDATA[f41080b7fc392bd3c800d56c1479f307897cb628]]></MsgSignature>
	<TimeStamp>1468298136</TimeStamp>
	<Nonce><![CDATA[1156171062]]></Nonce>
</xml>

研究的时候,借鉴了方倍工作室大神的博客<<微信公众平台开发者中心安全模式消息体加解密实现>>: http://www.cnblogs.com/txw1958/p/weixin-aes-encrypt-decrypt.html

时间: 2024-10-18 09:38:21

微信公众号开发教程[005]-消息管理-消息加解密的相关文章

微信公众号开发教程[002]-配置

一.注册微信公众号 微信公众号官方入口https://mp.weixin.qq.com注册公众号,注册过程中,类型选择可能是新手比较迷惑的地方.微信公众号分为订阅号和服务号(还有个企业号,似乎用的人不多),每种类型下面又分为公司,政府部门,社会组织,个人等不同性质.不同类型,不同性质的公众号,权限不同,申请资料也不同. 例如:公司(订阅号或服务号),你得提供工商注册号,银行对账号.注册成功后,也并不是所有权限都默认开通,需要手动开通.有些权限还得微信认证之后才能开通.关于这些细节,可参阅微信公众

微信公众号开发教程详细完整第1篇

| 版权声明:本文为博主原创文章,未经博主允许不得转载. 从2014.12月份左右接触微信公众号开发,短短续续也有了一年多在这期间做了不知道多少个公众号,各种奇葩的功能都有涉猎.从一无所知的小白,到对整个微信公众号生态的理解,不知道经历了多少个日日夜夜,鬼知道我经历了什么.此次教程不谈什么微信公众号O2O(基本死光了)也不谈什么分答,大字(基本被微信封的差不多了),这次我们只是对微信公众号的二次开发者们,希望对你们有所帮助,也希望有更多的朋友一起探讨,讨论. 下面说一下这个教程的前言:首先此次教

微信公众号开发系列-发送客服消息

下面是做微信公众号开发用到最多的两个客服消息发送类型,文本信息和图文信息. 1.发送文本消息 { "touser":"OPENID", "msgtype":"text", "text": { "content":"Hello World" } } 參数 是否必须 说明 access_token 是 调用接口凭证 touser 是 普通用户openid msgtype

微信公众号开发教程[003]-消息管理-接收消息

当微信用户向公众号发送消息时,微信服务器会向公众号配置的服务器URL地址发送请求,并将相关内容包装成一定格式的xml发送到这个服务器;响应时,这个服务器只要回复特定格式的xml字符串给微信服务器,微信服务器即可向微信用户的客户端转发这条回复消息.(假设公众号开发模式已开启,以后的教程,如果没有特别说明,都是如此).如下图: 例如,文本消息的xml结构如下: <xml> <ToUserName><![CDATA[toUser]]></ToUserName> &

微信公众号开发C#系列-6、消息管理-普通消息接受处理

1.概述 通过前面章节的学习,我们已经对微信的开发有了基本的掌握与熟悉,基本可以上手做复杂的应用了.本篇我们将详细讲解微信消息管理中普通消息的接收与处理.当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上.接收普通消息微信官方文档参考:接收普通消息文档API 消息接收后,就有一个处理或回复的过程,单单发送消息了没有响应也是不人性化的,下面我们就对接收到微信各类型消息分别讲解处理的方法. 2.消息接收 当普通微信用户向公众账号发消息时,微信服务器会先接收

微信公众号开发教程

开发和调试之殇 微信公众号的开发,说简单也简单,说麻烦也麻烦,麻烦的不是开发过程,而是搭建开发环境的过程.只是俗话说得好,磨刀不误砍柴工,我们有必要花点时间来研究下怎样攻破微信公众号的开发环.说白了,公众号的开发就是基于HTML/CSS/JS的移动端Web App的开发.但微信公众号和普通的移动Web App开发还略有不同,由于非常多情况下我们会调用公众号的接口.而仅仅要涉及微信接口的请求,都必须通过微信内置的浏览器来訪问,假设我们想把请求放到PC桌面浏览器上执行调试.就会跳转到一个笑脸,提醒你

微信公众号开发教程 微信小程序

PHP微信公众平台开发高级篇 http://www.imooc.com/u/197650/courses?sort=publish 微信小程序教程 .链接:http://pan.baidu.com/s/1slmAwDf 密码:ciry

微信公众号开发教程[006]-PHP使用CURL详解

往后的编章,开始涉及微信公众号的api了,php中访问站点有很多方式,例如file_get_contents也可以get,post站点: <?php $formdata = array('sParam1' => 'test1', 'sParam2' => 101, 'isAuto' => 1); $data = http_build_query($formdata); $options = array('http' => array('method' => 'POST'

【微信公众号开发】根据openId群发消息

根据开发文档可知,只要使用POST方式提交固定格式的json字符串到那个地址即可.这里我写的是最简单的文本 第一步:建立对应的实体类. 1 package cn.sp.bean; 2 3 import java.util.List; 4 import java.util.Map; 5 6 /**群发消息 7 * Created by 2YSP on 2017/7/12. 8 */ 9 public class MassMessage { 10 private List<String> tous