diff --git a/.gitignore b/.gitignore
index ff01410..ef6ce9b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
target/
+.settings/
*.iml
*.class
*.jar
+*.classpath
+*.project
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..2d64c61
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,16 @@
+sudo: false
+language: java
+script: mvn clean package -Dmaven.test.skip=true
+jdk:
+ - openjdk6
+ - openjdk7
+ - oraclejdk7
+# whitelist
+branches:
+ only:
+ - master
+ - develop
+notifications:
+ email: false
+before_install:
+ - export TZ=Asia/Shanghai
\ No newline at end of file
diff --git a/README.md b/README.md
index e10b9e9..d964b7e 100644
--- a/README.md
+++ b/README.md
@@ -1,195 +1,247 @@
-!["MPSDK4J"](http://j2ee.u.qiniudn.com/mpsdk4j-logo.png-aliassmall "MPSDK4J")
-## MPSDK4J
-### 目录
-* [1.引言](#引言)
-* [2.介绍](#介绍)
- * [2.1.结构设计](#结构设计)
- * [2.2.交互时序](#交互时序)
-* [3.项目](#项目)
- * [3.1.最新源码](#最新源码)
- * [3.2.Maven库引用](#Maven库引用)
-* [4.示例代码](#示例代码)
- * [4.1.HttpServlet环境](#HttpServlet环境)
- * [4.2.Struts2环境](#Struts2环境)
- * [4.3SpringMVC环境](#SpringMVC环境)
-* [5.Issue](#Issue)
-* [6.联系](#联系)
-* [7.其它](#其它)
-
-
-#### 1.引言
-双11是一个令不少人狂欢的日子,今天你买了么?或许在那XXX亿的曲线中能找到你的影子哟,呵~,不过这与俺无关了,只是借用这个双11来纪念一下而已。从事微信公众平台开发也有一段时间了,算是积累了不少经验吧,趁这些天空闲的时间,把这些经验重构一遍拿出来分享一下。特此声明本人并非技术大牛(纯粹的技术渣),只是用最简单的流程与编码实现微信公众平台交互SDK,有什么不满意的话,可以尽情的吐槽。目前已经实现微信API所有的功能且同步至官方最新发布(如最新的AES消息加密),后续还会不断的扩展(会做一个多微信号管理平台),欢迎关注加入,谢谢。
-
-
-#### 2.介绍
-**MPSDK4J**,非常直观的阐述了此项目的意义所在。没错,它就是JAVA语言环境下的微信公众平台开发SDK。其中MP代表的是微信公众平台的域名前缀,SDK表示开发工具包,4同音英文“for”,J代表了JAVA。虽然现网络上已经有不少JAVA版本的SDK现身,但是***[MPSDK4J]*** 的出现也并非只是造轮子的重复工作。它遵循单一设计模式规则,所有的设计与功能都是源于微信公众平台API,一切都是为了追求简单与速度。
-
->**a.设计简单**:整体设计非常的简单,仅有7个包39个类对象(其中VO对象占据一半之多,详见结构设计图),核心功能部分就4类(WxBase,WxApi,WxOpenApi,WxHandler);
-
->**b.解析速度**:基本SAX驱动式XML处理,结合JDK7的新特性,能够快速的解析收到用户发送的微信消息,放弃JAVA反射功能直接编码生成VO对象更加快速;
-
->**c.敏捷开发**:微信交互信息全都统一封装VO对象,所有VO的属性都是微信公众平台API原生状态。开发者无须再关心它来源是XML还JSON格式,其中消息的收发只需掌握2个VO(ReceiveMsg,OutPutMsg)即可;
-
->**d.支持力度**:API功能分为三个部分(后续会不断更新升级),微信基本消息的交互,高级接口(Token,自定义菜单,模板消息,群发消息等等)及开放平台功能接口的调用。
-
-
-##### 2.1结构设计
-!["MPSDK4J设计图"](http://j2ee.u.qiniudn.com/mpsdk4j-class-design.png-alias "MPSDK4J设计图")
-
-
-##### 2.2交互时序
-!["MPSDK4J交互时序图"](http://j2ee.u.qiniudn.com/mpsdk4j-sequence.png-alias "MPSDK4J交互时序图")
-
-
-#### 3.项目
-
-
-##### 3.1最新源码
-* OSChina项目主页:
-* 开源协议:[Apache Licenses 2.0](http://www.apache.org/licenses/LICENSE-2.0)
-
-
-##### 3.2Maven库引用
-另外你也可以通过OSChina的Maven库获取依赖
-
-* 1.加入OSC仓库,也可参考官方说明[OSChina Maven Help](http://maven.oschina.net/help.html)
-```xml
-
-
- nexus
- http://maven.oschina.net/content/groups/public/
-
- true
-
-
- false
-
-
-
- nexus-third
- http://maven.oschina.net/content/repositories/thirdparty/
-
- true
-
-
- true
-
-
-
-```
-
-* 2.添加依赖坐标
-```xml
-
- org.elkan1788.osc
- mpsdk4j
- 1.a.19
-
-```
-
-或者自己编译jar包。
-```
-mvn clean package
-```
-
-
-#### 4.示例代码
-MPSDK4J在Web环境中暂时提供了以下三种支持,欢迎提交其它环境扩展。在实际的使用过程中只需要继承相应环境的Wx***Support父类,重写init初始化方法修改其中的公众号信息及微信消息处理器,添加环境的入口(Servlet环境无需此步骤),调用wxInteract方法,最后发布上线即可。
-
-##### 4.1.HttpServlet环境:
-```java
-@WebServlet(name = "weixinServlet", urlPatterns = "/weixin/mp/core.ser")
-public class WeiXinServlet extends WxServletSupport {
-
- @Override
- public void init() throws ServletException {
- super.init();
- MPAct mpAct = new MPAct();
- // 修改为实际的公众号信息,可以在开发者栏目中查看
- mpAct.setAppId("wx****");
- mpAct.setAppSecert("***");
- mpAct.setToken("***");
- mpAct.setAESKey("******");
- this.setMpAct(mpAct);
- // 可实现自己的WxHandler
- this.setWxHandler(new WxDefaultHandler());
- }
-}
-```
-
-##### 4.2.SpringMVC环境:
-
-```java
-@Controller
-@RequestMapping("/weixin/mp")
-public class WeiXinController extends WxSpringSupport {
-
- @Override
- protected void init() {
- MPAct mpAct = new MPAct();
- // 修改为实际的公众号信息,可以在开发者栏目中查看
- mpAct.setAppId("wx****");
- mpAct.setAppSecert("***");
- mpAct.setToken("***");
- mpAct.setAESKey("******");
- this.setMpAct(mpAct);
- // 可实现自己的WxHandler
- this.setWxHandler(new WxDefaultHandler());
- }
-
- @RequestMapping(value = "/core",produces = {"text/plain;charset=UTF-8"})
- @ResponseBody
- public String wxCore(HttpServletRequest req) {
- String reply = "";
- try {
- reply = wxInteract(req);
- } catch (IOException e) {
- log.error(e.getLocalizedMessage(), e);
- }
- return reply;
- }
-}
-```
-
-
-##### 4.3.Struts2环境:
-```java
-public class WeiXinAction extends WxStruts2Support {
-
- @Override
- protected void init() {
- super.init();
- MPAct mpAct = new MPAct();
- // 修改为实际的公众号信息,可以在开发者栏目中查看
- mpAct.setAppId("wx****");
- mpAct.setAppSecert("***");
- mpAct.setToken("***");
- mpAct.setAESKey("******");
- this.setMpAct(mpAct);
- // 可实现自己的WxHandler
- this.setWxHandler(new WxDefaultHandler());
- }
-
- public void wxCore() throws IOException {
- wxInteract();
- }
-}
-```
-
-
-##### 5.Issue
-BUG提交:
-
-
-##### 6.联系
-特别希望看到该项目对您哪怕一点点的帮助。你有任何的想法和建议,除以上Issue提交外,也随时欢迎与我沟通,联系方式:
-
-* Email: elkan1788@gmail.com
-* QQ: 2292706174
-* 微信:
-
-
-##### 7.其它
-目前正在尝试微信开放平台探究,已初步实现授权管理功能,后续会不断完善成一个管理平台,期待你的加入。
-
-!["MPSDK4J公众号开发服务"](http://j2ee.u.qiniudn.com/weixn-open-demo.png-alias "MPSDK4J公众号开发服务")
\ No newline at end of file
+# MPSDK4J v2
+[![Build Status](https://travis-ci.org/elkan1788/mpsdk4j.svg?branch=master)](https://travis-ci.org/elkan1788/mpsdk4j)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.elkan1788/mpsdk4j/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.github.elkan1788/mpsdk4j)
+[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+
+!["MPSDK4J"](http://j2ee.u.qiniudn.com/mpsdk4j-logo.png-aliassmall "MPSDK4J")
+
+## 目录
+* [1.引言](#引言)
+* [2.介绍](#介绍)
+ * [2.1.结构设计](#结构设计)
+ * [2.2.交互时序](#时序图)
+ * [2.3.测试覆盖](#测试覆盖)
+* [3.项目](#项目)
+ * [3.1.最新源码](#最新源码)
+ * [3.2.Maven库引用](#Maven库引用)
+* [4.示例代码](#示例代码)
+ * [4.1.HttpServlet环境](#HttpServlet环境)
+ * [4.2.SpringMVC环境](#SpringMVC环境)
+ * [4.3.Nutz环境](#Nutz环境)
+ * [4.4.示例代码](#示例)
+* [5.Issue](#Issue)
+* [6.联系](#联系)
+* [7.其它](#其它)
+
+
+## 1.引言
+
+"十一"黄金周假期已悄然逝去,_MPSDK4J_在不知不觉中也经历过一个年头啦,非常感谢这段时间里网友们的支持.有了小伙伴们的支持_MPSDK4J_成长更加的迅速,当前版本也确实存在问题诸多的问题.如: 交互中单,多例问题,多公众号混淆问题,微信公众号API更新等等问题.所以趁最近空闲时间把_MPSDK4J_重构,需要注意**此次升级是全新的改造不往下兼容**.新版本的_MPSDK4J_结构上更加清晰,使用同样的简单,依然不忘追求速度与简单的初心.
+
+
+## 2.介绍
+
+_MPSDK4J_,非常直观的阐述了此项目的意义所在.没错,它就是JAVA语言环境下的微信公众平台开发SDK.其中MP代表的是微信公众平台的域名前缀,SDK表示开发工具包,4同音英文"for",J代表了JAVA.虽然现网络上已经有不少JAVA版本的SDK现身,但是[_MPSDK4J_]的出现也并非只是造轮子的重复工作.它遵循单一设计模式规则,所有的设计与功能都是源于微信公众平台API,一切都是为了追求简单与速度.
+
+>**a.设计简单**:整体设计非常的简单,仅有9个大包11个接口,3个枚举,55类,1个配置文件(其中API交互实体对象占据一半之多),核心功能部分就4类(WechatKeneral,MessageHandler,WechatHandler,WechatAPI);
+
+>**b.解析速度**:基本SAX驱动式XML处理,能够快速的解析收到用户发送的微信消息,放弃JAVA反射功能,采用直接编码生成VO对象,加快解释速度;
+
+>**c.敏捷开发**:微信交互信息全都统一封装VO对象,所有VO的属性都是微信公众平台API原生状态.但开发者无须再关心它来源是XML还JSON格式,只需掌握其中消息的收发对应VO对象即可;
+
+>**d.支持力度**:API功能分类与微信公众平台保持一致,分类信息详见下表(后续会不断更新升级),微信基本消息的交互,高级接口(Token,自定义菜单,模板消息,群发消息等等).
+
+| API名称 | 描述 |
+| ------ | ------ |
+| CredentialAPI | 微信服务器IP列表,access_token,jssdk_ticket,短链接生成 |
+| GroupsAPI | 用户分组接口: 创建,查询,移动用户等 |
+| MediaAPI | 多媒体文件接口: 上传多媒体素材(临时/永久),下载,删除 |
+| MenuAPI | 自定义菜单接口: 查询,创建,删除 |
+| MessageAPI | 高级消息接口: 发送模板消息,客服消息,群发消息 |
+| QRCodeAPI | 二维码接口: 创建,获取 |
+| UserAPI | 用户管理接口: 用户信息,订阅列表等 |
+| WechatAPIImpl | 上述接口统一实现 |
+
+
+### 2.1.整体结构设计
+!["MPSDK4J-V2"](http://j2ee.u.qiniudn.com/mpsdk4j-2.png-alias "MPSDK4J-V2")
+
+
+### 2.2.交互时序图
+!["MPSDK4J-seq"](http://j2ee.u.qiniudn.com/mpsdk4j-v2-seq.png-alias "MPSDK4J-seq")
+
+
+### 2.3.测试覆盖
+!["MPSDK4J-test"](http://j2ee.u.qiniudn.com/mpsdk4j-v2-test-coverage.png-alias "MPSDK4J-test")
+
+
+## 3.项目
+
+
+### 3.1最新源码
+* OSChina项目主页:
+* Github项目主页:
+* 开源协议:[Apache Licenses 2.0](http://www.apache.org/licenses/LICENSE-2.0)
+
+
+### 3.2Maven库引用
+
+```xml
+
+
+ io.github.elkan1788
+ mpsdk4j
+ 2.b.1
+
+
+```
+
+或者自己编译jar包.
+
+```
+
+mvn clean package
+
+```
+
+
+## 4.示例代码
+
+_MPSDK4J_在`Web`环境中暂时提供了以下环境支持,欢迎提交其它环境扩展.在实际的使用过程中只需要继承相应环境的`WechatWebSupport`父类,重写`init`初始化方法修改其中的公众号信息及微信消息处理器(实现`WechatHandler`接口或是继承`WechatDefHandler`基类),添加环境的入口(`Servlet`环境无需此步骤),调用`interact`方法,最后发布上线即可.
+
+
+### 4.1.HttpServlet环境:
+
+```java
+
+@WebServlet(name = "wechatCoreServlet", urlPatterns = "/servlet/wechatcore.ser")
+public class WechatCoreServlet extends HttpServletSupport {
+
+ private static final long serialVersionUID = 4370883777170946295L;
+
+ private static final Logger log = LoggerFactory.getLogger(WechatCoreServlet.class);
+
+ private static final ConfigReader _cr = new ConfigReader("/mp.properties");
+
+ @Override
+ public void init() throws ServletException {
+ log.info("====== Servlet环境 =======");
+ MPAccount mpact = new MPAccount();
+ // 修改为实际的公众号信息,可以在开发者栏目中查看
+ mpAct.setAppId("wx****");
+ mpAct.setAppSecert("***");
+ mpAct.setToken("***");
+ mpAct.setAESKey("******");
+ _wk.setMpAct(mpact);
+ _wk.setWechatHandler(new WechatDefHandler());
+ }
+
+}
+
+```
+
+
+### 4.2.SpringMVC环境:
+
+```java
+
+/**
+ * SpringMVC环境接入
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RequestMapping("/springmvc")
+@Controller
+public class WechatCoreController extends WechatWebSupport {
+
+ private static final Logger log = LoggerFactory.getLogger(WechatCoreController.class);
+
+ private static final ConfigReader _cr = new ConfigReader("/mp.properties");
+
+ @Override
+ public void init() {
+ log.info("====== SpringMVC环境 =======");
+ MPAccount mpact = new MPAccount();
+ // 修改为实际的公众号信息,可以在开发者栏目中查看
+ mpAct.setAppId("wx****");
+ mpAct.setAppSecert("***");
+ mpAct.setToken("***");
+ mpAct.setAESKey("******");
+ _wk.setMpAct(mpact);
+ _wk.setWechatHandler(new WechatDefHandler());
+ }
+
+ @RequestMapping("/wechatcore")
+ public void wechatCore(HttpServletRequest req, HttpServletResponse resp) throws Exception {
+ this.interact(req, resp);
+ }
+
+}
+
+```
+
+
+### 4.3.Nutz环境:
+
+```java
+
+/**
+ * Nutz环境接入
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@At("/nutz")
+@IocBean
+public class WechatCoreModule extends WechatWebSupport {
+
+ private static final Log log = Logs.get();
+
+ private static final ConfigReader _cr = new ConfigReader("/mp.properties");
+
+ @Override
+ public void init() {
+ log.info("====== Nutz环境 =======");
+ // 修改为实际的公众号信息,可以在开发者栏目中查看
+ mpAct.setAppId("wx****");
+ mpAct.setAppSecert("***");
+ mpAct.setToken("***");
+ mpAct.setAESKey("******");
+ _wk.setMpAct(mpact);
+ _wk.setWechatHandler(new WechatDefHandler());
+ }
+
+ @At("/wechatcore")
+ public void wechatCore(HttpServletRequest req, HttpServletResponse resp) {
+ try {
+ this.interact(req, resp);
+ }
+ catch (IOException e) {
+ throw Lang.wrapThrow(e);
+ }
+ }
+}
+
+```
+
+
+### 4.4.示例项目源码
+
+* OSChina仓库:
+
+
+## 5.Issue
+BUG提交:
+
+
+## 6.联系
+特别希望看到该项目对您哪怕一点点的帮助。你有任何的想法和建议,除以上Issue提交外,也随时欢迎与我沟通,联系方式:
+
+* Email: elkan1788@gmail.com
+* QQ群:486192816
+
+!["MPSDK4J-qq"](http://j2ee.u.qiniudn.com/MPSDK4J-qq.png-noalias "MPSDK4J-qq")
+
+
+## 7.其它: JCE 使用说明
+
+| 文件名称 | JDK版本 |
+| ------ | ------ |
+| jce_policy-6.zip | 1.6 |
+| UnlimitedJCEPolicyJDK7.zip | 1.7 |
+| jce_policy-8.zip | 1.8 |
+
+选择相应的`J2EE`版本下载后解压,可以看到`local_policy.jar`和`US_export_policy.jar`以及`readme.txt`
+* 如果安装了`JRE`,将两个`jar`文件放到`%JRE_HOME%\lib\security`目录下覆盖原来的文件;
+* 如果安装了`JDK`,将两个`jar`文件放到`%JDK_HOME%\jre\lib\security`目录下覆盖原来文件.
\ No newline at end of file
diff --git a/jce-patch/UnlimitedJCEPolicyJDK7.zip b/jce-patch/UnlimitedJCEPolicyJDK7.zip
new file mode 100644
index 0000000..0a6890c
Binary files /dev/null and b/jce-patch/UnlimitedJCEPolicyJDK7.zip differ
diff --git a/jce-patch/jce_policy-6.zip b/jce-patch/jce_policy-6.zip
new file mode 100644
index 0000000..1e59079
Binary files /dev/null and b/jce-patch/jce_policy-6.zip differ
diff --git a/jce-patch/jce_policy-8.zip b/jce-patch/jce_policy-8.zip
new file mode 100644
index 0000000..63cd0cd
Binary files /dev/null and b/jce-patch/jce_policy-8.zip differ
diff --git a/pom.xml b/pom.xml
index e3e62b9..9bb25a9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,183 +1,216 @@
-
- 4.0.0
+
+ 4.0.0
- org.elkan1788.osc
- mpsdk4j
- 1.a.24-SNAPSHOTS
- jar
- 微信公众平台JAVA开发SDK
-
- 腾讯微信公众平台开发者服务,Java平台开发下的SDK包
-
+ io.github.elkan1788
+ mpsdk4j
+ 2.b.1
+ jar
-
-
- 0
- 凡梦星尘
- elkan1788@gmail.com
- China
-
-
- Author
-
-
-
-
+ mpsdk4j
+
+ A simple SDK for wechat api develop in Java program.
+
+
+ http://elkan1788.github.io/mpskd4j
+
+ Github Issue
+ https://github.com/elkan1788/mpsdk4j/issues
+
+
+
+ The Apache Software License, Version 2.0
+ http://apache.org/licenses/LICENSE-2.0.txt
+
+
-
- UTF-8
-
+
+
+ 1
+ 凡梦星尘
+ elkan1788@gmail.com
+ CHINA
+
+
+ Author
+
+
+ Committer
+
+
+
+
+ 2
+ 黑色幽默
+ 1315055798@qq.com
+ CHINA
+
+
+ Committer
+
+
+
+
+ 3
+ 高轩雾褪
+ 977903096@qq.com
+ CHINA
+
+
+ Committer
+
+
+
+
-
-
-
- junit
- junit
- 4.11
- test
-
+
+ UTF-8
+
-
-
- log4j
- log4j
- 1.2.17
-
-
- org.slf4j
- slf4j-api
- 1.7.7
-
-
- org.slf4j
- log4j-over-slf4j
- 1.7.7
-
-
- org.slf4j
- slf4j-log4j12
- 1.7.7
-
+
-
-
- commons-codec
- commons-codec
- 1.9
-
-
- commons-logging
- commons-logging
- 1.1.3
-
-
- commons-collections
- commons-collections
- 3.2.1
-
-
- commons-beanutils
- commons-beanutils
- 1.9.2
-
+
+
+ junit
+ junit
+ 4.12
+ test
+
-
-
- org.apache.httpcomponents
- httpcore
- 4.3.3
-
-
- org.apache.httpcomponents
- httpclient
- 4.3.5
-
-
- org.apache.httpcomponents
- fluent-hc
- 4.3.6
-
-
- org.apache.httpcomponents
- httpmime
- 4.3.5
-
+
+
+ org.jmockit
+ jmockit
+ 1.19
+ test
+
-
-
- com.alibaba
- fastjson
- 1.2.0
-
+
+
+ log4j
+ log4j
+ 1.2.17
+ test
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.7
+ test
+
+
+ org.slf4j
+ log4j-over-slf4j
+ 1.7.7
+ test
+
+
+ org.slf4j
+ slf4j-log4j12
+ 1.7.7
+ test
+
-
-
- javax.servlet
- servlet-api
- 2.5
- provided
-
+
+
+ org.nutz
+ nutz
+ 1.b.52
+
-
- org.apache.struts
- struts2-core
- 2.3.20
- compile
-
+
+
+ javax.servlet
+ servlet-api
+ 2.5
+ provided
+ true
+
-
+
-
- mpsdk4j-${project.version}
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.1
-
-
- 1.7
- ${project.build.sourceEncoding}
-
-
-
- org.apache.maven.plugins
- maven-resources-plugin
- 2.7
-
- ${project.build.sourceEncoding}
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.5
-
-
- *.properties
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 2.4
-
- true
-
-
-
- compile
-
- jar
-
-
-
-
-
-
+
+ mpsdk4j-${project.version}
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+
+ 1.6
+ ${project.build.sourceEncoding}
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.10.3
+
+ ${project.build.sourceEncoding}
+ ${project.build.sourceEncoding}
+ ${project.build.sourceEncoding}
+
+
+
+ package
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 2.6
+
+ ${project.build.sourceEncoding}
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.4
+
+ true
+
+
+
+ compile
+
+ jar
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.7.5.201505241946
+
+
+ prepare-unit-tests
+
+ prepare-agent
+
+
+
+ report
+ test
+
+ report
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/qq/weixin/mp/aes/SHA1.java b/src/main/java/com/qq/weixin/mp/aes/SHA1.java
deleted file mode 100644
index b051969..0000000
--- a/src/main/java/com/qq/weixin/mp/aes/SHA1.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.qq.weixin.mp.aes;
-
-import java.security.MessageDigest;
-import java.util.Arrays;
-import java.util.Formatter;
-
-/**
- * SHA1算法计算公众平台的消息签名接口
- *
- * @author Tencent
- * @since 2014/11/4
- */
-public class SHA1 {
-
- /**
- * 用SHA1算法生成安全签名
- *
- * @param params [token, timestamp, nonce, encrypt]
- * @return 安全签名
- * @throws com.qq.weixin.mp.aes.AesException
- */
- public static String calculate(String... params) throws AesException {
- try {
- String[] array = params;
- StringBuffer sb = new StringBuffer();
- // 字符串排序
- Arrays.sort(array);
- int len = params.length;
- for (int i = 0; i < len; i++) {
- sb.append(array[i]);
- }
-
- // SHA1签名生成
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- md.reset();
- md.update(new String(sb).getBytes("UTF-8"));
-
- // HEX输出
- byte[] hash = md.digest();
- Formatter formatter = new Formatter();
- for (byte b : hash) {
- formatter.format("%02x", b);
- }
- String hex = formatter.toString();
- formatter.close();
- return hex;
- } catch (Exception e) {
- throw new AesException(AesException.ComputeSignatureError);
- }
- }
-}
diff --git a/src/main/java/com/qq/weixin/mp/aes/WXBizMsgCrypt.java b/src/main/java/com/qq/weixin/mp/aes/WXBizMsgCrypt.java
deleted file mode 100644
index 4f9b28e..0000000
--- a/src/main/java/com/qq/weixin/mp/aes/WXBizMsgCrypt.java
+++ /dev/null
@@ -1,284 +0,0 @@
-package com.qq.weixin.mp.aes;
-
-import org.apache.commons.codec.binary.Base64;
-import org.elkan1788.osc.weixin.mp.util.XmlMsgBuilder;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.Random;
-
-/**
- * 提供接收和推送给公众平台消息的加解密接口(UTF8编码的字符串).
- *
- * - 第三方回复加密消息给公众平台
- * - 第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。
- *
- * 说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案
- *
- * - 在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:
- * http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
- * - 下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt
- * - 如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件
- * - 如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件
- *
- */
-public class WXBizMsgCrypt {
-
- private static Charset CHARSET = Charset.forName("utf-8");
- private Base64 base64 = new Base64();
- private byte[] aesKey;
- private String token;
- private String appId;
- private String fromAppId;
-
- /**
- * 构造函数
- * @param token 公众平台上,开发者设置的token
- * @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey
- * @param appId 公众平台appid
- *
- * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
- */
- public WXBizMsgCrypt(String token, String encodingAesKey, String appId) throws AesException {
- if (encodingAesKey.length() != 43) {
- throw new AesException(AesException.IllegalAesKey);
- }
-
- this.token = token;
- this.appId = appId;
- aesKey = Base64.decodeBase64(encodingAesKey + "=");
- }
-
- // 生成4个字节的网络字节序
- private byte[] getNetworkBytesOrder(int sourceNumber) {
- byte[] orderBytes = new byte[4];
- orderBytes[3] = (byte) (sourceNumber & 0xFF);
- orderBytes[2] = (byte) (sourceNumber >> 8 & 0xFF);
- orderBytes[1] = (byte) (sourceNumber >> 16 & 0xFF);
- orderBytes[0] = (byte) (sourceNumber >> 24 & 0xFF);
- return orderBytes;
- }
-
- // 还原4个字节的网络字节序
- private int recoverNetworkBytesOrder(byte[] orderBytes) {
- int sourceNumber = 0;
- for (int i = 0; i < 4; i++) {
- sourceNumber <<= 8;
- sourceNumber |= orderBytes[i] & 0xff;
- }
- return sourceNumber;
- }
-
- // 随机生成16位字符串
- private String getRandomStr() {
- StringBuffer sb = new StringBuffer();
- Random ran = new Random();
- for(int i=0; i<16; i++) {
- boolean flag = ran.nextInt(2) % 2 == 0;
- if(flag) {
- char c = (char) (int) (Math.random() * 26 + 97);
- sb.append(c);
- } else {
- sb.append(ran.nextInt(10));
- }
- }
- return sb.toString();
- }
-
- /**
- * 对明文进行加密.
- *
- * @param text 需要加密的明文
- * @return 加密后base64编码的字符串
- * @throws AesException aes加密失败
- */
- private String encrypt(String randomStr, String text) throws AesException {
- ByteGroup byteCollector = new ByteGroup();
- byte[] randomStrBytes = randomStr.getBytes(CHARSET);
- byte[] textBytes = text.getBytes(CHARSET);
- byte[] networkBytesOrder = getNetworkBytesOrder(textBytes.length);
- byte[] appidBytes = appId.getBytes(CHARSET);
-
- // randomStr + networkBytesOrder + text + appid
- byteCollector.addBytes(randomStrBytes);
- byteCollector.addBytes(networkBytesOrder);
- byteCollector.addBytes(textBytes);
- byteCollector.addBytes(appidBytes);
-
- // ... + pad: 使用自定义的填充方式对明文进行补位填充
- byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());
- byteCollector.addBytes(padBytes);
-
- // 获得最终的字节流, 未加密
- byte[] unencrypted = byteCollector.toBytes();
-
- try {
- // 设置加密模式为AES的CBC模式
- Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
- SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
- IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
- cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
-
- // 加密
- byte[] encrypted = cipher.doFinal(unencrypted);
-
- // 使用BASE64对加密后的字符串进行编码
- String base64Encrypted = base64.encodeToString(encrypted);
-
- return base64Encrypted;
- } catch (Exception e) {
- throw new AesException(AesException.EncryptAESError);
- }
- }
-
- /**
- * 对密文进行解密.
- *
- * @param text 需要解密的密文
- * @return 解密得到的明文
- * @throws AesException aes解密失败
- */
- private String decrypt(String text) throws AesException {
- byte[] original;
- try {
- // 设置解密模式为AES的CBC模式
- Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
- SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
- IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
- cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
-
- // 使用BASE64对密文进行解码
- byte[] encrypted = Base64.decodeBase64(text);
-
- // 解密
- original = cipher.doFinal(encrypted);
- } catch (Exception e) {
- throw new AesException(AesException.DecryptAESError);
- }
-
- String xmlContent;
- try {
- // 去除补位字符
- byte[] bytes = PKCS7Encoder.decode(original);
-
- // 分离16位随机字符串,网络字节序和AppId
- byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
-
- int xmlLength = recoverNetworkBytesOrder(networkOrder);
-
- xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
- fromAppId = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),
- CHARSET);
- } catch (Exception e) {
- throw new AesException(AesException.IllegalBuffer);
- }
-
- // appid不相同的情况
- if (!fromAppId.equals(appId)) {
- throw new AesException(AesException.ValidateAppidError);
- }
- return xmlContent;
-
- }
-
- /**
- * 将公众平台回复用户的消息加密打包.
- *
- * - 对要发送的消息进行AES-CBC加密
- * - 生成安全签名
- * - 将消息密文和安全签名打包成xml格式
- *
- *
- * @param replyMsg 公众平台待回复用户的消息,xml格式的字符串
- * @param timeStamp 时间戳,可以自己生成,也可以用URL参数的timestamp
- * @param nonce 随机串,可以自己生成,也可以用URL参数的nonce
- *
- * @return 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串
- * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
- */
- public String encryptMsg(String replyMsg, String timeStamp, String nonce) throws AesException {
- // 加密
- String encrypt = encrypt(getRandomStr(), replyMsg);
-
- // 生成安全签名
- if ("".equals(timeStamp)) {
- timeStamp = Long.toString(System.currentTimeMillis());
- }
-
- String signature = SHA1.calculate(token, timeStamp, nonce, encrypt);
-
- // 生成发送的xml
- String result = XmlMsgBuilder.create().encrypt(encrypt, signature, timeStamp, nonce);
- return result;
- }
-
- /**
- * 检验消息的真实性,并且获取解密后的明文.
- *
- * - 利用收到的密文生成安全签名,进行签名验证
- * - 若验证通过,则提取xml中的加密消息
- * - 对消息进行解密
- *
- *
- * @param msgSignature 签名串,对应URL参数的msg_signature
- * @param timeStamp 时间戳,对应URL参数的timestamp
- * @param nonce 随机串,对应URL参数的nonce
- * @param postData 密文,对应POST请求的数据
- *
- * @return 解密后的原文
- * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
- */
- public String decryptMsg(String msgSignature, String timeStamp, String nonce, String postData)
- throws AesException {
-
- // 密钥,公众账号的app secret
- // 提取密文
- Object[] encrypt = XMLParse.extract(postData);
-
- // 验证安全签名
- String signature = SHA1.calculate(token, timeStamp, nonce, encrypt[1].toString());
-
- // 和URL中的签名比较是否相等
- if (!signature.equals(msgSignature)) {
- throw new AesException(AesException.ValidateSignatureError);
- }
-
- // 解密
- String result = decrypt(encrypt[1].toString());
- return result;
- }
-
- /**
- * 验证URL
- * @param msgSignature 签名串,对应URL参数的msg_signature
- * @param timeStamp 时间戳,对应URL参数的timestamp
- * @param nonce 随机串,对应URL参数的nonce
- * @param echoStr 随机串,对应URL参数的echostr
- *
- * @return 解密之后的echostr
- * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
- */
- public String verifyUrl(String msgSignature, String timeStamp, String nonce, String echoStr)
- throws AesException {
- String signature = SHA1.calculate(token, timeStamp, nonce, echoStr);
-
- if (!signature.equals(msgSignature)) {
- throw new AesException(AesException.ValidateSignatureError);
- }
-
- String result = decrypt(echoStr);
- return result;
- }
-
- /**
- * 获取加密消息中的APPID[为订阅号提供]
- *
- * @return APPID
- */
- public String getFromAppid() {
- return this.fromAppId;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/qq/weixin/mp/aes/package-info.java b/src/main/java/com/qq/weixin/mp/aes/package-info.java
deleted file mode 100644
index daaec1d..0000000
--- a/src/main/java/com/qq/weixin/mp/aes/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 微信消息AES加密工具
- */
-package com.qq.weixin.mp.aes;
\ No newline at end of file
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/MPSDK4J.java b/src/main/java/io/github/elkan1788/mpsdk4j/Mpsdk4j.java
similarity index 51%
rename from src/main/java/org/elkan1788/osc/weixin/mp/MPSDK4J.java
rename to src/main/java/io/github/elkan1788/mpsdk4j/Mpsdk4j.java
index e7ea7e3..d62a87f 100644
--- a/src/main/java/org/elkan1788/osc/weixin/mp/MPSDK4J.java
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/Mpsdk4j.java
@@ -1,12 +1,15 @@
-package org.elkan1788.osc.weixin.mp;
+package io.github.elkan1788.mpsdk4j;
/**
- * 微信公众平台JAVA SDK版本号声明
- *
+ * 项目版本号声明
+ *
+ *
+ * (参考:http://nutzam.com/core/committer/version_naming.html)
+ *
* @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/6
+ * @since 2.0
*/
-public class MPSDK4J {
+public final class Mpsdk4j {
/**
* 获取 mpsdk4j 的版本号,版本号的命名规范
@@ -21,16 +24,16 @@ public static String version() {
return String.format("%d.%s.%d", majorVersion(), releaseLevel(), minorVersion());
}
- public static int majorVersion() {
- return 1;
+ private static int majorVersion() {
+ return 2;
}
- public static int minorVersion() {
- return 24;
+ private static int minorVersion() {
+ return 1;
}
- public static String releaseLevel() {
- //a: 内部测试品质, b: 公测品质, r: 最终发布版
- return "a";
+ private static String releaseLevel() {
+ // a: 内部测试品质, b: 公测品质, r: 最终发布版
+ return "b";
}
}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/api/CredentialAPI.java b/src/main/java/io/github/elkan1788/mpsdk4j/api/CredentialAPI.java
new file mode 100644
index 0000000..fc6a9b9
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/api/CredentialAPI.java
@@ -0,0 +1,61 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import java.util.List;
+
+/**
+ * 微信凭据授权接口
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public interface CredentialAPI {
+
+ /**
+ * 获取access_token地址
+ */
+ static String get_at = "/token?grant_type=client_credential&appid=%s&secret=%s";
+ /**
+ * 获取微信服务器IP地址
+ */
+ static String cb_ips = "/getcallbackip?access_token=";
+
+ /**
+ * 长链接转短链接地址
+ */
+ static String short_url = "/shorturl?access_token=";
+
+ /**
+ * JSSDK临时凭证地址
+ */
+ static String js_ticket = "/ticket/getticket?type=jsapi&access_token=";
+
+ /**
+ * 获取微信服务凭证
+ *
+ * @return 凭证
+ */
+ String getAccessToken();
+
+ /**
+ * 获取微信服务器IP地址
+ *
+ * @return IP地址
+ */
+ List getServerIps();
+
+ /**
+ * 长链接转短链接
+ *
+ * @param longUrl
+ * 需要转换的长链接,支持http://,https://,weixin://wxpay 格式的url
+ * @return 短链接
+ */
+ String getShortUrl(String longUrl);
+
+ /**
+ * 获取JSSDK凭证
+ *
+ * @return 凭证
+ */
+ String getJSTicket();
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/api/GroupsAPI.java b/src/main/java/io/github/elkan1788/mpsdk4j/api/GroupsAPI.java
new file mode 100644
index 0000000..43d69c1
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/api/GroupsAPI.java
@@ -0,0 +1,120 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import java.util.Collection;
+import java.util.List;
+
+import io.github.elkan1788.mpsdk4j.vo.api.Groups;
+
+/**
+ * 微信用户组管理接口
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public interface GroupsAPI {
+
+ /**
+ * 创建分组地址
+ */
+ static String create_groups = "/groups/create?access_token=";
+
+ /**
+ * 查询所有分组地址
+ */
+ static String get_groups = "/groups/get?access_token=";
+
+ /**
+ * 查询用户所在分组地址
+ */
+ static String get_member_group = "/groups/getid?access_token=";
+
+ /**
+ * 修改分组名称地址
+ */
+ static String update_group = "/groups/update?access_token=";
+
+ /**
+ * 移动用户分组地址
+ */
+ static String update_member_group = "/groups/members/update?access_token=";
+
+ /**
+ * 批量移动用户分组地址
+ */
+ static String update_members_group = "/groups/members/batchupdate?access_token=";
+
+ /**
+ * 删除分组地址
+ */
+ static String delete_groups = "/groups/delete?access_token=";
+
+ /**
+ * 创建用户分组
+ *
+ *
+ * 一个公众账号,最多支持创建100个分组
+ *
+ * @param name
+ * 分组名字(30个字符以内)
+ * @return 分组Id
+ */
+ int createGroup(String name);
+
+ /**
+ * 查询所有分组
+ *
+ * @return 分组集合{@link Groups}
+ */
+ List getGroups();
+
+ /**
+ * 查询用户所在分组
+ *
+ * @param openId
+ * 用户openId
+ * @return 分组Id
+ */
+ int getGroup(String openId);
+
+ /**
+ * 修改分组名称
+ *
+ * @param id
+ * 分组Id
+ * @param name
+ * 新的分组名称
+ * @return true 或 false
+ */
+ boolean renGroups(int id, String name);
+
+ /**
+ * 移动用户所在分组
+ *
+ * @param openId
+ * 用户openId
+ * @param groupId
+ * 分组Id
+ * @return true 或 false
+ */
+ boolean move2Group(String openId, int groupId);
+
+ /**
+ * 批量移动用户分组
+ *
+ * @param openIds
+ * 用户openId集合
+ * @param groupId
+ * 分组Id
+ * @return true 或 false
+ */
+ boolean batchMove2Group(Collection openIds, int groupId);
+
+ /**
+ * 删除分组
+ *
+ * @param id
+ * 分组Id
+ * @return true 或 false
+ */
+ boolean delGroup(int id);
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/api/MediaAPI.java b/src/main/java/io/github/elkan1788/mpsdk4j/api/MediaAPI.java
new file mode 100644
index 0000000..0bd305b
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/api/MediaAPI.java
@@ -0,0 +1,54 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import java.io.File;
+
+import io.github.elkan1788.mpsdk4j.vo.api.Media;
+
+/**
+ * 微信多媒体数据接口
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public interface MediaAPI {
+
+ // 上传多媒体
+ static String upload_media = "/media/upload?access_token=%s&type=%s";
+
+ // 下载多媒体
+ static String get_media = "/media/get?access_token=%s&media_id=%s";
+
+ /**
+ * 上传多媒体文件
+ *
+ *
+ * 上传的临时多媒体文件有格式和大小限制,如下:
+ *
+ * 图片(image): 1M,支持JPG格式
+ *
+ * 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
+ *
+ * 视频(video):10MB,支持MP4格式
+ *
+ * 缩略图(thumb):64KB,支持JPG格式
+ *
+ *
+ * 媒体文件在后台保存时间为3天,即3天后media_id失效。
+ *
+ * @param type
+ * 多媒体类型 {@link io.github.elkan1788.mpsdk4j.common.MediaType}
+ * @param media
+ * 多媒体文件
+ * @return 实体{@link Media}
+ */
+ Media upMedia(String type, File media);
+
+ /**
+ * 下载多媒体文件
+ *
+ * @param mediaId
+ * 媒体文件ID
+ * @return {@link File}
+ */
+ File dlMedia(String mediaId);
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/api/MenuAPI.java b/src/main/java/io/github/elkan1788/mpsdk4j/api/MenuAPI.java
new file mode 100644
index 0000000..4a27c17
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/api/MenuAPI.java
@@ -0,0 +1,44 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import java.util.List;
+
+import io.github.elkan1788.mpsdk4j.vo.api.Menu;
+
+/**
+ * 微信自定义菜单接口
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public interface MenuAPI {
+
+ // 菜单查询地址
+ static String query_menu = "/menu/get?access_token=";
+ // 菜单创建地址
+ static String create_menu = "/menu/create?access_token=";
+ // 菜单删除地址
+ static String del_menu = "/menu/delete?access_token=";
+
+ /**
+ * 查询当前自定菜单
+ *
+ * @return 菜单项{@link io.github.elkan1788.mpsdk4j.vo.api.Menu}
+ */
+ List
+ * 较好的效果为大图360*200,小图200*200
+ */
+ private String picUrl;
+ /**
+ * 点击图文消息跳转链接
+ */
+ private String url;
- /**
- * 图文消息描述
- */
- private String description;
-
- /**
- * 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
- */
- private String picUrl;
-
- /**
- * 点击图文消息跳转链接
- */
- private String url;
-
- public Article() {
- }
+ public Article() {}
public Article(String title, String description, String picUrl, String url) {
+ super();
this.title = title;
this.description = description;
this.picUrl = picUrl;
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/BasicMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/BasicMsg.java
new file mode 100644
index 0000000..7924f21
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/BasicMsg.java
@@ -0,0 +1,109 @@
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.Map;
+
+import io.github.elkan1788.mpsdk4j.vo.event.BasicEvent;
+
+/**
+ * 消息基础类
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class BasicMsg {
+
+ /**
+ * 微信公众号Id/OpenId
+ */
+ protected String toUserName;
+ /**
+ * OpenId/微信公众号Id
+ */
+ protected String fromUserName;
+ /**
+ * 消息创建时间 (整型)
+ */
+ protected int createTime;
+ /**
+ * 消息类型: text, image, voice ...
+ */
+ protected String msgType;
+ /**
+ * 消息Id, 64位整型
+ */
+ protected long msgId;
+
+ /**
+ * 默认构造方法
+ */
+ public BasicMsg() {
+ this.createTime = Long.valueOf(System.currentTimeMillis() / 1000).intValue();
+ }
+
+ public BasicMsg(BasicMsg msg) {
+ this();
+ this.fromUserName = msg.getFromUserName();
+ this.toUserName = msg.getToUserName();
+ }
+
+ public BasicMsg(BasicEvent event) {
+ this();
+ this.fromUserName = event.getFromUserName();
+ this.toUserName = event.getToUserName();
+ }
+
+ /**
+ * 带XML解析值构造方法
+ *
+ * @param values
+ * XML值
+ */
+ public BasicMsg(Map values) {
+ this.fromUserName = values.get("fromUserName");
+ this.toUserName = values.get("toUserName");
+ this.createTime = Integer.parseInt(values.get("createTime"));
+ this.msgType = values.get("msgType");
+ this.msgId = Long.parseLong(values.get("msgId"));
+ }
+
+ public String getToUserName() {
+ return toUserName;
+ }
+
+ public void setToUserName(String toUserName) {
+ this.toUserName = toUserName;
+ }
+
+ public String getFromUserName() {
+ return fromUserName;
+ }
+
+ public void setFromUserName(String fromUserName) {
+ this.fromUserName = fromUserName;
+ }
+
+ public int getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(int createTime) {
+ this.createTime = createTime;
+ }
+
+ public String getMsgType() {
+ return msgType;
+ }
+
+ public void setMsgType(String msgType) {
+ this.msgType = msgType;
+ }
+
+ public long getMsgId() {
+ return msgId;
+ }
+
+ public void setMsgId(long msgId) {
+ this.msgId = msgId;
+ }
+
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/ImageMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/ImageMsg.java
new file mode 100644
index 0000000..09457fc
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/ImageMsg.java
@@ -0,0 +1,68 @@
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.Map;
+
+/**
+ * 图像消息
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class ImageMsg extends BasicMsg {
+
+ /**
+ * 图片链接
+ */
+ private String picUrl;
+ /**
+ * 图片消息媒体id,可以调用多媒体文件下载接口拉取数据
+ */
+ private String mediaId;
+
+ public ImageMsg() {
+ super();
+ this.msgType = "image";
+ }
+
+ public ImageMsg(Map values) {
+ super(values);
+ this.picUrl = values.get("picUrl");
+ this.mediaId = values.get("mediaId");
+ }
+
+ public String getPicUrl() {
+ return picUrl;
+ }
+
+ public void setPicUrl(String picUrl) {
+ this.picUrl = picUrl;
+ }
+
+ public String getMediaId() {
+ return mediaId;
+ }
+
+ public void setMediaId(String mediaId) {
+ this.mediaId = mediaId;
+ }
+
+ @Override
+ public String toString() {
+ return "ImageMsg [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", msgId="
+ + msgId
+ + ", picUrl="
+ + picUrl
+ + ", mediaId="
+ + mediaId
+ + "]";
+ }
+
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/LinkMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/LinkMsg.java
new file mode 100644
index 0000000..9d911cc
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/LinkMsg.java
@@ -0,0 +1,80 @@
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.Map;
+
+/**
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class LinkMsg extends BasicMsg {
+
+ /**
+ * 消息标题
+ */
+ private String title;
+ /**
+ * 消息描述
+ */
+ private String description;
+ /**
+ * 消息链接
+ */
+ private String url;
+
+ public LinkMsg() {
+ super();
+ this.msgType = "link";
+ }
+
+ public LinkMsg(Map values) {
+ super(values);
+ this.title = values.get("title");
+ this.description = values.get("description");
+ this.url = values.get("url");
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ @Override
+ public String toString() {
+ return "LinkMsg [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", msgId="
+ + msgId
+ + ", title="
+ + title
+ + ", description="
+ + description
+ + ", url="
+ + url
+ + "]";
+ }
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/LocationMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/LocationMsg.java
new file mode 100644
index 0000000..1158076
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/LocationMsg.java
@@ -0,0 +1,97 @@
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.Map;
+
+/**
+ * 地理位置消息
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class LocationMsg extends BasicMsg {
+
+ /**
+ * 地理位置维度
+ */
+ private String x;
+ /**
+ * 地理位置经度
+ */
+ private String y;
+ /**
+ * 地图缩放大小
+ */
+ private int scale;
+ /**
+ * 地理位置信息
+ */
+ private String label;
+
+ public LocationMsg() {
+ super();
+ this.msgType = "location";
+ }
+
+ public LocationMsg(Map values) {
+ super(values);
+ this.x = values.get("locationX");
+ this.y = values.get("locationY");
+ this.scale = Integer.parseInt(values.get("scale"));
+ this.label = values.get("label");
+ }
+
+ public String getX() {
+ return x;
+ }
+
+ public void setX(String x) {
+ this.x = x;
+ }
+
+ public String getY() {
+ return y;
+ }
+
+ public void setY(String y) {
+ this.y = y;
+ }
+
+ public int getScale() {
+ return scale;
+ }
+
+ public void setScale(int scale) {
+ this.scale = scale;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ @Override
+ public String toString() {
+ return "LocationMsg [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", msgId="
+ + msgId
+ + ", x="
+ + x
+ + ", y="
+ + y
+ + ", scale="
+ + scale
+ + ", label="
+ + label
+ + "]";
+ }
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/MusicMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/MusicMsg.java
new file mode 100644
index 0000000..8a29047
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/MusicMsg.java
@@ -0,0 +1,118 @@
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.Map;
+
+import io.github.elkan1788.mpsdk4j.vo.event.BasicEvent;
+
+/**
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class MusicMsg extends BasicMsg {
+
+ /**
+ * 音乐标题
+ */
+ private String title;
+ /**
+ * 音乐描述
+ */
+ private String description;
+ /**
+ * 音乐链接
+ */
+ private String musicUrl;
+ /**
+ * 高质音乐链接
+ */
+ private String HQMusicUrl;
+ /**
+ * 缩略图的媒体id,通过素材管理接口上传多媒体文件,得到的id
+ */
+ private String thumbMediaId;
+
+ public MusicMsg() {
+ super();
+ this.msgType = "music";
+ }
+
+ public MusicMsg(BasicEvent event) {
+ super(event);
+ this.msgType = "music";
+ }
+
+ public MusicMsg(BasicMsg msg) {
+ super(msg);
+ this.msgType = "music";
+ }
+
+ public MusicMsg(Map values) {
+ super(values);
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getMusicUrl() {
+ return musicUrl;
+ }
+
+ public void setMusicUrl(String musicUrl) {
+ this.musicUrl = musicUrl;
+ }
+
+ public String getHQMusicUrl() {
+ return HQMusicUrl;
+ }
+
+ public void setHQMusicUrl(String hQMusicUrl) {
+ HQMusicUrl = hQMusicUrl;
+ }
+
+ public String getThumbMediaId() {
+ return thumbMediaId;
+ }
+
+ public void setThumbMediaId(String thumbMediaId) {
+ this.thumbMediaId = thumbMediaId;
+ }
+
+ @Override
+ public String toString() {
+ return "MusicMsg [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", msgId="
+ + msgId
+ + ", title="
+ + title
+ + ", description="
+ + description
+ + ", musicUrl="
+ + musicUrl
+ + ", HQMusicUrl="
+ + HQMusicUrl
+ + ", thumbMediaId="
+ + thumbMediaId
+ + "]";
+ }
+
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/NewsMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/NewsMsg.java
new file mode 100644
index 0000000..ab5394a
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/NewsMsg.java
@@ -0,0 +1,84 @@
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.List;
+
+import org.nutz.lang.Lang;
+
+import io.github.elkan1788.mpsdk4j.vo.event.BasicEvent;
+
+/**
+ * 多图文消息
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class NewsMsg extends BasicMsg {
+
+ /**
+ * 图文消息个数,限制为10条以内
+ */
+ private int count;
+ /**
+ * 多条图文消息信息,默认第一个item为大图,
+ *
+ * 注意:如果图文数超过10,则将会无响应
+ */
+ private List articles;
+
+ public NewsMsg() {
+ super();
+ this.msgType = "news";
+ }
+
+ public NewsMsg(BasicEvent event) {
+ super(event);
+ this.msgType = "news";
+ }
+
+ public NewsMsg(BasicMsg msg) {
+ super(msg);
+ this.msgType = "news";
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ public List getArticles() {
+ if (!Lang.isEmpty(articles) && articles.size() > 10) {
+ this.articles = articles.subList(0, 10);
+ setCount(10);
+ }
+ else {
+ this.setCount(Lang.length(articles));
+ }
+ return articles;
+ }
+
+ public void setArticles(List articles) {
+ this.articles = articles;
+ }
+
+ @Override
+ public String toString() {
+ return "NewsMsg [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", msgId="
+ + msgId
+ + ", count="
+ + count
+ + ", articles="
+ + articles
+ + "]";
+ }
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/TextMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/TextMsg.java
new file mode 100644
index 0000000..a5d9c3b
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/TextMsg.java
@@ -0,0 +1,68 @@
+/**
+ * @author senhui.li
+ */
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.Map;
+
+import io.github.elkan1788.mpsdk4j.vo.event.BasicEvent;
+
+/**
+ * 文本消息
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class TextMsg extends BasicMsg {
+
+ /**
+ * 文本内容
+ */
+ private String content;
+
+ public TextMsg() {
+ super();
+ this.msgType = "text";
+ }
+
+ public TextMsg(BasicEvent event) {
+ super(event);
+ this.msgType = "text";
+ }
+
+ public TextMsg(BasicMsg msg) {
+ super(msg);
+ this.msgType = "text";
+ }
+
+ public TextMsg(Map values) {
+ super(values);
+ this.content = values.get("content");
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ @Override
+ public String toString() {
+ return "TextMsg [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", content="
+ + content
+ + ", msgId="
+ + msgId
+ + "]";
+ }
+
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/VideoMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/VideoMsg.java
new file mode 100644
index 0000000..aa3e0de
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/VideoMsg.java
@@ -0,0 +1,111 @@
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.Map;
+
+import io.github.elkan1788.mpsdk4j.vo.event.BasicEvent;
+
+/**
+ * 视频消息
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class VideoMsg extends BasicMsg {
+
+ /**
+ * 视频消息媒体id,可以调用多媒体文件下载接口拉取数据
+ */
+ private String mediaId;
+
+ /**
+ * 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据
+ */
+ private String thumbMediaId;
+
+ /**
+ * 视频消息的标题
+ */
+ private String title;
+
+ /**
+ * 视频消息的描述
+ */
+ private String description;
+
+ public VideoMsg() {
+ super();
+ this.msgType = "video";
+ }
+
+ public VideoMsg(BasicEvent event) {
+ super(event);
+ this.msgType = "video";
+ }
+
+ public VideoMsg(BasicMsg msg) {
+ super(msg);
+ this.msgType = "video";
+ }
+
+ public VideoMsg(Map values) {
+ super(values);
+ this.mediaId = values.get("mediaId");
+ this.thumbMediaId = values.get("thumbMediaId");
+ }
+
+ public String getMediaId() {
+ return mediaId;
+ }
+
+ public void setMediaId(String mediaId) {
+ this.mediaId = mediaId;
+ }
+
+ public String getThumbMediaId() {
+ return thumbMediaId;
+ }
+
+ public void setThumbMediaId(String thumbMediaId) {
+ this.thumbMediaId = thumbMediaId;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String toString() {
+ return "VideoMsg [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", msgId="
+ + msgId
+ + ", mediaId="
+ + mediaId
+ + ", thumbMediaId="
+ + thumbMediaId
+ + ", title="
+ + title
+ + ", description="
+ + description
+ + "]";
+ }
+
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/VoiceMsg.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/VoiceMsg.java
new file mode 100644
index 0000000..ecb15e4
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/VoiceMsg.java
@@ -0,0 +1,94 @@
+package io.github.elkan1788.mpsdk4j.vo.message;
+
+import java.util.Map;
+
+import io.github.elkan1788.mpsdk4j.vo.event.BasicEvent;
+
+/**
+ * 音频消息
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class VoiceMsg extends BasicMsg {
+
+ /**
+ * 语音消息媒体id,可以调用多媒体文件下载接口拉取数据
+ */
+ private String mediaId;
+ /**
+ * 语音格式,如amr,speex等
+ */
+ private String format;
+ /**
+ * 语音识别结果,UTF8编码
+ */
+ private String recognition;
+
+ public VoiceMsg() {
+ super();
+ this.msgType = "voice";
+ }
+
+ public VoiceMsg(BasicEvent event) {
+ super(event);
+ this.msgType = "voice";
+ }
+
+ public VoiceMsg(BasicMsg msg) {
+ super(msg);
+ this.msgType = "voice";
+ }
+
+ public VoiceMsg(Map values) {
+ super(values);
+ this.mediaId = values.get("mediaId");
+ this.format = values.get("format");
+ this.recognition = values.get("recognition");
+ }
+
+ public String getMediaId() {
+ return mediaId;
+ }
+
+ public void setMediaId(String mediaId) {
+ this.mediaId = mediaId;
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ public String getRecognition() {
+ return recognition;
+ }
+
+ public void setRecognition(String recognition) {
+ this.recognition = recognition;
+ }
+
+ @Override
+ public String toString() {
+ return "VoiceMsg [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", msgId="
+ + msgId
+ + ", mediaId="
+ + mediaId
+ + ", format="
+ + format
+ + ", recognition="
+ + recognition
+ + "]";
+ }
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/package-info.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/package-info.java
new file mode 100644
index 0000000..d917251
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/message/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * 普通消息实体类,如: 文本消息,图像消息,语音消息...
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+package io.github.elkan1788.mpsdk4j.vo.message;
\ No newline at end of file
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/package-info.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/package-info.java
new file mode 100644
index 0000000..a89be27
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * 微信公众平台API中对应所有实体类设计
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+package io.github.elkan1788.mpsdk4j.vo;
\ No newline at end of file
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/push/SentAllJobEvent.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/push/SentAllJobEvent.java
new file mode 100644
index 0000000..146b244
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/push/SentAllJobEvent.java
@@ -0,0 +1,139 @@
+package io.github.elkan1788.mpsdk4j.vo.push;
+
+import java.util.Map;
+
+/**
+ * 群发消息处理事件
+ *
+ * 微信发送消息状态(模板消息,群发消息)
+ *
+ *
+ * 群发的结构,为“send success”或“send fail”或“err(num)”。但send success时,
+ *
+ *
+ * 也有可能因用户拒收公众号的消息、系统错误等原因造成少量用户接收失败。err(num)是审核失败的具体原因,
+ *
+ *
+ * 可能的情况如下:
+ *
+ *
+ * err(10001), //涉嫌广告
+ *
+ *
+ * err(20001), //涉嫌政治
+ *
+ *
+ * err(20004), //涉嫌社会
+ *
+ *
+ * err(20002), //涉嫌色情
+ *
+ *
+ * err(20006), //涉嫌违法犯罪
+ *
+ *
+ * err(20008), //涉嫌欺诈
+ *
+ *
+ * err(20013), //涉嫌版权
+ *
+ *
+ * err(22000), //涉嫌互推(互相宣传)
+ *
+ *
+ * err(21000), //涉嫌其他
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class SentAllJobEvent extends SentTmlJobEvent {
+
+ /**
+ * group_id下粉丝数;或者openid_list中的粉丝数
+ */
+ private int totalCnt;
+ /**
+ * 过滤(过滤是指特定地区、性别的过滤、用户设置拒收的过滤,
+ * 用户接收已超4条的过滤)后,准备发送的粉丝数,原则上,
+ * FilterCount = SentCount + ErrorCount
+ */
+ private int filterCnt;
+ /**
+ * 发送成功的粉丝数
+ */
+ private int sentCnt;
+ /**
+ * 发送失败的粉丝数
+ */
+ private int errorCnt;
+
+ public SentAllJobEvent() {
+ super();
+ }
+
+ public SentAllJobEvent(Map values) {
+ super(values);
+ this.totalCnt = Integer.parseInt(values.get("totalCount"));
+ this.filterCnt = Integer.parseInt(values.get("filterCount"));
+ this.sentCnt = Integer.parseInt(values.get("sentCount"));
+ this.errorCnt = Integer.parseInt(values.get("errorCount"));
+ }
+
+ public int getTotalCnt() {
+ return totalCnt;
+ }
+
+ public void setTotalCnt(int totalCnt) {
+ this.totalCnt = totalCnt;
+ }
+
+ public int getFilterCnt() {
+ return filterCnt;
+ }
+
+ public void setFilterCnt(int filterCnt) {
+ this.filterCnt = filterCnt;
+ }
+
+ public int getSentCnt() {
+ return sentCnt;
+ }
+
+ public void setSentCnt(int sentCnt) {
+ this.sentCnt = sentCnt;
+ }
+
+ public int getErrorCnt() {
+ return errorCnt;
+ }
+
+ public void setErrorCnt(int errorCnt) {
+ this.errorCnt = errorCnt;
+ }
+
+ @ Override
+ public String toString() {
+ return "SenAllJobEvent [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", event="
+ + event
+ + ", eventKey="
+ + eventKey
+ + ", totalCnt="
+ + totalCnt
+ + ", filterCnt="
+ + filterCnt
+ + ", sentCnt="
+ + sentCnt
+ + ", errorCnt="
+ + errorCnt
+ + "]";
+ }
+
+}
diff --git a/src/main/java/io/github/elkan1788/mpsdk4j/vo/push/SentTmlJobEvent.java b/src/main/java/io/github/elkan1788/mpsdk4j/vo/push/SentTmlJobEvent.java
new file mode 100644
index 0000000..1704c4c
--- /dev/null
+++ b/src/main/java/io/github/elkan1788/mpsdk4j/vo/push/SentTmlJobEvent.java
@@ -0,0 +1,70 @@
+package io.github.elkan1788.mpsdk4j.vo.push;
+
+import java.util.Map;
+
+import io.github.elkan1788.mpsdk4j.vo.event.BasicEvent;
+
+/**
+ * 模板消息处理事件
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class SentTmlJobEvent extends BasicEvent {
+
+ /**
+ * 消息id
+ */
+ private String msgId;
+ /**
+ * 发送状态: success,failed:user block,failed: system failed
+ */
+ private String status;
+
+ public SentTmlJobEvent() {
+ super();
+ }
+
+ public SentTmlJobEvent(Map values) {
+ super(values);
+ this.msgId = values.get("msgId");
+ this.status = values.get("status");
+ }
+
+ public String getMsgId() {
+ return msgId;
+ }
+
+ public void setMsgId(String msgId) {
+ this.msgId = msgId;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ @ Override
+ public String toString() {
+ return "TemplateJobEvent [toUserName="
+ + toUserName
+ + ", fromUserName="
+ + fromUserName
+ + ", createTime="
+ + createTime
+ + ", msgType="
+ + msgType
+ + ", event="
+ + event
+ + ", eventKey="
+ + eventKey
+ + ", msgId="
+ + msgId
+ + ", status="
+ + status
+ + "]";
+ }
+}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/commons/WxApiUrl.java b/src/main/java/org/elkan1788/osc/weixin/mp/commons/WxApiUrl.java
deleted file mode 100644
index a777f60..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/commons/WxApiUrl.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.elkan1788.osc.weixin.mp.commons;
-
-/**
- * 微信所有的API地址
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @version 1.0.2
- * @since 2014/11/12
- */
-public interface WxApiUrl {
-
- /**
- * 微信API入口
- */
- public static final String WX_API = "https://api.weixin.qq.com/cgi-bin";
- /**
- * 微信开放平台入口
- */
- public static final String WX_OPEN_API = "https://open.weixin.qq.com";
- /**
- * 微信多媒体文件API入口
- */
- public static final String MEDIA_API = "http://file.api.weixin.qq.com/cgi-bin/media";
- /**
- * 令牌API入口
- */
- public static final String ACCESS_TOKEN_API = WX_API + "/token?grant_type=client_credential&appid=%1$s&secret=%2$s";
- /**
- * 获取微信服务器IP
- */
- public static final String IP_LIST_API = WX_API + "/getcallbackip?access_token=%1$s";
- /**
- * 自定义菜单API入口[create, get, delete]
- */
- public static final String CUSTOM_MENU_API = WX_API + "/menu/%1$s?access_token=%2$s";
- /**
- * 分组管理API入口[create, get, getid, update]
- */
- public static final String GROUPS_API = WX_API + "/groups/%1$s?access_token=%2$s";
- /**
- * 用户分组API入口
- */
- public static final String GROUPS_USER_API = WX_API + "/groups/members/update?access_token=%1$s";
- /**
- * 微信用户信息API入口
- */
- public static final String USER_INFO_API = WX_API + "/user/info?access_token=%1$s&openid=%2$s&lang=%3$s";
- /**
- * 公众号关注者API入口
- */
- public static final String FOLLOWS_USER_API = WX_API + "/user/get?access_token=%1$s&next_openid=%2$s";
- /**
- * 下载多媒体文件API入口
- */
- public static final String MEDIA_DL_API = MEDIA_API + "/get?access_token=%1$s&media_id=%2$s";
- /**
- * 上传多媒体文件API入口
- */
- public static final String MEDIA_UP_API = MEDIA_API + "/upload?type=%1$s&access_token=%2$s";
- /**
- * 发送客服消息入口
- */
- public static final String CUSTOM_MESSAGE_API = WX_API + "/message/custom/send?access_token=%1$s";
- /**
- * 网页授权请求地址
- */
- public static final String WEB_OAUTH2 = "/connect/oauth2/authorize?appid=%1$s&redirect_uri=%2$s&response_type=code&scope=%3$s&state=%4$s;%5$s#wechat_redirect";
- /**
- * 网页授权获取TOKEN
- */
- public static final String OAUTH_TOKEN = "/sns/oauth2/access_token?appid=%1$s&secret=%2$s&grant_type=authorization_code&code=%3$s";
- /**
- * 网页授权取得用户信息地址
- */
- public static final String OAUTH_USERINFO = "/sns/userinfo?access_token=%1$s&openid=%2$s&lang=%3$s";
- /**
- * 发送模板消息地址
- */
- public static final String TEMPLATE_MESSAGE_API = WX_API + "/message/template/send?access_token=%1$s";
- /**
- * 上传图文素材地址
- */
- public static final String NEWS_UPLOAD_API = WX_API + "/media/uploadnews?access_token=%1$s";
- /**
- * 分组群消息[sendall,send,delete]入口
- */
- public static final String GROUP_NEWS_MESSAGE_API = WX_API + "/message/mass/%1$s?access_token=%2$s";
- /**
- * 群发消息上传视频地址
- */
- public static final String MEDIA_UPVIDEO_API = MEDIA_API + "/uploadvideo?access_token=%1$s";
- /**
- * 服务组件API入口
- */
- public static final String COMPONENT_API = WX_API + "/component/%1$s?component_access_token=%2$s";
- /**
- * 获取服务组件token地址
- */
- public static final String COMPONENT_TOKEN_API = WX_API + "/component/api_component_token";
- /**
- * 获取JSTICKET地址
- */
- public static final String JSAPI_TICKET_URL = WX_API + "/ticket/getticket?type=jsapi&access_token=";
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/commons/WxErrCode.java b/src/main/java/org/elkan1788/osc/weixin/mp/commons/WxErrCode.java
deleted file mode 100644
index bbd27d6..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/commons/WxErrCode.java
+++ /dev/null
@@ -1,273 +0,0 @@
-package org.elkan1788.osc.weixin.mp.commons;
-
-/**
- * 微信通讯的错误代码
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/6
- * @version 1.0.0
- */
-public class WxErrCode {
-
- public static final int SYS_BUSY = -1;
- public static final int OK = 0;
- public static final int ERROR_SECRET = 40001;
- public static final int INVALID_CERTIFICATE = 40002;
- public static final int INVALID_OPENID = 40003;
- public static final int INVALID_MEDIATYPE = 40004;
- public static final int INVALID_FILETYPE = 40005;
- public static final int INVALID_FILESIZE = 40006;
- public static final int INVALID_MEDIAID = 40007;
- public static final int INVALID_MESGTYPE = 40008;
- public static final int INVALID_IMAGESIZE = 40009;
- public static final int INVALID_VOICESIZE = 40010;
- public static final int INVALID_VIDEOSIZE = 40011;
- public static final int INVALID_THUMBSIZE = 40012;
- public static final int INVALID_APPID = 40013;
- public static final int INVALID_ACCESSTOKEN = 40014;
- public static final int INVALID_MENUTYPE = 40015;
- public static final int INVALID_BUTTONSIZE = 40016;
- public static final int INVALID_BUTTONSIZE2 = 40017;
- public static final int INVALID_BUTTONNAMESIZE = 40018;
- public static final int INVALID_BUTTONKEYSIZE = 40019;
- public static final int INVALID_BUTTONURLSIZE = 40020;
- public static final int INVALID_BUTTONVERSION = 40021;
- public static final int INVALID_MENULEVEL = 40022;
- public static final int INVALID_SUBBUTTONSIZE = 40023;
- public static final int INVALID_SUBMENUTYPE = 40024;
- public static final int INVALID_SUBBUTTONNAMESIZE = 40025;
- public static final int INVALID_SUBBUTTONKEYSIZE = 40026;
- public static final int INVALID_SUBBUTTONURLSIZE = 40027;
- public static final int INVALID_MENUUSER = 40028;
- public static final int INVALID_OAUTHCODE = 40029;
- public static final int INVALID_REFRESHCODE = 40030;
- public static final int INVALID_OPENIDLIST = 40031;
- public static final int INVALID_OPENIDLENGTH = 40032;
- public static final int INVALID_REQUESTSTRING = 40033;
- public static final int INVALID_PARAMETERS = 40035;
- public static final int INVALID_REQUESTSTYLE = 40038;
- public static final int INVALID_URLLENGTH = 40039;
- public static final int INVALID_GROUPID = 40050;
- public static final int INVALID_GROUPNAME = 40051;
- public static final int INVALID_MSGID = 40059;
- public static final int LOST_AESSTOKEN = 41001;
- public static final int LOST_APPID = 41002;
- public static final int LOST_REFRESHTOKEN = 41003;
- public static final int LOST_APPSECRET = 41004;
- public static final int LOST_MEDIAFILE_DATA = 41005;
- public static final int LOST_MEDIAID = 41006;
- public static final int LOST_SUBMENUS = 41007;
- public static final int LOST_OAUTHCODE = 41008;
- public static final int LOST_OPENID = 41009;
- public static final int ACCESSTOKEN_OVERTIME = 42001;
- public static final int REFRESHTOKEN_OVERTIME = 42002;
- public static final int OAUTHCODE_OVERTIME = 42003;
- public static final int GET_REUEST = 43001;
- public static final int POST_REUEST = 43002;
- public static final int HTTPS_REUEST = 43003;
- public static final int FOLLOW_REUEST = 43004;
- public static final int FRIEND_REUEST = 43005;
- public static final int NULL_MEDIAFILE = 44001;
- public static final int NULL_POSTDATA = 44002;
- public static final int NULL_NEWSDATA = 44003;
- public static final int NULL_TEXTDATA = 44004;
- public static final int MEDIASIZE_LIMIT_OVER = 45001;
- public static final int CONTENT_LIMIT_OVER = 45002;
- public static final int TITLE_LIMIT_OVER = 45003;
- public static final int DIGEST_LIMIT_OVER = 45004;
- public static final int LINKURL_LIMIT_OVER = 45005;
- public static final int PICURL_LIMIT_OVER = 45006;
- public static final int VIOCE_PLAY_LIMIT_OVER = 45007;
- public static final int NEWS_LIMIT_OVER = 45008;
- public static final int INTERFACE_LIMIT_OVER = 45009;
- public static final int MENUSIZE_LIMIT_OVER = 45010;
- public static final int REPLYTIME_LIMIT_OVER = 45015;
- public static final int SYSTEM_GROUP = 45016;
- public static final int GROUPNAME_LIMIT_OVER = 45017;
- public static final int GROUPSIZE_LIMIT_OVER = 45018;
- public static final int NOEXIST_MEDIAFILE = 46001;
- public static final int NOEXIST_MENUVERSION = 46002;
- public static final int NOEXIST_MENUDATA = 46003;
- public static final int NOEXIST_USER = 46004;
- public static final int PARSE_XML_JSON_ERR = 47001;
- public static final int UNOAUTH_MODULE_API = 48001;
- public static final int UNOATH_API = 50001;
-
- /**
- * 获取错误信息描述
- *
- * @param errCode 错误代码
- * @return 错误描述
- */
- public static String getErrDesc(int errCode){
- switch (errCode) {
- case OK:
- return "请求成功";
- case SYS_BUSY:
- return "系统繁忙";
- case ERROR_SECRET:
- return "获取access_token时AppSecret错误,或者access_token无效";
- case INVALID_CERTIFICATE:
- return "不合法的凭证类型";
- case INVALID_OPENID:
- return "不合法的OpenID";
- case INVALID_MEDIATYPE:
- return "不合法的媒体文件类型";
- case INVALID_FILETYPE:
- return "不合法的文件类型";
- case INVALID_FILESIZE:
- return "不合法的文件大小";
- case INVALID_MEDIAID:
- return "不合法的媒体文件id";
- case INVALID_MESGTYPE:
- return "不合法的消息类型";
- case INVALID_IMAGESIZE:
- return "不合法的图片文件大小";
- case INVALID_VOICESIZE:
- return "不合法的语音文件大小";
- case INVALID_VIDEOSIZE:
- return "不合法的视频文件大小";
- case INVALID_THUMBSIZE:
- return "不合法的缩略图文件大小";
- case INVALID_APPID:
- return "不合法的APPID";
- case INVALID_ACCESSTOKEN:
- return "不合法的access_token";
- case INVALID_MENUTYPE:
- return "不合法的菜单类型";
- case INVALID_BUTTONSIZE:
- case INVALID_BUTTONSIZE2:
- return "不合法的按钮个数";
- case INVALID_BUTTONNAMESIZE:
- return "不合法的按钮名字长度";
- case INVALID_BUTTONKEYSIZE:
- return "不合法的按钮KEY长度";
- case INVALID_BUTTONURLSIZE:
- return "不合法的按钮URL长度";
- case INVALID_BUTTONVERSION:
- return "不合法的菜单版本号";
- case INVALID_MENULEVEL:
- return "不合法的子菜单级数";
- case INVALID_SUBBUTTONSIZE:
- return "不合法的子菜单按钮个数";
- case INVALID_SUBMENUTYPE:
- return "不合法的子菜单按钮类型";
- case INVALID_SUBBUTTONNAMESIZE:
- return "不合法的子菜单按钮名字长度";
- case INVALID_SUBBUTTONKEYSIZE:
- return "不合法的子菜单按钮KEY长度";
- case INVALID_SUBBUTTONURLSIZE:
- return "不合法的子菜单按钮KEY长度";
- case INVALID_MENUUSER:
- return "不合法的自定义菜单使用用户";
- case INVALID_OAUTHCODE:
- return "不合法的oauth_code";
- case INVALID_REFRESHCODE:
- return "不合法的refresh_token";
- case INVALID_OPENIDLIST:
- return "不合法的openid列表";
- case INVALID_OPENIDLENGTH:
- return "不合法的openid列表长度";
- case INVALID_REQUESTSTRING:
- return "不合法的请求字符,不能包含\\uxxxx格式的字符";
- case INVALID_PARAMETERS:
- return "不合法的参数";
- case INVALID_REQUESTSTYLE:
- return "不合法的请求格式";
- case INVALID_URLLENGTH:
- return "不合法的URL长度";
- case INVALID_GROUPID:
- return "不合法的分组id";
- case INVALID_GROUPNAME:
- return "分组名字不合法";
- case INVALID_MSGID:
- return "不合法的消息ID";
- case LOST_AESSTOKEN:
- return "缺少access_token参数";
- case LOST_APPID:
- return "缺少appid参数";
- case LOST_REFRESHTOKEN:
- return "缺少refresh_token参数";
- case LOST_APPSECRET:
- return "缺少secret参数";
- case LOST_MEDIAFILE_DATA:
- return "缺少多媒体文件数据";
- case LOST_MEDIAID:
- return "缺少media_id参数";
- case LOST_SUBMENUS:
- return "缺少子菜单数据";
- case LOST_OAUTHCODE:
- return "缺少oauth code";
- case LOST_OPENID:
- return "缺少openid";
- case ACCESSTOKEN_OVERTIME:
- return "access_token超时";
- case REFRESHTOKEN_OVERTIME:
- return "refresh_token超时";
- case OAUTHCODE_OVERTIME:
- return "oauth code超时";
- case GET_REUEST:
- return "需求GET请求";
- case POST_REUEST:
- return "需求POST请求";
- case HTTPS_REUEST:
- return "需求HTTPS请求";
- case FOLLOW_REUEST:
- return "需要接收者关注";
- case FRIEND_REUEST:
- return "需要好友关系";
- case NULL_MEDIAFILE:
- return "多媒体文件为空";
- case NULL_POSTDATA:
- return "POST的数据包为空";
- case NULL_NEWSDATA:
- return "图文消息内容为空";
- case NULL_TEXTDATA:
- return "文本消息内容为空";
- case MEDIASIZE_LIMIT_OVER:
- return "多媒体文件大小超过限制";
- case CONTENT_LIMIT_OVER:
- return "消息内容超过限制";
- case TITLE_LIMIT_OVER:
- return "标题字段超过限制";
- case DIGEST_LIMIT_OVER:
- return "描述字段超过限制";
- case LINKURL_LIMIT_OVER:
- return "链接字段超过限制";
- case PICURL_LIMIT_OVER:
- return "图片链接字段超过限制";
- case VIOCE_PLAY_LIMIT_OVER:
- return "语音播放时间超过限制";
- case NEWS_LIMIT_OVER:
- return "图文消息超过限制";
- case INTERFACE_LIMIT_OVER:
- return "接口调用超过限制";
- case MENUSIZE_LIMIT_OVER:
- return "创建菜单个数超过限制";
- case REPLYTIME_LIMIT_OVER:
- return "回复时间超过限制";
- case SYSTEM_GROUP:
- return "系统分组,不允许修改";
- case GROUPNAME_LIMIT_OVER:
- return "分组名字过长";
- case GROUPSIZE_LIMIT_OVER:
- return "分组数量超过上限";
- case NOEXIST_MEDIAFILE:
- return "不存在媒体数据";
- case NOEXIST_MENUVERSION:
- return "不存在的菜单版本";
- case NOEXIST_MENUDATA:
- return "不存在的菜单数据";
- case NOEXIST_USER:
- return "不存在的用户";
- case PARSE_XML_JSON_ERR:
- return "解析JSON/XML内容错误";
- case UNOAUTH_MODULE_API:
- return "api功能未授权";
- case UNOATH_API:
- return "用户未授权该api";
- default:
- return "未知异常";
- }
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/commons/package-info.java b/src/main/java/org/elkan1788/osc/weixin/mp/commons/package-info.java
deleted file mode 100644
index 21d62fe..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/commons/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 微信API的公共组件,如api地址,错误代码,消息,事件类型等
- */
-package org.elkan1788.osc.weixin.mp.commons;
\ No newline at end of file
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxApi.java b/src/main/java/org/elkan1788/osc/weixin/mp/core/WxApi.java
deleted file mode 100644
index 2392f3e..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxApi.java
+++ /dev/null
@@ -1,228 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import org.elkan1788.osc.weixin.mp.exception.WxRespException;
-import org.elkan1788.osc.weixin.mp.vo.*;
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 微信公众平台开发者API接口设计
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/10
- * @version 1.2.2
- */
-public interface WxApi {
-
- public static final String TEXT = "text";
- public static final String IMAGE = "image";
- public static final String VOICE = "voice";
- public static final String VIDEO = "video";
- public static final String MUSIC = "music";
- public static final String NEWS = "news";
- public static final String MPNEWS = "mpnews";
- public static final String MPVIDEO = "mpvideo";
-
- /**
- * 创建ACCESS_TOKEN
- *
- * @return 高级API需要的access_token
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- String getAccessToken() throws WxRespException;
-
- /**
- * 刷新过期的ACCESS_TOKE
- *
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- void refreshAccessToken() throws WxRespException;
-
- /**
- * 获取微信服务器IP列表
- *
- * @return IP地址集合
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- List getServerIp() throws WxRespException;
-
- /**
- * 上传多媒体文件,微信服务器只保存3天
- *
- * @param mediaType 媒体文件类型[image, voice, video]
- * @param file 文件
- * @return 储存媒体ID
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- String upMedia(String mediaType, File file) throws WxRespException;
-
- /**
- * 下载多媒体文件
- *
- * @param mediaId 多媒体ID
- * @param file 本地存储位置[默认使用媒体ID作文件名]
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- void dlMedia(String mediaId, File file) throws WxRespException;
-
- /**
- * 获取微信菜单
- *
- * @return 微信菜单集合
- */
- List getMenu() throws WxRespException;
-
- /**
- * 创建微信菜单
- *
- * @param menus 微信菜单
- * @return true或false
- */
- boolean createMenu(Menu... menus) throws WxRespException;
-
- /**
- * 删除自定义菜单
- *
- * @return true或false
- */
- boolean deleteMenu() throws WxRespException;
-
- /**
- * 创建分组
- *
- * @param name 分组名称
- * @return 分组ID
- */
- int creatGroup(String name) throws WxRespException;
-
- /**
- * 获取所有分组
- *
- * @return Groups集合
- */
- List getGroups() throws WxRespException;
-
- /**
- * 重命名分组
- *
- * @param id 分组ID
- * @param name 新的分组名称
- * @return true或false
- */
- boolean renGroup(int id, String name) throws WxRespException;
-
- /**
- * 获取用户分组ID
- *
- * @param openId 用户ID
- * @return 分组ID
- */
- int getGroupId(String openId) throws WxRespException;
-
- /**
- * 移动用户分组
- *
- * @param openId 用户ID
- * @param groupId 新分组ID
- * @return true或false
- */
- boolean move2Group(String openId, int groupId) throws WxRespException;
-
- /**
- * 获取关注用户列表
- *
- * @param nextOpenId 拉取列表的后一个用户的OPENID
- * @return 关注用户ID列表
- */
- FollowList getFollowerList(String nextOpenId) throws WxRespException;
-
- /**
- * 获取关注者的信息
- *
- * @param openId 用户ID
- * @param lang 使用语言
- * @return 关注者的基本信息
- */
- Follower getFollower(String openId, String lang) throws WxRespException;
-
- /**
- * 发送客服消息
- *
- * @param msg 消息
- * @return false或true
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- boolean sendCustomerMsg(OutPutMsg msg) throws WxRespException;
-
- /**
- * 发送模板消息
- *
- * @param openId 接收者ID
- * @param templateId 模板ID
- * @param topColor 顶部颜色
- * @param url 跳转地址
- * @param templates 模样数据
- * @return false或true
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- boolean sendTemplateMsg(String openId, String templateId, String topColor, String url, Template... templates) throws WxRespException;
-
- /**
- * 上传图文消息素材
- *
- * @param articles2s 图文消息实体数组
- * @return [0 消息类型, 1 多媒体ID, 2 创建时间]
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- String[] upNews(Article2... articles2s) throws WxRespException;
-
- /**
- * 上传群发消息中的视频文件
- *
- * @param mediaId 多媒体ID[需通过基础支持中的上传下载多媒体文件来得到]
- * @param title 标题
- * @param description 描述
- * @return [0 消息类型, 1 多媒体ID, 2 创建时间]
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- String[] upVideo(String mediaId, String title, String description) throws WxRespException;
-
- /**
- * 群发消息[分组或指定用户]
- *
- * @param msg 消息输出实体[groupId或toUsers, content, msgType, mediaId]
- * @return 消息ID
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- String sendAll(OutPutMsg msg) throws WxRespException;
-
- /**
- * 删除群发消息
- *
- * 只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效,
- * 已经收到的用户,还是能在其本地看到消息卡片。 另外,删除群发消息只能
- * 删除图文消息和视频消息,其他类型的消息一经发送,无法删除。
- * @param msgId 发送消息的ID
- * @return false或true
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- boolean delSendAll(String msgId) throws WxRespException;
-
- /**
- * 获取JSAPI签名
- *
- * @param url 使用jsapi页面地址
- * @return 集合[url, ticket, nonce, timestamp, sign]
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- Map getJsAPISign(String url) throws WxRespException;
-
- /**
- * 刷新过期的JSAPI TICKET
- *
- * @throws org.elkan1788.osc.weixin.mp.exception.WxRespException
- */
- void refreshJsAPITicket() throws WxRespException;
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxApiImpl.java b/src/main/java/org/elkan1788/osc/weixin/mp/core/WxApiImpl.java
deleted file mode 100644
index 31efe79..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxApiImpl.java
+++ /dev/null
@@ -1,601 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.serializer.PropertyFilter;
-import com.qq.weixin.mp.aes.AesException;
-import com.qq.weixin.mp.aes.SHA1;
-import org.elkan1788.osc.weixin.mp.commons.WxMsgType;
-import org.elkan1788.osc.weixin.mp.commons.WxApiUrl;
-import org.elkan1788.osc.weixin.mp.exception.WxRespException;
-import org.elkan1788.osc.weixin.mp.util.JsonMsgBuilder;
-import org.elkan1788.osc.weixin.mp.util.SimpleHttpReq;
-import org.elkan1788.osc.weixin.mp.vo.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
-
-/**
- * 微信公众平台开发者API接口实现
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/12
- * @version 1.2.2
- */
-public class WxApiImpl implements WxApi {
-
- private static final Logger log = LoggerFactory.getLogger(WxApiImpl.class);
-
- private MPAct mpAct;
-
- /**
- * 微信公众平台接口构建
- *
- * @param mpAct 公众号信息
- */
- public WxApiImpl(MPAct mpAct) {
- this.mpAct = mpAct;
- }
-
- @Override
- public String getAccessToken() throws WxRespException {
- String token = mpAct.getAccessToken();
- if (null == token
- || token.isEmpty()
- || mpAct.getExpiresIn() < System.currentTimeMillis()) {
- synchronized (mpAct){
- refreshAccessToken();
- }
- token = mpAct.getAccessToken();
- }
- return token;
- }
-
- @Override
- public void refreshAccessToken() throws WxRespException {
- String url = String.format(WxApiUrl.ACCESS_TOKEN_API,
- mpAct.getAppId(),
- mpAct.getAppSecret());
- String result = "";
- try {
- result = SimpleHttpReq.get(url);
- } catch (IOException e) {
- log.error("刷新ACCESS_TOKEN时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- mpAct.createAccessToken(result);
- }
-
- @Override
- public List getServerIp() throws WxRespException {
- String url = String.format(WxApiUrl.IP_LIST_API, getAccessToken());
- String result = "";
- try {
- result = SimpleHttpReq.get(url);
- } catch (IOException e) {
- log.error("获取微信服务器IP时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- JSONObject tmp = JSON.parseObject(result);
- List ips = JSONObject.parseArray(tmp.getString("ip_list"), String.class);
-
- return ips;
- }
-
- @Override
- public List getMenu() throws WxRespException {
- String url = String.format(WxApiUrl.CUSTOM_MENU_API, "get", getAccessToken());
- String result = "";
- try {
- result = SimpleHttpReq.get(url);
- } catch (IOException e) {
- log.error("获取当前自定义菜单时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
- JSONObject tmp = JSON.parseObject(result).getJSONObject("menu");
- List menus = JSON.parseArray(tmp.getString("button"), Menu.class);
- return menus;
- }
-
- @Override
- public boolean createMenu(Menu... menus) throws WxRespException {
- // 创建JSON格式化
- PropertyFilter null_filter = new PropertyFilter() {
- @Override
- public boolean apply(Object object, String name, Object value) {
- if(name.equals("key")
- && (null==value || "".equals(value))) {
- return false;
- }
- if (name.equals("url")
- && (null==value || "".equals(value))) {
- return false;
- }
- return true;
- }
- };
- // 准备菜单数据
- Map buttons = new HashMap<>();
- buttons.put("button", Arrays.asList(menus));
- String btn_json = JSONObject.toJSONString(buttons, null_filter);
- if (log.isInfoEnabled()) {
- log.info("创建的微信自定义菜单: {}", btn_json);
- }
- // 提交并创建菜单
- String url = String.format(WxApiUrl.CUSTOM_MENU_API, "create", getAccessToken());
- String result = "";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, btn_json);
- } catch (IOException e) {
- log.error("创建自定义菜单时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || !result.contains("ok")) {
- throw new WxRespException(result);
- }
-
- return true;
- }
-
- @Override
- public boolean deleteMenu() throws WxRespException {
- String url = String.format(WxApiUrl.CUSTOM_MENU_API, "delete", getAccessToken());
- String result = "";
- try {
- result = SimpleHttpReq.get(url);
- } catch (IOException e) {
- log.error("删除微信自定义菜单时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- return true;
- }
-
- @Override
- public int creatGroup(String name) throws WxRespException {
- String url = String.format(WxApiUrl.GROUPS_API, "create", getAccessToken());
- String data = "{\"group\":{\"name\":\""+name+"\"}}";
- String result = "";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
- } catch (IOException e) {
- log.error("创建微信分组时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || !result.contains("group")) {
- throw new WxRespException(result);
- }
-
- JSONObject tmp = JSON.parseObject(result).getJSONObject("group");
-
- return tmp.getInteger("id");
- }
-
- @Override
- public List getGroups() throws WxRespException {
- String url = String.format(WxApiUrl.GROUPS_API, "get", getAccessToken());
- String result = "";
- try {
- result = SimpleHttpReq.get(url);
- } catch (IOException e) {
- log.error("获取所有分组时失败!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.indexOf("errcode") > -1) {
- throw new WxRespException(result);
- }
-
- String tmp = JSON.parseObject(result).getString("groups");
- List groups = JSON.parseArray(tmp, Group.class);
-
- return groups;
- }
-
- @Override
- public boolean renGroup(int id, String name) throws WxRespException {
- String url = String.format(WxApiUrl.GROUPS_API, "update", getAccessToken());
- name = name.length() > 30 ? name.substring(0,30) : name;
- String data = "{\"group\":{\"id\":"+id+",\"name\":\""+name+"\"}}";
- String result = "";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
- } catch (IOException e) {
- log.error("修改分组名称时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- return true;
- }
-
- @Override
- public int getGroupId(String openId) throws WxRespException {
- String url = String.format(WxApiUrl.GROUPS_API, "getid", getAccessToken());
- String data = "{\"openid\":\""+openId+"\"}";
- String result = "";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
- } catch (IOException e) {
- log.error("获取用户所在分组时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.indexOf("errcode") > -1) {
- throw new WxRespException(result);
- }
-
- int group_id = JSON.parseObject(result).getInteger("groupid");
-
- return group_id;
- }
-
- @Override
- public boolean move2Group(String openId, int groupId) throws WxRespException {
- String url = String.format(WxApiUrl.GROUPS_USER_API, getAccessToken());
- String data = "{\"openid\":\""+openId+"\",\"to_groupid\":"+groupId+"}";
- String result = "";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
- } catch (IOException e) {
- log.error("移动用户分组时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || !result.contains("ok")) {
- throw new WxRespException(result);
- }
-
- return true;
- }
-
- @Override
- public FollowList getFollowerList(String nextOpenId) throws WxRespException {
- String url = String.format(WxApiUrl.FOLLOWS_USER_API, getAccessToken(), nextOpenId);
- String result = "";
- try {
- result = SimpleHttpReq.get(url);
- } catch (IOException e) {
- log.error("获取关注用户列表时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.indexOf("errcode") > -1) {
- throw new WxRespException(result);
- }
-
- FollowList followers = JSON.parseObject(result, FollowList.class);
- String openid = JSON.parseObject(result).getJSONObject("data").getString("openid");
- List openids = JSON.parseArray(openid, String.class);
- followers.setOpenIds(openids);
- return followers;
- }
-
- @Override
- public Follower getFollower(String openId, String lang) throws WxRespException {
- String url = String.format(WxApiUrl.USER_INFO_API, getAccessToken(), openId, lang);
- String result = "";
- try {
- result = SimpleHttpReq.get(url);
- } catch (IOException e) {
- log.error("获取用户信息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.indexOf("errcode") > -1) {
- throw new WxRespException(result);
- }
-
- Follower follower = JSON.parseObject(result, Follower.class);
-
- return follower;
- }
-
- @Override
- public boolean sendCustomerMsg(OutPutMsg msg) throws WxRespException {
- String url = String.format(WxApiUrl.CUSTOM_MESSAGE_API, getAccessToken());
- String custom_msg = "";
- WxMsgType type = WxMsgType.valueOf(msg.getMsgType());
- switch (type) {
- case text:
- custom_msg = JsonMsgBuilder.create().text(msg).build();
- break;
- case image:
- custom_msg = JsonMsgBuilder.create().image(msg).build();
- break;
- case voice:
- custom_msg = JsonMsgBuilder.create().voice(msg).build();
- break;
- case video:
- custom_msg = JsonMsgBuilder.create().video(msg).build();
- break;
- case music:
- custom_msg = JsonMsgBuilder.create().music(msg).build();
- break;
- case news:
- custom_msg = JsonMsgBuilder.create().news(msg).build();
- break;
- default:
- break;
- }
- String result = "";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, custom_msg);
- } catch (IOException e) {
- log.error("发送客服消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || !result.contains("ok")) {
- throw new WxRespException(result);
- }
-
- return true;
- }
-
- @Override
- public boolean sendTemplateMsg(String openId, String templateId,
- String topColor, String url, Template... templates) throws WxRespException {
- String api_url = String.format(WxApiUrl.TEMPLATE_MESSAGE_API, getAccessToken());
- String template_msg = JsonMsgBuilder.create()
- .template(openId, templateId, topColor, url, templates)
- .build();
- String result = "";
- try {
- result = SimpleHttpReq.post(api_url, SimpleHttpReq.APPLICATION_JSON, template_msg);
- } catch (IOException e) {
- log.error("发送模板消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty() ||
- result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- return true;
- }
-
- @Override
- public String upMedia(String mediaType, File file) throws WxRespException {
- String url = String.format(WxApiUrl.MEDIA_UP_API, mediaType, getAccessToken());
- String result = "";
- try {
- result = SimpleHttpReq.upload(url, file);
- } catch (IOException e) {
- log.error("上传多媒体文件时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- ||result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- String media_id = JSON.parseObject(result).getString("media_id");
-
- return media_id;
- }
-
- @Override
- public void dlMedia(String mediaId, File file) throws WxRespException {
-
- String url = String.format(WxApiUrl.MEDIA_DL_API, getAccessToken(), mediaId);
- // 检查文件夹是否存在
- if(!file.exists()) {
- String path = file.getAbsolutePath();
- String separ = System.getProperties().getProperty("file.separator");
- File dir = new File(path.substring(0, path.lastIndexOf(separ)));
- dir.mkdirs();
- }
-
- try {
- SimpleHttpReq.download(url, file);
- } catch (IOException e) {
- log.error("下载多媒体文件时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
- }
-
- @Override
- public String[] upNews(Article2... articles2s) throws WxRespException {
- String url = String.format(WxApiUrl.NEWS_UPLOAD_API, getAccessToken());
- String upnews_msg = JsonMsgBuilder.create().uploadNews(articles2s).build();
- String result = "";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, upnews_msg);
- } catch (IOException e) {
- log.error("上传群发图文消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- ||result.contains("errcode")) {
- throw new WxRespException(result);
- }
- JSONObject tmp = JSON.parseObject(result);
- String[] results = {
- tmp.getString("type"),
- tmp.getString("media_id"),
- tmp.getString("created_at")
- };
- return results;
- }
-
- @Override
- public String[] upVideo(String mediaId,
- String title, String description) throws WxRespException {
- String url = String.format(WxApiUrl.MEDIA_UPVIDEO_API, getAccessToken());
- String result = "";
- String upvideo_msg = JsonMsgBuilder.create().uploadVideo(mediaId,title,description).build();
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, upvideo_msg);
- } catch (IOException e) {
- log.error("上传群发消息中的视频时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- ||result.contains("errcode")) {
- throw new WxRespException(result);
- }
- JSONObject tmp = JSON.parseObject(result);
- String[] results = {
- tmp.getString("type"),
- tmp.getString("media_id"),
- tmp.getString("created_at")
- };
- return results;
- }
-
- @Override
- public String sendAll(OutPutMsg msg) throws WxRespException {
- String group_id = msg.getGroupId();
- List to_users = msg.getToUsers();
- if (null != group_id
- && !group_id.isEmpty()
- && !to_users.isEmpty()) {
- throw new RuntimeException("群发消息只能选择一种模式");
- }
-
- String url = "";
- if (to_users.isEmpty()) {
- url = String.format(WxApiUrl.GROUP_NEWS_MESSAGE_API, "sendall", getAccessToken());
- } else {
- url = String.format(WxApiUrl.GROUP_NEWS_MESSAGE_API, "send", getAccessToken());
- }
-
- String result = "";
- String send_msg = JsonMsgBuilder.create().sendAll(msg).build();
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, send_msg);
- } catch (IOException e) {
- log.error("发送群消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- ||!result.contains("msg_id")) {
- throw new WxRespException(result);
- }
-
- JSONObject tmp = JSON.parseObject(result);
-
- return tmp.getString("msg_id");
- }
-
- @Override
- public boolean delSendAll(String msgId) throws WxRespException {
- String url = String.format(WxApiUrl.GROUP_NEWS_MESSAGE_API, "delete", getAccessToken());
- String result = "";
- String del_msg = "{\"msg_id\":"+ msgId +"}";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, del_msg);
- } catch (IOException e) {
- log.error("删除群发消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- ||!result.contains("ok")) {
- throw new WxRespException(result);
- }
-
- return true;
- }
-
- @Override
- public Map getJsAPISign(String url) throws WxRespException {
- // 1.创建JSTICKET
- String ticket = mpAct.getJsTicket();
- if (null == ticket
- || ticket.isEmpty()
- || mpAct.getJsExpiresIn() < System.currentTimeMillis()) {
- synchronized (mpAct){
- refreshJsAPITicket();
- }
- ticket = mpAct.getJsTicket();
- }
-
- // 2.生成签名
- String sign_param = "jsapi_ticket=%1$s&noncestr=%2$s×tamp=%3$s&url=%4$s";
- String nonce = UUID.randomUUID().toString().toLowerCase();
- long time = System.currentTimeMillis() / 1000;
- String sign = null;
- try {
- sign = SHA1.calculate(String.format(sign_param, ticket, nonce, time, url));
- } catch (AesException e) {
- log.error("生成JSTICKET的签名时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- // 3.返回参数与值
- Map sign_map = new HashMap<>();
- sign_map.put("url", url);
- sign_map.put("ticket", ticket);
- sign_map.put("nonce", nonce);
- sign_map.put("timestamp", time);
- sign_map.put("sign", sign);
- return sign_map;
- }
-
- @Override
- public void refreshJsAPITicket() throws WxRespException {
-
- String token_url = WxApiUrl.JSAPI_TICKET_URL+getAccessToken();
-
- String result = "";
- try {
- result = SimpleHttpReq.get(token_url);
- } catch (IOException e) {
- log.error("刷新JSTICKET时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || !result.contains("ok")) {
- throw new WxRespException(result);
- }
-
- mpAct.createJsTicket(result);
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxBase.java b/src/main/java/org/elkan1788/osc/weixin/mp/core/WxBase.java
deleted file mode 100644
index c87c891..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxBase.java
+++ /dev/null
@@ -1,469 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import com.qq.weixin.mp.aes.AesException;
-import com.qq.weixin.mp.aes.WXBizMsgCrypt;
-import org.elkan1788.osc.weixin.mp.MPSDK4J;
-import org.elkan1788.osc.weixin.mp.commons.WxEventType;
-import org.elkan1788.osc.weixin.mp.commons.WxMsgType;
-import org.elkan1788.osc.weixin.mp.util.StreamTool;
-import org.elkan1788.osc.weixin.mp.util.XMLHandler;
-import org.elkan1788.osc.weixin.mp.util.XmlMsgBuilder;
-import org.elkan1788.osc.weixin.mp.vo.MPAct;
-import org.elkan1788.osc.weixin.mp.vo.OutPutMsg;
-import org.elkan1788.osc.weixin.mp.vo.ReceiveMsg;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-
-/**
- * 微信普通消息互动
- *
- * @author 凡梦星尘(senhuili@mdc.cn)
- * @version 1.2.0
- * @since 2014/11/8
- */
-public class WxBase {
-
- private static final Logger log = LoggerFactory.getLogger(WxBase.class);
- // 消息模式(默认明文)
- private boolean aesEncrypt = false;
- // 定义公众号信息
- private MPAct mpAct;
- // 微信加密
- private WXBizMsgCrypt wxInMsgCrt;
- // XML解析准备
- private SAXParserFactory factory = SAXParserFactory.newInstance();
- private SAXParser xmlParser;
- private XMLHandler xmlHandler = new XMLHandler();
- // 微信交互参数
- private String signature;
- private String msgSignature;
- private String timeStamp;
- private String nonce;
- private String echostr;
- // 微信消息流
- private InputStream wxInMsg;
- // 微信消息处理器
- private WxHandler wxHandler;
- // 解析/响应微信消息
- private ReceiveMsg rm;
- private OutPutMsg om;
-
- public WxBase() {
- try {
- xmlParser = factory.newSAXParser();
- } catch (ParserConfigurationException e) {
- log.error("SAX解析配置文件失败!!!");
- log.error(e.getLocalizedMessage(), e);
- } catch (SAXException e) {
- log.error("SAX异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
- }
-
- /**
- * 微信基础功能参数初始化
- *
- * @param req 请求
- */
- public void init(HttpServletRequest req) {
- // 请求编码设置
- try {
- req.setCharacterEncoding("UTF-8");
- } catch (UnsupportedEncodingException e) {
- log.error("设置微信服务器请求编辑时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
- // 获取各请求参数值
- String sign = req.getParameter("signature");
- String time = req.getParameter("timestamp");
- String nonce = req.getParameter("nonce");
- String echo = req.getParameter("echostr");
- String encrypt = req.getParameter("encrypt_type");
- // 设置各参数值
- setSignature(sign);
- setTimeStamp(time);
- setNonce(nonce);
- setEchostr(echo);
- // 判断是否启用AES加密
- if ("aes".equals(encrypt)) {
- String msgSign = req.getParameter("msg_signature");
- setMsgSignature(msgSign);
- setAesEncrypt(true);
- }
- // 读取微信消息
- try {
- InputStream wxInMsg = req.getInputStream();
- this.wxInMsg = wxInMsg;
- } catch (IOException e) {
- log.error("接收微信消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
- }
-
- /**
- * 微信URL接入校验
- *
- * @return 随机字符
- * @throws AesException
- */
- public String check() throws AesException {
-
- boolean check = wxHandler.check(this.mpAct.getToken(),
- this.signature, this.timeStamp, this.nonce);
- return check ? echostr : "";
- }
-
- /**
- * 微信消息处理
- *
- * @return 回复消息
- * @throws Exception
- */
- public String handler() throws Exception {
- // 释放缓存
- clear();
- String reply = "";
- this.rm = convert2VO(this.wxInMsg);
- // 处理消息
- String msg_type = this.rm.getMsgType();
- if ("event".equals(msg_type)) {
- this.om = handlerEvent();
- } else {
- this.om = handlerMsg();
- }
- // 输出消息
- if (null != this.om) {
- reply = this.convert2XML(this.om);
- }
- return reply;
- }
-
- /**
- * 处理普通的消息
- *
- * @return 回复消息实体
- * @throws Exception
- */
- private OutPutMsg handlerMsg() throws Exception {
- if (log.isInfoEnabled()) {
- log.info("[MPSDK4J-{}]处理普通消息...", MPSDK4J.version());
- }
- OutPutMsg om = null;
- WxMsgType type = WxMsgType.valueOf(this.rm.getMsgType());
- switch (type) {
- case text:
- om = wxHandler.text(this.rm);
- break;
- case image:
- om = wxHandler.image(this.rm);
- break;
- case voice:
- om = wxHandler.voice(this.rm);
- break;
- case video:
- om = wxHandler.video(this.rm);
- break;
- case location:
- om = wxHandler.location(this.rm);
- break;
- case link:
- om = wxHandler.link(this.rm);
- break;
- default:
- om = wxHandler.def(this.rm);
- break;
- }
- return om;
- }
-
- /**
- * 处理事件推送消息
- *
- * @return 回复消息实体
- * @throws Exception
- */
- private OutPutMsg handlerEvent() throws Exception {
- if (log.isInfoEnabled()) {
- log.info("[MPSDK4J-{}]处理事件推送消息...", MPSDK4J.version());
- }
- OutPutMsg om = null;
- WxEventType type = WxEventType.valueOf(this.rm.getEvent());
- switch (type) {
- case subscribe:
- om = wxHandler.eSub(this.rm);
- break;
- case unsubscribe:
- wxHandler.eUnSub(this.rm);
- break;
- case SCAN:
- om = wxHandler.eScan(this.rm);
- break;
- case CLICK:
- om = wxHandler.eClick(this.rm);
- break;
- case VIEW:
- wxHandler.eView(this.rm);
- break;
- case scancode_push:
- om = wxHandler.eScanCodePush(this.rm);
- break;
- case scancode_waitmsg:
- om = wxHandler.eScanCodeWait(this.rm);
- break;
- case pic_sysphoto:
- om = wxHandler.ePicSysPhoto(this.rm);
- break;
- case pic_photo_or_album:
- om = wxHandler.ePicPhotoOrAlbum(this.rm);
- break;
- case pic_weixin:
- om = wxHandler.ePicWeixin(this.rm);
- break;
- case location_select:
- om = wxHandler.eLocationSelect(this.rm);
- break;
- case LOCATION:
- om = wxHandler.eLocation(this.rm);
- break;
- case TEMPLATESENDJOBFINISH:
- wxHandler.eTemplateFinish(this.rm);
- break;
- case MASSSENDJOBFINISH:
- wxHandler.eSendJobFinish(this.rm);
- break;
- default:
- om = wxHandler.def(this.rm);
- break;
- }
- return om;
- }
-
-
- /**
- * 处理微信开放平台的推送消息
- *
- * @return 默认返回"success"
- * @throws Exception
- */
- public String handlerPush() throws Exception {
- if (log.isInfoEnabled()) {
- log.info("[MPSDK4J-{}]处理开放平台推送消息...", MPSDK4J.version());
- }
- this.rm = convert2VO(this.wxInMsg);
- String info_type = this.rm.getInfoType();
- switch (info_type) {
- case "component_verify_ticket":
- wxHandler.eComponentVerifyTicket(this.rm);
- break;
- case "unauthorized":
- wxHandler.eUnAuthorizerMP(this.rm);
- break;
- default:
- break;
- }
- return "success";
- }
-
- /**
- * 将微信消息转换成接收消息VO对象
- *
- * @param msg 微信消息输入流
- * @return 接收消息VO对象
- * @throws ParserConfigurationException
- * @throws SAXException
- * @throws IOException
- * @throws AesException
- */
- private ReceiveMsg convert2VO(InputStream msg)
- throws ParserConfigurationException,
- SAXException,
- IOException,
- AesException {
-
- if (!this.aesEncrypt) { // 明文
- this.xmlParser.parse(msg, this.xmlHandler);
- } else {// 密文
- String dcrp_msg = this.wxInMsgCrt.decryptMsg(this.msgSignature,
- this.timeStamp, this.nonce, StreamTool.toString(msg));
- this.wxInMsg = StreamTool.toStream(dcrp_msg);
- this.xmlParser.parse(this.wxInMsg, this.xmlHandler);
- }
-
- ReceiveMsg rm = this.xmlHandler.getMsgVO();
- this.xmlHandler.clear();
- // 调试信息
- if (log.isInfoEnabled()) {
- log.info("[MPSDK4J-{}]接收到微信消息[{},{}]:...",
- MPSDK4J.version(),
- rm.getMsgId(), rm.getCreateTime());
- log.info("{}", rm);
- }
-
- return rm;
- }
-
- /**
- * 将VO对象转换成XML消息体
- *
- * @param msg 输出消息VO对象
- * @return 微信消息
- * @throws AesException
- */
- private String convert2XML(OutPutMsg msg) throws AesException {
-
- String reply_msg = "";
-
- // 自定义内容回复
- if (null != msg.getCustomReply()
- && !msg.getCustomReply().isEmpty()) {
- return msg.getCustomReply();
- }
-
- // 获取消息类型
- WxMsgType msg_type = WxMsgType.valueOf(msg.getMsgType());
- switch (msg_type) {
- case text:
- reply_msg = XmlMsgBuilder.create().text(msg).build();
- break;
- case image:
- reply_msg = XmlMsgBuilder.create().image(msg).build();
- break;
- case voice:
- reply_msg = XmlMsgBuilder.create().vioce(msg).build();
- break;
- case video:
- reply_msg = XmlMsgBuilder.create().video(msg).build();
- break;
- case music:
- reply_msg = XmlMsgBuilder.create().music(msg).build();
- break;
- case news:
- reply_msg = XmlMsgBuilder.create().news(msg).build();
- break;
- default:
- break;
- }
-
- // 调试信息
- if (log.isInfoEnabled()) {
- log.info("[MPSDK4J-{}]微信回复消息[{},{}]...",
- MPSDK4J.version(),
- msg.getMsgId(), msg.getCreateTime());
- log.info(reply_msg);
- }
-
- if (this.aesEncrypt) {// 加密
- reply_msg = this.wxInMsgCrt.encryptMsg(reply_msg, this.timeStamp, this.nonce);
- }
-
- return reply_msg;
- }
-
- private void clear() {
- if (null != this.rm) {
- this.rm = null;
- }
- if (null != this.om) {
- this.om = null;
- }
- }
-
- public boolean isAesEncrypt() {
- return aesEncrypt;
- }
-
- public void setAesEncrypt(boolean aesEncrypt) {
- this.aesEncrypt = aesEncrypt;
- if (aesEncrypt) {
- try {
- this.wxInMsgCrt = new WXBizMsgCrypt(this.mpAct.getToken(),
- this.mpAct.getAESKey(), this.mpAct.getAppId());
- } catch (AesException e) {
- log.error("创建AES加密失败!!!");
- log.error(e.getLocalizedMessage(), e);
- this.wxInMsgCrt = null;
- }
- }
- }
-
- public MPAct getMpAct() {
- return mpAct;
- }
-
- public void setMpAct(MPAct mpAct) {
- this.mpAct = mpAct;
- if (log.isInfoEnabled()) {
- log.info("微信公众号信息...");
- log.info("{}", this.mpAct);
- }
- }
-
- public XMLHandler getXmlHandler() {
- return xmlHandler;
- }
-
- public String getSignature() {
- return signature;
- }
-
- public void setWxHandler(WxHandler wxHandler) {
- this.wxHandler = wxHandler;
- }
-
- public void setSignature(String signature) {
- this.signature = signature;
- }
-
- public String getMsgSignature() {
- return msgSignature;
- }
-
- public void setMsgSignature(String msgSignature) {
- this.msgSignature = msgSignature;
- }
-
- public String getTimeStamp() {
- return timeStamp;
- }
-
- public void setTimeStamp(String timeStamp) {
- this.timeStamp = timeStamp;
- }
-
- public String getNonce() {
- return nonce;
- }
-
- public void setNonce(String nonce) {
- this.nonce = nonce;
- }
-
- public String getEchostr() {
- return echostr;
- }
-
- public void setEchostr(String echostr) {
- this.echostr = echostr;
- }
-
- public void setWxInMsg(InputStream wxInMsg) {
- this.wxInMsg = wxInMsg;
- }
-
- public ReceiveMsg getReceiveMsg() {
- return rm;
- }
-
- public OutPutMsg getOutPutMsg() {
- return om;
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxDefaultHandler.java b/src/main/java/org/elkan1788/osc/weixin/mp/core/WxDefaultHandler.java
deleted file mode 100644
index 5ed427e..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxDefaultHandler.java
+++ /dev/null
@@ -1,362 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import com.qq.weixin.mp.aes.AesException;
-import com.qq.weixin.mp.aes.SHA1;
-import org.elkan1788.osc.weixin.mp.commons.WxMsgType;
-import org.elkan1788.osc.weixin.mp.vo.OutPutMsg;
-import org.elkan1788.osc.weixin.mp.vo.PicInfo;
-import org.elkan1788.osc.weixin.mp.vo.ReceiveMsg;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * 默认的微信消息处理器
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/12/05
- * @version 1.0.0
- */
-public class WxDefaultHandler implements WxHandler {
-
- private static final Logger log = LoggerFactory.getLogger(WxDefaultHandler.class);
-
- @Override
- public boolean check(String token,
- String signature,
- String timestamp,
- String nonce) throws AesException {
-
- if (null == signature
- || signature.length() > 128
- || null == timestamp
- || timestamp.length() > 128
- || null == nonce
- || nonce.length() > 128) {
- log.error("验证签名参数失败!!!");
- log.error("signature={},timestamp={},nonce={}", signature, timestamp, nonce);
- return false;
- }
-
- if (log.isInfoEnabled()) {
- log.info("微信接入URL验证成功...");
- log.info("signature={},timestamp={},nonce={}", signature, timestamp, nonce);
- }
-
- String s = SHA1.calculate(token, timestamp, nonce);
- if (s.equals(signature)){
- return true;
- }
-
- return false;
- }
-
-
- @Override
- public OutPutMsg def(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- om.setContent("新的功能消息,消息类型为:"+rm.getMsgType());
- if (log.isInfoEnabled()) {
- log.info("微信新类型消息!!!");
- log.info("msgid={}, from={},to={},msgtype={}", rm.getMsgId(),
- rm.getFromUserName(), rm.getTotalCnt(), rm.getMsgType());
- }
- return om;
- }
-
- @Override
- public OutPutMsg text(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(rm.getMsgType());
- om.setContent(rm.getContent() + "\n您的消息已经收到[微笑]");
- if (log.isInfoEnabled()) {
- log.info("接收到微信文本消息...");
- log.info("msgid={}, from={}, to={}, content={}", rm.getMsgId(),
- rm.getFromUserName(), rm.getToUserName(), rm.getContent());
- }
- return om;
- }
-
- @Override
- public OutPutMsg image(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(rm.getMsgType());
- om.setMediaId(rm.getMediaId());
- if (log.isInfoEnabled()) {
- log.info("接收到微信图像消息...");
- log.info("msgid={}, from={}, to={}, mediaid={}", rm.getMsgId(),
- rm.getFromUserName(), rm.getToUserName(), rm.getMediaId());
- }
- return om;
- }
-
- @Override
- public OutPutMsg voice(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- if (null != rm.getRecognition()) {
- om.setMsgType(WxMsgType.text.name());
- om.setContent("您的语音消息已接收.[微笑]\n内容为:"+rm.getRecognition());
- } else {
- om.setMsgType(rm.getMsgType());
- om.setMediaId(rm.getMediaId());
- }
- if (log.isInfoEnabled()) {
- log.info("接收到音频消息...");
- log.info("msgid={}, from={}, to={}, mediaid={}, trans={}", rm.getMsgId(),
- rm.getFromUserName(), rm.getToUserName(), rm.getMediaId(), rm.getRecognition());
- }
- return om;
- }
-
- @Override
- public OutPutMsg video(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(rm.getMsgType());
- om.setMediaId(rm.getMediaId());
- if (log.isInfoEnabled()) {
- log.info("接收到视频消息...");
- log.info("msgid={}, from={}, to={}, mediaid={}, thumbmid={}", rm.getMsgId(),
- rm.getFromUserName(), rm.getToUserName(), rm.getMediaId(), rm.getThumbMediaId());
- }
- return om;
- }
-
- @Override
- public OutPutMsg location(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- om.setContent("您当前的位置:"+rm.getLabel()+
- ",坐标:["+rm.getLatitude()+","+rm.getLongitude()+
- "],地图缩放级别:"+rm.getScale());
- if (log.isInfoEnabled()) {
- log.info("接收到地理位置消息...");
- log.info("msgid={}, from={}, to={}, x={}, y={}, scale={}, label={}",
- rm.getMsgId(), rm.getFromUserName(), rm.getToUserName(),
- rm.getLatitude(), rm.getLongitude(), rm.getScale(), rm.getLabel());
- }
- return om;
- }
-
- @Override
- public OutPutMsg link(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- om.setContent(rm.getTitle()+"\n点击打开");
- if (log.isInfoEnabled()) {
- log.info("接收到链接消息...");
- log.info("msgid={}, from={}, to={}, title={}, desc={}, url={}",
- rm.getMsgId(), rm.getFromUserName(), rm.getToUserName(),
- rm.getTitle(), rm.getDescription(), rm.getUrl());
- }
- return om;
- }
-
- @Override
- public OutPutMsg eClick(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- om.setContent("MENU_CLICK:"+rm.getEventKey());
- if (log.isInfoEnabled()) {
- log.info("接收到菜单点击消息...");
- log.info("from={}, to={}, event={}, key={}",
- rm.getFromUserName(), rm.getToUserName(), rm.getEvent(), rm.getEventKey());
- }
- return om;
- }
-
- @Override
- public void eView(ReceiveMsg rm) {
- if (log.isInfoEnabled()) {
- log.info("接收到菜单视图跳转消息...");
- log.info("from={}, to={}, event={}, key={}",
- rm.getFromUserName(), rm.getToUserName(), rm.getEvent(), rm.getEventKey());
- }
- }
-
- @Override
- public OutPutMsg eSub(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- om.setContent("做人最重要的是要有自信,记得每天起床时,在镜子前对自己说,你很好,你可以的,树立生活自信,你可以的!");
- if (log.isInfoEnabled()) {
- log.info("接收到订阅消息...");
- log.info("from={}, to={}, event={}",
- rm.getFromUserName(), rm.getToUserName(), rm.getEvent());
- }
- return om;
- }
-
- @Override
- public void eUnSub(ReceiveMsg rm) {
- if (log.isInfoEnabled()) {
- log.info("接收到退订消息...");
- log.info("from={}, to={}, event={}",
- rm.getFromUserName(), rm.getToUserName(), rm.getEvent());
- }
- }
-
- @Override
- public OutPutMsg eScan(ReceiveMsg rm) {
- if (log.isInfoEnabled()) {
- log.info("接收到扫描消息...");
- log.info("msgid={}, from={}, to={}, event={}, key={}, ticket={}",
- rm.getMsgId(), rm.getFromUserName(), rm.getToUserName(),
- rm.getEvent(), rm.getEventKey(), rm.getTicket());
- }
- return null;
- }
-
- @Override
- public OutPutMsg eLocation(ReceiveMsg rm) {
- if (log.isInfoEnabled()) {
- log.info("接收到地理位置消息...");
- log.info("msgid={}, from={}, to={}, x={}, y={}, precision={}",
- rm.getMsgId(), rm.getFromUserName(), rm.getToUserName(),
- rm.getLatitude(), rm.getLongitude(), rm.getPrecision());
- }
- return null;
- }
-
- @Override
- public OutPutMsg eScanCodePush(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- String content = "您此次用二维码扫描菜单["+rm.getEventKey()+"],扫描结果为: "+rm.getScanResult();
- om.setContent(content);
- if (log.isInfoEnabled()) {
- log.info("接收到二维码扫描事件消息...");
- log.info("msgid={}, from={}, to={}, eventKey={}, scantype={}, scanresult={}",
- rm.getMsgId(), rm.getFromUserName(),
- rm.getToUserName(), rm.getEventKey(),
- rm.getScanType(), rm.getScanResult());
- }
- return om;
- }
-
- @Override
- public OutPutMsg eScanCodeWait(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- String content = "您此次用扫描等待菜单["+rm.getEventKey()+"],扫描结果为: "+rm.getScanResult();
- om.setContent(content);
- if (log.isInfoEnabled()) {
- log.info("接收到扫码推事件且弹出“消息接收中”提示消息...");
- log.info("msgid={}, from={}, to={}, eventKey={}, scantype={}, scanresult={}",
- rm.getMsgId(), rm.getFromUserName(),
- rm.getToUserName(), rm.getEventKey(),
- rm.getScanType(), rm.getScanResult());
- }
- return om;
- }
-
- @Override
- public OutPutMsg ePicSysPhoto(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- String content = "您此次用系统拍照["+rm.getEventKey()+"]共发了"+rm.getCount()+"张图片,图片的MD5值为: ";
- for (PicInfo pic : rm.getPicList()) {
- content += pic.getPicMd5Sum() + ", ";
- }
- om.setContent(content.substring(0, content.lastIndexOf(",")));
- if (log.isInfoEnabled()) {
- log.info("接收到菜单弹出系统拍照发图消息...");
- log.info("msgid={}, from={}, to={}, eventkey={} count={}, picmd5sum={}",
- rm.getMsgId(), rm.getFromUserName(),
- rm.getToUserName(), rm.getEventKey(),
- rm.getCount(), String.valueOf(rm.getPicList()));
- }
- return om;
- }
-
- @Override
- public OutPutMsg ePicPhotoOrAlbum(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- String content = "您此次用拍照或相册["+rm.getEventKey()+"]共发了"+rm.getCount()+"张图片,图片的MD5值为: ";
- for (PicInfo pic : rm.getPicList()) {
- content += pic.getPicMd5Sum() + ", ";
- }
- om.setContent(content.substring(0, content.lastIndexOf(",")));
- if (log.isInfoEnabled()) {
- log.info("接收到菜单弹出拍照或者相册发图消息...");
- log.info("msgid={}, from={}, to={}, eventkey={}, count={}, picmd5sum={}",
- rm.getMsgId(), rm.getFromUserName(),
- rm.getToUserName(), rm.getEventKey(),
- rm.getCount(), String.valueOf(rm.getPicList()));
- }
- return om;
- }
-
- @Override
- public OutPutMsg ePicWeixin(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- String content = "您此次用微信相册["+rm.getEventKey()+"]共发了"+rm.getCount()+"张图片,图片的MD5值为: ";
- for (PicInfo pic : rm.getPicList()) {
- content += pic.getPicMd5Sum() + ", ";
- }
- om.setContent(content.substring(0, content.lastIndexOf(",")));
- if (log.isInfoEnabled()) {
- log.info("接收到菜单微信相册发图消息...");
- log.info("msgid={}, from={}, to={}, eventkey={}, count={}, picmd5sum={}",
- rm.getMsgId(), rm.getFromUserName(),
- rm.getToUserName(), rm.getEventKey(),
- rm.getCount(), String.valueOf(rm.getPicList()));
- }
- return om;
- }
-
- @Override
- public OutPutMsg eLocationSelect(ReceiveMsg rm) {
- OutPutMsg om = new OutPutMsg(rm);
- om.setMsgType(WxMsgType.text.name());
- om.setContent("菜单值:"+rm.getEventKey()+",您当前的位置:"+rm.getLabel()+
- ",坐标:["+rm.getLatitude()+","+rm.getLongitude()+
- "],地图缩放级别:"+rm.getScale()+",朋友圈:"+rm.getPoiName());
- if (log.isInfoEnabled()) {
- log.info("接收到菜单地理位置消息...");
- log.info("msgid={}, from={}, eventkey={}, to={}, " +
- "x={}, y={}, precision={}, label={}, poiname={}",
- rm.getMsgId(), rm.getFromUserName(),
- rm.getEventKey(), rm.getToUserName(),
- rm.getLatitude(), rm.getLongitude(),
- rm.getPrecision(), rm.getLabel(), rm.getPoiName());
- }
- return om;
- }
-
- @Override
- public void eTemplateFinish(ReceiveMsg rm) {
- if (log.isInfoEnabled()) {
- log.info("接收到模板推送消息...");
- log.info("from={}, to={}, msgid={}, status={}",
- rm.getFromUserName(), rm.getToUserName(), rm.getMsgId(), rm.getStatus());
- }
- }
-
- @Override
- public void eSendJobFinish(ReceiveMsg rm) {
- if (log.isInfoEnabled()) {
- log.info("接收到群发推送消息...");
- log.info("from={}, to={}, msgid={}, status={}, total={}, filter={}, sent={}, err={}",
- rm.getFromUserName(), rm.getToUserName(), rm.getMsgId(), rm.getStatus(),
- rm.getTotalCnt(), rm.getFilterCnt(), rm.getSentCnt(), rm.getErrorCnt());
- }
- }
-
- @Override
- public void eComponentVerifyTicket(ReceiveMsg rm) {
- if (log.isDebugEnabled()) {
- log.info("接收到微信开放平台推送的组件Ticket消息...");
- log.info("appid={}, infotype={}, ticket={}", rm.getAppId(), rm.getInfoType(), rm.getTicket());
- }
- }
-
- @Override
- public void eUnAuthorizerMP(ReceiveMsg rm) {
- if (log.isDebugEnabled()) {
- log.info("接收到微信开放平台推送的公众号取消授权消息...");
- log.info("appid={}, infotype={}, unauthorizerappid={}", rm.getAppId(), rm.getInfoType(), rm.getUnAuthAppid());
- }
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxHandler.java b/src/main/java/org/elkan1788/osc/weixin/mp/core/WxHandler.java
deleted file mode 100644
index 11b62a1..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxHandler.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import com.qq.weixin.mp.aes.AesException;
-import org.elkan1788.osc.weixin.mp.vo.OutPutMsg;
-import org.elkan1788.osc.weixin.mp.vo.ReceiveMsg;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * 微信消息处理接口
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/12/05
- * @version 1.0.0
- */
-public interface WxHandler {
-
- /**
- * 微信接入时URL验证
- *
- * @param token 密钥
- * @param signature 签名
- * @param timestamp 时间戳
- * @param nonce 随机字符
- * @return true或false
- * @throws AesException 签名异常
- */
- boolean check(String token,
- String signature,
- String timestamp,
- String nonce) throws AesException;
-
- /**
- * 处理微信新功能的消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg def(ReceiveMsg rm);
-
- /**
- * 处理文本消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg text(ReceiveMsg rm);
-
- /**
- * 处理图像消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg image(ReceiveMsg rm);
-
- /**
- * 处理音频消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg voice(ReceiveMsg rm);
-
- /**
- * 处理视频消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg video(ReceiveMsg rm);
-
- /**
- * 处理主动上传地理位置消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg location(ReceiveMsg rm);
-
- /**
- * 处理链接消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg link(ReceiveMsg rm);
-
- /**
- * 处理菜单点击事件消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg eClick(ReceiveMsg rm);
-
- /**
- * 处理菜单视图事件消息
- *
- * @param rm 接收到的消息
- */
- void eView(ReceiveMsg rm);
-
- /**
- * 处理订阅事件消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg eSub(ReceiveMsg rm);
-
- /**
- * 处理退订事件消息
- *
- * @param rm 接收到的消息
- */
- void eUnSub(ReceiveMsg rm);
-
- /**
- * 处理扫描事件消息
- *
- * @param rm 接收到的消息
- */
- OutPutMsg eScan(ReceiveMsg rm);
-
- /**
- * 处理自动上传地理事件消息
- *
- * @param rm 接收到的消息
- */
- OutPutMsg eLocation(ReceiveMsg rm);
-
- /**
- * 处理二维码扫描事件消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg eScanCodePush(ReceiveMsg rm);
-
- /**
- * 扫码推事件且弹出“消息接收中”提示框
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg eScanCodeWait(ReceiveMsg rm);
-
- /**
- * 处理弹出系统拍照发图的事件推送
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg ePicSysPhoto(ReceiveMsg rm);
-
- /**
- * 处理弹出拍照或者相册发图的事件推送
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg ePicPhotoOrAlbum(ReceiveMsg rm);
-
- /**
- * 处理弹出微信相册发图器的事件推送
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg ePicWeixin(ReceiveMsg rm);
-
- /**
- * 处理弹出地理位置选择器的事件推送消息
- *
- * @param rm 接收到的消息
- * @return 回复消息
- */
- OutPutMsg eLocationSelect(ReceiveMsg rm);
-
- /**
- * 处理模板发送事件消息
- *
- * @param rm 接收到的消息
- */
- void eTemplateFinish(ReceiveMsg rm);
-
- /**
- * 处理群发消息事件消息
- *
- * @param rm 接收到的消息
- */
- void eSendJobFinish(ReceiveMsg rm);
-
- /**
- * 处理微信开放平台推送的Ticket事件消息
- * (只要回复"success"即可)
- * @param rm 接收到的消息
- */
- void eComponentVerifyTicket(ReceiveMsg rm);
-
- /**
- * 处理微信开放平台推送的取消授权公众号事件消息
- * (只要回复"success"即可)
- * @param rm 接收到的消息
- */
- void eUnAuthorizerMP(ReceiveMsg rm);
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxOpenApi.java b/src/main/java/org/elkan1788/osc/weixin/mp/core/WxOpenApi.java
deleted file mode 100644
index 42e135b..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxOpenApi.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import org.elkan1788.osc.weixin.mp.exception.WxRespException;
-import org.elkan1788.osc.weixin.mp.vo.AuthInfo;
-import org.elkan1788.osc.weixin.mp.vo.MPAct;
-
-/**
- * 微信开放平台API接口设计
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2015/1/7
- * @version 1.0.0
- */
-public interface WxOpenApi {
-
- /**
- * 设置公众号信息
- * @param mpAct 公众号信息
- */
- void setMpAct(MPAct mpAct);
-
- /**
- * 设置凭证
- * @param ticket 凭证
- */
- void setTicket(String ticket);
-
- /**
- * 获取公众号服务组件的令牌
- * @return 令牌
- * @throws WxRespException
- */
- String getComponentToken() throws WxRespException;
-
- /**
- * 刷新公众号服务组件的令牌
- * @throws WxRespException
- */
- void refreshComponentToken() throws WxRespException;
-
- /**
- * 获取公众号预授权码
- * @return 预授权码
- * @throws WxRespException
- */
- String getPreAuthCode() throws WxRespException;
-
- /**
- * 创建公众号预授权码
- * @throws WxRespException
- */
- void createPreAuthCode() throws WxRespException;
-
- /**
- * 使用授权码换取授权公众号的授权信息
- * 并换取authorizer_access_token和authorizer_refresh_token
- * @param authCode 授权码
- * @return 授权信息
- * @throws WxRespException
- */
- AuthInfo queryAuth(String authCode) throws WxRespException;
-
- /**
- * 获取授权公众号的令牌
- *
- * @param authAppId 授权方appid
- * @param authRefreshToken 授权方的刷新令牌
- * @return 令牌
- * @throws WxRespException
- */
- String getAuthAccessToken(String authAppId, String authRefreshToken) throws WxRespException;
-
- /**
- * 刷新授权公众号的令牌
- *
- * @param authAppId 授权方appid
- * @param authRefreshToken 授权方的刷新令牌
- * @throws WxRespException
- */
- void refreshAuthAccessToken(String authAppId, String authRefreshToken) throws WxRespException;
-
- /**
- * 获取授权方的账户信息
- *
- * @param authAppId 授权方appid
- * @return 权方的账户信息
- * @throws WxRespException
- */
- AuthInfo getAuthorizerInfo(String authAppId) throws WxRespException;
-
- /**
- * 获取授权方的选项设置信息
- *
- * @param authAppId 授权方appid
- * @param optionName 选项名称(location_report,voice_recognize,customer_service)
- * @return 选项值
- * @throws WxRespException
- */
- String getAuthorizerOption(String authAppId, String optionName) throws WxRespException;
-
- /**
- * 设置授权方的选项设置信息
- *
- * @param authAppId 授权方appid
- * @param optionName 设置的选项名称
- * @param optionValue 设置的选项值
- * ocation_report(地理位置上报) 0关闭 1进入会话时上报 2每5s上报
- * voice_recognize(语音识别) 0关闭 1开启
- * customer_service(客服开关) 0关闭 1开启
- * @throws WxRespException
- */
- void setAuthorizerOption(String authAppId, String optionName, String optionValue) throws WxRespException;
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxOpenApiImpl.java b/src/main/java/org/elkan1788/osc/weixin/mp/core/WxOpenApiImpl.java
deleted file mode 100644
index 859b4a3..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/core/WxOpenApiImpl.java
+++ /dev/null
@@ -1,273 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import org.elkan1788.osc.weixin.mp.commons.WxApiUrl;
-import org.elkan1788.osc.weixin.mp.exception.WxRespException;
-import org.elkan1788.osc.weixin.mp.util.SimpleHttpReq;
-import org.elkan1788.osc.weixin.mp.vo.AuthInfo;
-import org.elkan1788.osc.weixin.mp.vo.MPAct;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 微信开放平台API接口设计
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2015/1/7
- * @version 1.0.0
- */
-public class WxOpenApiImpl implements WxOpenApi {
-
- private static final Logger log = LoggerFactory.getLogger(WxOpenApiImpl.class);
-
- private MPAct mpAct;
-
- private String ticket;
-
- public WxOpenApiImpl() {
- }
-
- /**
- * 微信开放平台接口构建
- *
- * @param mpAct 服务组件公众号信息
- * @param ticket 允许凭证
- */
- public WxOpenApiImpl(MPAct mpAct, String ticket) {
- this.mpAct = mpAct;
- this.ticket = ticket;
- }
-
- @Override
- public void setMpAct(MPAct mpAct) {
- this.mpAct = mpAct;
- }
-
- @Override
- public void setTicket(String ticket) {
- this.ticket = ticket;
- }
-
- @Override
- public String getComponentToken() throws WxRespException {
- String token = mpAct.getAccessToken();
- if (null == token
- || token.isEmpty()
- || mpAct.getExpiresIn() < System.currentTimeMillis()) {
- synchronized (this){
- refreshComponentToken();
- }
- token = mpAct.getAccessToken();
- }
- return token;
- }
-
- @Override
- public void refreshComponentToken() throws WxRespException {
- String result = "";
-
- String data = "{" +
- "\"component_appid\":\"" + mpAct.getAppId() + "\"," +
- "\"component_appsecret\":\"" + mpAct.getAppSecret() + "\"," +
- "\"component_verify_ticket\":\"" + ticket + "\"" +
- "}";
-
- try {
- result = SimpleHttpReq.post(WxApiUrl.COMPONENT_TOKEN_API,
- SimpleHttpReq.APPLICATION_JSON,
- data);
- } catch (IOException e) {
- log.error("刷新服务组件ACCESS_TOKEN时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- mpAct.createAccessToken(result);
- }
-
- @Override
- public void createPreAuthCode() throws WxRespException {
- String url = String.format(WxApiUrl.COMPONENT_API,
- "api_create_preauthcode", getComponentToken());
- String result = "";
- String data = "{" +
- "\"component_appid\":\"" + mpAct.getAppId() + "\"" +
- "}";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
- } catch (IOException e) {
- log.error("创建公众权预授权码时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- mpAct.createPreAuthCode(result);
- }
-
- @Override
- public String getPreAuthCode() throws WxRespException {
- String auth_code = mpAct.getPreAuthCode();
- if (null == auth_code
- || mpAct.getPreAuthExpiresIn() < System.currentTimeMillis()){
- synchronized (this.mpAct){
- createPreAuthCode();
- }
- }
- return auth_code;
- }
-
- @Override
- public AuthInfo queryAuth(String authCode) throws WxRespException {
- String url = String.format(WxApiUrl.COMPONENT_API, "api_query_auth", getComponentToken());
- String result = "";
- String data = "{" +
- "\"component_appid\":\"" + mpAct.getAppId() + "\" ," +
- "\" authorization_code\": \"" + authCode + "\"" +
- "}";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
- } catch (IOException e) {
- log.error("换取授权公众号信息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- AuthInfo tmp = JSON.parseObject(result, AuthInfo.class);
- return tmp;
- }
-
- @Override
- public String getAuthAccessToken(String authAppId, String authRefreshToken) throws WxRespException {
- return null;
- }
-
- @Override
- public void refreshAuthAccessToken(String authAppId, String authRefreshToken) throws WxRespException {
-
- }
-
- @Override
- public AuthInfo getAuthorizerInfo(String authAppId) throws WxRespException {
- return null;
- }
-
- @Override
- public String getAuthorizerOption(String authAppId, String optionName) throws WxRespException {
- String url = String.format(WxApiUrl.COMPONENT_API, "api_get_authorizer_option", getComponentToken());
- String result = "";
- String data = "{" +
- "\"component_appid\":\""+mpAct.getAppId()+"\"," +
- "\"authorizer_appid\": \""+authAppId+"\"," +
- "\"option_name\": \""+optionName+"\"" +
- "}";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
- } catch (IOException e) {
- log.error("获取授权公众号[{}]的选项值时出现异常!!!",authAppId);
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || result.contains("errcode")) {
- throw new WxRespException(result);
- }
-
- JSONObject tmp = JSON.parseObject(result);
- String option_value = tmp.getString("option_value");
- if (log.isInfoEnabled()) {
- String info = "获取授权公众号["+authAppId+"]";
- switch (optionName) {
- case "location_report":
- info += "地理位置上报选项成功,当前状态为: ";
- if (option_value.equals("0")) {
- info += "无上报";
- } else if (option_value.equals("1")) {
- info += "进入会话时上报";
- } else {
- info += "每5s上报";
- }
- break;
- case "voice_recognize":
- info += "语音识别选项成功,当前状态为: ";
- info += (option_value.equals("0")?"关闭":"开启");
- break;
- case "customer_service":
- info += "多客服选项成功,当前状态为: ";
- info += (option_value.equals("0")?"关闭":"开启");
- break;
- default:
- break;
- }
- log.info("{}",info);
- }
-
- return result;
- }
-
- @Override
- public void setAuthorizerOption(String authAppId, String optionName, String optionValue) throws WxRespException {
- String url = String.format(WxApiUrl.COMPONENT_API, "api_set_authorizer_option", getComponentToken());
- String result = "";
- String data = "{" +
- "\"component_appid\":\""+mpAct.getAppId()+"\"," +
- "\"authorizer_appid\": \""+authAppId+"\"," +
- "\"option_name\": \""+optionName+"\"," +
- "\"option_value\":\""+optionValue+"\"" +
- "}";
- try {
- result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
- } catch (IOException e) {
- log.error("设置授权公众号[{}]的选项值时出现异常!!!",authAppId);
- log.error(e.getLocalizedMessage(), e);
- }
-
- if (result.isEmpty()
- || !result.contains("ok")) {
- throw new WxRespException(result);
- }
-
- if (log.isInfoEnabled()) {
- String info = "设置授权公众号["+authAppId+"]";
- switch (optionName) {
- case "location_report":
- info += "地理位置上报选项成功,当前状态为: ";
- if (optionValue.equals("0")) {
- info += "无上报";
- } else if (optionValue.equals("1")) {
- info += "进入会话时上报";
- } else {
- info += "每5s上报";
- }
- break;
- case "voice_recognize":
- info += "语音识别选项成功,当前状态为: ";
- info += (optionValue.equals("0")?"关闭":"开启");
- break;
- case "customer_service":
- info += "多客服选项成功,当前状态为: ";
- info += (optionValue.equals("0")?"关闭":"开启");
- break;
- default:
- break;
- }
- log.info("{}",info);
- }
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/core/package-info.java b/src/main/java/org/elkan1788/osc/weixin/mp/core/package-info.java
deleted file mode 100644
index 62ec0b6..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/core/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 微信API实现的核心代码
- */
-package org.elkan1788.osc.weixin.mp.core;
\ No newline at end of file
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/exception/WxRespException.java b/src/main/java/org/elkan1788/osc/weixin/mp/exception/WxRespException.java
deleted file mode 100644
index da3bb46..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/exception/WxRespException.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.elkan1788.osc.weixin.mp.exception;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import org.elkan1788.osc.weixin.mp.commons.WxErrCode;
-
-/**
- * 微信响应错误异常
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/6
- * @version 1.0.0
- */
-public class WxRespException extends Exception {
-
- /**
- * 错误代码
- */
- private final int errCode;
- /**
- * 错误中文描述
- */
- private final String errMesg;
- // 临时JSON对象
- protected static JSONObject error;
-
- public WxRespException(String message) {
- super(convertMesg(message));
- this.errCode = error.getInteger("errcode");
- this.errMesg = error.getString("errmsg");
- }
-
- /**
- * 将消息转成JSON对象
- * @param message 消息
- * @return error对象
- */
- protected static String convertMesg(String message) {
- if (null == message || message.isEmpty()) {
- throw new RuntimeException("网络通讯异常,请检查!!!");
- }
- String err_desc = "";
- error = JSON.parseObject(message);
- err_desc = WxErrCode.getErrDesc(error.getInteger("errcode"));
- return err_desc;
- }
-
- /**
- * 获取错误代码
- *
- * @return errCode
- */
- public int getErrCode() {
- return errCode;
- }
-
- /**
- * 获取错误描述
- *
- * @return errmsg
- */
- public String getErrMesg() {
- return errMesg;
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/exception/package-info.java b/src/main/java/org/elkan1788/osc/weixin/mp/exception/package-info.java
deleted file mode 100644
index 8b7dd54..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/exception/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 微信API运行时的异常处理
- */
-package org.elkan1788.osc.weixin.mp.exception;
\ No newline at end of file
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/package-info.java b/src/main/java/org/elkan1788/osc/weixin/mp/package-info.java
deleted file mode 100644
index 2f73410..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * JAVA微信公平台开发SDK,没有复杂的功能,一切源于微信API,愿你会喜欢使用。
- */
-package org.elkan1788.osc.weixin.mp;
\ No newline at end of file
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/util/JsonMsgBuilder.java b/src/main/java/org/elkan1788/osc/weixin/mp/util/JsonMsgBuilder.java
deleted file mode 100644
index d259669..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/util/JsonMsgBuilder.java
+++ /dev/null
@@ -1,296 +0,0 @@
-package org.elkan1788.osc.weixin.mp.util;
-
-import org.elkan1788.osc.weixin.mp.commons.WxMsgType;
-import org.elkan1788.osc.weixin.mp.vo.Article;
-import org.elkan1788.osc.weixin.mp.vo.Article2;
-import org.elkan1788.osc.weixin.mp.vo.OutPutMsg;
-import org.elkan1788.osc.weixin.mp.vo.Template;
-
-/**
- * 创建微信客服消息
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/10
- * @version 1.0.0
- */
-public class JsonMsgBuilder {
-
- private final StringBuffer msgBuf = new StringBuffer("{");
-
- /**
- * 创建
- */
- public static JsonMsgBuilder create() {
- return new JsonMsgBuilder();
- }
-
- /**
- * 创建消息体前缀
- *
- * @param msg 客服消息实体
- */
- void msgPrefix(OutPutMsg msg) {
- msgBuf.append("\"touser\":\"")
- .append(msg.getToUserName())
- .append("\",");
- msgBuf.append("\"msgtype\":\"")
- .append(msg.getMsgType())
- .append("\",");
- }
-
- void msgSuffix(OutPutMsg msg) {
- msgBuf.append("\"msgtype\":\"").append(msg.getMsgType()).append("\"");
- }
-
- /**
- * 文本客服消息
- *
- * @param msg 客服消息实体
- */
- public JsonMsgBuilder text(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("\"text\": {");
- msgBuf.append(" \"content\":\"")
- .append(msg.getContent())
- .append("\"");
- msgBuf.append("}");
- return this;
- }
-
- /**
- * 图像客服消息
- *
- * @param msg 客服消息实体
- */
- public JsonMsgBuilder image(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("\"image\": {");
- msgBuf.append(" \"media_id\":\"")
- .append(msg.getMediaId())
- .append("\"");
- msgBuf.append("}");
- return this;
- }
-
- /**
- * 语音客服消息
- *
- * @param msg 客服消息实体
- */
- public JsonMsgBuilder voice(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("\"voice\": {");
- msgBuf.append(" \"media_id\":\"")
- .append(msg.getMediaId())
- .append("\"");
- msgBuf.append("}");
- return this;
- }
-
- /**
- * 视频客服消息
- *
- * @param msg 客服消息实体
- */
- public JsonMsgBuilder video(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("\"video\": {");
- msgBuf.append(" \"media_id\":\"")
- .append(msg.getMediaId())
- .append("\",");
- msgBuf.append(" \"thumb_media_id\":\"")
- .append(msg.getThumbMediaId())
- .append("\",");
- msgBuf.append(" \"title\":\"")
- .append(msg.getTitle())
- .append("\",");
- msgBuf.append(" \"description\":\"")
- .append(msg.getDescription())
- .append("\"");
- msgBuf.append("}");
- return this;
- }
-
- /**
- * 音乐客服消息
- *
- * @param msg 客服消息实体
- */
- public JsonMsgBuilder music(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("\"music\": {");
- msgBuf.append(" \"title\":\"")
- .append(msg.getTitle())
- .append("\",");
- msgBuf.append(" \"description\":\"")
- .append(msg.getDescription())
- .append("\",");
- msgBuf.append(" \"musicurl\":\"")
- .append(msg.getMusicUrl())
- .append("\",");
- msgBuf.append(" \"hqmusicurl\":\"")
- .append(msg.gethQMusicUrl())
- .append("\",");
- msgBuf.append(" \"thumb_media_id\":\"")
- .append(msg.getThumbMediaId())
- .append("\"");
- msgBuf.append("}");
- return this;
- }
-
- /**
- * 多图文客服消息
- *
- * @param msg 客服消息实体
- */
- public JsonMsgBuilder news(OutPutMsg msg) {
- msgPrefix(msg);
- StringBuffer arts_buf = new StringBuffer("\"articles\": [");
- StringBuffer art_buf = new StringBuffer();
- for (Article art : msg.getArticles()) {
- art_buf.setLength(0);
- art_buf.append("{");
- art_buf.append(" \"title\":\"")
- .append(art.getTitle())
- .append("\",");
- art_buf.append(" \"description\":\"")
- .append(art.getDescription())
- .append("\",");
- art_buf.append(" \"picurl\":\"")
- .append(art.getPicUrl())
- .append("\",");
- art_buf.append(" \"url\":\"")
- .append(art.getUrl());
- art_buf.append("\"},");
- }
- arts_buf.append(art_buf.substring(0, art_buf.lastIndexOf(",")));
- arts_buf.append("]");
- msgBuf.append("\"news\": {");
- msgBuf.append(arts_buf);
- msgBuf.append("}");
- return this;
- }
-
- /**
- * 模板消息
- *
- * @param openId 接收者
- * @param templateId 模板ID
- * @param topColor 顶部颜色
- * @param url 链接地址
- * @param templates 模板数据
- */
- public JsonMsgBuilder template(String openId, String templateId,
- String topColor, String url, Template... templates) {
- msgBuf.append("\"touser\":\"").append(openId).append("\",");
- msgBuf.append("\"template_id\":\"").append(templateId).append("\",");
- msgBuf.append("\"url\":\"").append(url).append("\",");
- msgBuf.append("\"topcolor\":\"").append(topColor).append("\",");
- msgBuf.append("\"data\":{");
- StringBuffer data = new StringBuffer("");
- for (Template t : templates) {
- data.append(t.templateData()).append(",");
- }
- msgBuf.append(data.substring(0, data.lastIndexOf(",")));
- msgBuf.append("}");
- return this;
- }
-
- /**
- * 上传多图文消息
- *
- * @param articles2s 图文消息
- */
- public JsonMsgBuilder uploadNews(Article2... articles2s) {
- msgBuf.append("\"articles\":[");
- StringBuffer art2_buf = new StringBuffer();
- for (Article2 art2 : articles2s) {
- art2_buf.append("{");
- art2_buf.append("\"thumb_media_id\":\"").append(art2.getMediaId()).append("\",");
- art2_buf.append("\"author\":\"").append(art2.getAuthor()).append("\",");
- art2_buf.append("\"title\":\"").append(art2.getTitle()).append("\",");
- art2_buf.append("\"content_source_url\":\"").append(art2.getSourceUrl()).append("\",");
- art2_buf.append("\"content\":\"").append(art2.getContent()).append("\",");
- art2_buf.append("\"digest\":\"").append(art2.getDigest()).append("\",");
- art2_buf.append("\"show_cover_pic\":\"").append(art2.getShowCover()).append("\"");
- art2_buf.append("},");
- }
- msgBuf.append(art2_buf.substring(0, art2_buf.lastIndexOf(",")));
- msgBuf.append("]");
- return this;
- }
-
- /**
- * 上传视频
- *
- * @param mediaId 多媒体ID
- * @param title 视频标题
- * @param description 视频描述
- */
- public JsonMsgBuilder uploadVideo(String mediaId, String title, String description) {
- msgBuf.append("\"media_id\":\"").append(mediaId).append("\",");
- msgBuf.append("\"title\":\"").append(title).append("\",");
- msgBuf.append("\"description\":\"").append(description).append("\"");
- return this;
- }
-
- /**
- * 群发消息
- *
- * @param msg 输出消息实体
- */
- public JsonMsgBuilder sendAll(OutPutMsg msg) {
- if (msg.getToUsers().isEmpty()) {
- msgBuf.append("\"filter\":{")
- .append("\"group_id\":\"")
- .append(msg.getGroupId())
- .append("\"},");
- } else {
- msgBuf.append("\"touser\":[");
- StringBuffer users_buf = new StringBuffer();
- for (String touser : msg.getToUsers()) {
- users_buf.append("\"").append(touser).append("\",");
- }
- msgBuf.append(users_buf.substring(0, users_buf.lastIndexOf(",")));
- msgBuf.append("],");
- }
-
- WxMsgType type = WxMsgType.valueOf(msg.getMsgType());
- switch (type) {
- case text:
- msgBuf.append("\"text\":{\"content\":\"").append(msg.getContent()).append("\"}");
- break;
- case image:
- msgBuf.append("\"image\":{\"media_id\":\"").append(msg.getMediaId()).append("\"}");
- break;
- case voice:
- msgBuf.append("\"voice\":{\"media_id\":\"").append(msg.getMediaId()).append("\"}");
- break;
- case mpvideo:
- msgBuf.append("\"mpvideo\":{\"media_id\":\"").append(msg.getMediaId()).append("\"}");
- break;
- case video:
- msgBuf.append("\"video\":{\"media_id\":\"")
- .append(msg.getMediaId())
- .append("\",\"title\":\"")
- .append(msg.getTitle())
- .append("\",\"description\":\"")
- .append(msg.getDescription()).append("\"}");
- break;
- case mpnews:
- msgBuf.append("\"mpnews\":{\"media_id\":\"").append(msg.getMediaId()).append("\"}");
- break;
- default:
- break;
- }
-
- msgBuf.append(",\"msgtype\":\"").append(msg.getMsgType()).append("\"");
-
- return this;
- }
-
- public String build() {
- msgBuf.append("}");
- return msgBuf.toString();
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/util/SimpleHttpReq.java b/src/main/java/org/elkan1788/osc/weixin/mp/util/SimpleHttpReq.java
deleted file mode 100644
index 7ab54c2..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/util/SimpleHttpReq.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.elkan1788.osc.weixin.mp.util;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.client.fluent.Request;
-import org.apache.http.entity.ContentType;
-import org.apache.http.entity.mime.MultipartEntityBuilder;
-import org.apache.http.entity.mime.content.FileBody;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * HTTP请求实现
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/7
- * @version 1.0.0
- */
-public class SimpleHttpReq {
-
- public static final String TEXT_PLAIN = "text/plain";
-
- public static final String TEXT_HTML = "text/html";
-
- public static final String TEXT_XML = "text/xml";
-
- public static final String APPLICATION_XML = "application/xml";
-
- public static final String APPLICATION_JSON = "application/json";
-
- private static final StrResponseHandler respHandler = new StrResponseHandler();
-
- /**
- * GET请求
- *
- * @param url 请求地址
- * @return 响应内容
- * @throws java.io.IOException
- */
- public static String get(String url) throws IOException {
- String content = Request.Get(url).execute().handleResponse(respHandler);
- return content;
- }
-
- /**
- * POST请求
- *
- * @param url 请求地址
- * @param contentType 请求体类型[text, xml, json, html]
- * @param body 请求体
- * @return 响应内容
- * @throws java.io.IOException
- */
- public static String post(String url,
- String contentType,
- String body) throws IOException {
- String content = Request.Post(url)
- .bodyString(body, ContentType.create(contentType))
- .execute().handleResponse(respHandler);
- return content;
- }
-
- /**
- * 上传文件
- *
- * @param url 请求地址
- * @param file 上传文件
- * @return 响应内容
- * @throws java.io.IOException
- */
- public static String upload(String url, File file) throws IOException {
- HttpEntity media = MultipartEntityBuilder.create()
- .addPart("media", new FileBody(file)).build();
- String content = Request.Post(url).body(media)
- .execute().handleResponse(respHandler);
- return content;
- }
-
- /**
- * 下载文件
- *
- * @param url 请求地址
- * @param file 文件保存位置
- * @throws java.io.IOException
- */
- public static void download(String url, File file) throws IOException {
- Request.Get(url).execute().saveContent(file);
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/util/StrResponseHandler.java b/src/main/java/org/elkan1788/osc/weixin/mp/util/StrResponseHandler.java
deleted file mode 100644
index c6bbbf4..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/util/StrResponseHandler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.elkan1788.osc.weixin.mp.util;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.util.EntityUtils;
-
-import java.io.IOException;
-
-/**
- * HTTP请求响应处理
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/6
- * @version 1.0.0
- */
-public class StrResponseHandler implements ResponseHandler {
-
- @Override
- public String handleResponse(HttpResponse resp)
- throws ClientProtocolException, IOException {
- int status = resp.getStatusLine().getStatusCode();
- if (status >= 200 && status < 300) {
- HttpEntity entity = resp.getEntity();
- String body = (null!= entity) ? EntityUtils.toString(entity,"UTF-8") : "";
- return body;
- } else {
- throw new ClientProtocolException("请求失败,服务器响应代码: " + status);
- }
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/util/XMLHandler.java b/src/main/java/org/elkan1788/osc/weixin/mp/util/XMLHandler.java
deleted file mode 100644
index 8f76f00..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/util/XMLHandler.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package org.elkan1788.osc.weixin.mp.util;
-
-import org.elkan1788.osc.weixin.mp.vo.PicInfo;
-import org.elkan1788.osc.weixin.mp.vo.ReceiveMsg;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.DefaultHandler2;
-import org.xml.sax.helpers.DefaultHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 微信消息内容处理器[更新JDK7特性]
- *
- * @author 凡梦星尘(senhuili@mdc.cn)
- * @since 2014/11/7
- * @version 1.0.4
- */
-public class XMLHandler extends DefaultHandler2 {
-
- private static final Logger log = LoggerFactory.getLogger(XMLHandler.class);
-
- /**
- * 消息实体定义
- */
- private ReceiveMsg msg = new ReceiveMsg();
-
- /**
- * 图片信息
- */
- private PicInfo picInfo;
-
- private List picList;
-
- /**
- * 节点属性值
- */
- private String attrVal;
-
- /**
- * 获取消息实体对象
- *
- * @return 带数据的消息实体
- */
- public ReceiveMsg getMsgVO() {
- return this.msg;
- }
-
- @Override
- public void startElement(String uri,
- String localName,
- String qName,
- Attributes attributes) throws SAXException {
-
- switch (qName) {
- case "PicList":
- this.picList = new ArrayList<>();
- break;
- case "item":
- this.picInfo = new PicInfo();
- break;
- default:
- break;
- }
- }
-
- @Override
- public void endElement(String uri,
- String localName,
- String qName) throws SAXException {
-
- if (log.isInfoEnabled()) {
- if (!"xml".equals(qName)) {
- log.info("当前节点值[{}]: {}", qName, attrVal);
- }
- }
-
- // 本想用反射实现,但耗时长,所以还是手动编码吧,累(更新JDK7特性)
- switch (qName) {
- case "MsgId":
- case "MsgID":
- msg.setMsgId(Long.valueOf(attrVal));
- break;
- case "CreateTime":
- msg.setCreateTime(Long.valueOf(attrVal));
- break;
- case "MsgType":
- msg.setMsgType(attrVal);
- break;
- case "Event":
- msg.setEvent(attrVal);
- break;
- case "ToUserName":
- msg.setToUserName(attrVal);
- break;
- case "FromUserName" :
- msg.setFromUserName(attrVal);
- break;
- case "Content":
- msg.setContent(attrVal);
- break;
- case "PicUrl":
- msg.setPicUrl(attrVal);
- break;
- case "MediaId":
- msg.setMediaId(attrVal);
- break;
- case "Format":
- msg.setFormat(attrVal);
- break;
- case "Recognition":
- msg.setRecognition(attrVal);
- break;
- case "ThumbMediaId":
- msg.setThumbMediaId(attrVal);
- break;
- case "Location_X":
- case "Latitude":
- msg.setLatitude(Double.valueOf(attrVal));
- break;
- case "Location_Y":
- case "Longitude":
- msg.setLongitude(Double.valueOf(attrVal));
- break;
- case "Scale":
- msg.setScale(Integer.parseInt(attrVal));
- break;
- case "Label":
- msg.setLabel(attrVal);
- break;
- case "Title":
- msg.setTitle(attrVal);
- break;
- case "Description":
- msg.setDescription(attrVal);
- break;
- case "Url":
- msg.setUrl(attrVal);
- break;
- case "EventKey":
- msg.setEventKey(attrVal);
- break;
- case "Ticket":
- case "ComponentVerifyTicket":
- msg.setTicket(attrVal);
- break;
- case "Precision":
- msg.setPrecision(Double.valueOf(attrVal));
- break;
- case "ScanType":
- msg.setScanType(attrVal);
- break;
- case "ScanResult":
- msg.setScanResult(attrVal);
- break;
- case "Count":
- msg.setCount(Integer.parseInt(attrVal));
- break;
- case "PicMd5Sum":
- picInfo.setPicMd5Sum(attrVal);
- break;
- case "item":
- picList.add(picInfo);
- break;
- case "PicList":
- msg.setPicList(picList);
- break;
- case "Poiname":
- msg.setPoiName(attrVal);
- break;
- case "Status":
- msg.setStatus(attrVal);
- break;
- case "TotalCount":
- msg.setTotalCnt(Integer.parseInt(attrVal));
- break;
- case "FilterCount":
- msg.setFilterCnt(Integer.parseInt(attrVal));
- break;
- case "SentCount":
- msg.setSentCnt(Integer.parseInt(attrVal));
- break;
- case "ErrorCount":
- msg.setErrorCnt(Integer.parseInt(attrVal));
- break;
- case "AppId":
- msg.setAppId(attrVal);
- break;
- case "InfoType":
- msg.setInfoType(attrVal);
- break;
- case "AuthorizerAppid":
- msg.setUnAuthAppid(attrVal);
- break;
- default:
- break;
- }
- }
-
- @Override
- public void characters(char[] ch, int start, int length) throws SAXException {
- this.attrVal = new String(ch, start, length);
- }
-
- /**
- * 清除当前VO对象缓存数据
- */
- public void clear() {
- this.picInfo = null;
- this.msg = null;
- this.msg = new ReceiveMsg();
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/util/XmlMsgBuilder.java b/src/main/java/org/elkan1788/osc/weixin/mp/util/XmlMsgBuilder.java
deleted file mode 100644
index 1918b46..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/util/XmlMsgBuilder.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package org.elkan1788.osc.weixin.mp.util;
-
-import org.elkan1788.osc.weixin.mp.vo.Article;
-import org.elkan1788.osc.weixin.mp.vo.OutPutMsg;
-
-/**
- * 创建微信被动消息回复
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/9
- * @version 1.0.0
- */
-public class XmlMsgBuilder {
-
- private final StringBuffer msgBuf = new StringBuffer("\n");;
-
- /**
- * 创建
- */
- public static XmlMsgBuilder create() {
- return new XmlMsgBuilder();
- }
-
- /**
- * 创建消息体前缀
- *
- * @param msg 输出消息实体
- */
- void msgPrefix(OutPutMsg msg) {
- msgBuf.append("\n");
- msgBuf.append("\n");
- msgBuf.append("")
- .append(msg.getCreateTime())
- .append("\n");
- msgBuf.append("\n");
- }
-
- /**
- * 被动文本消息
- * @param msg 输出消息实体
- */
- public XmlMsgBuilder text(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("\n");
- return this;
- }
-
- /**
- * 被动图像消息
- *
- * @param msg 输出消息实体
- */
- public XmlMsgBuilder image(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("");
- msgBuf.append("\n");
- msgBuf.append("");
- return this;
- }
-
- /**
- * 被动语音消息
- *
- * @param msg 输出消息实体
- */
- public XmlMsgBuilder vioce(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("");
- msgBuf.append("\n");
- msgBuf.append("\n");
- return this;
- }
-
- /**
- * 被动视频消息
- *
- * @param msg 输出消息实体
- */
- public XmlMsgBuilder video(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("\n");
- return this;
- }
-
- /**
- * 被动音乐消息
- *
- * @param msg 输出消息实体
- */
- public XmlMsgBuilder music(OutPutMsg msg) {
- msgPrefix(msg);
- msgBuf.append("");
- msgBuf.append("\n");
- msgBuf.append("\n");
- msgBuf.append("\n");
- msgBuf.append("\n");
- msgBuf.append("\n");
- msgBuf.append("\n");
- return this;
- }
-
- /**
- * 被动多图文消息
- *
- * @param msg 输出消息实体
- */
- public XmlMsgBuilder news(OutPutMsg msg) {
- msgPrefix(msg);
- StringBuffer arts_buf = new StringBuffer("\n");
- StringBuffer item_buf = new StringBuffer();
- for (Article art : msg.getArticles()) {
- item_buf.setLength(0);
- item_buf.append("- \n");
- item_buf.append("\n");
- item_buf.append("\n");
- item_buf.append("\n");
- item_buf.append("\n");
- item_buf.append("
\n");
- arts_buf.append(item_buf);
- }
- arts_buf.append("\n");
- msgPrefix(msg);
- msgBuf.append("")
- .append(msg.getArticles().size())
- .append("\n");
- msgBuf.append(arts_buf);
- return this;
- }
-
- /**
- * AES加密信息
- *
- * @param xml 消息原文
- * @param msgSignature 消息签名
- * @param timeStamp 时间戳
- * @param nonce 随机字符
- */
- public String encrypt(String xml, String msgSignature,
- String timeStamp, String nonce) {
-
- msgBuf.setLength(0);
- msgBuf.append("\n");
- msgBuf.append("\n");
- msgBuf.append("\n");
- msgBuf.append("")
- .append(timeStamp)
- .append("\n");
- msgBuf.append("\n");
- msgBuf.append("");
- return msgBuf.toString();
- }
-
- /**
- * 创建回复消息
- *
- * @return 回复消息
- */
- public String build() {
- msgBuf.append("");
- return msgBuf.toString();
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/util/package-info.java b/src/main/java/org/elkan1788/osc/weixin/mp/util/package-info.java
deleted file mode 100644
index b30c8a4..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/util/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 微信API常用的工具类
- */
-package org.elkan1788.osc.weixin.mp.util;
\ No newline at end of file
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/Article2.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/Article2.java
deleted file mode 100644
index 8d65fd9..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/Article2.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-/**
- * 高级群发消息的多图文
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/11
- * @version 1.0.0
- */
-public class Article2 {
-
- /**
- * 缩略图的media_id
- */
- private String mediaId;
- /**
- * 图文消息作者
- */
- private String author;
- /**
- * 标题
- */
- private String title;
- /**
- * 图文消息页面点击“阅读原文”后的页面
- */
- private String sourceUrl;
- /**
- * 图文消息页面的内容,支持HTML标签
- */
- private String content;
- /**
- * 图文消息的描述
- */
- private String digest;
- /**
- * 是否显示封面,1为显示,0为不显示
- */
- private int showCover;
-
- public String getMediaId() {
- return mediaId;
- }
-
- public void setMediaId(String mediaId) {
- this.mediaId = mediaId;
- }
-
- public String getAuthor() {
- return author;
- }
-
- public void setAuthor(String author) {
- this.author = author;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getSourceUrl() {
- return sourceUrl;
- }
-
- public void setSourceUrl(String sourceUrl) {
- this.sourceUrl = sourceUrl;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
- public String getDigest() {
- return digest;
- }
-
- public void setDigest(String digest) {
- this.digest = digest;
- }
-
- public int getShowCover() {
- return showCover;
- }
-
- public void setShowCover(int showCover) {
- this.showCover = showCover;
- }
-
- @Override
- public String toString() {
- return "Article2{" +
- "mediaId='" + mediaId + '\'' +
- ", author='" + author + '\'' +
- ", title='" + title + '\'' +
- ", sourceUrl='" + sourceUrl + '\'' +
- ", content='" + content + '\'' +
- ", digest='" + digest + '\'' +
- ", showCover=" + showCover +
- '}';
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/Articles2.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/Articles2.java
deleted file mode 100644
index 89c3133..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/Articles2.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-/**
- * 高级群发消息的多图文
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/11
- * @version 1.0.0
- */
-public class Articles2 {
-
- /**
- * 缩略图的media_id
- */
- private String mediaId;
- /**
- * 图文消息作者
- */
- private String author;
- /**
- * 标题
- */
- private String title;
- /**
- * 图文消息页面点击“阅读原文”后的页面
- */
- private String sourceUrl;
- /**
- * 图文消息页面的内容,支持HTML标签
- */
- private String content;
- /**
- * 图文消息的描述
- */
- private String digest;
- /**
- * 是否显示封面,1为显示,0为不显示
- */
- private int showCover;
-
- public String getMediaId() {
- return mediaId;
- }
-
- public void setMediaId(String mediaId) {
- this.mediaId = mediaId;
- }
-
- public String getAuthor() {
- return author;
- }
-
- public void setAuthor(String author) {
- this.author = author;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getSourceUrl() {
- return sourceUrl;
- }
-
- public void setSourceUrl(String sourceUrl) {
- this.sourceUrl = sourceUrl;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
- public String getDigest() {
- return digest;
- }
-
- public void setDigest(String digest) {
- this.digest = digest;
- }
-
- public int getShowCover() {
- return showCover;
- }
-
- public void setShowCover(int showCover) {
- this.showCover = showCover;
- }
-
- @Override
- public String toString() {
- return "Articles2{" +
- "mediaId='" + mediaId + '\'' +
- ", author='" + author + '\'' +
- ", title='" + title + '\'' +
- ", sourceUrl='" + sourceUrl + '\'' +
- ", content='" + content + '\'' +
- ", digest='" + digest + '\'' +
- ", showCover=" + showCover +
- '}';
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/AuthInfo.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/AuthInfo.java
deleted file mode 100644
index faa6b63..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/AuthInfo.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-import com.alibaba.fastjson.annotation.JSONField;
-
-import java.util.List;
-
-/**
- * 微信开放平台授权公众号信息
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2015/1/8
- */
-public class AuthInfo {
- /**
- * 授权方昵称
- */
- @JSONField(name = "nick_name")
- private String nickName;
- /**
- * 授权方appid
- */
- @JSONField(name = "authorizer_appid")
- private String appId;
- /**
- * 授权方令牌(在授权的公众号具备API权限时才有此返回值)
- */
- @JSONField(name = "authorizer_access_token")
- private String accessToken;
- /**
- * 有效期(在授权的公众号具备API权限时才有此返回值)
- */
- @JSONField(name = "expires_in")
- private long expiresIn;
- /**
- * 授权方头像
- */
- @JSONField(name = "head_img")
- private String headImg;
- /**
- * 授权方公众号类型
- * 0代表订阅号
- * 1代表由历史老帐号升级后的订阅号
- * 2代表服务号
- */
- @JSONField(name = "service_type_info")
- private String serTypeInfo;
- /**
- * 授权方认证类型
- * -1代表未认证
- * 0代表微信认证
- * 1代表新浪微博认证
- * 2代表腾讯微博认证
- * 3代表已资质认证通过但还未通过名称认证
- * 4代表已资质认证通过、还未通过名称认证
- * 但通过了新浪微博认证
- * 5代表已资质认证通过、还未通过名称认证但通过了腾讯微博认证
- */
- @JSONField(name = "verify_type_info")
- private String verTypeInfo;
- /**
- * 授权方公众号的原始ID
- */
- @JSONField(name = "user_name")
- private String mpId;
- /**
- * 授权方公众号所设置的微信号可能为空
- */
- @JSONField(name = "alias")
- private String alias;
- /**
- * 刷新令牌(在授权的公众号具备API权限时才有此返回值)
- * 刷新令牌主要用于公众号服务获取和刷新已授权用户的access_token
- * 只会在授权时刻提供请妥善保存。 一旦丢失只能让用户重新授权
- * 才能再次拿到新的刷新令牌
- */
- @JSONField(name = "authorizer_refresh_token")
- private String refreshToken;
-
- /**
- * 公众号授权给开发者的权限集列表
- */
- @JSONField(name = "func_info")
- private List funs;
-
- public String getNickName() {
- return nickName;
- }
-
- public void setNickName(String nickName) {
- this.nickName = nickName;
- }
-
- public String getAppId() {
- return appId;
- }
-
- public void setAppId(String appId) {
- this.appId = appId;
- }
-
- public String getAccessToken() {
- return accessToken;
- }
-
- public void setAccessToken(String accessToken) {
- this.accessToken = accessToken;
- }
-
- public long getExpiresIn() {
- return expiresIn;
- }
-
- public void setExpiresIn(long expiresIn) {
- this.expiresIn = expiresIn;
- }
-
- public String getHeadImg() {
- return headImg;
- }
-
- public void setHeadImg(String headImg) {
- this.headImg = headImg;
- }
-
- public String getSerTypeInfo() {
- return serTypeInfo;
- }
-
- public void setSerTypeInfo(String serTypeInfo) {
- this.serTypeInfo = serTypeInfo;
- }
-
- public String getVerTypeInfo() {
- return verTypeInfo;
- }
-
- public void setVerTypeInfo(String verTypeInfo) {
- this.verTypeInfo = verTypeInfo;
- }
-
- public String getMpId() {
- return mpId;
- }
-
- public void setMpId(String mpId) {
- this.mpId = mpId;
- }
-
- public String getAlias() {
- return alias;
- }
-
- public void setAlias(String alias) {
- this.alias = alias;
- }
-
- public String getRefreshToken() {
- return refreshToken;
- }
-
- public void setRefreshToken(String refreshToken) {
- this.refreshToken = refreshToken;
- }
-
- public List getFuns() {
- return funs;
- }
-
- public void setFuns(List funs) {
- this.funs = funs;
- }
-
- @Override
- public String toString() {
- return "AuthInfo{" +
- "nickName='" + nickName + '\'' +
- ", appId='" + appId + '\'' +
- ", accessToken='" + accessToken + '\'' +
- ", expiresIn='" + expiresIn + '\'' +
- ", headImg='" + headImg + '\'' +
- ", serTypeInfo='" + serTypeInfo + '\'' +
- ", verTypeInfo='" + verTypeInfo + '\'' +
- ", mpId='" + mpId + '\'' +
- ", alias='" + alias + '\'' +
- ", refreshToken='" + refreshToken + '\'' +
- ", funs=" + String.valueOf(funs) +
- '}';
- }
-
- /**
- * 公众号授权给开发者的权限集
- */
- public class FunctionInfo {
-
- /**
- * 公众号授权给开发者的权限集列表[1-9]分别代表
- * 1.消息与菜单权限集
- * 2.用户管理权限集
- * 3.帐号管理权限集
- * 4.网页授权权限集
- * 5.微信小店权限集
- * 6.多客服权限集
- * 7.业务通知权限集
- * 8.微信卡券权限集
- * 9.微信扫一扫权限集
- */
- @JSONField(name = "funcscope_category")
- private String category;
-
- public String getCategory() {
- return category;
- }
-
- public void setCategory(String category) {
- this.category = category;
- }
-
- @Override
- public String toString() {
- return "FunctionInfo{" +
- "category='" + category + '\'' +
- '}';
- }
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/BaseMsg.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/BaseMsg.java
deleted file mode 100644
index 00300e4..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/BaseMsg.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-/**
- * 微信消息实体基类
- *
- * @author 凡梦星尘(senhuili@mdc.cn)
- * @since 2014/11/7
- * @version 1.0.0
- */
-public abstract class BaseMsg {
-
- /**
- * 消息唯一ID(64位整型)
- */
- protected long msgId;
-
- /**
- * 消息创建时间 (整型)
- */
- protected long createTime;
-
- /**
- * 消息类型(text, image, video, voice, location, link,event)
- */
- protected String msgType;
-
- /**
- * 消息事件:
- * subscribe:订阅
- * unsubscribe:取消订阅
- * SCAN:关注后场景扫描
- * LOCATION:主动上传位置
- * VIEW,CLICK:菜单点击事件
- * TEMPLATESENDJOBFINISH:模板消息推送
- */
- protected String event;
-
- /**
- * 接收消息用户ID
- */
- protected String toUserName;
-
- /**
- * 消息来自用户ID
- */
- protected String fromUserName;
-
- /**
- * 文本消息内容
- */
- protected String content;
-
- /**
- * 多媒体消息ID(微信服务器有效时间为3天)
- */
- protected String mediaId;
-
- /**
- * 链接,文章消息标题
- */
- protected String title;
-
- /**
- * 详细描述
- */
- protected String description;
-
- /**
- * 视频消息缩略图的媒体id
- */
- protected String thumbMediaId;
- public long getMsgId() {
- return msgId;
- }
-
- public void setMsgId(long msgId) {
- this.msgId = msgId;
- }
-
- public long getCreateTime() {
- return createTime;
- }
-
- public void setCreateTime(long createTime) {
- this.createTime = createTime;
- }
-
- public String getMsgType() {
- return msgType;
- }
-
- public void setMsgType(String msgType) {
- this.msgType = msgType;
- }
-
- public String getEvent() {
- return event;
- }
-
- public void setEvent(String event) {
- this.event = event;
- }
-
- public String getToUserName() {
- return toUserName;
- }
-
- public void setToUserName(String toUserName) {
- this.toUserName = toUserName;
- }
-
- public String getFromUserName() {
- return fromUserName;
- }
-
- public void setFromUserName(String fromUserName) {
- this.fromUserName = fromUserName;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
- public String getMediaId() {
- return mediaId;
- }
-
- public void setMediaId(String mediaId) {
- this.mediaId = mediaId;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getThumbMediaId() {
- return thumbMediaId;
- }
-
- public void setThumbMediaId(String thumbMediaId) {
- this.thumbMediaId = thumbMediaId;
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/MPAct.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/MPAct.java
deleted file mode 100644
index 2095769..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/MPAct.java
+++ /dev/null
@@ -1,264 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-
-/**
- * 微信公众号信息
- *
- * @author 凡梦星尘(senhuili@mdc.cn)
- * @since 2014/11/8
- * @version 1.0.2
- */
-public class MPAct {
-
- /**
- * 公众号原始ID
- */
- private String mpId;
-
- /**
- * 公众号昵称
- */
- private String nickName;
-
- /**
- * 应用Id
- */
- private String appId;
-
- /**
- * 应用密钥
- */
- private String appSecret;
-
- /**
- * 令牌
- */
- private String token;
-
- /**
- * AES安全加密密钥
- */
- private String AESKey;
-
- /**
- * 公众号类型
- * D:订阅号
- * E:企业号
- * S:服务号
- *
- */
- private String mpType;
-
- /**
- * 是否认证
- */
- private boolean pass;
-
- /**
- * 应用凭证
- */
- private String accessToken;
-
- /**
- * 凭证有效时间(秒)
- */
- private long expiresIn;
-
- /**
- * 预授权码
- */
- private String preAuthCode;
-
- /**
- * 预授权码有效时间(秒)
- */
- private long preAuthExpiresIn;
-
- /**
- * JSAPI凭证
- */
- private String jsTicket;
-
- /**
- * JSAPI凭证有效时间(秒)
- */
- private long jsExpiresIn;
-
- public String getMpId() {
- return mpId;
- }
-
- public void setMpId(String mpId) {
- this.mpId = mpId;
- }
-
- public String getNickName() {
- return nickName;
- }
-
- public void setNickName(String nickName) {
- this.nickName = nickName;
- }
-
- public String getAppId() {
- return appId;
- }
-
- public void setAppId(String appId) {
- this.appId = appId;
- }
-
- public String getAppSecret() {
- return appSecret;
- }
-
- public void setAppSecret(String appSecret) {
- this.appSecret = appSecret;
- }
-
- public String getToken() {
- return token;
- }
-
- public void setToken(String token) {
- this.token = token;
- }
-
- public String getAESKey() {
- return AESKey;
- }
-
- public void setAESKey(String AESKey) {
- this.AESKey = AESKey;
- }
-
- public String getMpType() {
- return mpType;
- }
-
- public void setMpType(String mpType) {
- this.mpType = mpType;
- }
-
- public boolean isPass() {
- return pass;
- }
-
- public void setPass(boolean pass) {
- this.pass = pass;
- }
-
- public String getAccessToken() {
- return accessToken;
- }
-
- public void setAccessToken(String accessToken) {
- this.accessToken = accessToken;
- }
-
- public long getExpiresIn() {
- return expiresIn;
- }
-
- public void setExpiresIn(long expiresIn) {
- this.expiresIn = expiresIn;
- }
-
- /**
- * 解析微信服务器返回消息生成高级API或服务的凭证
- *
- * @param result 返回消息
- */
- public void createAccessToken(String result) {
-
- JSONObject tmp = JSON.parseObject(result);
- if (tmp.containsKey("access_token")) {
- setAccessToken(tmp.getString("access_token"));
- } else {
- setAccessToken(tmp.getString("component_access_token"));
- }
- long lose_time = (tmp.getLong("expires_in")-60) * 1000
- + System.currentTimeMillis();
- setExpiresIn(lose_time);
- }
-
- public String getPreAuthCode() {
- return preAuthCode;
- }
-
- public void setPreAuthCode(String preAuthCode) {
- this.preAuthCode = preAuthCode;
- }
-
- public long getPreAuthExpiresIn() {
- return preAuthExpiresIn;
- }
-
- public void setPreAuthExpiresIn(long preAuthExpiresIn) {
- this.preAuthExpiresIn = preAuthExpiresIn;
- }
-
- /**
- * 解析微信服务器返回消息生成预授权码
- *
- * @param result 返回消息
- */
- public void createPreAuthCode(String result) {
- JSONObject tmp = JSONObject.parseObject(result);
- setPreAuthCode(tmp.getString("pre_auth_code"));
- long lose_time = (tmp.getLong("expires_in")-60) * 1000
- + System.currentTimeMillis();
- setPreAuthExpiresIn(lose_time);
- }
-
- public String getJsTicket() {
- return jsTicket;
- }
-
- public void setJsTicket(String jsTicket) {
- this.jsTicket = jsTicket;
- }
-
- public long getJsExpiresIn() {
- return jsExpiresIn;
- }
-
- public void setJsExpiresIn(long jsExpiresIn) {
- this.jsExpiresIn = jsExpiresIn;
- }
-
- /**
- * 解析微信服务器返回消息生成JSTICKET
- *
- * @param result 返回消息
- */
- public void createJsTicket(String result) {
- JSONObject tmp = JSONObject.parseObject(result);
- setJsTicket(tmp.getString("ticket"));
- long lose_time = (tmp.getLong("expires_in")-60) * 1000
- + System.currentTimeMillis();
- setJsExpiresIn(lose_time);
- }
-
- @Override
- public String toString() {
- return "MPAct{" +
- "mpId='" + mpId + '\'' +
- ", nickName='" + nickName + '\'' +
- ", appId='" + appId + '\'' +
- ", appSecret='" + appSecret + '\'' +
- ", token='" + token + '\'' +
- ", AESKey='" + AESKey + '\'' +
- ", mpType='" + mpType + '\'' +
- ", pass=" + pass +
- ", accessToken='" + accessToken + '\'' +
- ", expiresIn=" + expiresIn +
- ", preAuthCode='" + preAuthCode + '\'' +
- ", preAuthExpiresIn=" + preAuthExpiresIn +
- ", jsTicket='" + jsTicket + '\'' +
- ", jsExpiresIn=" + jsExpiresIn +
- '}';
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/Menu.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/Menu.java
deleted file mode 100644
index 6337d62..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/Menu.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-import com.alibaba.fastjson.annotation.JSONField;
-
-import java.util.List;
-
-/**
- * 微信自定义菜单实体
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/7
- * @version 1.0.0
- */
-public class Menu {
-
- public static final String CLICK = "click";
- public static final String VIEW = "view";
- public static final String SCANCODE_PUSH = "scancode_push";
- public static final String SCANCODE_WAITMSG = "scancode_waitmsg";
- public static final String PIC_SYSPHOTO = "pic_sysphoto";
- public static final String PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
- public static final String PIC_WEIXIN = "pic_weixin";
- public static final String LOCATION_SELECT = "location_select";
-
- /**
- * 菜单标题,不超过16个字节,子菜单不超过40个字节
- */
- private String name;
-
- /**
- * 菜单的响应动作类型
- * click:点击推事件
- * view:跳转URL
- * scancode_push:扫码推事件
- * scancode_waitmsg:扫码推事件
- * pic_sysphoto:弹出系统拍照发图
- * pic_photo_or_album:弹出拍照或者相册发
- * pic_weixin:弹出微信相册发图器
- * location_select:弹出地理位置选择器
- *
- */
- private String type;
-
- /**
- * 点击类型菜单KEY值,用于消息接口推送,不超过128字节
- */
- private String key;
-
- /**
- * 网页链接,用户点击菜单可打开链接,不超过256字节
- */
- private String url;
-
- /**
- * 二级菜单
- */
- @JSONField(name = "sub_button")
- private List subButtons;
-
- public Menu() {
- }
-
- public Menu(String name) {
- this.name = name;
- }
-
- /**
- * 构造函数
- *
- * @param name 菜单名称
- * @param type 菜单类型
- * @param val KEY值/URL
- */
- public Menu(String name, String type, String val) {
- this.name = name;
- this.type = type;
- if (VIEW.equals(type)) {
- this.url = val;
- } else {
- this.key = val;
- }
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
- public String getKey() {
- return key;
- }
-
- public void setKey(String key) {
- this.key = key;
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public List getSubButtons() {
- return subButtons;
- }
-
- public void setSubButtons(List subButtons) {
- this.subButtons = subButtons;
- }
-
- @Override
- public String toString() {
- return "Menu{" +
- "name='" + name + '\'' +
- ", type='" + type + '\'' +
- ", key='" + key + '\'' +
- ", url='" + url + '\'' +
- ", subButtons=" + subButtons +
- '}';
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/OutPutMsg.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/OutPutMsg.java
deleted file mode 100644
index 094c514..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/OutPutMsg.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 输出消息实体
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/7
- * @version 1.0.0
- */
-public class OutPutMsg extends BaseMsg {
-
- /**
- * 音乐链接
- */
- private String musicUrl;
-
- /**
- * 高质量音乐链接
- */
- private String hQMusicUrl;
-
- /**
- * 多图文消息
- */
- private List articles = new ArrayList<>();
-
- /**
- * 用于群发消息中的分组ID
- */
- private String groupId;
-
- /**
- * 用于群发消息中的用户ID,最多支持1000个
- */
- private List toUsers = new ArrayList<>();
-
- /**
- * 自定义回复内容
- * 微信太坑人,在开放平台中,LOCATION事件居然可以回复消息
- * 因此为后续扩展考虑,增加此字段
- */
- private String customReply;
-
- /**
- * 带基础参数的构造函数
- * @param fromUserName 微信用户openId
- * @param toUserName 微信公众号原始ID
- * @param msgType 消息类型
- */
- public OutPutMsg(String fromUserName, String toUserName, String msgType) {
- this.fromUserName = toUserName;
- this.toUserName = fromUserName;
- this.msgType = msgType;
- this.createTime = System.currentTimeMillis() / 1000;
- }
-
- public OutPutMsg(ReceiveMsg rm) {
- this.fromUserName = rm.getToUserName();
- this.toUserName = rm.getFromUserName();
- this.createTime = System.currentTimeMillis() / 1000;
- }
-
- public OutPutMsg() {
- this.createTime = System.currentTimeMillis() / 1000;
- }
-
- public String getMusicUrl() {
- return musicUrl;
- }
-
- public void setMusicUrl(String musicUrl) {
- this.musicUrl = musicUrl;
- }
-
- public String gethQMusicUrl() {
- return hQMusicUrl;
- }
-
- public void sethQMusicUrl(String hQMusicUrl) {
- this.hQMusicUrl = hQMusicUrl;
- }
-
- public List getArticles() {
-
- return articles;
- }
-
- public void setArticles(List articles) {
- if (null != articles
- && articles.size() > 10) {
- this.articles = articles.subList(0, 10);
- } else {
- this.articles = articles;
- }
- }
-
- public String getGroupId() {
- return groupId;
- }
-
- public void setGroupId(String groupId) {
- this.groupId = groupId;
- }
-
- public List getToUsers() {
- return toUsers;
- }
-
- public void setToUsers(List toUsers) {
- this.toUsers = toUsers;
- }
-
- public String getCustomReply() {
- return customReply;
- }
-
- public void setCustomReply(String customReply) {
- this.customReply = customReply;
- }
-
- @Override
- public String toString() {
- return "OutPutMsg{" +
- "msgId='" + msgId + '\'' +
- ", createTime='" + createTime + '\'' +
- ", toUserName='" + toUserName + '\'' +
- ", fromUserName='" + fromUserName + '\'' +
- ", msgType='" + msgType + '\'' +
- ", event='" + event + '\'' +
- ", content='" + content + '\'' +
- ", mediaId='" + mediaId + '\'' +
- ", thumbMediaId='" + thumbMediaId + '\'' +
- ", title='" + title + '\'' +
- ", description='" + description + '\'' +
- ", musicUrl='" + musicUrl + '\'' +
- ", hQMusicUrl='" + hQMusicUrl + '\'' +
- ", groupId='" + groupId + '\'' +
- ", articles=" + ((null==articles) ? 0 : articles.size()) +
- ", toUsers=" + ((null==toUsers) ? 0 : toUsers.size()) +
- ", customReply=" + customReply +
- "} " + super.toString();
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/PicInfo.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/PicInfo.java
deleted file mode 100644
index 4c3c755..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/PicInfo.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-/**
- * 弹出微信相册发图器或拍照的照片信息
- *
- * @author 凡梦星尘(senhuili@mdc.cn)
- * @since 2015/1/7
- * @version 1.0.0
- */
-public class PicInfo {
-
- /**
- * 图片的MD5值,开发者若需要,可用于验证接收到图片
- */
- private String picMd5Sum;
-
- public String getPicMd5Sum() {
- return picMd5Sum;
- }
-
- public void setPicMd5Sum(String picMd5Sum) {
- this.picMd5Sum = picMd5Sum;
- }
-
- @Override
- public String toString() {
- return "PicInfo{" +
- "picMd5Sum='" + picMd5Sum + '\'' +
- '}';
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/ReceiveMsg.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/ReceiveMsg.java
deleted file mode 100644
index 8ebf26f..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/ReceiveMsg.java
+++ /dev/null
@@ -1,376 +0,0 @@
-package org.elkan1788.osc.weixin.mp.vo;
-
-import java.util.List;
-
-/**
- * 接收消息实体
- *
- * @author 凡梦星尘(senhuili@mdc.cn)
- * @since 2014/11/7
- * @version 1.0.0
- */
-public class ReceiveMsg extends BaseMsg {
-
- /**
- * 图片链接
- */
- private String picUrl;
-
- /**
- * 音频格式(arm,wav,mp3)
- */
- private String format;
-
- /**
- * 语音识别结果,UTF-8编码
- */
- private String recognition;
-
- /**
- * 地图缩放大小
- */
- private int scale;
-
- /**
- * 地理位置信息
- */
- private String label;
-
- /**
- * 链接地址
- */
- private String url;
-
- /**
- * 事件KEY值
- */
- private String eventKey;
-
- /**
- * 二维码的ticket或是开放平台中服务方的ComponentVerifyTicket
- */
- private String ticket;
-
- /**
- * 地理位置纬度
- */
- private double latitude;
-
- /**
- * 地理位置经度
- */
- private double longitude;
-
- /**
- * 地理位置精度
- */
- private double precision;
-
- /**
- * 扫描类型,一般是qcode
- */
- private String scanType;
-
- /**
- * 扫描结果,即二维码对应的字符串信息
- */
- private String scanResult;
-
- /**
- * 发送的图片数量
- */
- private int count;
-
- /**
- * 发送的图片列表
- */
- private List picList;
-
- /**
- * 朋友圈POI的名字,可能为空
- */
- private String poiName;
-
- /**
- * 微信发送消息状态(模板消息,群发消息)
- * 群发的结构,为“send success”或“send fail”或“err(num)”。但send success时,
- * 也有可能因用户拒收公众号的消息、系统错误等原因造成少量用户接收失败。err(num)是审核失败的具体原因,
- * 可能的情况如下:
- * err(10001), //涉嫌广告
- * err(20001), //涉嫌政治
- * err(20004), //涉嫌社会
- * err(20002), //涉嫌色情
- * err(20006), //涉嫌违法犯罪
- * err(20008), //涉嫌欺诈
- * err(20013), //涉嫌版权
- * err(22000), //涉嫌互推(互相宣传)
- * err(21000), //涉嫌其他
- */
- private String status;
-
- /**
- * group_id下粉丝数;或者openid_list中的粉丝数
- */
- private int totalCnt;
-
- /**
- * 过滤(过滤是指特定地区、性别的过滤、用户设置拒收的过滤,
- * 用户接收已超4条的过滤)后,准备发送的粉丝数,原则上,
- * FilterCount = SentCount + ErrorCount
- */
- private int filterCnt;
-
- /**
- * 发送成功的粉丝数
- */
- private int sentCnt;
-
- /**
- * 发送失败的粉丝数
- */
- private int errorCnt;
-
- /**
- * 服务appid
- */
- private String appId;
-
- /**
- * none,代表该消息推送给服务
- * unauthorized,代表公众号取消授权
- */
- private String infoType;
-
- /**
- * 取消授权的公众号
- */
- private String unAuthAppid;
-
- public String getPicUrl() {
- return picUrl;
- }
-
- public void setPicUrl(String picUrl) {
- this.picUrl = picUrl;
- }
-
- public String getFormat() {
- return format;
- }
-
- public void setFormat(String format) {
- this.format = format;
- }
-
- public String getRecognition() {
- return recognition;
- }
-
- public void setRecognition(String recognition) {
- this.recognition = recognition;
- }
-
- public int getScale() {
- return scale;
- }
-
- public void setScale(int scale) {
- this.scale = scale;
- }
-
- public String getLabel() {
- return label;
- }
-
- public void setLabel(String label) {
- this.label = label;
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public String getEventKey() {
- return eventKey;
- }
-
- public void setEventKey(String eventKey) {
- this.eventKey = eventKey;
- }
-
- public String getTicket() {
- return ticket;
- }
-
- public void setTicket(String ticket) {
- this.ticket = ticket;
- }
-
- public double getLatitude() {
- return latitude;
- }
-
- public void setLatitude(double latitude) {
- this.latitude = latitude;
- }
-
- public double getLongitude() {
- return longitude;
- }
-
- public void setLongitude(double longitude) {
- this.longitude = longitude;
- }
-
- public double getPrecision() {
- return precision;
- }
-
- public void setPrecision(double precision) {
- this.precision = precision;
- }
-
- public String getScanType() {
- return scanType;
- }
-
- public void setScanType(String scanType) {
- this.scanType = scanType;
- }
-
- public String getScanResult() {
- return scanResult;
- }
-
- public void setScanResult(String scanResult) {
- this.scanResult = scanResult;
- }
-
- public int getCount() {
- return count;
- }
-
- public void setCount(int count) {
- this.count = count;
- }
-
- public List getPicList() {
- return picList;
- }
-
- public void setPicList(List picList) {
- this.picList = picList;
- }
-
- public String getPoiName() {
- return poiName;
- }
-
- public void setPoiName(String poiName) {
- this.poiName = poiName;
- }
-
- public String getStatus() {
- return status;
- }
-
- public void setStatus(String status) {
- this.status = status;
- }
-
- public int getTotalCnt() {
- return totalCnt;
- }
-
- public void setTotalCnt(int totalCnt) {
- this.totalCnt = totalCnt;
- }
-
- public int getFilterCnt() {
- return filterCnt;
- }
-
- public void setFilterCnt(int filterCnt) {
- this.filterCnt = filterCnt;
- }
-
- public int getSentCnt() {
- return sentCnt;
- }
-
- public void setSentCnt(int sentCnt) {
- this.sentCnt = sentCnt;
- }
-
- public int getErrorCnt() {
- return errorCnt;
- }
-
- public void setErrorCnt(int errorCnt) {
- this.errorCnt = errorCnt;
- }
-
- public String getAppId() {
- return appId;
- }
-
- public void setAppId(String appId) {
- this.appId = appId;
- }
-
- public String getInfoType() {
- return infoType;
- }
-
- public void setInfoType(String infoType) {
- this.infoType = infoType;
- }
-
- public String getUnAuthAppid() {
- return unAuthAppid;
- }
-
- public void setUnAuthAppid(String unAuthAppid) {
- this.unAuthAppid = unAuthAppid;
- }
-
- @Override
- public String toString() {
- return "ReceiveMsg{" +
- "msgId='" + msgId + '\'' +
- ", createTime='" + createTime + '\'' +
- ", toUserName='" + toUserName + '\'' +
- ", fromUserName='" + fromUserName + '\'' +
- ", msgType='" + msgType + '\'' +
- ", event='" + event + '\'' +
- ", content='" + content + '\'' +
- ", mediaId='" + mediaId + '\'' +
- ", thumbMediaId='" + thumbMediaId + '\'' +
- ", title='" + title + '\'' +
- ", description='" + description + '\'' +
- ", picUrl='" + picUrl + '\'' +
- ", format='" + format + '\'' +
- ", recognition='" + recognition + '\'' +
- ", scale=" + scale +
- ", label='" + label + '\'' +
- ", url='" + url + '\'' +
- ", eventKey='" + eventKey + '\'' +
- ", ticket='" + ticket + '\'' +
- ", latitude=" + latitude +
- ", longitude=" + longitude +
- ", precision=" + precision +
- ", status='" + status + '\'' +
- ", totalCnt='" + totalCnt + '\'' +
- ", filterCnt='" + filterCnt + '\'' +
- ", sentCnt='" + sentCnt + '\'' +
- ", errorCnt='" + errorCnt + '\'' +
- ", appId='" + appId + '\'' +
- ", infoType='" + infoType + '\'' +
- ", unAuthAppid='" + unAuthAppid + '\'' +
- "} ";
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/vo/package-info.java b/src/main/java/org/elkan1788/osc/weixin/mp/vo/package-info.java
deleted file mode 100644
index c787e6a..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/vo/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 微信API对应的实体对象
- */
-package org.elkan1788.osc.weixin.mp.vo;
\ No newline at end of file
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/web/WxServletSupport.java b/src/main/java/org/elkan1788/osc/weixin/mp/web/WxServletSupport.java
deleted file mode 100644
index b90217d..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/web/WxServletSupport.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.elkan1788.osc.weixin.mp.web;
-
-import com.qq.weixin.mp.aes.AesException;
-import org.elkan1788.osc.weixin.mp.core.WxBase;
-import org.elkan1788.osc.weixin.mp.core.WxHandler;
-import org.elkan1788.osc.weixin.mp.vo.MPAct;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * Servlet环境接入
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2015/1/13
- */
-public abstract class WxServletSupport extends HttpServlet implements WxWebSupport {
-
- private static final Logger log = LoggerFactory.getLogger(WxServletSupport.class);
- // 微信基础功能
- private WxBase wxBase = new WxBase();
-
- @Override
- public void init() throws ServletException {
- super.init();
- // 重写此方法
- // 1.设置微信公众号的信息
- // 2.setMpAct();
- // 3.setWxHandler();
- }
-
- /**
- * 处理微信接收URL验证
- *
- * @param req 请求
- * @param resp 响应
- * @throws ServletException
- * @throws IOException
- */
- @Override
- protected void doGet(HttpServletRequest req,
- HttpServletResponse resp) throws ServletException, IOException {
- // 响应设置
- resp.setCharacterEncoding("UTF-8");
- resp.setContentType("text/html");
- this.wxBase.init(req);
- try {
- String echo = this.wxBase.check();
- PrintWriter out = resp.getWriter();
- if (!echo.isEmpty()) {
- out.print(echo);
- } else {
- out.print("error");
- log.error("微信接入验证URL时失败!!!");
- log.error("微信服务器echoStr值: {}", this.wxBase.getEchostr());
- log.error("SHA1签名echoStr值: {}", echo);
- }
- } catch (AesException e) {
- log.error("微信接入验证URL时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
- }
-
- /**
- * 处理微信普通消息
- *
- * @param req 请求
- * @param resp 响应
- * @throws ServletException
- * @throws IOException
- */
- @Override
- protected void doPost(HttpServletRequest req,
- HttpServletResponse resp) throws ServletException, IOException {
- this.wxBase.init(req);
- String result = "error";
- try {
- result = this.wxBase.handler();
- } catch (Exception e) {
- log.error("解析微信消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
- // 响应设置
- resp.setCharacterEncoding("UTF-8");
- resp.setContentType("text/html");
- resp.getWriter().print(result);
- }
-
- @Override
- public void setMpAct(MPAct mpAct) {
- this.wxBase.setMpAct(mpAct);
- }
-
- @Override
- public void setWxHandler(WxHandler wxHandler) {
- this.wxBase.setWxHandler(wxHandler);
- }
-
- @Override
- public WxBase getWxBase() {
- return this.wxBase;
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/web/WxSpringSupport.java b/src/main/java/org/elkan1788/osc/weixin/mp/web/WxSpringSupport.java
deleted file mode 100644
index 927922b..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/web/WxSpringSupport.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.elkan1788.osc.weixin.mp.web;
-
-import com.qq.weixin.mp.aes.AesException;
-import org.elkan1788.osc.weixin.mp.core.WxBase;
-import org.elkan1788.osc.weixin.mp.core.WxHandler;
-import org.elkan1788.osc.weixin.mp.vo.MPAct;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-
-/**
- * SpringMVC环境接入
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2015/1/13
- */
-public abstract class WxSpringSupport implements WxWebSupport {
-
- private static final Logger log = LoggerFactory.getLogger(WxSpringSupport.class);
- // 微信基础功能
- private WxBase wxBase = new WxBase();
-
- protected void init() {
- // 重写此方法
- // 1.设置微信公众号的信息
- // 2.setMpAct();
- // 3.setWxHandler();
- }
-
- /**
- * 与微信信息交互
- * 实现时只需写个SpringMVC入口调用此方法即可,入口用ResponseBody输出
- *
- * @param req 响应
- * @return 回复消息
- * @throws IOException
- */
- protected String wxInteract(HttpServletRequest req) throws IOException {
- // 准备
- this.init();
- this.wxBase.init(req);
- String reply = "";
- // 区分POST与GET来源
- String method = req.getMethod();
- // 微信接入验证
- if ("GET".equals(method)) {
- try {
- reply = this.wxBase.check();
- if (reply.isEmpty()) {
- reply = "error";
- log.error("微信接入验证URL时失败!!!");
- log.error("微信服务器echoStr值: {}", this.wxBase.getEchostr());
- log.error("SHA1签名echoStr值: {}", reply);
- }
- } catch (AesException e) {
- log.error("微信接入验证URL时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
- return reply;
- }
-
- // 信息互动
- try {
- reply = this.wxBase.handler();
- } catch (Exception e) {
- log.error("解析微信消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- }
-
- return reply;
- }
-
- @Override
- public void setMpAct(MPAct mpAct) {
- this.wxBase.setMpAct(mpAct);
- }
-
- @Override
- public void setWxHandler(WxHandler wxHandler) {
- this.wxBase.setWxHandler(wxHandler);
- }
-
- @Override
- public WxBase getWxBase() {
- return this.wxBase;
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/web/WxStruts2Support.java b/src/main/java/org/elkan1788/osc/weixin/mp/web/WxStruts2Support.java
deleted file mode 100644
index e89722d..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/web/WxStruts2Support.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.elkan1788.osc.weixin.mp.web;
-
-import com.opensymphony.xwork2.Action;
-import com.opensymphony.xwork2.ActionSupport;
-import com.qq.weixin.mp.aes.AesException;
-import org.apache.struts2.interceptor.ServletRequestAware;
-import org.apache.struts2.interceptor.ServletResponseAware;
-import org.elkan1788.osc.weixin.mp.core.WxBase;
-import org.elkan1788.osc.weixin.mp.core.WxHandler;
-import org.elkan1788.osc.weixin.mp.vo.MPAct;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * Struts2环境接入
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2015/1/13
- */
-public abstract class WxStruts2Support extends ActionSupport implements WxWebSupport, ServletRequestAware, ServletResponseAware {
-
- private static final Logger log = LoggerFactory.getLogger(WxStruts2Support.class);
- // 微信基础功能
- private WxBase wxBase = new WxBase();
- // Http请求
- private HttpServletRequest req;
- // Http响应
- private HttpServletResponse resp;
-
- protected void init() {
- // 重写此方法
- // 1.设置微信公众号的信息
- // 2.setMpAct();
- // 3.setWxHandler();
- }
-
- /**
- * 与微信信息交互
- * 实现时只需写个Struts2入口调用此方法即可
- *
- * @return 回复消息
- * @throws java.io.IOException
- */
- protected void wxInteract() throws IOException {
- // 准备
- this.init();
- this.wxBase.init(req);
- // 响应设置
- resp.setCharacterEncoding("UTF-8");
- resp.setContentType("text/html");
- PrintWriter out = resp.getWriter();
- String reply = "";
- // 区分POST与GET来源
- String method = req.getMethod();
- // 微信接入验证
- if ("GET".equals(method)) {
- try {
- reply = this.wxBase.check();
- if (reply.isEmpty()) {
- reply = "error";
- log.error("微信接入验证URL时失败!!!");
- log.error("微信服务器echoStr值: {}", this.wxBase.getEchostr());
- log.error("SHA1签名echoStr值: {}", reply);
- } else {
- out.print(reply);
- }
- } catch (AesException e) {
- log.error("微信接入验证URL时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- out.print("error");
- }
- }
-
- // 信息互动
- try {
- reply = this.wxBase.handler();
- out.print(reply);
- } catch (Exception e) {
- log.error("解析微信消息时出现异常!!!");
- log.error(e.getLocalizedMessage(), e);
- out.print("error");
- }
-
- }
-
- @Override
- public void setMpAct(MPAct mpAct) {
- this.wxBase.setMpAct(mpAct);
- }
-
- @Override
- public void setWxHandler(WxHandler wxHandler) {
- this.wxBase.setWxHandler(wxHandler);
- }
-
- @Override
- public WxBase getWxBase() {
- return this.wxBase;
- }
-
- @Override
- public void setServletRequest(HttpServletRequest req) {
- this.req = req;
- }
-
- @Override
- public void setServletResponse(HttpServletResponse resp) {
- this.resp = resp;
- }
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/web/WxWebSupport.java b/src/main/java/org/elkan1788/osc/weixin/mp/web/WxWebSupport.java
deleted file mode 100644
index 313ad24..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/web/WxWebSupport.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.elkan1788.osc.weixin.mp.web;
-
-import org.elkan1788.osc.weixin.mp.core.WxBase;
-import org.elkan1788.osc.weixin.mp.core.WxHandler;
-import org.elkan1788.osc.weixin.mp.vo.MPAct;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * 微信WEB环境接口设计
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2015/1/13
- */
-public interface WxWebSupport {
-
- /**
- * 设置微信公众号信息
- *
- * @param mpAct 公众号信息
- */
- void setMpAct(MPAct mpAct);
-
- /**
- * 设置微信消息处理器
- *
- * @param wxHandler 微信消息处理器
- */
- void setWxHandler(WxHandler wxHandler);
-
- /**
- * 获取微信基础功能
- *
- * @return 基础功能
- */
- WxBase getWxBase();
-}
diff --git a/src/main/java/org/elkan1788/osc/weixin/mp/web/package-info.java b/src/main/java/org/elkan1788/osc/weixin/mp/web/package-info.java
deleted file mode 100644
index 61444f3..0000000
--- a/src/main/java/org/elkan1788/osc/weixin/mp/web/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * 敏捷开发的各种WEB环境工具包,实现时只需要重写对应方法即可.
- * (一直很纠结是否需要添加,感觉会对环境过于依赖,暂定吧)
- */
-package org.elkan1788.osc.weixin.mp.web;
\ No newline at end of file
diff --git a/src/main/resources/ErrorCode.properties b/src/main/resources/ErrorCode.properties
new file mode 100644
index 0000000..3893b40
--- /dev/null
+++ b/src/main/resources/ErrorCode.properties
@@ -0,0 +1,142 @@
+#微信公众平台全局返回码说明(中文)
+#
+#author:凡梦星尘(elkan1788@gmail.com)
+# 高轩雾褪(977903096@qq.com)
+
+#系统类型
+-1=系统繁忙,此时请开发者稍候再试.
+0=请求成功.
+
+#消息类型
+40001=获取access_token时AppSecret错误,或者access_token无效.\
+请开发者认真比对AppSecret的正确性,或查看是否正在为恰当的公众号调用接口.
+40002=不合法的凭证类型.
+40003=不合法的OpenID,请开发者确认OpenID(该用户)是否已关注公众号,\
+或是否是其他公众号的OpenID.
+40004=不合法的媒体文件类型.
+40005=不合法的文件类型.
+40006=不合法的文件大小.
+40007=不合法的媒体文件id.
+40008=不合法的消息类型.
+40009=不合法的图片文件大小.
+40010=不合法的语音文件大小.
+40011=不合法的视频文件大小.
+40012=不合法的缩略图文件大小.
+40013=不合法的AppID,请开发者检查AppID的正确性,避免异常字符,注意大小写.
+40014=不合法的access_token,请开发者认真比对access_token的有效性\
+(如是否过期),或查看是否正在为恰当的公众号调用接口.
+40015=不合法的菜单类型.
+40016=不合法的按钮个数.
+40017=不合法的按钮个数.
+40018=不合法的按钮名字长度.
+40019=不合法的按钮KEY长度.
+40020=不合法的按钮URL长度.
+40021=不合法的菜单版本号.
+40022=不合法的子菜单级数.
+40023=不合法的子菜单按钮个数.
+40024=不合法的子菜单按钮类型.
+40025=不合法的子菜单按钮名字长度.
+40026=不合法的子菜单按钮KEY长度.
+40027=不合法的子菜单按钮URL长度.
+40028=不合法的自定义菜单使用用户.
+40029=不合法的oauth_code.
+40030=不合法的refresh_token.
+40031=不合法的openid列表.
+40032=不合法的openid列表长度.
+40033=不合法的请求字符,不能包含\\uxxxx格式的字符.
+40035=不合法的参数.
+40038=不合法的请求格式.
+40039=不合法的URL长度.
+40050=不合法的分组id.
+40051=分组名字不合法.
+40117=分组名字不合法.
+40118=media_id大小不合法.
+40119=button类型错误.
+40120=button类型错误.
+40121=不合法的media_id类型.
+40132=微信号不合法.
+40137=不支持的图片格式.
+41001=缺少access_token参数.
+41002=缺少appid参数.
+41003=缺少refresh_token参数.
+41004=缺少secret参数.
+41005=缺少多媒体文件数据.
+41006=缺少media_id参数.
+41007=缺少子菜单数据.
+41008=缺少oauthcode.
+41009=缺少openid.
+42001=access_token超时,请检查access_token的有效期,请参考基础支持-获取\
+access_token中,对access_token的详细机制说明.
+42002=refresh_token超时.
+42003=oauth_code超时.
+43001=需要GET请求.
+43002=需要POST请求.
+43003=需要HTTPS请求.
+43004=需要接收者关注.
+43005=需要好友关系.
+44001=多媒体文件为空.
+44002=POST的数据包为空.
+44003=图文消息内容为空.
+44004=文本消息内容为空.
+45001=多媒体文件大小超过限制.
+45002=消息内容超过限制.
+45003=标题字段超过限制.
+45004=描述字段超过限制.
+45005=链接字段超过限制.
+45006=图片链接字段超过限制.
+45007=语音播放时间超过限制.
+45008=图文消息超过限制.
+45009=接口调用超过限制.
+45010=创建菜单个数超过限制.
+45011=API调用频率太快受限制.
+45015=回复时间超过限制.
+45016=系统分组,不允许修改.
+45017=分组名字过长.
+45018=分组数量超过上限.
+46001=不存在媒体数据.
+46002=不存在的菜单版本.
+46003=不存在的菜单数据.
+46004=不存在的用户.
+47001=解析JSON/XML内容错误.
+48001=api功能未授权,请确认公众号已获得该接口,可以在\
+公众平台官网-开发者中心页中查看接口权限.
+50001=用户未授权该api.
+50002=用户受限,可能是违规后接口被封禁.
+61451=参数错误.
+61452=无效客服账号.
+61453=客服帐号已存在.
+61454=客服帐号名长度超过限制(仅允许10个英文字符,\
+不包括@及@后的公众号的微信号).
+61455=客服帐号名包含非法字符(仅允许英文+数字).
+61456=客服帐号个数超过限制(10个客服账号).
+61457=无效头像文件类型.
+61450=系统错误.
+61500=日期格式错误.
+61501=日期范围错误.
+9001001=POST数据参数不合法.
+9001002=远端服务不可用.
+9001003=Ticket不合法.
+9001004=获取摇周边用户信息失败.
+9001005=获取商户信息失败.
+9001006=获取OpenID失败.
+9001007=上传文件缺失.
+9001008=上传素材的文件类型不合法.
+9001009=上传素材的文件尺寸不合法.
+9001010=上传失败.
+9001020=帐号不合法.
+9001021=已有设备激活率低于50%,不能新增设备.
+9001022=设备申请数不合法,必须为大于0的数字.
+9001023=已存在审核中的设备ID申请.
+9001024=一次查询设备ID数量不能超过50.
+9001025=设备ID不合法.
+9001026=页面ID不合法.
+9001027=页面参数不合法.
+9001028=一次删除页面ID数量不能超过10.
+9001029=页面已应用在设备中,请先解除应用关系再删除.
+9001030=一次查询页面ID数量不能超过50.
+9001031=时间区间不合法.
+9001032=保存设备与页面的绑定关系参数错误.
+9001033=门店ID不合法.
+9001034=设备备注信息过长.
+9001035=设备申请参数不合法.
+9001036=查询起始值begin不合法.
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
deleted file mode 100644
index 65c9a74..0000000
--- a/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-log4j.rootLogger=DEBUG,Console
-
-log4j.appender.Console=org.apache.log4j.ConsoleAppender
-log4j.appender.Console.Target=System.out
-log4j.appender.Console.layout=org.apache.log4j.PatternLayout
-log4j.appender.Console.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c] %m%n
\ No newline at end of file
diff --git a/src/main/resources/test-cfg.properties b/src/main/resources/test-cfg.properties
deleted file mode 100644
index 63e4a0f..0000000
--- a/src/main/resources/test-cfg.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-## 微信API测试公众号信息
-mpId=
-openId=
-appId=
-appSecret=
-token=
-aesKey=
-accessToken=
-
-mediaId=
-msgSing=
-timestamp=
-echostr=
-nonce=
\ No newline at end of file
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/Mpsdk4jTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/Mpsdk4jTest.java
new file mode 100644
index 0000000..712d24d
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/Mpsdk4jTest.java
@@ -0,0 +1,29 @@
+package io.github.elkan1788.mpsdk4j;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * 测试Mpsdk4j
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class Mpsdk4jTest {
+
+ private static final Log log = Logs.get();
+
+ /**
+ * Test method for {@link io.github.elkan1788.mpsdk4j.Mpsdk4j#version()}.
+ */
+ @Test
+ public void testVersion() {
+ new Mpsdk4j(); // Just cover testing
+ log.debug(Mpsdk4j.version());
+ String curver = "2.b.1";
+ Assert.assertEquals(curver, Mpsdk4j.version());
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/RunTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/RunTest.java
new file mode 100644
index 0000000..acfe9a4
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/RunTest.java
@@ -0,0 +1,31 @@
+package io.github.elkan1788.mpsdk4j;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import io.github.elkan1788.mpsdk4j.api.APITest;
+import io.github.elkan1788.mpsdk4j.core.CoreTest;
+import io.github.elkan1788.mpsdk4j.mvc.MVCTest;
+import io.github.elkan1788.mpsdk4j.repo.com.qq.weixin.mp.aes.AESTest;
+import io.github.elkan1788.mpsdk4j.util.UtilTest;
+import io.github.elkan1788.mpsdk4j.vo.VOTest;
+
+/**
+ * Test all class
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ Mpsdk4jTest.class,
+ UtilTest.class,
+ VOTest.class,
+ APITest.class,
+ CoreTest.class,
+ AESTest.class,
+ MVCTest.class
+})
+public class RunTest {
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/TestSupport.java b/src/test/java/io/github/elkan1788/mpsdk4j/TestSupport.java
new file mode 100644
index 0000000..8369a4f
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/TestSupport.java
@@ -0,0 +1,16 @@
+package io.github.elkan1788.mpsdk4j;
+
+import io.github.elkan1788.mpsdk4j.util.ConfigReader;
+
+/**
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class TestSupport {
+
+ protected static ConfigReader _cr;
+
+ static {
+ _cr = new ConfigReader("/mpconf.properties");
+ }
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/APITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/APITest.java
new file mode 100644
index 0000000..6bbd0fb
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/APITest.java
@@ -0,0 +1,24 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * API 包测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ CredentialAPITest.class,
+ MenuAPITest.class,
+ MediaAPITest.class,
+ GroupsAPITest.class,
+ QRCodeAPITest.class,
+ UserAPITest.class,
+ TemplateAPITest.class
+})
+public class APITest {
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/APITestSupport.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/APITestSupport.java
new file mode 100644
index 0000000..29a0f76
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/APITestSupport.java
@@ -0,0 +1,35 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import org.junit.Before;
+
+import io.github.elkan1788.mpsdk4j.TestSupport;
+import io.github.elkan1788.mpsdk4j.vo.MPAccount;
+
+public class APITestSupport extends TestSupport {
+
+ protected MPAccount mpAct;
+ protected static String openId;
+ protected static String openId2;
+ protected static int groupId;
+ protected static String accessToken;
+ protected static String mediaId;
+ protected static String ticket;
+ protected static String tmplId;
+
+ @Before
+ public void init() {
+ mpAct = new MPAccount();
+ mpAct.setMpId(_cr.get("mpId"));
+ mpAct.setAppId(_cr.get("appId"));
+ mpAct.setAppSecret(_cr.get("appSecret"));
+
+ openId = _cr.get("openId");
+ openId2 = _cr.get("openId2");
+ groupId = _cr.getInt("groupId");
+ accessToken = _cr.get("accessToken");
+ mediaId = _cr.get("mediaId");
+ ticket = _cr.get("ticket");
+ tmplId = _cr.get("tmplId");
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/CredentialAPITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/CredentialAPITest.java
new file mode 100644
index 0000000..43d13a8
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/CredentialAPITest.java
@@ -0,0 +1,71 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * CredentialApi 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class CredentialAPITest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ private CredentialAPI ca;
+
+ @Override
+ @Before
+ public void init() {
+ log.info("====== CredentialAPITest ======");
+ super.init();
+ ca = WechatAPIImpl.create(mpAct);
+ }
+
+ @Test
+ public void testGetAccessToken() {
+ log.info("====== CredentialAPI#getAccessToken ======");
+ assertNotNull(ca.getAccessToken());
+ accessToken = ca.getAccessToken();
+ log.info(ca.getAccessToken());
+ }
+
+ @Test
+ public void testGetServerIps() {
+ log.info("====== CredentialAPI#getServerIps ======");
+ List ips = ca.getServerIps();
+ assertNotNull(ips);
+ int i = 0;
+ for (String ip : ips) {
+ i++;
+ log.infof("Wechat server[%d] ip: %s", i, ip);
+ }
+ }
+
+ @Test
+ public void testGetShorUrl() {
+ log.info("====== CredentialAPI#getShortUrl ======");
+ String longurl = "https://mp.weixin.qq.com/wiki/10/165c9b15eddcfbd8699ac12b0bd89ae6.html";
+ String shorurl = ca.getShortUrl(longurl);
+ assertNotNull(shorurl);
+ log.info(shorurl);
+ }
+
+ @Test
+ public void testGetJSTicket() {
+ log.info("====== CredentialAPI#getJSTicket ======");
+ String jsticket = ca.getJSTicket();
+ assertNotNull(jsticket);
+ log.info(jsticket);
+ }
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/GroupsAPITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/GroupsAPITest.java
new file mode 100644
index 0000000..ce7d16b
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/GroupsAPITest.java
@@ -0,0 +1,106 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+import io.github.elkan1788.mpsdk4j.vo.api.Groups;
+
+/**
+ * GroupsAPI 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@FixMethodOrder(MethodSorters.JVM)
+public class GroupsAPITest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ private GroupsAPI ga;
+
+ @Override
+ @Before
+ public void init() {
+ log.info("====== GroupsAPITest ======");
+ super.init();
+ ga = WechatAPIImpl.create(mpAct);
+ }
+
+ @Test
+ public void testCreateGroup() {
+ log.info("====== GroupsAPI#createGroup ======");
+ groupId = ga.createGroup("测试分组");
+ assertTrue(groupId > 0);
+ log.info(groupId);
+ }
+
+ @Test
+ public void testGetGroups() {
+ log.info("====== GroupsAPI#getGroups ======");
+ log.infof("groupId: %d", groupId);
+ List gs = ga.getGroups();
+ assertNotNull(gs);
+ for (Groups g : gs) {
+ log.info(g);
+ }
+ }
+
+ @Test
+ public void testRenGroups() {
+ log.info("====== GroupsAPI#renGroups ======");
+ boolean flag = ga.renGroups(groupId, "测试分组改名");
+ assertTrue(flag);
+ log.info(flag);
+ }
+
+ @Test
+ public void testMove2Group() throws Exception {
+ log.info("====== GroupsAPI#move2Group ======");
+ log.info(groupId);
+ boolean flag = ga.move2Group(openId, groupId);
+ assertTrue(flag);
+ log.info(flag);
+ Thread.sleep(5 * 1000);
+ }
+
+ // TODO 明明已移动用户到新分组,却还在系统分组,莫非腾讯服务器响应缓存/缓慢!!!
+ @Test
+ public void testGetGroup() {
+ log.info("====== GroupsAPI#getGroup ======");
+ int id = ga.getGroup(openId);
+ assertEquals(id, groupId);
+ log.info(id);
+ }
+
+ // TODO 一直提示需要关注用户才可以,莫名奇妙!!!
+ @Test(expected = RuntimeException.class)
+ public void testBatchMove2Group() {
+ log.info("====== GroupsAPI#batchMove2Group ======");
+ List openIds = new ArrayList();
+ openIds.add(openId);
+ openIds.add(openId2);
+ boolean flag = ga.batchMove2Group(openIds, groupId);
+ assertTrue(flag);
+ log.info(flag);
+ }
+
+ @Test
+ public void testDelGroup() {
+ log.info("====== GroupsAPI#delGroup ======");
+ boolean flag = ga.delGroup(groupId);
+ assertTrue(flag);
+ log.info(flag);
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/MediaAPITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/MediaAPITest.java
new file mode 100644
index 0000000..2745eea
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/MediaAPITest.java
@@ -0,0 +1,54 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import static org.junit.Assert.assertNotNull;
+import io.github.elkan1788.mpsdk4j.common.MediaType;
+import io.github.elkan1788.mpsdk4j.vo.api.Media;
+
+import java.io.File;
+
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@FixMethodOrder(MethodSorters.JVM)
+public class MediaAPITest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ private MediaAPI ma;
+
+ @Override
+ @Before
+ public void init() {
+ log.info("====== MediaAPITest ======");
+ super.init();
+ ma = WechatAPIImpl.create(mpAct);
+ }
+
+ @Test
+ public void testUploadImage() {
+ log.info("====== MediaAPI#upMedia ======");
+ File media = new File(this.getClass().getResource("/mpsdk4j-logo.png").getFile());
+ Media m = ma.upMedia(MediaType.image.name(), media);
+ assertNotNull(m);
+ log.info(m);
+ }
+
+ @Test
+ public void testGet() {
+ log.info("====== MediaAPI#dlMedia ======");
+ String mediaId = _cr.get("mediaId");
+ File media = ma.dlMedia(mediaId);
+ assertNotNull(media);
+ log.info(media.getAbsolutePath());
+ log.info(media.getName());
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/MenuAPITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/MenuAPITest.java
new file mode 100644
index 0000000..6a56712
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/MenuAPITest.java
@@ -0,0 +1,76 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+import io.github.elkan1788.mpsdk4j.common.EventType;
+import io.github.elkan1788.mpsdk4j.vo.api.Menu;
+
+/**
+ * CustomMenuAPI 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@FixMethodOrder(MethodSorters.JVM)
+public class MenuAPITest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ private MenuAPI cma;
+
+ @Override
+ @Before
+ public void init() {
+ log.info("====== MenuAPITest ======");
+ super.init();
+ cma = WechatAPIImpl.create(mpAct);
+ }
+
+ @Test
+ public void testDelMenu() {
+ log.info("====== MenuAPI#delMenu ======");
+ List menus = cma.getMenu();
+ assertNotNull(menus);
+ for (Menu m : menus) {
+ log.info(m);
+ }
+
+ boolean flag = cma.delMenu();
+ assertTrue(flag);
+
+ menus = cma.getMenu();
+ assertTrue(menus == null);
+ }
+
+ @Test
+ public void testCreateMenu() {
+ log.info("====== MenuAPI#createMenu ======");
+ Menu csdn = new Menu("CSND");
+ csdn.setType(EventType.VIEW.name());
+ csdn.setUrl("http://www.csdn.net");
+
+ Menu oschina = new Menu("OSCHINA");
+ oschina.setType(EventType.VIEW.name());
+ oschina.setUrl("http://www.oschina.net");
+
+ Menu map = new Menu("Map");
+ Menu baidu = new Menu("BaiDu", EventType.VIEW.name(), "http://map.baidu.com");
+ Menu tencent = new Menu("Tencent", EventType.VIEW.name(), "http://map.qq.com");
+ Menu ali = new Menu("Ali", EventType.VIEW.name(), "http://ditu.amap.com/");
+ map.setSubButtons(Arrays.asList(baidu, tencent, ali));
+
+ boolean flag = cma.createMenu(csdn, oschina, map);
+ assertTrue(flag);
+ }
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/MessageAPITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/MessageAPITest.java
new file mode 100644
index 0000000..15994dc
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/MessageAPITest.java
@@ -0,0 +1,44 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import static org.junit.Assert.assertTrue;
+import io.github.elkan1788.mpsdk4j.vo.api.Template;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * MessageAPI 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class MessageAPITest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ private MessageAPI ma;
+
+ private String openId;
+
+ @Before
+ public void init() {
+ log.info("====== MessageAPITest ======");
+ super.init();
+ this.openId = _cr.get("openId");
+ ma = WechatAPIImpl.create(mpAct);
+ }
+
+ @Test
+ public void testSendTemplateMsg() {
+ log.info("====== MessageAPI#sendTemplateMsg ======");
+ String tmlId = _cr.get("tmplId");
+ Template tml = new Template("title", "测试");
+ String url = "https://www.google.com";
+ long msgid = ma.sendTemplateMsg(openId, tmlId, "#119EF3", url, tml);
+ assertTrue(msgid > 0);
+ log.info(msgid);
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/QRCodeAPITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/QRCodeAPITest.java
new file mode 100644
index 0000000..4bb3bb7
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/QRCodeAPITest.java
@@ -0,0 +1,57 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import io.github.elkan1788.mpsdk4j.vo.api.QRTicket;
+
+import java.io.File;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * QRCodeAPI 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+// TODO 此API貌似有问题,以后再好好检测
+public class QRCodeAPITest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ private QRCodeAPI qa;
+ private int expireSeconds = 604800;
+ private String ticket;
+
+ @Override
+ @Before
+ public void init() {
+ log.info("====== QRCodeAPITest ======");
+ super.init();
+ this.ticket = _cr.get("ticket");
+ qa = WechatAPIImpl.create(mpAct);
+ }
+
+ @Test
+ public void testCreateQR() {
+ log.info("====== QRCodeAPI#createQR ======");
+ QRTicket qrt = qa.createQR(10, expireSeconds);
+ assertNotNull(qrt);
+ assertEquals(qrt.getExpireSeconds(), expireSeconds);
+ log.infof("QR ticket: %s", qrt.getTicket());
+ log.infof("QR expire time: %s", qrt.getExpireSeconds());
+ log.infof("QR url: %s", qrt.getUrl());
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testGetQR() {
+ log.info("====== QRCodeAPI#getQR ======");
+ File qrImg = qa.getQR(ticket);
+ assertNotNull(qrImg);
+ log.infof("temp path: %s", qrImg.getAbsolutePath());
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/TemplateAPITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/TemplateAPITest.java
new file mode 100644
index 0000000..6fba588
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/TemplateAPITest.java
@@ -0,0 +1,46 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * TemplateAPI 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+// TODO 此为新接口待测试
+public class TemplateAPITest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ @SuppressWarnings("unused")
+ private TemplateAPI ta;
+
+ @Override
+ @Before
+ public void init() {
+ log.info("====== TemplateAPITest ======");
+ super.init();
+ ta = WechatAPIImpl.create(mpAct);
+ }
+
+ @Test
+ public void testSetIndustry() {
+ log.info("====== TemplateAPITest#setIndustry ======");
+ // boolean flag = ta.setIndustry(1, 2);
+ // assertTrue(flag);
+ // log.info(flag);
+ }
+
+ @Test
+ public void testGetTemplateId() {
+ log.info("====== TemplateAPITest#getTemplateId ======");
+ // String tmplid = ta.getTemplateId("5A90LqXLMHUVd0d1PFv-TezTxYWf2PBDV1APvAMeb1E");
+ // assertNotNull(tmplid);
+ // log.info(tmplid);
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/api/UserAPITest.java b/src/test/java/io/github/elkan1788/mpsdk4j/api/UserAPITest.java
new file mode 100644
index 0000000..7e2930e
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/api/UserAPITest.java
@@ -0,0 +1,76 @@
+package io.github.elkan1788.mpsdk4j.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import io.github.elkan1788.mpsdk4j.vo.api.FollowList;
+import io.github.elkan1788.mpsdk4j.vo.api.Follower;
+import io.github.elkan1788.mpsdk4j.vo.api.Follower2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * UserAPI 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@FixMethodOrder(MethodSorters.JVM)
+public class UserAPITest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ private UserAPI ua;
+
+ @Before
+ public void init() {
+ log.info("====== UserAPITest ====== ");
+ super.init();
+ ua = WechatAPIImpl.create(mpAct);
+ }
+
+ @Test
+ public void testGetFollowerList() {
+ log.info("====== UserAPI#getFollowerList ====== ");
+ FollowList fl = ua.getFollowerList(null);
+ assertNotNull(fl);
+ log.info(fl);
+ }
+
+ @Test
+ public void testGetFollower() {
+ log.info("====== UserAPI#getFollower ====== ");
+ Follower f = ua.getFollower(openId, null);
+ assertNotNull(f);
+ log.info(f);
+ }
+
+ @Test
+ public void testUpdateRemark() {
+ log.info("====== UserAPI#updateRemark ====== ");
+ boolean flag = ua.updateRemark(openId, "Youself");
+ assertTrue(flag);
+ log.info(flag);
+ }
+
+ @Test
+ public void testGetFollowers() {
+ log.info("====== UserAPI#getFollowers ====== ");
+ List getfs = new ArrayList();
+ getfs.add(new Follower2(openId));
+ getfs.add(new Follower2(_cr.get("openId2")));
+
+ List fs = ua.getFollowers(getfs);
+ assertNotNull(fs);
+ assertEquals(2, fs.size());
+ log.info(fs);
+ }
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/core/CoreTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/core/CoreTest.java
new file mode 100644
index 0000000..cb6d23a
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/core/CoreTest.java
@@ -0,0 +1,21 @@
+package io.github.elkan1788.mpsdk4j.core;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * core 包测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ JsonMsgBuilderTest.class,
+ MessageHandlerTest.class,
+ XmlMsgBuilderTest.class,
+ WechatKernelTest.class
+})
+public class CoreTest {
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/core/JsonMsgBuilderTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/core/JsonMsgBuilderTest.java
new file mode 100644
index 0000000..740ff1c
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/core/JsonMsgBuilderTest.java
@@ -0,0 +1,150 @@
+package io.github.elkan1788.mpsdk4j.core;
+
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import io.github.elkan1788.mpsdk4j.api.APITestSupport;
+import io.github.elkan1788.mpsdk4j.vo.api.Template;
+import io.github.elkan1788.mpsdk4j.vo.message.Article;
+import io.github.elkan1788.mpsdk4j.vo.message.ImageMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.MusicMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.NewsMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.TextMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.VideoMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.VoiceMsg;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.nutz.json.Json;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * JsonBuilder 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class JsonMsgBuilderTest extends APITestSupport {
+
+ private static final Log log = Logs.get();
+
+ @Before
+ public void init() {
+ log.info("====== JsonMsgBuilderTest ======");
+ super.init();
+ }
+
+ @Test
+ public void testText() {
+ log.info("====== JsonMsgBuilder#text ======");
+ TextMsg tm = new TextMsg();
+ tm.setToUserName(openId);
+ tm.setContent("Hello world! 世界,你好!");
+ String textJson = JsonMsgBuilder.create().text(tm).build();
+ assertNotNull(textJson);
+ assertNotEquals(-1, textJson.indexOf("text"));
+ assertNotNull(Json.fromJson(textJson));
+ log.info(textJson);
+ }
+
+ @Test
+ public void testImage() {
+ log.info("====== JsonMsgBuilder#image ======");
+ ImageMsg im = new ImageMsg();
+ im.setToUserName(openId);
+ im.setMediaId(mediaId);
+ String imgJson = JsonMsgBuilder.create().image(im).build();
+ assertNotNull(imgJson);
+ assertNotEquals(-1, imgJson.indexOf("image"));
+ assertNotNull(Json.fromJson(imgJson));
+ log.info(imgJson);
+ }
+
+ @Test
+ public void testVoice() {
+ log.info("====== JsonMsgBuilder#voice ======");
+ VoiceMsg vom = new VoiceMsg();
+ vom.setToUserName(openId);
+ vom.setMediaId(mediaId);
+ String voiceJson = JsonMsgBuilder.create().voice(vom).build();
+ assertNotNull(voiceJson);
+ assertNotEquals(-1, voiceJson.indexOf("voice"));
+ assertNotNull(Json.fromJson(voiceJson));
+ log.info(voiceJson);
+ }
+
+ @Test
+ public void testVideo() {
+ log.info("====== JsonMsgBuilder#video ======");
+ VideoMsg vim = new VideoMsg();
+ vim.setToUserName(openId);
+ vim.setMediaId(mediaId);
+ vim.setThumbMediaId(mediaId);
+ vim.setTitle("Video message");
+ vim.setDescription("Video message.");
+ String videoJson = JsonMsgBuilder.create().video(vim).build();
+ assertNotNull(videoJson);
+ assertNotEquals(-1, videoJson.indexOf("video"));
+ assertNotNull(Json.fromJson(videoJson));
+ log.info(videoJson);
+ }
+
+ @Test
+ public void testMusic() {
+ log.info("====== JsonMsgBuilder#music ======");
+ MusicMsg mm = new MusicMsg();
+ mm.setToUserName(openId);
+ mm.setThumbMediaId(mediaId);
+ mm.setTitle("致爱 Your Song");
+ mm.setDescription("Music message.");
+ mm.setMusicUrl("http://y.qq.com/#type=song&mid=002IVyIU4093Xr&play=0");
+ mm.setHQMusicUrl("http://y.qq.com/#type=song&mid=002IVyIU4093Xr&play=0");
+ String musicJson = JsonMsgBuilder.create().music(mm).build();
+ assertNotNull(musicJson);
+ assertNotEquals(-1, musicJson.indexOf("music"));
+ assertNotNull(Json.fromJson(musicJson));
+ log.info(musicJson);
+ }
+
+ @Test
+ public void testNews() {
+ log.info("====== JsonMsgBuilder#news ======");
+ NewsMsg nm = new NewsMsg();
+ nm.setToUserName(openId);
+ Article art = new Article();
+ art.setTitle("Wechat news message.");
+ art.setDescription("Wechat news message Description.");
+ art.setPicUrl("http://www.baidu.com");
+ art.setUrl("http://www.baidu.com");
+ nm.setArticles(Arrays.asList(art));
+ String newsJson = JsonMsgBuilder.create().news(nm).build();
+ assertNotNull(newsJson);
+ assertNotEquals(-1, newsJson.indexOf("articles"));
+ assertNotNull(Json.fromJson(newsJson));
+ log.info(newsJson);
+ }
+
+ @Test
+ public void testTemplate() {
+ log.info("====== JsonMsgBuilder#template ======");
+ Template tmp = new Template();
+ tmp.setColor("#ff0000");
+ tmp.setName("title");
+ tmp.setValue("Wechat template message.");
+
+ String tmpJson = JsonMsgBuilder.create()
+ .template(openId,
+ tmplId,
+ "#ff0000",
+ "http://www.baidu.com",
+ tmp)
+ .build();
+ assertNotNull(tmpJson);
+ assertNotEquals(-1, tmpJson.indexOf("data"));
+ assertNotNull(Json.fromJson(tmpJson));
+ log.info(tmpJson);
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/core/MessageHandlerTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/core/MessageHandlerTest.java
new file mode 100644
index 0000000..1731a89
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/core/MessageHandlerTest.java
@@ -0,0 +1,214 @@
+package io.github.elkan1788.mpsdk4j.core;
+
+import static org.junit.Assert.assertNotNull;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.nutz.lang.Lang;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+import io.github.elkan1788.mpsdk4j.util.StreamTool;
+import io.github.elkan1788.mpsdk4j.vo.event.SendLocationInfoEvent;
+import io.github.elkan1788.mpsdk4j.vo.event.SendPhotosEvent;
+import io.github.elkan1788.mpsdk4j.vo.message.ImageMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.LinkMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.LocationMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.TextMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.VideoMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.VoiceMsg;
+
+/**
+ * 测试XML读取
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class MessageHandlerTest {
+
+ private static final Log log = Logs.get();
+
+ private SAXParserFactory factory = SAXParserFactory.newInstance();
+ private SAXParser xmlParser;
+ private MessageHandler msgHandler = new MessageHandler();
+
+ @Before
+ public void init() {
+ log.info("====== MessageHandlerTest ======");
+ try {
+ xmlParser = factory.newSAXParser();
+ }
+ catch (Exception e) {
+ throw Lang.wrapThrow(e);
+ }
+ }
+
+ @Test
+ public void testTextMessage() throws Exception {
+ log.info("====== MessageHandler#text ======");
+ String textXml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "6091046778677430\n"
+ + "";
+
+ xmlParser.parse(StreamTool.toStream(textXml), msgHandler);
+ TextMsg tm = new TextMsg(msgHandler.getValues());
+ assertNotNull(tm);
+ log.info(tm);
+ }
+
+ @Test
+ public void testImageMessage() throws Exception {
+ log.info("====== MessageHandler#image ======");
+ String imgXml = "\n"
+ + "\n"
+ + "1418182361\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "6091046778677460\n"
+ + "";
+
+ xmlParser.parse(StreamTool.toStream(imgXml), msgHandler);
+ ImageMsg im = new ImageMsg(msgHandler.getValues());
+ assertNotNull(im);
+ log.info(im);
+ }
+
+ @Test
+ public void testVoiceMessage() throws Exception {
+ log.info("====== MessageHandler#voice ======");
+ String voiceXml = "\n"
+ + "\n"
+ + "1418182361\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "6091046778677460\n"
+ + "";
+ xmlParser.parse(StreamTool.toStream(voiceXml), msgHandler);
+ VoiceMsg vm = new VoiceMsg(msgHandler.getValues());
+ assertNotNull(vm);
+ log.info(vm);
+ }
+
+ @Test
+ public void testVideoMessage() throws Exception {
+ log.info("====== MessageHandler#video ======");
+ String videoXml = "\n"
+ + "\n"
+ + "1418182361\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "6091046778677460\n"
+ + "";
+ xmlParser.parse(StreamTool.toStream(videoXml), msgHandler);
+ VideoMsg vm = new VideoMsg(msgHandler.getValues());
+ assertNotNull(vm);
+ log.info(vm);
+ }
+
+ @Test
+ public void testShortVideoMessage() throws Exception {
+ log.info("====== MessageHandler#shortvideo ======");
+ String videoXml = "\n"
+ + "\n"
+ + "1418182361\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "6091046778677460\n"
+ + "";
+ xmlParser.parse(StreamTool.toStream(videoXml), msgHandler);
+ VideoMsg vm = new VideoMsg(msgHandler.getValues());
+ assertNotNull(vm);
+ log.info(vm);
+ }
+
+ @Test
+ public void testLocationMessage() throws Exception {
+ log.info("====== MessageHandler#location ======");
+ String videoXml = "\n"
+ + "\n"
+ + "1418182361\n"
+ + "\n"
+ + "23.134521\n"
+ + "113.358803\n"
+ + "20\n"
+ + "\n"
+ + "6091046778677460\n"
+ + "";
+ xmlParser.parse(StreamTool.toStream(videoXml), msgHandler);
+ LocationMsg lm = new LocationMsg(msgHandler.getValues());
+ assertNotNull(lm);
+ log.info(lm);
+ }
+
+ @Test
+ public void testLinkMessage() throws Exception {
+ log.info("====== MessageHandler#link ======");
+ String videoXml = "\n"
+ + "\n"
+ + "1418182361\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "6091046778677460\n"
+ + "";
+ xmlParser.parse(StreamTool.toStream(videoXml), msgHandler);
+ LinkMsg lm = new LinkMsg(msgHandler.getValues());
+ assertNotNull(lm);
+ log.info(lm);
+ }
+
+ @Test
+ public void testSendLocationMessage() throws Exception {
+ log.info("====== MessageHandler#sendlocation ======");
+ String videoXml = "\n"
+ + "\n"
+ + "1418182361\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "";
+ xmlParser.parse(StreamTool.toStream(videoXml), msgHandler);
+ SendLocationInfoEvent slife = new SendLocationInfoEvent(msgHandler.getValues());
+ assertNotNull(slife);
+ log.info(slife);
+ }
+
+ @Test
+ public void testSendPicsMessage() throws Exception {
+ log.info("====== MessageHandler#sendpics ======");
+ String videoXml = "\n"
+ + "\n"
+ + "1418182361\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "2\n"
+ + "- \n"
+ + "
- \n"
+ + "
\n"
+ + "";
+ xmlParser.parse(StreamTool.toStream(videoXml), msgHandler);
+ SendPhotosEvent spe = new SendPhotosEvent(msgHandler.getValues());
+ assertNotNull(spe);
+ log.info(spe);
+ }
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/core/WechatKernelTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/core/WechatKernelTest.java
new file mode 100644
index 0000000..25d80bc
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/core/WechatKernelTest.java
@@ -0,0 +1,726 @@
+package io.github.elkan1788.mpsdk4j.core;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.nutz.lang.random.R;
+import org.nutz.lang.random.StringGenerator;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+import io.github.elkan1788.mpsdk4j.TestSupport;
+import io.github.elkan1788.mpsdk4j.util.StreamTool;
+import io.github.elkan1788.mpsdk4j.vo.MPAccount;
+import io.github.elkan1788.mpsdk4j.vo.message.BasicMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.MusicMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.VideoMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.VoiceMsg;
+import io.github.elkan1788.mpsdk4j.vo.push.SentAllJobEvent;
+import io.github.elkan1788.mpsdk4j.vo.push.SentTmlJobEvent;
+
+/**
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class WechatKernelTest extends TestSupport {
+
+ private static final Log log = Logs.get();
+
+ private MPAccount mpAct;
+ private Map data;
+
+ @Before
+ public void init() {
+ log.info("====== WechatKernelTest ======");
+ mpAct = new MPAccount();
+ mpAct.setMpId(_cr.get("mpId"));
+ mpAct.setAppId(_cr.get("appId"));
+ mpAct.setAppSecret(_cr.get("appSecret"));
+ mpAct.setToken(_cr.get("token"));
+ data = new HashMap();
+ data.put("signature", new String[]{"af06ae6995cb1979e465d3b8015509ad61bb7204"});
+ data.put("timestamp", new String[]{"1442726144"});
+ data.put("nonce", new String[]{"1439307736"});
+ data.put("echostr", new String[]{"1439307541"});
+ }
+
+ @Test
+ public void testNullParamsCheck() {
+ log.info("====== WechatKernel#check-null ======");
+ data.clear();
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals("error"));
+ }
+
+ @Test
+ public void testLongParamsCheck() {
+ log.info("====== WechatKernel#check-toolong ======");
+ StringGenerator sg = R.sg(129, 200);
+ data.put("signature", new String[]{sg.next()});
+ data.put("timestamp", new String[]{sg.next()});
+ data.put("nonce", new String[]{sg.next()});
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals("error"));
+ }
+
+ @Test
+ public void testLong1ParamsCheck() {
+ log.info("====== WechatKernel#check-toolong1 ======");
+ StringGenerator sg = R.sg(129, 200);
+ data.put("signature", new String[]{sg.next()});
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals("error"));
+ }
+
+ @Test
+ public void testLong2ParamsCheck() {
+ log.info("====== WechatKernel#check-toolong2 ======");
+ StringGenerator sg = R.sg(129, 200);
+ data.put("timestamp", new String[]{sg.next()});
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals("error"));
+ }
+
+ @Test
+ public void testLong3ParamsCheck() {
+ log.info("====== WechatKernel#check-toolong3 ======");
+ StringGenerator sg = R.sg(129, 200);
+ data.put("nonce", new String[]{sg.next()});
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals("error"));
+ }
+
+ @Test
+ public void testNull1ParamsCheck() {
+ log.info("====== WechatKernel#check-null1 ======");
+ data.put("signature", null);
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals("error"));
+ }
+
+ @Test
+ public void testNull2ParamsCheck() {
+ log.info("====== WechatKernel#check-null2 ======");
+ data.put("timestamp", null);
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals("error"));
+ }
+
+ @Test
+ public void testNull3ParamsCheck() {
+ log.info("====== WechatKernel#check-null3 ======");
+ data.put("nonce", null);
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals("error"));
+ }
+
+ @Test
+ public void testCheck() {
+ log.info("====== WechatKernel#check ======");
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String echo = wk.check();
+ assertNotNull(echo);
+ assertTrue(echo.equals(data.get("echostr")[0]));
+ }
+
+ @Test
+ public void testTextHandle() {
+ log.info("====== WechatKernel#handle-text ======");
+ String textxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "6091046778677430\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(textxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testImageHandle() {
+ log.info("====== WechatKernel#handle-image ======");
+ String imgxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + " \n"
+ + "\n"
+ + "\n"
+ + "6091046778677430\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(imgxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testVoiceHandle() {
+ log.info("====== WechatKernel#handle-voice ======");
+ String voicexml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "1234567890123456\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(voicexml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ log.info("====== WechatKernel#handle-voice-voice ======");
+ wk = new WechatKernel(mpAct, new VoiceHandler(), data);
+ respxml = wk.handle(StreamTool.toStream(voicexml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ log.info("====== WechatKernel#handle-voice-music ======");
+ wk = new WechatKernel(mpAct, new MediaHandler(), data);
+ respxml = wk.handle(StreamTool.toStream(voicexml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testVideoHandle() {
+ log.info("====== WechatKernel#handle-video ======");
+ String videoxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "1234567890123456\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(videoxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ log.info("====== WechatKernel#handle-video-video ======");
+ wk = new WechatKernel(mpAct, new MediaHandler(), data);
+ respxml = wk.handle(StreamTool.toStream(videoxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testShortVideoHandle() {
+ log.info("====== WechatKernel#handle-shortvideo ======");
+ String shortvxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "1234567890123456\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(shortvxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testLocationHandle() {
+ log.info("====== WechatKernel#handle-location ======");
+ String locationxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "23.134521\n"
+ + "113.358803\n"
+ + "20\n"
+ + "\n"
+ + "1234567890123456\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(locationxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testLinkHandle() {
+ log.info("====== WechatKernel#handle-location ======");
+ String linkxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "1234567890123456\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(linkxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testUnknowHandle() {
+ log.info("====== WechatKernel#handle-unknow ======");
+ String unknowxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "1234567890123456\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(unknowxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testSubEventHandle() {
+ log.info("====== WechatKernel#handle-subevent ======");
+ String subxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(subxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testUnSubEventHandle() {
+ log.info("====== WechatKernel#handle-subevent ======");
+ String unsubxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(unsubxml));
+ assertNotNull(respxml);
+ assertTrue(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testScanEventHandle() {
+ log.info("====== WechatKernel#handle-scanevent ======");
+ String scanxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel();
+ wk.setMpAct(mpAct);
+ wk.setWechatHandler(new WechatDefHandler());
+ wk.setParams(data);
+ String respxml = wk.handle(StreamTool.toStream(scanxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testLocationEventHandle() {
+ log.info("====== WechatKernel#handle-locationevent ======");
+ String locationxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "23.137466\n"
+ + "113.352425\n"
+ + "119.385040\n"
+ + "";
+ WechatKernel wk = new WechatKernel();
+ wk.setMpAct(mpAct);
+ wk.setWechatHandler(new WechatDefHandler());
+ wk.setParams(data);
+ String respxml = wk.handle(StreamTool.toStream(locationxml));
+ assertNotNull(respxml);
+ assertTrue(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testClickEventHandle() {
+ log.info("====== WechatKernel#handle-clickevent ======");
+ String clickxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel();
+ wk.setMpAct(mpAct);
+ wk.setWechatHandler(new WechatDefHandler());
+ wk.setParams(data);
+ String respxml = wk.handle(StreamTool.toStream(clickxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testViewEventHandle() {
+ log.info("====== WechatKernel#handle-viewevent ======");
+ String viewxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel();
+ wk.setMpAct(mpAct);
+ wk.setWechatHandler(new WechatDefHandler());
+ wk.setParams(data);
+ String respxml = wk.handle(StreamTool.toStream(viewxml));
+ assertNotNull(respxml);
+ assertTrue(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testScanPushEventHandle() {
+ log.info("====== WechatKernel#handle-scanpushevent ======");
+ String spxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(spxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testScanWaitEventHandle() {
+ log.info("====== WechatKernel#handle-scanwaitmsgevent ======");
+ String swxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(swxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testPicSysEventHandle() {
+ log.info("====== WechatKernel#handle-picsysevent ======");
+ String psxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "1\n"
+ + "- \n"
+ + "
\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(psxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testPicPhotoAlbumEventHandle() {
+ log.info("====== WechatKernel#handle-picphotoalbumevent ======");
+ String ppaxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "1\n"
+ + "- \n"
+ + "
\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(ppaxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testPicWeixinEventHandle() {
+ log.info("====== WechatKernel#handle-picweixinevent ======");
+ String pwxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "1\n"
+ + "- \n"
+ + "
\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(pwxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testSelectLocationEventHandle() {
+ log.info("====== WechatKernel#handle-selectlocationevent ======");
+ String slxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(slxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testSentTemplateFinshJobEventHandle() {
+ log.info("====== WechatKernel#handle-senttemplateevent ======");
+ String tmlfjxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "200163836\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(tmlfjxml));
+ assertNotNull(respxml);
+ assertTrue(respxml.equals("success"));
+ log.info(respxml);
+ wk = new WechatKernel(mpAct, new PushEventHandler(), data);
+ respxml = wk.handle(StreamTool.toStream(tmlfjxml));
+ assertNotNull(respxml);
+ assertTrue(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testSentAllFinshJobEventHandle() {
+ log.info("====== WechatKernel#handle-sentallevent ======");
+ String tmlfjxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "200163836\n"
+ + "\n"
+ + "100\n"
+ + "80\n"
+ + "75\n"
+ + "5\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(tmlfjxml));
+ assertNotNull(respxml);
+ assertTrue(respxml.equals("success"));
+ log.info(respxml);
+ wk = new WechatKernel(mpAct, new PushEventHandler(), data);
+ respxml = wk.handle(StreamTool.toStream(tmlfjxml));
+ assertNotNull(respxml);
+ assertTrue(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testNewEventHandle() {
+ log.info("====== WechatKernel#handle-viewevent ======");
+ String newxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "\n"
+ + "";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(newxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testErrorXmlHandle() {
+ log.info("====== WechatKernel#handle-viewevent ======");
+ String newxml = "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "/xml>";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(newxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testDecryptMsgFailure() {
+ log.info("====== WechatKernel#encryptmsg ======");
+ data.clear();
+ data.put("nonce", new String[]{"xxxxxx"});
+ data.put("timestamp", new String[]{"1409304348"});
+ data.put("msg_signature", new String[]{"9f8883ff0676a51299747fc2d4b2e6a4be9207cb"});
+ data.put("encrypt_type", new String[]{"aes"});
+ mpAct.setAESKey("abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG");
+ mpAct.setAppId("wxb11529c136998cb6");
+ mpAct.setToken("pamtest");
+ String encryptxml = "1409304348";
+ WechatKernel wk = new WechatKernel(mpAct, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(encryptxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ @Test
+ public void testDecryptMsg() {
+ log.info("====== WechatKernel#encryptmsg ======");
+ data.clear();
+ data.put("nonce", new String[]{"xxxxxx"});
+ data.put("timestamp", new String[]{"1409304348"});
+ data.put("msg_signature", new String[]{"92aa0aeee3943305c0127627dad968bd73e32428"});
+ data.put("encrypt_type", new String[]{"aes"});
+ MPAccount mpact = new MPAccount();
+ mpact.setAESKey("abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG");
+ mpact.setAppId("wxb11529c136998cb6");
+ mpact.setToken("pamtest");
+ String encryptxml = "1409304348";
+ WechatKernel wk = new WechatKernel(mpact, new WechatDefHandler(), data);
+ String respxml = wk.handle(StreamTool.toStream(encryptxml));
+ assertNotNull(respxml);
+ assertFalse(respxml.equals("success"));
+ log.info(respxml);
+ }
+
+ class VoiceHandler extends WechatDefHandler {
+
+ @Override
+ public BasicMsg voice(VoiceMsg vm) {
+ VoiceMsg vim = new VoiceMsg(vm);
+ vim.setMediaId(vm.getMediaId());
+ return vim;
+ }
+
+ }
+
+ class MediaHandler extends WechatDefHandler {
+
+ @Override
+ public BasicMsg voice(VoiceMsg vm) {
+ MusicMsg mm = new MusicMsg(vm);
+ mm.setTitle("致爱 Your Song");
+ mm.setThumbMediaId(vm.getMediaId());
+ mm.setMusicUrl("http://y.qq.com/#type=song&mid=002IVyIU4093Xr&play=0");
+ mm.setHQMusicUrl("http://y.qq.com/#type=song&mid=002IVyIU4093Xr&play=0");
+ return mm;
+ }
+
+ @Override
+ public BasicMsg video(VideoMsg vm) {
+ VideoMsg vdm = new VideoMsg(vm);
+ vdm.setTitle("习主席联合国峰会演讲");
+ vdm.setDescription("习主席联合国峰会演讲");
+ vdm.setMediaId("Hfdjlioieijl#22iojkljlkjlutfd");
+ return super.video(vm);
+ }
+
+ }
+
+ class PushEventHandler extends WechatDefHandler {
+
+ @Override
+ public void eSentTmplJobFinish(SentTmlJobEvent stje) {
+ log.info(stje);
+ }
+
+ @Override
+ public void eSentAllJobFinish(SentAllJobEvent saje) {
+ log.info(saje);
+ }
+
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/core/XmlMsgBuilderTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/core/XmlMsgBuilderTest.java
new file mode 100644
index 0000000..3f2e9fe
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/core/XmlMsgBuilderTest.java
@@ -0,0 +1,68 @@
+package io.github.elkan1788.mpsdk4j.core;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+import io.github.elkan1788.mpsdk4j.TestSupport;
+import io.github.elkan1788.mpsdk4j.vo.message.ImageMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.TextMsg;
+import io.github.elkan1788.mpsdk4j.vo.message.VoiceMsg;
+
+/**
+ * XmlMsgBuilder 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class XmlMsgBuilderTest extends TestSupport {
+
+ private static final Log log = Logs.get();
+
+ private String mpId;
+ private String openId;
+ private String mediaId;
+
+ @Before
+ public void init() {
+ log.info("====== XmlMsgBuilderTest ======");
+ mpId = _cr.get("mpId");
+ openId = _cr.get("openId");
+ mediaId = _cr.get("mediaId");
+ }
+
+ @Test
+ public void testText() {
+ log.info("====== XmlMsgBuilder#text ======");
+ TextMsg tm = new TextMsg();
+ tm.setFromUserName(mpId);
+ tm.setToUserName(openId);
+ tm.setContent("Hello world! 世界, 你好!");
+ String txtXml = XmlMsgBuilder.create().text(tm).build();
+ log.info(txtXml);
+ }
+
+ @Test
+ public void testImage() {
+ log.info("====== XmlMsgBuilder#image ======");
+ ImageMsg im = new ImageMsg();
+ im.setFromUserName(mpId);
+ im.setToUserName(openId);
+ im.setMediaId(mediaId);
+ String imgXml = XmlMsgBuilder.create().image(im).build();
+ log.info(imgXml);
+ }
+
+ @Test
+ public void testVoice() {
+ log.info("====== XmlMsgBuilder#voice ======");
+ VoiceMsg vm = new VoiceMsg();
+ vm.setFromUserName(mpId);
+ vm.setToUserName(openId);
+ vm.setMediaId(mediaId);
+ String voiceXml = XmlMsgBuilder.create().voice(vm).build();
+ log.info(voiceXml);
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/mvc/HttpServletSupportTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/HttpServletSupportTest.java
new file mode 100644
index 0000000..8493787
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/HttpServletSupportTest.java
@@ -0,0 +1,79 @@
+package io.github.elkan1788.mpsdk4j.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+import org.xml.sax.SAXException;
+
+import io.github.elkan1788.mpsdk4j.util.StreamTool;
+import mockit.Expectations;
+import mockit.integration.junit4.JMockit;
+
+/**
+ * HttpServletSupport 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(JMockit.class)
+public class HttpServletSupportTest extends WebContainerMockit {
+
+ private static final Log log = Logs.get();
+
+ @Override
+ @Before
+ public void init() {
+ log.info("====== HttpServletSupportTest ======");
+ super.init();
+ }
+
+ @Test
+ public void testGetCheck() throws IOException, SAXException, ServletException {
+ log.info("====== HttpServletSupportTest-get ======");
+
+ ServletContainer sc = new ServletContainer();
+ sc.doGet(req, resp);
+ }
+
+ @Test
+ public void testInteract() throws IOException, SAXException, ServletException {
+ log.info("====== HttpServletSupportTest-post ======");
+ new Expectations() {
+ {
+ // 模拟微信互动数据
+ req.getInputStream();
+ ServletInputStream sis = new ServletInputStream() {
+
+ String textxml = ""
+ + "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "6091046778677430\n"
+ + "";
+
+ InputStream is = StreamTool.toStream(textxml);
+
+ @Override
+ public int read() throws IOException {
+ return is.read();
+ }
+ };
+ returns(sis);
+ }
+ };
+
+ ServletContainer sc = new ServletContainer();
+ sc.doPost(req, resp);
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/mvc/MVCTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/MVCTest.java
new file mode 100644
index 0000000..26b87a6
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/MVCTest.java
@@ -0,0 +1,19 @@
+package io.github.elkan1788.mpsdk4j.mvc;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * mvc 包测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ HttpServletSupportTest.class,
+ WechatWebSupportTest.class
+})
+public class MVCTest {
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/mvc/ServletContainer.java b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/ServletContainer.java
new file mode 100644
index 0000000..aff1a63
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/ServletContainer.java
@@ -0,0 +1,53 @@
+package io.github.elkan1788.mpsdk4j.mvc;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import io.github.elkan1788.mpsdk4j.core.WechatDefHandler;
+import io.github.elkan1788.mpsdk4j.util.ConfigReader;
+import io.github.elkan1788.mpsdk4j.vo.MPAccount;
+
+/**
+ * Servlet容器
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class ServletContainer extends HttpServletSupport {
+
+ private static final long serialVersionUID = 8954466678965988236L;
+
+ private static ConfigReader _cr;
+
+ static {
+ _cr = new ConfigReader("/mpconf.properties");
+ }
+
+ @Override
+ public void init() throws ServletException {
+ MPAccount mpAct = new MPAccount();
+ mpAct.setMpId(_cr.get("mpId"));
+ mpAct.setAppId(_cr.get("appId"));
+ mpAct.setAppSecret(_cr.get("appSecret"));
+ mpAct.setToken(_cr.get("token"));
+ _wk.setMpAct(mpAct);
+ _wk.setWechatHandler(new WechatDefHandler());
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ init();
+ super.doGet(req, resp);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ init();
+ super.doPost(req, resp);
+ }
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WebContainerMockit.java b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WebContainerMockit.java
new file mode 100644
index 0000000..8d73fed
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WebContainerMockit.java
@@ -0,0 +1,44 @@
+package io.github.elkan1788.mpsdk4j.mvc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Before;
+
+import mockit.Expectations;
+import mockit.Mocked;
+
+/**
+ * WEB容器模拟
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class WebContainerMockit {
+
+ @Mocked
+ protected HttpServletRequest req;
+
+ @Mocked
+ protected HttpServletResponse resp;
+
+ @Before
+ public void init() {
+ new Expectations() {
+ {
+ // 模拟服务器检验参数
+ req.getParameterMap();
+ Map data = new HashMap();
+ data.put("signature", new String[]{"8f89b331558f93dd1931f0c01a1dc121e1ef744a"});
+ data.put("timestamp", new String[]{"1435267"});
+ data.put("nonce", new String[]{"ZnFI4vNoiAqbmPyQ-bkOktOt9x"});
+ data.put("echostr", new String[]{"123456"});
+ returns(data);
+
+ }
+ };
+ }
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WebSupportContainer.java b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WebSupportContainer.java
new file mode 100644
index 0000000..8ef267d
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WebSupportContainer.java
@@ -0,0 +1,40 @@
+package io.github.elkan1788.mpsdk4j.mvc;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import io.github.elkan1788.mpsdk4j.core.WechatDefHandler;
+import io.github.elkan1788.mpsdk4j.util.ConfigReader;
+import io.github.elkan1788.mpsdk4j.vo.MPAccount;
+
+/**
+ * WEB 容器
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class WebSupportContainer extends WechatWebSupport {
+
+ private static ConfigReader _cr;
+
+ static {
+ _cr = new ConfigReader("/mpconf.properties");
+ }
+
+ @Override
+ public void init() {
+ MPAccount mpAct = new MPAccount();
+ mpAct.setMpId(_cr.get("mpId"));
+ mpAct.setAppId(_cr.get("appId"));
+ mpAct.setAppSecret(_cr.get("appSecret"));
+ mpAct.setToken(_cr.get("token"));
+ _wk.setMpAct(mpAct);
+ _wk.setWechatHandler(new WechatDefHandler());
+ }
+
+ public void wechat(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ this.interact(req, resp);
+ }
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WechatWebSupportTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WechatWebSupportTest.java
new file mode 100644
index 0000000..332e271
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/mvc/WechatWebSupportTest.java
@@ -0,0 +1,88 @@
+package io.github.elkan1788.mpsdk4j.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.ServletInputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+import io.github.elkan1788.mpsdk4j.util.StreamTool;
+import mockit.Expectations;
+import mockit.integration.junit4.JMockit;
+
+/**
+ * WechatWebSupport 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(JMockit.class)
+public class WechatWebSupportTest extends WebContainerMockit {
+
+ private static final Log log = Logs.get();
+
+ @Override
+ @Before
+ public void init() {
+ log.info("====== WechatWebSupportTest ======");
+ super.init();
+ }
+
+ @Test
+ public void testCheck() throws IOException {
+
+ log.info("====== WechatWebSupportTest-get ======");
+ new Expectations() {
+ {
+ req.getMethod();
+ returns("GET");
+ }
+ };
+
+ WebSupportContainer wsct = new WebSupportContainer();
+ wsct.wechat(req, resp);
+ }
+
+ @Test
+ public void testInteract() throws IOException {
+
+ log.info("====== WechatWebSupportTest-post ======");
+ new Expectations() {
+ {
+ // 模拟微信互动数据
+ req.getInputStream();
+ ServletInputStream sis = new ServletInputStream() {
+
+ String textxml = ""
+ + "\n"
+ + "\n"
+ + "1418182341\n"
+ + "\n"
+ + "\n"
+ + "6091046778677430\n"
+ + "";
+
+ InputStream is = StreamTool.toStream(textxml);
+
+ @Override
+ public int read() throws IOException {
+ return is.read();
+ }
+ };
+ returns(sis);
+
+ req.getMethod();
+ returns("POST");
+ }
+ };
+
+ WebSupportContainer wsct = new WebSupportContainer();
+ wsct.wechat(req, resp);
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/repo/com/qq/weixin/mp/aes/AESTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/repo/com/qq/weixin/mp/aes/AESTest.java
new file mode 100644
index 0000000..ddf5273
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/repo/com/qq/weixin/mp/aes/AESTest.java
@@ -0,0 +1,18 @@
+package io.github.elkan1788.mpsdk4j.repo.com.qq.weixin.mp.aes;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * AES包测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ WXBizMsgCryptTest.class
+})
+public class AESTest {
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/repo/com/qq/weixin/mp/aes/WXBizMsgCryptTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/repo/com/qq/weixin/mp/aes/WXBizMsgCryptTest.java
new file mode 100644
index 0000000..1c0f6c9
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/repo/com/qq/weixin/mp/aes/WXBizMsgCryptTest.java
@@ -0,0 +1,74 @@
+package io.github.elkan1788.mpsdk4j.repo.com.qq.weixin.mp.aes;
+
+import static org.junit.Assert.assertNotNull;
+import io.github.elkan1788.mpsdk4j.util.StreamTool;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.nutz.lang.Lang;
+import org.nutz.log.Log;
+import org.nutz.log.Logs;
+
+/**
+ * WXBizMsgCrypt 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class WXBizMsgCryptTest {
+
+ private static final Log log = Logs.get();
+
+ private String encodingAesKey = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG";
+ private String token = "pamtest";
+ private String timeStamp = "1409304348";
+ private String nonce = "xxxxxx";
+ private String appId = "wxb11529c136998cb6";
+ private String replyMsg = "1407743423";
+ private String fromMsg = "1409304348";
+ private String msgSignature = "9f8883ff0676a51299747fc2d4b2e6a4be9207cb";
+
+ private WXBizMsgCrypt pc;
+
+ @Before
+ public void init() {
+ log.info("====== WXBizMsgCryptTest ======");
+ try {
+ pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
+ }
+ catch (AesException e) {
+ throw Lang.wrapThrow(e);
+ }
+ }
+
+ @Test
+ public void testEncryptMsg() {
+ log.info("====== WXBizMsgCrypt#encryptMsg ======");
+ try {
+ String encryptmsg = pc.encryptMsg(replyMsg, timeStamp, nonce);
+ assertNotNull(encryptmsg);
+ log.info(encryptmsg.replaceAll("\\n", ""));
+ }
+ catch (AesException e) {
+ throw Lang.wrapThrow(e);
+ }
+ }
+
+ @Test
+ public void testDecryptMsg() {
+ log.info("====== WXBizMsgCrypt#decryptMsg ======");
+ try {
+ String decryptmsg = pc.decryptMsg(msgSignature,
+ timeStamp,
+ nonce,
+ StreamTool.toStream(fromMsg));
+ assertNotNull(decryptmsg);
+ log.info(decryptmsg);
+ log.info(pc.getFromAppid());
+ }
+ catch (AesException e) {
+ throw Lang.wrapThrow(e);
+ }
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/util/ConfigReaderTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/util/ConfigReaderTest.java
new file mode 100644
index 0000000..38a26ae
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/util/ConfigReaderTest.java
@@ -0,0 +1,80 @@
+package io.github.elkan1788.mpsdk4j.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * ConfigReader Testing
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class ConfigReaderTest {
+
+ private static final int INTEGER = 1;
+ private static final boolean BOOL = true;
+ private static final long LONG = 100000000000000l;
+
+ private ConfigReader cr;
+
+ @Before
+ public void init() {
+ cr = new ConfigReader("/ErrorCode.properties");
+ cr.put("int", String.valueOf(INTEGER));
+ cr.put("bool", String.valueOf(BOOL));
+ cr.put("long", String.valueOf(LONG));
+ }
+
+ @After
+ public void testClear() {
+ cr.clear();
+ assertNull(cr.get("0"));
+ }
+
+ @Test
+ public void testAll() {
+ List keys = cr.keys();
+ Collection values = cr.values();
+ assertEquals(keys.size(), values.size());
+ }
+
+ @Test
+ public void testGet() {
+ assertNotNull(cr.get("0"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullFile() {
+ new ConfigReader("/test.properties");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullKey() {
+ cr.get(null);
+ }
+
+ @Test
+ public void testGetInt() {
+ assertEquals(cr.getInt("int"), INTEGER);
+ }
+
+ @Test
+ public void testGetLong() {
+ assertEquals(cr.getLong("long"), LONG);
+ }
+
+ @Test
+ public void testGetBoolean() {
+ assertTrue(cr.getBoolean("bool"));
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/util/HttpToolTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/util/HttpToolTest.java
new file mode 100644
index 0000000..205c459
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/util/HttpToolTest.java
@@ -0,0 +1,111 @@
+package io.github.elkan1788.mpsdk4j.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.nutz.json.Json;
+import org.nutz.lang.Files;
+import org.nutz.lang.Lang;
+import org.nutz.lang.Strings;
+
+import io.github.elkan1788.mpsdk4j.TestSupport;
+import io.github.elkan1788.mpsdk4j.vo.ApiResult;
+
+/**
+ * HttpTool 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@SuppressWarnings("unchecked")
+public class HttpToolTest extends TestSupport {
+
+ private String openId;
+ private String appId;
+ private String appSecret;
+ private String accessToken;
+ private String mediaId;
+
+ @Before
+ public void init() {
+ this.openId = _cr.get("openId");
+ this.appId = _cr.get("appId");
+ this.appSecret = _cr.get("appSecret");
+ this.accessToken = _cr.get("accessToken");
+ this.mediaId = _cr.get("mediaId");
+ }
+
+ // 注意access_token接口调用次数,建议跑一次就关闭
+ @Ignore
+ // @Before
+ public void testGet() {
+ if (Strings.isBlank(accessToken)) {
+ String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
+ appId,
+ appSecret);
+ String content = HttpTool.get(url);
+ assertNotNull(content);
+ Map data = (Map) Json.fromJson(content);
+ accessToken = data.get("access_token");
+ assertNotNull(data.get("expires_in"));
+ }
+ assertNotNull(accessToken);
+ }
+
+ @Test
+ public void testPost() {
+ // 测试前请发先消息给公众号
+ String url = String.format("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s",
+ accessToken);
+ String body = "{\"touser\":\""
+ + openId
+ + "\",\"msgtype\":\"text\",\"text\":{\"content\":\"Hello World!\r\n世界,你好!\"}}";
+ String content = HttpTool.post(url, body);
+ assertNotNull(content);
+ assertEquals("{\"errcode\":0,\"errmsg\":\"ok\"}", content);
+
+ }
+
+ @Test
+ public void testUpload() {
+ String url = String.format("https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s",
+ accessToken,
+ "image");
+ File file = new File(this.getClass().getResource("/mpsdk4j-logo.png").getFile());
+ String content = HttpTool.upload(url, file);
+ assertNotNull(content);
+ Map nm = (Map) Json.fromJson(content);
+ assertNotNull(nm.get("created_at"));
+ mediaId = nm.get("media_id");
+ System.out.println(mediaId);
+ }
+
+ // @Ignore
+ @Test
+ public void testDownload() {
+ String url = String.format("https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
+ accessToken,
+ mediaId);
+ Object tmp = HttpTool.download(url);
+ try {
+ if (tmp instanceof File) {
+ Files.copyFile((File) tmp, new File("D:/tmp/mpsdk4j-logo.png"));
+ }
+ else {
+ ApiResult ar = ApiResult.create((String) tmp);
+ System.out.println(ar);
+ }
+ }
+ catch (IOException e) {
+ throw Lang.wrapThrow(e);
+ }
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/util/UtilTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/util/UtilTest.java
new file mode 100644
index 0000000..a1b1c86
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/util/UtilTest.java
@@ -0,0 +1,17 @@
+package io.github.elkan1788.mpsdk4j.util;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Util 包测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ ConfigReaderTest.class,
+ HttpToolTest.class
+})
+public class UtilTest {}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/vo/ApiResultTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/vo/ApiResultTest.java
new file mode 100644
index 0000000..37c309d
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/vo/ApiResultTest.java
@@ -0,0 +1,83 @@
+package io.github.elkan1788.mpsdk4j.vo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * ApiResult 测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+public class ApiResultTest {
+
+ private String sucJson = "{'errcode':0,'errmsg':'Success.'}";
+ private String unKnowErrJson = "{'errcode':9999,'errmsg':'Unkonw error.'}";
+ private String errJson = "{'errcode':-1,'errmsg':'System busy.'}";
+ private String atErrJson1 = "{'errcode':40001,'errmsg':'invalid appsecret'}";
+ private String atErrJson2 = "{'errcode':42001,'errmsg':'access_token over time'}";
+ private String atErrJson3 = "{'errcode':42002,'errmsg':'refresh token over time'}";
+ private String atErrJson4 = "{'errcode':40014,'errmsg':'invalid access_token'}";
+
+ @Test
+ public void testGetJson() {
+ ApiResult ar = ApiResult.create(sucJson);
+ assertEquals(sucJson, ar.getJson());
+ }
+
+ @Test
+ public void testGetErrCode() {
+ ApiResult ar = ApiResult.create(errJson);
+ assertEquals(-1, ar.getErrCode().intValue());
+ }
+
+ @Test
+ public void testGetErrMsg() {
+ ApiResult ar = ApiResult.create(errJson);
+ assertEquals("System busy.", ar.getErrMsg());
+ }
+
+ @Test
+ public void testGetErrCNMsg() {
+ ApiResult ar = ApiResult.create(sucJson);
+ assertEquals("请求成功.", ar.getErrCNMsg());
+ }
+
+ @Test
+ public void testIsSuccess() {
+ ApiResult ar = ApiResult.create(errJson);
+ assertTrue(!ar.isSuccess());
+ }
+
+ @Test
+ public void testIsAccessTokenInvalid() {
+ ApiResult ar = ApiResult.create(atErrJson1);
+ assertFalse(ar.isSuccess());
+ ar = ApiResult.create(atErrJson2);
+ assertFalse(ar.isSuccess());
+ ar = ApiResult.create(atErrJson3);
+ assertFalse(ar.isSuccess());
+ ar = ApiResult.create(atErrJson4);
+ assertFalse(ar.isSuccess());
+ }
+
+ @Test
+ public void testUnknowError() {
+ ApiResult ar = ApiResult.create(unKnowErrJson);
+ assertEquals(unKnowErrJson, ar.getJson());
+ assertEquals("未知错误!", ar.getErrCNMsg());
+ }
+
+ @Test
+ public void testSucWithoutErrCode() {
+ String json = "{'access_token':'ACCESS_TOKEN','expires_in':7200}";
+ ApiResult ar = ApiResult.create(json);
+ assertEquals(json, ar.getJson());
+ assertEquals("Unknow Error!", ar.getErrMsg());
+ assertTrue(ar.isSuccess());
+ }
+
+}
diff --git a/src/test/java/io/github/elkan1788/mpsdk4j/vo/VOTest.java b/src/test/java/io/github/elkan1788/mpsdk4j/vo/VOTest.java
new file mode 100644
index 0000000..0c05639
--- /dev/null
+++ b/src/test/java/io/github/elkan1788/mpsdk4j/vo/VOTest.java
@@ -0,0 +1,18 @@
+package io.github.elkan1788.mpsdk4j.vo;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * VO 包测试
+ *
+ * @author 凡梦星尘(elkan1788@gmail.com)
+ * @since 2.0
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ ApiResultTest.class
+})
+public class VOTest {
+
+}
diff --git a/src/test/java/org/elkan1788/osc/testunit/TestSupport.java b/src/test/java/org/elkan1788/osc/testunit/TestSupport.java
deleted file mode 100644
index 39481b7..0000000
--- a/src/test/java/org/elkan1788/osc/testunit/TestSupport.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.elkan1788.osc.testunit;
-
-import org.elkan1788.osc.weixin.mp.vo.MPAct;
-import org.junit.Before;
-
-import java.util.Properties;
-
-/**
- * 测试父类
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/12
- * @version 1.0.0
- */
-public class TestSupport {
-
- protected String mpId;
- protected String appId;
- protected String appSecret;
- protected String token;
- protected String openId;
- protected String aesKey;
-
- protected String templateId;
- protected String mediaId;
- protected String accessToken;
-
- protected String msgSing;
- protected String timestamp;
- protected String echostr;
- protected String nonce;
-
- protected MPAct mpAct;
-
- @Before
- public void init() throws Exception {
- Properties p = new Properties();
- p.load(getClass().getResourceAsStream("/test-cfg.properties"));
-
- mpId = p.getProperty("mpId");
- appId = p.getProperty("appId");
- appSecret = p.getProperty("appSecret");
- token = p.getProperty("token");
- openId = p.getProperty("openId");
- aesKey = p.getProperty("aesKey");
-
- templateId = p.getProperty("templateId");
- mediaId = p.getProperty("mediaId");
- accessToken = p.getProperty("accessToken", "NOT");
-
- msgSing = p.getProperty("msgSing");
- timestamp = p.getProperty("timestamp");
- echostr = p.getProperty("echostr");
- nonce = p.getProperty("nonce");
-
- mpAct = new MPAct();
- mpAct.setMpId(mpId);
- mpAct.setAppId(appId);
- mpAct.setAppSecret(appSecret);
- mpAct.setToken(token);
- mpAct.setAESKey(aesKey);
- if (!accessToken.equals("NOT")||!accessToken.isEmpty()) {
- mpAct.setAccessToken(accessToken);
- mpAct.setExpiresIn(7000 * 1000 + System.currentTimeMillis());
- }
- }
-}
diff --git a/src/test/java/org/elkan1788/osc/weixin/mp/core/WxApiImplTest.java b/src/test/java/org/elkan1788/osc/weixin/mp/core/WxApiImplTest.java
deleted file mode 100644
index f58d272..0000000
--- a/src/test/java/org/elkan1788/osc/weixin/mp/core/WxApiImplTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import org.elkan1788.osc.testunit.TestSupport;
-import org.elkan1788.osc.weixin.mp.util.SimpleHttpReq;
-import org.elkan1788.osc.weixin.mp.vo.*;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * 微信API接口测试
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/12
- */
-public class WxApiImplTest extends TestSupport {
-
- private WxApi wxApi;
-
- @Before
- public void init() throws Exception {
- super.init();
-
- wxApi = new WxApiImpl(mpAct);
- if ("NOT".equals(accessToken)
- || "".equals(accessToken)
- || accessToken.isEmpty()) {
- mpAct.setToken(wxApi.getAccessToken());
- mpAct.setExpiresIn(7000 * 1000 + System.currentTimeMillis());
- }
- System.out.println("ACCESS_TOKEN: " + mpAct.getAccessToken());
- }
-
- @Test
- public void testGetAccessToken() throws Exception {
- String token = wxApi.getAccessToken();
- System.out.println(token);
- }
-
- @Test
- public void testGetServerIp() throws Exception {
- List ips = wxApi.getServerIp();
- for (String ip : ips) {
- System.out.println(ip);
- }
- }
-
- @Test
- public void testGetMenu() throws Exception {
- List menus = wxApi.getMenu();
- System.out.println("拉取到的菜单: " + menus);
- }
-
- @Test
- public void testCreateMenu() throws Exception {
- // 点击或视图菜单
- Menu m1 = new Menu("基本");
- Menu csdn = new Menu("CSDN", Menu.VIEW, "http://www.csdn.net");
- Menu osc = new Menu("OSC", Menu.VIEW, "http://www.oschina.net");
- Menu click = new Menu("点击我", Menu.CLICK, "Thanks you click me!");
- m1.setSubButtons(Arrays.asList(csdn, osc, click));
- // 发送相片或位置
- Menu m2 = new Menu("发送");
- Menu sysphoto = new Menu("拍照", Menu.PIC_SYSPHOTO, "pic_sysphoto");
- Menu album = new Menu("拍照或相册", Menu.PIC_PHOTO_OR_ALBUM, "pic_photo_or_album");
- Menu weixin = new Menu("微信相册", Menu.PIC_WEIXIN, "pic_weixin");
- Menu location = new Menu("位置", Menu.LOCATION_SELECT, "location_select");
- m2.setSubButtons(Arrays.asList(sysphoto, album, weixin, location));
- // 扫码菜单
- Menu m3 = new Menu("扫码");
- Menu push = new Menu("推送", Menu.SCANCODE_PUSH, "scancode_push");
- Menu wait = new Menu("等待", Menu.SCANCODE_WAITMSG, "scancode_waitmsg");
- m3.setSubButtons(Arrays.asList(push, wait));
-
- boolean flag = wxApi.createMenu(m1, m2, m3);
- System.out.println("创建菜单: " + flag);
- }
-
- @Test
- public void testDeleteMenu() throws Exception {
- boolean flag = wxApi.deleteMenu();
- System.out.println("删除菜单: " + flag);
- }
-
- @Test
- public void testCreatGroup() throws Exception {
- int groupId = wxApi.creatGroup("公司员工");
- System.out.println("创建分组: " + groupId);
- }
-
- @Test
- public void testGetGroups() throws Exception {
- List groups = wxApi.getGroups();
- System.out.println("拉取到的分组: " + groups);
- }
-
- @Test
- public void testRenGroup() throws Exception {
- boolean flag = wxApi.renGroup(104, "内部测试人员");
- System.out.println("修改分组: " + flag);
- }
-
- @Test
- public void testGetGroupId() throws Exception {
- int groupId = wxApi.getGroupId(openId);
- System.out.println("拉取到用户分组: " + groupId);
- }
-
- @Test
- public void testMove2Group() throws Exception {
- boolean flag = wxApi.move2Group("oMIXfjjEB8ifmUpjauItMXpGAik0", 104);
- System.out.println("移动用户分组: " + flag);
- }
-
- @Test
- public void testGetFollowerList() throws Exception {
- FollowList follows = wxApi.getFollowerList("");
- System.out.println("拉取用户关注列表: " + follows);
- }
-
- @Test
- public void testGetFollower() throws Exception {
- Follower follower = wxApi.getFollower(openId, "zh_CN");
- System.out.println("拉取用户的信息: " + follower);
- }
-
- @Test
- public void testSendCustomerMsg() throws Exception {
- // 文本客服消息
- OutPutMsg msg = new OutPutMsg();
- msg.setToUserName(openId);
- msg.setMsgType(WxApi.TEXT);
- msg.setContent("感谢你持续关注我们的公众号[微笑].");
- boolean flag = wxApi.sendCustomerMsg(msg);
- System.out.println("发送文本客服消息: " + flag);
- // 图像客服消息
- /*msg.setMsgType(WxApi.IMAGE);
- msg.setMediaId(mediaId);
- flag = wxApi.sendCustomerMsg(msg);
- System.out.println("发送图像客服消息: " + flag);*/
- }
-
- @Test
- public void testSendTemplateMsg() throws Exception {
- Template first = new Template("first", "#fffff", "faithzhang回复了您的评论");
- Template keyword = new Template("keyword", "#cccccc", "请问腾讯的妈妈们都几点下班?");
- Template time = new Template("time", "#000000", "2014/11/11 11:11:11");
- boolean flag = wxApi.sendTemplateMsg(openId, templateId, "#FF0000", "", first, keyword, time);
- System.out.println("发送模板消息: " + flag);
- }
-
- @Test
- public void testUpMedia() throws Exception {
- File image = new File("D:/upload.jpg");
- String mediaId = wxApi.upMedia("image", image);
- System.out.println("上传多媒体文件: " + mediaId);
- }
-
- @Test
- public void testDlMedia() throws Exception {
- File image = new File("D:/dl/" + mediaId + ".jpg");
- wxApi.dlMedia(mediaId, image);
- }
-
- @Test
- public void testUpNews() throws Exception {
- File image1 = new File("D:/art1.jpg");
- String mediaId1 = wxApi.upMedia(WxApi.IMAGE, image1);
- File image2 = new File("D:/art2.jpg");
- String mediaId2 = wxApi.upMedia(WxApi.IMAGE, image2);
- Article2 art1 = new Article2();
- art1.setTitle("不差钱!玩酷4G上线送话费啦!");
- art1.setDigest("不差钱!玩酷4G上线送话费啦!!");
- art1.setAuthor("凡梦星尘");
- art1.setContent("
就是那么有钱!就是那么任性!
这个季节,谁最风靡,是的,是我们玩酷4G!
这个年龄段,谁能带领互联网潮流,是的,是我们玩酷4G!
玩酷4G新上线啦,这里有新鲜、时尚的IT资讯,新潮、免费的产品体验,我们的福利多多!就是那么有钱,就是那么任性,就是那么时尚时尚最时尚!
玩酷4G公共账号上线第一波活动!咱们年轻人!不差钱!
活动一:关注玩酷4G公共账号,就有机会获赠电信充值卡。
1、小伙伴们只要关注玩酷4G,就自动拥有抽奖资格了。
2、等着好运降临!
3、奖品:11888话费充值卡。每期活动有:100元2名!50元4名!10元40名! 11888话费卡可以充值话费、宽带费、翼支付,绝对的生活好帮手!
4、活动从11月21日起正式开启!每周三公布获奖的小伙伴名单!共持续四期!
5、获奖查询可以点击“中奖名单”,小伙伴们记得保持关注哦!
活动二:关注玩酷4G公共账号,就有机会免费体验最新的互联网单品!华为荣耀立方智能路由器、Bong手环、天翼手机交通卡,一网打尽!
1、关注玩酷4G账号,在“玩酷爆点”中点击你喜欢的互联网单品按要求报名参加体验活动。
2、首批互联网单品有:
超越小米手环的手环Bong!11月21日起,每周四公布获得Bong的小伙伴,连续三期,每期1名。
让生活无比简单的翼支付手机交通卡!没有名额限制。只要你报名,就让你体验!11月29日将公布全部体验成功的小伙伴名单。
新时代的智能路由器华为荣耀立方!价值800!畅想精彩互联家庭生活!12月6日公布,只有一台,不要错过哦!
");
- art1.setMediaId(mediaId1);
- art1.setShowCover(1);
- art1.setSourceUrl("http://mp.weixin.qq.com/s?__biz=MzA3MTUyMTMyNg==&mid=201733564&idx=1&sn=ad92ead6499c322b4273cfb39708d40a&key=475e040e205b91d666e07d715eedc09b47d3c4631448d3cf4c229fec511f83e55cebe78da209f0aa51fcd1d8a82302e2&ascene=1&uin=MTU1ODU2MzgwMg%3D%3D&devicetype=webwx&version=70000001&pass_ticket=JG3EHTQ5Idcfm%2Bqt%2BhbFaY8U%2BKx3wCm%2FS6JZomsTeS10EjFBAsYWqTWOctZiAl5C");
-
- Article2 art2 = new Article2();
- art2.setTitle("【实用攻略】火车票预售期将延长至60天,买票攻略get!火速收藏~ ");
- art2.setDigest("【实用攻略】火车票预售期将延长至60天,买票攻略get!火速收藏~ ");
- art2.setAuthor("凡梦星尘");
- art2.setContent("自2014年12月1日起,中国铁路总公司将用一周时间,逐步将铁路互联网售票、电话订票的预售期,由目前的20天延长至60天。具体实施方法为:");
- art2.setMediaId(mediaId2);
- art2.setShowCover(1);
- art2.setSourceUrl("http://mp.weixin.qq.com/s?__biz=MzA4OTEwNDkyMw==&mid=201489837&idx=2&sn=a86b67dd34894ee1f124b2ddcd02c35b#rd");
-
- String[] results = wxApi.upNews(art1, art2);
- System.out.println("msgtype:"+results[0]);
- System.out.println("mediaid:"+results[1]);//q2t8zU4BGSH58YsBkL_WCdjdvVDZG1oyxe3NRgioLQp0gGjolztVjP6B4mugLfhE
- System.out.println("createat:"+results[2]);
-
- }
-
- @Test
- public void testUpVideo() throws Exception {
- File mp4 = new File("D:/kajiaren_clip.mp4");
- String mediaId = "KIV7QppP1LEwsXcUiSHx5BZEV4sIW53a_iX7uHWtU8QyG4maRvPiodiR_6t4JkX3"; //wxApi.upMedia(WxApi.VIDEO, mp4);
- System.out.println(mediaId);//KIV7QppP1LEwsXcUiSHx5BZEV4sIW53a_iX7uHWtU8QyG4maRvPiodiR_6t4JkX3
- String[] results = wxApi.upVideo(mediaId,"歌曲《客家人系有料》","歌曲《客家人系有料》");
- System.out.println("msgtype:"+results[0]);
- System.out.println("mediaid:"+results[1]);//-h6ETcIv_vOeS_X3Wjf2VlSuwWiPfZSJBelgKlNffqDB8pgg7QWWPG986vOCmG3G
- System.out.println("createat:"+results[2]);
- }
-
- @Test
- public void testSendAll() throws Exception {
- OutPutMsg outmsg = new OutPutMsg();
- outmsg.setToUsers(Arrays.asList(openId));
- outmsg.setMsgType(WxApi.MPNEWS);
- outmsg.setMediaId("-ClbTNHmkAYlBmuY0lK-_GMipA7rDQvlekihc8u6oCr3AcQkemGcI1Nxj8Xtma_9");
- String msgid = wxApi.sendAll(outmsg);
- System.out.println("news msgid:"+msgid);//2348282442
-
- /* outmsg.setMediaId("-h6ETcIv_vOeS_X3Wjf2VlSuwWiPfZSJBelgKlNffqDB8pgg7QWWPG986vOCmG3G");
- outmsg.setMsgType(WxApi.MPVIDEO);
- outmsg.setGroupId("104");
- String msgid = wxApi.sendAll(outmsg);
- System.out.println("video msgid:"+msgid);*///2348282861
- }
-
- @Test
- public void testDelSendAll() throws Exception {
- boolean flag = wxApi.delSendAll("2348282861");
- System.out.println("delsendall:"+flag);
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/elkan1788/osc/weixin/mp/core/WxBaseTest.java b/src/test/java/org/elkan1788/osc/weixin/mp/core/WxBaseTest.java
deleted file mode 100644
index 674634b..0000000
--- a/src/test/java/org/elkan1788/osc/weixin/mp/core/WxBaseTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.elkan1788.osc.weixin.mp.core;
-
-import org.elkan1788.osc.testunit.TestSupport;
-import org.elkan1788.osc.weixin.mp.util.StreamTool;
-import org.elkan1788.osc.weixin.mp.util.XmlMsgBuilder;
-import org.junit.Test;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.Is.is;
-
-
-/**
- * 微信公众平台普通消息互动测试
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @version 1.0.3
- * @since 2015/1/11
- */
-public class WxBaseTest extends TestSupport {
-
- private WxBase wxBase = new WxBase();
- private WxHandler handler = new WxDefaultHandler();
-
- @Override
- public void init() throws Exception {
- super.init();
- this.wxBase.setMpAct(mpAct);
- this.wxBase.setWxHandler(handler);
- this.wxBase.setMsgSignature(msgSing);
- this.wxBase.setTimeStamp(timestamp);
- this.wxBase.setNonce(nonce);
- this.wxBase.setMpAct(mpAct);
- this.wxBase.setAesEncrypt(true);
- }
-
-
- private String textXml = "\n" +
- "\n" +
- "1418182341\n" +
- "\n" +
- "\n" +
- "6091046778677430\n" +
- "";
-
- private String enrcpXml = "\n" +
- " \n" +
- " \n" +
- "";
-
- private String pushXml = "\n" +
- "" + this.mpId + "\n" +
- "1413192605\n" +
- "component_verify_ticket\n" +
- "\n" +
- "";
-
- /**
- * 测试微信验证URL方法
- */
- @Test
- public void testCheck() throws Exception {
- String echostr = this.wxBase.check();
- assertThat(echostr, is(this.wxBase.getEchostr()));
- }
-
- /**
- * 测试微信普通互动与事件消息
- */
- @Test
- public void testHandler() throws Exception {
- if (this.wxBase.isAesEncrypt()) {
- // 加密消息
- this.wxBase.setWxInMsg(StreamTool.toStream(this.enrcpXml));
- } else {
- this.wxBase.setWxInMsg(StreamTool.toStream(this.textXml));
- }
- String reply_msg = this.wxBase.handler();
- String xml_msg = XmlMsgBuilder.create().
- text(this.wxBase.getOutPutMsg()).build();
- assertThat(reply_msg, is(xml_msg));
- }
-
- /**
- * 测试微信开放平台推送事件消息
- */
- @Test
- public void testHandlerPush() throws Exception {
- this.wxBase.setWxInMsg(StreamTool.toStream(this.pushXml));
- String reply_msg = this.wxBase.handlerPush();
- assertThat("success", is(reply_msg));
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/elkan1788/osc/weixin/mp/util/SimpleHttpReqTest.java b/src/test/java/org/elkan1788/osc/weixin/mp/util/SimpleHttpReqTest.java
deleted file mode 100644
index f011889..0000000
--- a/src/test/java/org/elkan1788/osc/weixin/mp/util/SimpleHttpReqTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.elkan1788.osc.weixin.mp.util;
-
-import com.alibaba.fastjson.JSON;
-import org.elkan1788.osc.testunit.TestSupport;
-import org.elkan1788.osc.weixin.mp.commons.WxApiUrl;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * HTTP请求测试
- *
- * @author 凡梦星尘(elkan1788@gmail.com)
- * @since 2014/11/12
- */
-public class SimpleHttpReqTest extends TestSupport {
-
- private String mediaType = "image";
-
- @Before
- public void init() throws Exception {
- super.init();
- }
-
- @Test
- public void testGet() throws Exception {
- String url = String.format(WxApiUrl.ACCESS_TOKEN_API, appId, appSecret);
- System.out.println(url);
- String content = SimpleHttpReq.get(url);
- System.out.println(content);
- }
-
- @Test
- public void testPost() throws Exception {
- Map msg = new HashMap<>();
- msg.put("touser", openId);
- msg.put("msgtype", mediaType);
- Map image = new HashMap<>();
- image.put("media_id", mediaId);
- msg.put("image", image);
- String url = String.format(WxApiUrl.CUSTOM_MESSAGE_API, accessToken);
- System.out.println(url);
- System.out.println(JSON.toJSONString(msg));
- String content = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, JSON.toJSONString(msg));
- System.out.println(content);
- }
-
- @Test
- public void testUpload() throws Exception {
- File f = new File("D:/upload.jpg");
- String url = String.format(WxApiUrl.MEDIA_UP_API, mediaType, accessToken);
- System.out.println(url);
- String content = SimpleHttpReq.upload(url, f);
- System.out.println(content);
- }
-
- @Test
- public void testDownload() throws Exception {
- File f = new File("D:/download.jpg");
- String url = String.format(WxApiUrl.MEDIA_DL_API, accessToken, mediaId);
- System.out.println(url);
- SimpleHttpReq.download(url, f);
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/elkan1788/osc/weixin/mp/util/StreamUtilTest.java b/src/test/java/org/elkan1788/osc/weixin/mp/util/StreamUtilTest.java
deleted file mode 100644
index 23258e8..0000000
--- a/src/test/java/org/elkan1788/osc/weixin/mp/util/StreamUtilTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.elkan1788.osc.weixin.mp.util;
-
-import org.junit.Test;
-
-import java.io.InputStream;
-
-public class StreamUtilTest {
-
- @Test
- public void testStr2Stream() throws Exception {
-
- }
-
- @Test
- public void testStream2String() throws Exception {
- InputStream is = this.getClass().getResourceAsStream("/mysqlnginx.txt");
- long t1 = System.currentTimeMillis();
- String str = StreamTool.toString(is);
- long t2 = System.currentTimeMillis();
- System.out.println(str);
- System.out.println((t2-t1));
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/elkan1788/osc/weixin/mp/util/XmlMsgBuilderTest.java b/src/test/java/org/elkan1788/osc/weixin/mp/util/XmlMsgBuilderTest.java
deleted file mode 100644
index 07545af..0000000
--- a/src/test/java/org/elkan1788/osc/weixin/mp/util/XmlMsgBuilderTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.elkan1788.osc.weixin.mp.util;
-
-import org.elkan1788.osc.testunit.TestSupport;
-import org.elkan1788.osc.weixin.mp.core.WxApi;
-import org.elkan1788.osc.weixin.mp.vo.Article;
-import org.elkan1788.osc.weixin.mp.vo.OutPutMsg;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-public class XmlMsgBuilderTest extends TestSupport {
-
- private OutPutMsg msg;
-
- @Before
- public void init() {
- msg = new OutPutMsg(openId, mpId, WxApi.TEXT);
- List articles = new ArrayList<>();
- for (int i=1; i<11; i++) {
- Article a = new Article();
- a.setTitle(getRandomStr(new Random().nextInt(100)+20));
- a.setDescription(getRandomStr(new Random().nextInt(200) + 120));
- a.setPicUrl(getRandomStr(new Random().nextInt(60) + 20));
- a.setUrl(getRandomStr(new Random().nextInt(80) + 20));
- articles.add(a);
- }
- msg.setArticles(articles);
- }
-
- private String getRandomStr(int length) {
- String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- Random random = new Random();
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < length; i++) {
- int number = random.nextInt(base.length());
- sb.append(base.charAt(number));
- }
- return sb.toString();
- }
-
- @Test
- public void testText() throws Exception {
- msg.setContent(getRandomStr(20));
- long t1 = System.currentTimeMillis();
- String xml = XmlMsgBuilder.create().text(msg).build();
- long t2 = System.currentTimeMillis();
- System.out.println(xml);
- System.out.println((t2-t1));
- }
-
- @Test
- public void testImage() throws Exception {
-
- }
-
- @Test
- public void testNews() throws Exception {
- long t = 0l;
- String xml = "";
- for(int i=0; i<101; i++) {
- long t1 = System.currentTimeMillis();
- xml = XmlMsgBuilder.create().news(msg).build();
- long t2 = System.currentTimeMillis();
- t+= (t2 - t1);
- }
- System.out.println(((double)t / 101.0));
- t = 0l;
- for(int i=0; i<101; i++) {
- long t1 = System.currentTimeMillis();
- XmlMsgBuilder xb = new XmlMsgBuilder();
- xb.news(msg);
- xml = xb.build();
- long t2 = System.currentTimeMillis();
- t+= (t2 - t1);
- }
- System.out.println(((double)t / 101.0));
- System.out.println(xml);
- }
-}
\ No newline at end of file
diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties
new file mode 100644
index 0000000..3181327
--- /dev/null
+++ b/src/test/resources/log4j.properties
@@ -0,0 +1,5 @@
+log4j.rootLogger=DEBUG,STDOUT
+log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
+log4j.appender.STDOUT.Target=System.out
+log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
+log4j.appender.STDOUT.layout.ConversionPattern=%d{ABSOLUTE} %3p %c{1}:%L - %m%n
\ No newline at end of file
diff --git a/src/test/resources/mpconf.properties b/src/test/resources/mpconf.properties
new file mode 100644
index 0000000..9c47596
--- /dev/null
+++ b/src/test/resources/mpconf.properties
@@ -0,0 +1,15 @@
+## wechat 配置文件
+mpId=
+appId=
+appSecret=
+token=
+accessToken=
+jsTicket=
+
+## 测试数据
+openId=
+openId2=
+groupId=
+mediaId=
+ticket=
+tmplId=
\ No newline at end of file
diff --git a/src/test/resources/mpsdk4j-logo.png b/src/test/resources/mpsdk4j-logo.png
new file mode 100644
index 0000000..4cea696
Binary files /dev/null and b/src/test/resources/mpsdk4j-logo.png differ