29 Star 42 Fork 18

mrcode / wx_sdk

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

构建项目

eclipse 的没有添加插件和配置。请自行百度

idea

  1. 建议手动在cmd中使用命令行:执行 gradle build -x test --debug 能看到构建的进度和出错的详细信息
  2. 在命令行构建完成后,用idea打开该项目

在线文档地址 http://www.mrcode.cn/zhuqiang/article/details/825C9F25DB83418F9943E28B49D26CD6.html

#wxsdk

该项目能做什么?

该项目作为JAR包使用,从接入公众号,到开发调用微信api ,搭成了一个架子。 现有部分api 是自用过的。包括在生产环境用过的。 目的就是简化调用操作。 从封装体系来扩展一个 本项目没有的微信API来说,几行代码搞定。

  1. 统一的生命周期维护
  2. 统一的请求器
  3. 统一的api扩展机制
  4. 使用者只关注暴露的服务调用就ok

1. 文档风格简写定义

  1. 作废标识 : [× 2016.04.22][类型:废弃;理由:使用新策略维护,稳定性比较好] 作废的内容依次写到作废条目下,将该作废内容移动到,每个模块下专门的废弃条目中
  2. 更新标识 : [↑ 2016.04.22]
  3. 新增标识 : [* 2016.04.22]
  4. 解决标识 : [√ 2016.04.22] 类似bug管理等场景

2. 使用和部署注意事项

特别注意的是:使用分布式来维护生命周期,所有被部署的机器上的sdk文件必须一样

2.1. 使用前的准备:

  1. 填充配置文件 initConfig.xml 里面每个属性的说明能在initConfig.xsd中找到,也有注释
  2. 初始化sdk的入口类说明:
模块 初始化入口 描述
core CoreInit 不使用web的时候,可以直接new CorInit类完成初始化
pay - 依赖core中的初始化数据
web WebInit 如果依赖了web包,则只需要new WebInit类。该类会自动先去调用core中的初始化操作。

注:

  1. 初始化指定自定义initConfig.xml 路径 在初始化类构造函数中,选择有参构造注入参数:可为空:默认加载sdk中的initConfig.xml文件
  2. 初始化指定使用者机器id:用来定位是哪一台机器在更新维护zk数据 在初始化类构造函数中,选择有参构造注入参数:可为空:默认使用 “本机ip:描述” 的字符串作为id

spring.xml中初始化的时候,一定要设置lazy-init=false:让sdk在项目启动时完成初始化,否则可能会出现问题

spring 容器初始化:
<bean class="cn.mrcode.wxsdk.core.CoreInit" lazy-init="false">
    		 <!-- initConfig.xml 可为空使用默认的配置文件 -->
    		 <!--<constructor-arg index="0" value=""/>-->
    		 <!-- 指定该应用的唯一id,用于追踪是哪台机器更新了zk数据 ,可为空,使用默认策略生成id-->
    		 <!--<constructor-arg index="1" value="192.168.5.75"/>-->
</bean>    		 

测试模版中的初始化:
new CoreInit();

注意:应用的唯一id 建议手动为每一台机器增加,在linux中偶发性获取不到ip地址

2.2. 接入开发者模式

注: 该步骤不是必须的,因为本sdk 所提供的服务都是基于静态方法,该步骤适合需要接入开发者模式的服务器

    {
        // 设置自己的消息处理器,否则sdk将使用 DefaultInMessageProcessingHandler 作为默认的消息处理器
        Access.setInMessageProcessingHandler(myInMessageProcessingHandler);
    }
    @RequestMapping("/wx")
    public void index(HttpServletRequest request, HttpServletResponse response) {

        String appId = request.getParameter("appId");// 扩展字段,可用于管理多个微信号
        String signature = request.getParameter("signature");// 微信加密签名
        String timestamp = request.getParameter("timestamp");// 时间戳
        String nonce = request.getParameter("nonce");// 随机数
        String echostr = request.getParameter("echostr");// 随机字符串,接入的时候校验

        // 从配置上下文中获取到 配置文件中配置的公众号数据 也可以自定义数据源获取
        PublicAccount publicAccount = SdkContexts.getConfigContext().getDirstributedConfig().getPublicAccountMap().get(appId);
//      inMessageProcessingHandler.openTestMode();
        Access.in("",publicAccount,signature,timestamp,nonce,echostr,request,response);
    }

