+ * 微信类型枚举. + * Created by BinaryWang on 2018/5/14. + *+ * + * @author Binary Wang + */ +public enum WxType { + /** + * 企业微信 + */ + CP, + /** + * 微信公众号 + */ + MP, + /** + * 微信小程序 + */ + MiniApp, + /** + * 微信开放平台 + */ + Open, + /** + * 微信支付 + */ + Pay; +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java index e416323e02..a1e3c073c8 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java @@ -3,187 +3,352 @@ import java.util.HashMap; import java.util.Map; +/** + * 微信开发所使用到的常量类. + * + * @author Daniel Qian & binarywang + */ public class WxConsts { - - /////////////////////// - // 微信推送过来的消息的类型,和发送给微信xml格式消息的消息类型 - /////////////////////// - public static final String XML_MSG_TEXT = "text"; - public static final String XML_MSG_IMAGE = "image"; - public static final String XML_MSG_VOICE = "voice"; - public static final String XML_MSG_SHORTVIDEO = "shortvideo"; - public static final String XML_MSG_VIDEO = "video"; - public static final String XML_MSG_NEWS = "news"; - public static final String XML_MSG_MUSIC = "music"; - public static final String XML_MSG_LOCATION = "location"; - public static final String XML_MSG_LINK = "link"; - public static final String XML_MSG_EVENT = "event"; - public static final String XML_MSG_DEVICE_TEXT = "device_text"; - public static final String XML_MSG_DEVICE_EVENT = "device_event"; - public static final String XML_MSG_DEVICE_STATUS = "device_status"; - public static final String XML_MSG_HARDWARE = "hardware"; - public static final String XML_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; - - /////////////////////// - // 主动发送消息(即客服消息)的消息类型 - /////////////////////// - public static final String CUSTOM_MSG_TEXT = "text";//文本消息 - public static final String CUSTOM_MSG_IMAGE = "image";//图片消息 - public static final String CUSTOM_MSG_VOICE = "voice";//语音消息 - public static final String CUSTOM_MSG_VIDEO = "video";//视频消息 - public static final String CUSTOM_MSG_MUSIC = "music";//音乐消息 - public static final String CUSTOM_MSG_NEWS = "news";//图文消息(点击跳转到外链) - public static final String CUSTOM_MSG_MPNEWS = "mpnews";//图文消息(点击跳转到图文消息页面) - public static final String CUSTOM_MSG_FILE = "file";//发送文件(CP专用) - public static final String CUSTOM_MSG_TEXTCARD = "textcard";//文本卡片消息(CP专用) - public static final String CUSTOM_MSG_WXCARD = "wxcard";//卡券消息 - public static final String CUSTOM_MSG_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; - public static final String CUSTOM_MSG_SAFE_NO = "0"; - public static final String CUSTOM_MSG_SAFE_YES = "1"; - - /////////////////////// - // 群发消息的消息类型 - /////////////////////// - public static final String MASS_MSG_NEWS = "mpnews"; - public static final String MASS_MSG_TEXT = "text"; - public static final String MASS_MSG_VOICE = "voice"; - public static final String MASS_MSG_IMAGE = "image"; - public static final String MASS_MSG_VIDEO = "mpvideo"; - - /////////////////////// - // 群发消息后微信端推送给服务器的反馈消息 - /////////////////////// - public static final String MASS_ST_SUCCESS = "send success"; - public static final String MASS_ST_FAIL = "send fail"; - public static final String MASS_ST_10001 = "err(10001)"; - public static final String MASS_ST_20001 = "err(20001)"; - public static final String MASS_ST_20004 = "err(20004)"; - public static final String MASS_ST_20002 = "err(20002)"; - public static final String MASS_ST_20006 = "err(20006)"; - public static final String MASS_ST_20008 = "err(20008)"; - public static final String MASS_ST_20013 = "err(20013)"; - public static final String MASS_ST_22000 = "err(22000)"; - public static final String MASS_ST_21000 = "err(21000)"; - - /** - * 群发反馈消息代码所对应的文字描述 - */ - public static final Map
- * 消息重复检查器 + * 消息重复检查器. * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 *+ * + * @author Daniel Qian */ public interface WxMessageDuplicateChecker { /** + * 判断消息是否重复. *
+ * *
普通消息:关于重试的消息排重,推荐使用msgid排重。文档参考。
*事件消息:关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。文档参考
- *+ * *
- * 官方文档完全没有写,参照公众号的方式排重。 - *
+ *
官方文档完全没有写,参照公众号的方式排重。
*或者可以采取更简单的方式,如果有MsgId就用MsgId排重,如果没有就用FromUserName+CreateTime排重
* * @param messageId messageId需要根据上面讲的方式构造 diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateChecker.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateChecker.java index 1281e26012..c0f57c83c4 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateChecker.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateChecker.java @@ -6,46 +6,48 @@ /** *- * 默认消息重复检查器 + * 默认消息重复检查器. * 将每个消息id保存在内存里,每隔5秒清理已经过期的消息id,每个消息id的过期时间是15秒 *+ * + * @author Daniel Qian */ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChecker { /** - * 一个消息ID在内存的过期时间:15秒 + * 一个消息ID在内存的过期时间:15秒. */ private final Long timeToLive; /** - * 每隔多少周期检查消息ID是否过期:5秒 + * 每隔多少周期检查消息ID是否过期:5秒. */ private final Long clearPeriod; /** - * 消息id->消息时间戳的map + * 消息id->消息时间戳的map. */ private final ConcurrentHashMap
* 一个消息ID在内存的过期时间:15秒 * 每隔多少周期检查消息ID是否过期:5秒 **/ public WxMessageInMemoryDuplicateChecker() { - this.timeToLive = 15 * 1000l; - this.clearPeriod = 5 * 1000l; + this.timeToLive = 15 * 1000L; + this.clearPeriod = 5 * 1000L; } /** - * WxMsgIdInMemoryDuplicateChecker构造函数 + * 构造方法. * * @param timeToLive 一个消息ID在内存的过期时间:毫秒 * @param clearPeriod 每隔多少周期检查消息ID是否过期:毫秒 @@ -66,7 +68,8 @@ public void run() { while (true) { Thread.sleep(WxMessageInMemoryDuplicateChecker.this.clearPeriod); Long now = System.currentTimeMillis(); - for (Map.Entry
- * 菜单的响应动作类型: + * 菜单的响应动作类型. * view表示网页类型, * click表示点击类型, * miniprogram表示小程序类型 @@ -21,13 +30,13 @@ public class WxMenuButton implements Serializable { private String type; /** - * 菜单标题,不超过16个字节,子菜单不超过60个字节 + * 菜单标题,不超过16个字节,子菜单不超过60个字节. */ private String name; /** ** - * @author binarywang(Binary Wang) + * @author Binary Wang */ public class SHA1Test { @Test diff --git a/weixin-java-cp/pom.xml b/weixin-java-cp/pom.xml index 233a94ecc3..cba660670b 100644 --- a/weixin-java-cp/pom.xml +++ b/weixin-java-cp/pom.xml @@ -7,11 +7,11 @@- * 菜单KEY值,用于消息接口推送,不超过128字节 + * 菜单KEY值,用于消息接口推送,不超过128字节. * click等点击类型必须 **/ @@ -35,7 +44,8 @@ public class WxMenuButton implements Serializable { /** *- * 网页链接,用户点击菜单可打开链接,不超过1024字节。type为miniprogram时,不支持小程序的老版本客户端将打开本url。 + * 网页链接. + * 用户点击菜单可打开链接,不超过1024字节。type为miniprogram时,不支持小程序的老版本客户端将打开本url。 * view、miniprogram类型必须 **/ @@ -43,7 +53,7 @@ public class WxMenuButton implements Serializable { /** *- * 调用新增永久素材接口返回的合法media_id + * 调用新增永久素材接口返回的合法media_id. * media_id类型和view_limited类型必须 **/ @@ -52,7 +62,7 @@ public class WxMenuButton implements Serializable { /** *- * 小程序的appid + * 小程序的appid. * miniprogram类型必须 **/ @@ -61,7 +71,7 @@ public class WxMenuButton implements Serializable { /** *- * 小程序的页面路径 + * 小程序的页面路径. * miniprogram类型必须 **/ @@ -73,70 +83,7 @@ public class WxMenuButton implements Serializable { @Override public String toString() { - return ToStringUtils.toSimpleString(this); - } - - public String getType() { - return this.type; - } - - public void setType(String type) { - this.type = type; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getKey() { - return this.key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getUrl() { - return this.url; + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } - public void setUrl(String url) { - this.url = url; - } - - public ListgetSubButtons() { - return this.subButtons; - } - - public void setSubButtons(List subButtons) { - this.subButtons = subButtons; - } - - public String getMediaId() { - return this.mediaId; - } - - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - - public String getAppId() { - return appId; - } - - public void setAppId(String appId) { - this.appId = appId; - } - - public String getPagePath() { - return pagePath; - } - - public void setPagePath(String pagePath) { - this.pagePath = pagePath; - } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenuRule.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenuRule.java index e0182c9678..632279b92a 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenuRule.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenuRule.java @@ -1,12 +1,26 @@ package me.chanjar.weixin.common.bean.menu; -import me.chanjar.weixin.common.util.ToStringUtils; - import java.io.Serializable; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +/** + * menu rule. + * + * @author Daniel Qian + */ +@Data public class WxMenuRule implements Serializable { private static final long serialVersionUID = -4587181819499286670L; + /** + * 变态的微信接口,反序列化时这里反人类的使用和序列化时不一样的名字. + */ + @SerializedName(value = "tag_id", alternate = "group_id") private String tagId; private String sex; private String country; @@ -15,64 +29,8 @@ public class WxMenuRule implements Serializable { private String clientPlatformType; private String language; - public String getTagId() { - return this.tagId; - } - - public void setTagId(String tagId) { - this.tagId = tagId; - } - - public String getSex() { - return this.sex; - } - - public void setSex(String sex) { - this.sex = sex; - } - - public String getCountry() { - return this.country; - } - - public void setCountry(String country) { - this.country = country; - } - - public String getProvince() { - return this.province; - } - - public void setProvince(String province) { - this.province = province; - } - - public String getCity() { - return this.city; - } - - public void setCity(String city) { - this.city = city; - } - - public String getClientPlatformType() { - return this.clientPlatformType; - } - - public void setClientPlatformType(String clientPlatformType) { - this.clientPlatformType = clientPlatformType; - } - - public String getLanguage() { - return this.language; - } - - public void setLanguage(String language) { - this.language = language; - } - @Override public String toString() { - return ToStringUtils.toSimpleString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxError.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxError.java deleted file mode 100644 index 46c0ae89be..0000000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxError.java +++ /dev/null @@ -1,84 +0,0 @@ -package me.chanjar.weixin.common.bean.result; - -import me.chanjar.weixin.common.util.json.WxGsonBuilder; - -import java.io.Serializable; - -/** - * 微信错误码说明,请阅读: 全局返回码说明 - * - * @author Daniel Qian - */ -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); - } - - public static Builder newBuilder() { - return new Builder(); - } - - public int getErrorCode() { - return this.errorCode; - } - - public void setErrorCode(int errorCode) { - this.errorCode = errorCode; - } - - public String getErrorMsg() { - return this.errorMsg; - } - - public void setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - } - - public String getJson() { - return this.json; - } - - public void setJson(String json) { - this.json = json; - } - - @Override - public String toString() { - if (this.json != null) { - return this.json; - } - return "错误: Code=" + this.errorCode + ", Msg=" + this.errorMsg; - } - - public static class Builder { - private int errorCode; - private String errorMsg; - - public Builder setErrorCode(int errorCode) { - this.errorCode = errorCode; - return this; - } - - public Builder setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - return this; - } - - public WxError build() { - WxError wxError = new WxError(); - wxError.setErrorCode(this.errorCode); - wxError.setErrorMsg(this.errorMsg); - return wxError; - } - - } -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMediaUploadResult.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMediaUploadResult.java index 706de712c7..d6ffd50c51 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMediaUploadResult.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMediaUploadResult.java @@ -1,14 +1,22 @@ package me.chanjar.weixin.common.bean.result; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.Serializable; + import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import java.io.Serializable; +import lombok.Data; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +/** + * + * @author Daniel Qian + */ +@Data public class WxMediaUploadResult implements Serializable { private static final long serialVersionUID = 330834334738622341L; + private String url; private String type; private String mediaId; private String thumbMediaId; @@ -18,38 +26,6 @@ public static WxMediaUploadResult fromJson(String json) { return WxGsonBuilder.create().fromJson(json, WxMediaUploadResult.class); } - public String getType() { - return this.type; - } - - public void setType(String type) { - this.type = type; - } - - public String getMediaId() { - return this.mediaId; - } - - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - - public long getCreatedAt() { - return this.createdAt; - } - - public void setCreatedAt(long createdAt) { - this.createdAt = createdAt; - } - - public String getThumbMediaId() { - return this.thumbMediaId; - } - - public void setThumbMediaId(String thumbMediaId) { - this.thumbMediaId = thumbMediaId; - } - @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java new file mode 100644 index 0000000000..0ae580620a --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java @@ -0,0 +1,806 @@ +package me.chanjar.weixin.common.error; + +import lombok.Getter; + +/** + * + * 企业微信全局错误码. + * 参考文档:企业微信全局错误码 + * Created by Binary Wang on 2018/5/13. + *+ * + * @author Binary Wang + */ +@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; + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java new file mode 100644 index 0000000000..fc9b624fa3 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java @@ -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; + +/** + * 微信错误码. + * 请阅读: + * 公众平台:全局返回码说明 + * 企业微信:全局错误码 + * + * @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; + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/exception/WxErrorException.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxErrorException.java similarity index 81% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/exception/WxErrorException.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxErrorException.java index 4038e60185..6e9a2c538d 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/exception/WxErrorException.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxErrorException.java @@ -1,9 +1,9 @@ -package me.chanjar.weixin.common.exception; - -import me.chanjar.weixin.common.bean.result.WxError; +package me.chanjar.weixin.common.error; +/** + * @author Daniel Qian + */ public class WxErrorException extends Exception { - private static final long serialVersionUID = -6357149550353160810L; private WxError error; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMpErrorMsgEnum.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMpErrorMsgEnum.java new file mode 100644 index 0000000000..3882252b72 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMpErrorMsgEnum.java @@ -0,0 +1,654 @@ +package me.chanjar.weixin.common.error; + +import lombok.Getter; + +/** + *+ * 微信公众平台全局返回码. + * 参考文档:公众平台全局返回码 + * Created by Binary Wang on 2018/5/13. + *+ * + * @author Binary Wang + */ +@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; + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java index f30a0ae0d0..98d45e31d4 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,9 +23,6 @@ * * @author Craig R. McClanahan */ - public class Constants { - - public static final String Package = "me.chanjar.weixin.common.session"; - + public static final String PACKAGE = "me.chanjar.weixin.common.session"; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSession.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSession.java index 77d4d28291..05cb41363f 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSession.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSession.java @@ -1,5 +1,9 @@ package me.chanjar.weixin.common.session; +/** + * + * @author Daniel Qian + */ public interface InternalSession { /** diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSessionManager.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSessionManager.java index a92e107154..e3d9ab8351 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSessionManager.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSessionManager.java @@ -1,5 +1,8 @@ package me.chanjar.weixin.common.session; +/** + * @author Daniel Qian + */ public interface InternalSessionManager { /** diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java index f9d61707e3..3c4ec20c8d 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java @@ -1,23 +1,29 @@ package me.chanjar.weixin.common.session; -import me.chanjar.weixin.common.util.res.StringManager; - -import java.util.*; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import me.chanjar.weixin.common.util.res.StringManager; + +/** + * @author Daniel Qian + */ public class StandardSession implements WxSession, InternalSession { /** * The string manager for this package. */ - protected static final StringManager sm = StringManager.getManager(Constants.Package); + protected static final StringManager SM = StringManager.getManager(Constants.PACKAGE); /** * Type array. */ private static final String[] EMPTY_ARRAY = new String[0]; - // ------------------------------ WxSession protected Mapattributes = new ConcurrentHashMap<>(); /** * The session identifier of this Session. @@ -73,7 +79,7 @@ public Object getAttribute(String name) { if (!isValidInternal()) { throw new IllegalStateException - (sm.getString("sessionImpl.getAttribute.ise")); + (SM.getString("sessionImpl.getAttribute.ise")); } if (name == null) { @@ -86,7 +92,7 @@ public Object getAttribute(String name) { @Override public Enumeration getAttributeNames() { if (!isValidInternal()) { - throw new IllegalStateException(sm.getString("sessionImpl.getAttributeNames.ise")); + throw new IllegalStateException(SM.getString("sessionImpl.getAttributeNames.ise")); } Set names = new HashSet<>(); @@ -98,7 +104,7 @@ public Enumeration getAttributeNames() { public void setAttribute(String name, Object value) { // Name cannot be null if (name == null) { - throw new IllegalArgumentException(sm.getString("sessionImpl.setAttribute.namenull")); + throw new IllegalArgumentException(SM.getString("sessionImpl.setAttribute.namenull")); } // Null value is the same as removeAttribute() @@ -109,7 +115,7 @@ public void setAttribute(String name, Object value) { // Validate our current state if (!isValidInternal()) { - throw new IllegalStateException(sm.getString("sessionImpl.setAttribute.ise", getIdInternal())); + throw new IllegalStateException(SM.getString("sessionImpl.setAttribute.ise", getIdInternal())); } this.attributes.put(name, value); @@ -123,8 +129,9 @@ public void removeAttribute(String name) { @Override public void invalidate() { - if (!isValidInternal()) - throw new IllegalStateException(sm.getString("sessionImpl.invalidate.ise")); + if (!isValidInternal()) { + throw new IllegalStateException(SM.getString("sessionImpl.invalidate.ise")); + } // Cause this session to expire expire(); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionFacade.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionFacade.java index e449308961..aa9f877136 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionFacade.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionFacade.java @@ -2,6 +2,9 @@ import java.util.Enumeration; +/** + * @author Daniel Qian + */ public class StandardSessionFacade implements WxSession { /** diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java index f20fd5c2a3..bf2e735872 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java @@ -1,20 +1,22 @@ package me.chanjar.weixin.common.session; -import me.chanjar.weixin.common.util.res.StringManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import me.chanjar.weixin.common.util.res.StringManager; + /** - * 基于内存的session manager + * 基于内存的session manager. + * + * @author Daniel Qian */ public class StandardSessionManager implements WxSessionManager, InternalSessionManager { - protected static final StringManager sm = - StringManager.getManager(Constants.Package); + protected static final StringManager SM = StringManager.getManager(Constants.PACKAGE); /** * The descriptive name of this Manager implementation (for logging). */ @@ -82,7 +84,7 @@ public WxSession getSession(String sessionId) { public WxSession getSession(String sessionId, boolean create) { if (sessionId == null) { throw new IllegalStateException - (sm.getString("sessionManagerImpl.getSession.ise")); + (SM.getString("sessionManagerImpl.getSession.ise")); } InternalSession session = findSession(sessionId); @@ -124,25 +126,24 @@ public void remove(InternalSession session, boolean update) { @Override public InternalSession findSession(String id) { - - if (id == null) + if (id == null) { return (null); + } return this.sessions.get(id); - } @Override public InternalSession createSession(String sessionId) { if (sessionId == null) { throw new IllegalStateException - (sm.getString("sessionManagerImpl.createSession.ise")); + (SM.getString("sessionManagerImpl.createSession.ise")); } if ((this.maxActiveSessions >= 0) && (getActiveSessions() >= this.maxActiveSessions)) { this.rejectedSessions++; throw new TooManyActiveSessionsException( - sm.getString("sessionManagerImpl.createSession.tmase"), + SM.getString("sessionManagerImpl.createSession.tmase"), this.maxActiveSessions); } @@ -192,7 +193,7 @@ public void run() { while (true) { try { // 每秒清理一次 - Thread.sleep(StandardSessionManager.this.backgroundProcessorDelay * 1000l); + Thread.sleep(StandardSessionManager.this.backgroundProcessorDelay * 1000L); backgroundProcess(); } catch (InterruptedException e) { StandardSessionManager.this.log.error("SessionManagerImpl.backgroundProcess error", e); @@ -230,8 +231,9 @@ public InternalSession[] findSessions() { @Override public void backgroundProcess() { this.count = (this.count + 1) % this.processExpiresFrequency; - if (this.count == 0) + if (this.count == 0) { processExpires(); + } } /** @@ -243,16 +245,18 @@ public void processExpires() { InternalSession sessions[] = findSessions(); int expireHere = 0; - if (this.log.isDebugEnabled()) + if (this.log.isDebugEnabled()) { this.log.debug("Start expire sessions {} at {} sessioncount {}", getName(), timeNow, sessions.length); - for (int i = 0; i < sessions.length; i++) { - if (sessions[i] != null && !sessions[i].isValid()) { + } + for (InternalSession session : sessions) { + if (session != null && !session.isValid()) { expireHere++; } } long timeEnd = System.currentTimeMillis(); - if (this.log.isDebugEnabled()) + if (this.log.isDebugEnabled()) { this.log.debug("End expire sessions {} processingTime {} expired sessions: {}", getName(), timeEnd - timeNow, expireHere); + } this.processingTime += (timeEnd - timeNow); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/TooManyActiveSessionsException.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/TooManyActiveSessionsException.java index fa1b45fafe..114dd1c4ed 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/TooManyActiveSessionsException.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/TooManyActiveSessionsException.java @@ -19,6 +19,8 @@ /** * An exception that indicates the maximum number of active sessions has been * reached and the server is refusing to create any new sessions. + * + * @author Daniel Qian */ public class TooManyActiveSessionsException extends IllegalStateException { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSession.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSession.java index 25bed2d274..3aa79f9ad2 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSession.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSession.java @@ -2,6 +2,9 @@ import java.util.Enumeration; +/** + * @author Daniel Qian + */ public interface WxSession { Object getAttribute(String name); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSessionManager.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSessionManager.java index c966ddab28..789e272875 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSessionManager.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSessionManager.java @@ -1,5 +1,8 @@ package me.chanjar.weixin.common.session; +/** + * @author Daniel Qian + */ public interface WxSessionManager { /** diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java index 630821e954..4b7f9be6a7 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java @@ -1,11 +1,9 @@ package me.chanjar.weixin.common.util; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.annotation.Required; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,14 +12,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; /** * * bean操作的一些工具类 * Created by Binary Wang on 2016-10-21. - * @author binarywang(Binary Wang) *+ * + * @author binarywang(Binary Wang) */ public class BeanUtils { private static Logger log = LoggerFactory.getLogger(BeanUtils.class); @@ -30,7 +28,6 @@ public class BeanUtils { * 检查bean里标记为@Required的field是否为空,为空则抛异常 * * @param bean 要检查的bean对象 - * @throws WxErrorException */ public static void checkRequiredFields(Object bean) throws WxErrorException { ListrequiredFields = Lists.newArrayList(); @@ -42,55 +39,28 @@ public static void checkRequiredFields(Object bean) throws WxErrorException { boolean isAccessible = field.isAccessible(); field.setAccessible(true); if (field.isAnnotationPresent(Required.class)) { - if (field.get(bean) == null || (field.get(bean) instanceof String && StringUtils.isBlank(field.get(bean).toString()))) { - //两种情况,一种是值为null,另外一种情况是类型为字符串,但是字符串内容为空的,都认为是没有提供值 + // 两种情况,一种是值为null, + // 另外一种情况是类型为字符串,但是字符串内容为空的,都认为是没有提供值 + boolean isRequiredMissing = field.get(bean) == null + || (field.get(bean) instanceof String + && StringUtils.isBlank(field.get(bean).toString()) + ); + if (isRequiredMissing) { requiredFields.add(field.getName()); } } field.setAccessible(isAccessible); } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } } if (!requiredFields.isEmpty()) { String msg = "必填字段 " + requiredFields + " 必须提供值"; log.debug(msg); - throw new WxErrorException(WxError.newBuilder().setErrorMsg(msg).build()); + throw new WxErrorException(WxError.builder().errorMsg(msg).build()); } } - /** - * 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象 - * - * @param bean 包含@XStreamAlias的xml bean对象 - * @return map对象 - */ - public static Map xmlBean2Map(Object bean) { - Map result = Maps.newHashMap(); - List fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields())); - fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields())); - for (Field field : fields) { - try { - boolean isAccessible = field.isAccessible(); - field.setAccessible(true); - if (field.get(bean) == null) { - field.setAccessible(isAccessible); - continue; - } - - if (field.isAnnotationPresent(XStreamAlias.class)) { - result.put(field.getAnnotation(XStreamAlias.class).value(), field.get(bean).toString()); - } - - field.setAccessible(isAccessible); - } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) { - e.printStackTrace(); - } - - } - - return result; - } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/DataUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/DataUtils.java new file mode 100644 index 0000000000..983d9a668f --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/DataUtils.java @@ -0,0 +1,24 @@ +package me.chanjar.weixin.common.util; + +import org.apache.commons.lang3.StringUtils; + +/** + * + * 数据处理工具类 + * Created by BinaryWang on 2018/5/8. + *+ * + * @author Binary Wang + */ +public class DataUtils { + /** + * 将数据中包含的secret字符使用星号替换,防止日志打印时被输出 + */ + public staticE 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; + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/LogExceptionHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/LogExceptionHandler.java index 7ad976abd8..7487a0fe29 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/LogExceptionHandler.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/LogExceptionHandler.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.common.util; import me.chanjar.weixin.common.api.WxErrorExceptionHandler; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java new file mode 100644 index 0000000000..9ea33b123e --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java @@ -0,0 +1,40 @@ +package me.chanjar.weixin.common.util; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Hex; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +/** + * + * 签名工具类 + * Created by BinaryWang on 2018/7/11. + *+ * + * @author Binary Wang + */ +@Slf4j +public class SignUtils { + /** + * HmacSHA256 签名算法 + * + * @param message 签名数据 + * @param key 签名密钥 + */ + public static String createHmacSha256Sign(String message, String key) { + try { + Mac sha256 = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + sha256.init(secretKeySpec); + byte[] bytes = sha256.doFinal(message.getBytes()); + return Hex.encodeHexString(bytes).toUpperCase(); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + SignUtils.log.error(e.getMessage(), e); + } + + return null; + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/ToStringUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/ToStringUtils.java deleted file mode 100644 index 333e484a8f..0000000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/ToStringUtils.java +++ /dev/null @@ -1,63 +0,0 @@ -package me.chanjar.weixin.common.util; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - *- * 自定义的ToString方法,用于产生去掉空值属性的字符串 - * Created by Binary Wang on 2016-10-27. - * @author binarywang(Binary Wang) - *- */ -public class ToStringUtils { - public static final ToStringStyle THE_STYLE = new SimpleMultiLineToStringStyle(); - - /** - * 用于产生去掉空值属性并以换行符分割各属性键值的toString字符串 - * - * @param obj - */ - public static String toSimpleString(Object obj) { - String toStringResult = ToStringBuilder.reflectionToString(obj, THE_STYLE); - String[] split = toStringResult.split(SimpleMultiLineToStringStyle.LINE_SEPARATOR); - StringBuilder result = new StringBuilder(); - for (String string : split) { - if (string.endsWith(SimpleMultiLineToStringStyle.NULL_TEXT)) { - continue; - } - - result.append(string + SimpleMultiLineToStringStyle.LINE_SEPARATOR); - } - - if (result.length() == 0) { - return ""; - } - - //如果没有非空的属性,就输出- if (StringUtils.countMatches(result, SimpleMultiLineToStringStyle.LINE_SEPARATOR) == 2) { - return result.toString().split(SimpleMultiLineToStringStyle.LINE_SEPARATOR)[0] - + " ]"; - } - - return result.deleteCharAt(result.length() - 1).toString(); - } - - private static class SimpleMultiLineToStringStyle extends ToStringStyle { - private static final long serialVersionUID = 4645306494220335355L; - private static final String LINE_SEPARATOR = "\n"; - private static final String NULL_TEXT = " "; - - public SimpleMultiLineToStringStyle() { - super(); - this.setContentStart("["); - this.setFieldSeparator(LINE_SEPARATOR + " "); - this.setFieldSeparatorAtStart(true); - this.setContentEnd(LINE_SEPARATOR + "]"); - this.setNullText(NULL_TEXT); - this.setUseShortClassName(true); - this.setUseIdentityHashCode(false); - } - } -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/ByteGroup.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/ByteGroup.java index b12ec65555..bff08d680d 100755 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/ByteGroup.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/ByteGroup.java @@ -1,26 +1,26 @@ -package me.chanjar.weixin.common.util.crypto; - -import java.util.ArrayList; - -public class ByteGroup { - ArrayList byteContainer = new ArrayList<>(); - - public byte[] toBytes() { - byte[] bytes = new byte[this.byteContainer.size()]; - for (int i = 0; i < this.byteContainer.size(); i++) { - bytes[i] = this.byteContainer.get(i); - } - return bytes; - } - - public ByteGroup addBytes(byte[] bytes) { - for (byte b : bytes) { - this.byteContainer.add(b); - } - return this; - } - - public int size() { - return this.byteContainer.size(); - } -} +package me.chanjar.weixin.common.util.crypto; + +import java.util.ArrayList; + +public class ByteGroup { + ArrayList byteContainer = new ArrayList<>(); + + public byte[] toBytes() { + byte[] bytes = new byte[this.byteContainer.size()]; + for (int i = 0; i < this.byteContainer.size(); i++) { + bytes[i] = this.byteContainer.get(i); + } + return bytes; + } + + public ByteGroup addBytes(byte[] bytes) { + for (byte b : bytes) { + this.byteContainer.add(b); + } + return this; + } + + public int size() { + return this.byteContainer.size(); + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/PKCS7Encoder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/PKCS7Encoder.java index 145896a577..8ce94cbac0 100755 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/PKCS7Encoder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/PKCS7Encoder.java @@ -1,68 +1,68 @@ -/** - * 对公众平台发送给公众账号的消息加解密示例代码. - * - * @copyright Copyright (c) 1998-2014 Tencent Inc. - */ - -// ------------------------------------------------------------------------ - -package me.chanjar.weixin.common.util.crypto; - -import java.nio.charset.Charset; -import java.util.Arrays; - -/** - * 提供基于PKCS7算法的加解 - */ -public class PKCS7Encoder { - - private static final Charset CHARSET = Charset.forName("utf-8"); - private static final int BLOCK_SIZE = 32; - - /** - * 获得对明文进行补位填充的字节. - * - * @param count 需要进行填充补位操作的明文字节个数 - * @return 补齐用的字节数组 - */ - public static byte[] encode(int count) { - // 计算需要填充的位数 - int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE); - if (amountToPad == 0) { - amountToPad = BLOCK_SIZE; - } - // 获得补位所用的字符 - char padChr = chr(amountToPad); - String tmp = new String(); - for (int index = 0; index < amountToPad; index++) { - tmp += padChr; - } - return tmp.getBytes(CHARSET); - } - - /** - * 删除解密后明文的补位字符 - * - * @param decrypted 解密后的明文 - * @return 删除补位字符后的明文 - */ - public static byte[] decode(byte[] decrypted) { - int pad = decrypted[decrypted.length - 1]; - if (pad < 1 || pad > 32) { - pad = 0; - } - return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); - } - - /** - * 将数字转化成ASCII码对应的字符,用于对明文进行补码 - * - * @param a 需要转化的数字 - * @return 转化得到的字符 - */ - public static char chr(int a) { - byte target = (byte) (a & 0xFF); - return (char) target; - } - -} +/** + * 对公众平台发送给公众账号的消息加解密示例代码. + * + * @copyright Copyright (c) 1998-2014 Tencent Inc. + */ + +// ------------------------------------------------------------------------ + +package me.chanjar.weixin.common.util.crypto; + +import java.nio.charset.Charset; +import java.util.Arrays; + +/** + * 提供基于PKCS7算法的加解 + */ +public class PKCS7Encoder { + + private static final Charset CHARSET = Charset.forName("utf-8"); + private static final int BLOCK_SIZE = 32; + + /** + * 获得对明文进行补位填充的字节. + * + * @param count 需要进行填充补位操作的明文字节个数 + * @return 补齐用的字节数组 + */ + public static byte[] encode(int count) { + // 计算需要填充的位数 + int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE); + if (amountToPad == 0) { + amountToPad = BLOCK_SIZE; + } + // 获得补位所用的字符 + char padChr = chr(amountToPad); + String tmp = new String(); + for (int index = 0; index < amountToPad; index++) { + tmp += padChr; + } + return tmp.getBytes(CHARSET); + } + + /** + * 删除解密后明文的补位字符 + * + * @param decrypted 解密后的明文 + * @return 删除补位字符后的明文 + */ + public static byte[] decode(byte[] decrypted) { + int pad = decrypted[decrypted.length - 1]; + if (pad < 1 || pad > 32) { + pad = 0; + } + return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); + } + + /** + * 将数字转化成ASCII码对应的字符,用于对明文进行补码 + * + * @param a 需要转化的数字 + * @return 转化得到的字符 + */ + public static char chr(int a) { + byte target = (byte) (a & 0xFF); + return (char) target; + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java index c91e8ac089..f16d3bd3ea 100755 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java @@ -28,10 +28,10 @@ */ public class WxCryptUtil { - private static final Base64 base64 = new Base64(); + private static final Base64 BASE64 = new Base64(); private static final Charset CHARSET = StandardCharsets.UTF_8; - private static final ThreadLocal builderLocal = new ThreadLocal () { + private static final ThreadLocal BUILDER_LOCAL = new ThreadLocal () { @Override protected DocumentBuilder initialValue() { try { @@ -65,7 +65,7 @@ public WxCryptUtil(String token, String encodingAesKey, static String extractEncryptPart(String xml) { try { - DocumentBuilder db = builderLocal.get(); + DocumentBuilder db = BUILDER_LOCAL.get(); Document document = db.parse(new InputSource(new StringReader(xml))); Element root = document.getDocumentElement(); @@ -192,7 +192,7 @@ protected String encrypt(String randomStr, String plainText) { byte[] encrypted = cipher.doFinal(unencrypted); // 使用BASE64对加密后的字符串进行编码 - return base64.encodeToString(encrypted); + return BASE64.encodeToString(encrypted); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java index df031b3371..1b051a4718 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java @@ -1,52 +1,37 @@ package me.chanjar.weixin.common.util.fs; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; public class FileUtils { - /** - * 创建临时文件 + * 创建临时文件. * - * @param inputStream + * @param inputStream 输入文件流 * @param name 文件名 * @param ext 扩展名 * @param tmpDirFile 临时文件夹目录 */ public static File createTmpFile(InputStream inputStream, String name, String ext, File tmpDirFile) throws IOException { - File tmpFile; - if (tmpDirFile == null) { - tmpFile = File.createTempFile(name, '.' + ext); - } else { - tmpFile = File.createTempFile(name, '.' + ext, tmpDirFile); - } - - tmpFile.deleteOnExit(); - - try (FileOutputStream fos = new FileOutputStream(tmpFile)) { - int read = 0; - byte[] bytes = new byte[1024 * 100]; - while ((read = inputStream.read(bytes)) != -1) { - fos.write(bytes, 0, read); - } + File resultFile = File.createTempFile(name, '.' + ext, tmpDirFile); - fos.flush(); - return tmpFile; - } + resultFile.deleteOnExit(); + org.apache.commons.io.FileUtils.copyToFile(inputStream, resultFile); + return resultFile; } /** - * 创建临时文件 + * 创建临时文件. * - * @param inputStream + * @param inputStream 输入文件流 * @param name 文件名 * @param ext 扩展名 */ public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException { - return createTmpFile(inputStream, name, ext, null); + return createTmpFile(inputStream, name, ext, Files.createTempDirectory("weixin-java-tools-temp").toFile()); } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/BaseMediaDownloadRequestExecutor.java similarity index 85% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/BaseMediaDownloadRequestExecutor.java index d948859748..990e162008 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/BaseMediaDownloadRequestExecutor.java @@ -12,11 +12,11 @@ * * @author Daniel Qian */ -public abstract class MediaDownloadRequestExecutor implements RequestExecutor { - +public abstract class BaseMediaDownloadRequestExecutor implements RequestExecutor { protected RequestHttp requestHttp; protected File tmpDirFile; - public MediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + + public BaseMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { this.requestHttp = requestHttp; this.tmpDirFile = tmpDirFile; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java index a75aa963e0..ceaeffbd1e 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java @@ -1,8 +1,8 @@ package me.chanjar.weixin.common.util.http; import jodd.http.HttpResponse; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import okhttp3.Response; import org.apache.http.Header; import org.apache.http.client.methods.CloseableHttpResponse; @@ -19,6 +19,8 @@ * @author Binary Wang */ public class HttpResponseProxy { + private static final Pattern PATTERN = Pattern.compile(".*filename=\"(.*)\""); + private CloseableHttpResponse apacheHttpResponse; private HttpResponse joddHttpResponse; private Response okHttpResponse; @@ -56,7 +58,7 @@ public String getFileName() throws WxErrorException { private String getFileName(CloseableHttpResponse response) throws WxErrorException { Header[] contentDispositionHeader = response.getHeaders("Content-disposition"); if (contentDispositionHeader == null || contentDispositionHeader.length == 0) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + throw new WxErrorException(WxError.builder().errorMsg("无法获取到文件名").build()); } return this.extractFileNameFromContentString(contentDispositionHeader[0].getValue()); @@ -74,15 +76,15 @@ private String getFileName(Response response) throws WxErrorException { private String extractFileNameFromContentString(String content) throws WxErrorException { if (content == null || content.length() == 0) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + throw new WxErrorException(WxError.builder().errorMsg("无法获取到文件名").build()); } - Pattern p = Pattern.compile(".*filename=\"(.*)\""); - Matcher m = p.matcher(content); + Matcher m = PATTERN.matcher(content); if (m.matches()) { return m.group(1); } - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + + throw new WxErrorException(WxError.builder().errorMsg("无法获取到文件名").build()); } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java index c692eb9100..eff5907f7a 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java @@ -4,5 +4,16 @@ * Created by ecoolper on 2017/4/28. */ public enum HttpType { - JODD_HTTP, APACHE_HTTP, OK_HTTP; + /** + * jodd-http. + */ + JODD_HTTP, + /** + * apache httpclient. + */ + APACHE_HTTP, + /** + * okhttp. + */ + OK_HTTP } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java index 583db4f5ae..a5a9423fd0 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java @@ -1,6 +1,6 @@ package me.chanjar.weixin.common.util.http; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import java.io.IOException; @@ -9,51 +9,13 @@ * * @param 返回值类型 * @param 请求参数类型 + * @author Daniel Qian */ public interface RequestExecutor { /** * @param uri uri * @param data 数据 - * @throws WxErrorException - * @throws IOException */ T execute(String uri, E data) throws WxErrorException, IOException; - - /** - * apache-http实现方式 - * @param httpclient - * @param httpProxy - * @param uri - * @param data - * @return - * @throws WxErrorException - * @throws IOException - *//* - T executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, E data) throws WxErrorException, IOException; - - *//** - * jodd-http实现方式 - * @param provider - * @param proxyInfo - * @param uri - * @param data - * @return - * @throws WxErrorException - * @throws IOException - *//* - T executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, E data) throws WxErrorException, IOException; - - - *//** okhttp实现方式 - * @param pool - * @param proxyInfo - * @param uri - * @param data - * @return - * @throws WxErrorException - * @throws IOException - *//* - T executeOkhttp(ConnectionPool pool, final OkHttpProxyInfo proxyInfo, String uri, E data) throws WxErrorException, IOException; -*/ } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java index 939b624785..fcd56c48a7 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java @@ -4,51 +4,41 @@ import org.apache.http.impl.client.CloseableHttpClient; /** - * httpclient build interface + * httpclient build interface. * * @author kakotor */ public interface ApacheHttpClientBuilder { /** - * 构建httpclient实例 + * 构建httpclient实例. * * @return new instance of CloseableHttpClient */ CloseableHttpClient build(); /** - * 代理服务器地址 - * - * @param httpProxyHost + * 代理服务器地址. */ ApacheHttpClientBuilder httpProxyHost(String httpProxyHost); /** - * 代理服务器端口 - * - * @param httpProxyPort + * 代理服务器端口. */ ApacheHttpClientBuilder httpProxyPort(int httpProxyPort); /** - * 代理服务器用户名 - * - * @param httpProxyUsername + * 代理服务器用户名. */ ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername); /** - * 代理服务器密码 - * - * @param httpProxyPassword + * 代理服务器密码. */ ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword); /** - * ssl连接socket工厂 - * - * @param sslConnectionSocketFactory + * ssl连接socket工厂. */ ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientSimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientSimpleGetRequestExecutor.java index e47216e6cd..658ea4afd0 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientSimpleGetRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientSimpleGetRequestExecutor.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.common.util.http.apache; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; import org.apache.http.HttpHost; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpDnsClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpDnsClientBuilder.java index d3e5a1c167..033add1aa0 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpDnsClientBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpDnsClientBuilder.java @@ -1,6 +1,7 @@ package me.chanjar.weixin.common.util.http.apache; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpHost; import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -29,9 +30,8 @@ import java.util.concurrent.atomic.AtomicBoolean; /** - * httpclient 连接管理器 自带DNS解析 - * - * 大部分代码拷贝自:DefaultApacheHttpClientBuilder + * httpclient 连接管理器 自带DNS解析. + *
大部分代码拷贝自:DefaultApacheHttpClientBuilder
* * @author Andy.Huo */ @@ -64,7 +64,7 @@ public boolean retryRequest(IOException exception, int executionCount, HttpConte private String httpProxyPassword; /** - * 闲置连接监控线程 + * 闲置连接监控线程. */ private IdleConnectionMonitorThread idleConnectionMonitorThread; private HttpClientBuilder httpClientBuilder; @@ -162,7 +162,7 @@ public void setCheckWaitTime(int checkWaitTime) { } /** - * 每路的最大链接数,默认10 + * 每路的最大链接数,默认10. * * @param maxConnPerHost 每路的最大链接数,默认10 */ @@ -171,7 +171,7 @@ public void setMaxConnPerHost(int maxConnPerHost) { } /** - * 最大总连接数,默认50 + * 最大总连接数,默认50. * * @param maxTotalConn 最大总连接数,默认50 */ @@ -180,7 +180,7 @@ public void setMaxTotalConn(int maxTotalConn) { } /** - * 自定义httpclient的User Agent + * 自定义httpclient的User Agent. * * @param userAgent User Agent */ @@ -196,9 +196,12 @@ private synchronized void prepare() { if (prepared.get()) { return; } - Registryregistry = RegistryBuilder. create() - .register("http", this.plainConnectionSocketFactory).register("https", this.sslConnectionSocketFactory) - .build(); + + Registry registry = + RegistryBuilder. create() + .register("http", this.plainConnectionSocketFactory) + .register("https", this.sslConnectionSocketFactory) + .build(); @SuppressWarnings("resource") PoolingHttpClientConnectionManager connectionManager; @@ -219,8 +222,8 @@ private synchronized void prepare() { connectionManager .setDefaultSocketConfig(SocketConfig.copy(SocketConfig.DEFAULT).setSoTimeout(this.soTimeout).build()); - this.idleConnectionMonitorThread = new IdleConnectionMonitorThread(connectionManager, this.idleConnTimeout, - this.checkWaitTime); + this.idleConnectionMonitorThread = new IdleConnectionMonitorThread( + connectionManager, this.idleConnTimeout, this.checkWaitTime); this.idleConnectionMonitorThread.setDaemon(true); this.idleConnectionMonitorThread.start(); @@ -237,6 +240,7 @@ private synchronized void prepare() { provider.setCredentials(new AuthScope(this.httpProxyHost, this.httpProxyPort), new UsernamePasswordCredentials(this.httpProxyUsername, this.httpProxyPassword)); this.httpClientBuilder.setDefaultCredentialsProvider(provider); + this.httpClientBuilder.setProxy(new HttpHost(this.httpProxyHost, this.httpProxyPort)); } if (StringUtils.isNotBlank(this.userAgent)) { @@ -267,8 +271,10 @@ public static class IdleConnectionMonitorThread extends Thread { private final int checkWaitTime; private volatile boolean shutdown; - public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr, int idleConnTimeout, - int checkWaitTime) { + /** + * 构造方法. + */ + public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr, int idleConnTimeout, int checkWaitTime) { super("IdleConnectionMonitorThread"); this.connMgr = connMgr; this.idleConnTimeout = idleConnTimeout; @@ -289,12 +295,18 @@ public void run() { } } + /** + * 触发. + */ public void trigger() { synchronized (this) { notifyAll(); } } + /** + * 关闭. + */ public void shutdown() { this.shutdown = true; synchronized (this) { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java index 0a5a504873..2ce8750822 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java @@ -1,11 +1,9 @@ package me.chanjar.weixin.common.util.http.apache; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.HttpResponseProxy; -import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; -import me.chanjar.weixin.common.util.http.RequestHttp; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; @@ -16,14 +14,17 @@ import org.apache.http.entity.ContentType; import org.apache.http.impl.client.CloseableHttpClient; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.HttpResponseProxy; +import me.chanjar.weixin.common.util.http.RequestHttp; /** * Created by ecoolper on 2017/5/5. */ -public class ApacheMediaDownloadRequestExecutor extends MediaDownloadRequestExecutor { +public class ApacheMediaDownloadRequestExecutor extends BaseMediaDownloadRequestExecutor { public ApacheMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { super(requestHttp, tmpDirFile); @@ -45,8 +46,7 @@ public File execute(String uri, String queryParam) throws WxErrorException, IOEx } try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet); - InputStream inputStream = InputStreamResponseHandler.INSTANCE - .handleResponse(response)) { + InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) { Header[] contentTypeHeader = response.getHeaders("Content-Type"); if (contentTypeHeader != null && contentTypeHeader.length > 0) { if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaUploadRequestExecutor.java index bdddf0dfb9..6684bb9362 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaUploadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaUploadRequestExecutor.java @@ -1,8 +1,8 @@ package me.chanjar.weixin.common.util.http.apache; -import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import org.apache.http.HttpEntity; @@ -10,7 +10,6 @@ import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.CloseableHttpClient; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java index cc85fa76d7..2517dbcd71 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.common.util.http.apache; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; import org.apache.http.Consts; @@ -39,9 +39,7 @@ public String execute(String uri, String postEntity) throws WxErrorException, IO try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) { String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); if (responseContent.isEmpty()) { - throw new WxErrorException( - WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") - .build()); + throw new WxErrorException(WxError.builder().errorCode(9999).errorMsg("无响应内容").build()); } if (responseContent.startsWith(" ")) { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java index 19c79bdcf2..dfca21a7b2 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java @@ -1,6 +1,7 @@ package me.chanjar.weixin.common.util.http.apache; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpHost; import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -226,29 +227,26 @@ private synchronized void prepare() { .setConnectionManager(connectionManager) .setConnectionManagerShared(true) .setSSLSocketFactory(this.buildSSLConnectionSocketFactory()) - .setDefaultRequestConfig( - RequestConfig.custom() - .setSocketTimeout(this.soTimeout) - .setConnectTimeout(this.connectionTimeout) - .setConnectionRequestTimeout(this.connectionRequestTimeout) - .build() - ) - .setRetryHandler(this.httpRequestRetryHandler); - - if (StringUtils.isNotBlank(this.httpProxyHost) - && StringUtils.isNotBlank(this.httpProxyUsername)) { + .setDefaultRequestConfig(RequestConfig.custom() + .setSocketTimeout(this.soTimeout) + .setConnectTimeout(this.connectionTimeout) + .setConnectionRequestTimeout(this.connectionRequestTimeout) + .build() + ).setRetryHandler(this.httpRequestRetryHandler); + + if (StringUtils.isNotBlank(this.httpProxyHost) && StringUtils.isNotBlank(this.httpProxyUsername)) { // 使用代理服务器 需要用户认证的代理服务器 CredentialsProvider provider = new BasicCredentialsProvider(); - provider.setCredentials( - new AuthScope(this.httpProxyHost, this.httpProxyPort), - new UsernamePasswordCredentials(this.httpProxyUsername, - this.httpProxyPassword)); + provider.setCredentials(new AuthScope(this.httpProxyHost, this.httpProxyPort), + new UsernamePasswordCredentials(this.httpProxyUsername, this.httpProxyPassword)); httpClientBuilder.setDefaultCredentialsProvider(provider); + httpClientBuilder.setProxy(new HttpHost(this.httpProxyHost, this.httpProxyPort)); } if (StringUtils.isNotBlank(this.userAgent)) { httpClientBuilder.setUserAgent(this.userAgent); } + this.closeableHttpClient = httpClientBuilder.build(); prepared.set(true); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaDownloadRequestExecutor.java index bbd8bec47c..a0918f5b35 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaDownloadRequestExecutor.java @@ -1,28 +1,29 @@ package me.chanjar.weixin.common.util.http.jodd; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; + import jodd.http.HttpConnectionProvider; import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import jodd.util.StringPool; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.HttpResponseProxy; -import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; 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. */ -public class JoddHttpMediaDownloadRequestExecutor extends MediaDownloadRequestExecutor { +public class JoddHttpMediaDownloadRequestExecutor extends BaseMediaDownloadRequestExecutor { public JoddHttpMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { super(requestHttp, tmpDirFile); @@ -57,9 +58,12 @@ public File execute(String uri, String queryParam) throws WxErrorException, IOEx 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); + } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaUploadRequestExecutor.java index b4eef26a79..8ef4ddec1e 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaUploadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaUploadRequestExecutor.java @@ -6,9 +6,9 @@ import jodd.http.ProxyInfo; import jodd.util.StringPool; -import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimpleGetRequestExecutor.java index 63386e77a8..bee1d174f7 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimpleGetRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimpleGetRequestExecutor.java @@ -3,8 +3,8 @@ import jodd.http.*; import jodd.util.StringPool; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimplePostRequestExecutor.java index 8fa349c67a..b4ee996971 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimplePostRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimplePostRequestExecutor.java @@ -5,9 +5,8 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import jodd.util.StringPool; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; @@ -40,9 +39,8 @@ public String execute(String uri, String postEntity) throws WxErrorException, IO String responseContent = response.bodyText(); if (responseContent.isEmpty()) { - throw new WxErrorException( - WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") - .build()); + throw new WxErrorException(WxError.builder().errorCode(9999).errorMsg("无响应内容") + .build()); } if (responseContent.startsWith(" ")) { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java index 0923527b71..6f0a535fdf 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java @@ -1,9 +1,9 @@ package me.chanjar.weixin.common.util.http.okhttp; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.HttpResponseProxy; -import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -21,7 +21,7 @@ /** * Created by ecoolper on 2017/5/5. */ -public class OkHttpMediaDownloadRequestExecutor extends MediaDownloadRequestExecutor { +public class OkHttpMediaDownloadRequestExecutor extends BaseMediaDownloadRequestExecutor { private final Logger logger = LoggerFactory.getLogger(this.getClass()); public OkHttpMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { @@ -56,11 +56,14 @@ public File execute(String uri, String queryParam) throws WxErrorException, IOEx return null; } - File file = File.createTempFile(FilenameUtils.getBaseName(fileName), FilenameUtils.getExtension(fileName), - super.tmpDirFile); + File file = File.createTempFile( + FilenameUtils.getBaseName(fileName), "." + FilenameUtils.getExtension(fileName), super.tmpDirFile + ); + try (BufferedSink sink = Okio.buffer(Okio.sink(file))) { sink.writeAll(response.body().source()); } + file.deleteOnExit(); return file; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaUploadRequestExecutor.java index 9edeee89be..02fffb1b1b 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaUploadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaUploadRequestExecutor.java @@ -1,8 +1,8 @@ package me.chanjar.weixin.common.util.http.okhttp; -import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import okhttp3.*; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpSimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpSimpleGetRequestExecutor.java index e468c609c8..380014d003 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpSimpleGetRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpSimpleGetRequestExecutor.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.common.util.http.okhttp; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; import okhttp3.*; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpSimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpSimplePostRequestExecutor.java index bc54d7b4cd..8ba0906b38 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpSimplePostRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpSimplePostRequestExecutor.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.common.util.http.okhttp; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; import okhttp3.*; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java index 6166da9e04..882853945a 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java @@ -1,14 +1,5 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.common.util.json; - import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -16,7 +7,6 @@ import java.util.List; - public class GsonHelper { public static boolean isNull(JsonElement element) { @@ -77,7 +67,7 @@ public static Long getAsLong(JsonElement element) { public static long getAsPrimitiveLong(JsonElement element) { Long r = getAsLong(element); - return r == null ? 0l : r; + return r == null ? 0L : r; } public static Integer getAsInteger(JsonElement element) { @@ -95,7 +85,7 @@ public static Boolean getAsBoolean(JsonElement element) { public static boolean getAsPrimitiveBool(JsonElement element) { Boolean r = getAsBoolean(element); - return r != null && r.booleanValue(); + return r != null && r; } public static Double getAsDouble(JsonElement element) { @@ -130,6 +120,20 @@ public static Integer[] getIntArray(JsonObject o, String string) { return result.toArray(new Integer[0]); } + public static String[] getStringArray(JsonObject o, String string) { + JsonArray jsonArray = getAsJsonArray(o.getAsJsonArray(string)); + if (jsonArray == null) { + return null; + } + + List result = Lists.newArrayList(); + for (int i = 0; i < jsonArray.size(); i++) { + result.add(jsonArray.get(i).getAsString()); + } + + return result.toArray(new String[0]); + } + public static Long[] getLongArray(JsonObject o, String string) { JsonArray jsonArray = getAsJsonArray(o.getAsJsonArray(string)); if (jsonArray == null) { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java index e7d700e9d1..4d19ec3ad9 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.common.util.json; import com.google.gson.*; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java index cc426bc8ca..0ea52b9a86 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java @@ -1,36 +1,31 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.common.util.json; import com.google.gson.*; -import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.error.WxError; import java.lang.reflect.Type; /** - * @author Daniel Qian + * @author Daniel Qian. */ public class WxErrorAdapter implements JsonDeserializer { @Override - public WxError deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - WxError wxError = new WxError(); + public WxError deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + WxError.WxErrorBuilder errorBuilder = WxError.builder(); JsonObject wxErrorJsonObject = json.getAsJsonObject(); if (wxErrorJsonObject.get("errcode") != null && !wxErrorJsonObject.get("errcode").isJsonNull()) { - wxError.setErrorCode(GsonHelper.getAsPrimitiveInt(wxErrorJsonObject.get("errcode"))); + errorBuilder.errorCode(GsonHelper.getAsPrimitiveInt(wxErrorJsonObject.get("errcode"))); } if (wxErrorJsonObject.get("errmsg") != null && !wxErrorJsonObject.get("errmsg").isJsonNull()) { - wxError.setErrorMsg(GsonHelper.getAsString(wxErrorJsonObject.get("errmsg"))); + errorBuilder.errorMsg(GsonHelper.getAsString(wxErrorJsonObject.get("errmsg"))); } - wxError.setJson(json.toString()); - return wxError; + + errorBuilder.json(json.toString()); + + return errorBuilder.build(); } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxGsonBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxGsonBuilder.java index 9847d16211..7c7d92f03c 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxGsonBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxGsonBuilder.java @@ -4,7 +4,7 @@ import com.google.gson.GsonBuilder; import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.bean.menu.WxMenu; -import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; public class WxGsonBuilder { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java index 662b744274..3cb32c5ede 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java @@ -1,18 +1,14 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.common.util.json; -import com.google.gson.*; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; - import java.lang.reflect.Type; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; + /** * @author Daniel Qian */ @@ -20,22 +16,25 @@ public class WxMediaUploadResultAdapter implements JsonDeserializer > managers = - new Hashtable<>(); + private static final Map > MANAGERS = new Hashtable<>(); private static int LOCALE_CACHE_SIZE = 10; /** * The ResourceBundle for this StringManager. @@ -118,16 +117,16 @@ public static final synchronized StringManager getManager( public static final synchronized StringManager getManager( String packageName, Locale locale) { - Map map = managers.get(packageName); + Map map = MANAGERS.get(packageName); if (map == null) { - /* - * Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE. - * Expansion occurs when size() exceeds capacity. Therefore keep - * size at or below capacity. - * removeEldestEntry() executes after insertion therefore the test - * for removal needs to use one less than the maximum desired size - * - */ + /* + * Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE. + * Expansion occurs when size() exceeds capacity. Therefore keep + * size at or below capacity. + * removeEldestEntry() executes after insertion therefore the test + * for removal needs to use one less than the maximum desired size + * + */ map = new LinkedHashMap (LOCALE_CACHE_SIZE, 1, true) { private static final long serialVersionUID = 1L; @@ -137,7 +136,7 @@ protected boolean removeEldestEntry( return size() > (LOCALE_CACHE_SIZE - 1); } }; - managers.put(packageName, map); + MANAGERS.put(packageName, map); } StringManager mgr = map.get(locale); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java index aa2ce1763d..d97062ee61 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java @@ -1,6 +1,9 @@ package me.chanjar.weixin.common.util.xml; +import java.io.Writer; + import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider; import com.thoughtworks.xstream.core.util.QuickWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; @@ -8,12 +11,10 @@ import com.thoughtworks.xstream.security.NullPermission; import com.thoughtworks.xstream.security.PrimitiveTypePermission; -import java.io.Writer; - public class XStreamInitializer { public static XStream getInstance() { - XStream xstream = new XStream(new XppDriver() { + XStream xstream = new XStream(new PureJavaReflectionProvider(), new XppDriver() { @Override public HierarchicalStreamWriter createWriter(Writer out) { @@ -37,15 +38,18 @@ protected void writeText(QuickWriter writer, String text) { @Override public String encodeNode(String name) { - return name;//防止将_转换成__ + //防止将_转换成__ + return name; } }; } }); + xstream.ignoreUnknownElements(); xstream.setMode(XStream.NO_REFERENCES); xstream.addPermission(NullPermission.NULL); xstream.addPermission(PrimitiveTypePermission.PRIMITIVES); + xstream.setClassLoader(Thread.currentThread().getContextClassLoader()); return xstream; } diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java index 8599b29f89..6f98b3d986 100644 --- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java @@ -3,15 +3,17 @@ import org.testng.Assert; import org.testng.annotations.Test; +import java.util.concurrent.TimeUnit; + import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; @Test public class WxMessageInMemoryDuplicateCheckerTest { - private WxMessageInMemoryDuplicateChecker checker = new WxMessageInMemoryDuplicateChecker(2000l, 1000l); + private WxMessageInMemoryDuplicateChecker checker = new WxMessageInMemoryDuplicateChecker(2000L, 1000L); public void test() throws InterruptedException { - Long[] msgIds = new Long[]{1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l}; + Long[] msgIds = new Long[]{1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L}; // 第一次检查 for (Long msgId : msgIds) { @@ -20,14 +22,14 @@ public void test() throws InterruptedException { } // 过1秒再检查 - Thread.sleep(1000l); + TimeUnit.SECONDS.sleep(1); for (Long msgId : msgIds) { boolean result = checker.isDuplicate(String.valueOf(msgId)); assertTrue(result); } // 过1.5秒再检查 - Thread.sleep(1500l); + TimeUnit.MILLISECONDS.sleep(1500L); for (Long msgId : msgIds) { boolean result = checker.isDuplicate(String.valueOf(msgId)); assertFalse(result); diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/bean/WxErrorTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/error/WxErrorTest.java similarity index 53% rename from weixin-java-common/src/test/java/me/chanjar/weixin/common/bean/WxErrorTest.java rename to weixin-java-common/src/test/java/me/chanjar/weixin/common/error/WxErrorTest.java index 477fcdabc0..bbefd4879b 100644 --- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/bean/WxErrorTest.java +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/error/WxErrorTest.java @@ -1,36 +1,34 @@ -package me.chanjar.weixin.common.bean; +package me.chanjar.weixin.common.error; -import me.chanjar.weixin.common.bean.result.WxError; -import org.testng.*; -import org.testng.annotations.*; +import org.testng.Assert; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; @Test public class WxErrorTest { public void testFromJson() { - String json = "{ \"errcode\": 40003, \"errmsg\": \"invalid openid\" }"; WxError wxError = WxError.fromJson(json); - Assert.assertTrue(wxError.getErrorCode() == 40003); - Assert.assertEquals(wxError.getErrorMsg(), "invalid openid"); + assertEquals(40003, wxError.getErrorCode()); + assertEquals(wxError.getErrorMsg(), "invalid openid"); } public void testFromBadJson1() { - String json = "{ \"errcode\": 40003, \"errmsg\": \"invalid openid\", \"media_id\": \"12323423dsfafsf232f\" }"; WxError wxError = WxError.fromJson(json); - Assert.assertTrue(wxError.getErrorCode() == 40003); - Assert.assertEquals(wxError.getErrorMsg(), "invalid openid"); + assertEquals(40003, wxError.getErrorCode()); + assertEquals(wxError.getErrorMsg(), "invalid openid"); } public void testFromBadJson2() { - String json = "{\"access_token\":\"ACCESS_TOKEN\",\"expires_in\":7200}"; WxError wxError = WxError.fromJson(json); - Assert.assertTrue(wxError.getErrorCode() == 0); - Assert.assertEquals(wxError.getErrorMsg(), null); + assertEquals(0, wxError.getErrorCode()); + assertEquals(wxError.getErrorMsg(), null); } diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java index 93ad2bfc0c..84d80eab0d 100644 --- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java @@ -80,7 +80,7 @@ public void testBackgroundProcess(WxSessionManager sessionManager) throws Interr InternalSession abc = ism.createSession("abc"); abc.endAccess(); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -99,7 +99,7 @@ public void testBackgroundProcess2(WxSessionManager sessionManager) throws Inter abc.setMaxInactiveInterval(1); abc.endAccess(); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/DataUtilsTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/DataUtilsTest.java new file mode 100644 index 0000000000..af34880901 --- /dev/null +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/DataUtilsTest.java @@ -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.*; + +/** + * + * Created by BinaryWang on 2018/5/8. + *+ * + * @author Binary Wang + */ +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=******&"); + } +} diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/crypto/SHA1Test.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/crypto/SHA1Test.java index 323fc7060e..ffdb613128 100644 --- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/crypto/SHA1Test.java +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/crypto/SHA1Test.java @@ -10,7 +10,7 @@ * Created by BinaryWang on 2017/6/10. *
+ * 企业微信常量 + * Created by Binary Wang on 2018/8/25. + *+ * + * @author Binary Wang + */ +public class WxCpConsts { + /** + * 企业微信端推送过来的事件类型. + * 参考文档:https://work.weixin.qq.com/api/doc#12974 + */ + public static class EventType { + /** + * 成员关注事件. + */ + public static final String SUBSCRIBE = "subscribe"; + + /** + * 成员取消关注事件. + */ + public static final String UNSUBSCRIBE = "unsubscribe"; + + /** + * 进入应用事件. + */ + public static final String ENTER_AGENT = "enter_agent"; + + /** + * 上报地理位置. + */ + public static final String LOCATION = "LOCATION"; + + /** + * 异步任务完成事件推送. + */ + public static final String BATCH_JOB_RESULT = "batch_job_result"; + + /** + * 企业微信通讯录变更事件. + */ + public static final String CHANGE_CONTACT = "change_contact"; + + /** + * 点击菜单拉取消息的事件推送. + */ + public static final String CLICK = "click"; + + /** + * 点击菜单跳转链接的事件推送. + */ + public static final String VIEW = "view"; + + /** + * 扫码推事件的事件推送. + */ + public static final String SCANCODE_PUSH = "scancode_push"; + + /** + * 扫码推事件且弹出“消息接收中”提示框的事件推送. + */ + public static final String SCANCODE_WAITMSG = "scancode_waitmsg"; + + /** + * 弹出系统拍照发图的事件推送. + */ + public static final String PIC_SYSPHOTO = "pic_sysphoto"; + + /** + * 弹出拍照或者相册发图的事件推送. + */ + public static final String PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"; + + /** + * 弹出微信相册发图器的事件推送. + */ + public static final String PIC_WEIXIN = "pic_weixin"; + + /** + * 弹出地理位置选择器的事件推送. + */ + public static final String LOCATION_SELECT = "location_select"; + + } + + /** + * 企业微信通讯录变更事件. + */ + public static class ContactChangeType { + /** + * 新增成员事件. + */ + public static final String CREATE_USER = "create_user"; + + /** + * 更新成员事件. + */ + public static final String UPDATE_USER = "update_user"; + + /** + * 删除成员事件. + */ + public static final String DELETE_USER = "delete_user"; + + /** + * 新增部门事件. + */ + public static final String CREATE_PARTY = "create_party"; + + /** + * 更新部门事件. + */ + public static final String UPDATE_PARTY = "update_party"; + + /** + * 删除部门事件. + */ + public static final String DELETE_PARTY = "delete_party"; + + /** + * 标签成员变更事件. + */ + public static final String UPDATE_TAG = "update_tag"; + + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpAgentService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpAgentService.java new file mode 100644 index 0000000000..feea8acbd1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpAgentService.java @@ -0,0 +1,52 @@ +package me.chanjar.weixin.cp.api; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpAgent; + +import java.util.List; + +/** + *
+ * 管理企业号应用 + * 文档地址:https://work.weixin.qq.com/api/doc#10087 + * Created by huansinho on 2018/4/13. + *+ * + * @author huansinho + */ +public interface WxCpAgentService { + + /** + *
+ * 获取企业号应用信息 + * 该API用于获取企业号某个应用的基本信息,包括头像、昵称、帐号类型、认证类型、可见范围等信息 + * 详情请见: https://work.weixin.qq.com/api/doc#10087 + *+ * + * @param agentId 企业应用的id + * @return 部门id + */ + WxCpAgent get(Integer agentId) throws WxErrorException; + + /** + *
+ * 设置应用. + * 仅企业可调用,可设置当前凭证对应的应用;第三方不可调用。 + * 详情请见: https://work.weixin.qq.com/api/doc#10088 + *+ * + * @param agentInfo 应用信息 + */ + void set(WxCpAgent agentInfo) throws WxErrorException; + + /** + *
+ * 获取应用列表. + * 企业仅可获取当前凭证对应的应用;第三方仅可获取被授权的应用。 + * 详情请见: https://work.weixin.qq.com/api/doc#11214 + *+ * + */ + List
- * 部门管理接口 - 查询所有部门 - * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=部门管理接口 + * 部门管理接口 - 查询部门 + * 详情请见: http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E5.88.97.E8.A1.A8 *+ * @param id 部门id。获取指定部门及其下的子部门。非必需,可为null */ - List
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java index f813f1bf3f..19e6de4492 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java @@ -1,25 +1,28 @@ package me.chanjar.weixin.cp.api; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; - import java.io.File; import java.io.IOException; import java.io.InputStream; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.error.WxErrorException; + /** *- * 媒体管理接口 + * 媒体管理接口. * Created by BinaryWang on 2017/6/24. ** * @author Binary Wang */ public interface WxCpMediaService { + String MEDIA_GET_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; + String MEDIA_UPLOAD_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type="; + String IMG_UPLOAD_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/uploadimg"; /** *- * 上传多媒体文件 + * 上传多媒体文件. * 上传的多媒体文件有格式和大小限制,如下: * 图片(image): 1M,支持JPG格式 * 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式 @@ -30,12 +33,14 @@ public interface WxCpMediaService { * * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} * @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param inputStream 输入流 + * @param inputStream 输入流,需要调用方控制关闭该输入流 */ WxMediaUploadResult upload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException; /** + * 上传多媒体文件. + * * @param mediaType 媒体类型 * @param file 文件对象 * @see #upload(String, String, InputStream) @@ -44,7 +49,7 @@ WxMediaUploadResult upload(String mediaType, String fileType, InputStream inputS /** *- * 下载多媒体文件 + * 下载多媒体文件. * 根据微信文档,视频文件下载不了,会返回null * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=上传下载多媒体文件 *@@ -54,4 +59,17 @@ WxMediaUploadResult upload(String mediaType, String fileType, InputStream inputS */ File download(String mediaId) throws WxErrorException; + /** + *+ * 上传图片. + * 上传图片得到图片URL,该URL永久有效 + * 返回的图片URL,仅能用于图文消息(mpnews)正文中的图片展示;若用于非企业微信域名下的页面,图片将被屏蔽。 + * 每个企业每天最多可上传100张图片 + * 接口url格式:https://qyapi.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN + *+ * + * @param file 上传的文件对象 + * @return 返回图片url + */ + String uploadImg(File file) throws WxErrorException; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMenuService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMenuService.java index 012efefb7f..068c037a48 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMenuService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMenuService.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.cp.api; import me.chanjar.weixin.common.bean.menu.WxMenu; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; /** *diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java index 3312489538..5f3d6daa82 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java @@ -1,6 +1,7 @@ package me.chanjar.weixin.cp.api; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpUserDetail; /** *@@ -33,6 +34,19 @@ public interface WxCpOAuth2Service { */ String buildAuthorizationUrl(String redirectUri, String state); + /** + *+ * 构造oauth2授权的url连接 + * 详情请见: http://qydev.weixin.qq.com/wiki/index.php?title=企业获取code + *+ * + * @param redirectUri 跳转链接地址 + * @param state 状态码 + * @param scope 取值参考me.chanjar.weixin.common.api.WxConsts.OAuth2Scope类 + * @return url + */ + String buildAuthorizationUrl(String redirectUri, String state, String scope); + /** ** 用oauth2获取用户信息 @@ -50,18 +64,34 @@ public interface WxCpOAuth2Service { /** *- * 用oauth2获取用户信息 + * 根据code获取成员信息 * http://qydev.weixin.qq.com/wiki/index.php?title=根据code获取成员信息 + * https://work.weixin.qq.com/api/doc#10028/根据code获取成员信息 * 因为企业号oauth2.0必须在应用设置里设置通过ICP备案的可信域名,所以无法测试,因此这个方法很可能是坏的。 * * 注意: 这个方法不使用WxCpConfigStorage里的agentId,需要开发人员自己给出 ** * @param agentId 企业号应用的id - * @param code 微信oauth授权返回的代码 - * @return [userid, deviceid] + * @param code 通过成员授权获取到的code,最大为512字节。每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。 + * @return [UserId, DeviceId, OpenId, user_ticket, expires_in] * @see #getUserInfo(String) */ String[] getUserInfo(Integer agentId, String code) throws WxErrorException; + /** + *+ * 使用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 + * + * 权限说明: + * 需要有对应应用的使用权限,且成员必须在授权应用的可见范围内。 + *+ * + * @param userTicket 成员票据 + */ + WxCpUserDetail getUserDetail(String userTicket) throws WxErrorException; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index 03df947dc2..3e33c4eb55 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -1,9 +1,7 @@ package me.chanjar.weixin.cp.api; import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.menu.WxMenu; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.WxSession; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; @@ -12,16 +10,11 @@ import me.chanjar.weixin.cp.bean.*; import me.chanjar.weixin.cp.config.WxCpConfigStorage; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; - /** * 微信API的Service + * @author chanjaster */ public interface WxCpService { - /** ** 验证推送过来的消息的正确性 @@ -85,42 +78,6 @@ public interface WxCpService { */ WxJsapiSignature createJsapiSignature(String url) throws WxErrorException; - /** - * @deprecated 请使用 {@link WxCpMenuService#create(WxMenu)} - */ - @Deprecated - void menuCreate(WxMenu menu) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpMenuService#create(Integer, WxMenu)} - */ - @Deprecated - void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpMenuService#delete()} } - */ - @Deprecated - void menuDelete() throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpMenuService#delete(Integer)} - */ - @Deprecated - void menuDelete(Integer agentId) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpMenuService#get() } - */ - @Deprecated - WxMenu menuGet() throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpMenuService#get(Integer)} - */ - @Deprecated - WxMenu menuGet(Integer agentId) throws WxErrorException; - /** ** 发送消息 @@ -131,175 +88,6 @@ public interface WxCpService { */ WxCpMessageSendResult messageSend(WxCpMessage message) throws WxErrorException; - /** - * @deprecated 请使用 {@link WxCpDepartmentService#create(WxCpDepart)} - */ - @Deprecated - Integer departCreate(WxCpDepart depart) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpDepartmentService#update(WxCpDepart)} - */ - @Deprecated - void departUpdate(WxCpDepart group) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpDepartmentService#delete(Integer)} - */ - @Deprecated - void departDelete(Integer departId) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpDepartmentService#listAll() } - */ - @Deprecated - ListdepartGet() throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpMediaService#upload(String, String, InputStream)} - */ - @Deprecated - WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) - throws WxErrorException, IOException; - - /** - * @deprecated 请使用 {@link WxCpMediaService#upload(String, File)} - */ - @Deprecated - WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpMediaService#download(String)} - */ - @Deprecated - File mediaDownload(String mediaId) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpUserService#authenticate(String)} - */ - @Deprecated - void userAuthenticated(String userId) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpUserService#create(WxCpUser)} - */ - @Deprecated - void userCreate(WxCpUser user) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpUserService#update(WxCpUser)} - */ - @Deprecated - void userUpdate(WxCpUser user) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpUserService#delete(String...)} - */ - @Deprecated - void userDelete(String userid) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpUserService#delete(String...)} - */ - @Deprecated - void userDelete(String[] userids) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpUserService#getById(String)} - */ - @Deprecated - WxCpUser userGet(String userid) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpUserService#listByDepartment(Integer, Boolean, Integer)} - */ - @Deprecated - List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpUserService#listSimpleByDepartment(Integer, Boolean, Integer)} - */ - @Deprecated - List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpTagService#create(String)} - */ - @Deprecated - String tagCreate(String tagName) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpTagService#update(String, String)} - */ - @Deprecated - void tagUpdate(String tagId, String tagName) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpTagService#delete(String)} - */ - @Deprecated - void tagDelete(String tagId) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpTagService#listAll()} - */ - @Deprecated - List tagGet() throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpTagService#listUsersByTagId(String)} - */ - @Deprecated - List tagGetUsers(String tagId) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpTagService#addUsers2Tag(String, List, List)} - */ - @Deprecated - void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpTagService#removeUsersFromTag(String, List)} - */ - @Deprecated - void tagRemoveUsers(String tagId, List userIds) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpOAuth2Service#buildAuthorizationUrl(String)} - */ - @Deprecated - String oauth2buildAuthorizationUrl(String state); - - /** - * @deprecated 请使用 {@link WxCpOAuth2Service#buildAuthorizationUrl(String, String)} - */ - @Deprecated - String oauth2buildAuthorizationUrl(String redirectUri, String state); - - /** - * @deprecated 请使用 {@link WxCpOAuth2Service#getUserInfo(String)} - */ - @Deprecated - String[] oauth2getUserInfo(String code) throws WxErrorException; - - /** - * @deprecated 请使用 {@link WxCpOAuth2Service#getUserInfo(Integer, String)} - */ - @Deprecated - String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException; - - /** - * - * 邀请成员关注 - * 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 - *- * - * @param userId 用户的userid - * @param inviteTips 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。 - * @return 1:微信邀请 2.邮件邀请 - */ - int invite(String userId, String inviteTips) throws WxErrorException; - /** ** 获取微信服务器的ip段 @@ -454,6 +242,8 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i */ WxCpUserService getUserService(); + WxCpAgentService getAgentService(); + /** * http请求对象 */ diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTagService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTagService.java index c96318b80b..9624f9e409 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTagService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTagService.java @@ -1,15 +1,16 @@ package me.chanjar.weixin.cp.api; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.WxCpTag; import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; +import me.chanjar.weixin.cp.bean.WxCpTagGetResult; import me.chanjar.weixin.cp.bean.WxCpUser; import java.util.List; /** *- * 标签管理接口 + * 标签管理接口. * Created by BinaryWang on 2017/6/24. ** @@ -17,14 +18,14 @@ */ public interface WxCpTagService { /** - * 创建标签 + * 创建标签. * * @param tagName 标签名 */ String create(String tagName) throws WxErrorException; /** - * 更新标签 + * 更新标签. * * @param tagId 标签id * @param tagName 标签名 @@ -32,35 +33,49 @@ public interface WxCpTagService { void update(String tagId, String tagName) throws WxErrorException; /** - * 删除标签 + * 删除标签. * * @param tagId 标签id */ void delete(String tagId) throws WxErrorException; /** - * 获得标签列表 + * 获得标签列表. */ ListlistAll() throws WxErrorException; /** - * 获取标签成员 + * 获取标签成员. * * @param tagId 标签ID */ List 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 userIds, List partyIds) throws WxErrorException; /** - * 移除标签成员 - * @param tagId 标签id - * @param userIds 用户id列表 + * 移除标签成员. + * + * @param tagId 标签id + * @param userIds 用户id列表 + * @param partyIds 企业部门ID列表 */ - WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List userIds) throws WxErrorException; + WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List userIds, List partyIds) throws WxErrorException; + + + /** + * 获取标签成员. + * 对应: http://qydev.weixin.qq.com/wiki/index.php?title=管理标签 中的get接口 + * + * @param tagId 标签id + */ + WxCpTagGetResult get(String tagId) throws WxErrorException; + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java index 49ef9134f5..9f9317256e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java @@ -1,9 +1,12 @@ package me.chanjar.weixin.cp.api; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.cp.bean.WxCpUser; - import java.util.List; +import java.util.Map; + +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.WxCpUserExternalContactInfo; /** * @@ -16,7 +19,7 @@ public interface WxCpUserService { /** *- * 用在二次验证的时候 + * 用在二次验证的时候. * 企业在员工验证成功后,调用本方法告诉企业号平台该员工关注成功。 ** @@ -26,7 +29,7 @@ public interface WxCpUserService { /** *- * 获取部门成员(详情) + * 获取部门成员(详情). * * http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E6.88.90.E5.91.98.28.E8.AF.A6.E6.83.85.29 *@@ -39,7 +42,7 @@ public interface WxCpUserService { /** *- * 获取部门成员 + * 获取部门成员. * * http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E6.88.90.E5.91.98 *@@ -51,14 +54,14 @@ public interface WxCpUserService { ListlistSimpleByDepartment(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException; /** - * 新建用户 + * 新建用户. * * @param user 用户对象 */ void create(WxCpUser user) throws WxErrorException; /** - * 更新用户 + * 更新用户. * * @param user 用户对象 */ @@ -66,7 +69,7 @@ public interface WxCpUserService { /** * - * 删除用户/批量删除成员 + * 删除用户/批量删除成员. * http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E6.89.B9.E9.87.8F.E5.88.A0.E9.99.A4.E6.88.90.E5.91.98 ** @@ -75,9 +78,74 @@ public interface WxCpUserService { void delete(String... userIds) throws WxErrorException; /** - * 获取用户 + * 获取用户. * * @param userid 用户id */ WxCpUser getById(String userid) throws WxErrorException; + + /** + *+ * 邀请成员. + * 企业可通过接口批量邀请成员使用企业微信,邀请后将通过短信或邮件下发通知。 + * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/batch/invite?access_token=ACCESS_TOKEN + * 文档地址:https://work.weixin.qq.com/api/doc#12543 + *+ * + * @param userIds 成员ID列表, 最多支持1000个。 + * @param partyIds 部门ID列表,最多支持100个。 + * @param tagIds 标签ID列表,最多支持100个。 + */ + WxCpInviteResult invite(ListuserIds, List partyIds, List tagIds) throws WxErrorException; + + /** + * + * userid转openid. + * 该接口使用场景为微信支付、微信红包和企业转账。 + * + * 在使用微信支付的功能时,需要自行将企业微信的userid转成openid。 + * 在使用微信红包功能时,需要将应用id和userid转成appid和openid才能使用。 + * 注:需要成员使用微信登录企业微信或者关注微信插件才能转成openid + * + * 文档地址:https://work.weixin.qq.com/api/doc#11279 + *+ * + * @param userId 企业内的成员id + * @param agentId 非必填,整型,仅用于发红包。其它场景该参数不要填,如微信支付、企业转账、电子发票 + * @return map对象,可能包含以下值: + * - openid 企业微信成员userid对应的openid,若有传参agentid,则是针对该agentid的openid。否则是针对企业微信corpid的openid + * - appid 应用的appid,若请求包中不包含agentid则不返回appid。该appid在使用微信红包时会用到 + */ + MapuserId2Openid(String userId, Integer agentId) throws WxErrorException; + + /** + * + * openid转userid. + * + * 该接口主要应用于使用微信支付、微信红包和企业转账之后的结果查询。 + * 开发者需要知道某个结果事件的openid对应企业微信内成员的信息时,可以通过调用该接口进行转换查询。 + * 权限说明: + * 管理组需对openid对应的企业微信成员有查看权限。 + * + * 文档地址:https://work.weixin.qq.com/api/doc#11279 + *+ * + * @param openid 在使用微信支付、微信红包和企业转账之后,返回结果的openid + * @return userid 该openid在企业微信对应的成员userid + */ + String openid2UserId(String openid) throws WxErrorException; + + /** + * 获取外部联系人详情. + *+ * 企业可通过此接口,根据外部联系人的userid,拉取外部联系人详情。权限说明: + * 企业需要使用外部联系人管理secret所获取的accesstoken来调用 + * 第三方应用需拥有“企业客户”权限。 + * 第三方应用调用时,返回的跟进人follow_user仅包含应用可见范围之内的成员。 + *+ * + * @param userId 外部联系人的userid + */ + WxCpUserExternalContactInfo getExternalContact(String userId) throws WxErrorException; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImpl.java new file mode 100644 index 0000000000..e4914134c1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImpl.java @@ -0,0 +1,68 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.Gson; +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.cp.api.WxCpAgentService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpAgent; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + + +/** + *+ * 管理企业号应用 + * Created by huansinho on 2018/4/13. + *+ * + * @author huansinho + */ +public class WxCpAgentServiceImpl implements WxCpAgentService { + private static final JsonParser JSON_PARSER = new JsonParser(); + + private WxCpService mainService; + + public WxCpAgentServiceImpl(WxCpService mainService) { + this.mainService = mainService; + } + + @Override + public WxCpAgent get(Integer agentId) throws WxErrorException { + if (agentId == null) { + throw new IllegalArgumentException("缺少agentid参数"); + } + + String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/get?agentid=" + agentId; + String responseContent = this.mainService.get(url, null); + return WxCpAgent.fromJson(responseContent); + } + + @Override + public void set(WxCpAgent agentInfo) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/set"; + String responseContent = this.mainService.post(url, agentInfo.toJson()); + JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent)); + } + } + + @Override + public Listlist() throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/list"; + String responseContent = this.mainService.get(url, null); + JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent)); + } + + return WxCpGsonBuilder.create().fromJson(jsonObject.get("agentlist").toString(), new TypeToken >() { + }.getType()); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java index 82cd8c345c..6645219902 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java @@ -3,7 +3,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.cp.api.WxCpDepartmentService; import me.chanjar.weixin.cp.api.WxCpService; @@ -48,13 +48,13 @@ public void delete(Integer departId) throws WxErrorException { } @Override - public List
listAll() throws WxErrorException { + public List list(Integer id) throws WxErrorException { String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; + if (id != null) { + url += "?id=" + id; + } + String responseContent = this.mainService.get(url, null); - /* - * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } - * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } - */ JsonElement tmpJsonElement = new JsonParser().parse(responseContent); return WxCpGsonBuilder.INSTANCE.create() .fromJson(tmpJsonElement.getAsJsonObject().get("department"), diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImpl.java index 1364550aac..c3dc477495 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImpl.java @@ -1,24 +1,25 @@ package me.chanjar.weixin.cp.api.impl; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.cp.api.WxCpMediaService; import me.chanjar.weixin.cp.api.WxCpService; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; - /** * - * 媒体管理接口 + * 媒体管理接口. * Created by Binary Wang on 2017-6-25. - * @author Binary Wang *+ * + * @author Binary Wang */ public class WxCpMediaServiceImpl implements WxCpMediaService { private WxCpService mainService; @@ -35,16 +36,22 @@ public WxMediaUploadResult upload(String mediaType, String fileType, InputStream @Override public WxMediaUploadResult upload(String mediaType, File file) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; - return this.mainService.execute(MediaUploadRequestExecutor.create(this.mainService.getRequestHttp()), url, file); + return this.mainService.execute(MediaUploadRequestExecutor.create(this.mainService.getRequestHttp()), + MEDIA_UPLOAD_URL + mediaType, file); } @Override public File download(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; return this.mainService.execute( - MediaDownloadRequestExecutor.create(this.mainService.getRequestHttp(), + BaseMediaDownloadRequestExecutor.create(this.mainService.getRequestHttp(), this.mainService.getWxCpConfigStorage().getTmpDirFile()), - url, "media_id=" + mediaId); + MEDIA_GET_URL, "media_id=" + mediaId); + } + + @Override + public String uploadImg(File file) throws WxErrorException { + final WxMediaUploadResult result = this.mainService + .execute(MediaUploadRequestExecutor.create(this.mainService.getRequestHttp()), IMG_UPLOAD_URL, file); + return result.getUrl(); } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImpl.java index 7c3937d83e..f58eff4763 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImpl.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.cp.api.impl; import me.chanjar.weixin.common.bean.menu.WxMenu; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.WxCpMenuService; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java index a317bfb4e6..8f0375f340 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java @@ -1,19 +1,24 @@ package me.chanjar.weixin.cp.api.impl; +import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.URIUtil; import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.cp.api.WxCpOAuth2Service; import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpUserDetail; /** ** * Created by Binary Wang on 2017-6-25. * @author Binary Wang + * + * @author Binary Wang **/ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service { @@ -33,34 +38,55 @@ public String buildAuthorizationUrl(String state) { @Override public String buildAuthorizationUrl(String redirectUri, String state) { - String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; - url += "appid=" + this.mainService.getWxCpConfigStorage().getCorpId(); - url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); - url += "&response_type=code"; - url += "&scope=snsapi_base"; + return this.buildAuthorizationUrl(redirectUri, state, WxConsts.OAuth2Scope.SNSAPI_BASE); + } + + @Override + public String buildAuthorizationUrl(String redirectUri, String state, String scope) { + StringBuilder url = new StringBuilder("https://open.weixin.qq.com/connect/oauth2/authorize?"); + url.append("appid=").append(this.mainService.getWxCpConfigStorage().getCorpId()); + url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectUri)); + url.append("&response_type=code"); + url.append("&scope=").append(scope); + + if (WxConsts.OAuth2Scope.SNSAPI_PRIVATEINFO.equals(scope) + || WxConsts.OAuth2Scope.SNSAPI_USERINFO.equals(scope)) { + url.append("&agentid=").append(this.mainService.getWxCpConfigStorage().getAgentId()); + } + if (state != null) { - url += "&state=" + state; + url.append("&state=").append(state); } - url += "#wechat_redirect"; - return url; + url.append("#wechat_redirect"); + return url.toString(); } @Override public String[] getUserInfo(String code) throws WxErrorException { - return getUserInfo(this.mainService.getWxCpConfigStorage().getAgentId(), code); + return this.getUserInfo(this.mainService.getWxCpConfigStorage().getAgentId(), code); } @Override public String[] getUserInfo(Integer agentId, String code) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" - + "code=" + code - + "&agentid=" + agentId; + String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?code=%s&agentid=%d", + code, agentId); String responseText = this.mainService.get(url, null); JsonElement je = new JsonParser().parse(responseText); JsonObject jo = je.getAsJsonObject(); return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId"), - GsonHelper.getString(jo, "OpenId")}; + GsonHelper.getString(jo, "OpenId"), + GsonHelper.getString(jo, "user_ticket"), + GsonHelper.getString(jo, "expires_in") + }; } + @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); + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java index 83bc5e13c6..0c66e0ef77 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java @@ -5,13 +5,12 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.menu.WxMenu; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.StandardSessionManager; import me.chanjar.weixin.common.session.WxSession; import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.common.util.DataUtils; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; import me.chanjar.weixin.common.util.http.RequestExecutor; @@ -21,14 +20,11 @@ import me.chanjar.weixin.cp.api.*; import me.chanjar.weixin.cp.bean.*; import me.chanjar.weixin.cp.config.WxCpConfigStorage; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.util.List; public abstract class WxCpServiceAbstractImplimplements WxCpService, RequestHttp { protected final Logger log = LoggerFactory.getLogger(this.getClass()); @@ -39,6 +35,7 @@ public abstract class WxCpServiceAbstractImpl implements WxCpService, Requ private WxCpMenuService menuService = new WxCpMenuServiceImpl(this); private WxCpOAuth2Service oauth2Service = new WxCpOAuth2ServiceImpl(this); private WxCpTagService tagService = new WxCpTagServiceImpl(this); + private WxCpAgentService agentService = new WxCpAgentServiceImpl(this); /** * 全局的是否正在刷新access token的锁 @@ -138,188 +135,6 @@ public WxCpMessageSendResult messageSend(WxCpMessage message) throws WxErrorExce return WxCpMessageSendResult.fromJson(this.post(url, message.toJson())); } - @Override - @Deprecated - public void menuCreate(WxMenu menu) throws WxErrorException { - this.getMenuService().create(menu); - } - - @Override - @Deprecated - public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { - this.getMenuService().create(agentId, menu); - } - - @Override - @Deprecated - public void menuDelete() throws WxErrorException { - this.getMenuService().delete(); - } - - @Override - @Deprecated - public void menuDelete(Integer agentId) throws WxErrorException { - this.getMenuService().delete(agentId); - } - - @Override - @Deprecated - public WxMenu menuGet() throws WxErrorException { - return this.getMenuService().get(); - } - - @Override - @Deprecated - public WxMenu menuGet(Integer agentId) throws WxErrorException { - return this.getMenuService().get(agentId); - } - - @Override - @Deprecated - public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) - throws WxErrorException, IOException { - return this.getMediaService().upload(mediaType, fileType, inputStream); - } - - @Override - @Deprecated - public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { - return this.getMediaService().upload(mediaType, file); - } - - @Override - @Deprecated - public File mediaDownload(String mediaId) throws WxErrorException { - return this.getMediaService().download(mediaId); - } - - @Override - @Deprecated - public void userAuthenticated(String userId) throws WxErrorException { - this.getUserService().authenticate(userId); - } - - @Override - @Deprecated - public void userCreate(WxCpUser user) throws WxErrorException { - this.getUserService().create(user); - } - - @Override - @Deprecated - public void userUpdate(WxCpUser user) throws WxErrorException { - this.getUserService().update(user); - } - - @Override - @Deprecated - public void userDelete(String userid) throws WxErrorException { - this.getUserService().delete(userid); - } - - @Override - @Deprecated - public void userDelete(String[] userids) throws WxErrorException { - this.getUserService().delete(userids); - } - - @Override - @Deprecated - public WxCpUser userGet(String userid) throws WxErrorException { - return this.getUserService().getById(userid); - } - - @Override - @Deprecated - public List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - return this.getUserService().listByDepartment(departId, fetchChild, status); - } - - @Override - @Deprecated - public List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - return this.getUserService().listSimpleByDepartment(departId, fetchChild, status); - } - - @Override - @Deprecated - public String tagCreate(String tagName) throws WxErrorException { - return this.getTagService().create(tagName); - } - - @Override - @Deprecated - public void tagUpdate(String tagId, String tagName) throws WxErrorException { - this.getTagService().update(tagId, tagName); - } - - @Override - @Deprecated - public void tagDelete(String tagId) throws WxErrorException { - this.getTagService().delete(tagId); - } - - @Override - @Deprecated - public List tagGet() throws WxErrorException { - return this.getTagService().listAll(); - } - - @Override - @Deprecated - public List tagGetUsers(String tagId) throws WxErrorException { - return this.getTagService().listUsersByTagId(tagId); - } - - @Override - @Deprecated - public void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException { - this.getTagService().addUsers2Tag(tagId, userIds, partyIds); - } - - @Override - @Deprecated - public void tagRemoveUsers(String tagId, List userIds) throws WxErrorException { - this.getTagService().removeUsersFromTag(tagId, userIds); - } - - @Override - @Deprecated - public String oauth2buildAuthorizationUrl(String state) { - return this.getOauth2Service().buildAuthorizationUrl(state); - } - - @Override - @Deprecated - public String oauth2buildAuthorizationUrl(String redirectUri, String state) { - return this.getOauth2Service().buildAuthorizationUrl(redirectUri, state); - } - - @Override - @Deprecated - public String[] oauth2getUserInfo(String code) throws WxErrorException { - return this.getOauth2Service().getUserInfo(code); - } - - @Override - @Deprecated - public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { - return this.getOauth2Service().getUserInfo(agentId, code); - } - - @Override - public int invite(String userId, String inviteTips) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("userid", userId); - if (StringUtils.isNotEmpty(inviteTips)) { - jsonObject.addProperty("invite_tips", inviteTips); - } - String responseContent = post(url, jsonObject.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); - } - @Override public String[] getCallbackIp() throws WxErrorException { String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; @@ -381,7 +196,9 @@ public T execute(RequestExecutor executor, String uri, E data) thro throw new RuntimeException("微信服务端异常,超出重试次数"); } - protected synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + protected T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + E dataForLog = DataUtils.handleDataWithSecret(data); + if (uri.contains("access_token=")) { throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); } @@ -391,7 +208,7 @@ protected synchronized T executeInternal(RequestExecutor executor, try { T result = executor.execute(uriWithAccessToken, data); - this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); + this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); return result; } catch (WxErrorException e) { WxError error = e.getError(); @@ -408,12 +225,12 @@ protected synchronized T executeInternal(RequestExecutor executor, } if (error.getErrorCode() != 0) { - this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); + this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); throw new WxErrorException(error, e); } return null; } catch (IOException e) { - this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); + this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); throw new RuntimeException(e); } } @@ -516,30 +333,6 @@ public WxCpUserService getUserService() { return userService; } - @Override - @Deprecated - public Integer departCreate(WxCpDepart depart) throws WxErrorException { - return this.getDepartmentService().create(depart); - } - - @Override - @Deprecated - public void departUpdate(WxCpDepart depart) throws WxErrorException { - this.getDepartmentService().update(depart); - } - - @Override - @Deprecated - public void departDelete(Integer departId) throws WxErrorException { - this.getDepartmentService().delete(departId); - } - - @Override - @Deprecated - public List departGet() throws WxErrorException { - return this.getDepartmentService().listAll(); - } - @Override public RequestHttp getRequestHttp() { return this; @@ -574,4 +367,13 @@ public void setOauth2Service(WxCpOAuth2Service oauth2Service) { public void setTagService(WxCpTagService tagService) { this.tagService = tagService; } + + @Override + public WxCpAgentService getAgentService() { + return agentService; + } + + public void setAgentService(WxCpAgentService agentService) { + this.agentService = agentService; + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java index af32f5fb5d..7081272793 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java @@ -1,9 +1,10 @@ package me.chanjar.weixin.cp.api.impl; +import me.chanjar.weixin.common.WxType; import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.HttpType; import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; @@ -58,7 +59,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException { } finally { httpGet.releaseConnection(); } - WxError error = WxError.fromJson(resultContent); + WxError error = WxError.fromJson(resultContent, WxType.CP); if (error.getErrorCode() != 0) { throw new WxErrorException(error); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceImpl.java index ff8e149c77..a7538c6ead 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceImpl.java @@ -4,8 +4,9 @@ * * 默认接口实现类,使用apache httpclient实现 * Created by Binary Wang on 2017-5-27. - * @author binarywang(Binary Wang) *+ * + * @author Binary Wang */ public class WxCpServiceImpl extends WxCpServiceApacheHttpClientImpl { } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java index 3e7c4bc5b8..2d7e1b1c29 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java @@ -1,9 +1,10 @@ package me.chanjar.weixin.cp.api.impl; import jodd.http.*; +import me.chanjar.weixin.common.WxType; import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.HttpType; import me.chanjar.weixin.cp.config.WxCpConfigStorage; @@ -44,7 +45,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException { HttpResponse response = request.send(); String resultContent = response.bodyText(); - WxError error = WxError.fromJson(resultContent); + WxError error = WxError.fromJson(resultContent, WxType.CP); if (error.getErrorCode() != 0) { throw new WxErrorException(error); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceOkHttpImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceOkHttpImpl.java index f8476ff5af..34c978cd4f 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceOkHttpImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceOkHttpImpl.java @@ -1,20 +1,17 @@ package me.chanjar.weixin.cp.api.impl; +import me.chanjar.weixin.common.WxType; import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.HttpType; import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo; import me.chanjar.weixin.cp.config.WxCpConfigStorage; import okhttp3.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; public class WxCpServiceOkHttpImpl extends WxCpServiceAbstractImpl{ - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - protected OkHttpClient httpClient; protected OkHttpProxyInfo httpProxy; @@ -36,7 +33,7 @@ public HttpType getRequestType() { @Override public String getAccessToken(boolean forceRefresh) throws WxErrorException { - logger.debug("WxCpServiceOkHttpImpl is running"); + this.log.debug("WxCpServiceOkHttpImpl is running"); if (this.configStorage.isAccessTokenExpired() || forceRefresh) { synchronized (this.globalAccessTokenRefreshLock) { if (this.configStorage.isAccessTokenExpired()) { @@ -47,19 +44,15 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException { OkHttpClient client = getRequestHttpClient(); //请求的request Request request = new Request.Builder().url(url).get().build(); - Response response = null; - try { - response = client.newCall(request).execute(); - } catch (IOException e) { - e.printStackTrace(); - } String resultContent = null; try { + Response response = client.newCall(request).execute(); resultContent = response.body().string(); } catch (IOException e) { - e.printStackTrace(); + this.log.error(e.getMessage(), e); } - WxError error = WxError.fromJson(resultContent); + + WxError error = WxError.fromJson(resultContent, WxType.CP); if (error.getErrorCode() != 0) { throw new WxErrorException(error); } @@ -74,9 +67,16 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException { @Override public void initHttp() { - logger.debug("WxCpServiceOkHttpImpl initHttp"); - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + this.log.debug("WxCpServiceOkHttpImpl initHttp"); //设置代理 + if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { + httpProxy = OkHttpProxyInfo.httpProxy(configStorage.getHttpProxyHost(), + configStorage.getHttpProxyPort(), + configStorage.getHttpProxyUsername(), + configStorage.getHttpProxyPassword()); + } + + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); if (httpProxy != null) { clientBuilder.proxy(getRequestHttpProxy().getProxy()); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImpl.java index ff995d9724..aa8260b14e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImpl.java @@ -2,11 +2,12 @@ import com.google.gson.*; import com.google.gson.reflect.TypeToken; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.api.WxCpTagService; import me.chanjar.weixin.cp.bean.WxCpTag; import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; +import me.chanjar.weixin.cp.bean.WxCpTagGetResult; import me.chanjar.weixin.cp.bean.WxCpUser; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; @@ -82,6 +83,22 @@ public WxCpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List use String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("tagid", tagId); + this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject); + + return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString())); + } + + @Override + public WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List userIds, List 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 userIds, List partyIds, JsonObject jsonObject) { if (userIds != null) { JsonArray jsonArray = new JsonArray(); for (String userId : userIds) { @@ -89,6 +106,7 @@ public WxCpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List use } jsonObject.add("userlist", jsonArray); } + if (partyIds != null) { JsonArray jsonArray = new JsonArray(); for (String userId : partyIds) { @@ -96,21 +114,19 @@ public WxCpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List use } jsonObject.add("partylist", jsonArray); } - - return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString())); } @Override - public WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List 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); } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java index 13009427c6..68224b1eb9 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java @@ -1,15 +1,23 @@ package me.chanjar.weixin.cp.api.impl; -import com.google.gson.*; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Maps; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; import com.google.gson.reflect.TypeToken; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.api.WxCpUserService; +import me.chanjar.weixin.cp.bean.WxCpInviteResult; import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; -import java.util.List; - /** * * Created by BinaryWang on 2017/6/24. @@ -112,4 +120,74 @@ public ListlistSimpleByDepartment(Integer departId, Boolean fetchChil ); } + @Override + public WxCpInviteResult invite(List userIds, List partyIds, List tagIds) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/invite"; + JsonObject jsonObject = new JsonObject(); + if (userIds != null) { + JsonArray jsonArray = new JsonArray(); + for (String userId : userIds) { + jsonArray.add(new JsonPrimitive(userId)); + } + jsonObject.add("user", jsonArray); + } + + 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 + public Map userId2Openid(String userId, Integer agentId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + if (agentId != null) { + jsonObject.addProperty("agentid", agentId); + } + + String responseContent = this.mainService.post(url, jsonObject.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + Map result = Maps.newHashMap(); + if (tmpJsonElement.getAsJsonObject().get("openid") != null) { + result.put("openid", tmpJsonElement.getAsJsonObject().get("openid").getAsString()); + } + + if (tmpJsonElement.getAsJsonObject().get("appid") != null) { + result.put("appid", tmpJsonElement.getAsJsonObject().get("appid").getAsString()); + } + + return result; + } + + @Override + public String openid2UserId(String openid) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_userid"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("openid", openid); + String responseContent = this.mainService.post(url, jsonObject.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return tmpJsonElement.getAsJsonObject().get("userid").getAsString(); + } + + @Override + public WxCpUserExternalContactInfo getExternalContact(String userId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/crm/get_external_contact?external_userid=" + userId; + String responseContent = this.mainService.get(url, null); + return WxCpUserExternalContactInfo.fromJson(responseContent); + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/Gender.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/Gender.java new file mode 100644 index 0000000000..2b6e26efde --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/Gender.java @@ -0,0 +1,47 @@ +package me.chanjar.weixin.cp.bean; + +/** + * + * 性别枚举 + * Created by BinaryWang on 2018/4/22. + *+ * + * @author Binary Wang + */ +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; + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpAgent.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpAgent.java new file mode 100644 index 0000000000..b70571f075 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpAgent.java @@ -0,0 +1,105 @@ +package me.chanjar.weixin.cp.bean; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + *+ * 企业号应用信息. + * Created by huansinho on 2018/4/13. + *+ * + * @author huansinho + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpAgent implements Serializable { + private static final long serialVersionUID = 5002894979081127234L; + + @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("logo_mediaid") + private String logoMediaId; + + @SerializedName("description") + private String description; + + @SerializedName("allow_userinfos") + private Users allowUserInfos; + + @SerializedName("allow_partys") + private Parties allowParties; + + @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 Listusers; + } + + @Data + public class User implements Serializable { + @SerializedName("userid") + private String userId; + } + + @Data + public class Parties { + @SerializedName("partyid") + private List partyIds = null; + } + + @Data + public class Tags { + @SerializedName("tagid") + private List tagIds = null; + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpDepart.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpDepart.java index 118c500488..2890ce61eb 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpDepart.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpDepart.java @@ -1,69 +1,30 @@ package me.chanjar.weixin.cp.bean; +import lombok.Data; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; import java.io.Serializable; /** - * 微信部门 + * 微信部门. * * @author Daniel Qian */ +@Data public class WxCpDepart implements Serializable { private static final long serialVersionUID = -5028321625140879571L; private Integer id; private String name; private Integer parentId; - private Integer order; + private Long order; public static WxCpDepart fromJson(String json) { return WxCpGsonBuilder.create().fromJson(json, WxCpDepart.class); } - public Integer getId() { - return this.id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getParentId() { - return this.parentId; - } - - public void setParentId(Integer parentId) { - this.parentId = parentId; - } - - public Integer getOrder() { - return this.order; - } - - public void setOrder(Integer order) { - this.order = order; - } - public String toJson() { return WxCpGsonBuilder.create().toJson(this); } - @Override - public String toString() { - return "WxCpDepart{" + - "id=" + this.id + - ", name='" + this.name + '\'' + - ", parentId=" + this.parentId + - ", order=" + this.order + - '}'; - } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpInviteResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpInviteResult.java new file mode 100644 index 0000000000..f6ff46348e --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpInviteResult.java @@ -0,0 +1,62 @@ +package me.chanjar.weixin.cp.bean; + +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import com.google.common.base.Splitter; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * 邀请成员的结果对象类. + * Created by Binary Wang on 2018-5-13. + * + * @author Binary Wang + */ +@Data +public class WxCpInviteResult implements Serializable { + private static final long serialVersionUID = 1420065684270213578L; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + + 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 getInvalidUserList() { + return this.content2List(this.invalidUsers); + } + + private List content2List(String content) { + if (StringUtils.isBlank(content)) { + return Collections.emptyList(); + } + + return Splitter.on("|").splitToList(content); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessage.java index c59ca87e1f..58fc983063 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessage.java @@ -1,5 +1,7 @@ package me.chanjar.weixin.cp.bean; +import lombok.Data; +import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.cp.bean.article.MpnewsArticle; import me.chanjar.weixin.cp.bean.article.NewArticle; import me.chanjar.weixin.cp.bean.messagebuilder.*; @@ -10,13 +12,14 @@ import java.util.List; /** - * 消息 + * 消息. * * @author Daniel Qian */ +@Data public class WxCpMessage implements Serializable { - private static final long serialVersionUID = -2082278303476631708L; + private String toUser; private String toParty; private String toTag; @@ -31,119 +34,77 @@ public class WxCpMessage implements Serializable { private String hqMusicUrl; private String safe; private String url; + private String btnTxt; private List articles = new ArrayList<>(); private List mpnewsArticles = new ArrayList<>(); /** - * 获得文本消息builder + * 获得文本消息builder. */ public static TextBuilder TEXT() { return new TextBuilder(); } /** - * 获得文本卡片消息builder + * 获得文本卡片消息builder. */ public static TextCardBuilder TEXTCARD() { return new TextCardBuilder(); } /** - * 获得图片消息builder + * 获得图片消息builder. */ public static ImageBuilder IMAGE() { return new ImageBuilder(); } /** - * 获得语音消息builder + * 获得语音消息builder. */ public static VoiceBuilder VOICE() { return new VoiceBuilder(); } /** - * 获得视频消息builder + * 获得视频消息builder. */ public static VideoBuilder VIDEO() { return new VideoBuilder(); } /** - * 获得图文消息builder + * 获得图文消息builder. */ public static NewsBuilder NEWS() { return new NewsBuilder(); } /** - * 获得mpnews图文消息builder + * 获得mpnews图文消息builder. */ public static MpnewsBuilder MPNEWS() { return new MpnewsBuilder(); } /** - * 获得文件消息builder + * 获得文件消息builder. */ public static FileBuilder FILE() { return new FileBuilder(); } - public List getMpnewsArticles() { - return mpnewsArticles; - } - - public void setMpnewsArticles(List mpnewsArticles) { - this.mpnewsArticles = mpnewsArticles; - } - - public String getToUser() { - return this.toUser; - } - - public void setToUser(String toUser) { - this.toUser = toUser; - } - - public String getToParty() { - return this.toParty; - } - - public void setToParty(String toParty) { - this.toParty = toParty; - } - - public String getToTag() { - return this.toTag; - } - - public void setToTag(String toTag) { - this.toTag = toTag; - } - - public Integer getAgentId() { - return this.agentId; - } - - public void setAgentId(Integer agentId) { - this.agentId = agentId; - } - - public String getMsgType() { - return this.msgType; - } /** * * 请使用 - * {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_TEXT} - * {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_IMAGE} - * {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_VOICE} - * {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_MUSIC} - * {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_VIDEO} - * {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_NEWS} - * {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_MPNEWS} + * {@link WxConsts.KefuMsgType#TEXT} + * {@link WxConsts.KefuMsgType#IMAGE} + * {@link WxConsts.KefuMsgType#VOICE} + * {@link WxConsts.KefuMsgType#MUSIC} + * {@link WxConsts.KefuMsgType#VIDEO} + * {@link WxConsts.KefuMsgType#NEWS} + * {@link WxConsts.KefuMsgType#MPNEWS} ** * @param msgType 消息类型 @@ -152,87 +113,8 @@ public void setMsgType(String msgType) { this.msgType = msgType; } - public String getSafe() { - return this.safe; - } - - public void setSafe(String safe) { - this.safe = safe; - } - - public String getContent() { - return this.content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getMediaId() { - return this.mediaId; - } - - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - - public String getThumbMediaId() { - return this.thumbMediaId; - } - - public void setThumbMediaId(String thumbMediaId) { - this.thumbMediaId = thumbMediaId; - } - - public String getTitle() { - return this.title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return this.description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getMusicUrl() { - return this.musicUrl; - } - - public void setMusicUrl(String musicUrl) { - this.musicUrl = musicUrl; - } - - public String getHqMusicUrl() { - return this.hqMusicUrl; - } - - public void setHqMusicUrl(String hqMusicUrl) { - this.hqMusicUrl = hqMusicUrl; - } - - public ListgetArticles() { - return this.articles; - } - - public void setArticles(List articles) { - this.articles = articles; - } - public String toJson() { return WxCpGsonBuilder.INSTANCE.create().toJson(this); } - public String getUrl() { - return this.url; - } - - public void setUrl(String url) { - this.url = url; - } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessageSendResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessageSendResult.java index 6989c4988f..9d0a85b6b9 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessageSendResult.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessageSendResult.java @@ -1,25 +1,31 @@ package me.chanjar.weixin.cp.bean; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + import com.google.common.base.Splitter; import com.google.gson.annotations.SerializedName; -import me.chanjar.weixin.common.util.ToStringUtils; +import lombok.Data; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; -import org.apache.commons.lang3.StringUtils; - -import java.util.Collections; -import java.util.List; /** - * - * 消息发送结果对象类 + * 消息发送结果对象类. * Created by Binary Wang on 2017-6-22. + * * @author Binary Wang - **/ -public class WxCpMessageSendResult { +@Data +public class WxCpMessageSendResult implements Serializable { + private static final long serialVersionUID = 916455987193190004L; + @Override public String toString() { - return ToStringUtils.toSimpleString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } public static WxCpMessageSendResult fromJson(String json) { @@ -41,52 +47,13 @@ public static WxCpMessageSendResult fromJson(String json) { @SerializedName("invalidtag") private String invalidTag; - public Integer getErrCode() { - return this.errCode; - } - - public void setErrCode(Integer errCode) { - this.errCode = errCode; - } - - public String getErrMsg() { - return this.errMsg; - } - - public void setErrMsg(String errMsg) { - this.errMsg = errMsg; - } - - public String getInvalidUser() { - return this.invalidUser; - } - - public void setInvalidUser(String invalidUser) { - this.invalidUser = invalidUser; - } - - public String getInvalidParty() { - return this.invalidParty; - } - - public void setInvalidParty(String invalidParty) { - this.invalidParty = invalidParty; - } - - public String getInvalidTag() { - return this.invalidTag; - } - - public void setInvalidTag(String invalidTag) { - this.invalidTag = invalidTag; - } public ListgetInvalidUserList() { return this.content2List(this.invalidUser); } private List content2List(String content) { - if(StringUtils.isBlank(content)){ + if (StringUtils.isBlank(content)) { return Collections.emptyList(); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTag.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTag.java index 79ec3f1321..360ddd28be 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTag.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTag.java @@ -1,50 +1,30 @@ package me.chanjar.weixin.cp.bean; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; import java.io.Serializable; /** - * Created by Daniel Qian + * Created by Daniel Qian. */ +@Data +@AllArgsConstructor +@NoArgsConstructor public class WxCpTag implements Serializable { - private static final long serialVersionUID = -7243320279646928402L; private String id; private String name; - public WxCpTag() { - super(); - } - - public WxCpTag(String id, String name) { - super(); - this.id = id; - this.name = name; - } public static WxCpTag fromJson(String json) { return WxCpGsonBuilder.create().fromJson(json, WxCpTag.class); } - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getId() { - return this.id; - } - - public void setId(String id) { - this.id = id; - } - public String toJson() { return WxCpGsonBuilder.create().toJson(this); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTagAddOrRemoveUsersResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTagAddOrRemoveUsersResult.java index c216ae46a6..67d90978ba 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTagAddOrRemoveUsersResult.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTagAddOrRemoveUsersResult.java @@ -1,25 +1,31 @@ package me.chanjar.weixin.cp.bean; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + import com.google.common.base.Splitter; import com.google.gson.annotations.SerializedName; -import me.chanjar.weixin.common.util.ToStringUtils; +import lombok.Data; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; -import org.apache.commons.lang3.StringUtils; - -import java.util.Collections; -import java.util.List; /** - * - * 为标签添加或移除用户结果对象类 + * 为标签添加或移除用户结果对象类. * Created by Binary Wang on 2017-6-22. + * * @author Binary Wang - **/ -public class WxCpTagAddOrRemoveUsersResult { +@Data +public class WxCpTagAddOrRemoveUsersResult implements Serializable { + private static final long serialVersionUID = 1420065684270213578L; + @Override public String toString() { - return ToStringUtils.toSimpleString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } public static WxCpTagAddOrRemoveUsersResult fromJson(String json) { @@ -38,44 +44,12 @@ public static WxCpTagAddOrRemoveUsersResult fromJson(String json) { @SerializedName("invalidparty") private String[] invalidParty; - public Integer getErrCode() { - return this.errCode; - } - - public void setErrCode(Integer errCode) { - this.errCode = errCode; - } - - public String getErrMsg() { - return this.errMsg; - } - - public void setErrMsg(String errMsg) { - this.errMsg = errMsg; - } - - public String getInvalidUser() { - return this.invalidUsers; - } - - public void setInvalidUser(String invalidUser) { - this.invalidUsers = invalidUser; - } - - public String[] getInvalidParty() { - return this.invalidParty; - } - - public void setInvalidParty(String[] invalidParty) { - this.invalidParty = invalidParty; - } - public ListgetInvalidUserList() { return this.content2List(this.invalidUsers); } private List content2List(String content) { - if(StringUtils.isBlank(content)){ + if (StringUtils.isBlank(content)) { return Collections.emptyList(); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTagGetResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTagGetResult.java new file mode 100644 index 0000000000..28cc4807a1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTagGetResult.java @@ -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; + +/** + * + * 管理企业号应用-测试 + * Created by huansinho on 2018/4/16. + *+ * + * @author huansinho + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class WxCpTagGetResult implements Serializable { + + @SerializedName("errcode") + private Integer errcode; + + @SerializedName("errmsg") + private String errmsg; + + /** + * 用户列表 + */ + @SerializedName("userlist") + private Listuserlist; + + /** + * 部门列表 + */ + @SerializedName("partylist") + private List 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); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java index 647a4e6ba2..f3d5aa2282 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java @@ -1,50 +1,22 @@ package me.chanjar.weixin.cp.bean; -import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; - import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + /** - * 微信用户信息 + * 微信用户信息. * * @author Daniel Qian */ +@Data public class WxCpUser implements Serializable { - - public enum Gender { - MALE("男", "1"), - FEMAIL("女", "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.FEMAIL; - } - - return null; - } - } - private static final long serialVersionUID = -5696099236344075582L; private String userId; private String name; @@ -54,6 +26,7 @@ public static Gender fromCode(String code) { private Gender gender; private String email; private String avatar; + private String avatarMediaId; private Integer status; private Integer enable; private Integer isLeader; @@ -61,160 +34,69 @@ public static Gender fromCode(String code) { private Integer hideMobile; private String englishName; private String telephone; + private String qrCode; + private Boolean toInvite; + /** + * 成员对外信息. + */ + private List externalAttrs = new ArrayList<>(); - public static WxCpUser fromJson(String json) { - return WxCpGsonBuilder.INSTANCE.create().fromJson(json, WxCpUser.class); - } - - public String getUserId() { - return this.userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer[] getDepartIds() { - return this.departIds; - } - - public void setDepartIds(Integer[] departIds) { - this.departIds = departIds; - } - - public Gender getGender() { - return this.gender; - } - - public void setGender(Gender gender) { - this.gender = gender; - } - - public String getPosition() { - return this.position; - } - - public void setPosition(String position) { - this.position = position; - } - - public String getMobile() { - return this.mobile; - } - - public void setMobile(String mobile) { - this.mobile = mobile; - } - - public String getTelephone() { - return this.telephone; - } - - public void setTelephone(String telephone) { - this.telephone = telephone; - } - - public String getEmail() { - return this.email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getAvatar() { - return this.avatar; - } - - public void setAvatar(String avatar) { - this.avatar = avatar; - } - - public Integer getStatus() { - return this.status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public Integer getEnable() { - return this.enable; - } - - public void setEnable(Integer enable) { - this.enable = enable; + public void addExternalAttr(ExternalAttribute externalAttr) { + this.externalAttrs.add(externalAttr); } public void addExtAttr(String name, String value) { this.extAttrs.add(new Attr(name, value)); } - public List getExtAttrs() { - return this.extAttrs; - } - - public Integer getIsLeader() { - return isLeader; - } - - public void setIsLeader(Integer isLeader) { - this.isLeader = isLeader; - } - - public Integer getHideMobile() { - return hideMobile; - } - - public void setHideMobile(Integer hideMobile) { - this.hideMobile = hideMobile; - } - - public String getEnglishName() { - return englishName; - } - - public void setEnglishName(String englishName) { - this.englishName = englishName; + public static WxCpUser fromJson(String json) { + return WxCpGsonBuilder.INSTANCE.create().fromJson(json, WxCpUser.class); } public String toJson() { return WxCpGsonBuilder.INSTANCE.create().toJson(this); } + @Data + @AllArgsConstructor public static class Attr { private String name; private String value; - - public Attr(String name, String value) { - this.name = name; - this.value = value; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - } + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ExternalAttribute { + /** + * 属性类型: 0-本文 1-网页 2-小程序. + */ + private int type; + /** + * 属性名称: 需要先确保在管理端有创建改属性,否则会忽略. + */ + private String name; + /** + * 文本属性内容,长度限制12个UTF8字符. + */ + private String value; + /** + * 网页的url,必须包含http或者https头. + */ + private String url; + /** + * 小程序的展示标题,长度限制12个UTF8字符. + * 或者 网页的展示标题,长度限制12个UTF8字符 + */ + private String title; + /** + * 小程序appid,必须是有在本企业安装授权的小程序,否则会被忽略. + */ + private String appid; + /** + * 小程序的页面路径. + */ + private String pagePath; + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserDetail.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserDetail.java new file mode 100644 index 0000000000..1d40e94ae0 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserDetail.java @@ -0,0 +1,54 @@ +package me.chanjar.weixin.cp.bean; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +/** + * + * 使用user_ticket获取成员详情接口返回类. + * Created by BinaryWang on 2018/4/22. + *+ * + * @author Binary Wang + */ +@Data +public class WxCpUserDetail { + + /** + * 成员UserID + */ + @SerializedName("userid") + private String userId; + + /** + * 成员姓名 + */ + private String name; + + /** + * 成员手机号,仅在用户同意snsapi_privateinfo授权时返回 + */ + private String mobile; + + /** + * 性别。0表示未定义,1表示男性,2表示女性 + */ + private String gender; + + /** + * 成员邮箱,仅在用户同意snsapi_privateinfo授权时返回 + */ + private String email; + + /** + * 头像url。注:如果要获取小图将url最后的”/0”改成”/100”即可。仅在用户同意snsapi_privateinfo授权时返回 + */ + private String avatar; + + /** + * 员工个人二维码(扫描可添加为外部联系人),仅在用户同意snsapi_privateinfo授权时返回 + */ + @SerializedName("qr_code") + private String qrCode; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfo.java new file mode 100644 index 0000000000..466eac4a6e --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfo.java @@ -0,0 +1,126 @@ +package me.chanjar.weixin.cp.bean; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + *+ * 外部联系人详情 + * Created by Binary Wang on 2018/9/16. + * 参考文档:https://work.weixin.qq.com/api/doc#13878 + *+ * + * @author Binary Wang + */ +@Getter +@Setter +public class WxCpUserExternalContactInfo { + @SerializedName("external_contact") + private ExternalContact externalContact; + + @SerializedName("follow_user") + private ListfollowedUsers; + + @Getter + @Setter + public static class ExternalContact { + @SerializedName("external_userid") + private String externalUserId; + + @SerializedName("position") + private String position; + + @SerializedName("name") + private String name; + + @SerializedName("avatar") + private String avatar; + + @SerializedName("corp_name") + private String corpName; + + @SerializedName("corp_full_name") + private String corpFullName; + + @SerializedName("type") + private Integer type; + + @SerializedName("gender") + private Integer gender; + + @SerializedName("unionid") + private String unionId; + + @SerializedName("external_profile") + private ExternalProfile externalProfile; + } + + @Setter + @Getter + public static class ExternalProfile { + @SerializedName("external_attr") + private List externalAttrs; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ExternalAttribute { + @Setter + @Getter + public static class Text { + private String value; + } + + @Setter + @Getter + public static class Web { + private String title; + private String url; + } + + @Setter + @Getter + public static class MiniProgram { + @SerializedName("pagepath") + private String pagePath; + private String appid; + private String title; + } + + private int type; + + private String name; + + private Text text; + + private Web web; + + @SerializedName("miniprogram") + private MiniProgram miniProgram; + } + + @Setter + @Getter + public static class FollowedUser { + @SerializedName("userid") + private String userId; + private String remark; + private String description; + @SerializedName("createtime") + private Long createTime; + } + + public static WxCpUserExternalContactInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalContactInfo.class); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java index 117cf4115b..abb880d2e8 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java @@ -1,30 +1,37 @@ package me.chanjar.weixin.cp.bean; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; import me.chanjar.weixin.cp.config.WxCpConfigStorage; import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; import me.chanjar.weixin.cp.util.xml.XStreamTransformer; -import org.apache.commons.io.IOUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; /** * * 微信推送过来的消息,也是同步回复给用户的消息,xml格式 * 相关字段的解释看微信开发者文档: - * http://mp.weixin.qq.com/wiki/index.php?title=接收普通消息 - * http://mp.weixin.qq.com/wiki/index.php?title=接收事件推送 - * http://mp.weixin.qq.com/wiki/index.php?title=接收语音识别结果 + * https://work.weixin.qq.com/api/doc#12973 + * https://work.weixin.qq.com/api/doc#12974 ** * @author Daniel Qian */ +@Data +@Slf4j @XStreamAlias("xml") public class WxCpXmlMessage implements Serializable { private static final long serialVersionUID = -1042994982179476410L; @@ -47,6 +54,24 @@ public class WxCpXmlMessage implements Serializable { @XStreamAlias("CreateTime") private Long createTime; + /** + *+ * 当接受用户消息时,可能会获得以下值: + * {@link WxConsts.XmlMsgType#TEXT} + * {@link WxConsts.XmlMsgType#IMAGE} + * {@link WxConsts.XmlMsgType#VOICE} + * {@link WxConsts.XmlMsgType#VIDEO} + * {@link WxConsts.XmlMsgType#LOCATION} + * {@link WxConsts.XmlMsgType#LINK} + * {@link WxConsts.XmlMsgType#EVENT} + * 当发送消息的时候使用: + * {@link WxConsts.XmlMsgType#TEXT} + * {@link WxConsts.XmlMsgType#IMAGE} + * {@link WxConsts.XmlMsgType#VOICE} + * {@link WxConsts.XmlMsgType#VIDEO} + * {@link WxConsts.XmlMsgType#NEWS} + *+ */ @XStreamAlias("MsgType") @XStreamConverter(value = XStreamCDataConverter.class) private String msgType; @@ -124,32 +149,190 @@ public class WxCpXmlMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private String recognition; + /** + * 通讯录变更事件. + * 请参考常量 me.chanjar.weixin.cp.WxCpConsts.ContactChangeType + */ + @XStreamAlias("ChangeType") + @XStreamConverter(value = XStreamCDataConverter.class) + private String changeType; + + /** + * 变更信息的成员UserID. + */ + @XStreamAlias("UserID") + @XStreamConverter(value = XStreamCDataConverter.class) + private String userId; + + /** + * 新的UserID,变更时推送(userid由系统生成时可更改一次). + */ + @XStreamAlias("NewUserID") + @XStreamConverter(value = XStreamCDataConverter.class) + private String newUserId; + + /** + * 成员名称. + * 或者部门名称 + */ + @XStreamAlias("Name") + @XStreamConverter(value = XStreamCDataConverter.class) + private String name; + + /** + * 成员部门列表. + */ + @XStreamAlias("Department") + @XStreamConverter(value = XStreamCDataConverter.class) + private String department; + + /** + * 手机号码. + */ + @XStreamAlias("Mobile") + @XStreamConverter(value = XStreamCDataConverter.class) + private String mobile; + + /** + * 职位信息。长度为0~64个字节. + */ + @XStreamAlias("Position") + @XStreamConverter(value = XStreamCDataConverter.class) + private String position; + + /** + * 性别,1表示男性,2表示女性. + */ + @XStreamAlias("Gender") + private Integer gender; + + /** + * 邮箱. + */ + @XStreamAlias("Email") + @XStreamConverter(value = XStreamCDataConverter.class) + private String email; + + /** + * 头像url。注:如果要获取小图将url最后的”/0”改成”/100”即可. + */ + @XStreamAlias("Avatar") + @XStreamConverter(value = XStreamCDataConverter.class) + private String avatar; + + /** + * 英文名. + */ + @XStreamAlias("EnglishName") + @XStreamConverter(value = XStreamCDataConverter.class) + private String englishName; + + /** + * 上级字段,标识是否为上级。0表示普通成员,1表示上级. + */ + @XStreamAlias("IsLeader") + private Integer isLeader; + + /** + * 座机. + */ + @XStreamAlias("Telephone") + @XStreamConverter(value = XStreamCDataConverter.class) + private String telephone; + + /** + * 扩展属性. + */ + @XStreamAlias("ExtAttr") + private ExtAttr extAttrs = new ExtAttr(); + + /** + * 部门Id. + */ + @XStreamAlias("Id") + private Integer id; + + /** + * 父部门id. + */ + @XStreamAlias("ParentId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String parentId; + + /** + * 部门排序. + */ + @XStreamAlias("Order") + @XStreamConverter(value = XStreamCDataConverter.class) + private String order; + + /** + * 标签Id. + */ + @XStreamAlias("TagId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String tagId; + + /** + * 标签中新增的成员userid列表,用逗号分隔. + */ + @XStreamAlias("AddUserItems") + @XStreamConverter(value = XStreamCDataConverter.class) + private String addUserItems; + + /** + * 标签中删除的成员userid列表,用逗号分隔. + */ + @XStreamAlias("DelUserItems") + @XStreamConverter(value = XStreamCDataConverter.class) + private String delUserItems; + + /** + * 标签中新增的部门id列表,用逗号分隔. + */ + @XStreamAlias("AddPartyItems") + @XStreamConverter(value = XStreamCDataConverter.class) + private String addPartyItems; + + /** + * 标签中删除的部门id列表,用逗号分隔. + */ + @XStreamAlias("DelPartyItems") + @XStreamConverter(value = XStreamCDataConverter.class) + private String delPartyItems; + + /////////////////////////////////////// // 群发消息返回的结果 /////////////////////////////////////// /** - * 群发的结果 + * 多个时间共用字段. + * 1. 群发的结果. + * 2. 通讯录变更事件 + * 激活状态:1=已激活 2=已禁用 4=未激活 已激活代表已激活企业微信或已关注微工作台(原企业号). */ @XStreamAlias("Status") @XStreamConverter(value = XStreamCDataConverter.class) private String status; + /** - * group_id下粉丝数;或者openid_list中的粉丝数 + * group_id下粉丝数;或者openid_list中的粉丝数. */ @XStreamAlias("TotalCount") private Integer totalCount; /** - * 过滤(过滤是指特定地区、性别的过滤、用户设置拒收的过滤,用户接收已超4条的过滤)后,准备发送的粉丝数,原则上,filterCount = sentCount + errorCount + * 过滤. + * (过滤是指特定地区、性别的过滤、用户设置拒收的过滤,用户接收已超4条的过滤)后,准备发送的粉丝数,原则上,filterCount = sentCount + errorCount */ @XStreamAlias("FilterCount") private Integer filterCount; /** - * 发送成功的粉丝数 + * 发送成功的粉丝数. */ @XStreamAlias("SentCount") private Integer sentCount; /** - * 发送失败的粉丝数 + * 发送失败的粉丝数. */ @XStreamAlias("ErrorCount") private Integer errorCount; @@ -174,27 +357,18 @@ protected static WxCpXmlMessage fromXml(InputStream is) { } /** - * 从加密字符串转换 - * - * @param encryptedXml - * @param wxCpConfigStorage - * @param timestamp - * @param nonce - * @param msgSignature + * 从加密字符串转换. */ - public static WxCpXmlMessage fromEncryptedXml( - String encryptedXml, - WxCpConfigStorage wxCpConfigStorage, - String timestamp, String nonce, String msgSignature) { + public static WxCpXmlMessage fromEncryptedXml(String encryptedXml, WxCpConfigStorage wxCpConfigStorage, + String timestamp, String nonce, String msgSignature) { WxCpCryptUtil cryptUtil = new WxCpCryptUtil(wxCpConfigStorage); String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce, encryptedXml); + log.debug("解密后的原始xml消息内容:{}", plainText); return fromXml(plainText); } - public static WxCpXmlMessage fromEncryptedXml( - InputStream is, - WxCpConfigStorage wxCpConfigStorage, - String timestamp, String nonce, String msgSignature) { + public static WxCpXmlMessage fromEncryptedXml(InputStream is, WxCpConfigStorage wxCpConfigStorage, + String timestamp, String nonce, String msgSignature) { try { return fromEncryptedXml(IOUtils.toString(is, "UTF-8"), wxCpConfigStorage, timestamp, nonce, msgSignature); } catch (IOException e) { @@ -202,406 +376,66 @@ public static WxCpXmlMessage fromEncryptedXml( } } - public Integer getAgentId() { - return this.agentId; - } - - public void setAgentId(Integer agentId) { - this.agentId = agentId; - } - - public String getToUserName() { - return this.toUserName; - } - - public void setToUserName(String toUserName) { - this.toUserName = toUserName; - } - - public Long getCreateTime() { - return this.createTime; - } - - public void setCreateTime(Long createTime) { - this.createTime = createTime; - } - - /** - *- * 当接受用户消息时,可能会获得以下值: - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_TEXT} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_IMAGE} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_VOICE} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_VIDEO} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_LOCATION} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_LINK} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_EVENT} - *- */ - public String getMsgType() { - return this.msgType; - } - - /** - *- * 当发送消息的时候使用: - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_TEXT} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_IMAGE} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_VOICE} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_VIDEO} - * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_NEWS} - *- * - * @param msgType - */ - public void setMsgType(String msgType) { - this.msgType = msgType; - } - - public String getContent() { - return this.content; - } - - public void setContent(String content) { - this.content = content; - } - - public Long getMsgId() { - return this.msgId; - } - - public void setMsgId(Long msgId) { - this.msgId = msgId; - } - - public String getPicUrl() { - return this.picUrl; - } - - public void setPicUrl(String picUrl) { - this.picUrl = picUrl; - } - - public String getMediaId() { - return this.mediaId; - } - - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - - public String getFormat() { - return this.format; - } - - public void setFormat(String format) { - this.format = format; - } - - public String getThumbMediaId() { - return this.thumbMediaId; - } - - public void setThumbMediaId(String thumbMediaId) { - this.thumbMediaId = thumbMediaId; - } - - public Double getLocationX() { - return this.locationX; - } - - public void setLocationX(Double locationX) { - this.locationX = locationX; - } - - public Double getLocationY() { - return this.locationY; - } - - public void setLocationY(Double locationY) { - this.locationY = locationY; - } - - public Double getScale() { - return this.scale; - } - - public void setScale(Double scale) { - this.scale = scale; - } - - public String getLabel() { - return this.label; - } - - public void setLabel(String label) { - this.label = label; - } - - public String getTitle() { - return this.title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return this.description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getUrl() { - return this.url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getEvent() { - return this.event; - } - - public void setEvent(String event) { - this.event = event; - } - - public String getEventKey() { - return this.eventKey; - } - - public void setEventKey(String eventKey) { - this.eventKey = eventKey; - } - - public String getTicket() { - return this.ticket; - } - - public void setTicket(String ticket) { - this.ticket = ticket; - } - - public Double getLatitude() { - return this.latitude; - } - - public void setLatitude(Double latitude) { - this.latitude = latitude; - } - - public Double getLongitude() { - return this.longitude; - } - - public void setLongitude(Double longitude) { - this.longitude = longitude; - } - - public Double getPrecision() { - return this.precision; - } - - public void setPrecision(Double precision) { - this.precision = precision; - } - - public String getRecognition() { - return this.recognition; - } - - public void setRecognition(String recognition) { - this.recognition = recognition; - } - - public String getFromUserName() { - return this.fromUserName; - } - - public void setFromUserName(String fromUserName) { - this.fromUserName = fromUserName; - } - - public String getStatus() { - return this.status; - } - - public void setStatus(String status) { - this.status = status; - } - - public Integer getTotalCount() { - return this.totalCount; - } - - public void setTotalCount(Integer totalCount) { - this.totalCount = totalCount; - } - - public Integer getFilterCount() { - return this.filterCount; - } - - public void setFilterCount(Integer filterCount) { - this.filterCount = filterCount; - } - - public Integer getSentCount() { - return this.sentCount; - } - - public void setSentCount(Integer sentCount) { - this.sentCount = sentCount; - } - - public Integer getErrorCount() { - return this.errorCount; - } - - public void setErrorCount(Integer errorCount) { - this.errorCount = errorCount; - } - - public WxCpXmlMessage.ScanCodeInfo getScanCodeInfo() { - return this.scanCodeInfo; - } - - public void setScanCodeInfo(WxCpXmlMessage.ScanCodeInfo scanCodeInfo) { - this.scanCodeInfo = scanCodeInfo; - } - - public WxCpXmlMessage.SendPicsInfo getSendPicsInfo() { - return this.sendPicsInfo; - } - - public void setSendPicsInfo(WxCpXmlMessage.SendPicsInfo sendPicsInfo) { - this.sendPicsInfo = sendPicsInfo; - } - - public WxCpXmlMessage.SendLocationInfo getSendLocationInfo() { - return this.sendLocationInfo; - } - - public void setSendLocationInfo(WxCpXmlMessage.SendLocationInfo sendLocationInfo) { - this.sendLocationInfo = sendLocationInfo; - } - @Override public String toString() { - return "WxCpXmlMessage{" + - "agentId=" + this.agentId + - ", toUserName='" + this.toUserName + '\'' + - ", fromUserName='" + this.fromUserName + '\'' + - ", createTime=" + this.createTime + - ", msgType='" + this.msgType + '\'' + - ", content='" + this.content + '\'' + - ", msgId=" + this.msgId + - ", picUrl='" + this.picUrl + '\'' + - ", mediaId='" + this.mediaId + '\'' + - ", format='" + this.format + '\'' + - ", thumbMediaId='" + this.thumbMediaId + '\'' + - ", locationX=" + this.locationX + - ", locationY=" + this.locationY + - ", scale=" + this.scale + - ", label='" + this.label + '\'' + - ", title='" + this.title + '\'' + - ", description='" + this.description + '\'' + - ", url='" + this.url + '\'' + - ", event='" + this.event + '\'' + - ", eventKey='" + this.eventKey + '\'' + - ", ticket='" + this.ticket + '\'' + - ", latitude=" + this.latitude + - ", longitude=" + this.longitude + - ", precision=" + this.precision + - ", recognition='" + this.recognition + '\'' + - ", status='" + this.status + '\'' + - ", totalCount=" + this.totalCount + - ", filterCount=" + this.filterCount + - ", sentCount=" + this.sentCount + - ", errorCount=" + this.errorCount + - ", scanCodeInfo=" + this.scanCodeInfo + - ", sendPicsInfo=" + this.sendPicsInfo + - ", sendLocationInfo=" + this.sendLocationInfo + - '}'; + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } + @Data @XStreamAlias("ScanCodeInfo") public static class ScanCodeInfo { + /** + * 扫描类型,一般是qrcode. + */ @XStreamAlias("ScanType") @XStreamConverter(value = XStreamCDataConverter.class) private String scanType; + /** + * 扫描结果,即二维码对应的字符串信息. + */ @XStreamAlias("ScanResult") @XStreamConverter(value = XStreamCDataConverter.class) private String scanResult; + } - /** - * 扫描类型,一般是qrcode - */ - public String getScanType() { - - return this.scanType; - } - - public void setScanType(String scanType) { - this.scanType = scanType; - } + @Data + public static class ExtAttr { + @XStreamAlias("Item") + protected final List- items = new ArrayList<>(); - /** - * 扫描结果,即二维码对应的字符串信息 - */ - public String getScanResult() { - return this.scanResult; - } + @Data + public static class Item { + @XStreamAlias("Name") + @XStreamConverter(value = XStreamCDataConverter.class) + private String name; - public void setScanResult(String scanResult) { - this.scanResult = scanResult; + @XStreamAlias("Value") + @XStreamConverter(value = XStreamCDataConverter.class) + private String value; } - } + @Data @XStreamAlias("SendPicsInfo") public static class SendPicsInfo { - @XStreamAlias("PicList") protected final List
- picList = new ArrayList<>(); + @XStreamAlias("Count") private Long count; - public Long getCount() { - return this.count; - } - - public void setCount(Long count) { - this.count = count; - } - - public List
- getPicList() { - return this.picList; - } - @XStreamAlias("item") + @Data public static class Item { - @XStreamAlias("PicMd5Sum") @XStreamConverter(value = XStreamCDataConverter.class) - private String PicMd5Sum; - - public String getPicMd5Sum() { - return this.PicMd5Sum; - } - - public void setPicMd5Sum(String picMd5Sum) { - this.PicMd5Sum = picMd5Sum; - } + private String picMd5Sum; } } + @Data @XStreamAlias("SendLocationInfo") public static class SendLocationInfo { @@ -623,47 +457,8 @@ public static class SendLocationInfo { @XStreamAlias("Poiname") @XStreamConverter(value = XStreamCDataConverter.class) - private String poiname; + private String poiName; - public String getLocationX() { - return this.locationX; - } - - public void setLocationX(String locationX) { - this.locationX = locationX; - } - - public String getLocationY() { - return this.locationY; - } - - public void setLocationY(String locationY) { - this.locationY = locationY; - } - - public String getScale() { - return this.scale; - } - - public void setScale(String scale) { - this.scale = scale; - } - - public String getLabel() { - return this.label; - } - - public void setLabel(String label) { - this.label = label; - } - - public String getPoiname() { - return this.poiname; - } - - public void setPoiname(String poiname) { - this.poiname = poiname; - } } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java index 2ddb78afc9..cbef3f8766 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java @@ -2,10 +2,14 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; +import lombok.Data; +import lombok.EqualsAndHashCode; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter; @XStreamAlias("xml") +@Data +@EqualsAndHashCode(callSuper = false) public class WxCpXmlOutImageMessage extends WxCpXmlOutMessage { private static final long serialVersionUID = -1099446240667237313L; @@ -14,15 +18,7 @@ public class WxCpXmlOutImageMessage extends WxCpXmlOutMessage { private String mediaId; public WxCpXmlOutImageMessage() { - this.msgType = WxConsts.XML_MSG_IMAGE; - } - - public String getMediaId() { - return this.mediaId; - } - - public void setMediaId(String mediaId) { - this.mediaId = mediaId; + this.msgType = WxConsts.XmlMsgType.IMAGE; } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutMessage.java index d69703502f..a053a5460e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutMessage.java @@ -1,18 +1,29 @@ package me.chanjar.weixin.cp.bean; +import java.io.Serializable; + import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; +import lombok.Data; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; +import me.chanjar.weixin.cp.bean.outxmlbuilder.ImageBuilder; +import me.chanjar.weixin.cp.bean.outxmlbuilder.NewsBuilder; +import me.chanjar.weixin.cp.bean.outxmlbuilder.TextBuilder; +import me.chanjar.weixin.cp.bean.outxmlbuilder.VideoBuilder; +import me.chanjar.weixin.cp.bean.outxmlbuilder.VoiceBuilder; import me.chanjar.weixin.cp.config.WxCpConfigStorage; -import me.chanjar.weixin.cp.bean.outxmlbuilder.*; import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; import me.chanjar.weixin.cp.util.xml.XStreamTransformer; -import java.io.Serializable; - +/** + * 被动回复消息. + * https://work.weixin.qq.com/api/doc#12975 + * + * @author Daniel Qian + */ @XStreamAlias("xml") +@Data public abstract class WxCpXmlOutMessage implements Serializable { - private static final long serialVersionUID = 1418629839964153110L; @XStreamAlias("ToUserName") @@ -31,78 +42,46 @@ public abstract class WxCpXmlOutMessage implements Serializable { protected String msgType; /** - * 获得文本消息builder + * 获得文本消息builder. */ public static TextBuilder TEXT() { return new TextBuilder(); } /** - * 获得图片消息builder + * 获得图片消息builder. */ public static ImageBuilder IMAGE() { return new ImageBuilder(); } /** - * 获得语音消息builder + * 获得语音消息builder. */ public static VoiceBuilder VOICE() { return new VoiceBuilder(); } /** - * 获得视频消息builder + * 获得视频消息builder. */ public static VideoBuilder VIDEO() { return new VideoBuilder(); } /** - * 获得图文消息builder + * 获得图文消息builder. */ public static NewsBuilder NEWS() { return new NewsBuilder(); } - public String getToUserName() { - return this.toUserName; - } - - public void setToUserName(String toUserName) { - this.toUserName = toUserName; - } - - public String getFromUserName() { - return this.fromUserName; - } - - public void setFromUserName(String fromUserName) { - this.fromUserName = fromUserName; - } - - public Long getCreateTime() { - return this.createTime; - } - - public void setCreateTime(Long createTime) { - this.createTime = createTime; - } - - public String getMsgType() { - return this.msgType; - } - - public void setMsgType(String msgType) { - this.msgType = msgType; - } - protected String toXml() { return XStreamTransformer.toXml((Class) this.getClass(), this); } /** - * 转换成加密的xml格式 + * 转换成加密的xml格式. */ public String toEncryptedXml(WxCpConfigStorage wxCpConfigStorage) { String plainXml = toXml(); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessage.java index 0997841081..c8149cabfa 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessage.java @@ -2,6 +2,8 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; +import lombok.Data; +import lombok.EqualsAndHashCode; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; @@ -9,84 +11,47 @@ import java.util.List; @XStreamAlias("xml") +@Data +@EqualsAndHashCode(callSuper = true) public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { private static final long serialVersionUID = -5796178637883178826L; @XStreamAlias("Articles") protected final List
- articles = new ArrayList<>(); + @XStreamAlias("ArticleCount") protected int articleCount; public WxCpXmlOutNewsMessage() { - this.msgType = WxConsts.XML_MSG_NEWS; + this.msgType = WxConsts.XmlMsgType.NEWS; } - public int getArticleCount() { - return this.articleCount; - } public void addArticle(Item item) { this.articles.add(item); this.articleCount = this.articles.size(); } - public List
- getArticles() { - return this.articles; - } - - @XStreamAlias("item") + @Data public static class Item { @XStreamAlias("Title") @XStreamConverter(value = XStreamCDataConverter.class) - private String Title; + private String title; @XStreamAlias("Description") @XStreamConverter(value = XStreamCDataConverter.class) - private String Description; + private String description; @XStreamAlias("PicUrl") @XStreamConverter(value = XStreamCDataConverter.class) - private String PicUrl; + private String picUrl; @XStreamAlias("Url") @XStreamConverter(value = XStreamCDataConverter.class) - private String Url; - - public String getTitle() { - return this.Title; - } - - public void setTitle(String title) { - this.Title = title; - } - - public String getDescription() { - return this.Description; - } - - public void setDescription(String description) { - this.Description = description; - } - - public String getPicUrl() { - return this.PicUrl; - } - - public void setPicUrl(String picUrl) { - this.PicUrl = picUrl; - } - - public String getUrl() { - return this.Url; - } - - public void setUrl(String url) { - this.Url = url; - } + private String url; } - } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java index 5f09abf485..6589b0b3b6 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java @@ -2,10 +2,14 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; +import lombok.Data; +import lombok.EqualsAndHashCode; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; @XStreamAlias("xml") +@Data +@EqualsAndHashCode(callSuper = false) public class WxCpXmlOutTextMessage extends WxCpXmlOutMessage { private static final long serialVersionUID = 2569239617185930232L; @@ -14,16 +18,7 @@ public class WxCpXmlOutTextMessage extends WxCpXmlOutMessage { private String content; public WxCpXmlOutTextMessage() { - this.msgType = WxConsts.XML_MSG_TEXT; + this.msgType = WxConsts.XmlMsgType.TEXT; } - public String getContent() { - return this.content; - } - - public void setContent(String content) { - this.content = content; - } - - } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java index 46dae31c3f..f4aabd182b 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java @@ -2,10 +2,14 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; +import lombok.Data; +import lombok.EqualsAndHashCode; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; @XStreamAlias("xml") +@Data +@EqualsAndHashCode(callSuper = false) public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { private static final long serialVersionUID = -8672761162722733622L; @@ -13,7 +17,7 @@ public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { protected final Video video = new Video(); public WxCpXmlOutVideoMessage() { - this.msgType = WxConsts.XML_MSG_VIDEO; + this.msgType = WxConsts.XmlMsgType.VIDEO; } public String getMediaId() { @@ -40,7 +44,7 @@ public void setDescription(String description) { this.video.setDescription(description); } - + @Data @XStreamAlias("Video") public static class Video { @@ -56,30 +60,6 @@ public static class Video { @XStreamConverter(value = XStreamCDataConverter.class) private String description; - public String getMediaId() { - return this.mediaId; - } - - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - - public String getTitle() { - return this.title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return this.description; - } - - public void setDescription(String description) { - this.description = description; - } - } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java index b1827706dd..efe4a86fcf 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java @@ -2,10 +2,14 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; +import lombok.Data; +import lombok.EqualsAndHashCode; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter; @XStreamAlias("xml") +@Data +@EqualsAndHashCode(callSuper = false) public class WxCpXmlOutVoiceMessage extends WxCpXmlOutMessage { private static final long serialVersionUID = -7947384031546099340L; @@ -14,15 +18,7 @@ public class WxCpXmlOutVoiceMessage extends WxCpXmlOutMessage { private String mediaId; public WxCpXmlOutVoiceMessage() { - this.msgType = WxConsts.XML_MSG_VOICE; - } - - public String getMediaId() { - return this.mediaId; - } - - public void setMediaId(String mediaId) { - this.mediaId = mediaId; + this.msgType = WxConsts.XmlMsgType.VOICE; } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/MpnewsArticle.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/MpnewsArticle.java index b3f4acf402..af622fefd8 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/MpnewsArticle.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/MpnewsArticle.java @@ -1,5 +1,8 @@ package me.chanjar.weixin.cp.bean.article; +import lombok.Builder; +import lombok.Data; + import java.io.Serializable; /** @@ -9,6 +12,8 @@ * * @author Binary Wang */ +@Data +@Builder(builderMethodName = "newBuilder") public class MpnewsArticle implements Serializable { private static final long serialVersionUID = 6985871812170756481L; @@ -20,125 +25,4 @@ public class MpnewsArticle implements Serializable { private String digest; private String showCoverPic; - private MpnewsArticle(Builder builder) { - setTitle(builder.title); - setThumbMediaId(builder.thumbMediaId); - setAuthor(builder.author); - setContentSourceUrl(builder.contentSourceUrl); - setContent(builder.content); - setDigest(builder.digest); - setShowCoverPic(builder.showCoverPic); - } - - public static Builder newBuilder() { - return new Builder(); - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getThumbMediaId() { - return thumbMediaId; - } - - public void setThumbMediaId(String thumbMediaId) { - this.thumbMediaId = thumbMediaId; - } - - public String getAuthor() { - return author; - } - - public void setAuthor(String author) { - this.author = author; - } - - public String getContentSourceUrl() { - return contentSourceUrl; - } - - public void setContentSourceUrl(String contentSourceUrl) { - this.contentSourceUrl = contentSourceUrl; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getDigest() { - return digest; - } - - public void setDigest(String digest) { - this.digest = digest; - } - - public String getShowCoverPic() { - return showCoverPic; - } - - public void setShowCoverPic(String showCoverPic) { - this.showCoverPic = showCoverPic; - } - - public static final class Builder { - private String title; - private String thumbMediaId; - private String author; - private String contentSourceUrl; - private String content; - private String digest; - private String showCoverPic; - - private Builder() { - } - - public Builder title(String title) { - this.title = title; - return this; - } - - public Builder thumbMediaId(String thumbMediaId) { - this.thumbMediaId = thumbMediaId; - return this; - } - - public Builder author(String author) { - this.author = author; - return this; - } - - public Builder contentSourceUrl(String contentSourceUrl) { - this.contentSourceUrl = contentSourceUrl; - return this; - } - - public Builder content(String content) { - this.content = content; - return this; - } - - public Builder digest(String digest) { - this.digest = digest; - return this; - } - - public Builder showCoverPic(String showCoverPic) { - this.showCoverPic = showCoverPic; - return this; - } - - public MpnewsArticle build() { - return new MpnewsArticle(this); - } - } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/NewArticle.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/NewArticle.java index 02b0b1086f..7f10d363b4 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/NewArticle.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/NewArticle.java @@ -1,5 +1,7 @@ package me.chanjar.weixin.cp.bean.article; +import lombok.Data; + import java.io.Serializable; /** @@ -9,6 +11,7 @@ * * @author Binary Wang */ +@Data public class NewArticle implements Serializable { private static final long serialVersionUID = 4087852055781140659L; @@ -17,36 +20,4 @@ public class NewArticle implements Serializable { private String url; private String picUrl; - public String getTitle() { - return this.title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return this.description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getUrl() { - return this.url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getPicUrl() { - return this.picUrl; - } - - public void setPicUrl(String picUrl) { - this.picUrl = picUrl; - } - } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/BaseBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/BaseBuilder.java index 784de9a769..1064f00526 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/BaseBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/BaseBuilder.java @@ -44,7 +44,7 @@ public WxCpMessage build() { m.setToUser(this.toUser); m.setToParty(this.toParty); m.setToTag(this.toTag); - m.setSafe(StringUtils.defaultIfBlank(this.safe, WxConsts.CUSTOM_MSG_SAFE_NO)); + m.setSafe(StringUtils.defaultIfBlank(this.safe, WxConsts.KefuMsgSafe.NO)); return m; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/FileBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/FileBuilder.java index 1da7816926..f67cf6e50d 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/FileBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/FileBuilder.java @@ -15,7 +15,7 @@ public final class FileBuilder extends BaseBuilder
{ private String mediaId; public FileBuilder() { - this.msgType = WxConsts.CUSTOM_MSG_FILE; + this.msgType = WxConsts.KefuMsgType.FILE; } public FileBuilder mediaId(String media_id) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/ImageBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/ImageBuilder.java index a74f5016e4..ddf3b7373b 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/ImageBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/ImageBuilder.java @@ -15,7 +15,7 @@ public final class ImageBuilder extends BaseBuilder { private String mediaId; public ImageBuilder() { - this.msgType = WxConsts.CUSTOM_MSG_IMAGE; + this.msgType = WxConsts.KefuMsgType.IMAGE; } public ImageBuilder mediaId(String media_id) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/MpnewsBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/MpnewsBuilder.java index 55ed20abab..75739803f4 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/MpnewsBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/MpnewsBuilder.java @@ -23,7 +23,7 @@ public final class MpnewsBuilder extends BaseBuilder { private String mediaId; public MpnewsBuilder() { - this.msgType = WxConsts.CUSTOM_MSG_MPNEWS; + this.msgType = WxConsts.KefuMsgType.MPNEWS; } public MpnewsBuilder mediaId(String mediaId) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/NewsBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/NewsBuilder.java index dd23941244..9d0d2f603a 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/NewsBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/NewsBuilder.java @@ -22,7 +22,7 @@ public final class NewsBuilder extends BaseBuilder { private List articles = new ArrayList<>(); public NewsBuilder() { - this.msgType = WxConsts.CUSTOM_MSG_NEWS; + this.msgType = WxConsts.KefuMsgType.NEWS; } public NewsBuilder addArticle(NewArticle... articles) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TextBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TextBuilder.java index 8c1ee1d014..5079b5f846 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TextBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TextBuilder.java @@ -15,7 +15,7 @@ public final class TextBuilder extends BaseBuilder { private String content; public TextBuilder() { - this.msgType = WxConsts.CUSTOM_MSG_TEXT; + this.msgType = WxConsts.KefuMsgType.TEXT; } public TextBuilder content(String content) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TextCardBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TextCardBuilder.java index a30b9d4059..6cae763d19 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TextCardBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TextCardBuilder.java @@ -16,9 +16,10 @@ public class TextCardBuilder extends BaseBuilder { private String title; private String description; private String url; + private String btnTxt; public TextCardBuilder() { - this.msgType = WxConsts.CUSTOM_MSG_TEXTCARD; + this.msgType = WxConsts.KefuMsgType.TEXTCARD; } public TextCardBuilder title(String title) { @@ -36,12 +37,18 @@ public TextCardBuilder url(String url) { return this; } + public TextCardBuilder btnTxt(String btnTxt) { + this.btnTxt = btnTxt; + return this; + } + @Override public WxCpMessage build() { WxCpMessage m = super.build(); m.setTitle(this.title); m.setDescription(this.description); m.setUrl(this.url); + m.setBtnTxt(this.btnTxt); return m; } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/VideoBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/VideoBuilder.java index 52cba28703..8d47399407 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/VideoBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/VideoBuilder.java @@ -24,7 +24,7 @@ public final class VideoBuilder extends BaseBuilder { private String thumbMediaId; public VideoBuilder() { - this.msgType = WxConsts.CUSTOM_MSG_VIDEO; + this.msgType = WxConsts.KefuMsgType.VIDEO; } public VideoBuilder mediaId(String mediaId) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/VoiceBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/VoiceBuilder.java index 0960fe8f0c..33c36abcbe 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/VoiceBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/VoiceBuilder.java @@ -15,7 +15,7 @@ public final class VoiceBuilder extends BaseBuilder { private String mediaId; public VoiceBuilder() { - this.msgType = WxConsts.CUSTOM_MSG_VOICE; + this.msgType = WxConsts.KefuMsgType.VOICE; } public VoiceBuilder mediaId(String media_id) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java index 03eb8f544a..303ed3c46a 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java @@ -23,7 +23,7 @@ public BuilderType fromUser(String fromusername) { public void setCommon(WxCpXmlOutMessage m) { m.setToUserName(this.toUserName); m.setFromUserName(this.fromUserName); - m.setCreateTime(System.currentTimeMillis() / 1000l); + m.setCreateTime(System.currentTimeMillis() / 1000L); } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java index 1b57f83bf8..707188a27d 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java @@ -1,11 +1,13 @@ package me.chanjar.weixin.cp.config; +import java.io.File; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; -import java.io.File; - /** * 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化 * @@ -63,7 +65,7 @@ public synchronized void updateAccessToken(WxAccessToken accessToken) { @Override public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) { this.accessToken = accessToken; - this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l; + this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; } @Override @@ -92,7 +94,7 @@ public boolean isJsapiTicketExpired() { public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { this.jsapiTicket = jsapiTicket; // 预留200秒的时间 - this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l; + this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; } @Override @@ -201,7 +203,7 @@ public void setHttpProxyPassword(String httpProxyPassword) { @Override public String toString() { - return ToStringUtils.toSimpleString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } @Override diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java index 39b2ae5023..6ae48f0e64 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java @@ -9,18 +9,26 @@ import java.io.File; /** - * Jedis client implementor for wechat config storage + * Jedis client implementor for wechat config storage. + * + * 使用说明:本实现仅供参考,并不完整, + * 比如为减少项目依赖,未加入redis分布式锁的实现,如有需要请自行实现。 + ** * @author gaigeshen */ public class WxCpJedisConfigStorage implements WxCpConfigStorage { - /* Redis keys here */ + /** + * Redis keys here + */ private static final String ACCESS_TOKEN_KEY = "WX_CP_ACCESS_TOKEN"; private static final String ACCESS_TOKEN_EXPIRES_TIME_KEY = "WX_CP_ACCESS_TOKEN_EXPIRES_TIME"; private static final String JS_API_TICKET_KEY = "WX_CP_JS_API_TICKET"; private static final String JS_API_TICKET_EXPIRES_TIME_KEY = "WX_CP_JS_API_TICKET_EXPIRES_TIME"; - /* Redis clients pool */ + /** + * Redis clients pool + */ private final JedisPool jedisPool; private volatile String corpId; private volatile String corpSecret; @@ -35,17 +43,24 @@ public class WxCpJedisConfigStorage implements WxCpConfigStorage { private volatile File tmpDirFile; private volatile ApacheHttpClientBuilder apacheHttpClientBuilder; + public WxCpJedisConfigStorage(JedisPool jedisPool) { + this.jedisPool = jedisPool; + } + public WxCpJedisConfigStorage(String host, int port) { - this.jedisPool = new JedisPool(host, port); + jedisPool = new JedisPool(host, port); } - public WxCpJedisConfigStorage(JedisPoolConfig poolConfig, String host, int port) { - this.jedisPool = new JedisPool(poolConfig, host, port); + jedisPool = new JedisPool(poolConfig, host, port); + } + + public WxCpJedisConfigStorage(JedisPoolConfig poolConfig, String host, int port, int timeout, String password) { + jedisPool = new JedisPool(poolConfig, host, port, timeout, password); } - public WxCpJedisConfigStorage(JedisPoolConfig poolConfig, String host, int port, int timeout, final String password) { - this.jedisPool = new JedisPool(poolConfig, host, port, timeout, password); + public WxCpJedisConfigStorage(JedisPoolConfig poolConfig, String host, int port, int timeout, String password, int database) { + jedisPool = new JedisPool(poolConfig, host, port, timeout, password, database); } /** @@ -192,8 +207,7 @@ public long getExpiresTime() { String expiresTimeStr = jedis.get(ACCESS_TOKEN_EXPIRES_TIME_KEY); if (expiresTimeStr != null) { - Long expiresTime = Long.parseLong(expiresTimeStr); - return expiresTime; + return Long.parseLong(expiresTimeStr); } return 0L; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageHandler.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageHandler.java index 615fa8f220..22074d6e70 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageHandler.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageHandler.java @@ -1,6 +1,6 @@ package me.chanjar.weixin.cp.message; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.WxCpXmlMessage; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageInterceptor.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageInterceptor.java index 21abb5cdb4..ab4c658e4f 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageInterceptor.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageInterceptor.java @@ -1,6 +1,6 @@ package me.chanjar.weixin.cp.message; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.WxCpXmlMessage; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouter.java index 3c53d26106..99e4fd4573 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouter.java @@ -11,6 +11,7 @@ import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.WxCpXmlMessage; import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -215,17 +216,19 @@ public WxCpXmlOutMessage route(final WxCpXmlMessage wxMessage) { } protected boolean isDuplicateMessage(WxCpXmlMessage wxMessage) { - - String messageId = ""; + String messageId; if (wxMessage.getMsgId() == null) { messageId = String.valueOf(wxMessage.getCreateTime()) - + "-" + String.valueOf(wxMessage.getAgentId() == null ? "" : wxMessage.getAgentId()) + + "-" + StringUtils.trimToEmpty(String.valueOf(wxMessage.getAgentId())) + "-" + wxMessage.getFromUserName() - + "-" + String.valueOf(wxMessage.getEventKey() == null ? "" : wxMessage.getEventKey()) - + "-" + String.valueOf(wxMessage.getEvent() == null ? "" : wxMessage.getEvent()) + + "-" + StringUtils.trimToEmpty(wxMessage.getEventKey()) + + "-" + StringUtils.trimToEmpty(wxMessage.getEvent()) ; } else { - messageId = String.valueOf(wxMessage.getMsgId()); + messageId = new StringBuilder().append(wxMessage.getMsgId()) + .append("-").append(wxMessage.getCreateTime()) + .append("-").append(wxMessage.getFromUserName()) + .toString(); } return this.messageDuplicateChecker.isDuplicate(messageId); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouterRule.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouterRule.java index b5912404ce..8f3766a160 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouterRule.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouterRule.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.cp.message; import me.chanjar.weixin.common.api.WxErrorExceptionHandler; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.WxCpXmlMessage; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpDepartGsonAdapter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpDepartGsonAdapter.java index 431c38039b..a5a11d24f4 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpDepartGsonAdapter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpDepartGsonAdapter.java @@ -49,7 +49,7 @@ public WxCpDepart deserialize(JsonElement json, Type typeOfT, JsonDeserializatio depart.setName(GsonHelper.getAsString(departJson.get("name"))); } if (departJson.get("order") != null && !departJson.get("order").isJsonNull()) { - depart.setOrder(GsonHelper.getAsInteger(departJson.get("order"))); + depart.setOrder(GsonHelper.getAsLong(departJson.get("order"))); } if (departJson.get("parentid") != null && !departJson.get("parentid").isJsonNull()) { depart.setParentId(GsonHelper.getAsInteger(departJson.get("parentid"))); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpGsonBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpGsonBuilder.java index 5efee45ce5..f4dc691ea4 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpGsonBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpGsonBuilder.java @@ -3,13 +3,16 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import me.chanjar.weixin.common.bean.menu.WxMenu; -import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.util.json.WxErrorAdapter; import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.WxCpMessage; import me.chanjar.weixin.cp.bean.WxCpTag; import me.chanjar.weixin.cp.bean.WxCpUser; +/** + * @author Daniel Qian + */ public class WxCpGsonBuilder { public static final GsonBuilder INSTANCE = new GsonBuilder(); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpMessageGsonAdapter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpMessageGsonAdapter.java index 67e43c4ccc..7bed435d30 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpMessageGsonAdapter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpMessageGsonAdapter.java @@ -37,33 +37,34 @@ public JsonElement serialize(WxCpMessage message, Type typeOfSrc, JsonSerializat if (StringUtils.isNotBlank(message.getToTag())) { messageJson.addProperty("totag", message.getToTag()); } - if (WxConsts.CUSTOM_MSG_TEXT.equals(message.getMsgType())) { + if (WxConsts.KefuMsgType.TEXT.equals(message.getMsgType())) { JsonObject text = new JsonObject(); text.addProperty("content", message.getContent()); messageJson.add("text", text); } - if (WxConsts.CUSTOM_MSG_TEXTCARD.equals(message.getMsgType())) { + if (WxConsts.KefuMsgType.TEXTCARD.equals(message.getMsgType())) { JsonObject text = new JsonObject(); text.addProperty("title", message.getTitle()); text.addProperty("description", message.getDescription()); text.addProperty("url", message.getUrl()); + text.addProperty("btntxt", message.getBtnTxt()); messageJson.add("textcard", text); } - if (WxConsts.CUSTOM_MSG_IMAGE.equals(message.getMsgType())) { + if (WxConsts.KefuMsgType.IMAGE.equals(message.getMsgType())) { JsonObject image = new JsonObject(); image.addProperty("media_id", message.getMediaId()); messageJson.add("image", image); } - if (WxConsts.CUSTOM_MSG_FILE.equals(message.getMsgType())) { + if (WxConsts.KefuMsgType.FILE.equals(message.getMsgType())) { JsonObject image = new JsonObject(); image.addProperty("media_id", message.getMediaId()); messageJson.add("file", image); } - if (WxConsts.CUSTOM_MSG_VOICE.equals(message.getMsgType())) { + if (WxConsts.KefuMsgType.VOICE.equals(message.getMsgType())) { JsonObject voice = new JsonObject(); voice.addProperty("media_id", message.getMediaId()); messageJson.add("voice", voice); @@ -73,7 +74,7 @@ public JsonElement serialize(WxCpMessage message, Type typeOfSrc, JsonSerializat messageJson.addProperty("safe", message.getSafe()); } - if (WxConsts.CUSTOM_MSG_VIDEO.equals(message.getMsgType())) { + if (WxConsts.KefuMsgType.VIDEO.equals(message.getMsgType())) { JsonObject video = new JsonObject(); video.addProperty("media_id", message.getMediaId()); video.addProperty("thumb_media_id", message.getThumbMediaId()); @@ -82,7 +83,7 @@ public JsonElement serialize(WxCpMessage message, Type typeOfSrc, JsonSerializat messageJson.add("video", video); } - if (WxConsts.CUSTOM_MSG_NEWS.equals(message.getMsgType())) { + if (WxConsts.KefuMsgType.NEWS.equals(message.getMsgType())) { JsonObject newsJsonObject = new JsonObject(); JsonArray articleJsonArray = new JsonArray(); for (NewArticle article : message.getArticles()) { @@ -97,7 +98,7 @@ public JsonElement serialize(WxCpMessage message, Type typeOfSrc, JsonSerializat messageJson.add("news", newsJsonObject); } - if (WxConsts.CUSTOM_MSG_MPNEWS.equals(message.getMsgType())) { + if (WxConsts.KefuMsgType.MPNEWS.equals(message.getMsgType())) { JsonObject newsJsonObject = new JsonObject(); if (message.getMediaId() != null) { newsJsonObject.addProperty("media_id", message.getMediaId()); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java index 6531d07ba9..1dc3f687d5 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java @@ -8,20 +8,30 @@ */ package me.chanjar.weixin.cp.util.json; -import com.google.gson.*; +import java.lang.reflect.Type; + +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.cp.bean.Gender; import me.chanjar.weixin.cp.bean.WxCpUser; -import java.lang.reflect.Type; - /** * @author Daniel Qian */ public class WxCpUserGsonAdapter implements JsonDeserializer, JsonSerializer { + private static final String EXTERNAL_PROFILE = "external_profile"; + private static final String EXTERNAL_ATTR = "external_attr"; @Override - public WxCpUser deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { + public WxCpUser deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject o = json.getAsJsonObject(); WxCpUser user = new WxCpUser(); @@ -39,15 +49,18 @@ public WxCpUser deserialize(JsonElement json, Type typeOfT, JsonDeserializationC user.setName(GsonHelper.getString(o, "name")); user.setPosition(GsonHelper.getString(o, "position")); user.setMobile(GsonHelper.getString(o, "mobile")); - user.setGender(WxCpUser.Gender.fromCode(GsonHelper.getString(o, "gender"))); + user.setGender(Gender.fromCode(GsonHelper.getString(o, "gender"))); user.setEmail(GsonHelper.getString(o, "email")); user.setAvatar(GsonHelper.getString(o, "avatar")); + user.setAvatarMediaId(GsonHelper.getString(o, "avatar_mediaid")); user.setStatus(GsonHelper.getInteger(o, "status")); user.setEnable(GsonHelper.getInteger(o, "enable")); user.setIsLeader(GsonHelper.getInteger(o, "isleader")); user.setHideMobile(GsonHelper.getInteger(o, "hide_mobile")); user.setEnglishName(GsonHelper.getString(o, "english_name")); user.setTelephone(GsonHelper.getString(o, "telephone")); + user.setQrCode(GsonHelper.getString(o, "qr_code")); + user.setToInvite(GsonHelper.getBoolean(o, "to_invite")); if (GsonHelper.isNotNull(o.get("extattr"))) { JsonArray attrJsonElements = o.get("extattr").getAsJsonObject().get("attrs").getAsJsonArray(); @@ -59,6 +72,53 @@ public WxCpUser deserialize(JsonElement json, Type typeOfT, JsonDeserializationC user.getExtAttrs().add(attr); } } + + if (GsonHelper.isNotNull(o.get(EXTERNAL_PROFILE))) { + JsonArray attrJsonElements = o.get(EXTERNAL_PROFILE).getAsJsonObject().get(EXTERNAL_ATTR).getAsJsonArray(); + for (JsonElement element : attrJsonElements) { + final Integer type = GsonHelper.getInteger(element.getAsJsonObject(), "type"); + final String name = GsonHelper.getString(element.getAsJsonObject(), "name"); + + switch (type) { + case 0: { + user.getExternalAttrs() + .add(WxCpUser.ExternalAttribute.builder() + .type(type) + .name(name) + .value(GsonHelper.getString(element.getAsJsonObject().get("text").getAsJsonObject(), "value")) + .build() + ); + break; + } + case 1: { + final JsonObject web = element.getAsJsonObject().get("web").getAsJsonObject(); + user.getExternalAttrs() + .add(WxCpUser.ExternalAttribute.builder() + .type(type) + .name(name) + .url(GsonHelper.getString(web, "url")) + .title(GsonHelper.getString(web, "title")) + .build() + ); + break; + } + case 2: { + final JsonObject miniprogram = element.getAsJsonObject().get("miniprogram").getAsJsonObject(); + user.getExternalAttrs() + .add(WxCpUser.ExternalAttribute.builder() + .type(type) + .name(name) + .appid(GsonHelper.getString(miniprogram, "appid")) + .pagePath(GsonHelper.getString(miniprogram, "pagepath")) + .title(GsonHelper.getString(miniprogram, "title")) + .build() + ); + break; + } + default://ignored + } + } + } return user; } @@ -93,6 +153,9 @@ public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationCon if (user.getAvatar() != null) { o.addProperty("avatar", user.getAvatar()); } + if (user.getAvatarMediaId() != null) { + o.addProperty("avatar_mediaid", user.getAvatarMediaId()); + } if (user.getStatus() != null) { o.addProperty("status", user.getStatus()); } @@ -111,6 +174,13 @@ public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationCon if (user.getTelephone() != null) { o.addProperty("telephone", user.getTelephone()); } + if (user.getQrCode() != null) { + o.addProperty("qr_code", user.getQrCode()); + } + if (user.getToInvite() != null) { + o.addProperty("to_invite", user.getToInvite()); + } + if (user.getExtAttrs().size() > 0) { JsonArray attrsJsonArray = new JsonArray(); for (WxCpUser.Attr attr : user.getExtAttrs()) { @@ -123,6 +193,45 @@ public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationCon attrsJson.add("attrs", attrsJsonArray); o.add("extattr", attrsJson); } + + if (user.getExternalAttrs().size() > 0) { + JsonArray attrsJsonArray = new JsonArray(); + for (WxCpUser.ExternalAttribute attr : user.getExternalAttrs()) { + JsonObject attrJson = new JsonObject(); + attrJson.addProperty("type",attr.getType()); + attrJson.addProperty("name", attr.getName()); + switch (attr.getType()) { + case 0: { + JsonObject text = new JsonObject(); + text.addProperty("value", attr.getValue()); + attrJson.add("text", text); + break; + } + case 1: { + JsonObject web = new JsonObject(); + web.addProperty("url", attr.getUrl()); + web.addProperty("title", attr.getTitle()); + attrJson.add("web", web); + break; + } + case 2: { + JsonObject miniprogram = new JsonObject(); + miniprogram.addProperty("appid", attr.getAppid()); + miniprogram.addProperty("pagepath", attr.getPagePath()); + miniprogram.addProperty("title", attr.getTitle()); + attrJson.add("miniprogram", miniprogram); + break; + } + default://忽略 + } + attrsJsonArray.add(attrJson); + } + + JsonObject attrsJson = new JsonObject(); + attrsJson.add(EXTERNAL_ATTR, attrsJsonArray); + o.add(EXTERNAL_PROFILE, attrsJson); + } + return o; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java index 6b58063062..5ef1503df1 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java @@ -1,13 +1,19 @@ package me.chanjar.weixin.cp.util.xml; -import com.thoughtworks.xstream.XStream; -import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import me.chanjar.weixin.cp.bean.*; - import java.io.InputStream; import java.util.HashMap; import java.util.Map; +import com.thoughtworks.xstream.XStream; +import me.chanjar.weixin.common.util.xml.XStreamInitializer; +import me.chanjar.weixin.cp.bean.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutImageMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutNewsMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutVideoMessage; +import me.chanjar.weixin.cp.bean.WxCpXmlOutVoiceMessage; + public class XStreamTransformer { protected static final Map CLASS_2_XSTREAM_INSTANCE = configXStreamInstance(); @@ -28,7 +34,7 @@ public static T fromXml(Class clazz, InputStream is) { } /** - * 注册扩展消息的解析器 + * 注册扩展消息的解析器. * * @param clz 类型 * @param xStream xml解析器 @@ -38,7 +44,7 @@ public static void register(Class clz, XStream xStream) { } /** - * pojo -> xml + * pojo -> xml. */ public static String toXml(Class clazz, T object) { return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object); @@ -46,17 +52,18 @@ public static String toXml(Class clazz, T object) { private static Map configXStreamInstance() { Map map = new HashMap<>(); - map.put(WxCpXmlMessage.class, config_WxCpXmlMessage()); - map.put(WxCpXmlOutNewsMessage.class, config_WxCpXmlOutNewsMessage()); - map.put(WxCpXmlOutTextMessage.class, config_WxCpXmlOutTextMessage()); - map.put(WxCpXmlOutImageMessage.class, config_WxCpXmlOutImageMessage()); - map.put(WxCpXmlOutVideoMessage.class, config_WxCpXmlOutVideoMessage()); - map.put(WxCpXmlOutVoiceMessage.class, config_WxCpXmlOutVoiceMessage()); + map.put(WxCpXmlMessage.class, configWxCpXmlMessage()); + map.put(WxCpXmlOutNewsMessage.class, configWxCpXmlOutNewsMessage()); + map.put(WxCpXmlOutTextMessage.class, configWxCpXmlOutTextMessage()); + map.put(WxCpXmlOutImageMessage.class, configWxCpXmlOutImageMessage()); + map.put(WxCpXmlOutVideoMessage.class, configWxCpXmlOutVideoMessage()); + map.put(WxCpXmlOutVoiceMessage.class, configWxCpXmlOutVoiceMessage()); return map; } - private static XStream config_WxCpXmlMessage() { + private static XStream configWxCpXmlMessage() { XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(WxCpXmlMessage.class); xstream.processAnnotations(WxCpXmlMessage.ScanCodeInfo.class); xstream.processAnnotations(WxCpXmlMessage.SendPicsInfo.class); @@ -65,38 +72,43 @@ private static XStream config_WxCpXmlMessage() { return xstream; } - private static XStream config_WxCpXmlOutImageMessage() { + private static XStream configWxCpXmlOutImageMessage() { XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(WxCpXmlOutMessage.class); xstream.processAnnotations(WxCpXmlOutImageMessage.class); return xstream; } - private static XStream config_WxCpXmlOutNewsMessage() { + private static XStream configWxCpXmlOutNewsMessage() { XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(WxCpXmlOutMessage.class); xstream.processAnnotations(WxCpXmlOutNewsMessage.class); xstream.processAnnotations(WxCpXmlOutNewsMessage.Item.class); return xstream; } - private static XStream config_WxCpXmlOutTextMessage() { + private static XStream configWxCpXmlOutTextMessage() { XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(WxCpXmlOutMessage.class); xstream.processAnnotations(WxCpXmlOutTextMessage.class); return xstream; } - private static XStream config_WxCpXmlOutVideoMessage() { + private static XStream configWxCpXmlOutVideoMessage() { XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(WxCpXmlOutMessage.class); xstream.processAnnotations(WxCpXmlOutVideoMessage.class); xstream.processAnnotations(WxCpXmlOutVideoMessage.Video.class); return xstream; } - private static XStream config_WxCpXmlOutVoiceMessage() { + private static XStream configWxCpXmlOutVoiceMessage() { XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(WxCpXmlOutMessage.class); xstream.processAnnotations(WxCpXmlOutVoiceMessage.class); return xstream; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java index 179086f739..c87b6455ac 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java @@ -1,20 +1,24 @@ package me.chanjar.weixin.cp.api; +import java.io.IOException; +import java.io.InputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.google.inject.Binder; import com.google.inject.Module; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; -import me.chanjar.weixin.cp.config.WxCpConfigStorage; import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage; -import java.io.IOException; -import java.io.InputStream; - public class ApiTestModule implements Module { + private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final String TEST_CONFIG_XML = "test-config.xml"; - public static T fromXml(Class clazz, InputStream is) { + private static T fromXml(Class clazz, InputStream is) { XStream xstream = XStreamInitializer.getInstance(); xstream.alias("xml", clazz); xstream.processAnnotations(clazz); @@ -23,17 +27,19 @@ public static T fromXml(Class clazz, InputStream is) { @Override public void configure(Binder binder) { - try (InputStream is1 = ClassLoader - .getSystemResourceAsStream("test-config.xml")) { - WxXmlCpInMemoryConfigStorage config = fromXml( - WxXmlCpInMemoryConfigStorage.class, is1); + try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(TEST_CONFIG_XML)) { + if (inputStream == null) { + throw new RuntimeException("测试配置文件【" + TEST_CONFIG_XML + "】未找到,请参照test-config-sample.xml文件生成"); + } + + WxXmlCpInMemoryConfigStorage config = fromXml(WxXmlCpInMemoryConfigStorage.class, inputStream); WxCpService wxService = new WxCpServiceImpl(); wxService.setWxCpConfigStorage(config); binder.bind(WxCpService.class).toInstance(wxService); binder.bind(WxXmlCpInMemoryConfigStorage.class).toInstance(config); } catch (IOException e) { - e.printStackTrace(); + this.log.error(e.getMessage(), e); } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java index b535634a45..58ba1a9791 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.cp.api; import com.google.inject.Inject; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; import me.chanjar.weixin.cp.config.WxCpConfigStorage; import org.apache.commons.lang3.StringUtils; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBusyRetryTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBusyRetryTest.java index 2c964d309c..2e89e5e79d 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBusyRetryTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBusyRetryTest.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.cp.api; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; import org.testng.annotations.DataProvider; @@ -24,9 +24,7 @@ public synchronized T executeInternal( RequestExecutor executor, String uri, E data) throws WxErrorException { this.log.info("Executed"); - WxError error = new WxError(); - error.setErrorCode(-1); - throw new WxErrorException(error); + throw new WxErrorException(WxError.builder().errorCode(-1).build()); } }; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageAPITest.java index 0cecc01588..640bbad17d 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageAPITest.java @@ -2,8 +2,7 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.api.WxConsts; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.WxCpMessage; import me.chanjar.weixin.cp.bean.WxCpMessageSendResult; import org.testng.annotations.*; @@ -32,7 +31,7 @@ public void setup() { public void testSendMessage() throws WxErrorException { WxCpMessage message = new WxCpMessage(); // message.setAgentId(configStorage.getAgentId()); - message.setMsgType(WxConsts.CUSTOM_MSG_TEXT); + message.setMsgType(WxConsts.KefuMsgType.TEXT); message.setToUser(configStorage.getUserId()); message.setContent("欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java index e52101f508..a213488953 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java @@ -27,21 +27,21 @@ public void prepare(boolean async, StringBuffer sb, WxCpMessageRouter router) { router .rule() .async(async) - .msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1").content("CONTENT_1") + .msgType(WxConsts.XmlMsgType.TEXT).event(WxConsts.EventType.CLICK).eventKey("KEY_1").content("CONTENT_1") .handler(new WxEchoCpMessageHandler(sb, "COMBINE_4")) .end() .rule() .async(async) - .msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1") + .msgType(WxConsts.XmlMsgType.TEXT).event(WxConsts.EventType.CLICK).eventKey("KEY_1") .handler(new WxEchoCpMessageHandler(sb, "COMBINE_3")) .end() .rule() .async(async) - .msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK) + .msgType(WxConsts.XmlMsgType.TEXT).event(WxConsts.EventType.CLICK) .handler(new WxEchoCpMessageHandler(sb, "COMBINE_2")) .end() - .rule().async(async).msgType(WxConsts.XML_MSG_TEXT).handler(new WxEchoCpMessageHandler(sb, WxConsts.XML_MSG_TEXT)).end() - .rule().async(async).event(WxConsts.EVT_CLICK).handler(new WxEchoCpMessageHandler(sb, WxConsts.EVT_CLICK)).end() + .rule().async(async).msgType(WxConsts.XmlMsgType.TEXT).handler(new WxEchoCpMessageHandler(sb, WxConsts.XmlMsgType.TEXT)).end() + .rule().async(async).event(WxConsts.EventType.CLICK).handler(new WxEchoCpMessageHandler(sb, WxConsts.EventType.CLICK)).end() .rule().async(async).eventKey("KEY_1").handler(new WxEchoCpMessageHandler(sb, "KEY_1")).end() .rule().async(async).content("CONTENT_1").handler(new WxEchoCpMessageHandler(sb, "CONTENT_1")).end() .rule().async(async).rContent(".*bc.*").handler(new WxEchoCpMessageHandler(sb, "abcd")).end() @@ -69,7 +69,7 @@ public void testAsync(WxCpXmlMessage message, String expected) throws Interrupte WxCpMessageRouter router = new WxCpMessageRouter(null); prepare(true, sb, router); router.route(message); - Thread.sleep(500l); + Thread.sleep(500); Assert.assertEquals(sb.toString(), expected); } @@ -89,7 +89,7 @@ public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map co public void run() { router.route(m); try { - Thread.sleep(1000l); + Thread.sleep(1000); } catch (InterruptedException e) { } } @@ -98,16 +98,16 @@ public void run() { new Thread(r).start(); } - Thread.sleep(1000l * 2); + Thread.sleep(2000); } @DataProvider(name = "messages-1") public Object[][] messages2() { WxCpXmlMessage message1 = new WxCpXmlMessage(); - message1.setMsgType(WxConsts.XML_MSG_TEXT); + message1.setMsgType(WxConsts.XmlMsgType.TEXT); WxCpXmlMessage message2 = new WxCpXmlMessage(); - message2.setEvent(WxConsts.EVT_CLICK); + message2.setEvent(WxConsts.EventType.CLICK); WxCpXmlMessage message3 = new WxCpXmlMessage(); message3.setEventKey("KEY_1"); @@ -125,24 +125,24 @@ public Object[][] messages2() { message7.setFormat("strangeformat"); WxCpXmlMessage c2 = new WxCpXmlMessage(); - c2.setMsgType(WxConsts.XML_MSG_TEXT); - c2.setEvent(WxConsts.EVT_CLICK); + c2.setMsgType(WxConsts.XmlMsgType.TEXT); + c2.setEvent(WxConsts.EventType.CLICK); WxCpXmlMessage c3 = new WxCpXmlMessage(); - c3.setMsgType(WxConsts.XML_MSG_TEXT); - c3.setEvent(WxConsts.EVT_CLICK); + c3.setMsgType(WxConsts.XmlMsgType.TEXT); + c3.setEvent(WxConsts.EventType.CLICK); c3.setEventKey("KEY_1"); WxCpXmlMessage c4 = new WxCpXmlMessage(); - c4.setMsgType(WxConsts.XML_MSG_TEXT); - c4.setEvent(WxConsts.EVT_CLICK); + c4.setMsgType(WxConsts.XmlMsgType.TEXT); + c4.setEvent(WxConsts.EventType.CLICK); c4.setEventKey("KEY_1"); c4.setContent("CONTENT_1"); return new Object[][]{ - new Object[]{message1, WxConsts.XML_MSG_TEXT + ","}, - new Object[]{message2, WxConsts.EVT_CLICK + ","}, + new Object[]{message1, WxConsts.XmlMsgType.TEXT + ","}, + new Object[]{message2, WxConsts.EventType.CLICK + ","}, new Object[]{message3, "KEY_1,"}, new Object[]{message4, "CONTENT_1,"}, new Object[]{message5, "ALL,"}, @@ -184,7 +184,7 @@ public void testSessionClean1(StandardSessionManager ism) throws InterruptedExce msg.setFromUserName("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -204,7 +204,7 @@ public void testSessionClean2(StandardSessionManager ism) throws InterruptedExce msg.setFromUserName("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } { @@ -218,7 +218,7 @@ public void testSessionClean2(StandardSessionManager ism) throws InterruptedExce msg.setFromUserName("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -238,7 +238,7 @@ public void testSessionClean3(StandardSessionManager ism) throws InterruptedExce msg.setFromUserName("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -257,7 +257,7 @@ public void testSessionClean4(StandardSessionManager ism) throws InterruptedExce msg.setFromUserName("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -271,7 +271,7 @@ public void testSessionClean4(StandardSessionManager ism) throws InterruptedExce msg.setFromUserName("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImplTest.java new file mode 100644 index 0000000000..4ce497243d --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImplTest.java @@ -0,0 +1,90 @@ +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.WxCpAgentService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpAgent; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; + + +/** + * + * 管理企业号应用-测试 + * Created by huansinho on 2018/4/13. + *+ * + * @author huansinho + */ +@Guice(modules = ApiTestModule.class) +public class WxCpAgentServiceImplTest { + @Inject + private WxCpService wxCpService; + + @Test + public void testGet() throws Exception { + final Integer agentId = this.wxCpService.getWxCpConfigStorage().getAgentId(); + WxCpAgent wxCpAgent = this.wxCpService.getAgentService().get(agentId); + + assertThat(wxCpAgent.getAgentId()).isEqualTo(agentId); + + assertThat(wxCpAgent.getAllowUserInfos().getUsers().toArray()).isNotEmpty(); + assertThat(wxCpAgent.getAllowParties().getPartyIds().toArray()).isNotEmpty(); + assertThat(wxCpAgent.getAllowTags().getTagIds().toArray()).isNotEmpty(); + } + + @Test + public void testSet() throws WxErrorException { + final Integer agentId = this.wxCpService.getWxCpConfigStorage().getAgentId(); + + this.wxCpService.getAgentService().set(WxCpAgent.builder() + .description("abcddd") + .logoMediaId("aaaaaaaaaaaaaa") + .agentId(agentId) + .build()); + } + + @Test + public void testList() throws WxErrorException { + Listlist = this.wxCpService.getAgentService().list(); + + assertThat(list).isNotEmpty(); + + assertThat(list.get(0).getAgentId()).isNotNull(); + assertThat(list.get(0).getName()).isNotEmpty(); + assertThat(list.get(0).getSquareLogoUrl()).isNotEmpty(); + } + + public static class MockTest { + private 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); + + assertEquals(9, wxCpAgent.getAgentId().intValue()); + + assertEquals(new Integer[]{42762742}, wxCpAgent.getAllowParties().getPartyIds().toArray()); + + assertEquals(new Integer[]{23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7}, wxCpAgent.getAllowTags().getTagIds().toArray()); + + } + + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java index 685f37444f..9a19564cd2 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java @@ -1,15 +1,14 @@ package me.chanjar.weixin.cp.api.impl; import com.google.inject.Inject; -import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.cp.api.ApiTestModule; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.WxCpDepart; -import org.testng.annotations.Guice; -import org.testng.annotations.Test; +import org.testng.annotations.*; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; import static org.testng.Assert.*; /** @@ -31,25 +30,33 @@ public void testCreate() throws Exception { WxCpDepart cpDepart = new WxCpDepart(); cpDepart.setName("子部门" + System.currentTimeMillis()); cpDepart.setParentId(1); - cpDepart.setOrder(1); + cpDepart.setOrder(1L); Integer departId = this.wxCpService.getDepartmentService().create(cpDepart); System.out.println(departId); } - @Test - public void testListAll() throws Exception { + @DataProvider + public Object[][] departIds(){ + return new Object[][]{ + {null}, + {1}, + {5} + }; + } + + @Test(dataProvider = "departIds") + public void testList(Integer id) throws Exception { System.out.println("=================获取部门"); - List departList = this.wxCpService.getDepartmentService().listAll(); - assertNotNull(departList); - assertTrue(departList.size() > 0); + List departList = this.wxCpService.getDepartmentService().list(id); + assertThat(departList).isNotEmpty(); for (WxCpDepart g : departList) { this.depart = g; System.out.println(this.depart.getId() + ":" + this.depart.getName()); - assertNotNull(g.getName()); + assertThat(g.getName()).isNotBlank(); } } - @Test(dependsOnMethods = {"testListAll", "testCreate"}) + @Test(dependsOnMethods = {"testList", "testCreate"}) public void testUpdate() throws Exception { System.out.println("=================更新部门"); this.depart.setName("子部门改名" + System.currentTimeMillis()); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImplTest.java index 4bdb73413d..d7242a7703 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImplTest.java @@ -1,28 +1,29 @@ package me.chanjar.weixin.cp.api.impl; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.testng.annotations.*; + import com.google.inject.Inject; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.ApiTestModule; import me.chanjar.weixin.cp.api.TestConstants; import me.chanjar.weixin.cp.api.WxCpService; -import org.testng.annotations.*; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; import static org.testng.Assert.*; /** - * - * * Created by Binary Wang on 2017-6-25. + * * @author Binary Wang - **/ @Guice(modules = ApiTestModule.class) public class WxCpMediaServiceImplTest { @@ -34,11 +35,11 @@ public class WxCpMediaServiceImplTest { @DataProvider public Object[][] mediaData() { return new Object[][]{ - new Object[]{WxConsts.MEDIA_IMAGE, TestConstants.FILE_JPG, "mm.jpeg"}, - new Object[]{WxConsts.MEDIA_VOICE, TestConstants.FILE_MP3, "mm.mp3"}, - new Object[]{WxConsts.MEDIA_VOICE, TestConstants.FILE_AMR, "mm.amr"},//{"errcode":301017,"errmsg":"voice file only support amr like myvoice.amr"} - new Object[]{WxConsts.MEDIA_VIDEO, TestConstants.FILE_MP4, "mm.mp4"}, - new Object[]{WxConsts.MEDIA_FILE, TestConstants.FILE_JPG, "mm.jpeg"} + new Object[]{WxConsts.MediaFileType.IMAGE, TestConstants.FILE_JPG, "mm.jpeg"}, + new Object[]{WxConsts.MediaFileType.VOICE, TestConstants.FILE_MP3, "mm.mp3"},//{"errcode":301017,"errmsg":"voice file only support amr like myvoice.amr"} + new Object[]{WxConsts.MediaFileType.VOICE, TestConstants.FILE_AMR, "mm.amr"}, + new Object[]{WxConsts.MediaFileType.VIDEO, TestConstants.FILE_MP4, "mm.mp4"}, + new Object[]{WxConsts.MediaFileType.FILE, TestConstants.FILE_JPG, "mm.jpeg"} }; } @@ -75,4 +76,10 @@ public void testDownloadMedia(String media_id) throws WxErrorException { System.out.println(file); } + @Test + public void testUploadImg() throws WxErrorException { + URL url = ClassLoader.getSystemResource("mm.jpeg"); + String res = this.wxService.getMediaService().uploadImg(new File(url.getFile())); + assertThat(res).isNotEmpty(); + } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImplTest.java index def6419820..b9dbbd3aa1 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImplTest.java @@ -26,12 +26,12 @@ public class WxCpMenuServiceImplTest { public Object[][] menuData() { WxMenu menu = new WxMenu(); WxMenuButton button1 = new WxMenuButton(); - button1.setType(WxConsts.BUTTON_CLICK); + button1.setType(WxConsts.MenuButtonType.CLICK); button1.setName("今日歌曲"); button1.setKey("V1001_TODAY_MUSIC"); WxMenuButton button2 = new WxMenuButton(); - button2.setType(WxConsts.BUTTON_CLICK); + button2.setType(WxConsts.MenuButtonType.CLICK); button2.setName("歌手简介"); button2.setKey("V1001_TODAY_SINGER"); @@ -43,17 +43,17 @@ public Object[][] menuData() { menu.getButtons().add(button3); WxMenuButton button31 = new WxMenuButton(); - button31.setType(WxConsts.BUTTON_VIEW); + button31.setType(WxConsts.MenuButtonType.VIEW); button31.setName("搜索"); button31.setUrl("http://www.soso.com/"); WxMenuButton button32 = new WxMenuButton(); - button32.setType(WxConsts.BUTTON_VIEW); + button32.setType(WxConsts.MenuButtonType.VIEW); button32.setName("视频"); button32.setUrl("http://v.qq.com/"); WxMenuButton button33 = new WxMenuButton(); - button33.setType(WxConsts.BUTTON_CLICK); + button33.setType(WxConsts.MenuButtonType.CLICK); button33.setName("赞一下我们"); button33.setKey("V1001_GOOD"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImplTest.java new file mode 100644 index 0000000000..21801e4b42 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImplTest.java @@ -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; + +/** + *+ * Created by BinaryWang on 2018/4/22. + *+ * + * @author Binary Wang + */ +@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"); + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImplTest.java index 94ac3b09db..5a6e8ccabd 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImplTest.java @@ -2,16 +2,23 @@ import com.google.common.base.Splitter; import com.google.inject.Inject; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.ApiTestModule; import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.WxCpTagService; import me.chanjar.weixin.cp.bean.WxCpTag; import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult; +import me.chanjar.weixin.cp.bean.WxCpTagGetResult; import me.chanjar.weixin.cp.bean.WxCpUser; -import org.testng.annotations.*; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; import java.util.List; -import static org.testng.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; /** *@@ -63,7 +70,7 @@ public void testListUsersByTagId() throws Exception { @Test(dependsOnMethods = {"testListUsersByTagId", "testAddUsers2Tag", "testListAll", "testUpdate", "testCreate"}) public void testRemoveUsersFromTag() throws Exception { ListuserIds = Splitter.on("|").splitToList(this.configStorage.getUserId()); - WxCpTagAddOrRemoveUsersResult result = this.wxService.getTagService().removeUsersFromTag(this.tagId, userIds); + WxCpTagAddOrRemoveUsersResult result = this.wxService.getTagService().removeUsersFromTag(this.tagId, userIds, null); assertEquals(result.getErrCode(), Integer.valueOf(0)); } @@ -72,4 +79,24 @@ public void testDelete() throws Exception { 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()); + + + } + } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java index a01f03436e..6b67112095 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java @@ -1,14 +1,21 @@ package me.chanjar.weixin.cp.api.impl; -import com.google.inject.Inject; -import me.chanjar.weixin.cp.api.ApiTestModule; -import me.chanjar.weixin.cp.api.WxCpService; -import me.chanjar.weixin.cp.bean.WxCpUser; +import java.util.List; +import java.util.Map; + import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.testng.annotations.*; -import java.util.List; +import com.google.common.collect.Lists; +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.Gender; +import me.chanjar.weixin.cp.bean.WxCpInviteResult; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; import static org.testng.Assert.*; @@ -37,7 +44,7 @@ public void testCreate() throws Exception { user.setName("Some Woman"); user.setDepartIds(new Integer[]{2}); user.setEmail("none@none.com"); - user.setGender(WxCpUser.Gender.FEMAIL); + user.setGender(Gender.FEMALE); user.setMobile("13560084979"); user.setPosition("woman"); user.setTelephone("3300393"); @@ -83,4 +90,31 @@ public void testListSimpleByDepartment() throws Exception { } } + @Test + public void testInvite() throws Exception { + WxCpInviteResult result = this.wxCpService.getUserService().invite( + Lists.newArrayList(userId), null,null); + System.out.println(result); + } + + @Test + public void testUserId2Openid() throws Exception { + Map result = this.wxCpService.getUserService().userId2Openid(userId, null); + System.out.println(result); + assertNotNull(result); + } + + @Test + public void testOpenid2UserId() throws Exception { + String result = this.wxCpService.getUserService().openid2UserId(userId); + System.out.println(result); + assertNotNull(result); + } + + @Test + public void testGetExternalContact() throws WxErrorException { + WxCpUserExternalContactInfo result = this.wxCpService.getUserService().getExternalContact(userId); + System.out.println(result); + assertNotNull(result); + } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpAgentTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpAgentTest.java new file mode 100644 index 0000000000..74b8269d3d --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpAgentTest.java @@ -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.getAllowParties().getPartyIds().toArray()); + + Assert.assertEquals(new Integer[]{23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7}, wxCpAgent.getAllowTags().getTagIds().toArray()); + + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpMessageTest.java index e02cc6672d..0af121a835 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpMessageTest.java @@ -2,39 +2,47 @@ import me.chanjar.weixin.cp.bean.article.MpnewsArticle; import me.chanjar.weixin.cp.bean.article.NewArticle; -import org.testng.annotations.*; +import org.testng.annotations.Test; -import static org.testng.Assert.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.testng.Assert.assertEquals; @Test public class WxCpMessageTest { public void testTextBuild() { WxCpMessage reply = WxCpMessage.TEXT().toUser("OPENID").content("sfsfdsdf").build(); - assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"},\"safe\":\"0\"}"); + assertThat(reply.toJson()) + .isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"},\"safe\":\"0\"}"); } public void testTextCardBuild() { WxCpMessage reply = WxCpMessage.TEXTCARD().toUser("OPENID") .title("领奖通知") - .description( " 2016年9月26日恭喜你抽中iPhone 7一台,领奖码:xxxx请于2016年10月10日前联系行政同事领取") - .url("http://www.qq.com").build(); - assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"textcard\",\"textcard\":{\"title\":\"领奖通知\",\"description\":\"2016年9月26日恭喜你抽中iPhone 7一台,领奖码:xxxx请于2016年10月10日前联系行政同事领取\",\"url\":\"http://www.qq.com\"},\"safe\":\"0\"}"); + .description("2016年9月26日恭喜你抽中iPhone 7一台,领奖码:xxxx请于2016年10月10日前联系行政同事领取") + .url("http://www.qq.com") + .btnTxt("更多") + .build(); + assertThat(reply.toJson()) + .isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"textcard\",\"textcard\":{\"title\":\"领奖通知\",\"description\":\"2016年9月26日恭喜你抽中iPhone 7一台,领奖码:xxxx请于2016年10月10日前联系行政同事领取\",\"url\":\"http://www.qq.com\",\"btntxt\":\"更多\"},\"safe\":\"0\"}"); } public void testImageBuild() { WxCpMessage reply = WxCpMessage.IMAGE().toUser("OPENID").mediaId("MEDIA_ID").build(); - assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}"); + assertThat(reply.toJson()) + .isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}"); } public void testVoiceBuild() { WxCpMessage reply = WxCpMessage.VOICE().toUser("OPENID").mediaId("MEDIA_ID").build(); - assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}"); + assertThat(reply.toJson()) + .isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}"); } public void testVideoBuild() { WxCpMessage reply = WxCpMessage.VIDEO().toUser("OPENID").title("TITLE").mediaId("MEDIA_ID").thumbMediaId("MEDIA_ID").description("DESCRIPTION").build(); - assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"video\",\"safe\":\"0\",\"video\":{\"media_id\":\"MEDIA_ID\",\"thumb_media_id\":\"MEDIA_ID\",\"title\":\"TITLE\",\"description\":\"DESCRIPTION\"}}"); + assertThat(reply.toJson()) + .isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"video\",\"safe\":\"0\",\"video\":{\"media_id\":\"MEDIA_ID\",\"thumb_media_id\":\"MEDIA_ID\",\"title\":\"TITLE\",\"description\":\"DESCRIPTION\"}}"); } public void testNewsBuild() { @@ -52,7 +60,8 @@ public void testNewsBuild() { WxCpMessage reply = WxCpMessage.NEWS().toUser("OPENID").addArticle(article1).addArticle(article2).build(); - assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"news\",\"safe\":\"0\",\"news\":{\"articles\":[{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"},{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"}]}}"); + assertThat(reply.toJson()) + .isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"news\",\"safe\":\"0\",\"news\":{\"articles\":[{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"},{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"}]}}"); } public void testMpnewsBuild_with_articles() { @@ -78,14 +87,15 @@ public void testMpnewsBuild_with_articles() { WxCpMessage reply = WxCpMessage.MPNEWS().toUser("OPENID").addArticle(article1, article2).build(); - assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"articles\":[{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"},{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"}]}}"); + assertThat(reply.toJson()) + .isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"articles\":[{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"},{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"}]}}"); } public void testMpnewsBuild_with_media_id() { WxCpMessage reply = WxCpMessage.MPNEWS().toUser("OPENID").mediaId("mmm").build(); - assertEquals(reply.toJson(), - "{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"media_id\":\"mmm\"}}"); + assertThat(reply.toJson()) + .isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"media_id\":\"mmm\"}}"); } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfoTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfoTest.java new file mode 100644 index 0000000000..3c1b327cd3 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfoTest.java @@ -0,0 +1,129 @@ +package me.chanjar.weixin.cp.bean; + +import java.util.List; + +import org.testng.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + *+ * + * Created by Binary Wang on 2018/9/16. + *+ * + * @author Binary Wang + */ +public class WxCpUserExternalContactInfoTest { + + @Test + public void testFromJson() { + final String json = "{\n" + + " \"errcode\": 0,\n" + + " \"errmsg\": \"ok\",\n" + + " \"external_contact\": {\n" + + " \"external_userid\": \"woAJ2GCAAAXtWyujaWJHDDGi0mACH71w\",\n" + + " \"name\": \"李四\",\n" + + " \"position\": \"Mangaer\",\n" + + " \"avatar\": \"http://p.qlogo.cn/bizmail/IcsdgagqefergqerhewSdage/0\",\n" + + " \"corp_name\": \"腾讯\",\n" + + " \"corp_full_name\": \"腾讯科技有限公司\",\n" + + " \"type\": 2,\n" + + " \"gender\": 1,\n" + + " \"unionid\": \"ozynqsulJFCZ2z1aYeS8h-nuasdfR1\",\n" + + " \"external_profile\": {\n" + + " \"external_attr\": [\n" + + " {\n" + + " \"type\": 0,\n" + + " \"name\": \"文本名称\",\n" + + " \"text\": {\n" + + " \"value\": \"文本\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"type\": 1,\n" + + " \"name\": \"网页名称\",\n" + + " \"web\": {\n" + + " \"url\": \"http://www.test.com\",\n" + + " \"title\": \"标题\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"type\": 2,\n" + + " \"name\": \"测试app\",\n" + + " \"miniprogram\": {\n" + + " \"appid\": \"wx8bd80126147df384\",\n" + + " \"pagepath\": \"/index\",\n" + + " \"title\": \"my miniprogram\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"follow_user\": [\n" + + " {\n" + + " \"userid\": \"rocky\",\n" + + " \"remark\": \"李部长\",\n" + + " \"description\": \"对接采购事物\",\n" + + " \"createtime\": 1525779812\n" + + " },\n" + + " {\n" + + " \"userid\": \"tommy\",\n" + + " \"remark\": \"李总\",\n" + + " \"description\": \"采购问题咨询\",\n" + + " \"createtime\": 1525881637\n" + + " }\n" + + " ]\n" + + "}"; + + final WxCpUserExternalContactInfo contactInfo = WxCpUserExternalContactInfo.fromJson(json); + assertThat(contactInfo).isNotNull(); + assertThat(contactInfo.getExternalContact()).isNotNull(); + + assertThat(contactInfo.getExternalContact().getExternalUserId()).isEqualTo("woAJ2GCAAAXtWyujaWJHDDGi0mACH71w"); + assertThat(contactInfo.getExternalContact().getPosition()).isEqualTo("Mangaer"); + assertThat(contactInfo.getExternalContact().getAvatar()).isEqualTo("http://p.qlogo.cn/bizmail/IcsdgagqefergqerhewSdage/0"); + assertThat(contactInfo.getExternalContact().getCorpName()).isEqualTo("腾讯"); + assertThat(contactInfo.getExternalContact().getCorpFullName()).isEqualTo("腾讯科技有限公司"); + assertThat(contactInfo.getExternalContact().getType()).isEqualTo(2); + assertThat(contactInfo.getExternalContact().getGender()).isEqualTo(1); + assertThat(contactInfo.getExternalContact().getUnionId()).isEqualTo("ozynqsulJFCZ2z1aYeS8h-nuasdfR1"); + assertThat(contactInfo.getExternalContact().getName()).isEqualTo("李四"); + + assertThat(contactInfo.getExternalContact().getExternalProfile()).isNotNull(); + + final ListexternalAttrs = contactInfo.getExternalContact().getExternalProfile().getExternalAttrs(); + assertThat(externalAttrs).isNotEmpty(); + + final WxCpUserExternalContactInfo.ExternalAttribute externalAttr1 = externalAttrs.get(0); + assertThat(externalAttr1.getType()).isEqualTo(0); + assertThat(externalAttr1.getName()).isEqualTo("文本名称"); + assertThat(externalAttr1.getText().getValue()).isEqualTo("文本"); + + final WxCpUserExternalContactInfo.ExternalAttribute externalAttr2 = externalAttrs.get(1); + assertThat(externalAttr2.getType()).isEqualTo(1); + assertThat(externalAttr2.getName()).isEqualTo("网页名称"); + assertThat(externalAttr2.getWeb().getUrl()).isEqualTo("http://www.test.com"); + assertThat(externalAttr2.getWeb().getTitle()).isEqualTo("标题"); + + final WxCpUserExternalContactInfo.ExternalAttribute externalAttr3 = externalAttrs.get(2); + assertThat(externalAttr3.getType()).isEqualTo(2); + assertThat(externalAttr3.getName()).isEqualTo("测试app"); + assertThat(externalAttr3.getMiniProgram().getAppid()).isEqualTo("wx8bd80126147df384"); + assertThat(externalAttr3.getMiniProgram().getPagePath()).isEqualTo("/index"); + assertThat(externalAttr3.getMiniProgram().getTitle()).isEqualTo("my miniprogram"); + + + List followedUsers = contactInfo.getFollowedUsers(); + assertThat(followedUsers).isNotEmpty(); + assertThat(followedUsers.get(0).getUserId()).isEqualTo("rocky"); + assertThat(followedUsers.get(0).getRemark()).isEqualTo("李部长"); + assertThat(followedUsers.get(0).getDescription()).isEqualTo("对接采购事物"); + assertThat(followedUsers.get(0).getCreateTime()).isEqualTo(1525779812); + + assertThat(followedUsers.get(1).getUserId()).isEqualTo("tommy"); + assertThat(followedUsers.get(1).getRemark()).isEqualTo("李总"); + assertThat(followedUsers.get(1).getDescription()).isEqualTo("采购问题咨询"); + assertThat(followedUsers.get(1).getCreateTime()).isEqualTo(1525881637); + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java index 87e16d773a..68c57c3d89 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java @@ -57,10 +57,10 @@ public void testFromXml() { WxCpXmlMessage wxMessage = WxCpXmlMessage.fromXml(xml); assertEquals(wxMessage.getToUserName(), "toUser"); assertEquals(wxMessage.getFromUserName(), "fromUser"); - assertEquals(wxMessage.getCreateTime(), new Long(1348831860l)); - assertEquals(wxMessage.getMsgType(), WxConsts.XML_MSG_TEXT); + assertEquals(wxMessage.getCreateTime(), new Long(1348831860)); + assertEquals(wxMessage.getMsgType(), WxConsts.XmlMsgType.TEXT); assertEquals(wxMessage.getContent(), "this is a test"); - assertEquals(wxMessage.getMsgId(), new Long(1234567890123456l)); + assertEquals(wxMessage.getMsgId(), new Long(1234567890123456L)); assertEquals(wxMessage.getPicUrl(), "this is a url"); assertEquals(wxMessage.getMediaId(), "media_id"); assertEquals(wxMessage.getFormat(), "Format"); @@ -80,13 +80,13 @@ public void testFromXml() { assertEquals(wxMessage.getPrecision(), 119.385040); assertEquals(wxMessage.getScanCodeInfo().getScanType(), "qrcode"); assertEquals(wxMessage.getScanCodeInfo().getScanResult(), "1"); - assertEquals(wxMessage.getSendPicsInfo().getCount(), new Long(1l)); + assertEquals(wxMessage.getSendPicsInfo().getCount(), new Long(1)); assertEquals(wxMessage.getSendPicsInfo().getPicList().get(0).getPicMd5Sum(), "1b5f7c23b5bf75682a53e7b6d163e185"); assertEquals(wxMessage.getSendLocationInfo().getLocationX(), "23"); assertEquals(wxMessage.getSendLocationInfo().getLocationY(), "113"); assertEquals(wxMessage.getSendLocationInfo().getScale(), "15"); assertEquals(wxMessage.getSendLocationInfo().getLabel(), " 广州市海珠区客村艺苑路 106号"); - assertEquals(wxMessage.getSendLocationInfo().getPoiname(), "wo de poi"); + assertEquals(wxMessage.getSendLocationInfo().getPoiName(), "wo de poi"); } public void testSendPicsInfo() { @@ -108,7 +108,7 @@ public void testSendPicsInfo() { assertEquals(wxMessage.getToUserName(), "wx45a0972125658be9"); assertEquals(wxMessage.getFromUserName(), "xiaohe"); assertEquals(wxMessage.getCreateTime(), new Long(1502012364L)); - assertEquals(wxMessage.getMsgType(), WxConsts.XML_MSG_EVENT); + assertEquals(wxMessage.getMsgType(), WxConsts.XmlMsgType.EVENT); assertEquals(wxMessage.getAgentId(), Integer.valueOf(1000004)); assertEquals(wxMessage.getEvent(), "pic_weixin"); assertEquals(wxMessage.getEventKey(), "faceSimilarity"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java index 6f366988eb..87c9454c91 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java @@ -9,7 +9,7 @@ public class WxCpXmlOutImageMessageTest { public void test() { WxCpXmlOutImageMessage m = new WxCpXmlOutImageMessage(); m.setMediaId("ddfefesfsdfef"); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("from"); m.setToUserName("to"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java index 71dbf4125d..128bc9a4c6 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java @@ -8,7 +8,7 @@ public class WxCpXmlOutNewsMessageTest { public void test() { WxCpXmlOutNewsMessage m = new WxCpXmlOutNewsMessage(); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("fromUser"); m.setToUserName("toUser"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java index 4d73b27f5b..fd09ed6b92 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java @@ -9,7 +9,7 @@ public class WxCpXmlOutTextMessageTest { public void test() { WxCpXmlOutTextMessage m = new WxCpXmlOutTextMessage(); m.setContent("content"); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("from"); m.setToUserName("to"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java index b4124c6130..c5551dec01 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java @@ -11,7 +11,7 @@ public void test() { m.setMediaId("media_id"); m.setTitle("title"); m.setDescription("ddfff"); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("fromUser"); m.setToUserName("toUser"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java index f414256a5f..a3c9688c44 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java @@ -9,7 +9,7 @@ public class WxCpXmlOutVoiceMessageTest { public void test() { WxCpXmlOutVoiceMessage m = new WxCpXmlOutVoiceMessage(); m.setMediaId("ddfefesfsdfef"); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("from"); m.setToUserName("to"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoServer.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoServer.java index a9ab309c37..ff204a80f0 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoServer.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoServer.java @@ -1,6 +1,16 @@ package me.chanjar.weixin.cp.demo; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; + +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.WxCpConsts; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; import me.chanjar.weixin.cp.bean.WxCpXmlMessage; @@ -9,13 +19,6 @@ import me.chanjar.weixin.cp.config.WxCpConfigStorage; import me.chanjar.weixin.cp.message.WxCpMessageHandler; import me.chanjar.weixin.cp.message.WxCpMessageRouter; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.servlet.ServletHandler; -import org.eclipse.jetty.servlet.ServletHolder; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; public class WxCpDemoServer { @@ -78,9 +81,26 @@ public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, }; wxCpMessageRouter = new WxCpMessageRouter(wxCpService); - wxCpMessageRouter.rule().async(false).content("哈哈") // 拦截内容为“哈哈”的消息 - .handler(handler).end().rule().async(false).content("oauth") - .handler(oauth2handler).end(); + wxCpMessageRouter.rule() + .async(false) + .content("哈哈") // 拦截内容为“哈哈”的消息 + .handler(handler) + .end() + .rule() + .async(false) + .content("oauth") + .handler(oauth2handler) + .end() + .rule() + .event(WxCpConsts.EventType.CHANGE_CONTACT) + .handler(new WxCpMessageHandler() { + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService wxCpService, WxSessionManager sessionManager) throws WxErrorException { + System.out.println("通讯录发生变更"); + return null; + } + }) + .end(); } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpOAuth2Servlet.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpOAuth2Servlet.java index 37c2b7a12f..d652884b64 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpOAuth2Servlet.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpOAuth2Servlet.java @@ -1,6 +1,6 @@ package me.chanjar.weixin.cp.demo; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.WxCpService; import javax.servlet.http.HttpServlet; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapterTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapterTest.java new file mode 100644 index 0000000000..ec553f7521 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapterTest.java @@ -0,0 +1,124 @@ +package me.chanjar.weixin.cp.util.json; + +import org.testng.annotations.*; + +import me.chanjar.weixin.cp.bean.WxCpUser; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * + * + * Created by Binary Wang on 2018/9/16. + *+ * + * @author BinaryWang + */ +public class WxCpUserGsonAdapterTest { + + @Test + public void testDeserialize() { + final String userJson = "{\n" + + " \"errcode\": 0,\n" + + " \"errmsg\": \"ok\",\n" + + " \"userid\": \"zhangsan\",\n" + + " \"name\": \"李四\",\n" + + " \"department\": [1, 2],\n" + + " \"order\": [1, 2],\n" + + " \"position\": \"后台工程师\",\n" + + " \"mobile\": \"15913215421\",\n" + + " \"gender\": \"1\",\n" + + " \"email\": \"zhangsan@gzdev.com\",\n" + + " \"isleader\": 1,\n" + + " \"avatar\": \"http://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0\",\n" + + " \"telephone\": \"020-123456\",\n" + + " \"enable\": 1,\n" + + " \"alias\": \"jackzhang\",\n" + + " \"extattr\": {\n" + + " \"attrs\": [{\n" + + " \"name\": \"爱好\",\n" + + " \"value\": \"旅游\"\n" + + " }, {\n" + + " \"name\": \"卡号\",\n" + + " \"value\": \"1234567234\"\n" + + " }]\n" + + " },\n" + + " \"status\": 1,\n" + + " \"qr_code\": \"https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx\",\n" + + " \"external_profile\": {\n" + + " \"external_attr\": [{\n" + + " \"type\": 0,\n" + + " \"name\": \"文本名称\",\n" + + " \"text\": {\n" + + " \"value\": \"文本\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"type\": 1,\n" + + " \"name\": \"网页名称\",\n" + + " \"web\": {\n" + + " \"url\": \"http://www.test.com\",\n" + + " \"title\": \"标题\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"type\": 2,\n" + + " \"name\": \"测试app\",\n" + + " \"miniprogram\": {\n" + + " \"appid\": \"wx8bd80126147df384\",\n" + + " \"pagepath\": \"/index\",\n" + + " \"title\": \"my miniprogram\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + final WxCpUser user = WxCpUser.fromJson(userJson); + assertThat(user).isNotNull(); + assertThat(user.getExternalAttrs()).isNotEmpty(); + + final WxCpUser.ExternalAttribute externalAttr1 = user.getExternalAttrs().get(0); + assertThat(externalAttr1.getType()).isEqualTo(0); + assertThat(externalAttr1.getName()).isEqualTo("文本名称"); + assertThat(externalAttr1.getValue()).isEqualTo("文本"); + + final WxCpUser.ExternalAttribute externalAttr2 = user.getExternalAttrs().get(1); + assertThat(externalAttr2.getType()).isEqualTo(1); + assertThat(externalAttr2.getName()).isEqualTo("网页名称"); + assertThat(externalAttr2.getUrl()).isEqualTo("http://www.test.com"); + assertThat(externalAttr2.getTitle()).isEqualTo("标题"); + + final WxCpUser.ExternalAttribute externalAttr3 = user.getExternalAttrs().get(2); + assertThat(externalAttr3.getType()).isEqualTo(2); + assertThat(externalAttr3.getName()).isEqualTo("测试app"); + assertThat(externalAttr3.getAppid()).isEqualTo("wx8bd80126147df384"); + assertThat(externalAttr3.getPagePath()).isEqualTo("/index"); + assertThat(externalAttr3.getTitle()).isEqualTo("my miniprogram"); + } + + @Test + public void testSerialize() { + WxCpUser user = new WxCpUser(); + user.addExternalAttr(WxCpUser.ExternalAttribute.builder() + .type(0) + .name("文本名称") + .value("文本") + .build()); + user.addExternalAttr(WxCpUser.ExternalAttribute.builder() + .type(1) + .name("网页名称") + .url("http://www.test.com") + .title("标题") + .build()); + user.addExternalAttr(WxCpUser.ExternalAttribute.builder() + .type(2) + .name("测试app") + .appid("wx8bd80126147df384") + .pagePath("/index") + .title("my miniprogram") + .build()); + + assertThat(user.toJson()).isEqualTo("{\"external_profile\":{\"external_attr\":[{\"type\":0,\"name\":\"文本名称\",\"text\":{\"value\":\"文本\"}},{\"type\":1,\"name\":\"网页名称\",\"web\":{\"url\":\"http://www.test.com\",\"title\":\"标题\"}},{\"type\":2,\"name\":\"测试app\",\"miniprogram\":{\"appid\":\"wx8bd80126147df384\",\"pagepath\":\"/index\",\"title\":\"my miniprogram\"}}]}}"); + } +} diff --git a/weixin-java-miniapp/pom.xml b/weixin-java-miniapp/pom.xml index 3a2614aa59..456147618b 100644 --- a/weixin-java-miniapp/pom.xml +++ b/weixin-java-miniapp/pom.xml @@ -7,10 +7,10 @@com.github.binarywang weixin-java-parent -2.8.0 +3.2.0 weixin-java-miniapp -WeiXin Java Tools - MiniApp +Weixin Java Tools - MiniApp 微信小程序Java SDK @@ -61,10 +61,19 @@ joda-time test ++ org.assertj +assertj-guava +test ++ redis.clients jedis + org.projectlombok +lombok +diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaAnalysisService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaAnalysisService.java new file mode 100644 index 0000000000..e8273bc402 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaAnalysisService.java @@ -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 Charming + * @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 getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取日访问趋势 + * 温馨提示:小程序接口目前只能查询一天的数据,即 beginDate 和 endDate 一样 + * + * @param beginDate 开始日期 + * @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 + * @return 日访问趋势 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + List getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取周访问趋势 + * 限定查询一个自然周的数据,时间必须按照自然周的方式输入: 如:20170306(周一), 20170312(周日) + * + * @param beginDate 开始日期,为周一日期 + * @param endDate 结束日期,为周日日期,限定查询一周数据 + * @return 周访问趋势(每项数据都是一个自然周汇总) + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + List getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取月访问趋势 + * 限定查询一个自然月的数据,时间必须按照自然月的方式输入: 如:20170201(月初), 20170228(月末) + * + * @param beginDate 开始日期,为自然月第一天 + * @param endDate 结束日期,为自然月最后一天,限定查询一个月数据 + * @return 月访问趋势(每项数据都是一个自然月汇总) + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + List 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 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; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java new file mode 100644 index 0000000000..fbe0818493 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java @@ -0,0 +1,144 @@ +package cn.binarywang.wx.miniapp.api; + +import java.util.List; + +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; + +/** + * 小程序代码管理相关 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 Charming + * @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; + + /** + * 获取体验小程序的体验二维码 + * 文档地址: + * https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=&lang=zh_CN + * + * @param path 指定体验版二维码跳转到某个具体页面(如果不需要的话,则不需要填path参数,可在路径后以“?参数”方式传入参数) + * 具体的路径加参数需要urlencode(方法内部处理),比如page/index?action=1编码后得到page%2Findex%3Faction%3D1 + * @return 二维码 bytes + * @throws WxErrorException 上传失败时抛出,具体错误码请看类注释文档 + */ + byte[] getQrCode(String path) throws WxErrorException; + + /** + * 获取授权小程序帐号的可选类目 + * + * @return List + * @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档 + */ + List getCategory() throws WxErrorException; + + /** + * 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用) + * + * @return page_list 页面配置列表 + * @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档 + */ + List 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; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaJsapiService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaJsapiService.java new file mode 100644 index 0000000000..156fcbc1ce --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaJsapiService.java @@ -0,0 +1,48 @@ +package cn.binarywang.wx.miniapp.api; + +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * + * jsapi相关接口 + * Created by BinaryWang on 2018/8/5. + *+ * + * @author Binary Wang + */ +public interface WxMaJsapiService { + /** + * 获得jsapi_ticket的url + */ + String GET_JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; + + /** + * 获得jsapi_ticket,不强制刷新jsapi_ticket + * + * @see #getJsapiTicket(boolean) + */ + String getJsapiTicket() throws WxErrorException; + + /** + *+ * 获得jsapi_ticket + * 获得时会检查jsapiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干 + * + * 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN + *+ * + * @param forceRefresh 强制刷新 + */ + String getJsapiTicket(boolean forceRefresh) throws WxErrorException; + + /** + *+ * 创建调用jsapi时所需要的签名 + * + * 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN + *+ */ + WxJsapiSignature createJsapiSignature(String url) throws WxErrorException; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMediaService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMediaService.java index 09c8aa5b9d..d2c57ca5e4 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMediaService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMediaService.java @@ -1,7 +1,7 @@ package cn.binarywang.wx.miniapp.api; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import java.io.File; import java.io.InputStream; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMsgService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMsgService.java index 65522f4b75..a838417e23 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMsgService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMsgService.java @@ -2,7 +2,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; -import me.chanjar.weixin.common.exception.WxErrorException; +import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; +import me.chanjar.weixin.common.error.WxErrorException; /** *@@ -14,6 +15,7 @@ public interface WxMaMsgService { String KEFU_MESSAGE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send"; String TEMPLATE_MSG_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send"; + String UNIFORM_MSG_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send"; /** *@@ -32,4 +34,14 @@ public interface WxMaMsgService { **/ void sendTemplateMsg(WxMaTemplateMessage templateMessage) throws WxErrorException; + + + /** + *+ * 下发小程序和公众号统一的服务消息 + * 详情请见: 下发小程序和公众号统一的服务消息 + * 接口url格式:https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN + *+ */ + void sendUniformMsg(WxMaUniformMessage uniformMessage) throws WxErrorException; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java index c2222bc93e..2903737486 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java @@ -1,14 +1,15 @@ package cn.binarywang.wx.miniapp.api; -import me.chanjar.weixin.common.exception.WxErrorException; +import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; +import me.chanjar.weixin.common.error.WxErrorException; import java.io.File; /** *- * 二维码相关操作接口 + * 二维码相关操作接口. * - * 接口A(createWxCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。 + * 接口A(createWxaCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。 * * 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html *@@ -16,11 +17,13 @@ * @author Binary Wang */ public interface WxMaQrcodeService { + String CREATE_QRCODE_URL = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode"; + String GET_WXACODE_URL = "https://api.weixin.qq.com/wxa/getwxacode"; + String GET_WXACODE_UNLIMIT_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit"; /** - * 接口C + * 接口C: 获取小程序页面二维码. *- * 获取小程序页面二维码 * 适用于需要的码数量较少的业务场景 * 通过该接口,仅能生成已发布的小程序的二维码。 * 可以在开发者工具预览时生成开发版的带参二维码。 @@ -35,79 +38,38 @@ public interface WxMaQrcodeService { File createQrcode(String path) throws WxErrorException; /** - * 接口A - * 获取小程序码 + * 接口A: 获取小程序码. * - * @param path 不能为空,最大长度 128 字节 - * @param width 默认430 二维码的宽度 - * @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 - * @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} - * @return - * @throws WxErrorException + * @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, LineColor 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: 获取小程序码(永久有效、数量暂无限制). + *
* 通过该接口生成的小程序码,永久有效,数量暂无限制。 * 用户扫描该码进入小程序后,将统一打开首页,开发者需在对应页面根据获取的码中 scene 字段的值,再做处理逻辑。 * 使用如下代码可以获取到二维码中的 scene 字段的值。 * 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode + ** * @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) * @param page 必须是已经发布的小程序页面,例如 "pages/index/index" ,如果不填写这个字段,默认跳主页面 * @param width 默认false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 * @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 * @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} - * @return - * @throws WxErrorException - */ - File createWxCodeLimit(String scene, String page, int width, boolean autoColor, LineColor lineColor) throws WxErrorException; - - File createWxCodeLimit(String scene, String page) throws WxErrorException; - - /** - * lineColor 包装类 - * 用于描述二维码(小程序码)颜色(RGB参数值),详情请查看文档 + * @param isHyaline 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 */ - public static class LineColor { - - private String r = "0", g = "0", b = "0"; - - public LineColor(String r, String g, String b) { - this.r = r; - this.g = g; - this.b = b; - } - - public String getR() { - return r; - } - - public void setR(String r) { - this.r = r; - } - - public String getG() { - return g; - } - - public void setG(String g) { - this.g = g; - } + File createWxaCodeUnlimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException; - public String getB() { - return b; - } + File createWxaCodeUnlimit(String scene, String page) throws WxErrorException; - public void setB(String b) { - this.b = b; - } - } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java index 9098d4ac48..0904d606c1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java @@ -1,7 +1,10 @@ package cn.binarywang.wx.miniapp.api; +import java.io.File; + +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.config.WxMaConfig; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; @@ -11,20 +14,40 @@ */ public interface WxMaService { /** - * 获取access_token + * 获取access_token. */ String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; + String JSCODE_TO_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session"; + + String IMG_SEC_CHECK_URL = "https://api.weixin.qq.com/wxa/img_sec_check"; + + /** + *+ * 校验一张图片是否含有违法违规内容. + * 应用场景举例:1)图片智能鉴黄:涉及拍照的工具类应用(如美拍,识图类应用)用户拍照上传检测;电商类商品上架图片检测;媒体类用户文章里的图片检测等;2)敏感人脸识别:用户头像;媒体类用户文章里的图片检测;社交类用户上传的图片检测等。频率限制:单个 appId 调用上限为 1000 次/分钟,100,000 次/天 + * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api/imgSecCheck.html + *+ */ + boolean imgSecCheck(File file) throws WxErrorException; + + /** + * 获取登录后的session信息. + * + * @param jsCode 登录时获取的 code + */ + WxMaJscode2SessionResult jsCode2SessionInfo(String jsCode) throws WxErrorException; + /** *- * 验证消息的确来自微信服务器 + * 验证消息的确来自微信服务器. * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN **/ boolean checkSignature(String timestamp, String nonce, String signature); /** - * 获取access_token, 不强制刷新access_token + * 获取access_token, 不强制刷新access_token. * * @see #getAccessToken(boolean) */ @@ -32,7 +55,7 @@ public interface WxMaService { /** *- * 获取access_token,本方法线程安全 + * 获取access_token,本方法线程安全. * 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限 * * 另:本service的所有方法都会在access_token过期是调用此方法 @@ -47,12 +70,12 @@ public interface WxMaService { String getAccessToken(boolean forceRefresh) throws WxErrorException; /** - * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求 + * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求. */ String get(String url, String queryParam) throws WxErrorException; /** - * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求 + * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求. */ String post(String url, String postData) throws WxErrorException; @@ -67,7 +90,7 @@ public interface WxMaService { /** *- * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试 + * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试. * 默认:1000ms **/ @@ -75,59 +98,94 @@ public interface WxMaService { /** *- * 设置当微信系统响应系统繁忙时,最大重试次数 + * 设置当微信系统响应系统繁忙时,最大重试次数. * 默认:5次 **/ void setMaxRetryTimes(int maxRetryTimes); /** - * 获取WxMaConfig 对象 + * 获取WxMaConfig 对象. * * @return WxMaConfig */ WxMaConfig getWxMaConfig(); /** - * 注入 {@link WxMaConfig} 的实现 + * 注入 {@link WxMaConfig} 的实现. */ void setWxMaConfig(WxMaConfig wxConfigProvider); /** - * 返回消息(客服消息和模版消息)发送接口方法实现类,以方便调用其各个接口 + * 返回消息(客服消息和模版消息)发送接口方法实现类,以方便调用其各个接口. * * @return WxMaMsgService */ WxMaMsgService getMsgService(); /** - * 返回素材相关接口方法的实现类对象,以方便调用其各个接口 + * 返回素材相关接口方法的实现类对象,以方便调用其各个接口. * * @return WxMaMediaService */ WxMaMediaService getMediaService(); /** - * 返回用户相关接口方法的实现类对象,以方便调用其各个接口 + * 返回用户相关接口方法的实现类对象,以方便调用其各个接口. * * @return WxMaUserService */ WxMaUserService getUserService(); /** - * 返回二维码相关接口方法的实现类对象,以方便调用其各个接口 + * 返回二维码相关接口方法的实现类对象,以方便调用其各个接口. * * @return WxMaQrcodeService */ WxMaQrcodeService getQrcodeService(); /** - * 初始化http请求对象 + * 返回模板配置相关接口方法的实现类对象, 以方便调用其各个接口. + * + * @return WxMaTemplateService + */ + WxMaTemplateService getTemplateService(); + + /** + * 数据分析相关查询服务 + * + * @return WxMaAnalysisService + */ + WxMaAnalysisService getAnalysisService(); + + /** + * 返回代码操作相关的 API + * + * @return WxMaCodeService + */ + WxMaCodeService getCodeService(); + + /** + * 返回jsapi操作相关的 API服务类对象 + * + * @return WxMaJsapiService + */ + WxMaJsapiService getJsapiService(); + + /** + * 小程序修改服务器地址、成员管理 API + * + * @return WxMaSettingService + */ + WxMaSettingService getSettingService(); + + /** + * 初始化http请求对象. */ void initHttp(); /** - * 请求http请求相关信息 + * 请求http请求相关信息. */ RequestHttp getRequestHttp(); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSettingService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSettingService.java new file mode 100644 index 0000000000..8cc7934988 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSettingService.java @@ -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 Charming + * @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; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaTemplateService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaTemplateService.java new file mode 100644 index 0000000000..1dbf052695 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaTemplateService.java @@ -0,0 +1,89 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateAddResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryGetResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult; +import me.chanjar.weixin.common.error.WxErrorException; + +import java.util.List; + +public interface WxMaTemplateService { + + //获取小程序模板库标题列表 + String TEMPLATE_LIBRARY_LIST_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/library/list"; + + //获取模板库某个模板标题下关键词库 + String TEMPLATE_LIBRARY_KEYWORD_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get"; + + //组合模板并添加至帐号下的个人模板库 + String TEMPLATE_ADD_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/add"; + + //获取帐号下已存在的模板列表 + String TEMPLATE_LIST_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/list"; + + //删除帐号下的某个模板 + String TEMPLATE_DEL_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/del"; + + /** + *+ * 获取小程序模板库标题列表 + * + * 详情请见: 获取小程序模板库标题列表 + * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/library/list?access_token=ACCESS_TOKEN + *+ * @param offset + * @param count + * @return + */ + WxMaTemplateLibraryListResult findTemplateLibraryList(int offset, int count) throws WxErrorException; + + /** + *+ * 获取模板库某个模板标题下关键词库 + * + * 详情请见: 获取小程序模板库标题列表 + * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get?access_token=ACCESS_TOKEN + *+ * @param id + * @return + */ + WxMaTemplateLibraryGetResult findTemplateLibraryKeywordList(String id) throws WxErrorException; + + /** + *+ * 组合模板并添加至帐号下的个人模板库 + * + * 详情请见: 获取小程序模板库标题列表 + * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/add?access_token=ACCESS_TOKEN + *+ * @param id + * @param keywordIdList + * @return + */ + WxMaTemplateAddResult addTemplate(String id, ListkeywordIdList) throws WxErrorException; + + /** + * + * 获取帐号下已存在的模板列表 + * + * 详情请见: 获取小程序模板库标题列表 + * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=ACCESS_TOKEN + *+ * @param offset + * @param count + * @return + */ + WxMaTemplateListResult findTemplateList(int offset, int count) throws WxErrorException; + + /** + *+ * 删除帐号下的某个模板 + * + * 详情请见: 获取小程序模板库标题列表 + * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=ACCESS_TOKEN + *+ * @param templateId + */ + boolean delTemplate(String templateId) throws WxErrorException; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java index 84b17378ca..a4abdc04d4 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java @@ -1,26 +1,28 @@ package cn.binarywang.wx.miniapp.api; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; + +import java.util.Map; /** - * 用户信息相关操作接口 + * 用户信息相关操作接口. * * @author Binary Wang */ public interface WxMaUserService { - String JSCODE_TO_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session"; /** - * 获取登录后的session信息 + * 获取登录后的session信息. * * @param jsCode 登录时获取的 code */ WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException; /** - * 解密用户敏感数据 + * 解密用户敏感数据. * * @param sessionKey 会话密钥 * @param encryptedData 消息密文 @@ -29,7 +31,26 @@ public interface WxMaUserService { WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr); /** - * 验证用户信息完整性 + * 上报用户数据后台接口. + *小游戏可以通过本接口上报key-value数据到用户的CloudStorage。
+ * 文档参考https://developers.weixin.qq.com/minigame/dev/document/open-api/data/setUserStorage.html + * @param kvMap 要上报的数据 + * @param sessionKey 通过wx.login 获得的登录态 + * @param openid + */ + void setUserStorage(MapkvMap, String sessionKey, String openid) throws WxErrorException; + + /** + * 解密用户手机号信息. + * + * @param sessionKey 会话密钥 + * @param encryptedData 消息密文 + * @param ivStr 加密算法的初始向量 + */ + WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr); + + /** + * 验证用户信息完整性. * * @param sessionKey 会话密钥 * @param rawData 微信用户基本信息 diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImpl.java new file mode 100644 index 0000000000..dc7fe42437 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImpl.java @@ -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 Charming + * @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 getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_DAILY_SUMMARY_TREND_URL, beginDate, endDate, + new TypeToken >() { + }.getType()); + } + + @Override + public List
getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_DAILY_VISIT_TREND_URL, beginDate, endDate, + new TypeToken >() { + }.getType()); + } + + @Override + public List
getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_WEEKLY_VISIT_TREND_URL, beginDate, endDate, + new TypeToken >() { + }.getType()); + } + + @Override + public List
getMonthlyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_MONTHLY_VISIT_TREND_URL, beginDate, endDate, + new TypeToken >() { + }.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
getVisitPage(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_VISIT_PAGE_URL, beginDate, endDate, + new TypeToken >() { + }.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
返回的类型 + * @return List 类型的数据 + */ + private List 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(); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java new file mode 100644 index 0000000000..a460f4a314 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java @@ -0,0 +1,158 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import java.io.File; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +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; + +/** + * @author Charming + * @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(String path) throws WxErrorException { + String appId = this.wxMaService.getWxMaConfig().getAppid(); + Path qrCodeFilePath = null; + try { + RequestExecutor executor = BaseMediaDownloadRequestExecutor + .create(this.wxMaService.getRequestHttp(), Files.createTempDirectory("weixin-java-tools-ma-" + appId).toFile()); + + final StringBuilder url = new StringBuilder(GET_QRCODE_URL); + if (StringUtils.isNotBlank(path)) { + url.append("?path=").append(URLEncoder.encode(path, StandardCharsets.UTF_8.name())); + } + + qrCodeFilePath = this.wxMaService.execute(executor, url.toString(), 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 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 >() { + }.getType()); + } else { + return null; + } + } + + @Override + public List
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 >() { + }.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); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaJsapiServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaJsapiServiceImpl.java new file mode 100644 index 0000000000..8164db8bb6 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaJsapiServiceImpl.java @@ -0,0 +1,75 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaJsapiService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.RandomUtils; +import me.chanjar.weixin.common.util.crypto.SHA1; + +import java.util.concurrent.locks.Lock; + +/** + *
+ * Created by BinaryWang on 2018/8/5. + *+ * + * @author Binary Wang + */ +public class WxMaJsapiServiceImpl implements WxMaJsapiService { + private static final JsonParser JSON_PARSER = new JsonParser(); + + private WxMaService wxMaService; + + public WxMaJsapiServiceImpl(WxMaService wxMaService) { + this.wxMaService = wxMaService; + } + + @Override + public String getJsapiTicket() throws WxErrorException { + return getJsapiTicket(false); + } + + @Override + public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { + Lock lock = this.wxMaService.getWxMaConfig().getJsapiTicketLock(); + try { + lock.lock(); + if (forceRefresh) { + this.wxMaService.getWxMaConfig().expireJsapiTicket(); + } + + if (this.wxMaService.getWxMaConfig().isJsapiTicketExpired()) { + String responseContent = this.wxMaService.get(GET_JSAPI_TICKET_URL, null); + JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); + int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); + this.wxMaService.getWxMaConfig().updateJsapiTicket(jsapiTicket, expiresInSeconds); + } + } finally { + lock.unlock(); + } + return this.wxMaService.getWxMaConfig().getJsapiTicket(); + } + + @Override + public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { + long timestamp = System.currentTimeMillis() / 1000; + String randomStr = RandomUtils.getRandomStr(); + String jsapiTicket = getJsapiTicket(false); + String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, + "noncestr=" + randomStr, "timestamp=" + timestamp, "url=" + url); + return WxJsapiSignature + .builder() + .appId(this.wxMaService.getWxMaConfig().getAppid()) + .timestamp(timestamp) + .nonceStr(randomStr) + .url(url) + .signature(signature) + .build(); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMediaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMediaServiceImpl.java index 66ad3c2a91..695f9578d1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMediaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMediaServiceImpl.java @@ -2,15 +2,13 @@ import cn.binarywang.wx.miniapp.api.WxMaMediaService; import cn.binarywang.wx.miniapp.api.WxMaService; -import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -22,8 +20,6 @@ * @author Binary Wang */ public class WxMaMediaServiceImpl implements WxMaMediaService { - private final Logger log = LoggerFactory.getLogger(this.getClass()); - private WxMaService wxMaService; public WxMaMediaServiceImpl(WxMaService wxMaService) { @@ -35,8 +31,7 @@ public WxMediaUploadResult uploadMedia(String mediaType, String fileType, InputS try { return this.uploadMedia(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); } catch (IOException e) { - e.printStackTrace(); - throw new WxErrorException(WxError.newBuilder().setErrorMsg(e.getMessage()).build()); + throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); } } @@ -49,12 +44,11 @@ public WxMediaUploadResult uploadMedia(String mediaType, File file) throws WxErr @Override public File getMedia(String mediaId) throws WxErrorException { try { - RequestExecutorexecutor = MediaDownloadRequestExecutor + RequestExecutor executor = BaseMediaDownloadRequestExecutor .create(this.wxMaService.getRequestHttp(), Files.createTempDirectory("wxma").toFile()); return this.wxMaService.execute(executor, MEDIA_GET_URL, "media_id=" + mediaId); } catch (IOException e) { - this.log.error(e.getMessage(), e); - throw new WxErrorException(WxError.newBuilder().setErrorMsg(e.getMessage()).build()); + throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImpl.java index 70a4e50445..e0403a5103 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImpl.java @@ -4,10 +4,12 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; +import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; +import cn.binarywang.wx.miniapp.constant.WxMaConstants; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; /** * @author Binary Wang @@ -30,7 +32,16 @@ public boolean sendKefuMsg(WxMaKefuMessage message) throws WxErrorException { public void sendTemplateMsg(WxMaTemplateMessage templateMessage) throws WxErrorException { String responseContent = this.wxMaService.post(TEMPLATE_MSG_SEND_URL, templateMessage.toJson()); JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); - if (jsonObject.get("errcode").getAsInt() != 0) { + if (jsonObject.get(WxMaConstants.ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent)); + } + } + + @Override + public void sendUniformMsg(WxMaUniformMessage uniformMessage) throws WxErrorException { + String responseContent = this.wxMaService.post(UNIFORM_MSG_SEND_URL, uniformMessage.toJson()); + JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); + if (jsonObject.get(WxMaConstants.ERRCODE).getAsInt() != 0) { throw new WxErrorException(WxError.fromJson(responseContent)); } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java index fd58855b3d..277418e752 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java @@ -2,11 +2,12 @@ import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; import cn.binarywang.wx.miniapp.bean.WxMaQrcode; import cn.binarywang.wx.miniapp.bean.WxMaWxcode; -import cn.binarywang.wx.miniapp.bean.WxMaWxcodeLimit; +import cn.binarywang.wx.miniapp.bean.WxaCodeUnlimit; import cn.binarywang.wx.miniapp.util.http.QrCodeRequestExecutor; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import java.io.File; @@ -22,9 +23,8 @@ public WxMaQrcodeServiceImpl(WxMaService wxMaService) { @Override public File createQrcode(String path, int width) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode"; return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), - url, new WxMaQrcode(path, width)); + CREATE_QRCODE_URL, new WxMaQrcode(path, width)); } @Override @@ -33,43 +33,44 @@ public File createQrcode(String path) throws WxErrorException { } @Override - public File createWxCode(String path, int width, boolean autoColor, LineColor lineColor) throws WxErrorException { - String url = "https://api.weixin.qq.com/wxa/getwxacode"; + public File createWxaCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException { WxMaWxcode wxMaWxcode = new WxMaWxcode(); wxMaWxcode.setPath(path); wxMaWxcode.setWidth(width); wxMaWxcode.setAutoColor(autoColor); wxMaWxcode.setLineColor(lineColor); + wxMaWxcode.setHyaline(isHyaline); return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), - url, wxMaWxcode); + GET_WXACODE_URL, wxMaWxcode); } @Override - public File createWxCode(String path, int width) throws WxErrorException { - return this.createWxCode(path, width, true, null); + public File createWxaCode(String path, int width) throws WxErrorException { + return this.createWxaCode(path, width, true, null, false); } @Override - public File createWxCode(String path) throws WxErrorException { - return this.createWxCode(path, 430, true, null); + public File createWxaCode(String path) throws WxErrorException { + return this.createWxaCode(path, 430, true, null, false); } @Override - public File createWxCodeLimit(String scene, String page, int width, boolean autoColor, LineColor lineColor) throws WxErrorException { - String url = "http://api.weixin.qq.com/wxa/getwxacodeunlimit"; - WxMaWxcodeLimit wxMaWxcodeLimit = new WxMaWxcodeLimit(); - wxMaWxcodeLimit.setScene(scene); - wxMaWxcodeLimit.setPage(page); - wxMaWxcodeLimit.setWidth(width); - wxMaWxcodeLimit.setAutoColor(autoColor); - wxMaWxcodeLimit.setLineColor(lineColor); + public File createWxaCodeUnlimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline) + throws WxErrorException { + 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()), - url, wxMaWxcodeLimit); + GET_WXACODE_UNLIMIT_URL, wxaCodeUnlimit); } @Override - public File createWxCodeLimit(String scene, String page) throws WxErrorException { - return this.createWxCodeLimit(scene, page, 430, true, null); + public File createWxaCodeUnlimit(String scene, String page) throws WxErrorException { + return this.createWxaCodeUnlimit(scene, page, 430, true, null, false); } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java index 106f020e53..9c8ac82d73 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java @@ -1,15 +1,11 @@ package cn.binarywang.wx.miniapp.api.impl; -import cn.binarywang.wx.miniapp.api.*; -import cn.binarywang.wx.miniapp.config.WxMaConfig; -import com.google.gson.JsonParser; -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.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.*; -import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; -import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; +import java.io.File; +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; @@ -19,14 +15,41 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.concurrent.locks.Lock; +import cn.binarywang.wx.miniapp.api.WxMaAnalysisService; +import cn.binarywang.wx.miniapp.api.WxMaCodeService; +import cn.binarywang.wx.miniapp.api.WxMaJsapiService; +import cn.binarywang.wx.miniapp.api.WxMaMediaService; +import cn.binarywang.wx.miniapp.api.WxMaMsgService; +import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.WxMaSettingService; +import cn.binarywang.wx.miniapp.api.WxMaTemplateService; +import cn.binarywang.wx.miniapp.api.WxMaUserService; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.config.WxMaConfig; +import com.google.common.base.Joiner; +import com.google.gson.Gson; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.DataUtils; +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.common.util.http.HttpType; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; + +import static cn.binarywang.wx.miniapp.constant.WxMaConstants.ErrorCode.*; /** * @author Binary Wang */ public class WxMaServiceImpl implements WxMaService, RequestHttp { - private static final JsonParser JSON_PARSER = new JsonParser(); private final Logger log = LoggerFactory.getLogger(this.getClass()); private CloseableHttpClient httpClient; @@ -37,10 +60,17 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp params = new HashMap<>(8); + params.put("appid", config.getAppid()); + params.put("secret", config.getSecret()); + params.put("js_code", jsCode); + params.put("grant_type", "authorization_code"); + + String result = get(JSCODE_TO_SESSION_URL, Joiner.on("&").withKeyValueSeparator("=").join(params)); + return WxMaJscode2SessionResult.fromJson(result); + } + @Override public boolean checkSignature(String timestamp, String nonce, String signature) { try { @@ -147,6 +197,7 @@ public String post(String url, String postData) throws WxErrorException { /** * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 */ + @Override public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { int retryTimes = 0; do { @@ -179,7 +230,9 @@ public T execute(RequestExecutor executor, String uri, E data) thro throw new RuntimeException("微信服务端异常,超出重试次数"); } - public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + private T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + E dataForLog = DataUtils.handleDataWithSecret(data); + if (uri.contains("access_token=")) { throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); } @@ -189,17 +242,16 @@ public synchronized T executeInternal(RequestExecutor executor, Str try { T result = executor.execute(uriWithAccessToken, data); - this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); + this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); return result; } catch (WxErrorException e) { WxError error = e.getError(); /* * 发生以下情况时尝试刷新access_token - * 40001 获取access_token时AppSecret错误,或者access_token无效 - * 42001 access_token超时 - * 40014 不合法的access_token,请开发者认真比对access_token的有效性(如是否过期) */ - if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001 || error.getErrorCode() == 40014) { + if (error.getErrorCode() == ERR_40001 + || error.getErrorCode() == ERR_42001 + || error.getErrorCode() == ERR_40014) { // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token this.getWxMaConfig().expireAccessToken(); if (this.getWxMaConfig().autoRefreshToken()) { @@ -208,12 +260,12 @@ public synchronized T executeInternal(RequestExecutor executor, Str } if (error.getErrorCode() != 0) { - this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); + this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); throw new WxErrorException(error, e); } return null; } catch (IOException e) { - this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); + this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); throw new RuntimeException(e); } } @@ -258,4 +310,29 @@ public WxMaUserService getUserService() { public WxMaQrcodeService getQrcodeService() { return this.qrCodeService; } + + @Override + public WxMaTemplateService getTemplateService() { + return this.templateService; + } + + @Override + public WxMaAnalysisService getAnalysisService() { + return this.analysisService; + } + + @Override + public WxMaCodeService getCodeService() { + return this.codeService; + } + + @Override + public WxMaJsapiService getJsapiService() { + return this.jsapiService; + } + + @Override + public WxMaSettingService getSettingService() { + return this.settingService; + } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSettingServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSettingServiceImpl.java new file mode 100644 index 0000000000..ac45e6ce31 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSettingServiceImpl.java @@ -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 Charming + * @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 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 param = new HashMap<>(1); + param.put("wechatid", wechatId); + this.wxMaService.post(UNBIND_TESTER_URL, WxMaGsonBuilder.create().toJson(param)); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImpl.java new file mode 100644 index 0000000000..9570c07a91 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImpl.java @@ -0,0 +1,101 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.WxMaTemplateService; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateAddResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryGetResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class WxMaTemplateServiceImpl implements WxMaTemplateService { + + private WxMaService wxMaService; + + public WxMaTemplateServiceImpl(WxMaService wxMaService){ + this.wxMaService = wxMaService; + } + + @Override + public WxMaTemplateLibraryListResult findTemplateLibraryList(int offset, int count) throws WxErrorException { + + Map params = new HashMap<>(); + params.put("offset", offset); + params.put("count", count); + + String responseText = this.wxMaService.post(TEMPLATE_LIBRARY_LIST_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return WxMaTemplateLibraryListResult.fromJson(responseText); + }else { + throw new WxErrorException(wxError); + } + } + + @Override + public WxMaTemplateLibraryGetResult findTemplateLibraryKeywordList(String id) throws WxErrorException { + + Map params = new HashMap<>(); + params.put("id", id); + + String responseText = this.wxMaService.post(TEMPLATE_LIBRARY_KEYWORD_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return WxMaTemplateLibraryGetResult.fromJson(responseText); + }else { + throw new WxErrorException(wxError); + } + } + + @Override + public WxMaTemplateAddResult addTemplate(String id, List keywordIdList) throws WxErrorException { + + Map params = new HashMap<>(); + params.put("id", id); + params.put("keyword_id_list", keywordIdList.toArray()); + + String responseText = this.wxMaService.post(TEMPLATE_ADD_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return WxMaTemplateAddResult.fromJson(responseText); + }else { + throw new WxErrorException(wxError); + } + } + + @Override + public WxMaTemplateListResult findTemplateList(int offset, int count) throws WxErrorException { + + Map params = new HashMap<>(); + params.put("offset", offset); + params.put("count", count); + + String responseText = this.wxMaService.post(TEMPLATE_LIST_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return WxMaTemplateListResult.fromJson(responseText); + }else { + throw new WxErrorException(wxError); + } + } + + @Override + public boolean delTemplate(String templateId) throws WxErrorException { + Map params = new HashMap<>(); + params.put("template_id", templateId); + + String responseText = this.wxMaService.post(TEMPLATE_DEL_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return true; + }else { + throw new WxErrorException(wxError); + } + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java index e2fdb9dc2b..f8177bf1d6 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java @@ -3,14 +3,22 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.WxMaUserService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils; -import com.google.common.base.Joiner; -import me.chanjar.weixin.common.exception.WxErrorException; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.SignUtils; +import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; -import java.util.HashMap; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.Map; /** @@ -19,21 +27,13 @@ public class WxMaUserServiceImpl implements WxMaUserService { private WxMaService service; - WxMaUserServiceImpl(WxMaService service) { + public WxMaUserServiceImpl(WxMaService service) { this.service = service; } @Override public WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException { - final WxMaConfig config = service.getWxMaConfig(); - Map params = new HashMap<>(); - params.put("appid", config.getAppid()); - params.put("secret", config.getSecret()); - params.put("js_code", jsCode); - params.put("grant_type", "authorization_code"); - - String result = this.service.get(JSCODE_TO_SESSION_URL, Joiner.on("&").withKeyValueSeparator("=").join(params)); - return WxMaJscode2SessionResult.fromJson(result); + return service.jsCode2SessionInfo(jsCode); } @Override @@ -41,10 +41,38 @@ public WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String return WxMaUserInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)); } + @Override + public void setUserStorage(Map kvMap, String sessionKey, String openid) throws WxErrorException { + final WxMaConfig config = this.service.getWxMaConfig(); + JsonObject param = new JsonObject(); + JsonArray array = new JsonArray(); + for (Map.Entry e : kvMap.entrySet()) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("key", e.getKey()); + jsonObject.addProperty("value", e.getValue()); + array.add(jsonObject); + } + param.add("kv_list", array); + String params = param.toString(); + String signature = SignUtils.createHmacSha256Sign(params, sessionKey); + String url = String.format("https://api.weixin.qq.com/wxa/set_user_storage" + + "?appid=%s&signature=%s&openid=%s&sig_method=%s", + config.getAppid(), signature, openid, "hmac_sha256"); + String result = this.service.post(url, params); + WxError error = WxError.fromJson(result); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + } + + @Override + public WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr) { + return WxMaPhoneNumberInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)); + } + @Override public boolean checkUserInfo(String sessionKey, String rawData, String signature) { final String generatedSignature = DigestUtils.sha1Hex(rawData + sessionKey); - System.out.println(generatedSignature); return generatedSignature.equals(signature); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcodeWrapper.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java similarity index 53% rename from weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcodeWrapper.java rename to weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java index 37c5c5db88..cb444c94c1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcodeWrapper.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java @@ -3,14 +3,17 @@ import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; /** - * 微信二维码(小程序码)包装器 - * Created by Element on 2017/7/27. + * 微信二维码(小程序码)包装器. + * + * @author Element */ -public abstract class WxMaQrcodeWrapper { +public abstract class AbstractWxMaQrcodeWrapper { + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } @Override public String toString() { - return WxMaGsonBuilder.create().toJson(this); + return this.toJson(); } - } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaCodeLineColor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaCodeLineColor.java new file mode 100644 index 0000000000..2afb4c073e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaCodeLineColor.java @@ -0,0 +1,18 @@ +package cn.binarywang.wx.miniapp.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * + * lineColor 包装类 + * 用于描述二维码(小程序码)颜色(RGB参数值), + * 详情请查看文档 https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html + *+ * @author Element + */ +@Data +@AllArgsConstructor +public class WxMaCodeLineColor { + private String r = "0", g = "0", b = "0"; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaDomainAction.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaDomainAction.java new file mode 100644 index 0000000000..313f6cbed8 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaDomainAction.java @@ -0,0 +1,58 @@ +package cn.binarywang.wx.miniapp.bean; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 域名相关操作 + * + * @author Charming + * @since 2018-04-27 15:45 + */ +@Data +@Builder +public class WxMaDomainAction implements Serializable { + private static final long serialVersionUID = -2898601966852935708L; + /** + * add添加, delete删除, set覆盖, get获取。当参数是get时不需要填四个域名字段 + */ + private String action; + /** + * request合法域名,当action参数是get时不需要此字段。 + */ + @SerializedName("requestdomain") + private ListrequestDomain; + /** + * socket合法域名,当action参数是get时不需要此字段。 + */ + @SerializedName("wsrequestdomain") + private List wsRequestDomain; + /** + * uploadFile合法域名,当action参数是get时不需要此字段。 + */ + @SerializedName("uploaddomain") + private List uploadDomain; + /** + * downloadFile合法域名,当action参数是get时不需要此字段。 + */ + @SerializedName("downloaddomain") + private List downloadDomain; + /** + * 小程序业务域名,当action参数是get时不需要此字段。 + */ + @SerializedName("webviewdomain") + private List webViewDomain; + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } + + public static WxMaDomainAction fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaDomainAction.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java index 471e6c46ec..85b4767702 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java @@ -2,19 +2,27 @@ import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; /** - * {"session_key":"nzoqhc3OnwHzeTxJs+inbQ==","expires_in":2592000,"openid":"oVBkZ0aYgDMDIywRdgPW8-joxXc4"} - * + * + * code换取session_key接口的响应 + * 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject + * 微信返回报文:{"session_key":"nzoqhc3OnwHzeTxJs+inbQ==","openid":"oVBkZ0aYgDMDIywRdgPW8-joxXc4"} + ** @author Binary Wang */ -public class WxMaJscode2SessionResult { +@Data +@EqualsAndHashCode(callSuper = false) +public class WxMaJscode2SessionResult implements Serializable { + private static final long serialVersionUID = -1060216618475607933L; + @SerializedName("session_key") private String sessionKey; - @SerializedName("expires_in") - private Integer expiresin; - @SerializedName("openid") private String openid; @@ -25,36 +33,4 @@ public static WxMaJscode2SessionResult fromJson(String json) { return WxMaGsonBuilder.create().fromJson(json, WxMaJscode2SessionResult.class); } - public String getSessionKey() { - return sessionKey; - } - - public void setSessionKey(String sessionKey) { - this.sessionKey = sessionKey; - } - - public Integer getExpiresin() { - return expiresin; - } - - public void setExpiresin(Integer expiresin) { - this.expiresin = expiresin; - } - - public String getOpenid() { - return openid; - } - - public void setOpenid(String openid) { - this.openid = openid; - } - - public String getUnionid() { - return unionid; - } - - public void setUnionid(String unionid) { - this.unionid = unionid; - } - } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java index d75fbf12ae..ee11476878 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java @@ -1,95 +1,106 @@ package cn.binarywang.wx.miniapp.bean; -import cn.binarywang.wx.miniapp.builder.ImageBuilder; -import cn.binarywang.wx.miniapp.builder.TextBuilder; +import cn.binarywang.wx.miniapp.builder.ImageMessageBuilder; +import cn.binarywang.wx.miniapp.builder.LinkMessageBuilder; +import cn.binarywang.wx.miniapp.builder.MaPageMessageBuilder; +import cn.binarywang.wx.miniapp.builder.TextMessageBuilder; import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; import java.io.Serializable; /** - * 客服消息 + * 客服消息. * * @author Binary Wang */ +@Data public class WxMaKefuMessage implements Serializable { private static final long serialVersionUID = -9196732086954365246L; + @SerializedName("touser") private String toUser; + + @SerializedName("msgtype") private String msgType; - private String content; - private String mediaId; - private String thumbMediaId; - private String title; - private String description; - /** - * 获得文本消息builder - */ - public static TextBuilder TEXT() { - return new TextBuilder(); - } + @SerializedName("text") + private KfText text; - /** - * 获得图片消息builder - */ - public static ImageBuilder IMAGE() { - return new ImageBuilder(); - } + @SerializedName("image") + private KfImage image; - public String getToUser() { - return this.toUser; - } + @SerializedName("link") + private KfLink link; - public void setToUser(String toUser) { - this.toUser = toUser; - } - - public String getMsgType() { - return this.msgType; - } + @SerializedName("miniprogrampage") + private KfMaPage maPage; - public void setMsgType(String msgType) { - this.msgType = msgType; + @Data + @AllArgsConstructor + public static class KfText { + private String content; } - public String getContent() { - return this.content; + @Data + @AllArgsConstructor + public static class KfImage { + @SerializedName("media_id") + private String mediaId; } - public void setContent(String content) { - this.content = content; - } + @Data + @Builder + public static class KfLink { + private String title; + private String description; + private String url; - public String getMediaId() { - return this.mediaId; + @SerializedName("thumb_url") + private String thumbUrl; } - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + @Data + @Builder + public static class KfMaPage { + private String title; - public String getThumbMediaId() { - return this.thumbMediaId; - } + @SerializedName("pagepath") + private String pagePath; - public void setThumbMediaId(String thumbMediaId) { - this.thumbMediaId = thumbMediaId; + @SerializedName("thumb_media_id") + private String thumbMediaId; } - public String getTitle() { - return this.title; + /** + * 获得文本消息builder. + */ + public static TextMessageBuilder newTextBuilder() { + return new TextMessageBuilder(); } - public void setTitle(String title) { - this.title = title; + /** + * 获得图片消息builder. + */ + public static ImageMessageBuilder newImageBuilder() { + return new ImageMessageBuilder(); } - public String getDescription() { - return this.description; + /** + * 获得图文链接消息builder. + */ + public static LinkMessageBuilder newLinkBuilder() { + return new LinkMessageBuilder(); } - public void setDescription(String description) { - this.description = description; + /** + * 获得图文链接消息builder. + */ + public static MaPageMessageBuilder newMaPageBuilder() { + return new MaPageMessageBuilder(); } public String toJson() { diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java index 4b201da1cd..d44d155638 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java @@ -1,5 +1,14 @@ package cn.binarywang.wx.miniapp.bean; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils; import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; @@ -7,19 +16,14 @@ import com.google.gson.annotations.SerializedName; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; -import me.chanjar.weixin.common.util.ToStringUtils; +import lombok.Data; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; -import org.apache.commons.io.IOUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.nio.charset.StandardCharsets; /** * @author Binary Wang */ @XStreamAlias("xml") +@Data public class WxMaMessage implements Serializable { private static final long serialVersionUID = -3586245291677274914L; @@ -40,15 +44,18 @@ public class WxMaMessage implements Serializable { @SerializedName("CreateTime") @XStreamAlias("CreateTime") - @XStreamConverter(value = XStreamCDataConverter.class) private Integer createTime; + @SerializedName("MsgType") + @XStreamAlias("MsgType") + @XStreamConverter(value = XStreamCDataConverter.class) + private String msgType; + @SerializedName("MsgDataFormat") @XStreamAlias("MsgDataFormat") @XStreamConverter(value = XStreamCDataConverter.class) - private String msgType; + private String msgDataFormat; - // 文本消息 @SerializedName("Content") @XStreamAlias("Content") @XStreamConverter(value = XStreamCDataConverter.class) @@ -56,10 +63,8 @@ public class WxMaMessage implements Serializable { @SerializedName("MsgId") @XStreamAlias("MsgId") - @XStreamConverter(value = XStreamCDataConverter.class) private Long msgId; - // 图片消息 @SerializedName("PicUrl") @XStreamAlias("PicUrl") @XStreamConverter(value = XStreamCDataConverter.class) @@ -70,12 +75,36 @@ public class WxMaMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private String mediaId; - // 事件消息 @SerializedName("Event") @XStreamAlias("Event") @XStreamConverter(value = XStreamCDataConverter.class) private String event; + @SerializedName("Title") + @XStreamAlias("Title") + @XStreamConverter(value = XStreamCDataConverter.class) + private String title; + + @SerializedName("AppId") + @XStreamAlias("AppId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String appId; + + @SerializedName("PagePath") + @XStreamAlias("PagePath") + @XStreamConverter(value = XStreamCDataConverter.class) + private String pagePath; + + @SerializedName("ThumbUrl") + @XStreamAlias("ThumbUrl") + @XStreamConverter(value = XStreamCDataConverter.class) + private String thumbUrl; + + @SerializedName("ThumbMediaId") + @XStreamAlias("ThumbMediaId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String thumbMediaId; + @SerializedName("SessionFrom") @XStreamAlias("SessionFrom") @XStreamConverter(value = XStreamCDataConverter.class) @@ -90,7 +119,7 @@ public static WxMaMessage fromXml(InputStream is) { } /** - * 从加密字符串转换 + * 从加密字符串转换. * * @param encryptedXml 密文 * @param wxMaConfig 配置存储器对象 @@ -139,98 +168,11 @@ public static WxMaMessage fromEncryptedJson(InputStream inputStream, WxMaConfig @Override public String toString() { - return ToStringUtils.toSimpleString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } public String toJson() { return WxMaGsonBuilder.create().toJson(this); } - public String getToUser() { - return toUser; - } - - public void setToUser(String toUser) { - this.toUser = toUser; - } - - public String getFromUser() { - return fromUser; - } - - public void setFromUser(String fromUser) { - this.fromUser = fromUser; - } - - public Integer getCreateTime() { - return createTime; - } - - public void setCreateTime(Integer createTime) { - this.createTime = createTime; - } - - public String getMsgType() { - return msgType; - } - - public void setMsgType(String msgType) { - this.msgType = msgType; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public Long getMsgId() { - return msgId; - } - - public void setMsgId(Long msgId) { - this.msgId = msgId; - } - - public String getPicUrl() { - return picUrl; - } - - public void setPicUrl(String picUrl) { - this.picUrl = picUrl; - } - - public String getMediaId() { - return mediaId; - } - - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - - public String getEvent() { - return event; - } - - public void setEvent(String event) { - this.event = event; - } - - public String getSessionFrom() { - return sessionFrom; - } - - public void setSessionFrom(String sessionFrom) { - this.sessionFrom = sessionFrom; - } - - public String getEncrypt() { - return encrypt; - } - - public void setEncrypt(String encrypt) { - this.encrypt = encrypt; - } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java new file mode 100644 index 0000000000..6b39a3d718 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean; + +import java.io.Serializable; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Data; + +/** + * 微信用户绑定的手机号相关信息 + * @author Binary Wang + */ +@Data +public class WxMaPhoneNumberInfo implements Serializable { + private static final long serialVersionUID = 6719822331555402137L; + + private String phoneNumber; + private String purePhoneNumber; + private String countryCode; + private Watermark watermark; + + public static WxMaPhoneNumberInfo fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaPhoneNumberInfo.class); + } + + @Data + public static class Watermark { + private String timestamp; + private String appid; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcode.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcode.java index a047d7c8b1..5c17cd1e58 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcode.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcode.java @@ -1,13 +1,17 @@ package cn.binarywang.wx.miniapp.bean; import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Data; +import lombok.EqualsAndHashCode; import java.io.Serializable; /** * @author Binary Wang */ -public class WxMaQrcode extends WxMaQrcodeWrapper implements Serializable { +@Data +@EqualsAndHashCode(callSuper = false) +public class WxMaQrcode extends AbstractWxMaQrcodeWrapper implements Serializable { private static final long serialVersionUID = 5777119669111011584L; private String path; private int width = 430; @@ -21,22 +25,6 @@ public static WxMaQrcode fromJson(String json) { return WxMaGsonBuilder.create().fromJson(json, WxMaQrcode.class); } - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - @Override public String toString() { return WxMaGsonBuilder.create().toJson(this); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateData.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateData.java new file mode 100644 index 0000000000..5eae34b115 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateData.java @@ -0,0 +1,32 @@ +package cn.binarywang.wx.miniapp.bean; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *+ * + * Created by Binary Wang on 2018/9/23. + *+ * + * @author Binary Wang + */ +@Data +@NoArgsConstructor +public class WxMaTemplateData { + private String name; + private String value; + private String color; + + public WxMaTemplateData(String name, String value) { + this.name = name; + this.value = value; + } + + public WxMaTemplateData(String name, String value, String color) { + this.name = name; + this.value = value; + this.color = color; + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java index 79f955c6d2..5a67439478 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java @@ -1,20 +1,32 @@ package cn.binarywang.wx.miniapp.bean; -import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; - import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + /** + * 模板消息. * 参考 https://mp.weixin.qq.com/debug/wxadoc/dev/api/notice.html#接口说明 模板消息部分 * * @author Binary Wang */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder public class WxMaTemplateMessage implements Serializable { private static final long serialVersionUID = 5063374783759519418L; /** + * 接收者(用户)的 openid. ** 参数:touser * 是否必填: 是 @@ -24,6 +36,7 @@ public class WxMaTemplateMessage implements Serializable { private String toUser; /** + * 所需下发的模板消息的id. ** 参数:template_id * 是否必填: 是 @@ -33,6 +46,7 @@ public class WxMaTemplateMessage implements Serializable { private String templateId; /** + * 点击模板卡片后的跳转页面,仅限本小程序内的页面. ** 参数:page * 是否必填: 否 @@ -42,6 +56,7 @@ public class WxMaTemplateMessage implements Serializable { private String page; /** + * 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id. ** 参数:form_id * 是否必填: 是 @@ -51,15 +66,17 @@ public class WxMaTemplateMessage implements Serializable { private String formId; /** + * 模板内容,不填则下发空模板. ** 参数:data * 是否必填: 是 * 描述: 模板内容,不填则下发空模板 **/ - private List data = new ArrayList<>(); + private Listdata; /** + * 模板内容字体的颜色,不填默认黑色. * * 参数:color * 是否必填: 否 @@ -69,6 +86,7 @@ public class WxMaTemplateMessage implements Serializable { private String color; /** + * 模板需要放大的关键词,不填则默认无放大. ** 参数:emphasis_keyword * 是否必填: 否 @@ -77,171 +95,17 @@ public class WxMaTemplateMessage implements Serializable { */ private String emphasisKeyword; - private WxMaTemplateMessage(Builder builder) { - setToUser(builder.toUser); - setTemplateId(builder.templateId); - setPage(builder.page); - setFormId(builder.formId); - setData(builder.data); - setColor(builder.color); - setEmphasisKeyword(builder.emphasisKeyword); - } + public WxMaTemplateMessage addData(WxMaTemplateData datum) { + if (this.data == null) { + this.data = new ArrayList<>(); + } + this.data.add(datum); - public static Builder newBuilder() { - return new Builder(); + return this; } public String toJson() { return WxMaGsonBuilder.create().toJson(this); } - public String getToUser() { - return toUser; - } - - public void setToUser(String toUser) { - this.toUser = toUser; - } - - public String getTemplateId() { - return templateId; - } - - public void setTemplateId(String templateId) { - this.templateId = templateId; - } - - public String getPage() { - return page; - } - - public void setPage(String page) { - this.page = page; - } - - public String getFormId() { - return formId; - } - - public void setFormId(String formId) { - this.formId = formId; - } - - public List getData() { - return data; - } - - public void setData(List data) { - this.data = data; - } - - public String getColor() { - return color; - } - - public void setColor(String color) { - this.color = color; - } - - public String getEmphasisKeyword() { - return emphasisKeyword; - } - - public void setEmphasisKeyword(String emphasisKeyword) { - this.emphasisKeyword = emphasisKeyword; - } - - public static class Data { - private String name; - private String value; - private String color; - - public Data(String name, String value) { - this.name = name; - this.value = value; - } - - public Data(String name, String value, String color) { - this.name = name; - this.value = value; - this.color = color; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getColor() { - return this.color; - } - - public void setColor(String color) { - this.color = color; - } - - } - - public static final class Builder { - private String toUser; - private String templateId; - private String page; - private String formId; - private List data; - private String color; - private String emphasisKeyword; - - private Builder() { - } - - public Builder toUser(String toUser) { - this.toUser = toUser; - return this; - } - - public Builder templateId(String templateId) { - this.templateId = templateId; - return this; - } - - public Builder page(String page) { - this.page = page; - return this; - } - - public Builder formId(String formId) { - this.formId = formId; - return this; - } - - public Builder data(List data) { - this.data = data; - return this; - } - - public Builder color(String color) { - this.color = color; - return this; - } - - public Builder emphasisKeyword(String emphasisKeyword) { - this.emphasisKeyword = emphasisKeyword; - return this; - } - - public WxMaTemplateMessage build() { - return new WxMaTemplateMessage(this); - } - } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUniformMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUniformMessage.java new file mode 100644 index 0000000000..e58ad58a98 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUniformMessage.java @@ -0,0 +1,108 @@ +package cn.binarywang.wx.miniapp.bean; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * 模板消息. + * 参考 https://mp.weixin.qq.com/debug/wxadoc/dev/api/notice.html#接口说明 模板消息部分 + * + * @author Binary Wang + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class WxMaUniformMessage implements Serializable { + private static final long serialVersionUID = 5063374783759519418L; + + /** + * 是否发送公众号模版消息,否则发送小程序模版消息. + */ + private boolean isMpTemplateMsg; + + /** + * 用户openid. + * 可以是小程序的openid,也可以是mp_template_msg.appid对应的公众号的openid + */ + private String toUser; + + /** + * 公众号appid,要求与小程序有绑定且同主体. + */ + private String appid; + + /** + * 公众号或小程序模板ID. + */ + private String templateId; + + /** + * 公众号模板消息所要跳转的url. + */ + private String url; + + /** + * 小程序页面路径. + */ + private String page; + + /** + * 小程序模板消息formid. + */ + private String formId; + + /** + * 公众号模板消息所要跳转的小程序,小程序的必须与公众号具有绑定关系. + */ + private MiniProgram miniProgram; + + /** + * 小程序模板数据. + */ + private Listdata; + + /** + * 模板需要放大的关键词,不填则默认无放大. + */ + private String emphasisKeyword; + + public WxMaUniformMessage addData(WxMaTemplateData datum) { + if (this.data == null) { + this.data = new ArrayList<>(); + } + this.data.add(datum); + + return this; + } + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class MiniProgram implements Serializable { + private static final long serialVersionUID = -7945254706501974849L; + + private String appid; + private String pagePath; + + /** + * 是否使用path,否则使用pagepath. + * 加入此字段是基于微信官方接口变化多端的考虑 + */ + private boolean usePath = false; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUserInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUserInfo.java index e3cc69d913..8b0ed8fe6a 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUserInfo.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUserInfo.java @@ -1,13 +1,17 @@ package cn.binarywang.wx.miniapp.bean; import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; +import lombok.Data; + +import java.io.Serializable; /** * @author Binary Wang */ -public class WxMaUserInfo { +@Data +public class WxMaUserInfo implements Serializable { + private static final long serialVersionUID = 6719822331555402137L; + private String openId; private String nickName; private String gender; @@ -23,109 +27,9 @@ public static WxMaUserInfo fromJson(String json) { return WxMaGsonBuilder.create().fromJson(json, WxMaUserInfo.class); } - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); - } - - public String getOpenId() { - return openId; - } - - public void setOpenId(String openId) { - this.openId = openId; - } - - public String getNickName() { - return nickName; - } - - public void setNickName(String nickName) { - this.nickName = nickName; - } - - public String getGender() { - return gender; - } - - public void setGender(String gender) { - this.gender = gender; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getCity() { - return city; - } - - public void setCity(String city) { - this.city = city; - } - - public String getProvince() { - return province; - } - - public void setProvince(String province) { - this.province = province; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } - - public String getAvatarUrl() { - return avatarUrl; - } - - public void setAvatarUrl(String avatarUrl) { - this.avatarUrl = avatarUrl; - } - - public String getUnionId() { - return unionId; - } - - public void setUnionId(String unionId) { - this.unionId = unionId; - } - - public Watermark getWatermark() { - return watermark; - } - - public void setWatermark(Watermark watermark) { - this.watermark = watermark; - } - + @Data public static class Watermark { private String timestamp; private String appid; - - public String getTimestamp() { - return timestamp; - } - - public void setTimestamp(String timestamp) { - this.timestamp = timestamp; - } - - public String getAppid() { - return appid; - } - - public void setAppid(String appid) { - this.appid = appid; - } } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcode.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcode.java index 9ea674ed98..e538a1bb83 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcode.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcode.java @@ -1,64 +1,36 @@ package cn.binarywang.wx.miniapp.bean; -import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; import java.io.Serializable; /** - * Created by Element on 2017/7/27. + * + * @author Element + * @date 2017/7/27 */ -public class WxMaWxcode extends WxMaQrcodeWrapper implements Serializable { - +@Data +@EqualsAndHashCode(callSuper = false) +public class WxMaWxcode extends AbstractWxMaQrcodeWrapper implements Serializable { private static final long serialVersionUID = 1287399621649210322L; + private String path; private int width = 430; @SerializedName("auto_color") private boolean autoColor = true; + @SerializedName("is_hyaline") + private boolean isHyaline = false; + @SerializedName("line_color") - private WxMaQrcodeService.LineColor lineColor = new WxMaQrcodeService.LineColor("0", "0", "0"); + private WxMaCodeLineColor lineColor = new WxMaCodeLineColor("0", "0", "0"); public static WxMaWxcode fromJson(String json) { return WxMaGsonBuilder.create().fromJson(json, WxMaWxcode.class); } - public static long getSerialVersionUID() { - return serialVersionUID; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - public boolean isAutoColor() { - return autoColor; - } - - public void setAutoColor(boolean autoColor) { - this.autoColor = autoColor; - } - - public WxMaQrcodeService.LineColor getLineColor() { - return lineColor; - } - - public void setLineColor(WxMaQrcodeService.LineColor lineColor) { - this.lineColor = lineColor; - } - } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java deleted file mode 100644 index 7619fe46f2..0000000000 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java +++ /dev/null @@ -1,68 +0,0 @@ -package cn.binarywang.wx.miniapp.bean; - -import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; -import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; -import com.google.gson.annotations.SerializedName; - -import java.io.Serializable; - -/** - * Created by Element on 2017/7/27. - */ -public class WxMaWxcodeLimit extends WxMaQrcodeWrapper implements Serializable { - private static final long serialVersionUID = 4782193774524960401L; - private String scene; - private String page; - - private int width = 430; - - @SerializedName("auto_color") - private boolean autoColor = true; - - @SerializedName("line_color") - private WxMaQrcodeService.LineColor lineColor = new WxMaQrcodeService.LineColor("0", "0", "0"); - - public static WxMaWxcodeLimit fromJson(String json) { - return WxMaGsonBuilder.create().fromJson(json, WxMaWxcodeLimit.class); - } - - public String getPage() { - return page; - } - - public void setPage(String page) { - this.page = page; - } - - public String getScene() { - return scene; - } - - public void setScene(String scene) { - this.scene = scene; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - public boolean isAutoColor() { - return autoColor; - } - - public void setAutoColor(boolean autoColor) { - this.autoColor = autoColor; - } - - public WxMaQrcodeService.LineColor getLineColor() { - return lineColor; - } - - public void setLineColor(WxMaQrcodeService.LineColor lineColor) { - this.lineColor = lineColor; - } -} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxaCodeUnlimit.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxaCodeUnlimit.java new file mode 100644 index 0000000000..05bf134c6b --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxaCodeUnlimit.java @@ -0,0 +1,38 @@ +package cn.binarywang.wx.miniapp.bean; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * 小程序码接口B. + * + * @author Element + * @date 2017/7/27 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class WxaCodeUnlimit extends AbstractWxMaQrcodeWrapper implements Serializable { + private static final long serialVersionUID = 4782193774524960401L; + private String scene; + private String page; + + private int width = 430; + + @SerializedName("auto_color") + private boolean autoColor = true; + + @SerializedName("is_hyaline") + private boolean isHyaline = false; + + @SerializedName("line_color") + private WxMaCodeLineColor lineColor = new WxMaCodeLineColor("0", "0", "0"); + + public static WxaCodeUnlimit fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxaCodeUnlimit.class); + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaRetainInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaRetainInfo.java new file mode 100644 index 0000000000..7021a180e9 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaRetainInfo.java @@ -0,0 +1,43 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +/** + * 访问留存 + * + * @author Charming + * @since 2018-04-28 14:41 + */ +@Data +public class WxMaRetainInfo implements Serializable { + private static final long serialVersionUID = 8986403173656848413L; + /** + * 日留存:日期,yyyyMMdd 格式,如 20170313 + * 周留存:时间,如"20170306-20170312" + * 月留存:时间,如"201702" + */ + @SerializedName(value = "refDate", alternate = "ref_date") + private String refDate; + /** + * 新增用户留存 + * - key: + * - 日留存:标识,0开始,0表示当天,1表示1天后,依此类推,key取值分别是:0,1,2,3,4,5,6,7,14,30 + * - 周留存:标识,0开始,0表示当周,1表示1周后,依此类推,key 取值分别是:0,1,2,3,4 + * - 月留存:标识,0开始,0表示当月,1表示1月后,key取值分别是:0,1 + * - value: key对应日期的新增用户数/活跃用户数(key=0时)或留存用户数(k>0时) + */ + private Map visitUvNew; + /** + * 活跃用户留存 + */ + private Map visitUv; + + public static WxMaRetainInfo fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaRetainInfo.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaSummaryTrend.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaSummaryTrend.java new file mode 100644 index 0000000000..f4ceb0ad95 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaSummaryTrend.java @@ -0,0 +1,37 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * 小程序概况趋势 + * + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaSummaryTrend implements Serializable { + private static final long serialVersionUID = 1379688517709317935L; + /** + * 日期,yyyyMMdd 格式,如 20170313 + */ + @SerializedName(value = "refDate", alternate = "ref_date") + private String refDate; + /** + * 累计用户数 + */ + @SerializedName(value = "visitTotal", alternate = "visit_total") + private Long visitTotal; + /** + * 转发次数 + */ + @SerializedName(value = "sharePv", alternate = "share_pv") + private Long sharePv; + /** + * 转发人数 + */ + @SerializedName(value = "shareUv", alternate = "share_uv") + private Long shareUv; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortrait.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortrait.java new file mode 100644 index 0000000000..5e1164909e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortrait.java @@ -0,0 +1,68 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +/** + * 用户画像 + * + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaUserPortrait implements Serializable { + private static final long serialVersionUID = 5653571047669243178L; + /** + * 时间范围,如: "20170611-20170617" + */ + private String refDate; + /** + * 新用户 + */ + private Item visitUvNew; + /** + * 活跃用户 + */ + private Item visitUv; + + public static WxMaUserPortrait fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaUserPortrait.class); + } + + @Data + public static class Item { + /** + * key: 省份,如北京、广东等 + * value: 活跃用户数或新用户数 + */ + private Map province; + /** + * key: 城市,如北京、广州等 + * value: 活跃用户数或新用户数 + */ + private Map city; + /** + * key: 性别,包括男、女、未知 + * value: 活跃用户数或新用户数 + */ + private Map genders; + /** + * key: 终端类型,包括iPhone, android,其他 + * value: 活跃用户数或新用户数 + */ + private Map platforms; + /** + * key: 机型,如苹果iPhone6, OPPO R9等 + * value: 活跃用户数或新用户数 + */ + private Map devices; + /** + * key: 年龄,包括17岁以下、18-24岁等区间 + * value: 活跃用户数或新用户数 + */ + private Map ages; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistribution.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistribution.java new file mode 100644 index 0000000000..1655eec286 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistribution.java @@ -0,0 +1,83 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +/** + * 访问分布 + * 访问来源:(index="access_source_session_cnt") + * 1:小程序历史列表 + * 2:搜索 + * 3:会话 + * 4:二维码 + * 5:公众号主页 + * 6:聊天顶部 + * 7:系统桌面 + * 8:小程序主页 + * 9:附近的小程序 + * 10:其他 + * 11:模板消息 + * 12:客服消息 + * 13: 公众号菜单 + * 14: APP分享 + * 15: 支付完成页 + * 16: 长按识别二维码 + * 17: 相册选取二维码 + * 18: 公众号文章 + * 19:钱包 + * 20:卡包 + * 21:小程序内卡券 + * 22:其他小程序 + * 23:其他小程序返回 + * 24:卡券适用门店列表 + * 25:搜索框快捷入口 + * 26:小程序客服消息 + * 27:公众号下发 + * 访问时长:(index="access_staytime_info") + * 1: 0-2s + * 2: 3-5s + * 3: 6-10s + * 4: 11-20s + * 5: 20-30s + * 6: 30-50s + * 7: 50-100s + * 8: > 100s + * 平均访问深度:(index="access_depth_info") + * 1: 1页 + * 2: 2页 + * 3: 3页 + * 4: 4页 + * 5: 5页 + * 6: 6-10页 + * 7: >10页 + * + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaVisitDistribution implements Serializable { + private static final long serialVersionUID = 5404250039495926632L; + /** + * 日期,yyyyMMdd 格式,如 20170313 + */ + @SerializedName(value = "refDate", alternate = "ref_date") + private String refDate; + /** + * key: 分布类型 + * - access_source_session_cnt 访问来源分布 + * - access_staytime_info 访问时长分布 + * - access_depth_info 访问深度的分布 + * value: 场景 ID 下的值 + * - key: 场景 ID + * - value: 场景下的值 + */ + private Map > list; + + public static WxMaVisitDistribution fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaVisitDistribution.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitPage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitPage.java new file mode 100644 index 0000000000..705cf6b49e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitPage.java @@ -0,0 +1,55 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaVisitPage implements Serializable { + private static final long serialVersionUID = -7006334774516877372L; + /** + * 页面路径 + */ + @SerializedName(value = "pagePath", alternate = "page_path") + private String pagePath; + /** + * 访问次数 + */ + @SerializedName(value = "pageVisitPv", alternate = "page_visit_pv") + private Long pageVisitPv; + /** + * 访问人数 + */ + @SerializedName(value = "pageVisitUv", alternate = "page_visit_uv") + private Long pageVisitUv; + /** + * 次均停留时长 + */ + @SerializedName(value = "pageStayTimePv", alternate = "page_staytime_pv") + private Float pageStayTimePv; + /** + * 进入页次数 + */ + @SerializedName(value = "entryPagePv", alternate = "entrypage_pv") + private Long entryPagePv; + /** + * 退出页次数 + */ + @SerializedName(value = "exitPagePv", alternate = "exitpage_pv") + private Long exitPagePv; + /** + * 转发次数 + */ + @SerializedName(value = "pageSharePv", alternate = "page_share_pv") + private Long pageSharePv; + /** + * 转发人数 + */ + @SerializedName(value = "pageShareUv", alternate = "page_share_uv") + private Long pageShareUv; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitTrend.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitTrend.java new file mode 100644 index 0000000000..72223ef618 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitTrend.java @@ -0,0 +1,59 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * 访问趋势 + * + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaVisitTrend implements Serializable { + private static final long serialVersionUID = 1379688517709317935L; + /** + * 日留存:日期,yyyyMMdd 格式,如 20170313 + * 周留存:时间,如"20170306-20170312" + * 月留存:时间,如"201702" + */ + @SerializedName(value = "refDate", alternate = "ref_date") + private String refDate; + /** + * 打开次数 + */ + @SerializedName(value = "sessionCnt", alternate = "session_cnt") + private Long sessionCnt; + /** + * 访问次数 + */ + @SerializedName(value = "visitPv", alternate = "visit_pv") + private Long visitPv; + /** + * 访问人数 + */ + @SerializedName(value = "visitUv", alternate = "visit_uv") + private Long visitUv; + /** + * 新用户数 + */ + @SerializedName(value = "visitUvNew", alternate = "visit_uv_new") + private Long visitUvNew; + /** + * 人均停留时长 (浮点型,单位:秒) + */ + @SerializedName(value = "stayTimeUv", alternate = "stay_time_uv") + private Float stayTimeUv; + /** + * 人均停留时长 (浮点型,单位:秒) + */ + @SerializedName(value = "stayTimeSession", alternate = "stay_time_session") + private Float stayTimeSession; + /** + * 人均停留时长 (浮点型,单位:秒) + */ + @SerializedName(value = "visitDepth", alternate = "visit_depth") + private Float visitDepth; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/package-info.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/package-info.java new file mode 100644 index 0000000000..e4e68c7805 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/package-info.java @@ -0,0 +1,7 @@ +/** + * 数据分析 + * + * @author Charming + * @since 2018-04-28 + */ +package cn.binarywang.wx.miniapp.bean.analysis; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCategory.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCategory.java new file mode 100644 index 0000000000..32195333eb --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCategory.java @@ -0,0 +1,62 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * 小程序帐号的可选类目,其中 address / tag / title 是提交审核会用到的 + * + * @author Charming + * @since 2018-04-26 19:44 + */ +@Data +@Builder +public class WxMaCategory implements Serializable { + private static final long serialVersionUID = -7663757440028175135L; + /** + * 一级类目名称 + */ + @SerializedName("first_class") + private String firstClass; + /** + * 二级类目名称 + */ + @SerializedName("second_class") + private String secondClass; + /** + * 三级类目名称 + */ + @SerializedName("third_class") + private String thirdClass; + /** + * 一级类目的ID编号 + */ + @SerializedName("first_id") + private Long firstId; + /** + * 二级类目的ID编号 + */ + @SerializedName("second_id") + private Long secondId; + /** + * 三级类目的ID编号 + */ + @SerializedName("third_id") + private Long thirdId; + + /** + * 小程序的页面,可通过“获取小程序的第三方提交代码的页面配置”接口获得 + */ + private String address; + /** + * 小程序的标签,多个标签用空格分隔,标签不能多于10个,标签长度不超过20 + */ + private String tag; + /** + * 小程序页面的标题,标题长度不超过32 + */ + private String title; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeAuditStatus.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeAuditStatus.java new file mode 100644 index 0000000000..36c33eaf1a --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeAuditStatus.java @@ -0,0 +1,37 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * 小程序代码审核状态 + * + * @author Charming + * @since 2018-04-26 19:44:39 + */ +@Data +@Builder +public class WxMaCodeAuditStatus implements Serializable { + private static final long serialVersionUID = 4655119308692217268L; + /** + * 审核 ID + */ + @SerializedName(value = "auditId", alternate = {"auditid"}) + private Long auditId; + /** + * 审核状态,其中0为审核成功,1为审核失败,2为审核中 + */ + private Integer status; + /** + * 当status=1,审核被拒绝时,返回的拒绝原因 + */ + private String reason; + + public static WxMaCodeAuditStatus fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaCodeAuditStatus.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequest.java new file mode 100644 index 0000000000..ec64da59a3 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequest.java @@ -0,0 +1,39 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * 微信代码请求上传参数 + * + * @author Charming + * @since 2018-04-26 19:44:47 + */ +@Data +@Builder +public class WxMaCodeCommitRequest implements Serializable { + private static final long serialVersionUID = 7495157056049312108L; + /** + * 代码库中的代码模版ID + */ + private Long templateId; + /** + * 第三方自定义的配置 + */ + private WxMaCodeExtConfig extConfig; + /** + * 代码版本号,开发者可自定义 + */ + private String userVersion; + /** + * 代码描述,开发者可自定义 + */ + private String userDesc; + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeExtConfig.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeExtConfig.java new file mode 100644 index 0000000000..5d0314b2c6 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeExtConfig.java @@ -0,0 +1,205 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import lombok.Builder; +import lombok.Data; + +/** + * 上传代码需要用到的第三方自定义的配置 + * 详细文档,参考:https://developers.weixin.qq.com/miniprogram/dev/framework/config.html + * + * @author Charming + * @since 2018-04-26 19:44 + */ +@Data +@Builder +public class WxMaCodeExtConfig implements Serializable { + private static final long serialVersionUID = -7666911367458178753L; + /** + * 配置 ext.json 是否生效. + * 必填:是 + */ + private boolean extEnable; + /** + * 配置 extAppid. + * 必填:是 + */ + private String extAppid; + /** + * 开发自定义的数据字段. + * 必填:否 + */ + private Object ext; + /** + * 单独设置每个页面的 json. + * 必填:否 + * key: page 名称,如 pages/logs/logs + * value: page 配置 + */ + private Map extPages; + /** + * 是否直接提交到待审核列表. + * 必填:否 + */ + private Boolean directCommit; + /** + * 设置页面路径(同 app.json 相同的字段,填写会覆盖 app.json). + * 必填:否 + */ + private List pages; + /** + * 设置默认页面的窗口表现(同 app.json 相同的字段,填写会覆盖 app.json) + * 必填:否 + */ + private PageConfig window; + /** + * 设置各种网络请求的超时时间(同 app.json 相同的字段,填写会覆盖 app.json) + * 必填:否 + */ + private NetworkTimeout networkTimeout; + /** + * 设置是否开启 debug 模式(同 app.json 相同的字段,填写会覆盖 app.json) + * 必填:否 + */ + private Boolean debug; + /** + * 底部 tab 栏的表现. + * 必填:否 + */ + private TabBar tabBar; + + /** + * page.json 配置,页面配置 + * 文档:https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html + */ + @Data + @Builder + public static class PageConfig { + /** + * 导航栏背景颜色,如"#000000" HexColor. + * 默认:#000000 + */ + private String navigationBarBackgroundColor; + /** + * 导航栏标题颜色,仅支持 black/white. + * 默认:white + */ + private String navigationBarTextStyle; + /** + * 导航栏标题文字内容. + */ + private String navigationBarTitleText; + /** + * 窗口的背景色 HexColor. + * 默认:#ffffff + */ + private String backgroundColor; + /** + * 下拉背景字体、loading 图的样式,仅支持 dark/light. + * 默认:dark + */ + private String backgroundTextStyle; + /** + * 是否开启下拉刷新,详见页面相关事件处理函数. + * 默认:false + */ + private String enablePullDownRefresh; + /** + * 设置为 true 则页面整体不能上下滚动;只在 page.json 中有效,无法在 app.json 中设置该项. + * 默认:false + */ + private Boolean disableScroll; + /** + * 页面上拉触底事件触发时距页面底部距离,单位为px. + * 默认:50 + */ + private Integer onReachBottomDistance; + } + + /** + * tabBar 配置. + */ + @Data + @Builder + public static class TabBar { + /** + * HexColor, tab 上的文字默认颜色. + */ + private String color; + /** + * HexColor, tab 上的文字选中时的颜色. + */ + private String selectedColor; + /** + * HexColor, tab 的背景色. + */ + private String backgroundColor; + /** + * tabbar 上边框的颜色,仅支持 black/white. + */ + private String borderStyle; + /** + * tab 的列表,最少2个、最多5个 tab. + */ + private List - list; + /** + * 可选值 bottom、top. + */ + private String position; + + /** + * list item. + */ + @Data + @Builder + public static class Item { + /** + * 页面路径,必须在 pages 中先定义. + */ + private String pagePath; + /** + * tab 上按钮文字. + */ + private String text; + /** + * 图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px,当 postion 为 top 时,此参数无效,不支持网络图片. + */ + private String iconPath; + /** + * 选中时的图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px ,当 postion 为 top 时,此参数无效. + */ + private String selectedIconPath; + } + } + + /** + * 各种网络请求的超时时间. + */ + @Data + @Builder + public static class NetworkTimeout { + /** + * wx.request的超时时间,单位毫秒,默认为:60000. + * 必填:否 + */ + private Integer request; + /** + * wx.connectSocket的超时时间,单位毫秒,默认为:60000. + * 必填:否 + */ + private Integer connectSocket; + /** + * wx.uploadFile的超时时间,单位毫秒,默认为:60000. + * 必填:否 + */ + private Integer uploadFile; + /** + * wx.downloadFile的超时时间,单位毫秒,默认为:60000. + * 必填:否 + */ + private Integer downloadFile; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequest.java new file mode 100644 index 0000000000..5b784dbded --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequest.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 提交审核的请求 + * + * @author Charming + * @since 2018-04-26 19:45 + */ +@Data +@Builder +public class WxMaCodeSubmitAuditRequest implements Serializable { + private static final long serialVersionUID = 8854979405505241314L; + /** + * 提交审核项的一个列表(至少填写1项,至多填写5项) + */ + @SerializedName("item_list") + private List
itemList; + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistribution.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistribution.java new file mode 100644 index 0000000000..4c0f09644f --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistribution.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Data; + +import java.util.Map; + +/** + * 小程序代码版本号分布 + * + * @author Charming + * @since 2018-04-26 19:45 + */ +@Data +public class WxMaCodeVersionDistribution { + /** + * 当前版本 + */ + private String nowVersion; + /** + * 受影响用户占比 + * key: version, 版本号 + * value: percentage, 受影响比例 + */ + private Map uvInfo; + + public static WxMaCodeVersionDistribution fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaCodeVersionDistribution.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/package-info.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/package-info.java new file mode 100644 index 0000000000..01f6496b99 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/package-info.java @@ -0,0 +1,7 @@ +/** + * 微信小程序代码管理相关的 bean + * + * @author Charming + * @since 2018-04-26 19:44 + */ +package cn.binarywang.wx.miniapp.bean.code; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateAddResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateAddResult.java new file mode 100644 index 0000000000..4b30870d60 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateAddResult.java @@ -0,0 +1,20 @@ +package cn.binarywang.wx.miniapp.bean.template; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import java.io.Serializable; + +@Data +public class WxMaTemplateAddResult implements Serializable{ + + private static final long serialVersionUID = 872250961973834465L; + + @SerializedName("template_id") + private String templateId; + + public static WxMaTemplateAddResult fromJson(String json){ + return WxGsonBuilder.create().fromJson(json, WxMaTemplateAddResult.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryGetResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryGetResult.java new file mode 100644 index 0000000000..e55ed0d563 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryGetResult.java @@ -0,0 +1,31 @@ +package cn.binarywang.wx.miniapp.bean.template; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +@Data +public class WxMaTemplateLibraryGetResult implements Serializable{ + + private static final long serialVersionUID = -190847592776636744L; + private String id; + private String title; + @SerializedName("keyword_list") + private List keywordList; + + @Data + public static class KeywordInfo{ + + @SerializedName("keyword_id") + private int keywordId; + private String name; + private String example; + } + + public static WxMaTemplateLibraryGetResult fromJson(String json){ + return WxGsonBuilder.create().fromJson(json, WxMaTemplateLibraryGetResult.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryListResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryListResult.java new file mode 100644 index 0000000000..1926971b65 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryListResult.java @@ -0,0 +1,28 @@ +package cn.binarywang.wx.miniapp.bean.template; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +@Data +public class WxMaTemplateLibraryListResult implements Serializable{ + private static final long serialVersionUID = -2780782521447602209L; + + @SerializedName("total_count") + private int totalCount; + private List list; + + public static WxMaTemplateLibraryListResult fromJson(String json){ + return WxGsonBuilder.create().fromJson(json, WxMaTemplateLibraryListResult.class); + } + + @Data + public static class TemplateItem{ + + private String id; + private String title; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateListResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateListResult.java new file mode 100644 index 0000000000..0537fefcc5 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateListResult.java @@ -0,0 +1,29 @@ +package cn.binarywang.wx.miniapp.bean.template; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +@Data +public class WxMaTemplateListResult implements Serializable{ + + private static final long serialVersionUID = -7430535579782184537L; + private List list; + + public static WxMaTemplateListResult fromJson(String json){ + return WxGsonBuilder.create().fromJson(json, WxMaTemplateListResult.class); + } + + @Data + public static class TemplateInfo{ + + @SerializedName("template_id") + private String templateId; + private String title; + private String content; + private String example; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/BaseBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/BaseBuilder.java index 70d7cf4b7c..c353534c3f 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/BaseBuilder.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/BaseBuilder.java @@ -15,6 +15,9 @@ public T toUser(String toUser) { return (T) this; } + /** + * 构造器方法. + */ public WxMaKefuMessage build() { WxMaKefuMessage m = new WxMaKefuMessage(); m.setMsgType(this.msgType); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java deleted file mode 100644 index a903e97c43..0000000000 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.binarywang.wx.miniapp.builder; - -import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; -import cn.binarywang.wx.miniapp.constant.WxMaConstants; - -/** - * @author Binary Wang - */ -public final class ImageBuilder extends BaseBuilder { - private String mediaId; - - public ImageBuilder() { - this.msgType = WxMaConstants.KefuMsgType.IMAGE; - } - - public ImageBuilder mediaId(String media_id) { - this.mediaId = media_id; - return this; - } - - @Override - public WxMaKefuMessage build() { - WxMaKefuMessage m = super.build(); - m.setMediaId(this.mediaId); - return m; - } -} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageMessageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageMessageBuilder.java new file mode 100644 index 0000000000..bcd2290f10 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageMessageBuilder.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.builder; + +import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; + +import static cn.binarywang.wx.miniapp.constant.WxMaConstants.KefuMsgType; + +/** + * 图片消息builder. + * + * @author Binary Wang + */ +public final class ImageMessageBuilder extends BaseBuilder { + private String mediaId; + + public ImageMessageBuilder() { + this.msgType = KefuMsgType.IMAGE; + } + + public ImageMessageBuilder mediaId(String mediaId) { + this.mediaId = mediaId; + return this; + } + + @Override + public WxMaKefuMessage build() { + WxMaKefuMessage m = super.build(); + m.setImage(new WxMaKefuMessage.KfImage(this.mediaId)); + return m; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/LinkMessageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/LinkMessageBuilder.java new file mode 100644 index 0000000000..f4927e16dc --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/LinkMessageBuilder.java @@ -0,0 +1,53 @@ +package cn.binarywang.wx.miniapp.builder; + +import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; + +import static cn.binarywang.wx.miniapp.constant.WxMaConstants.KefuMsgType; + +/** + * 图文链接消息builder + * + * @author Binary Wang + */ +public class LinkMessageBuilder extends BaseBuilder { + private String title; + private String description; + private String url; + private String thumbUrl; + + public LinkMessageBuilder() { + this.msgType = KefuMsgType.LINK; + } + + public LinkMessageBuilder title(String title) { + this.title = title; + return this; + } + + public LinkMessageBuilder description(String description) { + this.description = description; + return this; + } + + public LinkMessageBuilder url(String url) { + this.url = url; + return this; + } + + public LinkMessageBuilder thumbUrl(String thumbUrl) { + this.thumbUrl = thumbUrl; + return this; + } + + @Override + public WxMaKefuMessage build() { + WxMaKefuMessage m = super.build(); + m.setLink(WxMaKefuMessage.KfLink.builder().title(this.title) + .description(this.description) + .url(this.url) + .thumbUrl(this.thumbUrl) + .build() + ); + return m; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/MaPageMessageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/MaPageMessageBuilder.java new file mode 100644 index 0000000000..238a60146e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/MaPageMessageBuilder.java @@ -0,0 +1,47 @@ +package cn.binarywang.wx.miniapp.builder; + +import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; + +import static cn.binarywang.wx.miniapp.constant.WxMaConstants.KefuMsgType; + +/** + * 小程序卡片消息builder + * + * @author Binary Wang + */ +public class MaPageMessageBuilder extends BaseBuilder { + private String title; + private String pagePath; + private String thumbMediaId; + + public MaPageMessageBuilder() { + this.msgType = KefuMsgType.MA_PAGE; + } + + public MaPageMessageBuilder title(String title) { + this.title = title; + return this; + } + + public MaPageMessageBuilder pagePath(String pagePath) { + this.pagePath = pagePath; + return this; + } + + public MaPageMessageBuilder thumbMediaId(String thumbMediaId) { + this.thumbMediaId = thumbMediaId; + return this; + } + + @Override + public WxMaKefuMessage build() { + WxMaKefuMessage m = super.build(); + m.setMaPage(WxMaKefuMessage.KfMaPage.builder() + .title(this.title) + .pagePath(this.pagePath) + .thumbMediaId(this.thumbMediaId) + .build() + ); + return m; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextBuilder.java deleted file mode 100644 index 35c58a67df..0000000000 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextBuilder.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.binarywang.wx.miniapp.builder; - -import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; -import cn.binarywang.wx.miniapp.constant.WxMaConstants; - -/** - * @author Binary Wang - */ -public final class TextBuilder extends BaseBuilder { - private String content; - - public TextBuilder() { - this.msgType = WxMaConstants.KefuMsgType.TEXT; - } - - public TextBuilder content(String content) { - this.content = content; - return this; - } - - @Override - public WxMaKefuMessage build() { - WxMaKefuMessage m = super.build(); - m.setContent(this.content); - return m; - } -} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextMessageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextMessageBuilder.java new file mode 100644 index 0000000000..d0da32573c --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextMessageBuilder.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.builder; + +import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; + +import static cn.binarywang.wx.miniapp.constant.WxMaConstants.KefuMsgType; + +/** + * 文本消息builder. + * + * @author Binary Wang + */ +public final class TextMessageBuilder extends BaseBuilder { + private String content; + + public TextMessageBuilder() { + this.msgType = KefuMsgType.TEXT; + } + + public TextMessageBuilder content(String content) { + this.content = content; + return this; + } + + @Override + public WxMaKefuMessage build() { + WxMaKefuMessage m = super.build(); + m.setText(new WxMaKefuMessage.KfText(this.content)); + return m; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java index df72bb2c7d..915cffdddd 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java @@ -38,6 +38,25 @@ public interface WxMaConfig { */ void updateAccessToken(String accessToken, int expiresInSeconds); + String getJsapiTicket(); + + Lock getJsapiTicketLock(); + + boolean isJsapiTicketExpired(); + + /** + * 强制将jsapi ticket过期掉 + */ + void expireJsapiTicket(); + + /** + * 应该是线程安全的 + * + * @param jsapiTicket 新的jsapi ticket值 + * @param expiresInSeconds 过期时间,以秒为单位 + */ + void updateJsapiTicket(String jsapiTicket, int expiresInSeconds); + String getAppid(); String getSecret(); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaInMemoryConfig.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaInMemoryConfig.java index 735a52b56a..d8e286afec 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaInMemoryConfig.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaInMemoryConfig.java @@ -1,13 +1,15 @@ package cn.binarywang.wx.miniapp.config; -import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.util.ToStringUtils; -import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; - import java.io.File; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; + /** * 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化 * @@ -27,7 +29,11 @@ public class WxMaInMemoryConfig implements WxMaConfig { protected volatile String httpProxyUsername; protected volatile String httpProxyPassword; + protected volatile String jsapiTicket; + protected volatile long jsapiTicketExpiresTime; + protected Lock accessTokenLock = new ReentrantLock(); + protected Lock jsapiTicketLock = new ReentrantLock(); /** * 临时文件目录 @@ -70,6 +76,33 @@ public synchronized void updateAccessToken(String accessToken, int expiresInSeco this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; } + @Override + public String getJsapiTicket() { + return this.jsapiTicket; + } + + @Override + public Lock getJsapiTicketLock() { + return this.jsapiTicketLock; + } + + @Override + public boolean isJsapiTicketExpired() { + return System.currentTimeMillis() > this.jsapiTicketExpiresTime; + } + + @Override + public void expireJsapiTicket() { + this.jsapiTicketExpiresTime = 0; + } + + @Override + public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { + this.jsapiTicket = jsapiTicket; + // 预留200秒的时间 + this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; + } + @Override public void expireAccessToken() { this.expiresTime = 0; @@ -158,7 +191,7 @@ public void setHttpProxyPassword(String httpProxyPassword) { @Override public String toString() { - return ToStringUtils.toSimpleString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } @Override @@ -175,6 +208,7 @@ public boolean autoRefreshToken() { return true; } + @Override public String getAppid() { return appid; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java index 14016fa578..1ea3595e9a 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java @@ -2,21 +2,29 @@ /** * - * 小程序常量 + * 小程序常量. ** * @author Binary Wang */ public class WxMaConstants { /** - * 素材类型 + * 微信接口返回的参数errcode. + */ + public static final String ERRCODE = "errcode"; + + /** + * 素材类型. */ public static class MediaType { - public static final String IMAGE = "image";//图片 + /** + * 图片. + */ + public static final String IMAGE = "image"; } /** - * 消息格式 + * 消息格式. */ public static class MsgDataFormat { public static final String XML = "XML"; @@ -24,10 +32,41 @@ public static class MsgDataFormat { } /** - * 客服消息的消息类型 + * 客服消息的消息类型. */ public static class KefuMsgType { - public static final String TEXT = "text";//文本消息 - public static final String IMAGE = "image";//图片消息 + /** + * 文本消息. + */ + public static final String TEXT = "text"; + /** + * 图片消息. + */ + public static final String IMAGE = "image"; + /** + * 图文链接. + */ + public static final String LINK = "link"; + /** + * 小程序卡片消息. + */ + public static final String MA_PAGE = "miniprogrampage"; + } + + public static final class ErrorCode { + /** + * 40001 获取access_token时AppSecret错误,或者access_token无效. + */ + public static final int ERR_40001 = 40001; + + /** + * 42001 access_token超时. + */ + public static final int ERR_42001 = 42001; + + /** + * 40014 不合法的access_token,请开发者认真比对access_token的有效性(如是否过期). + */ + public static final int ERR_40014 = 40014; } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageHandler.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageHandler.java index 794d60e98a..f60edc1d8a 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageHandler.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageHandler.java @@ -2,7 +2,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaMessage; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.WxSessionManager; import java.util.Map; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageInterceptor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageInterceptor.java index 3443862fe1..ef0d500a19 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageInterceptor.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageInterceptor.java @@ -2,7 +2,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaMessage; -import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.session.WxSessionManager; import java.util.Map; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java index cbe42b1f26..be3af708bd 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java @@ -2,6 +2,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaMessage; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import me.chanjar.weixin.common.api.WxErrorExceptionHandler; import me.chanjar.weixin.common.api.WxMessageDuplicateChecker; import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker; @@ -17,10 +18,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; +import java.util.concurrent.*; /** * @author Binary Wang @@ -42,7 +40,9 @@ public class WxMaMessageRouter { public WxMaMessageRouter(WxMaService wxMaService) { this.wxMaService = wxMaService; - this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE); + ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("WxMaMessageRouter-pool-%d").build(); + this.executorService = new ThreadPoolExecutor(DEFAULT_THREAD_POOL_SIZE, DEFAULT_THREAD_POOL_SIZE, + 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), namedThreadFactory); this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); this.sessionManager = new StandardSessionManager(); this.exceptionHandler = new LogExceptionHandler(); @@ -159,7 +159,7 @@ public void run() { } public void route(final WxMaMessage wxMessage) { - this.route(wxMessage, new HashMap ()); + this.route(wxMessage, new HashMap (2)); } /** diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouterRule.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouterRule.java index 835eb2894a..2e4906ebf1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouterRule.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouterRule.java @@ -3,7 +3,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaMessage; 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 java.util.ArrayList; @@ -196,7 +196,7 @@ protected void service(WxMaMessage wxMessage, WxSessionManager sessionManager, WxErrorExceptionHandler exceptionHandler) { if (context == null) { - context = new HashMap<>(); + context = new HashMap<>(16); } try { diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java index 3c026f4a18..cb8097db53 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java @@ -1,8 +1,8 @@ package cn.binarywang.wx.miniapp.util.http; -import cn.binarywang.wx.miniapp.bean.WxMaQrcodeWrapper; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import cn.binarywang.wx.miniapp.bean.AbstractWxMaQrcodeWrapper; +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.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; @@ -25,7 +25,7 @@ /** * @author Binary Wang */ -public class QrCodeRequestExecutor implements RequestExecutor { +public class QrCodeRequestExecutor implements RequestExecutor