升讯威微信营销系统开发实践:(4)源代码结构说明 与 安装部署说明( 完整开源于 Github)
我在之前的博客中开源了全部工程源代码和数据库脚本,陆续有朋友问我怎样安装部署,因为时间的关系我只能有一搭没一搭的回答一些零散的问题,对不住大家。前些天帮一个小兄弟把整个系统完整的部署起来并运行成功,我想索性借着这个机会,把这个过程整理出来,写成博客分享,这样大家从 Github 上拿到工程就不会不知从何开始。
GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction
因为个人精力时间有限,不会再对现有代码进行更新维护,不过微信接口比较稳定,经测试至今没有变化,功能依然全部可用,你可以在此基础上,二次开发,完成你的业务功能,也可以抽取本平台中的代码复用在你的项目中,请遵循 MIT 开源协议保留我的版权声明和网站链接即可。
GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction.WeixinContract
微信协议包装的项目还有一个单独的工程,这个工程的版本稍新,我会进行一定的更新维护,如最近增加了几个小程序开发需要使用到的接口。但是注意因为代码结构经过优化调整,直接引用到升讯威微信平台中,需要修改一些类的引用和名称。
升讯威微信营销系统开发实践系列
升讯威微信营销系统开发实践:(1)功能概要与架构设计
升讯威微信营销系统开发实践:(2)中控服务器的详细设计
升讯威微信营销系统开发实践:(3)功能介绍与此项目推广过程的一些体会
升讯威微信营销系统开发实践:(4)源代码结构说明 与 安装部署说明
这是2015年到2016年间业余时间写的一个项目,最初的期望是实现一个微信云平台,类似于微盟,只需要商家扫码绑定即可提供整套的营销功能。
我的定位是专门服务于线下商家,例如电影院、商业中心、各类线下门店等,线下商家的一些业务场景和业务流程是比较特殊的,和纯现上的公众号运营不尽相同。 这是我最初想找到的切入点,在系统初步上线后,自己也试着做了推广,包括百度关键词、线下陌拜都尝试过,在之前的博客中我也简单讨论过一些细节。
我在之前的博客中开源了全部工程源代码和数据库脚本,陆续有朋友问我怎样安装部署,因为时间的关系我只能有一搭没一搭的回答一些零散的问题,对不住大家。前些天帮一个小兄弟把整个系统完整的部署起来并运行成功,我想索性借着这个机会,把这个过程整理出来,写成博客分享,这样大家从 Github 上拿到工程就不会不知从何开始。
要了解升讯威微信营销系统的架构设计,请参阅之前我发表的博客,帮助你快速了解代码实现层面的体系结构。
本文不再对宏观结构进行赘述,只从代码细节方面介绍几个关键的地方,帮助你快速了解代码的具体实现。
功能概要:
有关架构设计,和详细功能介绍,请参阅我之前的博客文章。
升讯威微信营销系统开发实践:(1)功能概要与架构设计
升讯威微信营销系统开发实践:(2)中控服务器的详细设计
微信端效果:
更详细的功能介绍请参阅:
升讯威微信营销系统开发实践:(3)功能介绍与此项目推广过程的一些体会
在本文中我将分为两个部分,第一部分详细介绍代码层面的主要结构,第二部分详细介绍安装部署的方法。
一)代码结构
从 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/ThirdPartyWeixinApi/Handler/$APPID$
其中$APPID$在实际推送时会替换成所属的已授权公众号的appid。
推送消息过来时,URL如下格式:
http://wxc.shengxunwei.com/WeixinApi/Handler/F6AAD430-CA1F-4AFD-B2B0-6E0D2FABB622
?signature=84001ea92e2f369642e861d557b9f4c6781db1ca
×tamp=1446393828
&nonce=1291578710
&encrypt_type=aes
&msg_signature=3ed4a96dbc50d491664ec3f425eb7fc1f088ac9b
在接收到POST过来的消息后,第一步需要先解密,然后找到这条消息应该归属哪个微信公众号,找到它对应的公众号上下文,把解密后的消息交给它处理。
ClientDomainContext 是微信端使用的公众号上下文,有关公众号上下文的详细说明,请参阅:
升讯威微信营销系统开发实践:(2)中控服务器的设计
http://blog.shengxunwei.com/Home/Post/1acfa439-8fef-4609-8e74-7057c9f15a3b
在 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 中实现了相关功能:
二)安装部署
1)微信开放平台配置说明
注册申请微信开放平台
在第三方平台中,创建第三方平台。创建成功后,获得所创建第三方平台的 AppId 和 AppSecret。
并按提示配置好“授权登录相关”和“授权后实现业务”中的各项参数。
关于几个 URL 的配置,需要先了解升讯威微信营销系统的架构,可以参考相关博客文章和下文的站点部署说明部分。
登录授权的发起页域名:管理端域名,如 wxcm.shengxunwei.com,不需要填写协议部分 http 或 https。
授权事件接收URL:http://鉴权中控服务域名/ThirdPartyAuth/Handler
消息与事件接收URL:http://微信端域名/ThirdPartyWeixinApi/Handler/$APPID$
公众号开发域名:管理端域名和微信端域名,如 wxcm.shengxunwei.com;wxc.shengxunwei.com
白名单IP地址列表填写你的服务器IP地址。
2)安装Redis
可以准备一台 Linux 服务器安装:
https://redis.io/download
也可以下载 Windows 版本安装在 Windows 服务器:
https://github.com/MicrosoftArchive/redis
3)站点部署说明
Sheng.WeixinConstruction.Client.Shell
微信端
解决方案:Sheng.WeixinConstruction.sln
所对接过来的公众号所使用的站点。
微信端在部署时使用的域名,必须在你的域名服务端后台开启泛解析,因为对接过来的公众号,会使用 appid 开始的二级或三级域名过时行访问。
假设你的微信端域名是 wxc.shengxunwei.com ,那么对接过来的公众号将使用 $APPID$.wxc.shengxunwei.com 作为域名。这样避免因某个公众号出现违规内容被封,影响到其它公众号甚至整个平台。
IIS绑定参考:
类型 |
主机名 |
端口 |
IP地址 |
http |
wxc.shengxunwei.com |
80 |
* |
http |
80 |
* |
注意,要添加一个不指定主机名的绑定,并使用80端口,与泛解析对应。
WebConfig的配置:
connectionStrings节点下:
DefaultConnection配置主数据库 WxConstruction 的连接串,LoggingConnection 配置日志库 WxLogging 的连接串。
appSettings节点下:
debug:false,正常运行发布模式,如果设置为true,则开始调试模式,不走微信鉴权,直接模拟一个访问者身份,方便本地开发调试。
FileService:文件服务器的地址,如:http://wxcfile1.shengxunwei.com/
ContainerService:鉴权中控服务的地址,可以使用内网地址,只要项目能访问到即可,如:http://localhost:8013/
ClientAddress:微信端的地址,注意必须加上 $APPID$,如:http://$APPID$.wxc.shengxunwei.com/
IntranetIp:微信端自身的内网IP 地址,用于其它服务发起回调使用,使用公网地址也可以,只要能被其它服务,如文件服务访问到即可,如:127.0.0.1
Sheng.WeixinConstruction.Container
鉴权中控服务
解决方案:Sheng.WeixinConstruction.Container.sln
鉴权中控服务的中提供的 API分为两部分,一部分开放给微信第三方平台调用,另一部分为升讯威微信营销系统自己使用,对于后者,我们使用内网IP地址加端口号的方式访问即可,同时在webconfig 中,配置上允许调用的IP地址白名单,防止未经许可的调用。
IIS绑定参考:
类型 |
主机名 |
端口 |
IP地址 |
http |
8013 |
* |
|
http |
wxauth.你的域名 |
80 |
* |
WebConfig的配置:
connectionStrings节点下:
DefaultConnection配置主数据库 WxConstruction 的连接串,LoggingConnection 配置日志库 WxLogging 的连接串。
appSettings节点下:
Redis:Redis服务的地址和端口号。
AllowedIPList:IP地址白名单,逗号分隔,只有从这些IP 地址发起的请求,才被允许访问中控服务器的全部接口。
ContainerService:鉴权中控服务的地址,可以使用内网地址,只要项目能访问到即可,如:http://localhost:8013/
Management.Shell
管理端
解决方案:Sheng.WeixinConstruction.sln
升讯威微信营销系统的后台,用户在此注册账户后,对接到自己的公众号并使用相关功能。
IIS绑定参考:
类型 |
主机名 |
端口 |
IP地址 |
http |
wxcm.shengxunwei.com |
80 |
* |
WebConfig的配置:
connectionStrings节点下:
DefaultConnection配置主数据库 WxConstruction 的连接串,LoggingConnection 配置日志库 WxLogging 的连接串。
appSettings节点下:
debug:false,正常运行发布模式,如果设置为true,则开始调试模式。
FileService:文件服务器的地址,用户从后台上传的文件,将被上传到文件服务器中进行存储,如:http://wxcfile1.shengxunwei.com/
ContainerService:鉴权中控服务的地址,可以使用内网地址,只要项目能访问到即可,如:http://localhost:8013/
ClientAddress:微信端公众号所使用的域名地址,如http://$APPID$.wxc.shengxunwei.com/
emailPassword:发邮件功能中邮件服务器的密码。
Redis:Redis服务的地址和端口号。
FileService
文件服务器
解决方案:Sheng.WeixinConstruction.FileService.sln
升讯威微信营销系统的文件服务器,可以部署多个实例,后台上传的文件将被存储在这里。同时,它还兼具与微信后台中的素材管理接口一部分互通和功能实现。
IIS绑定参考:
类型 |
主机名 |
端口 |
IP地址 |
http |
wxcfile1.shengxunwei.com |
80 |
* |
WebConfig的配置:
connectionStrings节点下:
DefaultConnection配置主数据库 WxConstruction 的连接串,LoggingConnection 配置日志库 WxLogging 的连接串,FileConnection配置文件数据库WxConstruction_File的连接串。
appSettings节点下:
ContainerService:鉴权中控服务的地址,可以使用内网地址,只要项目能访问到即可,如:http://localhost:8013/
ServerPath:部署的实际物理路径地址,如:D:\wwwroot\WeixinConstruction\FileService\
Redis:Redis服务的地址和端口号。
文件服务的 MIME类型需要添加:
.mp4 – video/mpeg4
至此,代码结构和安装部署说明结束,如有其它疑问,可以与我联系留言。