2.3. 服务简介

服务路径 描述
cn.mrcode.wxsdk.core.dialogue.service.Access 开发者模式消息接入入口
cn.mrcode.wxsdk.core.dialogue.service.BaseService 所有服务的基类,不能直接使用
cn.mrcode.wxsdk.core.dialogue.service.CommonService 获取accesstoken 等公用服务
cn.mrcode.wxsdk.core.dialogue.service.TemplateMsgService 模版消息服务
cn.mrcode.wxsdk.core.dialogue.service.ToPromoteService 推广服务:二维码服务 与 长链接转短链接
cn.mrcode.wxsdk.web.service.PayCommonService 支付的公共服务,包括支付相关的原生api
cn.mrcode.wxsdk.web.service.CommonService 获取openid等服务
cn.mrcode.wxsdk.web.service.JsSdkService 微信jssdk相关服务
cn.mrcode.wxsdk.web.service.WebCommSV 与web容器相关的web公用服务,算是一个小扩展

2.4. 关于快速测试

  1. 每个模块都有一个基于 cn.mrcode.wxsdk.core.test.BaseTest 的子类实现;BaseTest 用于为测试类提供统一初始化操作
  2. cn.mrcode.wxsdk.core.dialogue.service.CommonServiceTest 中是一个获取accesstoken的测试用列模版

2.5. 关于分布式zookpeer维护token和tike的生命周期问题

在线上增加新的公众号支持:(不包括支付:支付动态增加还没有做)

  1. 更改配置文件中的公众号列表,使用 WebResetZkData(对应的CoreResetZkData 只更新token相关数据,而web的则会自动调用core的再调用自己的) 手动更新zk上的数据(覆盖更新)
  2. 手动更新完整之后,这个时候在线的机器就会收到 最新的数据
  3. 把最新的配置文件同步到线上机器,然后重新启动服务器。完成线上机器的配置文件的替换

预计将来做成:能直接使用手动更新操作,新增对公众号的普通维护和支付维护。

zk目录介绍

服务路径 描述
/wx 根路径
/wx/basetoken token 节点路径
/wx/ticket ticket节点路径
/wx/runing leader id 存放位置,用于定位是哪一台机器导致更新失效(出现127.0.0.1 霸占了leader)

2.6. 关于消息/关键词自动回复

sdk实现了默认的规则框架:思路是:

  1. 配置文件中 根据cn.mrcode.wxsdk.core.dialogue.common.rule中所支持的规则实体,进行json数据填充
  2. 使用线程( new Thread(new RuleTiminUpdateTask()).start();)去监视文件,然后读取配置文件中的内容到内存中
  3. 在消息处理器里面根据自有需求获取关键词对应的规则实体,然后判断处理并返回;
    RuleTiminUpdateTask.rules.get(keyword);
        String type = rule.getType();
  1. 更具体的描述在 RuleTiminUpdateTask 中的说明;

2.7 本框架中,你需要关注的侧重点

  1. initConfig.xml 配置文件,配置好所需要的参数
  2. InMessageProcessingHandler接口 : 生产开发是必须自己实现该接口,编写自己的业务代码,在这个里面调用提供的各种服务和消息等转换(在DefaultInMessageProcessingHandler中有简单的消息类型示例)

