* #519 修复小程序客服消息 URL 被转义的问题 * 优化单元测试提示信息 * 网页授权url增加&connect_redirect=1参数解决两次重定向跳转问题: https://blog.csdn.net/jiangguilong2000/article/details/79416615 * 修复错误的feeToYuan方法名为fenToYuan * #529 EntPayBankRequest增加默认构造函数 * #529 EntPayBankResult中cmmsAmount的数据类型改为Integer * #528 WxMpUser类增加三个属性:subscribe_scene、 qr_scene 和qr_scene_str * 修复代码 * 发布3.0.1.BETA测试版本 * #533 微信刷卡支付请求类增加缺少的三个参数 * #536 企业号模块增加获取企业号应用相关接口 * 定义《企业号应用》的bean * 增加《获取企业号应用》接口实现 * 增加获取测试企业号应用信息测试类 * #535 修复Tomcat 不能正常关闭的问题,增加线程池shutdown相关的操作 * #541 企业号增加实现管理标签的(获取标签成员)接口 * 定义《企业号应用》的bean * 增加《获取企业号应用》接口实现 * 增加获取测试企业号应用信息测试类 * tag service增加获取标签成员方法 http://qydev.weixin.qq.com/wiki/index.php?title=管理标签 * #534 公众号发送模版消息中的小程序path改回pagepath * 发布3.0.2.BETA测试版本 * #547 开放平台模块 componentAccessToken 增加过期自动刷新 * createOrder方法增加H5支付的支持 * #551 文本卡片消息增加btntext字段 * #550 企业微信删除标签成员接口增加部门列表参数 * 清理无用代码 * #530 微信支付申请退款接口结果类增加单个代金券相关参数 ,并根据官方文档整理其他参数 * #531 小程序WxMaMessage类增加小程序卡片消息相关的几个属性 * #520 企业微信网页授权增加使用user_ticket获取成员详情的接口 * 发布3.0.3.BETA测试版本 * 优化代码 * 完善测试 * #559 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * #560 微信开放平台:增加小程序代码模板库管理 * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * #562 小程序增加代码管理相关 API * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * #563 小程序增加修改服务器地址、成员管理 API * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * #565 小程序增加数据分析相关 API * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * 小程序:增加数据分析相关 API * #567 微信开放平台增加 HTTP proxy 机制 * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * 小程序:增加数据分析相关 API * 微信开放平台:增加 HTTP proxy 机制 * #568 修复三方平台多次授权时,RefreshToken 没有刷新的问题 * fix 多次授权时,RefreshToken 没有刷新 * null 判断 * 发布3.0.4.BETA测试版本 * fix code * #569 微信支付几个查询关闭对账下载相关接口增加重载方法,以方便客户端指定更多参数 * #578 微信开放平台增加 WxMaUserService 的实现 * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * 小程序:增加数据分析相关 API * 微信开放平台:增加 HTTP proxy 机制 * 微信开放平台:增加 WxMaUserService 的实现 * 修复小程序码的相关方法命名:WxCode->WxaCode, WxCodeLimit -> WxaCodeUnlimit * #556 日志信息中如果含有secret值的,将其值隐藏掉 * #585 小程序二维码支持is_hyaline参数生成透明背景二维码 * 发布3.0.5.BETA测试版本 * #584 修复企业付款到银行卡接口签名失败的问题 * 简化代码 * #586 微信支付 WxPayConfig增加支持byte数组方式设置证书 * #581 增加微信公众号错误信息枚举类WxMpErrorMsg,并提供方法,方便根据错误代码查询错误信息内容 * #555 修复微信支付服务商模式支付验证签名失败的问题 * #521 微信支付回调通知类WxPayOrderNotifyResult增加version参数 * #583 企业微信新增人员接口新增字段to_invite * #583 企业微信通讯录管理增加邀请成员接口 * #587 企业微信几个接口增加个人二维码字段 * 修复字符 * 修复单元测试 * 发布3.0.6.BETA测试版本 * 重构WxError相关代码,自动根据代码补充错误中文说明 * 优化微信支付代码 * #584 修复企业付款queryEntPay签名失败问题 * #591 文件上传接口不自动关闭inputStream,由调用方自己控制 * #595 优化WxPayException * 发布3.0.7.BETA测试版本 * 更新pom * 优化代码 * #615 公众号客服消息添加 "发送小程序卡片" 类型 * 优化XStreamTransformer * 微信支付模块jodd-http修改scope * 发布3.0.8.BETA测试版本 * #623 群发接口增加clientmsgid * add author for some files * clean code * 重构规范RequestExecuter代码 * #532 实现微信AI开放接口的三个接口:语音上传、查询识别结果和微信翻译功能 * 发布3.0.9.BETA测试版本 * #516 增加获取Wi-Fi门店列表接口 * #629 修复WxPayOrderNotifyResult解析xml报错问题 * #639 修复小程序代码模版库管理 access_token key 错误 * 发布3.1.0正式版本master
@@ -6,7 +6,7 @@ | |||
<modelVersion>4.0.0</modelVersion> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-java-parent</artifactId> | |||
<version>3.0.0</version> | |||
<version>3.1.0</version> | |||
<packaging>pom</packaging> | |||
<name>Weixin Java Tools - Parent</name> | |||
<description>微信公众号、企业号上级POM</description> | |||
@@ -7,7 +7,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-java-parent</artifactId> | |||
<version>3.0.0</version> | |||
<version>3.1.0</version> | |||
</parent> | |||
<artifactId>weixin-java-common</artifactId> | |||
@@ -109,6 +109,11 @@ | |||
<artifactId>jetty-servlet</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.assertj</groupId> | |||
<artifactId>assertj-guava</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
@@ -0,0 +1,32 @@ | |||
package me.chanjar.weixin.common; | |||
/** | |||
* <pre> | |||
* 微信类型枚举. | |||
* Created by BinaryWang on 2018/5/14. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
public enum WxType { | |||
/** | |||
* 企业微信 | |||
*/ | |||
CP, | |||
/** | |||
* 微信公众号 | |||
*/ | |||
MP, | |||
/** | |||
* 微信小程序 | |||
*/ | |||
MiniApp, | |||
/** | |||
* 微信开放平台 | |||
*/ | |||
Open, | |||
/** | |||
* 微信支付 | |||
*/ | |||
Pay; | |||
} |
@@ -78,6 +78,11 @@ public class WxConsts { | |||
* 转发到客服的消息. | |||
*/ | |||
public static final String TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; | |||
/** | |||
* 小程序卡片(要求小程序与公众号已关联) | |||
*/ | |||
public static final String MINIPROGRAMPAGE="miniprogrampage"; | |||
} | |||
/** | |||
@@ -1,6 +1,6 @@ | |||
package me.chanjar.weixin.common.api; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
/** | |||
* WxErrorException处理器. | |||
@@ -1,38 +0,0 @@ | |||
package me.chanjar.weixin.common.bean.result; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||
import java.io.Serializable; | |||
/** | |||
* 微信错误码说明,请阅读: <a href="http://mp.weixin.qq.com/wiki/10/6380dc743053a91c544ffd2b7c959166.html">全局返回码说明</a>. | |||
* | |||
* @author Daniel Qian | |||
*/ | |||
@Data | |||
@Builder | |||
public class WxError implements Serializable { | |||
private static final long serialVersionUID = 7869786563361406291L; | |||
private int errorCode; | |||
private String errorMsg; | |||
private String json; | |||
public static WxError fromJson(String json) { | |||
return WxGsonBuilder.create().fromJson(json, WxError.class); | |||
} | |||
@Override | |||
public String toString() { | |||
if (this.json != null) { | |||
return this.json; | |||
} | |||
return "错误: Code=" + this.errorCode + ", Msg=" + this.errorMsg; | |||
} | |||
} |
@@ -0,0 +1,806 @@ | |||
package me.chanjar.weixin.common.error; | |||
import lombok.Getter; | |||
/** | |||
* <pre> | |||
* 企业微信全局错误码. | |||
* 参考文档:<a href="https://work.weixin.qq.com/api/doc#10649">企业微信全局错误码</a> | |||
* Created by Binary Wang on 2018/5/13. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
@Getter | |||
public enum WxCpErrorMsgEnum { | |||
/** | |||
* 系统繁忙;服务器暂不可用,建议稍候重试。建议重试次数不超过3次。 | |||
*/ | |||
CODE_1(-1, "系统繁忙;服务器暂不可用,建议稍候重试。建议重试次数不超过3次。"), | |||
/** | |||
* 请求成功;接口调用成功 | |||
*/ | |||
CODE_0(0, "请求成功;接口调用成功"), | |||
/** | |||
* 不合法的secret参数;secret在应用详情/通讯录管理助手可查看 | |||
*/ | |||
CODE_40001(40001, "不合法的secret参数;secret在应用详情/通讯录管理助手可查看"), | |||
/** | |||
* 无效的UserID | |||
*/ | |||
CODE_40003(40003, "无效的UserID"), | |||
/** | |||
* 不合法的媒体文件类型;不满足系统文件要求。参考:上传的媒体文件限制 | |||
*/ | |||
CODE_40004(40004, "不合法的媒体文件类型;不满足系统文件要求。参考:上传的媒体文件限制"), | |||
/** | |||
* 不合法的type参数;合法的type取值,参考:上传临时素材 | |||
*/ | |||
CODE_40005(40005, "不合法的type参数;合法的type取值,参考:上传临时素材"), | |||
/** | |||
* 不合法的文件大小;系统文件要求,参考:上传的媒体文件限制 | |||
*/ | |||
CODE_40006(40006, "不合法的文件大小;系统文件要求,参考:上传的媒体文件限制"), | |||
/** | |||
* 不合法的media_id参数 | |||
*/ | |||
CODE_40007(40007, "不合法的media_id参数"), | |||
/** | |||
* 不合法的msgtype参数;合法的msgtype取值,参考:消息类型 | |||
*/ | |||
CODE_40008(40008, "不合法的msgtype参数;合法的msgtype取值,参考:消息类型"), | |||
/** | |||
* 上传图片大小不是有效值;图片大小的系统限制,参考上传的媒体文件限制 | |||
*/ | |||
CODE_40009(40009, "上传图片大小不是有效值;图片大小的系统限制,参考上传的媒体文件限制"), | |||
/** | |||
* 上传视频大小不是有效值;视频大小的系统限制,参考上传的媒体文件限制 | |||
*/ | |||
CODE_40011(40011, "上传视频大小不是有效值;视频大小的系统限制,参考上传的媒体文件限制"), | |||
/** | |||
* 不合法的CorpID;需确认CorpID是否填写正确,在 web管理端-设置 可查看 | |||
*/ | |||
CODE_40013(40013, "不合法的CorpID;需确认CorpID是否填写正确,在 web管理端-设置 可查看"), | |||
/** | |||
* 不合法的access_token | |||
*/ | |||
CODE_40014(40014, "不合法的access_token"), | |||
/** | |||
* 不合法的按钮个数;菜单按钮1-3个 | |||
*/ | |||
CODE_40016(40016, "不合法的按钮个数;菜单按钮1-3个"), | |||
/** | |||
* 不合法的按钮类型;支持的类型,参考:按钮类型 | |||
*/ | |||
CODE_40017(40017, "不合法的按钮类型;支持的类型,参考:按钮类型"), | |||
/** | |||
* 不合法的按钮名字长度;长度应不超过16个字节 | |||
*/ | |||
CODE_40018(40018, "不合法的按钮名字长度;长度应不超过16个字节"), | |||
/** | |||
* 不合法的按钮KEY长度;长度应不超过128字节 | |||
*/ | |||
CODE_40019(40019, "不合法的按钮KEY长度;长度应不超过128字节"), | |||
/** | |||
* 不合法的按钮URL长度;长度应不超过1024字节 | |||
*/ | |||
CODE_40020(40020, "不合法的按钮URL长度;长度应不超过1024字节"), | |||
/** | |||
* 不合法的子菜单级数;只能包含一级菜单和二级菜单 | |||
*/ | |||
CODE_40022(40022, "不合法的子菜单级数;只能包含一级菜单和二级菜单"), | |||
/** | |||
* 不合法的子菜单按钮个数;子菜单按钮1-5个 | |||
*/ | |||
CODE_40023(40023, "不合法的子菜单按钮个数;子菜单按钮1-5个"), | |||
/** | |||
* 不合法的子菜单按钮类型;支持的类型,参考:按钮类型 | |||
*/ | |||
CODE_40024(40024, "不合法的子菜单按钮类型;支持的类型,参考:按钮类型"), | |||
/** | |||
* 不合法的子菜单按钮名字长度;支持的类型,参考:按钮类型 | |||
*/ | |||
CODE_40025(40025, "不合法的子菜单按钮名字长度;支持的类型,参考:按钮类型"), | |||
/** | |||
* 不合法的子菜单按钮KEY长度;长度应不超过60个字节 | |||
*/ | |||
CODE_40026(40026, "不合法的子菜单按钮KEY长度;长度应不超过60个字节"), | |||
/** | |||
* 不合法的子菜单按钮URL长度;长度应不超过1024字节 | |||
*/ | |||
CODE_40027(40027, "不合法的子菜单按钮URL长度;长度应不超过1024字节"), | |||
/** | |||
* 不合法的oauth_code | |||
*/ | |||
CODE_40029(40029, "不合法的oauth_code"), | |||
/** | |||
* 不合法的UserID列表;指定的UserID列表,至少存在一个UserID不在通讯录中 | |||
*/ | |||
CODE_40031(40031, "不合法的UserID列表;指定的UserID列表,至少存在一个UserID不在通讯录中"), | |||
/** | |||
* 不合法的UserID列表长度 | |||
*/ | |||
CODE_40032(40032, "不合法的UserID列表长度"), | |||
/** | |||
* 不合法的请求字符;不能包含\\uxxxx格式的字符 | |||
*/ | |||
CODE_40033(40033, "不合法的请求字符;不能包含\\uxxxx格式的字符"), | |||
/** | |||
* 不合法的参数 | |||
*/ | |||
CODE_40035(40035, "不合法的参数"), | |||
/** | |||
* chatid不存在;会话需要先创建后,才可修改会话详情或者发起聊天 | |||
*/ | |||
CODE_40050(40050, "chatid不存在;会话需要先创建后,才可修改会话详情或者发起聊天"), | |||
/** | |||
* 不合法的子菜单url域名 | |||
*/ | |||
CODE_40054(40054, "不合法的子菜单url域名"), | |||
/** | |||
* 不合法的菜单url域名 | |||
*/ | |||
CODE_40055(40055, "不合法的菜单url域名"), | |||
/** | |||
* 不合法的agentid | |||
*/ | |||
CODE_40056(40056, "不合法的agentid"), | |||
/** | |||
* 不合法的callbackurl或者callbackurl验证失败;可自助到开发调试工具重现 | |||
*/ | |||
CODE_40057(40057, "不合法的callbackurl或者callbackurl验证失败;可自助到开发调试工具重现"), | |||
/** | |||
* 不合法的参数;传递参数不符合系统要求,需要参照具体API接口说明 | |||
*/ | |||
CODE_40058(40058, "不合法的参数;传递参数不符合系统要求,需要参照具体API接口说明"), | |||
/** | |||
* 不合法的上报地理位置标志位;开关标志位只能填 0 或者 1 | |||
*/ | |||
CODE_40059(40059, "不合法的上报地理位置标志位;开关标志位只能填 0 或者 1"), | |||
/** | |||
* 参数为空 | |||
*/ | |||
CODE_40063(40063, "参数为空"), | |||
/** | |||
* 不合法的部门列表;部门列表为空,或者至少存在一个部门ID不存在于通讯录中 | |||
*/ | |||
CODE_40066(40066, "不合法的部门列表;部门列表为空,或者至少存在一个部门ID不存在于通讯录中"), | |||
/** | |||
* 不合法的标签ID;标签ID未指定,或者指定的标签ID不存在 | |||
*/ | |||
CODE_40068(40068, "不合法的标签ID;标签ID未指定,或者指定的标签ID不存在"), | |||
/** | |||
* 指定的标签范围结点全部无效 | |||
*/ | |||
CODE_40070(40070, "指定的标签范围结点全部无效"), | |||
/** | |||
* 不合法的标签名字;标签名字已经存在 | |||
*/ | |||
CODE_40071(40071, "不合法的标签名字;标签名字已经存在"), | |||
/** | |||
* 不合法的标签名字长度;不允许为空,最大长度限制为32个字(汉字或英文字母) | |||
*/ | |||
CODE_40072(40072, "不合法的标签名字长度;不允许为空,最大长度限制为32个字(汉字或英文字母)"), | |||
/** | |||
* 不合法的openid;openid不存在,需确认获取来源 | |||
*/ | |||
CODE_40073(40073, "不合法的openid;openid不存在,需确认获取来源"), | |||
/** | |||
* news消息不支持保密消息类型;图文消息支持保密类型需改用mpnews | |||
*/ | |||
CODE_40074(40074, "news消息不支持保密消息类型;图文消息支持保密类型需改用mpnews"), | |||
/** | |||
* 不合法的pre_auth_code参数;预授权码不存在,参考:获取预授权码 | |||
*/ | |||
CODE_40077(40077, "不合法的pre_auth_code参数;预授权码不存在,参考:获取预授权码"), | |||
/** | |||
* 不合法的auth_code参数;需确认获取来源,并且只能消费一次 | |||
*/ | |||
CODE_40078(40078, "不合法的auth_code参数;需确认获取来源,并且只能消费一次"), | |||
/** | |||
* 不合法的suite_secret;套件secret可在第三方管理端套件详情查看 | |||
*/ | |||
CODE_40080(40080, "不合法的suite_secret;套件secret可在第三方管理端套件详情查看"), | |||
/** | |||
* 不合法的suite_token | |||
*/ | |||
CODE_40082(40082, "不合法的suite_token"), | |||
/** | |||
* 不合法的suite_id;suite_id不存在 | |||
*/ | |||
CODE_40083(40083, "不合法的suite_id;suite_id不存在"), | |||
/** | |||
* 不合法的permanent_code参数 | |||
*/ | |||
CODE_40084(40084, "不合法的permanent_code参数"), | |||
/** | |||
* 不合法的的suite_ticket参数;suite_ticket不存在或者已失效 | |||
*/ | |||
CODE_40085(40085, "不合法的的suite_ticket参数;suite_ticket不存在或者已失效"), | |||
/** | |||
* 不合法的第三方应用appid;至少有一个不存在应用id | |||
*/ | |||
CODE_40086(40086, "不合法的第三方应用appid;至少有一个不存在应用id"), | |||
/** | |||
* jobid不存在;请检查 jobid 来源 | |||
*/ | |||
CODE_40088(40088, "jobid不存在;请检查 jobid 来源"), | |||
/** | |||
* 批量任务的结果已清理;系统仅保存最近5次批量任务的结果。可在通讯录查看实际导入情况 | |||
*/ | |||
CODE_40089(40089, "批量任务的结果已清理;系统仅保存最近5次批量任务的结果。可在通讯录查看实际导入情况"), | |||
/** | |||
* secret不合法;可能用了别的企业的secret | |||
*/ | |||
CODE_40091(40091, "secret不合法;可能用了别的企业的secret"), | |||
/** | |||
* 导入文件存在不合法的内容 | |||
*/ | |||
CODE_40092(40092, "导入文件存在不合法的内容"), | |||
/** | |||
* 不合法的jsapi_ticket参数;ticket已失效,或者拼写错误 | |||
*/ | |||
CODE_40093(40093, "不合法的jsapi_ticket参数;ticket已失效,或者拼写错误"), | |||
/** | |||
* 不合法的URL;缺少主页URL参数,或者URL不合法(链接需要带上协议头,以 http:// 或者 https:// 开头) | |||
*/ | |||
CODE_40094(40094, "不合法的URL;缺少主页URL参数,或者URL不合法(链接需要带上协议头,以 http:// 或者 https:// 开头)"), | |||
/** | |||
* 缺少access_token参数 | |||
*/ | |||
CODE_41001(41001, "缺少access_token参数"), | |||
/** | |||
* 缺少corpid参数 | |||
*/ | |||
CODE_41002(41002, "缺少corpid参数"), | |||
/** | |||
* 缺少secret参数 | |||
*/ | |||
CODE_41004(41004, "缺少secret参数"), | |||
/** | |||
* 缺少media_id参数;media_id为调用接口必填参数,请确认是否有传递 | |||
*/ | |||
CODE_41006(41006, "缺少media_id参数;media_id为调用接口必填参数,请确认是否有传递"), | |||
/** | |||
* 缺少auth code参数 | |||
*/ | |||
CODE_41008(41008, "缺少auth code参数"), | |||
/** | |||
* 缺少userid参数 | |||
*/ | |||
CODE_41009(41009, "缺少userid参数"), | |||
/** | |||
* 缺少url参数 | |||
*/ | |||
CODE_41010(41010, "缺少url参数"), | |||
/** | |||
* 缺少agentid参数 | |||
*/ | |||
CODE_41011(41011, "缺少agentid参数"), | |||
/** | |||
* 缺少 description 参数;发送文本卡片消息接口,description 是必填字段 | |||
*/ | |||
CODE_41033(41033, "缺少 description 参数;发送文本卡片消息接口,description 是必填字段"), | |||
/** | |||
* 缺少title参数;发送图文消息,标题是必填参数。请确认参数是否有传递。 | |||
*/ | |||
CODE_41016(41016, "缺少title参数;发送图文消息,标题是必填参数。请确认参数是否有传递。"), | |||
/** | |||
* 缺少 department 参数 | |||
*/ | |||
CODE_41019(41019, "缺少 department 参数"), | |||
/** | |||
* 缺少tagid参数 | |||
*/ | |||
CODE_41017(41017, "缺少tagid参数"), | |||
/** | |||
* 缺少suite_id参数 | |||
*/ | |||
CODE_41021(41021, "缺少suite_id参数"), | |||
/** | |||
* 缺少suite_access_token参数 | |||
*/ | |||
CODE_41022(41022, "缺少suite_access_token参数"), | |||
/** | |||
* 缺少suite_ticket参数 | |||
*/ | |||
CODE_41023(41023, "缺少suite_ticket参数"), | |||
/** | |||
* 缺少secret参数 | |||
*/ | |||
CODE_41024(41024, "缺少secret参数"), | |||
/** | |||
* 缺少permanent_code参数 | |||
*/ | |||
CODE_41025(41025, "缺少permanent_code参数"), | |||
/** | |||
* access_token已过期;access_token有时效性,需要重新获取一次 | |||
*/ | |||
CODE_42001(42001, "access_token已过期;access_token有时效性,需要重新获取一次"), | |||
/** | |||
* pre_auth_code已过期;pre_auth_code有时效性,需要重新获取一次 | |||
*/ | |||
CODE_42007(42007, "pre_auth_code已过期;pre_auth_code有时效性,需要重新获取一次"), | |||
/** | |||
* suite_access_token已过期;suite_access_token有时效性,需要重新获取一次 | |||
*/ | |||
CODE_42009(42009, "suite_access_token已过期;suite_access_token有时效性,需要重新获取一次"), | |||
/** | |||
* 指定的userid未绑定微信或未关注微信插件;需要成员使用微信登录企业微信或者关注微信插件才能获取openid | |||
*/ | |||
CODE_43004(43004, "指定的userid未绑定微信或未关注微信插件;需要成员使用微信登录企业微信或者关注微信插件才能获取openid"), | |||
/** | |||
* 多媒体文件为空;上传格式参考:上传临时素材,确认header和body的内容正确。 | |||
*/ | |||
CODE_44001(44001, "多媒体文件为空;上传格式参考:上传临时素材,确认header和body的内容正确。"), | |||
/** | |||
* 文本消息content参数为空;发文本消息content为必填参数,且不能为空 | |||
*/ | |||
CODE_44004(44004, "文本消息content参数为空;发文本消息content为必填参数,且不能为空"), | |||
/** | |||
* 多媒体文件大小超过限制;图片不可超过5M;音频不可超过5M;文件不可超过20M | |||
*/ | |||
CODE_45001(45001, "多媒体文件大小超过限制;图片不可超过5M;音频不可超过5M;文件不可超过20M"), | |||
/** | |||
* 消息内容大小超过限制 | |||
*/ | |||
CODE_45002(45002, "消息内容大小超过限制"), | |||
/** | |||
* 应用description参数长度不符合系统限制;设置应用若带有description参数,则长度必须为4至120个字符 | |||
*/ | |||
CODE_45004(45004, "应用description参数长度不符合系统限制;设置应用若带有description参数,则长度必须为4至120个字符"), | |||
/** | |||
* 语音播放时间超过限制;语音播放时长不能超过60秒 | |||
*/ | |||
CODE_45007(45007, "语音播放时间超过限制;语音播放时长不能超过60秒"), | |||
/** | |||
* 图文消息的文章数量不符合系统限制;图文消息的文章数量不能超过8条 | |||
*/ | |||
CODE_45008(45008, "图文消息的文章数量不符合系统限制;图文消息的文章数量不能超过8条"), | |||
/** | |||
* 接口调用超过限制 | |||
*/ | |||
CODE_45009(45009, "接口调用超过限制"), | |||
/** | |||
* 应用name参数长度不符合系统限制;设置应用若带有name参数,则不允许为空,且不超过32个字符 | |||
*/ | |||
CODE_45022(45022, "应用name参数长度不符合系统限制;设置应用若带有name参数,则不允许为空,且不超过32个字符"), | |||
/** | |||
* 帐号数量超过上限 | |||
*/ | |||
CODE_45024(45024, "帐号数量超过上限"), | |||
/** | |||
* 触发删除用户数的保护;限制参考:全量覆盖成员 | |||
*/ | |||
CODE_45026(45026, "触发删除用户数的保护;限制参考:全量覆盖成员"), | |||
/** | |||
* 图文消息author参数长度超过限制;最长64个字节 | |||
*/ | |||
CODE_45032(45032, "图文消息author参数长度超过限制;最长64个字节"), | |||
/** | |||
* 接口并发调用超过限制 | |||
*/ | |||
CODE_45033(45033, "接口并发调用超过限制"), | |||
/** | |||
* 菜单未设置;菜单需发布后才能获取到数据 | |||
*/ | |||
CODE_46003(46003, "菜单未设置;菜单需发布后才能获取到数据"), | |||
/** | |||
* 指定的用户不存在;需要确认指定的用户存在于通讯录中 | |||
*/ | |||
CODE_46004(46004, "指定的用户不存在;需要确认指定的用户存在于通讯录中"), | |||
/** | |||
* API接口无权限调用 | |||
*/ | |||
CODE_48002(48002, "API接口无权限调用"), | |||
/** | |||
* 不合法的suite_id;确认suite_access_token由指定的suite_id生成 | |||
*/ | |||
CODE_48003(48003, "不合法的suite_id;确认suite_access_token由指定的suite_id生成"), | |||
/** | |||
* 授权关系无效;可能是无授权或授权已被取消 | |||
*/ | |||
CODE_48004(48004, "授权关系无效;可能是无授权或授权已被取消"), | |||
/** | |||
* API接口已废弃;接口已不再支持,建议改用新接口或者新方案 | |||
*/ | |||
CODE_48005(48005, "API接口已废弃;接口已不再支持,建议改用新接口或者新方案"), | |||
/** | |||
* redirect_url未登记可信域名 | |||
*/ | |||
CODE_50001(50001, "redirect_url未登记可信域名"), | |||
/** | |||
* 成员不在权限范围;请检查应用或管理组的权限范围 | |||
*/ | |||
CODE_50002(50002, "成员不在权限范围;请检查应用或管理组的权限范围"), | |||
/** | |||
* 应用已禁用;禁用的应用无法使用API接口。可在”管理端-企业应用”启用应用 | |||
*/ | |||
CODE_50003(50003, "应用已禁用;禁用的应用无法使用API接口。可在”管理端-企业应用”启用应用"), | |||
/** | |||
* 部门长度不符合限制;部门名称不能为空且长度不能超过32个字 | |||
*/ | |||
CODE_60001(60001, "部门长度不符合限制;部门名称不能为空且长度不能超过32个字"), | |||
/** | |||
* 部门ID不存在;需要确认部门ID是否有带,并且存在通讯录中 | |||
*/ | |||
CODE_60003(60003, "部门ID不存在;需要确认部门ID是否有带,并且存在通讯录中"), | |||
/** | |||
* 父部门不存在;需要确认父亲部门ID是否有带,并且存在通讯录中 | |||
*/ | |||
CODE_60004(60004, "父部门不存在;需要确认父亲部门ID是否有带,并且存在通讯录中"), | |||
/** | |||
* 部门下存在成员;不允许删除有成员的部门 | |||
*/ | |||
CODE_60005(60005, "部门下存在成员;不允许删除有成员的部门"), | |||
/** | |||
* 部门下存在子部门;不允许删除有子部门的部门 | |||
*/ | |||
CODE_60006(60006, "部门下存在子部门;不允许删除有子部门的部门"), | |||
/** | |||
* 不允许删除根部门 | |||
*/ | |||
CODE_60007(60007, "不允许删除根部门"), | |||
/** | |||
* 部门已存在;部门ID或者部门名称已存在 | |||
*/ | |||
CODE_60008(60008, "部门已存在;部门ID或者部门名称已存在"), | |||
/** | |||
* 部门名称含有非法字符;不能含有 \\:?*“< >| 等字符 | |||
*/ | |||
CODE_60009(60009, "部门名称含有非法字符;不能含有 \\ :?*“< >| 等字符"), | |||
/** | |||
* 部门存在循环关系 | |||
*/ | |||
CODE_60010(60010, "部门存在循环关系"), | |||
/** | |||
* 指定的成员/部门/标签参数无权限 | |||
*/ | |||
CODE_60011(60011, "指定的成员/部门/标签参数无权限"), | |||
/** | |||
* 不允许删除默认应用;默认应用的id为0 | |||
*/ | |||
CODE_60012(60012, "不允许删除默认应用;默认应用的id为0"), | |||
/** | |||
* 访问ip不在白名单之中;请确认访问ip是否在服务商白名单IP列表 | |||
*/ | |||
CODE_60020(60020, "访问ip不在白名单之中;请确认访问ip是否在服务商白名单IP列表"), | |||
/** | |||
* 不允许修改第三方应用的主页 URL;第三方应用类型,不允许通过接口修改该应用的主页 URL | |||
*/ | |||
CODE_60028(60028, "不允许修改第三方应用的主页 URL;第三方应用类型,不允许通过接口修改该应用的主页 URL"), | |||
/** | |||
* UserID已存在 | |||
*/ | |||
CODE_60102(60102, "UserID已存在"), | |||
/** | |||
* 手机号码不合法;长度不超过32位,字符仅支持数字,加号和减号 | |||
*/ | |||
CODE_60103(60103, "手机号码不合法;长度不超过32位,字符仅支持数字,加号和减号"), | |||
/** | |||
* 手机号码已存在;同一个企业内,成员的手机号不能重复。建议更换手机号,或者更新已有的手机记录。 | |||
*/ | |||
CODE_60104(60104, "手机号码已存在;同一个企业内,成员的手机号不能重复。建议更换手机号,或者更新已有的手机记录。"), | |||
/** | |||
* 邮箱不合法;长度不超过64位,且为有效的email格式 | |||
*/ | |||
CODE_60105(60105, "邮箱不合法;长度不超过64位,且为有效的email格式"), | |||
/** | |||
* 邮箱已存在;同一个企业内,成员的邮箱不能重复。建议更换邮箱,或者更新已有的邮箱记录。 | |||
*/ | |||
CODE_60106(60106, "邮箱已存在;同一个企业内,成员的邮箱不能重复。建议更换邮箱,或者更新已有的邮箱记录。"), | |||
/** | |||
* 微信号不合法;微信号格式由字母、数字、”-“、”_“组成,长度为 3-20 字节,首字符必须是字母或”-“或”_“ | |||
*/ | |||
CODE_60107(60107, "微信号不合法;微信号格式由字母、数字、”-“、”_“组成,长度为 3-20 字节,首字符必须是字母或”-“或”_“"), | |||
/** | |||
* 用户所属部门数量超过限制;用户同时归属部门不超过20个 | |||
*/ | |||
CODE_60110(60110, "用户所属部门数量超过限制;用户同时归属部门不超过20个"), | |||
/** | |||
* UserID不存在;UserID参数为空,或者不存在通讯录中 | |||
*/ | |||
CODE_60111(60111, "UserID不存在;UserID参数为空,或者不存在通讯录中"), | |||
/** | |||
* 成员name参数不合法;不能为空,且不能超过64字符 | |||
*/ | |||
CODE_60112(60112, "成员name参数不合法;不能为空,且不能超过64字符"), | |||
/** | |||
* 无效的部门id;部门不存在通讯录中 | |||
*/ | |||
CODE_60123(60123, "无效的部门id;部门不存在通讯录中"), | |||
/** | |||
* 无效的父部门id;父部门不存在通讯录中 | |||
*/ | |||
CODE_60124(60124, "无效的父部门id;父部门不存在通讯录中"), | |||
/** | |||
* 非法部门名字;不能为空,且不能超过64字节,且不能含有\\:*?”< >|等字符 | |||
*/ | |||
CODE_60125(60125, "非法部门名字;不能为空,且不能超过64字节,且不能含有\\:*?”< >|等字符"), | |||
/** | |||
* 缺少department参数 | |||
*/ | |||
CODE_60127(60127, "缺少department参数"), | |||
/** | |||
* 成员手机和邮箱都为空;成员手机和邮箱至少有个非空 | |||
*/ | |||
CODE_60129(60129, "成员手机和邮箱都为空;成员手机和邮箱至少有个非空"), | |||
/** | |||
* 发票已被其他公众号锁定 | |||
*/ | |||
CODE_72023(72023, "发票已被其他公众号锁定"), | |||
/** | |||
* 发票状态错误;reimburse_status状态错误,参考:更新发票状态 | |||
*/ | |||
CODE_72024(72024, "发票状态错误;reimburse_status状态错误,参考:更新发票状态"), | |||
/** | |||
* 存在发票不属于该用户;只能批量更新该openid的发票,参考:批量更新发票状态 | |||
*/ | |||
CODE_72037(72037, "存在发票不属于该用户;只能批量更新该openid的发票,参考:批量更新发票状态"), | |||
/** | |||
* 可信域名不正确,或者无ICP备案 | |||
*/ | |||
CODE_80001(80001, "可信域名不正确,或者无ICP备案"), | |||
/** | |||
* 部门下的结点数超过限制(3W) | |||
*/ | |||
CODE_81001(81001, "部门下的结点数超过限制(3W)"), | |||
/** | |||
* 部门最多15层 | |||
*/ | |||
CODE_81002(81002, "部门最多15层"), | |||
/** | |||
* 无权限操作标签 | |||
*/ | |||
CODE_81011(81011, "无权限操作标签"), | |||
/** | |||
* UserID、部门ID、标签ID全部非法或无权限 | |||
*/ | |||
CODE_81013(81013, "UserID、部门ID、标签ID全部非法或无权限"), | |||
/** | |||
* 标签添加成员,单次添加user或party过多 | |||
*/ | |||
CODE_81014(81014, "标签添加成员,单次添加user或party过多"), | |||
/** | |||
* 指定的成员/部门/标签全部无效 | |||
*/ | |||
CODE_82001(82001, "指定的成员/部门/标签全部无效"), | |||
/** | |||
* 不合法的PartyID列表长度;发消息,单次不能超过100个部门 | |||
*/ | |||
CODE_82002(82002, "不合法的PartyID列表长度;发消息,单次不能超过100个部门"), | |||
/** | |||
* 不合法的TagID列表长度;发消息,单次不能超过100个标签 | |||
*/ | |||
CODE_82003(82003, "不合法的TagID列表长度;发消息,单次不能超过100个标签"), | |||
/** | |||
* 成员票据过期 | |||
*/ | |||
CODE_84014(84014, "成员票据过期"), | |||
/** | |||
* 成员票据无效;确认user_ticket参数来源是否正确。参考接口:根据code获取成员信息 | |||
*/ | |||
CODE_84015(84015, "成员票据无效;确认user_ticket参数来源是否正确。参考接口:根据code获取成员信息"), | |||
/** | |||
* 缺少templateid参数 | |||
*/ | |||
CODE_84019(84019, "缺少templateid参数"), | |||
/** | |||
* templateid不存在;确认参数是否有带,并且已创建 | |||
*/ | |||
CODE_84020(84020, "templateid不存在;确认参数是否有带,并且已创建"), | |||
/** | |||
* 缺少register_code参数 | |||
*/ | |||
CODE_84021(84021, "缺少register_code参数"), | |||
/** | |||
* 无效的register_code参数 | |||
*/ | |||
CODE_84022(84022, "无效的register_code参数"), | |||
/** | |||
* 不允许调用设置通讯录同步完成接口 | |||
*/ | |||
CODE_84023(84023, "不允许调用设置通讯录同步完成接口"), | |||
/** | |||
* 无注册信息 | |||
*/ | |||
CODE_84024(84024, "无注册信息"), | |||
/** | |||
* 不符合的state参数;必须是[a-zA-Z0-9]的参数值,长度不可超过128个字节 | |||
*/ | |||
CODE_84025(84025, "不符合的state参数;必须是[a-zA-Z0-9]的参数值,长度不可超过128个字节"), | |||
/** | |||
* 包含不合法的词语 | |||
*/ | |||
CODE_85002(85002, "包含不合法的词语"), | |||
/** | |||
* 每企业每个月设置的可信域名不可超过20个 | |||
*/ | |||
CODE_85004(85004, "每企业每个月设置的可信域名不可超过20个"), | |||
/** | |||
* 可信域名未通过所有权校验 | |||
*/ | |||
CODE_85005(85005, "可信域名未通过所有权校验"), | |||
/** | |||
* 参数 chatid 不合法 | |||
*/ | |||
CODE_86001(86001, "参数 chatid 不合法"), | |||
/** | |||
* 参数 chatid 不存在 | |||
*/ | |||
CODE_86003(86003, "参数 chatid 不存在"), | |||
/** | |||
* 参数 群名不合法 | |||
*/ | |||
CODE_86004(86004, "参数 群名不合法"), | |||
/** | |||
* 参数 群主不合法 | |||
*/ | |||
CODE_86005(86005, "参数 群主不合法"), | |||
/** | |||
* 群成员数过多或过少 | |||
*/ | |||
CODE_86006(86006, "群成员数过多或过少"), | |||
/** | |||
* 不合法的群成员 | |||
*/ | |||
CODE_86007(86007, "不合法的群成员"), | |||
/** | |||
* 非法操作非自己创建的群 | |||
*/ | |||
CODE_86008(86008, "非法操作非自己创建的群"), | |||
/** | |||
* 存在非法会话成员ID | |||
*/ | |||
CODE_86216(86216, "存在非法会话成员ID"), | |||
/** | |||
* 会话发送者不在会话成员列表中;会话的发送者,必须是会话的成员列表之一 | |||
*/ | |||
CODE_86217(86217, "会话发送者不在会话成员列表中;会话的发送者,必须是会话的成员列表之一"), | |||
/** | |||
* 指定的会话参数不合法 | |||
*/ | |||
CODE_86220(86220, "指定的会话参数不合法"), | |||
/** | |||
* 未认证摇一摇周边 | |||
*/ | |||
CODE_90001(90001, "未认证摇一摇周边"), | |||
/** | |||
* 缺少摇一摇周边ticket参数 | |||
*/ | |||
CODE_90002(90002, "缺少摇一摇周边ticket参数"), | |||
/** | |||
* 摇一摇周边ticket参数不合法 | |||
*/ | |||
CODE_90003(90003, "摇一摇周边ticket参数不合法"), | |||
/** | |||
* 非法的对外属性类型 | |||
*/ | |||
CODE_90100(90100, "非法的对外属性类型"), | |||
/** | |||
* 对外属性:文本类型长度不合法;文本长度不可超过12个UTF8字符 | |||
*/ | |||
CODE_90101(90101, "对外属性:文本类型长度不合法;文本长度不可超过12个UTF8字符"), | |||
/** | |||
* 对外属性:网页类型标题长度不合法;标题长度不可超过12个UTF8字符 | |||
*/ | |||
CODE_90102(90102, "对外属性:网页类型标题长度不合法;标题长度不可超过12个UTF8字符"), | |||
/** | |||
* 对外属性:网页url不合法 | |||
*/ | |||
CODE_90103(90103, "对外属性:网页url不合法"), | |||
/** | |||
* 对外属性:小程序类型标题长度不合法;标题长度不可超过12个UTF8字符 | |||
*/ | |||
CODE_90104(90104, "对外属性:小程序类型标题长度不合法;标题长度不可超过12个UTF8字符"), | |||
/** | |||
* 对外属性:小程序类型pagepath不合法 | |||
*/ | |||
CODE_90105(90105, "对外属性:小程序类型pagepath不合法"), | |||
/** | |||
* 对外属性:请求参数不合法 | |||
*/ | |||
CODE_90106(90106, "对外属性:请求参数不合法"), | |||
/** | |||
* 获取ticket的类型无效 | |||
*/ | |||
CODE_91040(91040, "获取ticket的类型无效"), | |||
/** | |||
* 无权限操作指定的应用 | |||
*/ | |||
CODE_301002(301002, "无权限操作指定的应用"), | |||
/** | |||
* 不允许删除创建者;创建者不允许从通讯录中删除。如果需要删除该成员,需要先在WEB管理端转移创建者身份。 | |||
*/ | |||
CODE_301005(301005, "不允许删除创建者;创建者不允许从通讯录中删除。如果需要删除该成员,需要先在WEB管理端转移创建者身份。"), | |||
/** | |||
* 参数 position 不合法;长度不允许超过128个字符 | |||
*/ | |||
CODE_301012(301012, "参数 position 不合法;长度不允许超过128个字符"), | |||
/** | |||
* 参数 telephone 不合法;telephone必须由1-32位的纯数字或’-‘号组成。 | |||
*/ | |||
CODE_301013(301013, "参数 telephone 不合法;telephone必须由1-32位的纯数字或’-‘号组成。"), | |||
/** | |||
* 参数 english_name 不合法;参数如果有传递,不允许为空字符串,同时不能超过64字节,只能是由字母、数字、点(.)、减号(-)、空格或下划线(_)组成 | |||
*/ | |||
CODE_301014(301014, "参数 english_name 不合法;参数如果有传递,不允许为空字符串,同时不能超过64字节,只能是由字母、数字、点(.)、减号(-)、空格或下划线(_)组成"), | |||
/** | |||
* 参数 mediaid 不合法;请检查 mediaid 来源,应该通过上传临时素材的图片类型获得mediaid | |||
*/ | |||
CODE_301015(301015, "参数 mediaid 不合法;请检查 mediaid 来源,应该通过上传临时素材的图片类型获得mediaid"), | |||
/** | |||
* 上传语音文件不符合系统要求;语音文件的系统限制,参考上传的媒体文件限制 | |||
*/ | |||
CODE_301016(301016, "上传语音文件不符合系统要求;语音文件的系统限制,参考上传的媒体文件限制"), | |||
/** | |||
* 上传语音文件仅支持AMR格式;语音文件的系统限制,参考上传的媒体文件限制 | |||
*/ | |||
CODE_301017(301017, "上传语音文件仅支持AMR格式;语音文件的系统限制,参考上传的媒体文件限制"), | |||
/** | |||
* 参数 userid 无效;至少有一个userid不存在于通讯录中 | |||
*/ | |||
CODE_301021(301021, "参数 userid 无效;至少有一个userid不存在于通讯录中"), | |||
/** | |||
* 获取打卡数据失败;系统失败,可重试处理 | |||
*/ | |||
CODE_301022(301022, "获取打卡数据失败;系统失败,可重试处理"), | |||
/** | |||
* useridlist非法或超过限额;列表数量不能为0且不超过100 | |||
*/ | |||
CODE_301023(301023, "useridlist非法或超过限额;列表数量不能为0且不超过100"), | |||
/** | |||
* 获取打卡记录时间间隔超限;保证开始时间大于0 且结束时间大于 0 且结束时间大于开始时间,且间隔少于93天 | |||
*/ | |||
CODE_301024(301024, "获取打卡记录时间间隔超限;保证开始时间大于0 且结束时间大于 0 且结束时间大于开始时间,且间隔少于93天"), | |||
/** | |||
* 不允许更新该用户的userid | |||
*/ | |||
CODE_301036(301036, "不允许更新该用户的userid"), | |||
/** | |||
* 批量导入任务的文件中userid有重复 | |||
*/ | |||
CODE_302003(302003, "批量导入任务的文件中userid有重复"), | |||
/** | |||
* 组织架构不合法(1不是一棵树,2 多个一样的partyid,3 partyid空,4 partyid name 空,5 同一个父节点下有两个子节点 部门名字一样 可能是以上情况,请一一排查) | |||
*/ | |||
CODE_302004(302004, "组织架构不合法(1不是一棵树,2 多个一样的partyid,3 partyid空,4 partyid name 空,5 同一个父节点下有两个子节点 部门名字一样 可能是以上情况,请一一排查)"), | |||
/** | |||
* 批量导入系统失败,请重新尝试导入 | |||
*/ | |||
CODE_302005(302005, "批量导入系统失败,请重新尝试导入"), | |||
/** | |||
* 批量导入任务的文件中partyid有重复 | |||
*/ | |||
CODE_302006(302006, "批量导入任务的文件中partyid有重复"), | |||
/** | |||
* 批量导入任务的文件中,同一个部门下有两个子部门名字一样 | |||
*/ | |||
CODE_302007(302007, "批量导入任务的文件中,同一个部门下有两个子部门名字一样"), | |||
/** | |||
* CorpId参数无效;指定的CorpId不存在 | |||
*/ | |||
CODE_2000002(2000002, "CorpId参数无效;指定的CorpId不存在"); | |||
private int code; | |||
private String msg; | |||
WxCpErrorMsgEnum(int code, String msg) { | |||
this.code = code; | |||
this.msg = msg; | |||
} | |||
/** | |||
* 通过错误代码查找其中文含义. | |||
*/ | |||
public static String findMsgByCode(int code) { | |||
WxCpErrorMsgEnum[] values = WxCpErrorMsgEnum.values(); | |||
for (WxCpErrorMsgEnum value : values) { | |||
if (value.code == code) { | |||
return value.msg; | |||
} | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
package me.chanjar.weixin.common.error; | |||
import java.io.Serializable; | |||
import org.apache.commons.lang3.StringUtils; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||
/** | |||
* 微信错误码. | |||
* 请阅读: | |||
* 公众平台:<a href="http://mp.weixin.qq.com/wiki/10/6380dc743053a91c544ffd2b7c959166.html">全局返回码说明</a> | |||
* 企业微信:<a href="https://work.weixin.qq.com/api/doc#10649">全局错误码</a> | |||
* | |||
* @author Daniel Qian & Binary Wang | |||
*/ | |||
@Data | |||
@Builder | |||
public class WxError implements Serializable { | |||
private static final long serialVersionUID = 7869786563361406291L; | |||
/** | |||
* 微信错误代码. | |||
*/ | |||
private int errorCode; | |||
/** | |||
* 微信错误信息. | |||
* (如果可以翻译为中文,就为中文) | |||
*/ | |||
private String errorMsg; | |||
/** | |||
* 微信接口返回的错误原始信息(英文). | |||
*/ | |||
private String errorMsgEn; | |||
private String json; | |||
public static WxError fromJson(String json) { | |||
return fromJson(json, null); | |||
} | |||
public static WxError fromJson(String json, WxType type) { | |||
final WxError wxError = WxGsonBuilder.create().fromJson(json, WxError.class); | |||
if (StringUtils.isNotEmpty(wxError.getErrorMsg())) { | |||
wxError.setErrorMsgEn(wxError.getErrorMsg()); | |||
} | |||
if (type == null) { | |||
return wxError; | |||
} | |||
if (type == WxType.MP) { | |||
final String msg = WxMpErrorMsgEnum.findMsgByCode(wxError.getErrorCode()); | |||
if (msg != null) { | |||
wxError.setErrorMsg(msg); | |||
} | |||
} else if (type == WxType.CP) { | |||
final String msg = WxCpErrorMsgEnum.findMsgByCode(wxError.getErrorCode()); | |||
if (msg != null) { | |||
wxError.setErrorMsg(msg); | |||
} | |||
} | |||
return wxError; | |||
} | |||
@Override | |||
public String toString() { | |||
if (this.json != null) { | |||
return this.json; | |||
} | |||
return "错误: Code=" + this.errorCode + ", Msg=" + this.errorMsg; | |||
} | |||
} |
@@ -1,9 +1,9 @@ | |||
package me.chanjar.weixin.common.exception; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
package me.chanjar.weixin.common.error; | |||
/** | |||
* @author Daniel Qian | |||
*/ | |||
public class WxErrorException extends Exception { | |||
private static final long serialVersionUID = -6357149550353160810L; | |||
private WxError error; |
@@ -0,0 +1,654 @@ | |||
package me.chanjar.weixin.common.error; | |||
import lombok.Getter; | |||
/** | |||
* <pre> | |||
* 微信公众平台全局返回码. | |||
* 参考文档:<a href="http://mp.weixin.qq.com/wiki/10/6380dc743053a91c544ffd2b7c959166.html">公众平台全局返回码</a> | |||
* Created by Binary Wang on 2018/5/13. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
@Getter | |||
public enum WxMpErrorMsgEnum { | |||
/** | |||
* 系统繁忙,此时请开发者稍候再试 | |||
*/ | |||
CODE_1(-1, "系统繁忙,此时请开发者稍候再试"), | |||
/** | |||
* 请求成功 | |||
*/ | |||
CODE_0(0, "请求成功"), | |||
/** | |||
* 获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口 | |||
*/ | |||
CODE_40001(40001, "获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口"), | |||
/** | |||
* 不合法的凭证类型 | |||
*/ | |||
CODE_40002(40002, "不合法的凭证类型"), | |||
/** | |||
* 不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID | |||
*/ | |||
CODE_40003(40003, "不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID"), | |||
/** | |||
* 不合法的媒体文件类型 | |||
*/ | |||
CODE_40004(40004, "不合法的媒体文件类型"), | |||
/** | |||
* 不合法的文件类型 | |||
*/ | |||
CODE_40005(40005, "不合法的文件类型"), | |||
/** | |||
* 不合法的文件大小 | |||
*/ | |||
CODE_40006(40006, "不合法的文件大小"), | |||
/** | |||
* 不合法的媒体文件 id | |||
*/ | |||
CODE_40007(40007, "不合法的媒体文件 id"), | |||
/** | |||
* 不合法的消息类型 | |||
*/ | |||
CODE_40008(40008, "不合法的消息类型"), | |||
/** | |||
* 不合法的图片文件大小 | |||
*/ | |||
CODE_40009(40009, "不合法的图片文件大小"), | |||
/** | |||
* 不合法的语音文件大小 | |||
*/ | |||
CODE_40010(40010, "不合法的语音文件大小"), | |||
/** | |||
* 不合法的视频文件大小 | |||
*/ | |||
CODE_40011(40011, "不合法的视频文件大小"), | |||
/** | |||
* 不合法的缩略图文件大小 | |||
*/ | |||
CODE_40012(40012, "不合法的缩略图文件大小"), | |||
/** | |||
* 不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写 | |||
*/ | |||
CODE_40013(40013, "不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写"), | |||
/** | |||
* 不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口 | |||
*/ | |||
CODE_40014(40014, "不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口"), | |||
/** | |||
* 不合法的菜单类型 | |||
*/ | |||
CODE_40015(40015, "不合法的菜单类型"), | |||
/** | |||
* 不合法的按钮个数 | |||
*/ | |||
CODE_40016(40016, "不合法的按钮个数"), | |||
/** | |||
* 不合法的按钮个数 | |||
*/ | |||
CODE_40017(40017, "不合法的按钮个数"), | |||
/** | |||
* 不合法的按钮名字长度 | |||
*/ | |||
CODE_40018(40018, "不合法的按钮名字长度"), | |||
/** | |||
* 不合法的按钮 KEY 长度 | |||
*/ | |||
CODE_40019(40019, "不合法的按钮 KEY 长度"), | |||
/** | |||
* 不合法的按钮 URL 长度 | |||
*/ | |||
CODE_40020(40020, "不合法的按钮 URL 长度"), | |||
/** | |||
* 不合法的菜单版本号 | |||
*/ | |||
CODE_40021(40021, "不合法的菜单版本号"), | |||
/** | |||
* 不合法的子菜单级数 | |||
*/ | |||
CODE_40022(40022, "不合法的子菜单级数"), | |||
/** | |||
* 不合法的子菜单按钮个数 | |||
*/ | |||
CODE_40023(40023, "不合法的子菜单按钮个数"), | |||
/** | |||
* 不合法的子菜单按钮类型 | |||
*/ | |||
CODE_40024(40024, "不合法的子菜单按钮类型"), | |||
/** | |||
* 不合法的子菜单按钮名字长度 | |||
*/ | |||
CODE_40025(40025, "不合法的子菜单按钮名字长度"), | |||
/** | |||
* 不合法的子菜单按钮 KEY 长度 | |||
*/ | |||
CODE_40026(40026, "不合法的子菜单按钮 KEY 长度"), | |||
/** | |||
* 不合法的子菜单按钮 URL 长度 | |||
*/ | |||
CODE_40027(40027, "不合法的子菜单按钮 URL 长度"), | |||
/** | |||
* 不合法的自定义菜单使用用户 | |||
*/ | |||
CODE_40028(40028, "不合法的自定义菜单使用用户"), | |||
/** | |||
* 不合法的 oauth_code | |||
*/ | |||
CODE_40029(40029, "不合法的 oauth_code"), | |||
/** | |||
* 不合法的 refresh_token | |||
*/ | |||
CODE_40030(40030, "不合法的 refresh_token"), | |||
/** | |||
* 不合法的 openid 列表 | |||
*/ | |||
CODE_40031(40031, "不合法的 openid 列表"), | |||
/** | |||
* 不合法的 openid 列表长度 | |||
*/ | |||
CODE_40032(40032, "不合法的 openid 列表长度"), | |||
/** | |||
* 不合法的请求字符,不能包含\\uxxxx 格式的字符 | |||
*/ | |||
CODE_40033(40033, "不合法的请求字符,不能包含\\uxxxx 格式的字符"), | |||
/** | |||
* 不合法的参数 | |||
*/ | |||
CODE_40035(40035, "不合法的参数"), | |||
/** | |||
* 不合法的请求格式 | |||
*/ | |||
CODE_40038(40038, "不合法的请求格式"), | |||
/** | |||
* 不合法的 URL 长度 | |||
*/ | |||
CODE_40039(40039, "不合法的 URL 长度"), | |||
/** | |||
* 不合法的分组 id | |||
*/ | |||
CODE_40050(40050, "不合法的分组 id"), | |||
/** | |||
* 分组名字不合法 | |||
*/ | |||
CODE_40051(40051, "分组名字不合法"), | |||
/** | |||
* 删除单篇图文时,指定的 article_idx 不合法 | |||
*/ | |||
CODE_40060(40060, "删除单篇图文时,指定的 article_idx 不合法"), | |||
/** | |||
* 分组名字不合法 | |||
*/ | |||
CODE_40117(40117, "分组名字不合法"), | |||
/** | |||
* media_id 大小不合法 | |||
*/ | |||
CODE_40118(40118, "media_id 大小不合法"), | |||
/** | |||
* button 类型错误 | |||
*/ | |||
CODE_40119(40119, "button 类型错误"), | |||
/** | |||
* button 类型错误 | |||
*/ | |||
CODE_40120(40120, "button 类型错误"), | |||
/** | |||
* 不合法的 media_id 类型 | |||
*/ | |||
CODE_40121(40121, "不合法的 media_id 类型"), | |||
/** | |||
* 微信号不合法 | |||
*/ | |||
CODE_40132(40132, "微信号不合法"), | |||
/** | |||
* 不支持的图片格式 | |||
*/ | |||
CODE_40137(40137, "不支持的图片格式"), | |||
/** | |||
* 请勿添加其他公众号的主页链接 | |||
*/ | |||
CODE_40155(40155, "请勿添加其他公众号的主页链接"), | |||
/** | |||
* 缺少 access_token 参数 | |||
*/ | |||
CODE_41001(41001, "缺少 access_token 参数"), | |||
/** | |||
* 缺少 appid 参数 | |||
*/ | |||
CODE_41002(41002, "缺少 appid 参数"), | |||
/** | |||
* 缺少 refresh_token 参数 | |||
*/ | |||
CODE_41003(41003, "缺少 refresh_token 参数"), | |||
/** | |||
* 缺少 secret 参数 | |||
*/ | |||
CODE_41004(41004, "缺少 secret 参数"), | |||
/** | |||
* 缺少多媒体文件数据 | |||
*/ | |||
CODE_41005(41005, "缺少多媒体文件数据"), | |||
/** | |||
* 缺少 media_id 参数 | |||
*/ | |||
CODE_41006(41006, "缺少 media_id 参数"), | |||
/** | |||
* 缺少子菜单数据 | |||
*/ | |||
CODE_41007(41007, "缺少子菜单数据"), | |||
/** | |||
* 缺少 oauth code | |||
*/ | |||
CODE_41008(41008, "缺少 oauth code"), | |||
/** | |||
* 缺少 openid | |||
*/ | |||
CODE_41009(41009, "缺少 openid"), | |||
/** | |||
* access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明 | |||
*/ | |||
CODE_42001(42001, "access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明"), | |||
/** | |||
* refresh_token 超时 | |||
*/ | |||
CODE_42002(42002, "refresh_token 超时"), | |||
/** | |||
* oauth_code 超时 | |||
*/ | |||
CODE_42003(42003, "oauth_code 超时"), | |||
/** | |||
* 用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权 | |||
*/ | |||
CODE_42007(42007, "用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权"), | |||
/** | |||
* 需要 GET 请求 | |||
*/ | |||
CODE_43001(43001, "需要 GET 请求"), | |||
/** | |||
* 需要 POST 请求 | |||
*/ | |||
CODE_43002(43002, "需要 POST 请求"), | |||
/** | |||
* 需要 HTTPS 请求 | |||
*/ | |||
CODE_43003(43003, "需要 HTTPS 请求"), | |||
/** | |||
* 需要接收者关注 | |||
*/ | |||
CODE_43004(43004, "需要接收者关注"), | |||
/** | |||
* 需要好友关系 | |||
*/ | |||
CODE_43005(43005, "需要好友关系"), | |||
/** | |||
* 需要将接收者从黑名单中移除 | |||
*/ | |||
CODE_43019(43019, "需要将接收者从黑名单中移除"), | |||
/** | |||
* 多媒体文件为空 | |||
*/ | |||
CODE_44001(44001, "多媒体文件为空"), | |||
/** | |||
* POST 的数据包为空 | |||
*/ | |||
CODE_44002(44002, "POST 的数据包为空"), | |||
/** | |||
* 图文消息内容为空 | |||
*/ | |||
CODE_44003(44003, "图文消息内容为空"), | |||
/** | |||
* 文本消息内容为空 | |||
*/ | |||
CODE_44004(44004, "文本消息内容为空"), | |||
/** | |||
* 多媒体文件大小超过限制 | |||
*/ | |||
CODE_45001(45001, "多媒体文件大小超过限制"), | |||
/** | |||
* 消息内容超过限制 | |||
*/ | |||
CODE_45002(45002, "消息内容超过限制"), | |||
/** | |||
* 标题字段超过限制 | |||
*/ | |||
CODE_45003(45003, "标题字段超过限制"), | |||
/** | |||
* 描述字段超过限制 | |||
*/ | |||
CODE_45004(45004, "描述字段超过限制"), | |||
/** | |||
* 链接字段超过限制 | |||
*/ | |||
CODE_45005(45005, "链接字段超过限制"), | |||
/** | |||
* 图片链接字段超过限制 | |||
*/ | |||
CODE_45006(45006, "图片链接字段超过限制"), | |||
/** | |||
* 语音播放时间超过限制 | |||
*/ | |||
CODE_45007(45007, "语音播放时间超过限制"), | |||
/** | |||
* 图文消息超过限制 | |||
*/ | |||
CODE_45008(45008, "图文消息超过限制"), | |||
/** | |||
* 接口调用超过限制 | |||
*/ | |||
CODE_45009(45009, "接口调用超过限制"), | |||
/** | |||
* 创建菜单个数超过限制 | |||
*/ | |||
CODE_45010(45010, "创建菜单个数超过限制"), | |||
/** | |||
* API 调用太频繁,请稍候再试 | |||
*/ | |||
CODE_45011(45011, "API 调用太频繁,请稍候再试"), | |||
/** | |||
* 回复时间超过限制 | |||
*/ | |||
CODE_45015(45015, "回复时间超过限制"), | |||
/** | |||
* 系统分组,不允许修改 | |||
*/ | |||
CODE_45016(45016, "系统分组,不允许修改"), | |||
/** | |||
* 分组名字过长 | |||
*/ | |||
CODE_45017(45017, "分组名字过长"), | |||
/** | |||
* 分组数量超过上限 | |||
*/ | |||
CODE_45018(45018, "分组数量超过上限"), | |||
/** | |||
* 客服接口下行条数超过上限 | |||
*/ | |||
CODE_45047(45047, "客服接口下行条数超过上限"), | |||
/** | |||
* 不存在媒体数据 | |||
*/ | |||
CODE_46001(46001, "不存在媒体数据"), | |||
/** | |||
* 不存在的菜单版本 | |||
*/ | |||
CODE_46002(46002, "不存在的菜单版本"), | |||
/** | |||
* 不存在的菜单数据 | |||
*/ | |||
CODE_46003(46003, "不存在的菜单数据"), | |||
/** | |||
* 不存在的用户 | |||
*/ | |||
CODE_46004(46004, "不存在的用户"), | |||
/** | |||
* 解析 JSON/XML 内容错误 | |||
*/ | |||
CODE_47001(47001, "解析 JSON/XML 内容错误"), | |||
/** | |||
* api 功能未授权,请确认公众号已获得该接口,可以在公众平台官网 - 开发者中心页中查看接口权限 | |||
*/ | |||
CODE_48001(48001, "api 功能未授权,请确认公众号已获得该接口,可以在公众平台官网 - 开发者中心页中查看接口权限"), | |||
/** | |||
* 粉丝拒收消息(粉丝在公众号选项中,关闭了 “ 接收消息 ” ) | |||
*/ | |||
CODE_48002(48002, "粉丝拒收消息(粉丝在公众号选项中,关闭了 “ 接收消息 ” )"), | |||
/** | |||
* api 接口被封禁,请登录 mp.weixin.qq.com 查看详情 | |||
*/ | |||
CODE_48004(48004, "api 接口被封禁,请登录 mp.weixin.qq.com 查看详情"), | |||
/** | |||
* api 禁止删除被自动回复和自定义菜单引用的素材 | |||
*/ | |||
CODE_48005(48005, "api 禁止删除被自动回复和自定义菜单引用的素材"), | |||
/** | |||
* api 禁止清零调用次数,因为清零次数达到上限 | |||
*/ | |||
CODE_48006(48006, "api 禁止清零调用次数,因为清零次数达到上限"), | |||
/** | |||
* 没有该类型消息的发送权限 | |||
*/ | |||
CODE_48008(48008, "没有该类型消息的发送权限"), | |||
/** | |||
* 用户未授权该 api | |||
*/ | |||
CODE_50001(50001, "用户未授权该 api"), | |||
/** | |||
* 用户受限,可能是违规后接口被封禁 | |||
*/ | |||
CODE_50002(50002, "用户受限,可能是违规后接口被封禁"), | |||
/** | |||
* 用户未关注公众号 | |||
*/ | |||
CODE_50005(50005, "用户未关注公众号"), | |||
/** | |||
* 参数错误 (invalid parameter) | |||
*/ | |||
CODE_61451(61451, "参数错误 (invalid parameter)"), | |||
/** | |||
* 无效客服账号 (invalid kf_account) | |||
*/ | |||
CODE_61452(61452, "无效客服账号 (invalid kf_account)"), | |||
/** | |||
* 客服帐号已存在 (kf_account exsited) | |||
*/ | |||
CODE_61453(61453, "客服帐号已存在 (kf_account exsited)"), | |||
/** | |||
* 客服帐号名长度超过限制 ( 仅允许 10 个英文字符,不包括 @ 及 @ 后的公众号的微信号 )(invalid kf_acount length) | |||
*/ | |||
CODE_61454(61454, "客服帐号名长度超过限制 ( 仅允许 10 个英文字符,不包括 @ 及 @ 后的公众号的微信号 )(invalid kf_acount length)"), | |||
/** | |||
* 客服帐号名包含非法字符 ( 仅允许英文 + 数字 )(illegal character in kf_account) | |||
*/ | |||
CODE_61455(61455, "客服帐号名包含非法字符 ( 仅允许英文 + 数字 )(illegal character in kf_account)"), | |||
/** | |||
* 客服帐号个数超过限制 (10 个客服账号 )(kf_account count exceeded) | |||
*/ | |||
CODE_61456(61456, "客服帐号个数超过限制 (10 个客服账号 )(kf_account count exceeded)"), | |||
/** | |||
* 无效头像文件类型 (invalid file type) | |||
*/ | |||
CODE_61457(61457, "无效头像文件类型 (invalid file type)"), | |||
/** | |||
* 系统错误 (system error) | |||
*/ | |||
CODE_61450(61450, "系统错误 (system error)"), | |||
/** | |||
* 日期格式错误 | |||
*/ | |||
CODE_61500(61500, "日期格式错误"), | |||
/** | |||
* 不存在此 menuid 对应的个性化菜单 | |||
*/ | |||
CODE_65301(65301, "不存在此 menuid 对应的个性化菜单"), | |||
/** | |||
* 没有相应的用户 | |||
*/ | |||
CODE_65302(65302, "没有相应的用户"), | |||
/** | |||
* 没有默认菜单,不能创建个性化菜单 | |||
*/ | |||
CODE_65303(65303, "没有默认菜单,不能创建个性化菜单"), | |||
/** | |||
* MatchRule 信息为空 | |||
*/ | |||
CODE_65304(65304, "MatchRule 信息为空"), | |||
/** | |||
* 个性化菜单数量受限 | |||
*/ | |||
CODE_65305(65305, "个性化菜单数量受限"), | |||
/** | |||
* 不支持个性化菜单的帐号 | |||
*/ | |||
CODE_65306(65306, "不支持个性化菜单的帐号"), | |||
/** | |||
* 个性化菜单信息为空 | |||
*/ | |||
CODE_65307(65307, "个性化菜单信息为空"), | |||
/** | |||
* 包含没有响应类型的 button | |||
*/ | |||
CODE_65308(65308, "包含没有响应类型的 button"), | |||
/** | |||
* 个性化菜单开关处于关闭状态 | |||
*/ | |||
CODE_65309(65309, "个性化菜单开关处于关闭状态"), | |||
/** | |||
* 填写了省份或城市信息,国家信息不能为空 | |||
*/ | |||
CODE_65310(65310, "填写了省份或城市信息,国家信息不能为空"), | |||
/** | |||
* 填写了城市信息,省份信息不能为空 | |||
*/ | |||
CODE_65311(65311, "填写了城市信息,省份信息不能为空"), | |||
/** | |||
* 不合法的国家信息 | |||
*/ | |||
CODE_65312(65312, "不合法的国家信息"), | |||
/** | |||
* 不合法的省份信息 | |||
*/ | |||
CODE_65313(65313, "不合法的省份信息"), | |||
/** | |||
* 不合法的城市信息 | |||
*/ | |||
CODE_65314(65314, "不合法的城市信息"), | |||
/** | |||
* 该公众号的菜单设置了过多的域名外跳(最多跳转到 3 个域名的链接) | |||
*/ | |||
CODE_65316(65316, "该公众号的菜单设置了过多的域名外跳(最多跳转到 3 个域名的链接)"), | |||
/** | |||
* 不合法的 URL | |||
*/ | |||
CODE_65317(65317, "不合法的 URL"), | |||
/** | |||
* POST 数据参数不合法 | |||
*/ | |||
CODE_9001001(9001001, "POST 数据参数不合法"), | |||
/** | |||
* 远端服务不可用 | |||
*/ | |||
CODE_9001002(9001002, "远端服务不可用"), | |||
/** | |||
* Ticket 不合法 | |||
*/ | |||
CODE_9001003(9001003, "Ticket 不合法"), | |||
/** | |||
* 获取摇周边用户信息失败 | |||
*/ | |||
CODE_9001004(9001004, "获取摇周边用户信息失败"), | |||
/** | |||
* 获取商户信息失败 | |||
*/ | |||
CODE_9001005(9001005, "获取商户信息失败"), | |||
/** | |||
* 获取 OpenID 失败 | |||
*/ | |||
CODE_9001006(9001006, "获取 OpenID 失败"), | |||
/** | |||
* 上传文件缺失 | |||
*/ | |||
CODE_9001007(9001007, "上传文件缺失"), | |||
/** | |||
* 上传素材的文件类型不合法 | |||
*/ | |||
CODE_9001008(9001008, "上传素材的文件类型不合法"), | |||
/** | |||
* 上传素材的文件尺寸不合法 | |||
*/ | |||
CODE_9001009(9001009, "上传素材的文件尺寸不合法"), | |||
/** | |||
* 上传失败 | |||
*/ | |||
CODE_9001010(9001010, "上传失败"), | |||
/** | |||
* 帐号不合法 | |||
*/ | |||
CODE_9001020(9001020, "帐号不合法"), | |||
/** | |||
* 已有设备激活率低于 50% ,不能新增设备 | |||
*/ | |||
CODE_9001021(9001021, "已有设备激活率低于 50% ,不能新增设备"), | |||
/** | |||
* 设备申请数不合法,必须为大于 0 的数字 | |||
*/ | |||
CODE_9001022(9001022, "设备申请数不合法,必须为大于 0 的数字"), | |||
/** | |||
* 已存在审核中的设备 ID 申请 | |||
*/ | |||
CODE_9001023(9001023, "已存在审核中的设备 ID 申请"), | |||
/** | |||
* 一次查询设备 ID 数量不能超过 50 | |||
*/ | |||
CODE_9001024(9001024, "一次查询设备 ID 数量不能超过 50"), | |||
/** | |||
* 设备 ID 不合法 | |||
*/ | |||
CODE_9001025(9001025, "设备 ID 不合法"), | |||
/** | |||
* 页面 ID 不合法 | |||
*/ | |||
CODE_9001026(9001026, "页面 ID 不合法"), | |||
/** | |||
* 页面参数不合法 | |||
*/ | |||
CODE_9001027(9001027, "页面参数不合法"), | |||
/** | |||
* 一次删除页面 ID 数量不能超过 10 | |||
*/ | |||
CODE_9001028(9001028, "一次删除页面 ID 数量不能超过 10"), | |||
/** | |||
* 页面已应用在设备中,请先解除应用关系再删除 | |||
*/ | |||
CODE_9001029(9001029, "页面已应用在设备中,请先解除应用关系再删除"), | |||
/** | |||
* 一次查询页面 ID 数量不能超过 50 | |||
*/ | |||
CODE_9001030(9001030, "一次查询页面 ID 数量不能超过 50"), | |||
/** | |||
* 时间区间不合法 | |||
*/ | |||
CODE_9001031(9001031, "时间区间不合法"), | |||
/** | |||
* 保存设备与页面的绑定关系参数错误 | |||
*/ | |||
CODE_9001032(9001032, "保存设备与页面的绑定关系参数错误"), | |||
/** | |||
* 门店 ID 不合法 | |||
*/ | |||
CODE_9001033(9001033, "门店 ID 不合法"), | |||
/** | |||
* 设备备注信息过长 | |||
*/ | |||
CODE_9001034(9001034, "设备备注信息过长"), | |||
/** | |||
* 设备申请参数不合法 | |||
*/ | |||
CODE_9001035(9001035, "设备申请参数不合法"), | |||
/** | |||
* 查询起始值 begin 不合法 | |||
*/ | |||
CODE_9001036(9001036, "查询起始值 begin 不合法"); | |||
private int code; | |||
private String msg; | |||
WxMpErrorMsgEnum(int code, String msg) { | |||
this.code = code; | |||
this.msg = msg; | |||
} | |||
/** | |||
* 通过错误代码查找其中文含义. | |||
*/ | |||
public static String findMsgByCode(int code) { | |||
WxMpErrorMsgEnum[] values = WxMpErrorMsgEnum.values(); | |||
for (WxMpErrorMsgEnum value : values) { | |||
if (value.code == code) { | |||
return value.msg; | |||
} | |||
} | |||
return null; | |||
} | |||
} |
@@ -1,21 +1,17 @@ | |||
package me.chanjar.weixin.common.util; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.Maps; | |||
import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
import me.chanjar.weixin.common.annotation.Required; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.lang.reflect.Field; | |||
import java.lang.reflect.Modifier; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* <pre> | |||
@@ -0,0 +1,24 @@ | |||
package me.chanjar.weixin.common.util; | |||
import org.apache.commons.lang3.StringUtils; | |||
/** | |||
* <pre> | |||
* 数据处理工具类 | |||
* Created by BinaryWang on 2018/5/8. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
public class DataUtils { | |||
/** | |||
* 将数据中包含的secret字符使用星号替换,防止日志打印时被输出 | |||
*/ | |||
public static <E> E handleDataWithSecret(E data) { | |||
E dataForLog = data; | |||
if(data instanceof String && StringUtils.contains((String)data, "&secret=")){ | |||
dataForLog = (E) StringUtils.replaceAll((String)data,"&secret=\\w+&","&secret=******&"); | |||
} | |||
return dataForLog; | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.common.util; | |||
import me.chanjar.weixin.common.api.WxErrorExceptionHandler; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
@@ -19,7 +19,7 @@ public class FileUtils { | |||
File resultFile = File.createTempFile(name, '.' + ext, tmpDirFile); | |||
resultFile.deleteOnExit(); | |||
org.apache.commons.io.FileUtils.copyInputStreamToFile(inputStream, resultFile); | |||
org.apache.commons.io.FileUtils.copyToFile(inputStream, resultFile); | |||
return resultFile; | |||
} | |||
@@ -1,8 +1,8 @@ | |||
package me.chanjar.weixin.common.util.http; | |||
import jodd.http.HttpResponse; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import okhttp3.Response; | |||
import org.apache.http.Header; | |||
import org.apache.http.client.methods.CloseableHttpResponse; | |||
@@ -1,6 +1,6 @@ | |||
package me.chanjar.weixin.common.util.http; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.io.IOException; | |||
@@ -9,51 +9,13 @@ import java.io.IOException; | |||
* | |||
* @param <T> 返回值类型 | |||
* @param <E> 请求参数类型 | |||
* @author Daniel Qian | |||
*/ | |||
public interface RequestExecutor<T, E> { | |||
/** | |||
* @param uri uri | |||
* @param data 数据 | |||
* @throws WxErrorException | |||
* @throws IOException | |||
*/ | |||
T execute(String uri, E data) throws WxErrorException, IOException; | |||
/** | |||
* apache-http实现方式 | |||
* @param httpclient | |||
* @param httpProxy | |||
* @param uri | |||
* @param data | |||
* @return | |||
* @throws WxErrorException | |||
* @throws IOException | |||
*//* | |||
T executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, E data) throws WxErrorException, IOException; | |||
*//** | |||
* jodd-http实现方式 | |||
* @param provider | |||
* @param proxyInfo | |||
* @param uri | |||
* @param data | |||
* @return | |||
* @throws WxErrorException | |||
* @throws IOException | |||
*//* | |||
T executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, E data) throws WxErrorException, IOException; | |||
*//** okhttp实现方式 | |||
* @param pool | |||
* @param proxyInfo | |||
* @param uri | |||
* @param data | |||
* @return | |||
* @throws WxErrorException | |||
* @throws IOException | |||
*//* | |||
T executeOkhttp(ConnectionPool pool, final OkHttpProxyInfo proxyInfo, String uri, E data) throws WxErrorException, IOException; | |||
*/ | |||
} |
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.common.util.http.apache; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | |||
import org.apache.http.HttpHost; | |||
@@ -1,11 +1,9 @@ | |||
package me.chanjar.weixin.common.util.http.apache; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.util.fs.FileUtils; | |||
import me.chanjar.weixin.common.util.http.HttpResponseProxy; | |||
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import org.apache.commons.io.FilenameUtils; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.apache.http.Header; | |||
@@ -16,9 +14,12 @@ import org.apache.http.client.methods.HttpGet; | |||
import org.apache.http.entity.ContentType; | |||
import org.apache.http.impl.client.CloseableHttpClient; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.fs.FileUtils; | |||
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.HttpResponseProxy; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
/** | |||
* Created by ecoolper on 2017/5/5. | |||
@@ -45,8 +46,7 @@ public class ApacheMediaDownloadRequestExecutor extends BaseMediaDownloadRequest | |||
} | |||
try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet); | |||
InputStream inputStream = InputStreamResponseHandler.INSTANCE | |||
.handleResponse(response)) { | |||
InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) { | |||
Header[] contentTypeHeader = response.getHeaders("Content-Type"); | |||
if (contentTypeHeader != null && contentTypeHeader.length > 0) { | |||
if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { | |||
@@ -1,8 +1,8 @@ | |||
package me.chanjar.weixin.common.util.http.apache; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import org.apache.http.HttpEntity; | |||
@@ -10,7 +10,6 @@ import org.apache.http.HttpHost; | |||
import org.apache.http.client.config.RequestConfig; | |||
import org.apache.http.client.methods.CloseableHttpResponse; | |||
import org.apache.http.client.methods.HttpPost; | |||
import org.apache.http.entity.ContentType; | |||
import org.apache.http.entity.mime.HttpMultipartMode; | |||
import org.apache.http.entity.mime.MultipartEntityBuilder; | |||
import org.apache.http.impl.client.CloseableHttpClient; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.common.util.http.apache; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||
import org.apache.http.Consts; | |||
@@ -1,23 +1,24 @@ | |||
package me.chanjar.weixin.common.util.http.jodd; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import org.apache.commons.io.FilenameUtils; | |||
import org.apache.commons.lang3.StringUtils; | |||
import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.fs.FileUtils; | |||
import me.chanjar.weixin.common.util.http.HttpResponseProxy; | |||
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.HttpResponseProxy; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import org.apache.commons.io.FilenameUtils; | |||
import org.apache.commons.lang3.StringUtils; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
/** | |||
* Created by ecoolper on 2017/5/5. | |||
@@ -57,9 +58,12 @@ public class JoddHttpMediaDownloadRequestExecutor extends BaseMediaDownloadReque | |||
return null; | |||
} | |||
InputStream inputStream = new ByteArrayInputStream(response.bodyBytes()); | |||
return FileUtils.createTmpFile(inputStream, FilenameUtils.getBaseName(fileName), FilenameUtils.getExtension(fileName), | |||
super.tmpDirFile); | |||
try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { | |||
return FileUtils.createTmpFile(inputStream, | |||
FilenameUtils.getBaseName(fileName), | |||
FilenameUtils.getExtension(fileName), | |||
super.tmpDirFile); | |||
} | |||
} | |||
@@ -6,9 +6,9 @@ import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
@@ -3,8 +3,8 @@ package me.chanjar.weixin.common.util.http.jodd; | |||
import jodd.http.*; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | |||
@@ -5,8 +5,8 @@ import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.common.util.http.okhttp; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.HttpResponseProxy; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
@@ -1,8 +1,8 @@ | |||
package me.chanjar.weixin.common.util.http.okhttp; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import okhttp3.*; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.common.util.http.okhttp; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | |||
import okhttp3.*; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.common.util.http.okhttp; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||
import okhttp3.*; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.common.util.json; | |||
import com.google.gson.*; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import java.lang.reflect.Type; | |||
@@ -4,7 +4,7 @@ import com.google.gson.Gson; | |||
import com.google.gson.GsonBuilder; | |||
import me.chanjar.weixin.common.bean.WxAccessToken; | |||
import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
public class WxGsonBuilder { | |||
@@ -1,5 +1,7 @@ | |||
package me.chanjar.weixin.common.util.xml; | |||
import java.io.Writer; | |||
import com.thoughtworks.xstream.XStream; | |||
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider; | |||
import com.thoughtworks.xstream.core.util.QuickWriter; | |||
@@ -9,8 +11,6 @@ import com.thoughtworks.xstream.io.xml.XppDriver; | |||
import com.thoughtworks.xstream.security.NullPermission; | |||
import com.thoughtworks.xstream.security.PrimitiveTypePermission; | |||
import java.io.Writer; | |||
public class XStreamInitializer { | |||
public static XStream getInstance() { | |||
@@ -38,7 +38,8 @@ public class XStreamInitializer { | |||
@Override | |||
public String encodeNode(String name) { | |||
return name;//防止将_转换成__ | |||
//防止将_转换成__ | |||
return name; | |||
} | |||
}; | |||
} | |||
@@ -48,6 +49,7 @@ public class XStreamInitializer { | |||
xstream.setMode(XStream.NO_REFERENCES); | |||
xstream.addPermission(NullPermission.NULL); | |||
xstream.addPermission(PrimitiveTypePermission.PRIMITIVES); | |||
xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||
return xstream; | |||
} | |||
@@ -1,8 +1,9 @@ | |||
package me.chanjar.weixin.common.bean; | |||
package me.chanjar.weixin.common.error; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import org.testng.*; | |||
import org.testng.annotations.*; | |||
import org.testng.Assert; | |||
import org.testng.annotations.Test; | |||
import static org.testng.Assert.*; | |||
@Test | |||
public class WxErrorTest { | |||
@@ -10,26 +11,24 @@ public class WxErrorTest { | |||
public void testFromJson() { | |||
String json = "{ \"errcode\": 40003, \"errmsg\": \"invalid openid\" }"; | |||
WxError wxError = WxError.fromJson(json); | |||
Assert.assertTrue(wxError.getErrorCode() == 40003); | |||
Assert.assertEquals(wxError.getErrorMsg(), "invalid openid"); | |||
assertEquals(40003, wxError.getErrorCode()); | |||
assertEquals(wxError.getErrorMsg(), "invalid openid"); | |||
} | |||
public void testFromBadJson1() { | |||
String json = "{ \"errcode\": 40003, \"errmsg\": \"invalid openid\", \"media_id\": \"12323423dsfafsf232f\" }"; | |||
WxError wxError = WxError.fromJson(json); | |||
Assert.assertTrue(wxError.getErrorCode() == 40003); | |||
Assert.assertEquals(wxError.getErrorMsg(), "invalid openid"); | |||
assertEquals(40003, wxError.getErrorCode()); | |||
assertEquals(wxError.getErrorMsg(), "invalid openid"); | |||
} | |||
public void testFromBadJson2() { | |||
String json = "{\"access_token\":\"ACCESS_TOKEN\",\"expires_in\":7200}"; | |||
WxError wxError = WxError.fromJson(json); | |||
Assert.assertTrue(wxError.getErrorCode() == 0); | |||
Assert.assertEquals(wxError.getErrorMsg(), null); | |||
assertEquals(0, wxError.getErrorCode()); | |||
assertEquals(wxError.getErrorMsg(), null); | |||
} | |||
@@ -0,0 +1,23 @@ | |||
package me.chanjar.weixin.common.util; | |||
import org.testng.annotations.Test; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.testng.Assert.*; | |||
/** | |||
* <pre> | |||
* Created by BinaryWang on 2018/5/8. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
public class DataUtilsTest { | |||
@Test | |||
public void testHandleDataWithSecret() { | |||
String data = "js_code=001tZveq0SMoiq1AEXeq0ECJeq0tZveZ&secret=5681022fa1643845392367ea88888888&grant_type=authorization_code&appid=wxe156d4848d999999"; | |||
final String s = DataUtils.handleDataWithSecret(data); | |||
assertThat(s).contains("&secret=******&"); | |||
} | |||
} |
@@ -7,7 +7,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-java-parent</artifactId> | |||
<version>3.0.0</version> | |||
<version>3.1.0</version> | |||
</parent> | |||
<artifactId>weixin-java-cp</artifactId> | |||
@@ -0,0 +1,28 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.bean.WxCpAgent; | |||
/** | |||
* <pre> | |||
* 管理企业号应用 | |||
* Created by huansinho on 2018/4/13. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/huansinho">huansinho</a> | |||
*/ | |||
public interface WxCpAgentService { | |||
/** | |||
* <pre> | |||
* 获取企业号应用信息 | |||
* 该API用于获取企业号某个应用的基本信息,包括头像、昵称、帐号类型、认证类型、可见范围等信息 | |||
* 详情请见: http://qydev.weixin.qq.com/wiki/index.php?title=获取企业号应用 | |||
* </pre> | |||
* | |||
* @param agentId 企业应用的id | |||
* @return 部门id | |||
*/ | |||
WxCpAgent get(Integer agentId) throws WxErrorException; | |||
} |
@@ -1,6 +1,6 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
import java.util.List; | |||
@@ -1,12 +1,12 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
/** | |||
* <pre> | |||
* 媒体管理接口 | |||
@@ -30,7 +30,7 @@ public interface WxCpMediaService { | |||
* | |||
* @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} | |||
* @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts} | |||
* @param inputStream 输入流 | |||
* @param inputStream 输入流,需要调用方控制关闭该输入流 | |||
*/ | |||
WxMediaUploadResult upload(String mediaType, String fileType, InputStream inputStream) | |||
throws WxErrorException, IOException; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
/** | |||
* <pre> | |||
@@ -1,6 +1,7 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.bean.WxCpUserDetail; | |||
/** | |||
* <pre> | |||
@@ -64,4 +65,19 @@ public interface WxCpOAuth2Service { | |||
*/ | |||
String[] getUserInfo(Integer agentId, String code) throws WxErrorException; | |||
/** | |||
* <pre> | |||
* 使用user_ticket获取成员详情. | |||
* | |||
* 文档地址:https://work.weixin.qq.com/api/doc#10028/%E4%BD%BF%E7%94%A8user_ticket%E8%8E%B7%E5%8F%96%E6%88%90%E5%91%98%E8%AF%A6%E6%83%85 | |||
* 请求方式:POST(HTTPS) | |||
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail?access_token=ACCESS_TOKEN | |||
* | |||
* 权限说明: | |||
* 需要有对应应用的使用权限,且成员必须在授权应用的可见范围内。 | |||
* </pre> | |||
* | |||
* @param userTicket 成员票据 | |||
*/ | |||
WxCpUserDetail getUserDetail(String userTicket) throws WxErrorException; | |||
} |
@@ -1,9 +1,7 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.bean.WxJsapiSignature; | |||
import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.session.WxSession; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | |||
@@ -12,11 +10,6 @@ import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.cp.bean.*; | |||
import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.List; | |||
/** | |||
* 微信API的Service | |||
* @author chanjaster | |||
@@ -249,6 +242,8 @@ public interface WxCpService { | |||
*/ | |||
WxCpUserService getUserService(); | |||
WxCpAgentService getAgentService(); | |||
/** | |||
* http请求对象 | |||
*/ | |||
@@ -1,15 +1,16 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.bean.WxCpTag; | |||
import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; | |||
import me.chanjar.weixin.cp.bean.WxCpTagGetResult; | |||
import me.chanjar.weixin.cp.bean.WxCpUser; | |||
import java.util.List; | |||
/** | |||
* <pre> | |||
* 标签管理接口 | |||
* 标签管理接口. | |||
* Created by BinaryWang on 2017/6/24. | |||
* </pre> | |||
* | |||
@@ -17,14 +18,14 @@ import java.util.List; | |||
*/ | |||
public interface WxCpTagService { | |||
/** | |||
* 创建标签 | |||
* 创建标签. | |||
* | |||
* @param tagName 标签名 | |||
*/ | |||
String create(String tagName) throws WxErrorException; | |||
/** | |||
* 更新标签 | |||
* 更新标签. | |||
* | |||
* @param tagId 标签id | |||
* @param tagName 标签名 | |||
@@ -32,35 +33,49 @@ public interface WxCpTagService { | |||
void update(String tagId, String tagName) throws WxErrorException; | |||
/** | |||
* 删除标签 | |||
* 删除标签. | |||
* | |||
* @param tagId 标签id | |||
*/ | |||
void delete(String tagId) throws WxErrorException; | |||
/** | |||
* 获得标签列表 | |||
* 获得标签列表. | |||
*/ | |||
List<WxCpTag> listAll() throws WxErrorException; | |||
/** | |||
* 获取标签成员 | |||
* 获取标签成员. | |||
* | |||
* @param tagId 标签ID | |||
*/ | |||
List<WxCpUser> listUsersByTagId(String tagId) throws WxErrorException; | |||
/** | |||
* 增加标签成员 | |||
* @param tagId 标签id | |||
* @param userIds 用户ID 列表 | |||
* 增加标签成员. | |||
* | |||
* @param tagId 标签id | |||
* @param userIds 用户ID 列表 | |||
* @param partyIds 企业部门ID列表 | |||
*/ | |||
WxCpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException; | |||
/** | |||
* 移除标签成员 | |||
* @param tagId 标签id | |||
* @param userIds 用户id列表 | |||
* 移除标签成员. | |||
* | |||
* @param tagId 标签id | |||
* @param userIds 用户id列表 | |||
* @param partyIds 企业部门ID列表 | |||
*/ | |||
WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds) throws WxErrorException; | |||
WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException; | |||
/** | |||
* 获取标签成员. | |||
* 对应: http://qydev.weixin.qq.com/wiki/index.php?title=管理标签 中的get接口 | |||
* | |||
* @param tagId 标签id | |||
*/ | |||
WxCpTagGetResult get(String tagId) throws WxErrorException; | |||
} |
@@ -1,6 +1,7 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.bean.WxCpInviteResult; | |||
import me.chanjar.weixin.cp.bean.WxCpUser; | |||
import java.util.List; | |||
@@ -84,18 +85,18 @@ public interface WxCpUserService { | |||
/** | |||
* <pre> | |||
* 邀请成员关注 | |||
* http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8 | |||
* 邀请成员 | |||
* 企业可通过接口批量邀请成员使用企业微信,邀请后将通过短信或邮件下发通知。 | |||
* 请求方式:POST(HTTPS) | |||
* 请求地址: https://qyapi.weixin.qq.com/cgi-bin/batch/invite?access_token=ACCESS_TOKEN | |||
* 文档地址:https://work.weixin.qq.com/api/doc#12543 | |||
* </pre> | |||
* | |||
* @param userId 用户的userid | |||
* @param inviteTips 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。 | |||
* @return 1:微信邀请 2.邮件邀请 | |||
* @deprecated api obsoleted. 邀请关注的功能微信企业号已经下线了, | |||
* 详细请参考该链接点击查看 https://qy.weixin.qq.com/cgi-bin/homepagenotify?action=get&id=46 | |||
* @param userIds 成员ID列表, 最多支持1000个。 | |||
* @param partyIds 部门ID列表,最多支持100个。 | |||
* @param tagIds 标签ID列表,最多支持100个。 | |||
*/ | |||
@Deprecated | |||
int invite(String userId, String inviteTips) throws WxErrorException; | |||
WxCpInviteResult invite(List<String> userIds, List<String> partyIds, List<String> tagIds) throws WxErrorException; | |||
/** | |||
* <pre> | |||
@@ -0,0 +1,37 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.WxCpAgentService; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpAgent; | |||
/** | |||
* <pre> | |||
* 管理企业号应用 | |||
* Created by huansinho on 2018/4/13. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/huansinho">huansinho</a> | |||
*/ | |||
public class WxCpAgentServiceImpl implements WxCpAgentService { | |||
private WxCpService mainService; | |||
public WxCpAgentServiceImpl(WxCpService mainService) { | |||
this.mainService = mainService; | |||
} | |||
@Override | |||
public WxCpAgent get(Integer agentId) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/get"; | |||
if (agentId != null) { | |||
url += "?agentid=" + agentId; | |||
} else { | |||
throw new IllegalArgumentException("缺少agentid参数"); | |||
} | |||
String responseContent = this.mainService.get(url, null); | |||
return WxCpAgent.fromJson(responseContent); | |||
} | |||
} |
@@ -3,7 +3,7 @@ package me.chanjar.weixin.cp.api.impl; | |||
import com.google.gson.JsonElement; | |||
import com.google.gson.JsonParser; | |||
import com.google.gson.reflect.TypeToken; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.json.GsonHelper; | |||
import me.chanjar.weixin.cp.api.WxCpDepartmentService; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.fs.FileUtils; | |||
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.WxCpMenuService; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
@@ -1,13 +1,15 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import com.google.gson.GsonBuilder; | |||
import com.google.gson.JsonElement; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.URIUtil; | |||
import me.chanjar.weixin.common.util.json.GsonHelper; | |||
import me.chanjar.weixin.cp.api.WxCpOAuth2Service; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpUserDetail; | |||
/** | |||
* <pre> | |||
@@ -52,9 +54,8 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service { | |||
@Override | |||
public String[] getUserInfo(Integer agentId, String code) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" | |||
+ "code=" + code | |||
+ "&agentid=" + agentId; | |||
String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?code=%s&agentid=%d", | |||
code, agentId); | |||
String responseText = this.mainService.get(url, null); | |||
JsonElement je = new JsonParser().parse(responseText); | |||
JsonObject jo = je.getAsJsonObject(); | |||
@@ -63,4 +64,12 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service { | |||
GsonHelper.getString(jo, "OpenId")}; | |||
} | |||
@Override | |||
public WxCpUserDetail getUserDetail(String userTicket) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail"; | |||
JsonObject param = new JsonObject(); | |||
param.addProperty("user_ticket", userTicket); | |||
String responseText = this.mainService.post(url, param.toString()); | |||
return new GsonBuilder().create().fromJson(responseText, WxCpUserDetail.class); | |||
} | |||
} |
@@ -5,13 +5,12 @@ import com.google.gson.JsonElement; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import me.chanjar.weixin.common.bean.WxJsapiSignature; | |||
import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.session.StandardSessionManager; | |||
import me.chanjar.weixin.common.session.WxSession; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.common.util.DataUtils; | |||
import me.chanjar.weixin.common.util.RandomUtils; | |||
import me.chanjar.weixin.common.util.crypto.SHA1; | |||
import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
@@ -21,14 +20,11 @@ import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||
import me.chanjar.weixin.cp.api.*; | |||
import me.chanjar.weixin.cp.bean.*; | |||
import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.List; | |||
public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, RequestHttp<H, P> { | |||
protected final Logger log = LoggerFactory.getLogger(this.getClass()); | |||
@@ -39,6 +35,7 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||
private WxCpMenuService menuService = new WxCpMenuServiceImpl(this); | |||
private WxCpOAuth2Service oauth2Service = new WxCpOAuth2ServiceImpl(this); | |||
private WxCpTagService tagService = new WxCpTagServiceImpl(this); | |||
private WxCpAgentService agentService = new WxCpAgentServiceImpl(this); | |||
/** | |||
* 全局的是否正在刷新access token的锁 | |||
@@ -200,6 +197,8 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||
} | |||
protected <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | |||
E dataForLog = DataUtils.handleDataWithSecret(data); | |||
if (uri.contains("access_token=")) { | |||
throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | |||
} | |||
@@ -209,7 +208,7 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||
try { | |||
T result = executor.execute(uriWithAccessToken, data); | |||
this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); | |||
this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); | |||
return result; | |||
} catch (WxErrorException e) { | |||
WxError error = e.getError(); | |||
@@ -226,12 +225,12 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||
} | |||
if (error.getErrorCode() != 0) { | |||
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); | |||
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); | |||
throw new WxErrorException(error, e); | |||
} | |||
return null; | |||
} catch (IOException e) { | |||
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); | |||
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); | |||
throw new RuntimeException(e); | |||
} | |||
} | |||
@@ -368,4 +367,13 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||
public void setTagService(WxCpTagService tagService) { | |||
this.tagService = tagService; | |||
} | |||
@Override | |||
public WxCpAgentService getAgentService() { | |||
return agentService; | |||
} | |||
public void setAgentService(WxCpAgentService agentService) { | |||
this.agentService = agentService; | |||
} | |||
} |
@@ -1,9 +1,10 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.bean.WxAccessToken; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.HttpType; | |||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | |||
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | |||
@@ -58,7 +59,7 @@ public class WxCpServiceApacheHttpClientImpl extends WxCpServiceAbstractImpl<Clo | |||
} finally { | |||
httpGet.releaseConnection(); | |||
} | |||
WxError error = WxError.fromJson(resultContent); | |||
WxError error = WxError.fromJson(resultContent, WxType.CP); | |||
if (error.getErrorCode() != 0) { | |||
throw new WxErrorException(error); | |||
} | |||
@@ -1,9 +1,10 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import jodd.http.*; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.bean.WxAccessToken; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.HttpType; | |||
import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
@@ -44,7 +45,7 @@ public class WxCpServiceJoddHttpImpl extends WxCpServiceAbstractImpl<HttpConnect | |||
HttpResponse response = request.send(); | |||
String resultContent = response.bodyText(); | |||
WxError error = WxError.fromJson(resultContent); | |||
WxError error = WxError.fromJson(resultContent, WxType.CP); | |||
if (error.getErrorCode() != 0) { | |||
throw new WxErrorException(error); | |||
} | |||
@@ -1,8 +1,9 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.bean.WxAccessToken; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.HttpType; | |||
import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo; | |||
import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
@@ -51,7 +52,7 @@ public class WxCpServiceOkHttpImpl extends WxCpServiceAbstractImpl<OkHttpClient, | |||
this.log.error(e.getMessage(), e); | |||
} | |||
WxError error = WxError.fromJson(resultContent); | |||
WxError error = WxError.fromJson(resultContent, WxType.CP); | |||
if (error.getErrorCode() != 0) { | |||
throw new WxErrorException(error); | |||
} | |||
@@ -2,11 +2,12 @@ package me.chanjar.weixin.cp.api.impl; | |||
import com.google.gson.*; | |||
import com.google.gson.reflect.TypeToken; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.api.WxCpTagService; | |||
import me.chanjar.weixin.cp.bean.WxCpTag; | |||
import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; | |||
import me.chanjar.weixin.cp.bean.WxCpTagGetResult; | |||
import me.chanjar.weixin.cp.bean.WxCpUser; | |||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
@@ -82,6 +83,22 @@ public class WxCpTagServiceImpl implements WxCpTagService { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; | |||
JsonObject jsonObject = new JsonObject(); | |||
jsonObject.addProperty("tagid", tagId); | |||
this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject); | |||
return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString())); | |||
} | |||
@Override | |||
public WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers"; | |||
JsonObject jsonObject = new JsonObject(); | |||
jsonObject.addProperty("tagid", tagId); | |||
this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject); | |||
return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString())); | |||
} | |||
private void addUserIdsAndPartyIdsToJson(List<String> userIds, List<String> partyIds, JsonObject jsonObject) { | |||
if (userIds != null) { | |||
JsonArray jsonArray = new JsonArray(); | |||
for (String userId : userIds) { | |||
@@ -89,6 +106,7 @@ public class WxCpTagServiceImpl implements WxCpTagService { | |||
} | |||
jsonObject.add("userlist", jsonArray); | |||
} | |||
if (partyIds != null) { | |||
JsonArray jsonArray = new JsonArray(); | |||
for (String userId : partyIds) { | |||
@@ -96,21 +114,19 @@ public class WxCpTagServiceImpl implements WxCpTagService { | |||
} | |||
jsonObject.add("partylist", jsonArray); | |||
} | |||
return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString())); | |||
} | |||
@Override | |||
public WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers"; | |||
JsonObject jsonObject = new JsonObject(); | |||
jsonObject.addProperty("tagid", tagId); | |||
JsonArray jsonArray = new JsonArray(); | |||
for (String userId : userIds) { | |||
jsonArray.add(new JsonPrimitive(userId)); | |||
public WxCpTagGetResult get(String tagId) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get"; | |||
if (tagId != null) { | |||
url += "?tagId=" + tagId; | |||
} else { | |||
throw new IllegalArgumentException("缺少tagId参数"); | |||
} | |||
jsonObject.add("userlist", jsonArray); | |||
return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString())); | |||
String responseContent = this.mainService.get(url, null); | |||
return WxCpTagGetResult.fromJson(responseContent); | |||
} | |||
} |
@@ -3,12 +3,12 @@ package me.chanjar.weixin.cp.api.impl; | |||
import com.google.common.collect.Maps; | |||
import com.google.gson.*; | |||
import com.google.gson.reflect.TypeToken; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.api.WxCpUserService; | |||
import me.chanjar.weixin.cp.bean.WxCpInviteResult; | |||
import me.chanjar.weixin.cp.bean.WxCpUser; | |||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
import org.apache.commons.lang3.StringUtils; | |||
import java.util.List; | |||
import java.util.Map; | |||
@@ -116,17 +116,34 @@ public class WxCpUserServiceImpl implements WxCpUserService { | |||
} | |||
@Override | |||
@Deprecated | |||
public int invite(String userId, String inviteTips) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; | |||
public WxCpInviteResult invite(List<String> userIds, List<String> partyIds, List<String> tagIds) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/invite"; | |||
JsonObject jsonObject = new JsonObject(); | |||
jsonObject.addProperty("userid", userId); | |||
if (StringUtils.isNotEmpty(inviteTips)) { | |||
jsonObject.addProperty("invite_tips", inviteTips); | |||
if (userIds != null) { | |||
JsonArray jsonArray = new JsonArray(); | |||
for (String userId : userIds) { | |||
jsonArray.add(new JsonPrimitive(userId)); | |||
} | |||
jsonObject.add("user", jsonArray); | |||
} | |||
String responseContent = this.mainService.post(url, jsonObject.toString()); | |||
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); | |||
if (partyIds != null) { | |||
JsonArray jsonArray = new JsonArray(); | |||
for (String userId : partyIds) { | |||
jsonArray.add(new JsonPrimitive(userId)); | |||
} | |||
jsonObject.add("party", jsonArray); | |||
} | |||
if (tagIds != null) { | |||
JsonArray jsonArray = new JsonArray(); | |||
for (String tagId : tagIds) { | |||
jsonArray.add(new JsonPrimitive(tagId)); | |||
} | |||
jsonObject.add("tag", jsonArray); | |||
} | |||
return WxCpInviteResult.fromJson(this.mainService.post(url, jsonObject.toString())); | |||
} | |||
@Override | |||
@@ -0,0 +1,47 @@ | |||
package me.chanjar.weixin.cp.bean; | |||
/** | |||
* <pre> | |||
* 性别枚举 | |||
* Created by BinaryWang on 2018/4/22. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
public enum Gender { | |||
/** | |||
* 男 | |||
*/ | |||
MALE("男", "1"), | |||
/** | |||
* 女 | |||
*/ | |||
FEMALE("女", "2"); | |||
private String genderName; | |||
private String code; | |||
Gender(String genderName, String code) { | |||
this.genderName = genderName; | |||
this.code = code; | |||
} | |||
public String getGenderName() { | |||
return this.genderName; | |||
} | |||
public String getCode() { | |||
return this.code; | |||
} | |||
public static Gender fromCode(String code) { | |||
if ("1".equals(code)) { | |||
return Gender.MALE; | |||
} | |||
if ("2".equals(code)) { | |||
return Gender.FEMALE; | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,96 @@ | |||
package me.chanjar.weixin.cp.bean; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* <pre> | |||
* 企业号应用信息. | |||
* Created by huansinho on 2018/4/13. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/huansinho">huansinho</a> | |||
*/ | |||
@Data | |||
public class WxCpAgent implements Serializable { | |||
@SerializedName("errcode") | |||
private Integer errcode; | |||
@SerializedName("errmsg") | |||
private String errmsg; | |||
@SerializedName("agentid") | |||
private Integer agentid; | |||
@SerializedName("name") | |||
private String name; | |||
@SerializedName("square_logo_url") | |||
private String squareLogoUrl; | |||
@SerializedName("description") | |||
private String description; | |||
@SerializedName("allow_userinfos") | |||
private Users allowUserinfos; | |||
@SerializedName("allow_partys") | |||
private Partys allowPartys; | |||
@SerializedName("allow_tags") | |||
private Tags allowTags; | |||
@SerializedName("close") | |||
private Integer close; | |||
@SerializedName("redirect_domain") | |||
private String redirectDomain; | |||
@SerializedName("report_location_flag") | |||
private Integer reportLocationFlag; | |||
@SerializedName("isreportenter") | |||
private Integer isreportenter; | |||
@SerializedName("home_url") | |||
private String homeUrl; | |||
public static WxCpAgent fromJson(String json) { | |||
return WxCpGsonBuilder.create().fromJson(json, WxCpAgent.class); | |||
} | |||
public String toJson() { | |||
return WxCpGsonBuilder.create().toJson(this); | |||
} | |||
@Data | |||
public static class Users implements Serializable { | |||
@SerializedName("user") | |||
private List<User> user; | |||
} | |||
@Data | |||
public class User implements Serializable { | |||
@SerializedName("userid") | |||
private String userid; | |||
} | |||
@Data | |||
public class Partys { | |||
@SerializedName("partyid") | |||
private List<Integer> partyids = null; | |||
} | |||
@Data | |||
public class Tags { | |||
@SerializedName("tagid") | |||
private List<Integer> tagids = null; | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
package me.chanjar.weixin.cp.bean; | |||
import com.google.common.base.Splitter; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import me.chanjar.weixin.common.util.ToStringUtils; | |||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
import org.apache.commons.lang3.StringUtils; | |||
import java.io.Serializable; | |||
import java.util.Collections; | |||
import java.util.List; | |||
/** | |||
* 邀请成员的结果对象类. | |||
* Created by Binary Wang on 2018-5-13. | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
@Data | |||
public class WxCpInviteResult implements Serializable { | |||
private static final long serialVersionUID = 1420065684270213578L; | |||
@Override | |||
public String toString() { | |||
return ToStringUtils.toSimpleString(this); | |||
} | |||
public static WxCpInviteResult fromJson(String json) { | |||
return WxCpGsonBuilder.INSTANCE.create().fromJson(json, WxCpInviteResult.class); | |||
} | |||
@SerializedName("errcode") | |||
private Integer errCode; | |||
@SerializedName("errmsg") | |||
private String errMsg; | |||
@SerializedName("invaliduser") | |||
private String invalidUsers; | |||
@SerializedName("invalidparty") | |||
private String[] invalidParties; | |||
@SerializedName("invalidtag") | |||
private String[] invalidTags; | |||
public List<String> getInvalidUserList() { | |||
return this.content2List(this.invalidUsers); | |||
} | |||
private List<String> content2List(String content) { | |||
if (StringUtils.isBlank(content)) { | |||
return Collections.emptyList(); | |||
} | |||
return Splitter.on("|").splitToList(content); | |||
} | |||
} |
@@ -34,6 +34,7 @@ public class WxCpMessage implements Serializable { | |||
private String hqMusicUrl; | |||
private String safe; | |||
private String url; | |||
private String btnTxt; | |||
private List<NewArticle> articles = new ArrayList<>(); | |||
private List<MpnewsArticle> mpnewsArticles = new ArrayList<>(); | |||
@@ -0,0 +1,57 @@ | |||
package me.chanjar.weixin.cp.bean; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* <pre> | |||
* 管理企业号应用-测试 | |||
* Created by huansinho on 2018/4/16. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/huansinho">huansinho</a> | |||
*/ | |||
@Data | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
public class WxCpTagGetResult implements Serializable { | |||
@SerializedName("errcode") | |||
private Integer errcode; | |||
@SerializedName("errmsg") | |||
private String errmsg; | |||
/** | |||
* 用户列表 | |||
*/ | |||
@SerializedName("userlist") | |||
private List<WxCpUser> userlist; | |||
/** | |||
* 部门列表 | |||
*/ | |||
@SerializedName("partylist") | |||
private List<Integer> partylist; | |||
/** | |||
* 标签名称 | |||
*/ | |||
@SerializedName("tagname") | |||
private String tagname; | |||
public static WxCpTagGetResult fromJson(String json) { | |||
return WxCpGsonBuilder.create().fromJson(json, WxCpTagGetResult.class); | |||
} | |||
public String toJson() { | |||
return WxCpGsonBuilder.create().toJson(this); | |||
} | |||
} |
@@ -15,44 +15,6 @@ import java.util.List; | |||
*/ | |||
@Data | |||
public class WxCpUser implements Serializable { | |||
public enum Gender { | |||
/** | |||
* 男 | |||
*/ | |||
MALE("男", "1"), | |||
/** | |||
* 女 | |||
*/ | |||
FEMALE("女", "2"); | |||
private String genderName; | |||
private String code; | |||
Gender(String genderName, String code) { | |||
this.genderName = genderName; | |||
this.code = code; | |||
} | |||
public String getGenderName() { | |||
return this.genderName; | |||
} | |||
public String getCode() { | |||
return this.code; | |||
} | |||
public static Gender fromCode(String code) { | |||
if ("1".equals(code)) { | |||
return Gender.MALE; | |||
} | |||
if ("2".equals(code)) { | |||
return Gender.FEMALE; | |||
} | |||
return null; | |||
} | |||
} | |||
private static final long serialVersionUID = -5696099236344075582L; | |||
private String userId; | |||
private String name; | |||
@@ -69,6 +31,8 @@ public class WxCpUser implements Serializable { | |||
private Integer hideMobile; | |||
private String englishName; | |||
private String telephone; | |||
private String qrCode; | |||
private Boolean toInvite; | |||
public void addExtAttr(String name, String value) { | |||
this.extAttrs.add(new Attr(name, value)); | |||
@@ -0,0 +1,24 @@ | |||
package me.chanjar.weixin.cp.bean; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
/** | |||
* <pre> | |||
* 使用user_ticket获取成员详情接口返回类. | |||
* Created by BinaryWang on 2018/4/22. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
@Data | |||
public class WxCpUserDetail { | |||
@SerializedName("userid") | |||
private String userId; | |||
private String name; | |||
private String mobile; | |||
private String gender; | |||
private String email; | |||
@SerializedName("qrCode") | |||
private String qrCode; | |||
} |
@@ -3,6 +3,7 @@ package me.chanjar.weixin.cp.bean; | |||
import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
import lombok.Data; | |||
import lombok.EqualsAndHashCode; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
@@ -11,6 +12,7 @@ import java.util.List; | |||
@XStreamAlias("xml") | |||
@Data | |||
@EqualsAndHashCode(callSuper = true) | |||
public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | |||
private static final long serialVersionUID = -5796178637883178826L; | |||
@@ -16,6 +16,7 @@ public class TextCardBuilder extends BaseBuilder<TextCardBuilder> { | |||
private String title; | |||
private String description; | |||
private String url; | |||
private String btnTxt; | |||
public TextCardBuilder() { | |||
this.msgType = WxConsts.KefuMsgType.TEXTCARD; | |||
@@ -36,12 +37,18 @@ public class TextCardBuilder extends BaseBuilder<TextCardBuilder> { | |||
return this; | |||
} | |||
public TextCardBuilder btnTxt(String btnTxt) { | |||
this.btnTxt = btnTxt; | |||
return this; | |||
} | |||
@Override | |||
public WxCpMessage build() { | |||
WxCpMessage m = super.build(); | |||
m.setTitle(this.title); | |||
m.setDescription(this.description); | |||
m.setUrl(this.url); | |||
m.setBtnTxt(this.btnTxt); | |||
return m; | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
package me.chanjar.weixin.cp.message; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
@@ -1,6 +1,6 @@ | |||
package me.chanjar.weixin.cp.message; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.cp.message; | |||
import me.chanjar.weixin.common.api.WxErrorExceptionHandler; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.session.WxSessionManager; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
@@ -3,7 +3,7 @@ package me.chanjar.weixin.cp.util.json; | |||
import com.google.gson.Gson; | |||
import com.google.gson.GsonBuilder; | |||
import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.util.json.WxErrorAdapter; | |||
import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
import me.chanjar.weixin.cp.bean.WxCpMessage; | |||
@@ -48,6 +48,7 @@ public class WxCpMessageGsonAdapter implements JsonSerializer<WxCpMessage> { | |||
text.addProperty("title", message.getTitle()); | |||
text.addProperty("description", message.getDescription()); | |||
text.addProperty("url", message.getUrl()); | |||
text.addProperty("btntxt", message.getBtnTxt()); | |||
messageJson.add("textcard", text); | |||
} | |||
@@ -10,6 +10,7 @@ package me.chanjar.weixin.cp.util.json; | |||
import com.google.gson.*; | |||
import me.chanjar.weixin.common.util.json.GsonHelper; | |||
import me.chanjar.weixin.cp.bean.Gender; | |||
import me.chanjar.weixin.cp.bean.WxCpUser; | |||
import java.lang.reflect.Type; | |||
@@ -39,7 +40,7 @@ public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSeri | |||
user.setName(GsonHelper.getString(o, "name")); | |||
user.setPosition(GsonHelper.getString(o, "position")); | |||
user.setMobile(GsonHelper.getString(o, "mobile")); | |||
user.setGender(WxCpUser.Gender.fromCode(GsonHelper.getString(o, "gender"))); | |||
user.setGender(Gender.fromCode(GsonHelper.getString(o, "gender"))); | |||
user.setEmail(GsonHelper.getString(o, "email")); | |||
user.setAvatar(GsonHelper.getString(o, "avatar")); | |||
user.setStatus(GsonHelper.getInteger(o, "status")); | |||
@@ -48,6 +49,8 @@ public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSeri | |||
user.setHideMobile(GsonHelper.getInteger(o, "hide_mobile")); | |||
user.setEnglishName(GsonHelper.getString(o, "english_name")); | |||
user.setTelephone(GsonHelper.getString(o, "telephone")); | |||
user.setQrCode(GsonHelper.getString(o, "qr_code")); | |||
user.setToInvite(GsonHelper.getBoolean(o, "to_invite")); | |||
if (GsonHelper.isNotNull(o.get("extattr"))) { | |||
JsonArray attrJsonElements = o.get("extattr").getAsJsonObject().get("attrs").getAsJsonArray(); | |||
@@ -111,6 +114,13 @@ public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSeri | |||
if (user.getTelephone() != null) { | |||
o.addProperty("telephone", user.getTelephone()); | |||
} | |||
if (user.getQrCode() != null) { | |||
o.addProperty("qr_code", user.getQrCode()); | |||
} | |||
if (user.getToInvite() != null) { | |||
o.addProperty("to_invite", user.getToInvite()); | |||
} | |||
if (user.getExtAttrs().size() > 0) { | |||
JsonArray attrsJsonArray = new JsonArray(); | |||
for (WxCpUser.Attr attr : user.getExtAttrs()) { | |||
@@ -63,7 +63,6 @@ public class XStreamTransformer { | |||
private static XStream configWxCpXmlMessage() { | |||
XStream xstream = XStreamInitializer.getInstance(); | |||
xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||
xstream.processAnnotations(WxCpXmlMessage.class); | |||
xstream.processAnnotations(WxCpXmlMessage.ScanCodeInfo.class); | |||
@@ -75,7 +74,6 @@ public class XStreamTransformer { | |||
private static XStream configWxCpXmlOutImageMessage() { | |||
XStream xstream = XStreamInitializer.getInstance(); | |||
xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||
xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
xstream.processAnnotations(WxCpXmlOutImageMessage.class); | |||
@@ -84,7 +82,6 @@ public class XStreamTransformer { | |||
private static XStream configWxCpXmlOutNewsMessage() { | |||
XStream xstream = XStreamInitializer.getInstance(); | |||
xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||
xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
xstream.processAnnotations(WxCpXmlOutNewsMessage.class); | |||
@@ -94,7 +91,6 @@ public class XStreamTransformer { | |||
private static XStream configWxCpXmlOutTextMessage() { | |||
XStream xstream = XStreamInitializer.getInstance(); | |||
xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||
xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
xstream.processAnnotations(WxCpXmlOutTextMessage.class); | |||
@@ -103,7 +99,6 @@ public class XStreamTransformer { | |||
private static XStream configWxCpXmlOutVideoMessage() { | |||
XStream xstream = XStreamInitializer.getInstance(); | |||
xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||
xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
xstream.processAnnotations(WxCpXmlOutVideoMessage.class); | |||
@@ -113,7 +108,6 @@ public class XStreamTransformer { | |||
private static XStream configWxCpXmlOutVoiceMessage() { | |||
XStream xstream = XStreamInitializer.getInstance(); | |||
xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||
xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
xstream.processAnnotations(WxCpXmlOutVoiceMessage.class); | |||
@@ -1,20 +1,24 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import com.google.inject.Binder; | |||
import com.google.inject.Module; | |||
import com.thoughtworks.xstream.XStream; | |||
import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; | |||
import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
public class ApiTestModule implements Module { | |||
private final Logger log = LoggerFactory.getLogger(this.getClass()); | |||
private static final String TEST_CONFIG_XML = "test-config.xml"; | |||
public static <T> T fromXml(Class<T> clazz, InputStream is) { | |||
private static <T> T fromXml(Class<T> clazz, InputStream is) { | |||
XStream xstream = XStreamInitializer.getInstance(); | |||
xstream.alias("xml", clazz); | |||
xstream.processAnnotations(clazz); | |||
@@ -23,17 +27,19 @@ public class ApiTestModule implements Module { | |||
@Override | |||
public void configure(Binder binder) { | |||
try (InputStream is1 = ClassLoader | |||
.getSystemResourceAsStream("test-config.xml")) { | |||
WxXmlCpInMemoryConfigStorage config = fromXml( | |||
WxXmlCpInMemoryConfigStorage.class, is1); | |||
try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(TEST_CONFIG_XML)) { | |||
if (inputStream == null) { | |||
throw new RuntimeException("测试配置文件【" + TEST_CONFIG_XML + "】未找到,请参照test-config-sample.xml文件生成"); | |||
} | |||
WxXmlCpInMemoryConfigStorage config = fromXml(WxXmlCpInMemoryConfigStorage.class, inputStream); | |||
WxCpService wxService = new WxCpServiceImpl(); | |||
wxService.setWxCpConfigStorage(config); | |||
binder.bind(WxCpService.class).toInstance(wxService); | |||
binder.bind(WxXmlCpInMemoryConfigStorage.class).toInstance(config); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
this.log.error(e.getMessage(), e); | |||
} | |||
} | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; | |||
import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
import org.apache.commons.lang3.StringUtils; | |||
@@ -1,7 +1,7 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; | |||
import org.testng.annotations.DataProvider; | |||
@@ -2,7 +2,7 @@ package me.chanjar.weixin.cp.api; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.bean.WxCpMessage; | |||
import me.chanjar.weixin.cp.bean.WxCpMessageSendResult; | |||
import org.testng.annotations.*; | |||
@@ -0,0 +1,52 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
import me.chanjar.weixin.common.bean.menu.WxMenuButton; | |||
import me.chanjar.weixin.cp.api.ApiTestModule; | |||
import me.chanjar.weixin.cp.api.WxCpAgentService; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpAgent; | |||
import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage; | |||
import org.mockito.Mock; | |||
import org.testng.Assert; | |||
import org.testng.annotations.DataProvider; | |||
import org.testng.annotations.Guice; | |||
import org.testng.annotations.Test; | |||
import static org.testng.Assert.assertEquals; | |||
import static org.testng.Assert.assertNotNull; | |||
import static org.mockito.Mockito.*; | |||
/** | |||
* <pre> | |||
* 管理企业号应用-测试 | |||
* Created by huansinho on 2018/4/13. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/huansinho">huansinho</a> | |||
*/ | |||
public class WxCpAgentServiceImplTest { | |||
protected WxCpService wxService = mock(WxCpService.class); | |||
@Test | |||
public void testGet() throws Exception { | |||
String returnJson = "{\"errcode\": 0,\"errmsg\": \"ok\",\"agentid\": 9,\"name\": \"测试应用\",\"square_logo_url\": \"http://wx.qlogo.cn/mmhead/alksjf;lasdjf;lasjfuodiuj3rj2o34j/0\",\"description\": \"这是一个企业号应用\",\"allow_userinfos\": {\"user\": [{\"userid\": \"0009854\"}, {\"userid\": \"1723\"}, {\"userid\": \"5625\"}]},\"allow_partys\": {\"partyid\": [42762742]},\"allow_tags\": {\"tagid\": [23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7]},\"close\": 0,\"redirect_domain\": \"weixin.com.cn\",\"report_location_flag\": 0,\"isreportenter\": 0,\"home_url\": \"\"}"; | |||
when(wxService.get("https://qyapi.weixin.qq.com/cgi-bin/agent/get?agentid=9", null)).thenReturn(returnJson); | |||
when(wxService.getAgentService()).thenReturn(new WxCpAgentServiceImpl(wxService)); | |||
WxCpAgentService wxAgentService = this.wxService.getAgentService(); | |||
WxCpAgent wxCpAgent = wxAgentService.get(9); | |||
Assert.assertEquals(9, wxCpAgent.getAgentid().intValue()); | |||
Assert.assertEquals(new Integer[]{42762742}, wxCpAgent.getAllowPartys().getPartyids().toArray()); | |||
Assert.assertEquals(new Integer[]{23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7}, wxCpAgent.getAllowTags().getTagids().toArray()); | |||
} | |||
} |
@@ -56,7 +56,7 @@ public class WxCpDepartmentServiceImplTest { | |||
} | |||
} | |||
@Test(dependsOnMethods = {"testListAll", "testCreate"}) | |||
@Test(dependsOnMethods = {"testList", "testCreate"}) | |||
public void testUpdate() throws Exception { | |||
System.out.println("=================更新部门"); | |||
this.depart.setName("子部门改名" + System.currentTimeMillis()); | |||
@@ -3,7 +3,7 @@ package me.chanjar.weixin.cp.api.impl; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.ApiTestModule; | |||
import me.chanjar.weixin.cp.api.TestConstants; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
@@ -0,0 +1,33 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.ApiTestModule; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpUserDetail; | |||
import org.testng.annotations.Guice; | |||
import org.testng.annotations.Test; | |||
/** | |||
* <pre> | |||
* Created by BinaryWang on 2018/4/22. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
@Guice(modules = ApiTestModule.class) | |||
public class WxCpOAuth2ServiceImplTest { | |||
@Inject | |||
private WxCpService wxService; | |||
@Test | |||
public void testGetUserDetail() throws WxErrorException { | |||
WxCpUserDetail userDetail = this.wxService.getOauth2Service().getUserDetail("b"); | |||
System.out.println(userDetail); | |||
} | |||
@Test | |||
public void testGetUserInfo() throws WxErrorException { | |||
this.wxService.getOauth2Service().getUserInfo("abc"); | |||
} | |||
} |
@@ -2,16 +2,23 @@ package me.chanjar.weixin.cp.api.impl; | |||
import com.google.common.base.Splitter; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.ApiTestModule; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.api.WxCpTagService; | |||
import me.chanjar.weixin.cp.bean.WxCpTag; | |||
import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; | |||
import me.chanjar.weixin.cp.bean.WxCpTagGetResult; | |||
import me.chanjar.weixin.cp.bean.WxCpUser; | |||
import org.testng.annotations.*; | |||
import org.testng.annotations.Guice; | |||
import org.testng.annotations.Test; | |||
import java.util.List; | |||
import static org.testng.Assert.*; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.testng.Assert.assertEquals; | |||
import static org.testng.Assert.assertNotEquals; | |||
/** | |||
* <pre> | |||
@@ -63,7 +70,7 @@ public class WxCpTagServiceImplTest { | |||
@Test(dependsOnMethods = {"testListUsersByTagId", "testAddUsers2Tag", "testListAll", "testUpdate", "testCreate"}) | |||
public void testRemoveUsersFromTag() throws Exception { | |||
List<String> userIds = Splitter.on("|").splitToList(this.configStorage.getUserId()); | |||
WxCpTagAddOrRemoveUsersResult result = this.wxService.getTagService().removeUsersFromTag(this.tagId, userIds); | |||
WxCpTagAddOrRemoveUsersResult result = this.wxService.getTagService().removeUsersFromTag(this.tagId, userIds, null); | |||
assertEquals(result.getErrCode(), Integer.valueOf(0)); | |||
} | |||
@@ -72,4 +79,24 @@ public class WxCpTagServiceImplTest { | |||
this.wxService.getTagService().delete(this.tagId); | |||
} | |||
@Test | |||
public void testGet() throws WxErrorException { | |||
String apiResultJson = "{\"errcode\": 0,\"errmsg\": \"ok\",\"userlist\": [{\"userid\": \"0124035\",\"name\": \"王五\"},{\"userid\": \"0114035\",\"name\": \"梦雪\"}],\"partylist\": [9576,9567,9566],\"tagname\": \"测试标签-001\"}"; | |||
WxCpService wxService = mock(WxCpService.class); | |||
when(wxService.get("https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagId=150", null)).thenReturn(apiResultJson); | |||
when(wxService.getTagService()).thenReturn(new WxCpTagServiceImpl(wxService)); | |||
WxCpTagService wxCpTagService = wxService.getTagService(); | |||
WxCpTagGetResult wxCpTagGetResult = wxCpTagService.get(String.valueOf(150)); | |||
assertEquals(0, wxCpTagGetResult.getErrcode().intValue()); | |||
assertEquals(2, wxCpTagGetResult.getUserlist().size()); | |||
assertEquals(3, wxCpTagGetResult.getPartylist().size()); | |||
assertEquals("测试标签-001", wxCpTagGetResult.getTagname()); | |||
} | |||
} |
@@ -1,8 +1,11 @@ | |||
package me.chanjar.weixin.cp.api.impl; | |||
import com.google.common.collect.Lists; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.cp.api.ApiTestModule; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.Gender; | |||
import me.chanjar.weixin.cp.bean.WxCpInviteResult; | |||
import me.chanjar.weixin.cp.bean.WxCpUser; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import org.apache.commons.lang3.builder.ToStringStyle; | |||
@@ -40,7 +43,7 @@ public class WxCpUserServiceImplTest { | |||
user.setName("Some Woman"); | |||
user.setDepartIds(new Integer[]{2}); | |||
user.setEmail("none@none.com"); | |||
user.setGender(WxCpUser.Gender.FEMALE); | |||
user.setGender(Gender.FEMALE); | |||
user.setMobile("13560084979"); | |||
user.setPosition("woman"); | |||
user.setTelephone("3300393"); | |||
@@ -87,9 +90,9 @@ public class WxCpUserServiceImplTest { | |||
} | |||
@Test | |||
@Deprecated | |||
public void testInvite() throws Exception { | |||
int result = this.wxCpService.getUserService().invite(userId, ""); | |||
WxCpInviteResult result = this.wxCpService.getUserService().invite( | |||
Lists.newArrayList(userId), null,null); | |||
System.out.println(result); | |||
} | |||
@@ -0,0 +1,25 @@ | |||
package me.chanjar.weixin.cp.bean; | |||
import org.testng.Assert; | |||
import org.testng.annotations.Test; | |||
/** | |||
* Created by huansinho on 2018/4/13. | |||
*/ | |||
@Test | |||
public class WxCpAgentTest { | |||
public void testDeserialize() { | |||
String json = "{\"errcode\": 0,\"errmsg\": \"ok\",\"agentid\": 9,\"name\": \"测试应用\",\"square_logo_url\": \"http://wx.qlogo.cn/mmhead/alksjf;lasdjf;lasjfuodiuj3rj2o34j/0\",\"description\": \"这是一个企业号应用\",\"allow_userinfos\": {\"user\": [{\"userid\": \"0009854\"}, {\"userid\": \"1723\"}, {\"userid\": \"5625\"}]},\"allow_partys\": {\"partyid\": [42762742]},\"allow_tags\": {\"tagid\": [23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7]},\"close\": 0,\"redirect_domain\": \"weixin.com.cn\",\"report_location_flag\": 0,\"isreportenter\": 0,\"home_url\": \"\"}"; | |||
WxCpAgent wxCpAgent = WxCpAgent.fromJson(json); | |||
Assert.assertEquals(9, wxCpAgent.getAgentid().intValue()); | |||
Assert.assertEquals(new Integer[]{42762742}, wxCpAgent.getAllowPartys().getPartyids().toArray()); | |||
Assert.assertEquals(new Integer[]{23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7}, wxCpAgent.getAllowTags().getTagids().toArray()); | |||
} | |||
} |
@@ -2,39 +2,47 @@ package me.chanjar.weixin.cp.bean; | |||
import me.chanjar.weixin.cp.bean.article.MpnewsArticle; | |||
import me.chanjar.weixin.cp.bean.article.NewArticle; | |||
import org.testng.annotations.*; | |||
import org.testng.annotations.Test; | |||
import static org.testng.Assert.*; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.testng.Assert.assertEquals; | |||
@Test | |||
public class WxCpMessageTest { | |||
public void testTextBuild() { | |||
WxCpMessage reply = WxCpMessage.TEXT().toUser("OPENID").content("sfsfdsdf").build(); | |||
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"},\"safe\":\"0\"}"); | |||
assertThat(reply.toJson()) | |||
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"},\"safe\":\"0\"}"); | |||
} | |||
public void testTextCardBuild() { | |||
WxCpMessage reply = WxCpMessage.TEXTCARD().toUser("OPENID") | |||
.title("领奖通知") | |||
.description( "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>") | |||
.url("http://www.qq.com").build(); | |||
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"textcard\",\"textcard\":{\"title\":\"领奖通知\",\"description\":\"<div class=\\\"gray\\\">2016年9月26日</div> <div class=\\\"normal\\\">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\\\"highlight\\\">请于2016年10月10日前联系行政同事领取</div>\",\"url\":\"http://www.qq.com\"},\"safe\":\"0\"}"); | |||
.description("<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>") | |||
.url("http://www.qq.com") | |||
.btnTxt("更多") | |||
.build(); | |||
assertThat(reply.toJson()) | |||
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"textcard\",\"textcard\":{\"title\":\"领奖通知\",\"description\":\"<div class=\\\"gray\\\">2016年9月26日</div> <div class=\\\"normal\\\">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\\\"highlight\\\">请于2016年10月10日前联系行政同事领取</div>\",\"url\":\"http://www.qq.com\",\"btntxt\":\"更多\"},\"safe\":\"0\"}"); | |||
} | |||
public void testImageBuild() { | |||
WxCpMessage reply = WxCpMessage.IMAGE().toUser("OPENID").mediaId("MEDIA_ID").build(); | |||
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}"); | |||
assertThat(reply.toJson()) | |||
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}"); | |||
} | |||
public void testVoiceBuild() { | |||
WxCpMessage reply = WxCpMessage.VOICE().toUser("OPENID").mediaId("MEDIA_ID").build(); | |||
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}"); | |||
assertThat(reply.toJson()) | |||
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}"); | |||
} | |||
public void testVideoBuild() { | |||
WxCpMessage reply = WxCpMessage.VIDEO().toUser("OPENID").title("TITLE").mediaId("MEDIA_ID").thumbMediaId("MEDIA_ID").description("DESCRIPTION").build(); | |||
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"video\",\"safe\":\"0\",\"video\":{\"media_id\":\"MEDIA_ID\",\"thumb_media_id\":\"MEDIA_ID\",\"title\":\"TITLE\",\"description\":\"DESCRIPTION\"}}"); | |||
assertThat(reply.toJson()) | |||
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"video\",\"safe\":\"0\",\"video\":{\"media_id\":\"MEDIA_ID\",\"thumb_media_id\":\"MEDIA_ID\",\"title\":\"TITLE\",\"description\":\"DESCRIPTION\"}}"); | |||
} | |||
public void testNewsBuild() { | |||
@@ -52,7 +60,8 @@ public class WxCpMessageTest { | |||
WxCpMessage reply = WxCpMessage.NEWS().toUser("OPENID").addArticle(article1).addArticle(article2).build(); | |||
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"news\",\"safe\":\"0\",\"news\":{\"articles\":[{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"},{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"}]}}"); | |||
assertThat(reply.toJson()) | |||
.isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"news\",\"safe\":\"0\",\"news\":{\"articles\":[{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"},{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"}]}}"); | |||
} | |||
public void testMpnewsBuild_with_articles() { | |||
@@ -78,14 +87,15 @@ public class WxCpMessageTest { | |||
WxCpMessage reply = WxCpMessage.MPNEWS().toUser("OPENID").addArticle(article1, article2).build(); | |||
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"articles\":[{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"},{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"}]}}"); | |||
assertThat(reply.toJson()) | |||
.isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"articles\":[{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"},{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"}]}}"); | |||
} | |||
public void testMpnewsBuild_with_media_id() { | |||
WxCpMessage reply = WxCpMessage.MPNEWS().toUser("OPENID").mediaId("mmm").build(); | |||
assertEquals(reply.toJson(), | |||
"{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"media_id\":\"mmm\"}}"); | |||
assertThat(reply.toJson()) | |||
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"media_id\":\"mmm\"}}"); | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
package me.chanjar.weixin.cp.demo; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import javax.servlet.http.HttpServlet; | |||
@@ -7,7 +7,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-java-parent</artifactId> | |||
<version>3.0.0</version> | |||
<version>3.1.0</version> | |||
</parent> | |||
<artifactId>weixin-java-miniapp</artifactId> | |||
<name>Weixin Java Tools - MiniApp</name> | |||
@@ -0,0 +1,145 @@ | |||
package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaSummaryTrend; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaUserPortrait; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitDistribution; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitPage; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitTrend; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.util.Date; | |||
import java.util.List; | |||
/** | |||
* 小程序数据分析相关接口 | |||
* 文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/analysis.html | |||
* | |||
* @author <a href="https://github.com/charmingoh">Charming</a> | |||
* @since 2018-04-28 | |||
*/ | |||
public interface WxMaAnalysisService { | |||
String GET_DAILY_SUMMARY_TREND_URL = "https://api.weixin.qq.com/datacube/getweanalysisappiddailysummarytrend"; | |||
String GET_DAILY_VISIT_TREND_URL = "https://api.weixin.qq.com/datacube/getweanalysisappiddailyvisittrend"; | |||
String GET_WEEKLY_VISIT_TREND_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidweeklyvisittrend"; | |||
String GET_MONTHLY_VISIT_TREND_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidmonthlyvisittrend"; | |||
String GET_VISIT_DISTRIBUTION_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidvisitdistribution"; | |||
String GET_DAILY_RETAIN_INFO_URL = "https://api.weixin.qq.com/datacube/getweanalysisappiddailyretaininfo"; | |||
String GET_WEEKLY_RETAIN_INFO_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidweeklyretaininfo"; | |||
String GET_MONTHLY_RETAIN_INFO_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidmonthlyretaininfo"; | |||
String GET_VISIT_PAGE_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidvisitpage"; | |||
String GET_USER_PORTRAIT_URL = "https://api.weixin.qq.com/datacube/getweanalysisappiduserportrait"; | |||
/** | |||
* 查询概况趋势 | |||
* 温馨提示:小程序接口目前只能查询一天的数据,即 beginDate 和 endDate 一样 | |||
* | |||
* @param beginDate 开始日期 | |||
* @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 | |||
* @return 概况趋势 | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
List<WxMaSummaryTrend> getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 获取日访问趋势 | |||
* 温馨提示:小程序接口目前只能查询一天的数据,即 beginDate 和 endDate 一样 | |||
* | |||
* @param beginDate 开始日期 | |||
* @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 | |||
* @return 日访问趋势 | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
List<WxMaVisitTrend> getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 获取周访问趋势 | |||
* 限定查询一个自然周的数据,时间必须按照自然周的方式输入: 如:20170306(周一), 20170312(周日) | |||
* | |||
* @param beginDate 开始日期,为周一日期 | |||
* @param endDate 结束日期,为周日日期,限定查询一周数据 | |||
* @return 周访问趋势(每项数据都是一个自然周汇总) | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
List<WxMaVisitTrend> getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 获取月访问趋势 | |||
* 限定查询一个自然月的数据,时间必须按照自然月的方式输入: 如:20170201(月初), 20170228(月末) | |||
* | |||
* @param beginDate 开始日期,为自然月第一天 | |||
* @param endDate 结束日期,为自然月最后一天,限定查询一个月数据 | |||
* @return 月访问趋势(每项数据都是一个自然月汇总) | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
List<WxMaVisitTrend> getMonthlyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 获取访问分布 | |||
* (此接口目前只能查询一天的数据,即 beginDate 和 endDate 一样) | |||
* | |||
* @param beginDate 开始日期,为周一日期 | |||
* @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 | |||
* @return 访问分布 | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
WxMaVisitDistribution getVisitDistribution(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 日留存 | |||
* (此接口目前只能查询一天的数据,即 beginDate 和 endDate 一样) | |||
* | |||
* @param beginDate 开始日期,为周一日期 | |||
* @param endDate 结束日期,限定查询 1 天数据,endDate 允许设置的最大值为昨日 | |||
* @return 日留存 | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
WxMaRetainInfo getDailyRetainInfo(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 周留存 | |||
* 限定查询一个自然周的数据,时间必须按照自然周的方式输入: 如:20170306(周一), 20170312(周日) | |||
* | |||
* @param beginDate 开始日期,为周一日期 | |||
* @param endDate 结束日期,为周日日期,限定查询一周数据 | |||
* @return 周留存 | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
WxMaRetainInfo getWeeklyRetainInfo(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 月留存 | |||
* 限定查询一个自然月的数据,时间必须按照自然月的方式输入: 如:20170201(月初), 20170228(月末) | |||
* | |||
* @param beginDate 开始日期,为自然月第一天 | |||
* @param endDate 结束日期,为自然月最后一天,限定查询一个月数据 | |||
* @return 月留存 | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
WxMaRetainInfo getMonthlyRetainInfo(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 获取访问页面数据 | |||
* 温馨提示:此接口目前只能查询一天的数据,即 beginDate 和 endDate 一样 | |||
* | |||
* @param beginDate 开始日期 | |||
* @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 | |||
* @return 访问页面数据 | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
List<WxMaVisitPage> getVisitPage(Date beginDate, Date endDate) throws WxErrorException; | |||
/** | |||
* 获取小程序新增或活跃用户的画像分布数据 | |||
* 时间范围支持昨天、最近7天、最近30天。 | |||
* 其中,新增用户数为时间范围内首次访问小程序的去重用户数, | |||
* 活跃用户数为时间范围内访问过小程序的去重用户数。 | |||
* 画像属性包括用户年龄、性别、省份、城市、终端类型、机型。 | |||
* | |||
* @param beginDate 开始日期 | |||
* @param endDate 结束日期,开始日期与结束日期相差的天数限定为0/6/29,分别表示查询最近1/7/30天数据,end_date允许设置的最大值为昨日 | |||
* @return 小程序新增或活跃用户的画像分布数据 | |||
* @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
*/ | |||
WxMaUserPortrait getUserPortrait(Date beginDate, Date endDate) throws WxErrorException; | |||
} |
@@ -0,0 +1,140 @@ | |||
package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCategory; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.util.List; | |||
/** | |||
* 小程序代码管理相关 API(大部分只能是第三方平台调用) | |||
* 文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=&lang=zh_CN | |||
* | |||
* @author <a href="https://github.com/charmingoh">Charming</a> | |||
* @since 2018-04-26 19:43 | |||
*/ | |||
public interface WxMaCodeService { | |||
/** | |||
* 为授权的小程序帐号上传小程序代码 | |||
*/ | |||
String COMMIT_URL = "https://api.weixin.qq.com/wxa/commit"; | |||
String GET_QRCODE_URL = "https://api.weixin.qq.com/wxa/get_qrcode"; | |||
String GET_CATEGORY_URL = "https://api.weixin.qq.com/wxa/get_category"; | |||
String GET_PAGE_URL = "https://api.weixin.qq.com/wxa/get_page"; | |||
String SUBMIT_AUDIT_URL = "https://api.weixin.qq.com/wxa/submit_audit"; | |||
String GET_AUDIT_STATUS_URL = "https://api.weixin.qq.com/wxa/get_auditstatus"; | |||
String GET_LATEST_AUDIT_STATUS_URL = "https://api.weixin.qq.com/wxa/get_latest_auditstatus"; | |||
String RELEASE_URL = "https://api.weixin.qq.com/wxa/release"; | |||
String CHANGE_VISIT_STATUS_URL = "https://api.weixin.qq.com/wxa/change_visitstatus"; | |||
String REVERT_CODE_RELEASE_URL = "https://api.weixin.qq.com/wxa/revertcoderelease"; | |||
String GET_SUPPORT_VERSION_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/getweappsupportversion"; | |||
String SET_SUPPORT_VERSION_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion"; | |||
String UNDO_CODE_AUDIT_URL = "https://api.weixin.qq.com/wxa/undocodeaudit"; | |||
/** | |||
* 为授权的小程序帐号上传小程序代码(仅仅支持第三方开放平台) | |||
* | |||
* @param commitRequest 参数 | |||
* @throws WxErrorException 上传失败时抛出,具体错误码请看类注释文档 | |||
*/ | |||
void commit(WxMaCodeCommitRequest commitRequest) throws WxErrorException; | |||
/** | |||
* 获取体验小程序的体验二维码 | |||
* | |||
* @return 二维码 bytes | |||
* @throws WxErrorException 上传失败时抛出,具体错误码请看类注释文档 | |||
*/ | |||
byte[] getQrCode() throws WxErrorException; | |||
/** | |||
* 获取授权小程序帐号的可选类目 | |||
* | |||
* @return List<WxMaCategory> | |||
* @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档 | |||
*/ | |||
List<WxMaCategory> getCategory() throws WxErrorException; | |||
/** | |||
* 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用) | |||
* | |||
* @return page_list 页面配置列表 | |||
* @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档 | |||
*/ | |||
List<String> getPage() throws WxErrorException; | |||
/** | |||
* 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用) | |||
* | |||
* @param auditRequest 提交审核参数 | |||
* @return 审核编号 | |||
* @throws WxErrorException 提交失败时返回,具体错误码请看此接口的注释文档 | |||
*/ | |||
long submitAudit(WxMaCodeSubmitAuditRequest auditRequest) throws WxErrorException; | |||
/** | |||
* 查询某个指定版本的审核状态(仅供第三方代小程序调用) | |||
* | |||
* @param auditId 提交审核时获得的审核id | |||
* @return 审核状态 | |||
* @throws WxErrorException 查询失败时返回,具体错误码请看此接口的注释文档 | |||
*/ | |||
WxMaCodeAuditStatus getAuditStatus(long auditId) throws WxErrorException; | |||
/** | |||
* 查询最新一次提交的审核状态(仅供第三方代小程序调用) | |||
* | |||
* @return 审核状态 | |||
* @throws WxErrorException 查询失败时返回,具体错误码请看此接口的注释文档 | |||
*/ | |||
WxMaCodeAuditStatus getLatestAuditStatus() throws WxErrorException; | |||
/** | |||
* 发布已通过审核的小程序(仅供第三方代小程序调用) | |||
* | |||
* @throws WxErrorException 发布失败时抛出,具体错误码请看此接口的注释文档 | |||
*/ | |||
void release() throws WxErrorException; | |||
/** | |||
* 修改小程序线上代码的可见状态(仅供第三方代小程序调用) | |||
* | |||
* @param action 设置可访问状态,发布后默认可访问,close为不可见,open为可见 | |||
* @throws WxErrorException 发布失败时抛出,具体错误码请看此接口的注释文档 | |||
*/ | |||
void changeVisitStatus(String action) throws WxErrorException; | |||
/** | |||
* 小程序版本回退(仅供第三方代小程序调用) | |||
* | |||
* @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 | |||
*/ | |||
void revertCodeRelease() throws WxErrorException; | |||
/** | |||
* 查询当前设置的最低基础库版本及各版本用户占比 (仅供第三方代小程序调用) | |||
* | |||
* @return 小程序版本分布信息 | |||
* @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 | |||
*/ | |||
WxMaCodeVersionDistribution getSupportVersion() throws WxErrorException; | |||
/** | |||
* 设置最低基础库版本(仅供第三方代小程序调用) | |||
* | |||
* @param version 版本 | |||
* @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 | |||
*/ | |||
void setSupportVersion(String version) throws WxErrorException; | |||
/** | |||
* 小程序审核撤回 | |||
* 单个帐号每天审核撤回次数最多不超过1次,一个月不超过10次 | |||
* | |||
* @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 | |||
*/ | |||
void undoCodeAudit() throws WxErrorException; | |||
} |
@@ -1,7 +1,7 @@ | |||
package cn.binarywang.wx.miniapp.api; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
@@ -2,7 +2,7 @@ package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; | |||
import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
/** | |||
* <pre> | |||
@@ -1,7 +1,7 @@ | |||
package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.io.File; | |||
@@ -9,7 +9,7 @@ import java.io.File; | |||
* <pre> | |||
* 二维码相关操作接口. | |||
* | |||
* 接口A(createWxCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。 | |||
* 接口A(createWxaCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。 | |||
* | |||
* 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html | |||
* </pre> | |||
@@ -40,16 +40,17 @@ public interface WxMaQrcodeService { | |||
/** | |||
* 接口A: 获取小程序码. | |||
* | |||
* @param path 不能为空,最大长度 128 字节 | |||
* @param width 默认430 二维码的宽度 | |||
* @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | |||
* @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} | |||
* @param path 不能为空,最大长度 128 字节 | |||
* @param width 默认430 二维码的宽度 | |||
* @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | |||
* @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} | |||
* @param is_hyaline 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 | |||
*/ | |||
File createWxCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor) throws WxErrorException; | |||
File createWxaCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean is_hyaline) throws WxErrorException; | |||
File createWxCode(String path, int width) throws WxErrorException; | |||
File createWxaCode(String path, int width) throws WxErrorException; | |||
File createWxCode(String path) throws WxErrorException; | |||
File createWxaCode(String path) throws WxErrorException; | |||
/** | |||
* 接口B: 获取小程序码(永久有效、数量暂无限制). | |||
@@ -59,14 +60,16 @@ public interface WxMaQrcodeService { | |||
* 使用如下代码可以获取到二维码中的 scene 字段的值。 | |||
* 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode | |||
* </pre> | |||
* | |||
* @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) | |||
* @param page 必须是已经发布的小程序页面,例如 "pages/index/index" ,如果不填写这个字段,默认跳主页面 | |||
* @param width 默认false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | |||
* @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | |||
* @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} | |||
* @param isHyaline 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 | |||
*/ | |||
File createWxCodeLimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor) throws WxErrorException; | |||
File createWxaCodeUnlimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException; | |||
File createWxCodeLimit(String scene, String page) throws WxErrorException; | |||
File createWxaCodeUnlimit(String scene, String page) throws WxErrorException; | |||
} |
@@ -2,7 +2,7 @@ package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | |||
import cn.binarywang.wx.miniapp.config.WxMaConfig; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
@@ -135,6 +135,27 @@ public interface WxMaService { | |||
*/ | |||
WxMaTemplateService getTemplateService(); | |||
/** | |||
* 数据分析相关查询服务 | |||
* | |||
* @return WxMaAnalysisService | |||
*/ | |||
WxMaAnalysisService getAnalysisService(); | |||
/** | |||
* 返回代码操作相关的 API | |||
* | |||
* @return WxMaCodeService | |||
*/ | |||
WxMaCodeService getCodeService(); | |||
/** | |||
* 小程序修改服务器地址、成员管理 API | |||
* | |||
* @return WxMaSettingService | |||
*/ | |||
WxMaSettingService getSettingService(); | |||
/** | |||
* 初始化http请求对象. | |||
*/ | |||
@@ -0,0 +1,65 @@ | |||
package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.WxMaDomainAction; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
/** | |||
* 小程序修改服务器地址、成员管理 API(大部分只能是第三方平台调用) | |||
* | |||
* @author <a href="https://github.com/charmingoh">Charming</a> | |||
* @since 2018-04-27 15:46 | |||
*/ | |||
public interface WxMaSettingService { | |||
/** | |||
* 修改服务器地址:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489138143_WPbOO&token=&lang=zh_CN | |||
* access_token 为 authorizer_access_token | |||
*/ | |||
String MODIFY_DOMAIN_URL = "https://api.weixin.qq.com/wxa/modify_domain"; | |||
String SET_WEB_VIEW_DOMAIN_URL = "https://api.weixin.qq.com/wxa/setwebviewdomain"; | |||
/** | |||
* 小程序成员管理:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140588_nVUgx&token=&lang=zh_CN | |||
* access_token 为 authorizer_access_token | |||
*/ | |||
String BIND_TESTER_URL = "https://api.weixin.qq.com/wxa/bind_tester"; | |||
String UNBIND_TESTER_URL = "https://api.weixin.qq.com/wxa/unbind_tester"; | |||
/** | |||
* 操作服务器域名 | |||
* | |||
* @param domainAction 域名操作参数 | |||
* 除了 webViewDomain,都是有效的 | |||
* @return 以下字段仅在 get 时返回完整字段 | |||
* @throws WxErrorException 操作失败时抛出,具体错误码请看文档 | |||
*/ | |||
WxMaDomainAction modifyDomain(WxMaDomainAction domainAction) throws WxErrorException; | |||
/** | |||
* 设置小程序业务域名(仅供第三方代小程序调用) | |||
* 授权给第三方的小程序,其业务域名只可以为第三方的服务器, | |||
* 当小程序通过第三方发布代码上线后,小程序原先自己配置的业务域名将被删除, | |||
* 只保留第三方平台的域名,所以第三方平台在代替小程序发布代码之前,需要调用接口为小程序添加业务域名。 | |||
* 提示:需要先将域名登记到第三方平台的小程序业务域名中,才可以调用接口进行配置。 | |||
* | |||
* @param domainAction 域名操作参数 | |||
* 只有 action 和 webViewDomain 是有效的 | |||
* @return 以下字段仅在 get 时返回完整字段 | |||
* @throws WxErrorException 操作失败时抛出,具体错误码请看文档 | |||
*/ | |||
WxMaDomainAction setWebViewDomain(WxMaDomainAction domainAction) throws WxErrorException; | |||
/** | |||
* 绑定微信用户为小程序体验者 | |||
* | |||
* @param wechatId 微信号 | |||
* @throws WxErrorException 失败时抛出,具体错误码请看文档 | |||
*/ | |||
void bindTester(String wechatId) throws WxErrorException; | |||
/** | |||
* 解除绑定小程序的体验者 | |||
* | |||
* @param wechatId 微信号 | |||
* @throws WxErrorException 失败时抛出,具体错误码请看文档 | |||
*/ | |||
void unbindTester(String wechatId) throws WxErrorException; | |||
} |
@@ -4,7 +4,7 @@ import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateAddResult; | |||
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryGetResult; | |||
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; | |||
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.util.List; | |||
@@ -3,7 +3,7 @@ package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | |||
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; | |||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
/** | |||
* 用户信息相关操作接口. | |||
@@ -0,0 +1,126 @@ | |||
package cn.binarywang.wx.miniapp.api.impl; | |||
import cn.binarywang.wx.miniapp.api.WxMaAnalysisService; | |||
import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaSummaryTrend; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaUserPortrait; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitDistribution; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitPage; | |||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitTrend; | |||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import com.google.gson.reflect.TypeToken; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import org.apache.commons.lang3.time.DateFormatUtils; | |||
import java.lang.reflect.Type; | |||
import java.util.Date; | |||
import java.util.List; | |||
/** | |||
* @author <a href="https://github.com/charmingoh">Charming</a> | |||
* @since 2018-04-28 | |||
*/ | |||
public class WxMaAnalysisServiceImpl implements WxMaAnalysisService { | |||
private static final JsonParser JSON_PARSER = new JsonParser(); | |||
private WxMaService wxMaService; | |||
public WxMaAnalysisServiceImpl(WxMaService wxMaService) { | |||
this.wxMaService = wxMaService; | |||
} | |||
@Override | |||
public List<WxMaSummaryTrend> getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException { | |||
return getAnalysisResultAsList(GET_DAILY_SUMMARY_TREND_URL, beginDate, endDate, | |||
new TypeToken<List<WxMaSummaryTrend>>() { | |||
}.getType()); | |||
} | |||
@Override | |||
public List<WxMaVisitTrend> getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { | |||
return getAnalysisResultAsList(GET_DAILY_VISIT_TREND_URL, beginDate, endDate, | |||
new TypeToken<List<WxMaVisitTrend>>() { | |||
}.getType()); | |||
} | |||
@Override | |||
public List<WxMaVisitTrend> getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { | |||
return getAnalysisResultAsList(GET_WEEKLY_VISIT_TREND_URL, beginDate, endDate, | |||
new TypeToken<List<WxMaVisitTrend>>() { | |||
}.getType()); | |||
} | |||
@Override | |||
public List<WxMaVisitTrend> getMonthlyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { | |||
return getAnalysisResultAsList(GET_MONTHLY_VISIT_TREND_URL, beginDate, endDate, | |||
new TypeToken<List<WxMaVisitTrend>>() { | |||
}.getType()); | |||
} | |||
@Override | |||
public WxMaVisitDistribution getVisitDistribution(Date beginDate, Date endDate) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(GET_VISIT_DISTRIBUTION_URL, toJson(beginDate, endDate)); | |||
return WxMaVisitDistribution.fromJson(responseContent); | |||
} | |||
@Override | |||
public WxMaRetainInfo getDailyRetainInfo(Date beginDate, Date endDate) throws WxErrorException { | |||
return getRetainInfo(beginDate, endDate, GET_DAILY_RETAIN_INFO_URL); | |||
} | |||
@Override | |||
public WxMaRetainInfo getWeeklyRetainInfo(Date beginDate, Date endDate) throws WxErrorException { | |||
return getRetainInfo(beginDate, endDate, GET_WEEKLY_RETAIN_INFO_URL); | |||
} | |||
@Override | |||
public WxMaRetainInfo getMonthlyRetainInfo(Date beginDate, Date endDate) throws WxErrorException { | |||
return getRetainInfo(beginDate, endDate, GET_MONTHLY_RETAIN_INFO_URL); | |||
} | |||
@Override | |||
public List<WxMaVisitPage> getVisitPage(Date beginDate, Date endDate) throws WxErrorException { | |||
return getAnalysisResultAsList(GET_VISIT_PAGE_URL, beginDate, endDate, | |||
new TypeToken<List<WxMaVisitPage>>() { | |||
}.getType()); | |||
} | |||
@Override | |||
public WxMaUserPortrait getUserPortrait(Date beginDate, Date endDate) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(GET_USER_PORTRAIT_URL, toJson(beginDate, endDate)); | |||
return WxMaUserPortrait.fromJson(responseContent); | |||
} | |||
private WxMaRetainInfo getRetainInfo(Date beginDate, Date endDate, String url) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(url, toJson(beginDate, endDate)); | |||
return WxMaRetainInfo.fromJson(responseContent); | |||
} | |||
/** | |||
* 获取数据分析结果并返回 List,returnType 类型 | |||
* | |||
* @param url 链接 | |||
* @param returnType 返回的类型 | |||
* @param <T> 返回的类型 | |||
* @return List 类型的数据 | |||
*/ | |||
private <T> List<T> getAnalysisResultAsList(String url, Date beginDate, Date endDate, Type returnType) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(url, toJson(beginDate, endDate)); | |||
JsonObject response = JSON_PARSER.parse(responseContent).getAsJsonObject(); | |||
boolean hasList = response.has("list"); | |||
if (hasList) { | |||
return WxMaGsonBuilder.create().fromJson(response.getAsJsonArray("list"), returnType); | |||
} else { | |||
return null; | |||
} | |||
} | |||
private static String toJson(Date beginDate, Date endDate) { | |||
JsonObject param = new JsonObject(); | |||
param.addProperty("begin_date", DateFormatUtils.format(beginDate, "yyyyMMdd")); | |||
param.addProperty("end_date", DateFormatUtils.format(endDate, "yyyyMMdd")); | |||
return param.toString(); | |||
} | |||
} |
@@ -0,0 +1,148 @@ | |||
package cn.binarywang.wx.miniapp.api.impl; | |||
import cn.binarywang.wx.miniapp.api.WxMaCodeService; | |||
import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCategory; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest; | |||
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; | |||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import com.google.gson.reflect.TypeToken; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
import me.chanjar.weixin.common.util.json.GsonHelper; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.file.Files; | |||
import java.nio.file.Path; | |||
import java.util.List; | |||
/** | |||
* @author <a href="https://github.com/charmingoh">Charming</a> | |||
* @since 2018-04-26 20:00 | |||
*/ | |||
public class WxMaCodeServiceImpl implements WxMaCodeService { | |||
private static final JsonParser JSON_PARSER = new JsonParser(); | |||
private WxMaService wxMaService; | |||
public WxMaCodeServiceImpl(WxMaService wxMaService) { | |||
this.wxMaService = wxMaService; | |||
} | |||
@Override | |||
public void commit(WxMaCodeCommitRequest commitRequest) throws WxErrorException { | |||
this.wxMaService.post(COMMIT_URL, commitRequest.toJson()); | |||
} | |||
@Override | |||
public byte[] getQrCode() throws WxErrorException { | |||
String appId = this.wxMaService.getWxMaConfig().getAppid(); | |||
Path qrCodeFilePath = null; | |||
try { | |||
RequestExecutor<File, String> executor = BaseMediaDownloadRequestExecutor | |||
.create(this.wxMaService.getRequestHttp(), Files.createTempDirectory("weixin-java-tools-ma-" + appId).toFile()); | |||
qrCodeFilePath = this.wxMaService.execute(executor, GET_QRCODE_URL, null).toPath(); | |||
return Files.readAllBytes(qrCodeFilePath); | |||
} catch (IOException e) { | |||
throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); | |||
} finally { | |||
if (qrCodeFilePath != null) { | |||
try { | |||
// 及时删除二维码文件,避免积压过多缓存文件 | |||
Files.delete(qrCodeFilePath); | |||
} catch (Exception ignored) { | |||
} | |||
} | |||
} | |||
} | |||
@Override | |||
public List<WxMaCategory> getCategory() throws WxErrorException { | |||
String responseContent = this.wxMaService.get(GET_CATEGORY_URL, null); | |||
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); | |||
boolean hasCategoryList = jsonObject.has("category_list"); | |||
if (hasCategoryList) { | |||
return WxMaGsonBuilder.create().fromJson(jsonObject.getAsJsonArray("category_list"), | |||
new TypeToken<List<WxMaCategory>>() { | |||
}.getType()); | |||
} else { | |||
return null; | |||
} | |||
} | |||
@Override | |||
public List<String> getPage() throws WxErrorException { | |||
String responseContent = this.wxMaService.get(GET_PAGE_URL, null); | |||
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); | |||
boolean hasPageList = jsonObject.has("page_list"); | |||
if (hasPageList) { | |||
return WxMaGsonBuilder.create().fromJson(jsonObject.getAsJsonArray("page_list"), | |||
new TypeToken<List<String>>() { | |||
}.getType()); | |||
} else { | |||
return null; | |||
} | |||
} | |||
@Override | |||
public long submitAudit(WxMaCodeSubmitAuditRequest auditRequest) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(SUBMIT_AUDIT_URL, auditRequest.toJson()); | |||
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); | |||
return GsonHelper.getLong(jsonObject, "auditid"); | |||
} | |||
@Override | |||
public WxMaCodeAuditStatus getAuditStatus(long auditId) throws WxErrorException { | |||
JsonObject param = new JsonObject(); | |||
param.addProperty("auditid", auditId); | |||
String responseContent = this.wxMaService.post(GET_AUDIT_STATUS_URL, param.toString()); | |||
return WxMaCodeAuditStatus.fromJson(responseContent); | |||
} | |||
@Override | |||
public WxMaCodeAuditStatus getLatestAuditStatus() throws WxErrorException { | |||
String responseContent = this.wxMaService.get(GET_LATEST_AUDIT_STATUS_URL, null); | |||
return WxMaCodeAuditStatus.fromJson(responseContent); | |||
} | |||
@Override | |||
public void release() throws WxErrorException { | |||
this.wxMaService.post(RELEASE_URL, "{}"); | |||
} | |||
@Override | |||
public void changeVisitStatus(String action) throws WxErrorException { | |||
JsonObject param = new JsonObject(); | |||
param.addProperty("action", action); | |||
this.wxMaService.post(CHANGE_VISIT_STATUS_URL, param.toString()); | |||
} | |||
@Override | |||
public void revertCodeRelease() throws WxErrorException { | |||
this.wxMaService.get(REVERT_CODE_RELEASE_URL, null); | |||
} | |||
@Override | |||
public WxMaCodeVersionDistribution getSupportVersion() throws WxErrorException { | |||
String responseContent = this.wxMaService.post(GET_SUPPORT_VERSION_URL, "{}"); | |||
return WxMaCodeVersionDistribution.fromJson(responseContent); | |||
} | |||
@Override | |||
public void setSupportVersion(String version) throws WxErrorException { | |||
JsonObject param = new JsonObject(); | |||
param.addProperty("version", version); | |||
this.wxMaService.post(SET_SUPPORT_VERSION_URL, param.toString()); | |||
} | |||
@Override | |||
public void undoCodeAudit() throws WxErrorException { | |||
this.wxMaService.get(UNDO_CODE_AUDIT_URL, null); | |||
} | |||
} |
@@ -2,9 +2,9 @@ package cn.binarywang.wx.miniapp.api.impl; | |||
import cn.binarywang.wx.miniapp.api.WxMaMediaService; | |||
import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.fs.FileUtils; | |||
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | |||
@@ -7,8 +7,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; | |||
import cn.binarywang.wx.miniapp.constant.WxMaConstants; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
/** | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
@@ -5,9 +5,9 @@ import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; | |||
import cn.binarywang.wx.miniapp.bean.WxMaQrcode; | |||
import cn.binarywang.wx.miniapp.bean.WxMaWxcode; | |||
import cn.binarywang.wx.miniapp.bean.WxMaWxcodeLimit; | |||
import cn.binarywang.wx.miniapp.bean.WxaCodeUnlimit; | |||
import cn.binarywang.wx.miniapp.util.http.QrCodeRequestExecutor; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.io.File; | |||
@@ -33,42 +33,44 @@ public class WxMaQrcodeServiceImpl implements WxMaQrcodeService { | |||
} | |||
@Override | |||
public File createWxCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor) throws WxErrorException { | |||
public File createWxaCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException { | |||
WxMaWxcode wxMaWxcode = new WxMaWxcode(); | |||
wxMaWxcode.setPath(path); | |||
wxMaWxcode.setWidth(width); | |||
wxMaWxcode.setAutoColor(autoColor); | |||
wxMaWxcode.setLineColor(lineColor); | |||
wxMaWxcode.setHyaline(isHyaline); | |||
return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), | |||
GET_WXACODE_URL, wxMaWxcode); | |||
} | |||
@Override | |||
public File createWxCode(String path, int width) throws WxErrorException { | |||
return this.createWxCode(path, width, true, null); | |||
public File createWxaCode(String path, int width) throws WxErrorException { | |||
return this.createWxaCode(path, width, true, null, false); | |||
} | |||
@Override | |||
public File createWxCode(String path) throws WxErrorException { | |||
return this.createWxCode(path, 430, true, null); | |||
public File createWxaCode(String path) throws WxErrorException { | |||
return this.createWxaCode(path, 430, true, null, false); | |||
} | |||
@Override | |||
public File createWxCodeLimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor) | |||
public File createWxaCodeUnlimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline) | |||
throws WxErrorException { | |||
WxMaWxcodeLimit wxMaWxcodeLimit = new WxMaWxcodeLimit(); | |||
wxMaWxcodeLimit.setScene(scene); | |||
wxMaWxcodeLimit.setPage(page); | |||
wxMaWxcodeLimit.setWidth(width); | |||
wxMaWxcodeLimit.setAutoColor(autoColor); | |||
wxMaWxcodeLimit.setLineColor(lineColor); | |||
WxaCodeUnlimit wxaCodeUnlimit = new WxaCodeUnlimit(); | |||
wxaCodeUnlimit.setScene(scene); | |||
wxaCodeUnlimit.setPage(page); | |||
wxaCodeUnlimit.setWidth(width); | |||
wxaCodeUnlimit.setAutoColor(autoColor); | |||
wxaCodeUnlimit.setLineColor(lineColor); | |||
wxaCodeUnlimit.setHyaline(isHyaline); | |||
return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), | |||
GET_WXACODE_UNLIMIT_URL, wxMaWxcodeLimit); | |||
GET_WXACODE_UNLIMIT_URL, wxaCodeUnlimit); | |||
} | |||
@Override | |||
public File createWxCodeLimit(String scene, String page) throws WxErrorException { | |||
return this.createWxCodeLimit(scene, page, 430, true, null); | |||
public File createWxaCodeUnlimit(String scene, String page) throws WxErrorException { | |||
return this.createWxaCodeUnlimit(scene, page, 430, true, null, false); | |||
} | |||
} |
@@ -1,32 +1,21 @@ | |||
package cn.binarywang.wx.miniapp.api.impl; | |||
import java.io.IOException; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.concurrent.locks.Lock; | |||
import org.apache.http.HttpHost; | |||
import org.apache.http.client.config.RequestConfig; | |||
import org.apache.http.client.methods.CloseableHttpResponse; | |||
import org.apache.http.client.methods.HttpGet; | |||
import org.apache.http.impl.client.BasicResponseHandler; | |||
import org.apache.http.impl.client.CloseableHttpClient; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import cn.binarywang.wx.miniapp.api.WxMaAnalysisService; | |||
import cn.binarywang.wx.miniapp.api.WxMaCodeService; | |||
import cn.binarywang.wx.miniapp.api.WxMaMediaService; | |||
import cn.binarywang.wx.miniapp.api.WxMaMsgService; | |||
import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; | |||
import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import cn.binarywang.wx.miniapp.api.WxMaSettingService; | |||
import cn.binarywang.wx.miniapp.api.WxMaTemplateService; | |||
import cn.binarywang.wx.miniapp.api.WxMaUserService; | |||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | |||
import cn.binarywang.wx.miniapp.config.WxMaConfig; | |||
import cn.binarywang.wx.miniapp.constant.WxMaConstants; | |||
import com.google.common.base.Joiner; | |||
import me.chanjar.weixin.common.bean.WxAccessToken; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.DataUtils; | |||
import me.chanjar.weixin.common.util.crypto.SHA1; | |||
import me.chanjar.weixin.common.util.http.HttpType; | |||
import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
@@ -35,6 +24,21 @@ import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | |||
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | |||
import org.apache.http.HttpHost; | |||
import org.apache.http.client.config.RequestConfig; | |||
import org.apache.http.client.methods.CloseableHttpResponse; | |||
import org.apache.http.client.methods.HttpGet; | |||
import org.apache.http.impl.client.BasicResponseHandler; | |||
import org.apache.http.impl.client.CloseableHttpClient; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.IOException; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.concurrent.locks.Lock; | |||
import static cn.binarywang.wx.miniapp.constant.WxMaConstants.ErrorCode.*; | |||
/** | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
@@ -51,6 +55,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
private WxMaUserService userService = new WxMaUserServiceImpl(this); | |||
private WxMaQrcodeService qrCodeService = new WxMaQrcodeServiceImpl(this); | |||
private WxMaTemplateService templateService = new WxMaTemplateServiceImpl(this); | |||
private WxMaAnalysisService analysisService = new WxMaAnalysisServiceImpl(this); | |||
private WxMaCodeService codeService = new WxMaCodeServiceImpl(this); | |||
private WxMaSettingService settingService = new WxMaSettingServiceImpl(this); | |||
private int retrySleepMillis = 1000; | |||
private int maxRetryTimes = 5; | |||
@@ -207,7 +214,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
throw new RuntimeException("微信服务端异常,超出重试次数"); | |||
} | |||
public <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | |||
private <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | |||
E dataForLog = DataUtils.handleDataWithSecret(data); | |||
if (uri.contains("access_token=")) { | |||
throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | |||
} | |||
@@ -217,16 +226,16 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
try { | |||
T result = executor.execute(uriWithAccessToken, data); | |||
this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); | |||
this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); | |||
return result; | |||
} catch (WxErrorException e) { | |||
WxError error = e.getError(); | |||
/* | |||
* 发生以下情况时尝试刷新access_token | |||
*/ | |||
if (error.getErrorCode() == WxMaConstants.ErrorCode.ERR_40001 | |||
|| error.getErrorCode() == WxMaConstants.ErrorCode.ERR_42001 | |||
|| error.getErrorCode() == WxMaConstants.ErrorCode.ERR_40014) { | |||
if (error.getErrorCode() == ERR_40001 | |||
|| error.getErrorCode() == ERR_42001 | |||
|| error.getErrorCode() == ERR_40014) { | |||
// 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | |||
this.getWxMaConfig().expireAccessToken(); | |||
if (this.getWxMaConfig().autoRefreshToken()) { | |||
@@ -235,12 +244,12 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
} | |||
if (error.getErrorCode() != 0) { | |||
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); | |||
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); | |||
throw new WxErrorException(error, e); | |||
} | |||
return null; | |||
} catch (IOException e) { | |||
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); | |||
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); | |||
throw new RuntimeException(e); | |||
} | |||
} | |||
@@ -290,4 +299,19 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
public WxMaTemplateService getTemplateService() { | |||
return this.templateService; | |||
} | |||
@Override | |||
public WxMaAnalysisService getAnalysisService() { | |||
return this.analysisService; | |||
} | |||
@Override | |||
public WxMaCodeService getCodeService() { | |||
return this.codeService; | |||
} | |||
@Override | |||
public WxMaSettingService getSettingService() { | |||
return this.settingService; | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
package cn.binarywang.wx.miniapp.api.impl; | |||
import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import cn.binarywang.wx.miniapp.api.WxMaSettingService; | |||
import cn.binarywang.wx.miniapp.bean.WxMaDomainAction; | |||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* @author <a href="https://github.com/charmingoh">Charming</a> | |||
* @since 2018-04-27 15:46 | |||
*/ | |||
public class WxMaSettingServiceImpl implements WxMaSettingService { | |||
private WxMaService wxMaService; | |||
public WxMaSettingServiceImpl(WxMaService wxMaService) { | |||
this.wxMaService = wxMaService; | |||
} | |||
@Override | |||
public WxMaDomainAction modifyDomain(WxMaDomainAction domainAction) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(MODIFY_DOMAIN_URL, domainAction.toJson()); | |||
return WxMaDomainAction.fromJson(responseContent); | |||
} | |||
@Override | |||
public WxMaDomainAction setWebViewDomain(WxMaDomainAction domainAction) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(SET_WEB_VIEW_DOMAIN_URL, domainAction.toJson()); | |||
return WxMaDomainAction.fromJson(responseContent); | |||
} | |||
@Override | |||
public void bindTester(String wechatId) throws WxErrorException { | |||
Map<String, Object> param = new HashMap<>(1); | |||
param.put("wechatid", wechatId); | |||
this.wxMaService.post(BIND_TESTER_URL, WxMaGsonBuilder.create().toJson(param)); | |||
} | |||
@Override | |||
public void unbindTester(String wechatId) throws WxErrorException { | |||
Map<String, Object> param = new HashMap<>(1); | |||
param.put("wechatid", wechatId); | |||
this.wxMaService.post(UNBIND_TESTER_URL, WxMaGsonBuilder.create().toJson(param)); | |||
} | |||
} |
@@ -6,8 +6,8 @@ import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateAddResult; | |||
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryGetResult; | |||
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; | |||
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||
import java.util.HashMap; | |||