微信公众号开发C#系列-二、微信公众平台接入指南

概述

微信公众平台消息接口的工做原理大概能够这样理解:从用户端到公众号端一个流程是这样的,用户发送消息到微信服务器,微信服务器将接收到的消息post到用户接入时填写的url中,在url处理程序中,首先判断消息的合法性,判断成功后根据消息体的内容作相应的处理。原理很容易理解,接触过socket的可能理解起来更容易。对于微信开发者模式的接入官网文档很是的简洁,对于初学者不少都摸不着头脑,微信官方技术文档的接入指南能够参考接入指南
大体步骤就是:git

  1. 填写服务器配置
  2. 验证服务器地址的有效性
  3. 依据接口文档实现业务逻辑

准备工做

要接入微信,首先咱们须要一个微信公众号,相信作微信公众号开发的朋友都会遇到这样的问题,就是微信公众号提供的接口权限问题。若是是我的订阅号,官方提供的接口不多,不少接口都不能用。若是想测试接口功能怎么办?其实,微信公众号官方给咱们提供一个微信公众测试号,测试号除了不能用微信支付接口,其余接口基本均可以用获取而且可使用。下面我就教你们如何申请微信公众号测试号。全微信扫一扫公众平台测试帐号系统登陆便可,很是的方便。微信公众平台测试帐号系统地址:公众平台测试帐号系统登陆后咱们就能够轻松愉快的进行下面的玩耍了。对于常规的微信公众号接入方式与测试公众号大同小异,这儿成功了其余的相似。github

填写服务器配置与验证消息的确来自微信服务器

  • 填写服务器配置

在填写服务器配置以前咱们须要了解一下微信与咱们的服务器交互的过程:算法

当咱们在微信app上,给公众号发送一条消息时,这条消息其实是发送到了微信的服务器上,此时微信的服务器就会对消息进行封装成某种格式的数据好比xml格式,再转发到咱们配置好的URL上,因此该URL实际就是咱们处理数据的一个请求路径。所以该URL必须是能暴露给外界访问的一个公网地址,不能使用内网地址,生产环境能够申请腾讯云,阿里云服务器等,但在开发环境中可暂时利用一些软件来完成内网穿透以便于修改和测试,如NATAPP,花生壳等软件,使用起来也很方便,在本地安装对应的软件,配置运行后,直接使用软件分配的临时域名来访问本地应用便可,只是偶尔会存在网络不稳定的状况,具体的外网映射工具与调试的方法后面的文章咱们会接受。编程

微信与咱们的服务器交互的过程

有了这样一个基本的概念后,咱们看下接口配置信息相关的说明。浏览器

接口配置以下图所示:安全

接口配置

对于测试号信息中的appid与appsecret两个属性是惟一的标识,每一个测试号都会有本身的appid与appsecret ,是比较重要的信息,不要随意发给别人。服务器

  1. appid:是公众号开发识别码,配合开发者密码可调用公众号的接口能力。
  2. appsecret:是校验公众号开发者身份的密码,具备极高的安全性。

服务器地址URL是开发者用来接收微信消息和事件的接口URL,是咱们服务器的响应微信请求的地址。
假设咱们本身的服务器域名是www.rdiframework.net,准备用/WeiXin/WeChat/来接收消息,就填写:
http://www.rdiframework.net/WeiXin/WeChat/微信

Token能够任意填写,为了安全性和防止黑客攻击建议设置得复杂一些,并要防止泄露。
测试号通常只须要填写URL与Token两项内容,真实项目的填写还要填写EncodingAESKey,能够由开发者手动填写或随机生成,将用做消息体加解密密钥。
开发者还可选择消息加解密方式:明文模式、兼容模式和安全模式,具体可参看开发者文档。网络

另请注意,微信公众号接口地址必须以http://或https://开头,分别支持80端口和443端口。微信开发

  • 验证消息的确来自微信服务器

当咱们填入url与token的值,并提交后,微信会发送一个get请求到咱们填写的url上,而且携带4个参数,而signature参数结合了开发者填写的token参数和请求中的timestamp参数、nonce参数来作的加密签名,咱们在后台须要对该签名进行校验,看是否合法。实际上,咱们发现微信带过来的4个参数中并无带token参数,仅有signature是和token有关的,因此咱们应该在本地应用中也准备一个和填入的token相同的参数,再经过微信传入的timestamp与nonce作相同算法的加密操做,若结果与微信传入的signature相同,即为合法,则原样返回echostr参数,表明接入成功,不然不作处理,则接入失败。

详细流程可参考微信官方提供的逻辑流程图,咱们的应用须要以该流程图的步骤来实现。

逻辑流程图

下面为咱们以.NET MVC代码实现get请求样例代码,可供参考:

[HttpGet]
[ActionName("Index")]
public Task<ActionResult> Get(string signature, string timestamp, string nonce, string echostr)
{       
    return Task.Factory.StartNew(() =>
    {

        if (CheckSignature.Check(signature, timestamp, nonce, "WeiXinToken"))
        {
            return echostr; //返回随机字符串则表示验证经过
        }
        else
        {
            return "failed:" + signature + "," + CheckSignature.GetSignature(timestamp, nonce, weixinOfficialAccountEntity.Token) + "。" + "若是你在浏览器中看到这句话,说明此地址能够被做为微信公众帐号后台的Url,请注意保持Token一致。";
        }
    }).ContinueWith<ActionResult>(task => Content(task.Result));
}