3. 引用本sdk出现的FAQ

  1. Q:项目启动提示某某jar不存在等类似提示 A:项目中存在不兼容的版本jar包,引用sdk的项目中不存在sdk所使用的jar包,解决:引入所需要的jar包
  2. Q:如果出现 无可用token的日志。 A:最大的可能是每台机器的配置文件不一致。作为leader的机器上的配置文件中没有该appId的信息。
  3. Q:如果在运行过程中,有token/ticket过期了怎么办? A:使用 WebResetZkData(对应的CoreResetZkData 只更新token相关数据,而web的则会自动调用core的再调用自己的) 手动更新zk上的数据(覆盖更新)
  4. Q:提示 wx.sdk.dialogue.common.XMLParaser 中 Node 相关的方法出错,(一般出现在My/eclipse中) A:打开Java build path --> order and export 选项卡中,把 JRE(就是java jdk包移动到最顶端)
  5. Q:在使用过程中,特别是在linux中部署的web服务,会出现一台服务器出现两次或多次在zookpeer上注册临时目录,或则就是web容器服务被停止掉了,但是临时目录不会消失 以上问题就会导致出现更新维护数据错乱,或则更新不及时 A:有可能出现的问题有以下几点: 1. 其他使用的zk服务的客户端 的系统时间和zk服务器的不同步,导致通信有问题 2. tomcat配置文件配置有问题,导致项目资源被加载了两次,依赖web容器生命周期的功能 都会存在被启动两次的情况 3. tomcat进程可能存未杀死。

4. 开发和维护sdk注意事项

4.1. 协议约定

在开发和维护的时候,要严格遵守:

  1. 每个模块之间不能循环依赖
  2. 请求器中httpClient访问错误通过ReqException抛出
  3. 微信api返回的协议result 如果有错,通过WxException抛出,sdk最多只能校验result的协议异常。其他业务异常禁止sdk处理。在每个数据返回包中都有业务result字段,需要调用出自己判断处理
  4. sdk自己的一些规则异常,通过 SdkException抛出
  5. 严格按照 sdk 结构封装

4.2. 一些策略点

  1. 多公众号支付,提供的默认httpClient中会在初始化的时候通过支付公众号列表把证书请求器都创建出来。
  2. 在分布式的情况下,暂时只支持维护固定配置列表中的 token 或则 ticket公众号
    1. [* 2016.04.22] 动态新增公众号方法:
      1. 任意一台服务起上手动重置zk数据(使用test包中cn.mrcode.wxsdk.**.upzk.curator.Client,把当前所有需要维护的公众号,包括新增的(initConfig.xml中) 重置一遍到zk上)
      2. 然后启动该服务器 原理解析:
        1. master 任务更新机器,提供对外读,进程写功能:
          1. 第一次获得master启动更新任务钱,会先从 zk上获取数据,解析成task列表,如果initConfig.xml中存在zk中没有的公众号,那么该公众号将被忽略加入task中
          2. 启动更新任务,以task列表为准,转换成延迟队列,然后阻塞获取超时的数据
        2. follow 只提供读功能 :
          1. 启动时,将会从zk上拉取一次数据,存入本地缓存中。 根据以上两步操作,就能让集群中的新启动的机器立即支持新的公众号服务,但是旧的机器 因为 策略1的限制下,将不能提供对新增公众号的服务支持,采用逐步重新启动所有机器,将能达到过渡更新的效果
  3. 配置上下文和初始化上下文,在重构中:目标是做成能动态根据配置文件修改后,自动重新加载新的配置文件内容

5. 暂未解决的或则未完善的点


6. 需求

  1. 进一步封装 初始化相关的代码,完善 封装的安全性。
  2. 扫码 触发的关注事件,和扫码触发的事件,貌似没有处理。
  3. 再次抽象化zkmaster

7. 更新问题汇总

2016.06.29

  1. 抽象生命周期维护任务类,优化该类执行逻辑代码
  2. 手动重置数据使用默认的test规则
  3. 修复生命周期维护重构后的一些bug

2016.06.28

  1. 修复 在liunx中设置sdk默认id的时候偶尔会获取到的ip地址为 127.0.0.1 的bug:根据测试看来,在linux中光靠程序优化处理不了获得正确的ip地址(应该需要修改host文件,显式的配置内网ip)
  2. 重构test下 curator中的 重置zk上的数据
  3. 重构提取curator中相关比较多的重复操作
  4. 增加test下 自动查找leader的path路径类
  5. 其他部分代码优化

2016.06.27

  1. 增加leader更新运行信息。用于定位是哪一台机器占用了leader位置 (由于暂时无法取得lockPath 创建的子节点名称,所以使用了新建子节点runing,用于保存leader运行id)
  2. 在维护的临时目录下写入id,分辨是哪一台机器在使用该目录

2016.06.23

  1. 在入口处增加id标识,在更新过程中,将会使用该id作为最后更新者定位某一台机器

2016.06.17

  1. 完善test的前置sdk初始化抽象类,基于基类快速完成测试
  2. 优化手动更新数据功能
  3. 无论是手动更新功能还是数据测试功能,都统一从ConfigContext中获取公众号列表信息
  4. web 中测试的时候,读取不到config.properties 文件,只能单独和 core中的配置文件分开了
  5. 重新整理了不需要的原生分布式维护生命周期相关类
  6. 分布式维护生命周期的 lastUpBy 也就是唯一id(用ip的话就不唯一了),现在使用当前机器的ip地址进行赋值

2016.06.16

  1. 把项目更改为 gradle构建的项目
  2. 把项目分模块:对话层功能(也就是基础的一些功能,按微信api划分) -- core;pay --> pay; web --> web
  3. 重构初始化类的逻辑:把web层的初始化分离到web层了: 现在的初始化逻辑相当于:如果没有web层,则直接new CoreInit;有web层就new WebInit
  4. 分布式下的功能已测(依赖zookpeer管理token 和 ticke);单机版的暂未测试
  5. 移除initConfig文件中的一些不需要的配置参数
  6. 手动更新的类文件在core 和 web 下的upzk中。同上面的规则一样,使用到了web 就直接执行web的就能更新core的了

2016.04.22

  1. 新增手动更新生命周期源:curator.updatezk --> public class Client 类中 main方法:用于动态新增前的准备工作
  2. 确认文档描述中的一些规范

2016.04.20

  1. 把简单初步的关键词延迟功能模型增加到本sdk中。并在sdk.dialogue.common.rule.task.RuleTiminUpdateTask 中标识了使用方法 由于定位是sdk,只是提供了一个简单的规则动态解析,规则模型,调用思路 ,要使用的话,需要在项目启动完成后,手动启动task线程, 或则(不使用本sdk提供的简单框架模型,自己模仿该思路定义一套更强大的规则模型) 支持的功能有: 1. 动态修改ruls源:wxrule.properties中的规则内容,task在一定时间内会自动重新获取覆盖内存中的ruls源,方便对规则的修改 2. 单关键字/多关键字 对应单条规则 3. 规则可以返回的类型:文本消息类型,单图文类型
  2. 新增一套分布式生命周期维护,使用 Curator zk客户端的master策略进行维护。试运行,把根目录集成到了一个里面 使用框架客户端来维护,性能和出错几率减少。

2016.04.19

  1. 增加了转接多客服消息的outMsg类型支持

2016.03.23

  1. 在初始化分布式zk的时候,把init方法放到构造函数外面。应该可以防止一些莫名奇妙的问题(比如:父类还没有构造完成,但是会回调子类的一些属性,虽然已经解决过了,但是以后再统一详细的调式吧)

2016.02.23

1.对获取Ticket 和 token的api增加了最后更新者的属性(在分布式中可根据它进行定位是那一台机器更新的)

2016.02.22

  1. 修改分布式tick和token task 中的日志打印方式。

2016.1.14

  1. 修改一些日志级别
  2. 对web项目支持一种session维护openid的支持

2015.11.20

  1. 简单增加xsd schema文件校验。降低程序中的一部分校验

2015.11.18

  1. 在配置文件中配置 httpClientClassName 项,可以动态的替换实现(IHttpClinet请求器的实现)

