GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction
因为个人精力时间有限,不会再对现有代码进行更新维护,不过微信接口比较稳定,经测试至今没有变化,功能依然全部可用,你可以在此基础上,二次开发,完成你的业务功能,也可以抽取本平台中的代码复用在你的项目中,请遵循 MIT 开源协议保留我的版权声明和网站链接即可。
GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction.WeixinContract
微信协议包装的项目还有一个单独的工程,这个工程的版本稍新,我会进行一定的更新维护,如最近增加了几个小程序开发需要使用到的接口。但是注意因为代码结构经过优化调整,直接引用到升讯威微信平台中,需要修改一些类的引用和名称。
升讯威微信营销系统开发实践系列
升讯威微信营销系统开发实践:(1)功能概要与架构设计
升讯威微信营销系统开发实践:(2)中控服务器的详细设计
升讯威微信营销系统开发实践:(3)功能介绍与此项目推广过程的一些体会
升讯威微信营销系统开发实践:(4)源代码结构说明
升讯威微信营销系统开发实践:(5)安装部署说明
在本文中我将分为两个部分,第一部分详细介绍代码层面的主要结构,第二部分详细介绍安装部署的方法。
一)代码结构
从 Github 上获取代码后,源代码目录结构如图所示:
解决方案说明:
- Sheng.WeixinConstruction.Admin.sln
超级管理员、系统运维人员使用的超级管理后台。
此部分功能开发并未完成,目前只有基本框架和微主页模版的简单管理功能。
- Sheng.WeixinConstruction.Container.sln
鉴权中控服务服务。
负责管理和维护第三方平台自己的 AccessToken 和对接过来的所有公众号的 AccessToken。
- Sheng.WeixinConstruction.FileService.sln
文件服务器。
提供独立文件存储服务,并提供了部分与微信公众号素材管理的功能。
可以部署多个不同的文件服务器实例,可以部署CDN内容分发。
- Sheng.WeixinConstruction.sln
管理后台和微信端。
管理后台用于向升讯威微信管理系统的一般用户提供服务,在此注册账户,对接自己的公众号,并使用升讯威微信营销系统的一系列功能。
微信端用于向所对接的公众号提供服务,在微信公众号上访问的站点。
- Sheng.WeixinConstruction.WindowsService.sln
Windows 服务
主要用来执行一些定时服务。
下面主要对解决方案 Sheng.WeixinConstruction.sln 和 Sheng.WeixinConstruction.Container.sln 进行说明,其它几个解决方案都比较简单,不作赘述。
打开 Sheng.WeixinConstruction.sln 之后,结构如图:
- Sheng.WeixinConstruction.Management.Shell
后台站点
- Sheng.WeixinConstruction.Client.Shell
微信端站点
1)Sheng.WeixinConstruction.Management.Shell
对于管理后台,一个重要的功能是在用户注册账号后,实现与微信公众号的对接。
打开 Controllers 目录下的 SettingsController.cs ,并展开“对接”region。
Docking 与 DockingDemo 对应着用户对接公众号的页面。 DockingDemo是发起授权页的体验URL:用于腾讯审核人员前往授权页体验,确认流程可用性。此为腾讯要求。
AuthorizerEntity 表示授权公众号的信息,代码中有详细的注释,可自行查阅:
在用户对接公众号时,需要先获取一个预授权码,打开 Areas /Api/ Controllers 目录下的 SettingsController.cs,找到 GetPreAuthCode 方法,此方法用于获取预授权码:
在 Docking.cshtml 这个画面调用此接口,当成功获取预授权码之后,将页面转到腾讯要求的授权页面,并给出一个用于完成授权的回调页面,当公众号所有者通过授权时,腾讯将把页面转到此回调页面,并传回授权码:
打开 Controllers目录下的 SettingsController.cs,找到 AuthorizationCallback 这个授权回调方法,在此完成公众号的授权对接:
这里留意一个细节:
在系统中创建公众号授权信息,并开始维护它的 AccessToken ,并不是在后台中完成,而是调用鉴权中控服务器的接口,通知鉴权中控服务器来实现的:
_createAuthorizerUrl 是鉴权中控服务器的地址:
2) Sheng.WeixinConstruction.Client.Shell
微信端除了向所对接的公众号提供服务外,还负责与微信官方后台行进消息通信,微信官方下发的消息,是发到Sheng.WeixinConstruction.Client.Shell,而不是 Sheng.WeixinConstruction.Management.Shell。
所以最重要的是首先要处理好微信推送过来的消息,打开 Controllers 目录下的 ThirdPartyWeixinApiController.cs:
Handler 接口用于接收公众号消息与事件推送。
当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到此接口。
在微信用户和公众号产生交互的过程中,用户的某些操作会使得微信服务器通过事件推送的形式通知,在开发者中心处设置的服务器地址,从而开发者可以获取到该信息。其中,某些事件推送在发生后,是允许开发者回复用户的,某些则不允许。作为第三方平台运营时,AppId 会作为URL的一部分带过来,如:
http://wxc.shengxunwei.com/Th...$APPID$
其中$APPID$在实际推送时会替换成所属的已授权公众号的appid。
推送消息过来时,URL如下格式:
http://wxc.shengxunwei.com/We...
?signature=84001ea92e2f369642e861d557b9f4c6781db1ca
×tamp=1446393828
&nonce=1291578710
&encrypt_type=aes
&msg_signature=3ed4a96dbc50d491664ec3f425eb7fc1f088ac9b
在接收到POST过来的消息后,第一步需要先解密,然后找到这条消息应该归属哪个微信公众号,找到它对应的公众号上下文,把解密后的消息交给它处理。
ClientDomainContext 是微信端使用的公众号上下文,有关公众号上下文的详细说明,请参阅:
升讯威微信营销系统开发实践:(2)中控服务器的设计
http://blog.shengxunwei.com/H...
在 ClientDomainContext 中,引用了一个 XMLMessageReceiverFactory 的工厂类用于处理微信推送过来的XML消息:
在这个工厂类中,_receiverList 保存了处理不同消息所需要的具体实现,这些消息接收器的实现,定义在Sheng.WeixinConstruction.Client.Core:
那么当收到微信推送的消息时,只需找到对应公众号的上下文对象,调用它的 Handle方法,根据消息的类型,找到对应的处理器类,交给它处理,就可以了,这就是消息处理的过程。
在微信端,还有一件非常重要的工作,就是对公众号关注者的身份获取,OpenId和用户信息,例如:
当公众号的关注者(粉丝)访问微信端的页面时,需要获取关注者的个人身份信息,OpenId和其它信息,在此基础之上,与我们自己后台的信息关联。
打开 Controllers 目录下的 ClientBasalController,微信端视图控制器类都继承此基类:
当公众号的关注者访问微信端的页面时,首先控制器基类会获取该关注者的会员信息上下文和对应的公众号上下文:
在OnActionExecuting 方法中,按微信的协议要求完成对关注者身份的网页授权。
这里要先了解所服务公众号的域名解析细节,假设我们将微信端的域名配置为 wxc.shengxunwei.com,理论上我们让所有的公众号直接使用此页面,在URL后跟上公众号的ID即可,但是这样有一个重要的缺陷,如果平台所服务的公众号,有一个公众号存在违规行为,被微信查封,会导致我们整个平台被封,微信会直接把 wxc.shengxunwei.com 这个域名查封。所以我们必须泛解析的方式,让所服务的公众号使用 appid.wxc.shengxunwei.com 这样的域名来避免这种情况。如何在安装部署升讯威微信营销系统时配置泛解析域名,请参阅安装部署相关的详细说明。
网页授权的过程在 OnActionExecuting 方法中有详细的注释说明,可对照着代码来看:
注意对关注者身份的网页授权是跳转到微信官方授权页面进行的,完成授权后,会跳转回指定的回调页面,在 Areas/Api/Controllers 目录下的 ThirdPartyWeixinApi/OAuthCallback,代码中有详细的注释,请自行查阅:
至此,对关注者身份的网页授权完成。
还有一个前端页面 JS授权的方式,在微信支付时会涉及到,你可以找到 ClientDomainContext下的GetJsApiConfig方法来查阅:
此外,微信端也实现了微信支付功能,用于会员充值或积分商品购买商品:
微信支付的流程简而言之,需要先调用微信提供的统一下单接口,在微信支付端实现一个下单操作,这个下单和我们系统自身的下单是两个概念,完成统一下单后,生成相关信息给前端页面,前端页面调用微信提供的 js sdk 完成支付,支付成功后,微信服务器会向我们指定的回调 url 地址发出支付结果的通知。详细的流程,请查阅微信官方的开发文档。
我在 Areas/Api/Controllers/PayController.cs 中实现了相关功能: