关于微信开放平台如何申请,如何配置,如何全网发布的文章,大神们已经写了很多,不想再造轮子,特针对微信授权事件的处理这一个点,对自己遇到的坑进行总结,也希望能给着手做微信开放平台的小伙伴们提供一份简单的参考资料,在写这篇文章之前,先吐槽一下微信开放平台的API文档,烂,真烂。
- 首先申请一个微信开放平台的账号,申请过程不赘述,很简单的流程,但再次吐槽一次,需要交审核费用(每年),中国大陆地区:300元,非中国大陆地区:120美元(不能理解微信的套路,难道真的有非大陆地区的国家在用微信?)
- 交完钱之后,等待审核,审核很快,大概一周时间即可
- 审核通过之后,即可创建第三方平台:创建过程如下:
在开放平台的官网,点击管理中心父菜单,
点击创建第三方平台按钮,即可打开创建第三方平台页面
根据自己的需要,填写基本信息:包括平台名称,选择业务标签,填写平台介绍,官方网站包括上传Logo等
点击下一步,选择公众号权限,一点儿小提示:如果选择了消息通知以及自定义菜单权限之后,如果用户公众号授权之 后,将会导致用户无法自定义菜单以及设置消息回复
最后一步,填写开发资料,包括:授权页发起页域名,授权测试公众号列表(在全网发布审核通过之前,该列表中的公众 号可用于测试授权),授权事件接收Url(本文主要对该Url的填写以及如何接收微信授权通知参数进行阐述)授权后实现 业务,主要包括:消息校验Token以及消息加解密Key(这两个字段可自定义,微信授权通知后,接收的消息用该字段进 行 加密解密,下文会对这俩字段如何使用进行详细说明)消息与事件接收URL,公众号开发域名(第三方平台在代公众号 做网页授权、调用JS SDK等网页开发工作时所用的域名) 做过微信公众号开发的小伙伴肯定很清楚,使用微信扫一扫以 及微信转发,分享等功能的JS时,微信需要验证是否拥有该域名权限 - 关于如何配置授权事件接收Url
二话不说,先贴图
首先域名必须为,授权页发起页域名中填写的域名,我采用的C#,MVC的开发模式,在开放平台发布成功之后,微信会每隔10分钟,推送授权信息给该域名,所以在填写时,一定要保证该方法可以被访问 - 关于ReceiveController下的SysMessage方法的代码如下:仅供参考
首先微信会推送6个参数给该方法,贴代码:
创建对象ReceiveRequestData
在ReceiveController中的方法接收微信推送的参数并赋值给该对象,代码如下:public class ReceiveRequestData { /// <summary> /// 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 /// </summary> public string signature { get; set; } /// <summary> /// 时间戳 /// </summary> public string timestamp { get; set; } /// <summary> /// 随机数 /// </summary> public string nonce { get; set; } /// <summary> /// /// </summary> public string encrypt_type { get; set; } /// <summary> /// /// </summary> public string msg_signature { get; set; } }
请注意,除这些参数外,微信还会推送文件流给该方法,接收方式如下:ReceiveRequestData postModel = new ReceiveRequestData(); postModel.signature = HttpContext.Current.Request["signature"]; postModel.timestamp = HttpContext.Current.Request["timestamp"]; postModel.nonce = HttpContext.Current.Request["nonce"]; postModel.encrypt_type = HttpContext.Current.Request["encrypt_type"]; postModel.msg_signature = HttpContext.Current.Request["msg_signature"];
对接收到的参数进行解密处理HttpContext.Current.Request.InputStream
首先声明对象ResponseAuthEventReceiveMsg,代码如下
public class ResponseAuthEventReceiveMsg { /// <summary> /// 第三方平台appid /// </summary> public string AppId { get; set; } /// <summary> /// 时间戳 /// </summary> public int CreateTime { get; set; } /// <summary> /// none,代表该消息推送给服务 /// component_verify_ticket 推送component_verify_ticket协议 /// </summary> public string InfoType { get; set; } /// <summary> /// Ticket内容 /// </summary> public string ComponentVerifyTicket { get; set; } /// <summary> /// 取消授权的公众号 /// </summary> public string AuthorizerAppid { get; set; } }
对接收到的参数进行解密:
ResponseAuthEventReceiveMsg response = _logic.Component_verify_ticket(postModel, HttpContext.Current.Request.InputStream);
Component_verify_ticket方法如下:
/// <summary>
/// 接收component_verify_ticket协议
/// </summary>
/// <param name="postModel"></param>
/// <param name="inputStream"></param>
/// <returns></returns>
public ResponseAuthEventReceiveMsg Component_verify_ticket(ReceiveRequestData postModel,
Stream inputStream)
{
if (inputStream != null)
{
inputStream.Seek(0, SeekOrigin.Begin);//强制调整指针位置
using (XmlReader xr = XmlReader.Create(inputStream))
{
var postDataDocument = XDocument.Load(xr);
var result = Init(postDataDocument, postModel);
var resultMessage = new ResponseAuthEventReceiveMsg();
//xml to model
EntityHelper.FillEntityWithXml(resultMessage, result);
return resultMessage;
}
}
return null;
}
Init方法如下:
private XDocument Init(XDocument postDataDocument, ReceiveRequestData postModel)
{
//进行加密判断并处理
var postDataStr = postDataDocument.ToString();
XDocument decryptDoc = postDataDocument;
if (postModel != null && postDataDocument.Root.Element("Encrypt") != null && !string.IsNullOrEmpty(postDataDocument.Root.Element("Encrypt").Value))
{
//使用了加密
string sToken = WeiXinConfig.ThirdPartToken;
string sAppId = WeiXinConfig.ComponentAppId;
string sEncodingAesKey = WeiXinConfig.ThirdPartMsgSign;
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAesKey, sAppId);
string msgXml = null;
var result = wxcpt.DecryptMsg(postModel.msg_signature, postModel.timestamp, postModel.nonce, postDataStr, ref msgXml);
//判断result类型
if (result != 0)
{
DevelopFileLog4Net.Instance.Info("方法:Init,验证没有通过");
//验证没有通过,取消执行
return null;
}
decryptDoc = XDocument.Parse(msgXml);//完成解密
}
return decryptDoc;
}
着重介绍一下Init方法中的sToken参数、sEncodingAesKey参数、sAppId参数
sAppId参数:开放平台发布成功之后,微信会为用户分配一个AppId,此处即为该参数
sToken参数:在申请开放平台时,填写开发资料时,填写的消息校验Token
sEncodingAesKey参数:在申请开放平台时,填写开发资料时,填写的消息加解密Key
至于WXBizMsgCrypt对象中的DecryptMsg方法,废话不说,贴图:
根据开发语言下载加解密对象即可。