2015.11.16

  1. 替换sdk底层支持逻辑,支持多公众号支付功能,httpClient请求器/ssl证书请求器,现在由IHttpClinet的子类来管理实现
  2. 重构异常类:
    1. SdkException :顶层异常,sdk中的业务规则,等会使用该异常对象抛出。抛出的编码都存在SdkGlobalCode中
    2. ReqException :httpClient请求器,请求过程中出现的异常,通过该对象抛出,包括远程服务器不可访问等异常消息
    3. WxException : sdk中微信所返回的所有协议异常都由该对象抛出。比如:调用接口返回的 解析xml错误,token不能使用等异常。

2015.10.23

  1. 提供IHttpClinet请求器接口,在整个sdk访问过程中,都使用该接口进行远程调用。 为自定义提供请求器做铺垫
  2. 提供一个默认的DefeatHttpClient请求器实现,该请求器使用使用AsyncHttpClient作为基础实现

2015.10.23

  1. 新增测试类:解决token/ticket偶然过期问题(一般多出现在 zk服务器重复开关,多个项目更新同一个公众号的情况)。使用方式:测试包下: updateZk.Client.main(); 手动运行

2015.10.20

  1. 解决初始化 给私有静态常量赋值的 封装安全性问题。已经把显示的setter方法给移除。

2015.10.12

  1. 新增app端支付参数的获取

2015.10.10

  1. 统一日志打印,之前的日志打印有bug
  2. 更改一些类文件的说明信息位置,之前的doc查看不显示
  3. 新增 发送模版消息功能,增加一种 金融/银行 交成功通知的 模版内容支持。
  4. 消息处理增加 模版消息发送后的 成功与否的事件推送处理

2015.10.08

  1. 初始化基础token 和 ticket 休眠策略修改为5秒。(在本机是leader的情况下,有足够的时间刷新token到本地)
  2. ZkDistributedSingleNodeExecutor 修改超类,解决 由于第一次推送数据,构造块未执行完,造成的空指针问题。
  3. init类中初始化策略变更:在初始化 ticket前,会尝试先获取本地的token,有日志打印(一般来说,出现无可用的token的日志信息,造成的原因是,每台机器的配置文件不一致。 可以通过 本地可用token的数量 和 尝试获取的进度数量看出来一些端倪)
  4. 修改生命周期任务机制:为 动态新增修改公众号token做铺垫: 每次获取到数据,就更新本地 task列表(以zk上的列表为准),也就是说:动态增加公众号之前,需要手动的触发更新到zk上。 如果以后有这样的需求。可以写一个小工具类(目前的实现是:DelayQueue队列来获取超时的,每次超时后会重置DelayQueue队列(把最新的task列表放入DelayQueue队列中) 所以这样更新到本地就有一个时间延迟,只有有超时的时候,队列中才会被更新。 处理小工具的时候 需要考虑下这个问题 (1.不能修改公众号的账户信,如果需要。只能把该公众号移除zk,等待leader更新之后,再把该公众号加上))

2015.9.29

  1. 新增 jssdk ticket 支持分布式维护生命周期
  2. 解决ZkDistributedSingleNodeExecutor中出现的一些多线程空指针问题
  3. 暂时解决ZkDistributedSingleNodeExecutor的实现类 由于先初始化父类首次推动数据firstRefresh所照成的 自定义构造参数未实例化的问题。
  4. 由于引入 ticket 生命周期分布式支持,引发了:本地token没有数据的时候被ticket所调用,采用先初始化 基础token的zk服务,休眠2秒后再执行ticket的初始化操作。
  5. getAccesstoken操作,由于分布式数据第一次刷新到本地的时差,增加了策略:如果一直没有获取到数据,最多将尝试获取10次,每次休眠500毫秒。
  6. 新增log4j日志打印,方便调试(没能解决按自定义模版打印消息)