上面的代码注意token不是微信服务器发过来的,而是咱们本身写死的一个常量,就是在微信后台填写的Token,这儿我填写的是:WeiXinToken

依据接口文档实现业务逻辑

验证URL有效性成功后咱们就能够接收来自微信的数据,并对接收到的数据按需作相应的业务处理。用户每次向公众号发送消息、或者产生自定义菜单、或产生微信支付订单等状况时,开发者填写的服务器配置URL将获得微信服务器推送过来的消息和事件,开发者能够依据自身业务逻辑进行响应,如回复消息。

公众号调用各接口时,通常会得到正确的结果,具体结果可见对应接口的说明。返回错误时,可根据返回码来查询错误缘由。全局返回码说明

微信后台发送消息是一个POST请求,但和普通的POST请求不一样的是,首先,URL会带上signature、timestamp、nonce这3个参数:

POST http://www.rdiframework.net/WeiXin/WeChat/?signature=xxx&timestamp=123456&nonce=123

而后,HTTP请求的BODY是一个不规范的XML:

<xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[fromUser]]></FromUserName> 
    <CreateTime>1348831860</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[this is a test]]></Content>
    <MsgId>1234567890123456</MsgId>
</xml>

咱们本身的服务器只须要处理该XML,而后,向微信返回一个相似以下的XML:

<xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[fromUser]]></FromUserName>
    <CreateTime>12345678</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[你好]]></Content>
</xml>

就能够完成消息的回复。微信后台要求必须在5秒内回复,最多重试3次,不然咱们本身的回复消息就到达不了用户的手机了。若是咱们本身的服务器没法在5秒内回复,就回复一个空字符串,告诉微信服务器,不用重试了,这个消息处理不了,不给用户回复了。

上面的交互逻辑看起来很简单,但实际上坑有不少。

首先,微信服务器发送的POST请求根本就不符合HTTP规范。原则上POST请求不该该在URL上附带参数,但微信后台恰恰要这么干,这就让不少编程语言的标准框架没法获取到POST参数,由于标准的POST参数是从HTTP BODY中解析的。因此从POST获取URL参数就须要用到更底层的代码。如今不管作什么都讲究的是效率,什么东西有现成的咱们就不须要去重复的造轮子,直接拿来使用便可。在.net下微信开发咱们推荐使用开源的SENPARC.WEIXIN SDK,这个sdk基本完成了微信全系列的操做功能,使用的客户多,一直在升级中,可放心使用。简单的几行代码就能够实现一个功能,何乐而不为呢。
接收微信的请求代码参考:

[HttpPost]
[ActionName("Index")]
public Task<ActionResult> Post(PostModel postModel)
{
    return Task.Factory.StartNew<ActionResult>(() =>
    {           
        if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, "WeiXinToken"))
        {
            return new WeixinResult("参数错误!");
        }
        postModel.Token = "****Token***";
        postModel.EncodingAESKey = "***EncodingAESKey***"; //根据本身后台的设置保持一致
        postModel.AppId = "****AppId***"; //根据本身后台的设置保持一致
        
        //自定义MessageHandler,对微信请求的详细判断操做都在这里面。
        var messageHandler = new CustomMessageHandler(Request.InputStream, postModel,10);

        messageHandler.Execute(); //执行微信处理过程

        return new FixWeixinBugWeixinResult(messageHandler);

    }).ContinueWith<ActionResult>(task => task.Result);
}

吐槽:微信和微信公众平台虽然产品很先进,但后台API设计得确实不咋地。因为API是给开发人员使用的,因此,设计一个好的API要从开发人员的角度出发。与其使用笨重的XML,不如使用更符合Web潮流的JSON。
例如验证服务器:

{
    "signature": "xxx",
    "timestamp": 123456,
    "nonce": "xxx",
    "action": "verify",
    "data": {
        "echostr": "echo"
    }
}

这样设计的API,各类编程语言都能处理,并且处理逻辑更简单,速度更快。

参考文章

微信公众平台技术文档-官方

Senparc.Weixin SDK + 官网示例源代码

RDIFramework.NET — 基于.NET的快速信息化系统开发框架 — 系列目录

RDIFramework.NET ━ .NET快速信息化系统开发框架 ━ 工做流程组件介绍

RDIFramework.NET框架SOA解决方案(集Windows服务、WinForm形式与IIS形式发布)-分布式应用

RDIFramework.NET代码生成器全新V3.5版本发布-重大升级


一路走来数个年头,感谢RDIFramework.NET框架的支持者与使用者,你们能够经过下面的地址了解详情。

RDIFramework.NET官方网站:http://www.rdiframework.net/

RDIFramework.NET官方博客:http://blog.rdiframework.net/

同时须要说明的,之后的全部技术文章以官方网站为准,欢迎你们收藏!

RDIFramework.NET框架由专业团队长期打造、一直在更新、一直在升级,请放心使用!

欢迎关注RDIFramework.net框架官方公众微信(微信号:guosisoft),及时了解最新动态。

扫描二维码当即关注

微信号:guosisoft

相关文章
相关标签/搜索