* #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> | <modelVersion>4.0.0</modelVersion> | ||||
| <groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
| <artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
| <version>3.0.0</version> | |||||
| <version>3.1.0</version> | |||||
| <packaging>pom</packaging> | <packaging>pom</packaging> | ||||
| <name>Weixin Java Tools - Parent</name> | <name>Weixin Java Tools - Parent</name> | ||||
| <description>微信公众号、企业号上级POM</description> | <description>微信公众号、企业号上级POM</description> | ||||
| @@ -7,7 +7,7 @@ | |||||
| <parent> | <parent> | ||||
| <groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
| <artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
| <version>3.0.0</version> | |||||
| <version>3.1.0</version> | |||||
| </parent> | </parent> | ||||
| <artifactId>weixin-java-common</artifactId> | <artifactId>weixin-java-common</artifactId> | ||||
| @@ -109,6 +109,11 @@ | |||||
| <artifactId>jetty-servlet</artifactId> | <artifactId>jetty-servlet</artifactId> | ||||
| <scope>test</scope> | <scope>test</scope> | ||||
| </dependency> | </dependency> | ||||
| <dependency> | |||||
| <groupId>org.assertj</groupId> | |||||
| <artifactId>assertj-guava</artifactId> | |||||
| <scope>test</scope> | |||||
| </dependency> | |||||
| </dependencies> | </dependencies> | ||||
| <build> | <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 TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; | ||||
| /** | |||||
| * 小程序卡片(要求小程序与公众号已关联) | |||||
| */ | |||||
| public static final String MINIPROGRAMPAGE="miniprogrampage"; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -1,6 +1,6 @@ | |||||
| package me.chanjar.weixin.common.api; | package me.chanjar.weixin.common.api; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| /** | /** | ||||
| * 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 { | public class WxErrorException extends Exception { | ||||
| private static final long serialVersionUID = -6357149550353160810L; | private static final long serialVersionUID = -6357149550353160810L; | ||||
| private WxError error; | 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; | package me.chanjar.weixin.common.util; | ||||
| import com.google.common.collect.Lists; | 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.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.apache.commons.lang3.StringUtils; | ||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import java.lang.reflect.Field; | import java.lang.reflect.Field; | ||||
| import java.lang.reflect.Modifier; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.Arrays; | import java.util.Arrays; | ||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | |||||
| /** | /** | ||||
| * <pre> | * <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; | package me.chanjar.weixin.common.util; | ||||
| import me.chanjar.weixin.common.api.WxErrorExceptionHandler; | 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.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| @@ -19,7 +19,7 @@ public class FileUtils { | |||||
| File resultFile = File.createTempFile(name, '.' + ext, tmpDirFile); | File resultFile = File.createTempFile(name, '.' + ext, tmpDirFile); | ||||
| resultFile.deleteOnExit(); | resultFile.deleteOnExit(); | ||||
| org.apache.commons.io.FileUtils.copyInputStreamToFile(inputStream, resultFile); | |||||
| org.apache.commons.io.FileUtils.copyToFile(inputStream, resultFile); | |||||
| return resultFile; | return resultFile; | ||||
| } | } | ||||
| @@ -1,8 +1,8 @@ | |||||
| package me.chanjar.weixin.common.util.http; | package me.chanjar.weixin.common.util.http; | ||||
| import jodd.http.HttpResponse; | 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 okhttp3.Response; | ||||
| import org.apache.http.Header; | import org.apache.http.Header; | ||||
| import org.apache.http.client.methods.CloseableHttpResponse; | import org.apache.http.client.methods.CloseableHttpResponse; | ||||
| @@ -1,6 +1,6 @@ | |||||
| package me.chanjar.weixin.common.util.http; | 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; | import java.io.IOException; | ||||
| @@ -9,51 +9,13 @@ import java.io.IOException; | |||||
| * | * | ||||
| * @param <T> 返回值类型 | * @param <T> 返回值类型 | ||||
| * @param <E> 请求参数类型 | * @param <E> 请求参数类型 | ||||
| * @author Daniel Qian | |||||
| */ | */ | ||||
| public interface RequestExecutor<T, E> { | public interface RequestExecutor<T, E> { | ||||
| /** | /** | ||||
| * @param uri uri | * @param uri uri | ||||
| * @param data 数据 | * @param data 数据 | ||||
| * @throws WxErrorException | |||||
| * @throws IOException | |||||
| */ | */ | ||||
| T execute(String uri, E data) throws WxErrorException, 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; | 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.RequestHttp; | ||||
| import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | ||||
| import org.apache.http.HttpHost; | import org.apache.http.HttpHost; | ||||
| @@ -1,11 +1,9 @@ | |||||
| package me.chanjar.weixin.common.util.http.apache; | 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.io.FilenameUtils; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.apache.http.Header; | 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.entity.ContentType; | ||||
| import org.apache.http.impl.client.CloseableHttpClient; | 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. | * Created by ecoolper on 2017/5/5. | ||||
| @@ -45,8 +46,7 @@ public class ApacheMediaDownloadRequestExecutor extends BaseMediaDownloadRequest | |||||
| } | } | ||||
| try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet); | 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"); | Header[] contentTypeHeader = response.getHeaders("Content-Type"); | ||||
| if (contentTypeHeader != null && contentTypeHeader.length > 0) { | if (contentTypeHeader != null && contentTypeHeader.length > 0) { | ||||
| if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { | if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { | ||||
| @@ -1,8 +1,8 @@ | |||||
| package me.chanjar.weixin.common.util.http.apache; | 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.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.MediaUploadRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | import me.chanjar.weixin.common.util.http.RequestHttp; | ||||
| import org.apache.http.HttpEntity; | 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.config.RequestConfig; | ||||
| import org.apache.http.client.methods.CloseableHttpResponse; | import org.apache.http.client.methods.CloseableHttpResponse; | ||||
| import org.apache.http.client.methods.HttpPost; | 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.HttpMultipartMode; | ||||
| import org.apache.http.entity.mime.MultipartEntityBuilder; | import org.apache.http.entity.mime.MultipartEntityBuilder; | ||||
| import org.apache.http.impl.client.CloseableHttpClient; | import org.apache.http.impl.client.CloseableHttpClient; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.common.util.http.apache; | 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.RequestHttp; | ||||
| import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | ||||
| import org.apache.http.Consts; | import org.apache.http.Consts; | ||||
| @@ -1,23 +1,24 @@ | |||||
| package me.chanjar.weixin.common.util.http.jodd; | 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.HttpConnectionProvider; | ||||
| import jodd.http.HttpRequest; | import jodd.http.HttpRequest; | ||||
| import jodd.http.HttpResponse; | import jodd.http.HttpResponse; | ||||
| import jodd.http.ProxyInfo; | import jodd.http.ProxyInfo; | ||||
| import jodd.util.StringPool; | 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.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.BaseMediaDownloadRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.HttpResponseProxy; | |||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | 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. | * Created by ecoolper on 2017/5/5. | ||||
| @@ -57,9 +58,12 @@ public class JoddHttpMediaDownloadRequestExecutor extends BaseMediaDownloadReque | |||||
| return null; | 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.http.ProxyInfo; | ||||
| import jodd.util.StringPool; | 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.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.MediaUploadRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | 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.http.*; | ||||
| import jodd.util.StringPool; | 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.RequestHttp; | ||||
| import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | ||||
| @@ -5,8 +5,8 @@ import jodd.http.HttpRequest; | |||||
| import jodd.http.HttpResponse; | import jodd.http.HttpResponse; | ||||
| import jodd.http.ProxyInfo; | import jodd.http.ProxyInfo; | ||||
| import jodd.util.StringPool; | 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.RequestHttp; | ||||
| import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.common.util.http.okhttp; | 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.BaseMediaDownloadRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.HttpResponseProxy; | import me.chanjar.weixin.common.util.http.HttpResponseProxy; | ||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | import me.chanjar.weixin.common.util.http.RequestHttp; | ||||
| @@ -1,8 +1,8 @@ | |||||
| package me.chanjar.weixin.common.util.http.okhttp; | 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.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.MediaUploadRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | import me.chanjar.weixin.common.util.http.RequestHttp; | ||||
| import okhttp3.*; | import okhttp3.*; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.common.util.http.okhttp; | 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.RequestHttp; | ||||
| import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | ||||
| import okhttp3.*; | import okhttp3.*; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.common.util.http.okhttp; | 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.RequestHttp; | ||||
| import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | ||||
| import okhttp3.*; | import okhttp3.*; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.common.util.json; | package me.chanjar.weixin.common.util.json; | ||||
| import com.google.gson.*; | import com.google.gson.*; | ||||
| import me.chanjar.weixin.common.bean.result.WxError; | |||||
| import me.chanjar.weixin.common.error.WxError; | |||||
| import java.lang.reflect.Type; | import java.lang.reflect.Type; | ||||
| @@ -4,7 +4,7 @@ import com.google.gson.Gson; | |||||
| import com.google.gson.GsonBuilder; | import com.google.gson.GsonBuilder; | ||||
| import me.chanjar.weixin.common.bean.WxAccessToken; | import me.chanjar.weixin.common.bean.WxAccessToken; | ||||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | 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; | import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | ||||
| public class WxGsonBuilder { | public class WxGsonBuilder { | ||||
| @@ -1,5 +1,7 @@ | |||||
| package me.chanjar.weixin.common.util.xml; | package me.chanjar.weixin.common.util.xml; | ||||
| import java.io.Writer; | |||||
| import com.thoughtworks.xstream.XStream; | import com.thoughtworks.xstream.XStream; | ||||
| import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider; | import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider; | ||||
| import com.thoughtworks.xstream.core.util.QuickWriter; | 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.NullPermission; | ||||
| import com.thoughtworks.xstream.security.PrimitiveTypePermission; | import com.thoughtworks.xstream.security.PrimitiveTypePermission; | ||||
| import java.io.Writer; | |||||
| public class XStreamInitializer { | public class XStreamInitializer { | ||||
| public static XStream getInstance() { | public static XStream getInstance() { | ||||
| @@ -38,7 +38,8 @@ public class XStreamInitializer { | |||||
| @Override | @Override | ||||
| public String encodeNode(String name) { | public String encodeNode(String name) { | ||||
| return name;//防止将_转换成__ | |||||
| //防止将_转换成__ | |||||
| return name; | |||||
| } | } | ||||
| }; | }; | ||||
| } | } | ||||
| @@ -48,6 +49,7 @@ public class XStreamInitializer { | |||||
| xstream.setMode(XStream.NO_REFERENCES); | xstream.setMode(XStream.NO_REFERENCES); | ||||
| xstream.addPermission(NullPermission.NULL); | xstream.addPermission(NullPermission.NULL); | ||||
| xstream.addPermission(PrimitiveTypePermission.PRIMITIVES); | xstream.addPermission(PrimitiveTypePermission.PRIMITIVES); | ||||
| xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||||
| return xstream; | 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 | @Test | ||||
| public class WxErrorTest { | public class WxErrorTest { | ||||
| @@ -10,26 +11,24 @@ public class WxErrorTest { | |||||
| public void testFromJson() { | public void testFromJson() { | ||||
| String json = "{ \"errcode\": 40003, \"errmsg\": \"invalid openid\" }"; | String json = "{ \"errcode\": 40003, \"errmsg\": \"invalid openid\" }"; | ||||
| WxError wxError = WxError.fromJson(json); | 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() { | public void testFromBadJson1() { | ||||
| String json = "{ \"errcode\": 40003, \"errmsg\": \"invalid openid\", \"media_id\": \"12323423dsfafsf232f\" }"; | String json = "{ \"errcode\": 40003, \"errmsg\": \"invalid openid\", \"media_id\": \"12323423dsfafsf232f\" }"; | ||||
| WxError wxError = WxError.fromJson(json); | 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() { | public void testFromBadJson2() { | ||||
| String json = "{\"access_token\":\"ACCESS_TOKEN\",\"expires_in\":7200}"; | String json = "{\"access_token\":\"ACCESS_TOKEN\",\"expires_in\":7200}"; | ||||
| WxError wxError = WxError.fromJson(json); | 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> | <parent> | ||||
| <groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
| <artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
| <version>3.0.0</version> | |||||
| <version>3.1.0</version> | |||||
| </parent> | </parent> | ||||
| <artifactId>weixin-java-cp</artifactId> | <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; | 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 me.chanjar.weixin.cp.bean.WxCpDepart; | ||||
| import java.util.List; | import java.util.List; | ||||
| @@ -1,12 +1,12 @@ | |||||
| package me.chanjar.weixin.cp.api; | 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.File; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| /** | /** | ||||
| * <pre> | * <pre> | ||||
| * 媒体管理接口 | * 媒体管理接口 | ||||
| @@ -30,7 +30,7 @@ public interface WxCpMediaService { | |||||
| * | * | ||||
| * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} | * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} | ||||
| * @param fileType 文件类型,请看{@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) | WxMediaUploadResult upload(String mediaType, String fileType, InputStream inputStream) | ||||
| throws WxErrorException, IOException; | throws WxErrorException, IOException; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.cp.api; | package me.chanjar.weixin.cp.api; | ||||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | import me.chanjar.weixin.common.bean.menu.WxMenu; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| /** | /** | ||||
| * <pre> | * <pre> | ||||
| @@ -1,6 +1,7 @@ | |||||
| package me.chanjar.weixin.cp.api; | 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> | * <pre> | ||||
| @@ -64,4 +65,19 @@ public interface WxCpOAuth2Service { | |||||
| */ | */ | ||||
| String[] getUserInfo(Integer agentId, String code) throws WxErrorException; | 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; | package me.chanjar.weixin.cp.api; | ||||
| import me.chanjar.weixin.common.bean.WxJsapiSignature; | 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.WxSession; | ||||
| import me.chanjar.weixin.common.session.WxSessionManager; | import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | 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.bean.*; | ||||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | 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 | * 微信API的Service | ||||
| * @author chanjaster | * @author chanjaster | ||||
| @@ -249,6 +242,8 @@ public interface WxCpService { | |||||
| */ | */ | ||||
| WxCpUserService getUserService(); | WxCpUserService getUserService(); | ||||
| WxCpAgentService getAgentService(); | |||||
| /** | /** | ||||
| * http请求对象 | * http请求对象 | ||||
| */ | */ | ||||
| @@ -1,15 +1,16 @@ | |||||
| package me.chanjar.weixin.cp.api; | 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.WxCpTag; | ||||
| import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; | 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.bean.WxCpUser; | ||||
| import java.util.List; | import java.util.List; | ||||
| /** | /** | ||||
| * <pre> | * <pre> | ||||
| * 标签管理接口 | |||||
| * 标签管理接口. | |||||
| * Created by BinaryWang on 2017/6/24. | * Created by BinaryWang on 2017/6/24. | ||||
| * </pre> | * </pre> | ||||
| * | * | ||||
| @@ -17,14 +18,14 @@ import java.util.List; | |||||
| */ | */ | ||||
| public interface WxCpTagService { | public interface WxCpTagService { | ||||
| /** | /** | ||||
| * 创建标签 | |||||
| * 创建标签. | |||||
| * | * | ||||
| * @param tagName 标签名 | * @param tagName 标签名 | ||||
| */ | */ | ||||
| String create(String tagName) throws WxErrorException; | String create(String tagName) throws WxErrorException; | ||||
| /** | /** | ||||
| * 更新标签 | |||||
| * 更新标签. | |||||
| * | * | ||||
| * @param tagId 标签id | * @param tagId 标签id | ||||
| * @param tagName 标签名 | * @param tagName 标签名 | ||||
| @@ -32,35 +33,49 @@ public interface WxCpTagService { | |||||
| void update(String tagId, String tagName) throws WxErrorException; | void update(String tagId, String tagName) throws WxErrorException; | ||||
| /** | /** | ||||
| * 删除标签 | |||||
| * 删除标签. | |||||
| * | * | ||||
| * @param tagId 标签id | * @param tagId 标签id | ||||
| */ | */ | ||||
| void delete(String tagId) throws WxErrorException; | void delete(String tagId) throws WxErrorException; | ||||
| /** | /** | ||||
| * 获得标签列表 | |||||
| * 获得标签列表. | |||||
| */ | */ | ||||
| List<WxCpTag> listAll() throws WxErrorException; | List<WxCpTag> listAll() throws WxErrorException; | ||||
| /** | /** | ||||
| * 获取标签成员 | |||||
| * 获取标签成员. | |||||
| * | * | ||||
| * @param tagId 标签ID | * @param tagId 标签ID | ||||
| */ | */ | ||||
| List<WxCpUser> listUsersByTagId(String tagId) throws WxErrorException; | 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; | 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; | 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 me.chanjar.weixin.cp.bean.WxCpUser; | ||||
| import java.util.List; | import java.util.List; | ||||
| @@ -84,18 +85,18 @@ public interface WxCpUserService { | |||||
| /** | /** | ||||
| * <pre> | * <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> | * </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> | * <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.JsonElement; | ||||
| import com.google.gson.JsonParser; | import com.google.gson.JsonParser; | ||||
| import com.google.gson.reflect.TypeToken; | 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.common.util.json.GsonHelper; | ||||
| import me.chanjar.weixin.cp.api.WxCpDepartmentService; | import me.chanjar.weixin.cp.api.WxCpDepartmentService; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | import me.chanjar.weixin.cp.api.WxCpService; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.cp.api.impl; | package me.chanjar.weixin.cp.api.impl; | ||||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | 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.fs.FileUtils; | ||||
| import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.cp.api.impl; | package me.chanjar.weixin.cp.api.impl; | ||||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | 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.WxCpMenuService; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | import me.chanjar.weixin.cp.api.WxCpService; | ||||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | ||||
| @@ -1,13 +1,15 @@ | |||||
| package me.chanjar.weixin.cp.api.impl; | package me.chanjar.weixin.cp.api.impl; | ||||
| import com.google.gson.GsonBuilder; | |||||
| import com.google.gson.JsonElement; | import com.google.gson.JsonElement; | ||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
| import com.google.gson.JsonParser; | 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.http.URIUtil; | ||||
| import me.chanjar.weixin.common.util.json.GsonHelper; | import me.chanjar.weixin.common.util.json.GsonHelper; | ||||
| import me.chanjar.weixin.cp.api.WxCpOAuth2Service; | import me.chanjar.weixin.cp.api.WxCpOAuth2Service; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | import me.chanjar.weixin.cp.api.WxCpService; | ||||
| import me.chanjar.weixin.cp.bean.WxCpUserDetail; | |||||
| /** | /** | ||||
| * <pre> | * <pre> | ||||
| @@ -52,9 +54,8 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service { | |||||
| @Override | @Override | ||||
| public String[] getUserInfo(Integer agentId, String code) throws WxErrorException { | 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); | String responseText = this.mainService.get(url, null); | ||||
| JsonElement je = new JsonParser().parse(responseText); | JsonElement je = new JsonParser().parse(responseText); | ||||
| JsonObject jo = je.getAsJsonObject(); | JsonObject jo = je.getAsJsonObject(); | ||||
| @@ -63,4 +64,12 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service { | |||||
| GsonHelper.getString(jo, "OpenId")}; | 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.JsonObject; | ||||
| import com.google.gson.JsonParser; | import com.google.gson.JsonParser; | ||||
| import me.chanjar.weixin.common.bean.WxJsapiSignature; | 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.StandardSessionManager; | ||||
| import me.chanjar.weixin.common.session.WxSession; | import me.chanjar.weixin.common.session.WxSession; | ||||
| import me.chanjar.weixin.common.session.WxSessionManager; | 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.RandomUtils; | ||||
| import me.chanjar.weixin.common.util.crypto.SHA1; | import me.chanjar.weixin.common.util.crypto.SHA1; | ||||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | 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.api.*; | ||||
| import me.chanjar.weixin.cp.bean.*; | import me.chanjar.weixin.cp.bean.*; | ||||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | import me.chanjar.weixin.cp.config.WxCpConfigStorage; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | |||||
| import java.util.List; | |||||
| public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, RequestHttp<H, P> { | public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, RequestHttp<H, P> { | ||||
| protected final Logger log = LoggerFactory.getLogger(this.getClass()); | 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 WxCpMenuService menuService = new WxCpMenuServiceImpl(this); | ||||
| private WxCpOAuth2Service oauth2Service = new WxCpOAuth2ServiceImpl(this); | private WxCpOAuth2Service oauth2Service = new WxCpOAuth2ServiceImpl(this); | ||||
| private WxCpTagService tagService = new WxCpTagServiceImpl(this); | private WxCpTagService tagService = new WxCpTagServiceImpl(this); | ||||
| private WxCpAgentService agentService = new WxCpAgentServiceImpl(this); | |||||
| /** | /** | ||||
| * 全局的是否正在刷新access token的锁 | * 全局的是否正在刷新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 { | 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=")) { | if (uri.contains("access_token=")) { | ||||
| throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | ||||
| } | } | ||||
| @@ -209,7 +208,7 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||||
| try { | try { | ||||
| T result = executor.execute(uriWithAccessToken, data); | 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; | return result; | ||||
| } catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
| WxError error = e.getError(); | WxError error = e.getError(); | ||||
| @@ -226,12 +225,12 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||||
| } | } | ||||
| if (error.getErrorCode() != 0) { | 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); | throw new WxErrorException(error, e); | ||||
| } | } | ||||
| return null; | return null; | ||||
| } catch (IOException e) { | } 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); | throw new RuntimeException(e); | ||||
| } | } | ||||
| } | } | ||||
| @@ -368,4 +367,13 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||||
| public void setTagService(WxCpTagService tagService) { | public void setTagService(WxCpTagService tagService) { | ||||
| this.tagService = 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; | 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.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.HttpType; | ||||
| import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | ||||
| import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | ||||
| @@ -58,7 +59,7 @@ public class WxCpServiceApacheHttpClientImpl extends WxCpServiceAbstractImpl<Clo | |||||
| } finally { | } finally { | ||||
| httpGet.releaseConnection(); | httpGet.releaseConnection(); | ||||
| } | } | ||||
| WxError error = WxError.fromJson(resultContent); | |||||
| WxError error = WxError.fromJson(resultContent, WxType.CP); | |||||
| if (error.getErrorCode() != 0) { | if (error.getErrorCode() != 0) { | ||||
| throw new WxErrorException(error); | throw new WxErrorException(error); | ||||
| } | } | ||||
| @@ -1,9 +1,10 @@ | |||||
| package me.chanjar.weixin.cp.api.impl; | package me.chanjar.weixin.cp.api.impl; | ||||
| import jodd.http.*; | import jodd.http.*; | ||||
| import me.chanjar.weixin.common.WxType; | |||||
| import me.chanjar.weixin.common.bean.WxAccessToken; | 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.HttpType; | ||||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | import me.chanjar.weixin.cp.config.WxCpConfigStorage; | ||||
| @@ -44,7 +45,7 @@ public class WxCpServiceJoddHttpImpl extends WxCpServiceAbstractImpl<HttpConnect | |||||
| HttpResponse response = request.send(); | HttpResponse response = request.send(); | ||||
| String resultContent = response.bodyText(); | String resultContent = response.bodyText(); | ||||
| WxError error = WxError.fromJson(resultContent); | |||||
| WxError error = WxError.fromJson(resultContent, WxType.CP); | |||||
| if (error.getErrorCode() != 0) { | if (error.getErrorCode() != 0) { | ||||
| throw new WxErrorException(error); | throw new WxErrorException(error); | ||||
| } | } | ||||
| @@ -1,8 +1,9 @@ | |||||
| package me.chanjar.weixin.cp.api.impl; | 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.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.HttpType; | ||||
| import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo; | import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo; | ||||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | import me.chanjar.weixin.cp.config.WxCpConfigStorage; | ||||
| @@ -51,7 +52,7 @@ public class WxCpServiceOkHttpImpl extends WxCpServiceAbstractImpl<OkHttpClient, | |||||
| this.log.error(e.getMessage(), e); | this.log.error(e.getMessage(), e); | ||||
| } | } | ||||
| WxError error = WxError.fromJson(resultContent); | |||||
| WxError error = WxError.fromJson(resultContent, WxType.CP); | |||||
| if (error.getErrorCode() != 0) { | if (error.getErrorCode() != 0) { | ||||
| throw new WxErrorException(error); | throw new WxErrorException(error); | ||||
| } | } | ||||
| @@ -2,11 +2,12 @@ package me.chanjar.weixin.cp.api.impl; | |||||
| import com.google.gson.*; | import com.google.gson.*; | ||||
| import com.google.gson.reflect.TypeToken; | 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.WxCpService; | ||||
| import me.chanjar.weixin.cp.api.WxCpTagService; | import me.chanjar.weixin.cp.api.WxCpTagService; | ||||
| import me.chanjar.weixin.cp.bean.WxCpTag; | import me.chanjar.weixin.cp.bean.WxCpTag; | ||||
| import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; | 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.bean.WxCpUser; | ||||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | 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"; | String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; | ||||
| JsonObject jsonObject = new JsonObject(); | JsonObject jsonObject = new JsonObject(); | ||||
| jsonObject.addProperty("tagid", tagId); | 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) { | if (userIds != null) { | ||||
| JsonArray jsonArray = new JsonArray(); | JsonArray jsonArray = new JsonArray(); | ||||
| for (String userId : userIds) { | for (String userId : userIds) { | ||||
| @@ -89,6 +106,7 @@ public class WxCpTagServiceImpl implements WxCpTagService { | |||||
| } | } | ||||
| jsonObject.add("userlist", jsonArray); | jsonObject.add("userlist", jsonArray); | ||||
| } | } | ||||
| if (partyIds != null) { | if (partyIds != null) { | ||||
| JsonArray jsonArray = new JsonArray(); | JsonArray jsonArray = new JsonArray(); | ||||
| for (String userId : partyIds) { | for (String userId : partyIds) { | ||||
| @@ -96,21 +114,19 @@ public class WxCpTagServiceImpl implements WxCpTagService { | |||||
| } | } | ||||
| jsonObject.add("partylist", jsonArray); | jsonObject.add("partylist", jsonArray); | ||||
| } | } | ||||
| return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString())); | |||||
| } | } | ||||
| @Override | @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.common.collect.Maps; | ||||
| import com.google.gson.*; | import com.google.gson.*; | ||||
| import com.google.gson.reflect.TypeToken; | 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.WxCpService; | ||||
| import me.chanjar.weixin.cp.api.WxCpUserService; | 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.bean.WxCpUser; | ||||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| @@ -116,17 +116,34 @@ public class WxCpUserServiceImpl implements WxCpUserService { | |||||
| } | } | ||||
| @Override | @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 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 | @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 hqMusicUrl; | ||||
| private String safe; | private String safe; | ||||
| private String url; | private String url; | ||||
| private String btnTxt; | |||||
| private List<NewArticle> articles = new ArrayList<>(); | private List<NewArticle> articles = new ArrayList<>(); | ||||
| private List<MpnewsArticle> mpnewsArticles = 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 | @Data | ||||
| public class WxCpUser implements Serializable { | 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 static final long serialVersionUID = -5696099236344075582L; | ||||
| private String userId; | private String userId; | ||||
| private String name; | private String name; | ||||
| @@ -69,6 +31,8 @@ public class WxCpUser implements Serializable { | |||||
| private Integer hideMobile; | private Integer hideMobile; | ||||
| private String englishName; | private String englishName; | ||||
| private String telephone; | private String telephone; | ||||
| private String qrCode; | |||||
| private Boolean toInvite; | |||||
| public void addExtAttr(String name, String value) { | public void addExtAttr(String name, String value) { | ||||
| this.extAttrs.add(new Attr(name, 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.XStreamAlias; | ||||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | import com.thoughtworks.xstream.annotations.XStreamConverter; | ||||
| import lombok.Data; | import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | |||||
| import me.chanjar.weixin.common.api.WxConsts; | import me.chanjar.weixin.common.api.WxConsts; | ||||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | ||||
| @@ -11,6 +12,7 @@ import java.util.List; | |||||
| @XStreamAlias("xml") | @XStreamAlias("xml") | ||||
| @Data | @Data | ||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | ||||
| private static final long serialVersionUID = -5796178637883178826L; | private static final long serialVersionUID = -5796178637883178826L; | ||||
| @@ -16,6 +16,7 @@ public class TextCardBuilder extends BaseBuilder<TextCardBuilder> { | |||||
| private String title; | private String title; | ||||
| private String description; | private String description; | ||||
| private String url; | private String url; | ||||
| private String btnTxt; | |||||
| public TextCardBuilder() { | public TextCardBuilder() { | ||||
| this.msgType = WxConsts.KefuMsgType.TEXTCARD; | this.msgType = WxConsts.KefuMsgType.TEXTCARD; | ||||
| @@ -36,12 +37,18 @@ public class TextCardBuilder extends BaseBuilder<TextCardBuilder> { | |||||
| return this; | return this; | ||||
| } | } | ||||
| public TextCardBuilder btnTxt(String btnTxt) { | |||||
| this.btnTxt = btnTxt; | |||||
| return this; | |||||
| } | |||||
| @Override | @Override | ||||
| public WxCpMessage build() { | public WxCpMessage build() { | ||||
| WxCpMessage m = super.build(); | WxCpMessage m = super.build(); | ||||
| m.setTitle(this.title); | m.setTitle(this.title); | ||||
| m.setDescription(this.description); | m.setDescription(this.description); | ||||
| m.setUrl(this.url); | m.setUrl(this.url); | ||||
| m.setBtnTxt(this.btnTxt); | |||||
| return m; | return m; | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,6 +1,6 @@ | |||||
| package me.chanjar.weixin.cp.message; | 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.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | import me.chanjar.weixin.cp.api.WxCpService; | ||||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | ||||
| @@ -1,6 +1,6 @@ | |||||
| package me.chanjar.weixin.cp.message; | 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.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | import me.chanjar.weixin.cp.api.WxCpService; | ||||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.cp.message; | package me.chanjar.weixin.cp.message; | ||||
| import me.chanjar.weixin.common.api.WxErrorExceptionHandler; | 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.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | import me.chanjar.weixin.cp.api.WxCpService; | ||||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | 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.Gson; | ||||
| import com.google.gson.GsonBuilder; | import com.google.gson.GsonBuilder; | ||||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | 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.common.util.json.WxErrorAdapter; | ||||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | import me.chanjar.weixin.cp.bean.WxCpDepart; | ||||
| import me.chanjar.weixin.cp.bean.WxCpMessage; | import me.chanjar.weixin.cp.bean.WxCpMessage; | ||||
| @@ -48,6 +48,7 @@ public class WxCpMessageGsonAdapter implements JsonSerializer<WxCpMessage> { | |||||
| text.addProperty("title", message.getTitle()); | text.addProperty("title", message.getTitle()); | ||||
| text.addProperty("description", message.getDescription()); | text.addProperty("description", message.getDescription()); | ||||
| text.addProperty("url", message.getUrl()); | text.addProperty("url", message.getUrl()); | ||||
| text.addProperty("btntxt", message.getBtnTxt()); | |||||
| messageJson.add("textcard", text); | messageJson.add("textcard", text); | ||||
| } | } | ||||
| @@ -10,6 +10,7 @@ package me.chanjar.weixin.cp.util.json; | |||||
| import com.google.gson.*; | import com.google.gson.*; | ||||
| import me.chanjar.weixin.common.util.json.GsonHelper; | import me.chanjar.weixin.common.util.json.GsonHelper; | ||||
| import me.chanjar.weixin.cp.bean.Gender; | |||||
| import me.chanjar.weixin.cp.bean.WxCpUser; | import me.chanjar.weixin.cp.bean.WxCpUser; | ||||
| import java.lang.reflect.Type; | import java.lang.reflect.Type; | ||||
| @@ -39,7 +40,7 @@ public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSeri | |||||
| user.setName(GsonHelper.getString(o, "name")); | user.setName(GsonHelper.getString(o, "name")); | ||||
| user.setPosition(GsonHelper.getString(o, "position")); | user.setPosition(GsonHelper.getString(o, "position")); | ||||
| user.setMobile(GsonHelper.getString(o, "mobile")); | 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.setEmail(GsonHelper.getString(o, "email")); | ||||
| user.setAvatar(GsonHelper.getString(o, "avatar")); | user.setAvatar(GsonHelper.getString(o, "avatar")); | ||||
| user.setStatus(GsonHelper.getInteger(o, "status")); | 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.setHideMobile(GsonHelper.getInteger(o, "hide_mobile")); | ||||
| user.setEnglishName(GsonHelper.getString(o, "english_name")); | user.setEnglishName(GsonHelper.getString(o, "english_name")); | ||||
| user.setTelephone(GsonHelper.getString(o, "telephone")); | 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"))) { | if (GsonHelper.isNotNull(o.get("extattr"))) { | ||||
| JsonArray attrJsonElements = o.get("extattr").getAsJsonObject().get("attrs").getAsJsonArray(); | JsonArray attrJsonElements = o.get("extattr").getAsJsonObject().get("attrs").getAsJsonArray(); | ||||
| @@ -111,6 +114,13 @@ public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSeri | |||||
| if (user.getTelephone() != null) { | if (user.getTelephone() != null) { | ||||
| o.addProperty("telephone", user.getTelephone()); | 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) { | if (user.getExtAttrs().size() > 0) { | ||||
| JsonArray attrsJsonArray = new JsonArray(); | JsonArray attrsJsonArray = new JsonArray(); | ||||
| for (WxCpUser.Attr attr : user.getExtAttrs()) { | for (WxCpUser.Attr attr : user.getExtAttrs()) { | ||||
| @@ -63,7 +63,6 @@ public class XStreamTransformer { | |||||
| private static XStream configWxCpXmlMessage() { | private static XStream configWxCpXmlMessage() { | ||||
| XStream xstream = XStreamInitializer.getInstance(); | XStream xstream = XStreamInitializer.getInstance(); | ||||
| xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||||
| xstream.processAnnotations(WxCpXmlMessage.class); | xstream.processAnnotations(WxCpXmlMessage.class); | ||||
| xstream.processAnnotations(WxCpXmlMessage.ScanCodeInfo.class); | xstream.processAnnotations(WxCpXmlMessage.ScanCodeInfo.class); | ||||
| @@ -75,7 +74,6 @@ public class XStreamTransformer { | |||||
| private static XStream configWxCpXmlOutImageMessage() { | private static XStream configWxCpXmlOutImageMessage() { | ||||
| XStream xstream = XStreamInitializer.getInstance(); | XStream xstream = XStreamInitializer.getInstance(); | ||||
| xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | xstream.processAnnotations(WxCpXmlOutMessage.class); | ||||
| xstream.processAnnotations(WxCpXmlOutImageMessage.class); | xstream.processAnnotations(WxCpXmlOutImageMessage.class); | ||||
| @@ -84,7 +82,6 @@ public class XStreamTransformer { | |||||
| private static XStream configWxCpXmlOutNewsMessage() { | private static XStream configWxCpXmlOutNewsMessage() { | ||||
| XStream xstream = XStreamInitializer.getInstance(); | XStream xstream = XStreamInitializer.getInstance(); | ||||
| xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | xstream.processAnnotations(WxCpXmlOutMessage.class); | ||||
| xstream.processAnnotations(WxCpXmlOutNewsMessage.class); | xstream.processAnnotations(WxCpXmlOutNewsMessage.class); | ||||
| @@ -94,7 +91,6 @@ public class XStreamTransformer { | |||||
| private static XStream configWxCpXmlOutTextMessage() { | private static XStream configWxCpXmlOutTextMessage() { | ||||
| XStream xstream = XStreamInitializer.getInstance(); | XStream xstream = XStreamInitializer.getInstance(); | ||||
| xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | xstream.processAnnotations(WxCpXmlOutMessage.class); | ||||
| xstream.processAnnotations(WxCpXmlOutTextMessage.class); | xstream.processAnnotations(WxCpXmlOutTextMessage.class); | ||||
| @@ -103,7 +99,6 @@ public class XStreamTransformer { | |||||
| private static XStream configWxCpXmlOutVideoMessage() { | private static XStream configWxCpXmlOutVideoMessage() { | ||||
| XStream xstream = XStreamInitializer.getInstance(); | XStream xstream = XStreamInitializer.getInstance(); | ||||
| xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | xstream.processAnnotations(WxCpXmlOutMessage.class); | ||||
| xstream.processAnnotations(WxCpXmlOutVideoMessage.class); | xstream.processAnnotations(WxCpXmlOutVideoMessage.class); | ||||
| @@ -113,7 +108,6 @@ public class XStreamTransformer { | |||||
| private static XStream configWxCpXmlOutVoiceMessage() { | private static XStream configWxCpXmlOutVoiceMessage() { | ||||
| XStream xstream = XStreamInitializer.getInstance(); | XStream xstream = XStreamInitializer.getInstance(); | ||||
| xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); | |||||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | xstream.processAnnotations(WxCpXmlOutMessage.class); | ||||
| xstream.processAnnotations(WxCpXmlOutVoiceMessage.class); | xstream.processAnnotations(WxCpXmlOutVoiceMessage.class); | ||||
| @@ -1,20 +1,24 @@ | |||||
| package me.chanjar.weixin.cp.api; | 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.Binder; | ||||
| import com.google.inject.Module; | import com.google.inject.Module; | ||||
| import com.thoughtworks.xstream.XStream; | import com.thoughtworks.xstream.XStream; | ||||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
| import me.chanjar.weixin.common.util.xml.XStreamInitializer; | import me.chanjar.weixin.common.util.xml.XStreamInitializer; | ||||
| import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; | import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; | ||||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||||
| import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage; | import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage; | ||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| public class ApiTestModule implements Module { | 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 xstream = XStreamInitializer.getInstance(); | ||||
| xstream.alias("xml", clazz); | xstream.alias("xml", clazz); | ||||
| xstream.processAnnotations(clazz); | xstream.processAnnotations(clazz); | ||||
| @@ -23,17 +27,19 @@ public class ApiTestModule implements Module { | |||||
| @Override | @Override | ||||
| public void configure(Binder binder) { | 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(); | WxCpService wxService = new WxCpServiceImpl(); | ||||
| wxService.setWxCpConfigStorage(config); | wxService.setWxCpConfigStorage(config); | ||||
| binder.bind(WxCpService.class).toInstance(wxService); | binder.bind(WxCpService.class).toInstance(wxService); | ||||
| binder.bind(WxXmlCpInMemoryConfigStorage.class).toInstance(config); | binder.bind(WxXmlCpInMemoryConfigStorage.class).toInstance(config); | ||||
| } catch (IOException e) { | } catch (IOException e) { | ||||
| e.printStackTrace(); | |||||
| this.log.error(e.getMessage(), e); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.cp.api; | package me.chanjar.weixin.cp.api; | ||||
| import com.google.inject.Inject; | 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.api.impl.WxCpServiceImpl; | ||||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | import me.chanjar.weixin.cp.config.WxCpConfigStorage; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| @@ -1,7 +1,7 @@ | |||||
| package me.chanjar.weixin.cp.api; | 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.common.util.http.RequestExecutor; | ||||
| import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; | import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; | ||||
| import org.testng.annotations.DataProvider; | import org.testng.annotations.DataProvider; | ||||
| @@ -2,7 +2,7 @@ package me.chanjar.weixin.cp.api; | |||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||
| import me.chanjar.weixin.common.api.WxConsts; | 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.WxCpMessage; | ||||
| import me.chanjar.weixin.cp.bean.WxCpMessageSendResult; | import me.chanjar.weixin.cp.bean.WxCpMessageSendResult; | ||||
| import org.testng.annotations.*; | 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 { | public void testUpdate() throws Exception { | ||||
| System.out.println("=================更新部门"); | System.out.println("=================更新部门"); | ||||
| this.depart.setName("子部门改名" + System.currentTimeMillis()); | this.depart.setName("子部门改名" + System.currentTimeMillis()); | ||||
| @@ -3,7 +3,7 @@ package me.chanjar.weixin.cp.api.impl; | |||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||
| import me.chanjar.weixin.common.api.WxConsts; | import me.chanjar.weixin.common.api.WxConsts; | ||||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | 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.ApiTestModule; | ||||
| import me.chanjar.weixin.cp.api.TestConstants; | import me.chanjar.weixin.cp.api.TestConstants; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | 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.common.base.Splitter; | ||||
| import com.google.inject.Inject; | 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.ApiTestModule; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | 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.WxCpTag; | ||||
| import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; | 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.bean.WxCpUser; | ||||
| import org.testng.annotations.*; | |||||
| import org.testng.annotations.Guice; | |||||
| import org.testng.annotations.Test; | |||||
| import java.util.List; | 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> | * <pre> | ||||
| @@ -63,7 +70,7 @@ public class WxCpTagServiceImplTest { | |||||
| @Test(dependsOnMethods = {"testListUsersByTagId", "testAddUsers2Tag", "testListAll", "testUpdate", "testCreate"}) | @Test(dependsOnMethods = {"testListUsersByTagId", "testAddUsers2Tag", "testListAll", "testUpdate", "testCreate"}) | ||||
| public void testRemoveUsersFromTag() throws Exception { | public void testRemoveUsersFromTag() throws Exception { | ||||
| List<String> userIds = Splitter.on("|").splitToList(this.configStorage.getUserId()); | 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)); | assertEquals(result.getErrCode(), Integer.valueOf(0)); | ||||
| } | } | ||||
| @@ -72,4 +79,24 @@ public class WxCpTagServiceImplTest { | |||||
| this.wxService.getTagService().delete(this.tagId); | 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; | package me.chanjar.weixin.cp.api.impl; | ||||
| import com.google.common.collect.Lists; | |||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||
| import me.chanjar.weixin.cp.api.ApiTestModule; | import me.chanjar.weixin.cp.api.ApiTestModule; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | 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 me.chanjar.weixin.cp.bean.WxCpUser; | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | import org.apache.commons.lang3.builder.ToStringBuilder; | ||||
| import org.apache.commons.lang3.builder.ToStringStyle; | import org.apache.commons.lang3.builder.ToStringStyle; | ||||
| @@ -40,7 +43,7 @@ public class WxCpUserServiceImplTest { | |||||
| user.setName("Some Woman"); | user.setName("Some Woman"); | ||||
| user.setDepartIds(new Integer[]{2}); | user.setDepartIds(new Integer[]{2}); | ||||
| user.setEmail("none@none.com"); | user.setEmail("none@none.com"); | ||||
| user.setGender(WxCpUser.Gender.FEMALE); | |||||
| user.setGender(Gender.FEMALE); | |||||
| user.setMobile("13560084979"); | user.setMobile("13560084979"); | ||||
| user.setPosition("woman"); | user.setPosition("woman"); | ||||
| user.setTelephone("3300393"); | user.setTelephone("3300393"); | ||||
| @@ -87,9 +90,9 @@ public class WxCpUserServiceImplTest { | |||||
| } | } | ||||
| @Test | @Test | ||||
| @Deprecated | |||||
| public void testInvite() throws Exception { | 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); | 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.MpnewsArticle; | ||||
| import me.chanjar.weixin.cp.bean.article.NewArticle; | 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 | @Test | ||||
| public class WxCpMessageTest { | public class WxCpMessageTest { | ||||
| public void testTextBuild() { | public void testTextBuild() { | ||||
| WxCpMessage reply = WxCpMessage.TEXT().toUser("OPENID").content("sfsfdsdf").build(); | 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() { | public void testTextCardBuild() { | ||||
| WxCpMessage reply = WxCpMessage.TEXTCARD().toUser("OPENID") | WxCpMessage reply = WxCpMessage.TEXTCARD().toUser("OPENID") | ||||
| .title("领奖通知") | .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() { | public void testImageBuild() { | ||||
| WxCpMessage reply = WxCpMessage.IMAGE().toUser("OPENID").mediaId("MEDIA_ID").build(); | 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() { | public void testVoiceBuild() { | ||||
| WxCpMessage reply = WxCpMessage.VOICE().toUser("OPENID").mediaId("MEDIA_ID").build(); | 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() { | public void testVideoBuild() { | ||||
| WxCpMessage reply = WxCpMessage.VIDEO().toUser("OPENID").title("TITLE").mediaId("MEDIA_ID").thumbMediaId("MEDIA_ID").description("DESCRIPTION").build(); | 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() { | public void testNewsBuild() { | ||||
| @@ -52,7 +60,8 @@ public class WxCpMessageTest { | |||||
| WxCpMessage reply = WxCpMessage.NEWS().toUser("OPENID").addArticle(article1).addArticle(article2).build(); | 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() { | public void testMpnewsBuild_with_articles() { | ||||
| @@ -78,14 +87,15 @@ public class WxCpMessageTest { | |||||
| WxCpMessage reply = WxCpMessage.MPNEWS().toUser("OPENID").addArticle(article1, article2).build(); | 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() { | public void testMpnewsBuild_with_media_id() { | ||||
| WxCpMessage reply = WxCpMessage.MPNEWS().toUser("OPENID").mediaId("mmm").build(); | 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; | 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 me.chanjar.weixin.cp.api.WxCpService; | ||||
| import javax.servlet.http.HttpServlet; | import javax.servlet.http.HttpServlet; | ||||
| @@ -7,7 +7,7 @@ | |||||
| <parent> | <parent> | ||||
| <groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
| <artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
| <version>3.0.0</version> | |||||
| <version>3.1.0</version> | |||||
| </parent> | </parent> | ||||
| <artifactId>weixin-java-miniapp</artifactId> | <artifactId>weixin-java-miniapp</artifactId> | ||||
| <name>Weixin Java Tools - MiniApp</name> | <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; | package cn.binarywang.wx.miniapp.api; | ||||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | 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.File; | ||||
| import java.io.InputStream; | 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.WxMaKefuMessage; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; | import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| /** | /** | ||||
| * <pre> | * <pre> | ||||
| @@ -1,7 +1,7 @@ | |||||
| package cn.binarywang.wx.miniapp.api; | package cn.binarywang.wx.miniapp.api; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; | 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; | import java.io.File; | ||||
| @@ -9,7 +9,7 @@ import java.io.File; | |||||
| * <pre> | * <pre> | ||||
| * 二维码相关操作接口. | * 二维码相关操作接口. | ||||
| * | * | ||||
| * 接口A(createWxCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。 | |||||
| * 接口A(createWxaCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。 | |||||
| * | * | ||||
| * 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html | * 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html | ||||
| * </pre> | * </pre> | ||||
| @@ -40,16 +40,17 @@ public interface WxMaQrcodeService { | |||||
| /** | /** | ||||
| * 接口A: 获取小程序码. | * 接口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: 获取小程序码(永久有效、数量暂无限制). | * 接口B: 获取小程序码(永久有效、数量暂无限制). | ||||
| @@ -59,14 +60,16 @@ public interface WxMaQrcodeService { | |||||
| * 使用如下代码可以获取到二维码中的 scene 字段的值。 | * 使用如下代码可以获取到二维码中的 scene 字段的值。 | ||||
| * 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode | * 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode | ||||
| * </pre> | * </pre> | ||||
| * | |||||
| * @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) | * @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) | ||||
| * @param page 必须是已经发布的小程序页面,例如 "pages/index/index" ,如果不填写这个字段,默认跳主页面 | * @param page 必须是已经发布的小程序页面,例如 "pages/index/index" ,如果不填写这个字段,默认跳主页面 | ||||
| * @param width 默认false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | * @param width 默认false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | ||||
| * @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | * @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | ||||
| * @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} | * @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.bean.WxMaJscode2SessionResult; | ||||
| import cn.binarywang.wx.miniapp.config.WxMaConfig; | 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.MediaUploadRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | import me.chanjar.weixin.common.util.http.RequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | import me.chanjar.weixin.common.util.http.RequestHttp; | ||||
| @@ -135,6 +135,27 @@ public interface WxMaService { | |||||
| */ | */ | ||||
| WxMaTemplateService getTemplateService(); | WxMaTemplateService getTemplateService(); | ||||
| /** | |||||
| * 数据分析相关查询服务 | |||||
| * | |||||
| * @return WxMaAnalysisService | |||||
| */ | |||||
| WxMaAnalysisService getAnalysisService(); | |||||
| /** | |||||
| * 返回代码操作相关的 API | |||||
| * | |||||
| * @return WxMaCodeService | |||||
| */ | |||||
| WxMaCodeService getCodeService(); | |||||
| /** | |||||
| * 小程序修改服务器地址、成员管理 API | |||||
| * | |||||
| * @return WxMaSettingService | |||||
| */ | |||||
| WxMaSettingService getSettingService(); | |||||
| /** | /** | ||||
| * 初始化http请求对象. | * 初始化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.WxMaTemplateLibraryGetResult; | ||||
| import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; | import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; | ||||
| import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult; | 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; | 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.WxMaJscode2SessionResult; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; | import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; | 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.WxMaMediaService; | ||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | 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.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.fs.FileUtils; | ||||
| import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | 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 cn.binarywang.wx.miniapp.constant.WxMaConstants; | ||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
| import com.google.gson.JsonParser; | 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> | * @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.WxMaCodeLineColor; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaQrcode; | import cn.binarywang.wx.miniapp.bean.WxMaQrcode; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaWxcode; | 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 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; | import java.io.File; | ||||
| @@ -33,42 +33,44 @@ public class WxMaQrcodeServiceImpl implements WxMaQrcodeService { | |||||
| } | } | ||||
| @Override | @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 wxMaWxcode = new WxMaWxcode(); | ||||
| wxMaWxcode.setPath(path); | wxMaWxcode.setPath(path); | ||||
| wxMaWxcode.setWidth(width); | wxMaWxcode.setWidth(width); | ||||
| wxMaWxcode.setAutoColor(autoColor); | wxMaWxcode.setAutoColor(autoColor); | ||||
| wxMaWxcode.setLineColor(lineColor); | wxMaWxcode.setLineColor(lineColor); | ||||
| wxMaWxcode.setHyaline(isHyaline); | |||||
| return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), | return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), | ||||
| GET_WXACODE_URL, wxMaWxcode); | GET_WXACODE_URL, wxMaWxcode); | ||||
| } | } | ||||
| @Override | @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 | @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 | @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 { | 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()), | return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), | ||||
| GET_WXACODE_UNLIMIT_URL, wxMaWxcodeLimit); | |||||
| GET_WXACODE_UNLIMIT_URL, wxaCodeUnlimit); | |||||
| } | } | ||||
| @Override | @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; | 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.WxMaMediaService; | ||||
| import cn.binarywang.wx.miniapp.api.WxMaMsgService; | import cn.binarywang.wx.miniapp.api.WxMaMsgService; | ||||
| import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; | import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; | ||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | 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.WxMaTemplateService; | ||||
| import cn.binarywang.wx.miniapp.api.WxMaUserService; | import cn.binarywang.wx.miniapp.api.WxMaUserService; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | ||||
| import cn.binarywang.wx.miniapp.config.WxMaConfig; | import cn.binarywang.wx.miniapp.config.WxMaConfig; | ||||
| import cn.binarywang.wx.miniapp.constant.WxMaConstants; | |||||
| import com.google.common.base.Joiner; | import com.google.common.base.Joiner; | ||||
| import me.chanjar.weixin.common.bean.WxAccessToken; | 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.crypto.SHA1; | ||||
| import me.chanjar.weixin.common.util.http.HttpType; | import me.chanjar.weixin.common.util.http.HttpType; | ||||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | 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.SimplePostRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | ||||
| import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | 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> | * @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 WxMaUserService userService = new WxMaUserServiceImpl(this); | ||||
| private WxMaQrcodeService qrCodeService = new WxMaQrcodeServiceImpl(this); | private WxMaQrcodeService qrCodeService = new WxMaQrcodeServiceImpl(this); | ||||
| private WxMaTemplateService templateService = new WxMaTemplateServiceImpl(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 retrySleepMillis = 1000; | ||||
| private int maxRetryTimes = 5; | private int maxRetryTimes = 5; | ||||
| @@ -207,7 +214,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||||
| throw new RuntimeException("微信服务端异常,超出重试次数"); | 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=")) { | if (uri.contains("access_token=")) { | ||||
| throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | ||||
| } | } | ||||
| @@ -217,16 +226,16 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||||
| try { | try { | ||||
| T result = executor.execute(uriWithAccessToken, data); | 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; | return result; | ||||
| } catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
| WxError error = e.getError(); | WxError error = e.getError(); | ||||
| /* | /* | ||||
| * 发生以下情况时尝试刷新access_token | * 发生以下情况时尝试刷新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 | // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | ||||
| this.getWxMaConfig().expireAccessToken(); | this.getWxMaConfig().expireAccessToken(); | ||||
| if (this.getWxMaConfig().autoRefreshToken()) { | if (this.getWxMaConfig().autoRefreshToken()) { | ||||
| @@ -235,12 +244,12 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||||
| } | } | ||||
| if (error.getErrorCode() != 0) { | 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); | throw new WxErrorException(error, e); | ||||
| } | } | ||||
| return null; | return null; | ||||
| } catch (IOException e) { | } 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); | throw new RuntimeException(e); | ||||
| } | } | ||||
| } | } | ||||
| @@ -290,4 +299,19 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||||
| public WxMaTemplateService getTemplateService() { | public WxMaTemplateService getTemplateService() { | ||||
| return this.templateService; | 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.WxMaTemplateLibraryGetResult; | ||||
| import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; | import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; | ||||
| import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult; | 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 me.chanjar.weixin.common.util.json.WxGsonBuilder; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||