2015.9.23

  1. 初步实现 ZkDistributedSingleNodeExecutor 分布式单节点容灾
  2. 把之前写死的 配置,提出了一部分到initConfig.xml中,使用配置文件或则配置类来初始化sdk所需要的一些参数

2015.9.23~以前

初始迁移成独立模块。


8. 一张图看懂本sdk结构

微信封装sdk结构图.jpg


9. sdk层级讲解

说明:层级模块划分按照:微信公众平台后台登录后,左侧菜单中--> 接口权限 中列出的功能进行模块层级的划分

core

  1. context: 提供上下文环境配置,配置文件的解析配置
  2. test 测试基类: 用于提供初始化 配置参数等功能;用于测试每个模块的测试用列
  3. zkhelper.curator 封装操作zookpeer的curator框架工具类,也包括根据机器id查找zk路径

dialogue

按照微信APi划分模块,基础对话模块,文档下面所有的模块都会依赖此模块

common

  1. common.accessToken 的核心功能之一:维护accessToken的生命周期,包括单机版(长久未使用,所以没有继续维护了,不保证能正常使用)和分布式版本
  2. common.exception 包括全局code错误码,和sdk的异常类;sdk中的大部分可捕获异常都会被包装为该包下面的异常类抛出
  3. common.httpClient 核心功能之一:提供sdk所操作的http请求接口,和提供默认实现类,可以继承该接口然后在配置文件里面配置,使用自己的http请求器
  4. common.rule 基础功能框架的实现,sdk不会主动调用该功能,只是演示了一下思路。功能有:自动回复,按关键词回复,按事件触发回复, 要结合InMessageProcessingHandler类来开启调用该模块的功能。里面相关的类说明里面有详细的说明
  5. common下其他类 都是基础的工具类和实体类

hander

核心功能之一: 开发者模式接入处理接口和默认实现类,需要接入开发者模式的话,此接口是重点实现对象,需要根据自身的业务规则 实现具体所需要的功能,里面有默认的类进行一个示例

protocol

协议数据包,req包实体,res包实体,根据微信api进行划分。 基础会话等api请求回包,全局基类接口等协议都在这里了

service

客户端使用量最多的对外包:此包封装了该模块下所有的接口请求和服务。一般客户端都只需要使用该类下面的服务类即可 1. Access 是开发者模式入口所需要的参数逻辑进行了简单的封装,一般在开发者回调链接的action中直接委托该类即可 Access.in(inMessageProcessingHandler,"",publicAccount,signature,timestamp,nonce,echostr,request,response); 2. 其他服务 按照微信 api 功能进行封装

pay

微信支付相关的功能都在该模块下进行封装,依赖 dialogue 模块

common

公用操作 包括:支付错误码,返回码,交易类型等

hander

数据辅助处理操作 提供对支付接口所请求的api参数进行校验功能

protocol

协议数据包,req包实体,res包实体,根据微信api进行划分。 支付相关的api请求回报协议都在这里了

service

客户端使用量最多的对外包:此包封装了该模块下所有的接口请求和服务。一般客户端都只需要使用该类下面的服务类即可 支付功能对外暴露的服务功能

web

微信jssdk相关的api功能都在这里了

common

公用操作 包括:ticket的生命周期维护,与dialogue中的accessToken生命周期是同一类功能;微信网页授权 链接生成功能等

hander

数据辅助处理操作 提供对支付接口所请求的api参数进行校验功能

protocol

协议数据包,req包实体,res包实体,根据微信api进行划分。 支付相关的api请求回报协议都在这里了

service

客户端使用量最多的对外包:此包封装了该模块下所有的接口请求和服务。一般客户端都只需要使用该类下面的服务类即可 jssdk授权,openid,jssdk支付参数获取等功能

空文件

简介

封装微信常用的api,从接入到开发,扩展没有的api,easy 展开 收起
Java
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/zhuqiang/wx_sdk.git
git@gitee.com:zhuqiang/wx_sdk.git
zhuqiang
wx_sdk
wx_sdk
master

搜索帮助