| @@ -0,0 +1,14 @@ | |||
| # EditorConfig: http://editorconfig.org/ | |||
| root = true | |||
| [*] | |||
| indent_style = space | |||
| indent_size = 2 | |||
| end_of_line = lf | |||
| charset = utf-8 | |||
| trim_trailing_whitespace = true | |||
| insert_final_newline = true | |||
| [*.md] | |||
| trim_trailing_whitespace = false | |||
| @@ -5,7 +5,7 @@ | |||
| ### 注意: | |||
| 1. ***本项目Fork自chanjarster/weixin-java-tools,但由于原项目已停止维护,故单独维护和发布,且发布到maven上的groupId也会不同,详细信息见下文。*** | |||
| 1. ***自2.0.0版本以来,主要是公众号的接口调整比较大,主要是为了解决主接口类过于庞大不方便管理的问题,将接口实现代码按模块进行拆分。*** | |||
| 1. 最新更新:2016-08-31 发布2.1.0正式版! | |||
| 1. 最新更新:2016-09-30 发布2.2.0正式版! | |||
| =========== | |||
| @@ -33,12 +33,12 @@ maven: | |||
| <dependency> | |||
| <groupId>com.github.binarywang</groupId> | |||
| <artifactId>weixin-java-mp</artifactId> | |||
| <version>2.1.0</version> | |||
| <version>2.2.0</version> | |||
| </dependency> | |||
| ``` | |||
| gradle: | |||
| ```groovy | |||
| compile 'com.github.binarywang:weixin-java-mp:2.1.0' | |||
| compile 'com.github.binarywang:weixin-java-mp:2.2.0' | |||
| ``` | |||
| * 企业号: | |||
| @@ -48,12 +48,12 @@ maven: | |||
| <dependency> | |||
| <groupId>com.github.binarywang</groupId> | |||
| <artifactId>weixin-java-cp</artifactId> | |||
| <version>2.1.0</version> | |||
| <version>2.2.0</version> | |||
| </dependency> | |||
| ``` | |||
| gradle: | |||
| ```groovy | |||
| compile 'com.github.binarywang:weixin-java-cp:2.1.0' | |||
| compile 'com.github.binarywang:weixin-java-cp:2.2.0' | |||
| ``` | |||
| #### 本项目主要存放在github上,地址为 : | |||
| @@ -74,4 +74,4 @@ compile 'com.github.binarywang:weixin-java-cp:2.1.0' | |||
| * 本项目可以采用两种方式接受代码贡献: | |||
| 1. 第一种就是基于[Git Flow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow)开发流程,因此在发起Pull Request的时候请选择develop分支。 | |||
| 1. 另外一种贡献代码的方式就是加入SDK Developers开发组,如果对自己的代码足够自信,可以随时提交代码,注意要随时进行单元测试,保证提交代码没有明显问题,具体加入方式,请咨询管理员。 | |||
| 1. 另外一种贡献代码的方式就是加入SDK Developers开发组,前提是对自己的代码足够自信就可以申请加入,加入之后可以随时直接提交代码,但要注意对所做的修改或新增的代码进行单元测试,保证提交代码没有明显问题,具体加入方式,请咨询管理员。 | |||
| @@ -2,7 +2,7 @@ allprojects { | |||
| apply plugin: 'maven' | |||
| group = 'com.github.binarywang' | |||
| version = '2.1.0-SNAPSHOT' | |||
| version = '2.2.0' | |||
| } | |||
| subprojects { | |||
| @@ -13,8 +13,8 @@ subprojects { | |||
| repositories { | |||
| mavenLocal() | |||
| maven { url "http://maven.aliyun.com/nexus/content/groups/public" } | |||
| maven { url "http://central.maven.org/maven2" } | |||
| //maven { url "http://maven.aliyun.com/nexus/content/groups/public" } | |||
| } | |||
| @@ -24,6 +24,8 @@ subprojects { | |||
| compile group: 'org.apache.httpcomponents', name: 'httpmime', version:'4.5' | |||
| compile group: 'org.jodd', name: 'jodd-http', version:'3.6.7' | |||
| compile group: 'com.google.code.gson', name: 'gson', version:'2.7' | |||
| compile group: 'com.google.guava', name: 'guava', version:'19.0' | |||
| compile group: 'org.jooq', name: 'joor', version:'0.9.6' | |||
| compile group: 'commons-codec', name: 'commons-codec', version:'1.10' | |||
| compile group: 'commons-io', name: 'commons-io', version:'2.5' | |||
| compile group: 'org.apache.commons', name: 'commons-lang3', version:'3.4' | |||
| @@ -5,7 +5,7 @@ | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <groupId>com.github.binarywang</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>2.1.0</version> | |||
| <version>2.2.0</version> | |||
| <packaging>pom</packaging> | |||
| <name>WeiXin Java Tools - Parent</name> | |||
| <description>微信公众号、企业号上级POM</description> | |||
| @@ -49,9 +49,10 @@ | |||
| <slf4j.version>1.7.10</slf4j.version> | |||
| <logback.version>1.1.2</logback.version> | |||
| <jodd-http.version>3.6.7</jodd-http.version> | |||
| <jackson.version>2.8.0</jackson.version> | |||
| <jedis.version>2.9.0</jedis.version> | |||
| <gson.version>2.7</gson.version> | |||
| <guava.version>19.0</guava.version> | |||
| <joor.version>0.9.6</joor.version> | |||
| <commons-lang3.version>3.4</commons-lang3.version> | |||
| <commons-io.version>2.5</commons-io.version> | |||
| <commons-codec.version>1.10</commons-codec.version> | |||
| @@ -106,15 +107,19 @@ | |||
| <artifactId>commons-lang3</artifactId> | |||
| <version>${commons-lang3.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.fasterxml.jackson.core</groupId> | |||
| <artifactId>jackson-databind</artifactId> | |||
| <version>${jackson.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>redis.clients</groupId> | |||
| <artifactId>jedis</artifactId> | |||
| <version>${jedis.version}</version> | |||
| <scope>provided</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.google.guava</groupId> | |||
| <artifactId>guava</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.jooq</groupId> | |||
| <artifactId>joor</artifactId> | |||
| </dependency> | |||
| </dependencies> | |||
| @@ -156,6 +161,16 @@ | |||
| <version>${jetty.version}</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.google.guava</groupId> | |||
| <artifactId>guava</artifactId> | |||
| <version>${guava.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.jooq</groupId> | |||
| <artifactId>joor</artifactId> | |||
| <version>${joor.version}</version> | |||
| </dependency> | |||
| </dependencies> | |||
| </dependencyManagement> | |||
| @@ -6,7 +6,7 @@ | |||
| <parent> | |||
| <groupId>com.github.binarywang</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>2.1.0</version> | |||
| <version>2.2.0</version> | |||
| </parent> | |||
| <artifactId>weixin-java-common</artifactId> | |||
| @@ -0,0 +1,19 @@ | |||
| package me.chanjar.weixin.common.annotation; | |||
| import java.lang.annotation.ElementType; | |||
| import java.lang.annotation.Retention; | |||
| import java.lang.annotation.RetentionPolicy; | |||
| import java.lang.annotation.Target; | |||
| /** | |||
| * 标识某个字段是否是必填的 | |||
| * | |||
| * Created by Binary Wang on 2016/9/25. | |||
| * @author binarywang (https://github.com/binarywang) | |||
| * | |||
| */ | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| @Target(ElementType.FIELD) | |||
| public @interface Required { | |||
| } | |||
| @@ -30,6 +30,7 @@ public class WxConsts { | |||
| public static final String CUSTOM_MSG_MUSIC = "music"; | |||
| public static final String CUSTOM_MSG_NEWS = "news"; | |||
| public static final String CUSTOM_MSG_FILE = "file"; | |||
| 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"; | |||
| @@ -61,7 +62,7 @@ public class WxConsts { | |||
| /** | |||
| * 群发反馈消息代码所对应的文字描述 | |||
| */ | |||
| public static final Map<String, String> MASS_ST_2_DESC = new HashMap<String, String>(); | |||
| public static final Map<String, String> MASS_ST_2_DESC = new HashMap<>(); | |||
| /////////////////////// | |||
| // 微信端推送过来的事件类型 | |||
| /////////////////////// | |||
| @@ -92,6 +93,8 @@ public class WxConsts { | |||
| public static final String EVT_KF_CREATE_SESSION = "kf_create_session"; // 客服接入会话 | |||
| public static final String EVT_KF_CLOSE_SESSION = "kf_close_session"; // 客服关闭会话 | |||
| public static final String EVT_KF_SWITCH_SESSION = "kf_switch_session"; // 客服转接会话 | |||
| public static final String EVT_POI_CHECK_NOTIFY = "poi_check_notify"; //门店审核事件推送 | |||
| /////////////////////// | |||
| // 上传多媒体文件的类型 | |||
| /////////////////////// | |||
| @@ -25,7 +25,7 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec | |||
| /** | |||
| * 消息id->消息时间戳的map | |||
| */ | |||
| private final ConcurrentHashMap<String, Long> msgId2Timestamp = new ConcurrentHashMap<String, Long>(); | |||
| private final ConcurrentHashMap<String, Long> msgId2Timestamp = new ConcurrentHashMap<>(); | |||
| /** | |||
| * 后台清理线程是否已经开启 | |||
| @@ -56,7 +56,7 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec | |||
| } | |||
| protected void checkBackgroundProcessStarted() { | |||
| if (backgroundProcessStarted.getAndSet(true)) { | |||
| if (this.backgroundProcessStarted.getAndSet(true)) { | |||
| return; | |||
| } | |||
| Thread t = new Thread(new Runnable() { | |||
| @@ -64,11 +64,11 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec | |||
| public void run() { | |||
| try { | |||
| while (true) { | |||
| Thread.sleep(clearPeriod); | |||
| Thread.sleep(WxMessageInMemoryDuplicateChecker.this.clearPeriod); | |||
| Long now = System.currentTimeMillis(); | |||
| for (Map.Entry<String, Long> entry : msgId2Timestamp.entrySet()) { | |||
| if (now - entry.getValue() > timeToLive) { | |||
| msgId2Timestamp.entrySet().remove(entry); | |||
| for (Map.Entry<String, Long> entry : WxMessageInMemoryDuplicateChecker.this.msgId2Timestamp.entrySet()) { | |||
| if (now - entry.getValue() > WxMessageInMemoryDuplicateChecker.this.timeToLive) { | |||
| WxMessageInMemoryDuplicateChecker.this.msgId2Timestamp.entrySet().remove(entry); | |||
| } | |||
| } | |||
| } | |||
| @@ -87,7 +87,7 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec | |||
| return false; | |||
| } | |||
| checkBackgroundProcessStarted(); | |||
| Long timestamp = msgId2Timestamp.putIfAbsent(messageId, System.currentTimeMillis()); | |||
| Long timestamp = this.msgId2Timestamp.putIfAbsent(messageId, System.currentTimeMillis()); | |||
| return timestamp != null; | |||
| } | |||
| @@ -16,7 +16,7 @@ public class WxAccessToken implements Serializable { | |||
| } | |||
| public String getAccessToken() { | |||
| return accessToken; | |||
| return this.accessToken; | |||
| } | |||
| public void setAccessToken(String accessToken) { | |||
| @@ -24,7 +24,7 @@ public class WxAccessToken implements Serializable { | |||
| } | |||
| public int getExpiresIn() { | |||
| return expiresIn; | |||
| return this.expiresIn; | |||
| } | |||
| public void setExpiresIn(int expiresIn) { | |||
| @@ -39,7 +39,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public String getAppId() { | |||
| return appId; | |||
| return this.appId; | |||
| } | |||
| public void setAppId(String appId) { | |||
| @@ -47,7 +47,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public String getCardId() { | |||
| return cardId; | |||
| return this.cardId; | |||
| } | |||
| public void setCardId(String cardId) { | |||
| @@ -55,7 +55,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public String getCardType() { | |||
| return cardType; | |||
| return this.cardType; | |||
| } | |||
| public void setCardType(String cardType) { | |||
| @@ -63,7 +63,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public String getLocationId() { | |||
| return locationId; | |||
| return this.locationId; | |||
| } | |||
| public void setLocationId(String locationId) { | |||
| @@ -71,7 +71,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public String getCode() { | |||
| return code; | |||
| return this.code; | |||
| } | |||
| public void setCode(String code) { | |||
| @@ -79,7 +79,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public String getOpenId() { | |||
| return openId; | |||
| return this.openId; | |||
| } | |||
| public void setOpenId(String openId) { | |||
| @@ -87,7 +87,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public Long getTimestamp() { | |||
| return timestamp; | |||
| return this.timestamp; | |||
| } | |||
| public void setTimestamp(Long timestamp) { | |||
| @@ -95,7 +95,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public String getNonceStr() { | |||
| return nonceStr; | |||
| return this.nonceStr; | |||
| } | |||
| public void setNonceStr(String nonceStr) { | |||
| @@ -103,7 +103,7 @@ public class WxCardApiSignature implements Serializable { | |||
| } | |||
| public String getSignature() { | |||
| return signature; | |||
| return this.signature; | |||
| } | |||
| public void setSignature(String signature) { | |||
| @@ -19,7 +19,7 @@ public class WxJsapiSignature implements Serializable { | |||
| private String signature; | |||
| public String getSignature() { | |||
| return signature; | |||
| return this.signature; | |||
| } | |||
| public void setSignature(String signature) { | |||
| @@ -27,7 +27,7 @@ public class WxJsapiSignature implements Serializable { | |||
| } | |||
| public String getNoncestr() { | |||
| return noncestr; | |||
| return this.noncestr; | |||
| } | |||
| public void setNoncestr(String noncestr) { | |||
| @@ -35,7 +35,7 @@ public class WxJsapiSignature implements Serializable { | |||
| } | |||
| public long getTimestamp() { | |||
| return timestamp; | |||
| return this.timestamp; | |||
| } | |||
| public void setTimestamp(long timestamp) { | |||
| @@ -43,7 +43,7 @@ public class WxJsapiSignature implements Serializable { | |||
| } | |||
| public String getUrl() { | |||
| return url; | |||
| return this.url; | |||
| } | |||
| public void setUrl(String url) { | |||
| @@ -51,7 +51,7 @@ public class WxJsapiSignature implements Serializable { | |||
| } | |||
| public String getAppid() { | |||
| return appid; | |||
| return this.appid; | |||
| } | |||
| public void setAppid(String appid) { | |||
| @@ -19,7 +19,7 @@ public class WxMenu implements Serializable { | |||
| private static final long serialVersionUID = -7083914585539687746L; | |||
| private List<WxMenuButton> buttons = new ArrayList<WxMenuButton>(); | |||
| private List<WxMenuButton> buttons = new ArrayList<>(); | |||
| private WxMenuRule matchRule; | |||
| @@ -40,7 +40,7 @@ public class WxMenu implements Serializable { | |||
| } | |||
| public List<WxMenuButton> getButtons() { | |||
| return buttons; | |||
| return this.buttons; | |||
| } | |||
| public void setButtons(List<WxMenuButton> buttons) { | |||
| @@ -48,7 +48,7 @@ public class WxMenu implements Serializable { | |||
| } | |||
| public WxMenuRule getMatchRule() { | |||
| return matchRule; | |||
| return this.matchRule; | |||
| } | |||
| public void setMatchRule(WxMenuRule matchRule) { | |||
| @@ -62,7 +62,7 @@ public class WxMenu implements Serializable { | |||
| @Override | |||
| public String toString() { | |||
| return "WxMenu{" + | |||
| "buttons=" + buttons + | |||
| "buttons=" + this.buttons + | |||
| '}'; | |||
| } | |||
| @@ -14,7 +14,7 @@ public class WxMenuButton { | |||
| private String url; | |||
| private String mediaId; | |||
| private List<WxMenuButton> subButtons = new ArrayList<WxMenuButton>(); | |||
| private List<WxMenuButton> subButtons = new ArrayList<>(); | |||
| @Override | |||
| public String toString() { | |||
| @@ -23,7 +23,7 @@ public class WxMenuButton { | |||
| } | |||
| public String getType() { | |||
| return type; | |||
| return this.type; | |||
| } | |||
| public void setType(String type) { | |||
| @@ -31,7 +31,7 @@ public class WxMenuButton { | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| return this.name; | |||
| } | |||
| public void setName(String name) { | |||
| @@ -39,7 +39,7 @@ public class WxMenuButton { | |||
| } | |||
| public String getKey() { | |||
| return key; | |||
| return this.key; | |||
| } | |||
| public void setKey(String key) { | |||
| @@ -47,7 +47,7 @@ public class WxMenuButton { | |||
| } | |||
| public String getUrl() { | |||
| return url; | |||
| return this.url; | |||
| } | |||
| public void setUrl(String url) { | |||
| @@ -55,7 +55,7 @@ public class WxMenuButton { | |||
| } | |||
| public List<WxMenuButton> getSubButtons() { | |||
| return subButtons; | |||
| return this.subButtons; | |||
| } | |||
| public void setSubButtons(List<WxMenuButton> subButtons) { | |||
| @@ -63,7 +63,7 @@ public class WxMenuButton { | |||
| } | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| return this.mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| @@ -13,7 +13,7 @@ public class WxMenuRule { | |||
| private String language; | |||
| public String getTagId() { | |||
| return tagId; | |||
| return this.tagId; | |||
| } | |||
| public void setTagId(String tagId) { | |||
| @@ -21,7 +21,7 @@ public class WxMenuRule { | |||
| } | |||
| public String getSex() { | |||
| return sex; | |||
| return this.sex; | |||
| } | |||
| public void setSex(String sex) { | |||
| @@ -29,7 +29,7 @@ public class WxMenuRule { | |||
| } | |||
| public String getCountry() { | |||
| return country; | |||
| return this.country; | |||
| } | |||
| public void setCountry(String country) { | |||
| @@ -37,7 +37,7 @@ public class WxMenuRule { | |||
| } | |||
| public String getProvince() { | |||
| return province; | |||
| return this.province; | |||
| } | |||
| public void setProvince(String province) { | |||
| @@ -45,7 +45,7 @@ public class WxMenuRule { | |||
| } | |||
| public String getCity() { | |||
| return city; | |||
| return this.city; | |||
| } | |||
| public void setCity(String city) { | |||
| @@ -53,7 +53,7 @@ public class WxMenuRule { | |||
| } | |||
| public String getClientPlatformType() { | |||
| return clientPlatformType; | |||
| return this.clientPlatformType; | |||
| } | |||
| public void setClientPlatformType(String clientPlatformType) { | |||
| @@ -61,7 +61,7 @@ public class WxMenuRule { | |||
| } | |||
| public String getLanguage() { | |||
| return language; | |||
| return this.language; | |||
| } | |||
| public void setLanguage(String language) { | |||
| @@ -29,7 +29,7 @@ public class WxError implements Serializable { | |||
| } | |||
| public int getErrorCode() { | |||
| return errorCode; | |||
| return this.errorCode; | |||
| } | |||
| public void setErrorCode(int errorCode) { | |||
| @@ -37,7 +37,7 @@ public class WxError implements Serializable { | |||
| } | |||
| public String getErrorMsg() { | |||
| return errorMsg; | |||
| return this.errorMsg; | |||
| } | |||
| public void setErrorMsg(String errorMsg) { | |||
| @@ -45,7 +45,7 @@ public class WxError implements Serializable { | |||
| } | |||
| public String getJson() { | |||
| return json; | |||
| return this.json; | |||
| } | |||
| public void setJson(String json) { | |||
| @@ -54,10 +54,10 @@ public class WxError implements Serializable { | |||
| @Override | |||
| public String toString() { | |||
| if (json != null) { | |||
| return json; | |||
| if (this.json != null) { | |||
| return this.json; | |||
| } | |||
| return "错误: Code=" + errorCode + ", Msg=" + errorMsg; | |||
| return "错误: Code=" + this.errorCode + ", Msg=" + this.errorMsg; | |||
| } | |||
| public static class Builder { | |||
| @@ -17,7 +17,7 @@ public class WxMediaUploadResult implements Serializable { | |||
| } | |||
| public String getType() { | |||
| return type; | |||
| return this.type; | |||
| } | |||
| public void setType(String type) { | |||
| @@ -25,7 +25,7 @@ public class WxMediaUploadResult implements Serializable { | |||
| } | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| return this.mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| @@ -33,7 +33,7 @@ public class WxMediaUploadResult implements Serializable { | |||
| } | |||
| public long getCreatedAt() { | |||
| return createdAt; | |||
| return this.createdAt; | |||
| } | |||
| public void setCreatedAt(long createdAt) { | |||
| @@ -41,7 +41,7 @@ public class WxMediaUploadResult implements Serializable { | |||
| } | |||
| public String getThumbMediaId() { | |||
| return thumbMediaId; | |||
| return this.thumbMediaId; | |||
| } | |||
| public void setThumbMediaId(String thumbMediaId) { | |||
| @@ -50,8 +50,8 @@ public class WxMediaUploadResult implements Serializable { | |||
| @Override | |||
| public String toString() { | |||
| return "WxUploadResult [type=" + type + ", media_id=" + mediaId + ", thumb_media_id=" + thumbMediaId | |||
| + ", created_at=" + createdAt + "]"; | |||
| return "WxUploadResult [type=" + this.type + ", media_id=" + this.mediaId + ", thumb_media_id=" + this.thumbMediaId | |||
| + ", created_at=" + this.createdAt + "]"; | |||
| } | |||
| } | |||
| @@ -14,7 +14,7 @@ public class WxErrorException extends Exception { | |||
| } | |||
| public WxError getError() { | |||
| return error; | |||
| return this.error; | |||
| } | |||
| @@ -18,7 +18,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| */ | |||
| protected static final String EMPTY_ARRAY[] = new String[0]; | |||
| // ------------------------------ WxSession | |||
| protected Map<String, Object> attributes = new ConcurrentHashMap<String, Object>(); | |||
| protected Map<String, Object> attributes = new ConcurrentHashMap<>(); | |||
| /** | |||
| * The session identifier of this Session. | |||
| */ | |||
| @@ -47,7 +47,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| /** | |||
| * The current accessed time for this session. | |||
| */ | |||
| protected volatile long thisAccessedTime = creationTime; | |||
| protected volatile long thisAccessedTime = this.creationTime; | |||
| /** | |||
| * The default maximum inactive interval for Sessions created by | |||
| * this Manager. | |||
| @@ -77,7 +77,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| if (name == null) return null; | |||
| return (attributes.get(name)); | |||
| return (this.attributes.get(name)); | |||
| } | |||
| @Override | |||
| @@ -86,8 +86,8 @@ public class StandardSession implements WxSession, InternalSession { | |||
| throw new IllegalStateException | |||
| (sm.getString("sessionImpl.getAttributeNames.ise")); | |||
| Set<String> names = new HashSet<String>(); | |||
| names.addAll(attributes.keySet()); | |||
| Set<String> names = new HashSet<>(); | |||
| names.addAll(this.attributes.keySet()); | |||
| return Collections.enumeration(names); | |||
| } | |||
| @@ -109,7 +109,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| throw new IllegalStateException(sm.getString( | |||
| "sessionImpl.setAttribute.ise", getIdInternal())); | |||
| attributes.put(name, value); | |||
| this.attributes.put(name, value); | |||
| } | |||
| @@ -132,10 +132,10 @@ public class StandardSession implements WxSession, InternalSession { | |||
| @Override | |||
| public WxSession getSession() { | |||
| if (facade == null) { | |||
| facade = new StandardSessionFacade(this); | |||
| if (this.facade == null) { | |||
| this.facade = new StandardSessionFacade(this); | |||
| } | |||
| return (facade); | |||
| return (this.facade); | |||
| } | |||
| @@ -157,15 +157,15 @@ public class StandardSession implements WxSession, InternalSession { | |||
| return true; | |||
| } | |||
| if (accessCount.get() > 0) { | |||
| if (this.accessCount.get() > 0) { | |||
| return true; | |||
| } | |||
| if (maxInactiveInterval > 0) { | |||
| if (this.maxInactiveInterval > 0) { | |||
| long timeNow = System.currentTimeMillis(); | |||
| int timeIdle; | |||
| timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L); | |||
| if (timeIdle >= maxInactiveInterval) { | |||
| timeIdle = (int) ((timeNow - this.thisAccessedTime) / 1000L); | |||
| if (timeIdle >= this.maxInactiveInterval) { | |||
| expire(); | |||
| } | |||
| } | |||
| @@ -193,7 +193,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| if (name == null) return; | |||
| // Remove this attribute from our collection | |||
| attributes.remove(name); | |||
| this.attributes.remove(name); | |||
| } | |||
| @@ -202,7 +202,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| // Check to see if session has already been invalidated. | |||
| // Do not check expiring at this point as expire should not return until | |||
| // isValid is false | |||
| if (!isValid) | |||
| if (!this.isValid) | |||
| return; | |||
| synchronized (this) { | |||
| @@ -210,24 +210,24 @@ public class StandardSession implements WxSession, InternalSession { | |||
| // Double check locking - isValid needs to be volatile | |||
| // The check of expiring is to ensure that an infinite loop is not | |||
| // entered as per bug 56339 | |||
| if (expiring || !isValid) | |||
| if (this.expiring || !this.isValid) | |||
| return; | |||
| if (manager == null) | |||
| if (this.manager == null) | |||
| return; | |||
| // Mark this session as "being expired" | |||
| expiring = true; | |||
| this.expiring = true; | |||
| accessCount.set(0); | |||
| this.accessCount.set(0); | |||
| // Remove this session from our manager's active sessions | |||
| manager.remove(this, true); | |||
| this.manager.remove(this, true); | |||
| // We have completed expire of this session | |||
| setValid(false); | |||
| expiring = false; | |||
| this.expiring = false; | |||
| // Unbind any objects associated with this session | |||
| String keys[] = keys(); | |||
| @@ -244,7 +244,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| public void access() { | |||
| this.thisAccessedTime = System.currentTimeMillis(); | |||
| accessCount.incrementAndGet(); | |||
| this.accessCount.incrementAndGet(); | |||
| } | |||
| @@ -253,7 +253,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| public void endAccess() { | |||
| this.thisAccessedTime = System.currentTimeMillis(); | |||
| accessCount.decrementAndGet(); | |||
| this.accessCount.decrementAndGet(); | |||
| } | |||
| @@ -273,13 +273,13 @@ public class StandardSession implements WxSession, InternalSession { | |||
| @Override | |||
| public void setId(String id) { | |||
| if ((this.id != null) && (manager != null)) | |||
| manager.remove(this); | |||
| if ((this.id != null) && (this.manager != null)) | |||
| this.manager.remove(this); | |||
| this.id = id; | |||
| if (manager != null) | |||
| manager.add(this); | |||
| if (this.manager != null) | |||
| this.manager.add(this); | |||
| } | |||
| /** | |||
| @@ -289,7 +289,7 @@ public class StandardSession implements WxSession, InternalSession { | |||
| */ | |||
| protected String[] keys() { | |||
| return attributes.keySet().toArray(EMPTY_ARRAY); | |||
| return this.attributes.keySet().toArray(EMPTY_ARRAY); | |||
| } | |||
| @@ -300,31 +300,31 @@ public class StandardSession implements WxSession, InternalSession { | |||
| StandardSession session = (StandardSession) o; | |||
| if (creationTime != session.creationTime) return false; | |||
| if (expiring != session.expiring) return false; | |||
| if (isValid != session.isValid) return false; | |||
| if (maxInactiveInterval != session.maxInactiveInterval) return false; | |||
| if (thisAccessedTime != session.thisAccessedTime) return false; | |||
| if (!accessCount.equals(session.accessCount)) return false; | |||
| if (!attributes.equals(session.attributes)) return false; | |||
| if (!facade.equals(session.facade)) return false; | |||
| if (!id.equals(session.id)) return false; | |||
| return manager.equals(session.manager); | |||
| if (this.creationTime != session.creationTime) return false; | |||
| if (this.expiring != session.expiring) return false; | |||
| if (this.isValid != session.isValid) return false; | |||
| if (this.maxInactiveInterval != session.maxInactiveInterval) return false; | |||
| if (this.thisAccessedTime != session.thisAccessedTime) return false; | |||
| if (!this.accessCount.equals(session.accessCount)) return false; | |||
| if (!this.attributes.equals(session.attributes)) return false; | |||
| if (!this.facade.equals(session.facade)) return false; | |||
| if (!this.id.equals(session.id)) return false; | |||
| return this.manager.equals(session.manager); | |||
| } | |||
| @Override | |||
| public int hashCode() { | |||
| int result = attributes.hashCode(); | |||
| result = 31 * result + id.hashCode(); | |||
| result = 31 * result + (isValid ? 1 : 0); | |||
| result = 31 * result + (expiring ? 1 : 0); | |||
| result = 31 * result + manager.hashCode(); | |||
| result = 31 * result + (int) (creationTime ^ (creationTime >>> 32)); | |||
| result = 31 * result + (int) (thisAccessedTime ^ (thisAccessedTime >>> 32)); | |||
| result = 31 * result + maxInactiveInterval; | |||
| result = 31 * result + facade.hashCode(); | |||
| result = 31 * result + accessCount.hashCode(); | |||
| int result = this.attributes.hashCode(); | |||
| result = 31 * result + this.id.hashCode(); | |||
| result = 31 * result + (this.isValid ? 1 : 0); | |||
| result = 31 * result + (this.expiring ? 1 : 0); | |||
| result = 31 * result + this.manager.hashCode(); | |||
| result = 31 * result + (int) (this.creationTime ^ (this.creationTime >>> 32)); | |||
| result = 31 * result + (int) (this.thisAccessedTime ^ (this.thisAccessedTime >>> 32)); | |||
| result = 31 * result + this.maxInactiveInterval; | |||
| result = 31 * result + this.facade.hashCode(); | |||
| result = 31 * result + this.accessCount.hashCode(); | |||
| return result; | |||
| } | |||
| @@ -14,32 +14,32 @@ public class StandardSessionFacade implements WxSession { | |||
| } | |||
| public InternalSession getInternalSession() { | |||
| return (InternalSession) session; | |||
| return (InternalSession) this.session; | |||
| } | |||
| @Override | |||
| public Object getAttribute(String name) { | |||
| return session.getAttribute(name); | |||
| return this.session.getAttribute(name); | |||
| } | |||
| @Override | |||
| public Enumeration<String> getAttributeNames() { | |||
| return session.getAttributeNames(); | |||
| return this.session.getAttributeNames(); | |||
| } | |||
| @Override | |||
| public void setAttribute(String name, Object value) { | |||
| session.setAttribute(name, value); | |||
| this.session.setAttribute(name, value); | |||
| } | |||
| @Override | |||
| public void removeAttribute(String name) { | |||
| session.removeAttribute(name); | |||
| this.session.removeAttribute(name); | |||
| } | |||
| @Override | |||
| public void invalidate() { | |||
| session.invalidate(); | |||
| this.session.invalidate(); | |||
| } | |||
| } | |||
| @@ -32,7 +32,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| * The set of currently active Sessions for this Manager, keyed by | |||
| * session identifier. | |||
| */ | |||
| protected Map<String, InternalSession> sessions = new ConcurrentHashMap<String, InternalSession>(); | |||
| protected Map<String, InternalSession> sessions = new ConcurrentHashMap<>(); | |||
| /** | |||
| * The maximum number of active Sessions allowed, or -1 for no limit. | |||
| */ | |||
| @@ -117,7 +117,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| @Override | |||
| public void remove(InternalSession session, boolean update) { | |||
| if (session.getIdInternal() != null) { | |||
| sessions.remove(session.getIdInternal()); | |||
| this.sessions.remove(session.getIdInternal()); | |||
| } | |||
| } | |||
| @@ -127,7 +127,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| if (id == null) | |||
| return (null); | |||
| return sessions.get(id); | |||
| return this.sessions.get(id); | |||
| } | |||
| @@ -138,12 +138,12 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| (sm.getString("sessionManagerImpl.createSession.ise")); | |||
| } | |||
| if ((maxActiveSessions >= 0) && | |||
| (getActiveSessions() >= maxActiveSessions)) { | |||
| rejectedSessions++; | |||
| if ((this.maxActiveSessions >= 0) && | |||
| (getActiveSessions() >= this.maxActiveSessions)) { | |||
| this.rejectedSessions++; | |||
| throw new TooManyActiveSessionsException( | |||
| sm.getString("sessionManagerImpl.createSession.tmase"), | |||
| maxActiveSessions); | |||
| this.maxActiveSessions); | |||
| } | |||
| // Recycle or create a Session instance | |||
| @@ -155,7 +155,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| session.setMaxInactiveInterval(this.maxInactiveInterval); | |||
| String id = sessionId; | |||
| session.setId(id); | |||
| sessionCounter++; | |||
| this.sessionCounter++; | |||
| return (session); | |||
| @@ -164,7 +164,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| @Override | |||
| public int getActiveSessions() { | |||
| return sessions.size(); | |||
| return this.sessions.size(); | |||
| } | |||
| @@ -185,17 +185,17 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| public void add(InternalSession session) { | |||
| // 当第一次有session创建的时候,开启session清理线程 | |||
| if (!backgroundProcessStarted.getAndSet(true)) { | |||
| if (!this.backgroundProcessStarted.getAndSet(true)) { | |||
| Thread t = new Thread(new Runnable() { | |||
| @Override | |||
| public void run() { | |||
| while (true) { | |||
| try { | |||
| // 每秒清理一次 | |||
| Thread.sleep(backgroundProcessorDelay * 1000l); | |||
| Thread.sleep(StandardSessionManager.this.backgroundProcessorDelay * 1000l); | |||
| backgroundProcess(); | |||
| } catch (InterruptedException e) { | |||
| log.error("SessionManagerImpl.backgroundProcess error", e); | |||
| StandardSessionManager.this.log.error("SessionManagerImpl.backgroundProcess error", e); | |||
| } | |||
| } | |||
| } | |||
| @@ -204,12 +204,12 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| t.start(); | |||
| } | |||
| sessions.put(session.getIdInternal(), session); | |||
| this.sessions.put(session.getIdInternal(), session); | |||
| int size = getActiveSessions(); | |||
| if (size > maxActive) { | |||
| synchronized (maxActiveUpdateLock) { | |||
| if (size > maxActive) { | |||
| maxActive = size; | |||
| if (size > this.maxActive) { | |||
| synchronized (this.maxActiveUpdateLock) { | |||
| if (size > this.maxActive) { | |||
| this.maxActive = size; | |||
| } | |||
| } | |||
| } | |||
| @@ -223,14 +223,14 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| @Override | |||
| public InternalSession[] findSessions() { | |||
| return sessions.values().toArray(new InternalSession[0]); | |||
| return this.sessions.values().toArray(new InternalSession[0]); | |||
| } | |||
| @Override | |||
| public void backgroundProcess() { | |||
| count = (count + 1) % processExpiresFrequency; | |||
| if (count == 0) | |||
| this.count = (this.count + 1) % this.processExpiresFrequency; | |||
| if (this.count == 0) | |||
| processExpires(); | |||
| } | |||
| @@ -243,17 +243,17 @@ public class StandardSessionManager implements WxSessionManager, InternalSession | |||
| InternalSession sessions[] = findSessions(); | |||
| int expireHere = 0; | |||
| if (log.isDebugEnabled()) | |||
| log.debug("Start expire sessions {} at {} sessioncount {}", getName(), timeNow, sessions.length); | |||
| 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()) { | |||
| expireHere++; | |||
| } | |||
| } | |||
| long timeEnd = System.currentTimeMillis(); | |||
| if (log.isDebugEnabled()) | |||
| log.debug("End expire sessions {} processingTime {} expired sessions: {}", getName(), timeEnd - timeNow, expireHere); | |||
| processingTime += (timeEnd - timeNow); | |||
| if (this.log.isDebugEnabled()) | |||
| this.log.debug("End expire sessions {} processingTime {} expired sessions: {}", getName(), timeEnd - timeNow, expireHere); | |||
| this.processingTime += (timeEnd - timeNow); | |||
| } | |||
| @@ -40,7 +40,7 @@ public class TooManyActiveSessionsException | |||
| int maxActive) { | |||
| super(message); | |||
| maxActiveSessions = maxActive; | |||
| this.maxActiveSessions = maxActive; | |||
| } | |||
| /** | |||
| @@ -49,6 +49,6 @@ public class TooManyActiveSessionsException | |||
| * @return The maximum number of sessions allowed by the session manager. | |||
| */ | |||
| public int getMaxActiveSessions() { | |||
| return maxActiveSessions; | |||
| return this.maxActiveSessions; | |||
| } | |||
| } | |||
| @@ -13,7 +13,7 @@ public class LogExceptionHandler implements WxErrorExceptionHandler { | |||
| @Override | |||
| public void handle(WxErrorException e) { | |||
| log.error("Error happens", e); | |||
| this.log.error("Error happens", e); | |||
| } | |||
| @@ -3,24 +3,24 @@ package me.chanjar.weixin.common.util.crypto; | |||
| import java.util.ArrayList; | |||
| public class ByteGroup { | |||
| ArrayList<Byte> byteContainer = new ArrayList<Byte>(); | |||
| ArrayList<Byte> byteContainer = new ArrayList<>(); | |||
| public byte[] toBytes() { | |||
| byte[] bytes = new byte[byteContainer.size()]; | |||
| for (int i = 0; i < byteContainer.size(); i++) { | |||
| bytes[i] = byteContainer.get(i); | |||
| 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) { | |||
| byteContainer.add(b); | |||
| this.byteContainer.add(b); | |||
| } | |||
| return this; | |||
| } | |||
| public int size() { | |||
| return byteContainer.size(); | |||
| return this.byteContainer.size(); | |||
| } | |||
| } | |||
| @@ -47,7 +47,7 @@ public class PKCS7Encoder { | |||
| * @return 删除补位字符后的明文 | |||
| */ | |||
| public static byte[] decode(byte[] decrypted) { | |||
| int pad = (int) decrypted[decrypted.length - 1]; | |||
| int pad = decrypted[decrypted.length - 1]; | |||
| if (pad < 1 || pad > 32) { | |||
| pad = 0; | |||
| } | |||
| @@ -1,10 +1,9 @@ | |||
| package me.chanjar.weixin.common.util.crypto; | |||
| import org.apache.commons.codec.digest.DigestUtils; | |||
| import java.security.NoSuchAlgorithmException; | |||
| import java.util.Arrays; | |||
| import org.apache.commons.codec.digest.DigestUtils; | |||
| /** | |||
| * Created by Daniel Qian on 14/10/19. | |||
| */ | |||
| @@ -13,7 +12,7 @@ public class SHA1 { | |||
| /** | |||
| * 串接arr参数,生成sha1 digest | |||
| */ | |||
| public static String gen(String... arr) throws NoSuchAlgorithmException { | |||
| public static String gen(String... arr) { | |||
| Arrays.sort(arr); | |||
| StringBuilder sb = new StringBuilder(); | |||
| for (String a : arr) { | |||
| @@ -25,7 +24,7 @@ public class SHA1 { | |||
| /** | |||
| * 用&串接arr参数,生成sha1 digest | |||
| */ | |||
| public static String genWithAmple(String... arr) throws NoSuchAlgorithmException { | |||
| public static String genWithAmple(String... arr) { | |||
| Arrays.sort(arr); | |||
| StringBuilder sb = new StringBuilder(); | |||
| for (int i = 0; i < arr.length; i++) { | |||
| @@ -17,11 +17,10 @@ | |||
| */ | |||
| package me.chanjar.weixin.common.util.crypto; | |||
| import org.apache.commons.codec.binary.Base64; | |||
| import org.apache.commons.codec.digest.DigestUtils; | |||
| import org.w3c.dom.Document; | |||
| import org.w3c.dom.Element; | |||
| import org.xml.sax.InputSource; | |||
| import java.io.StringReader; | |||
| import java.nio.charset.Charset; | |||
| import java.util.Arrays; | |||
| import java.util.Random; | |||
| import javax.crypto.Cipher; | |||
| import javax.crypto.spec.IvParameterSpec; | |||
| @@ -29,10 +28,11 @@ import javax.crypto.spec.SecretKeySpec; | |||
| import javax.xml.parsers.DocumentBuilder; | |||
| import javax.xml.parsers.DocumentBuilderFactory; | |||
| import javax.xml.parsers.ParserConfigurationException; | |||
| import java.io.StringReader; | |||
| import java.nio.charset.Charset; | |||
| import java.security.NoSuchAlgorithmException; | |||
| import java.util.*; | |||
| import org.apache.commons.codec.binary.Base64; | |||
| import org.w3c.dom.Document; | |||
| import org.w3c.dom.Element; | |||
| import org.xml.sax.InputSource; | |||
| public class WxCryptUtil { | |||
| @@ -72,33 +72,6 @@ public class WxCryptUtil { | |||
| this.aesKey = Base64.decodeBase64(encodingAesKey + "="); | |||
| } | |||
| /** | |||
| * 微信公众号支付签名算法(详见:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3) | |||
| * @param packageParams 原始参数 | |||
| * @param signKey 加密Key(即 商户Key) | |||
| * @return 签名字符串 | |||
| */ | |||
| public static String createSign(Map<String, String> packageParams, | |||
| String signKey) { | |||
| SortedMap<String, String> sortedMap = new TreeMap<String, String>(); | |||
| sortedMap.putAll(packageParams); | |||
| List<String> keys = new ArrayList<String>(packageParams.keySet()); | |||
| Collections.sort(keys); | |||
| StringBuffer toSign = new StringBuffer(); | |||
| for (String key : keys) { | |||
| String value = packageParams.get(key); | |||
| if (null != value && !"".equals(value) && !"sign".equals(key) | |||
| && !"key".equals(key)) { | |||
| toSign.append(key + "=" + value + "&"); | |||
| } | |||
| } | |||
| toSign.append("key=" + signKey); | |||
| String sign = DigestUtils.md5Hex(toSign.toString()).toUpperCase(); | |||
| return sign; | |||
| } | |||
| static String extractEncryptPart(String xml) { | |||
| try { | |||
| DocumentBuilder db = builderLocal.get(); | |||
| @@ -130,13 +103,9 @@ public class WxCryptUtil { | |||
| String timeStamp = Long.toString(System.currentTimeMillis() / 1000l); | |||
| String nonce = genRandomStr(); | |||
| try { | |||
| String signature = SHA1.gen(token, timeStamp, nonce, encryptedXml); | |||
| String result = generateXml(encryptedXml, signature, timeStamp, nonce); | |||
| return result; | |||
| } catch (NoSuchAlgorithmException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| String signature = SHA1.gen(this.token, timeStamp, nonce, encryptedXml); | |||
| String result = generateXml(encryptedXml, signature, timeStamp, nonce); | |||
| return result; | |||
| } | |||
| /** | |||
| @@ -151,7 +120,7 @@ public class WxCryptUtil { | |||
| byte[] plainTextBytes = plainText.getBytes(CHARSET); | |||
| byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder( | |||
| plainTextBytes.length); | |||
| byte[] appIdBytes = appidOrCorpid.getBytes(CHARSET); | |||
| byte[] appIdBytes = this.appidOrCorpid.getBytes(CHARSET); | |||
| // randomStr + networkBytesOrder + text + appid | |||
| byteCollector.addBytes(randomStringBytes); | |||
| @@ -169,8 +138,8 @@ public class WxCryptUtil { | |||
| try { | |||
| // 设置加密模式为AES的CBC模式 | |||
| Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); | |||
| SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); | |||
| IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16); | |||
| SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES"); | |||
| IvParameterSpec iv = new IvParameterSpec(this.aesKey, 0, 16); | |||
| cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); | |||
| // 加密 | |||
| @@ -205,14 +174,10 @@ public class WxCryptUtil { | |||
| // 提取密文 | |||
| String cipherText = extractEncryptPart(encryptedXml); | |||
| try { | |||
| // 验证安全签名 | |||
| String signature = SHA1.gen(token, timeStamp, nonce, cipherText); | |||
| if (!signature.equals(msgSignature)) { | |||
| throw new RuntimeException("加密消息签名校验失败"); | |||
| } | |||
| } catch (NoSuchAlgorithmException e) { | |||
| throw new RuntimeException(e); | |||
| // 验证安全签名 | |||
| String signature = SHA1.gen(this.token, timeStamp, nonce, cipherText); | |||
| if (!signature.equals(msgSignature)) { | |||
| throw new RuntimeException("加密消息签名校验失败"); | |||
| } | |||
| // 解密 | |||
| @@ -231,9 +196,9 @@ public class WxCryptUtil { | |||
| try { | |||
| // 设置解密模式为AES的CBC模式 | |||
| Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); | |||
| SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES"); | |||
| SecretKeySpec key_spec = new SecretKeySpec(this.aesKey, "AES"); | |||
| IvParameterSpec iv = new IvParameterSpec( | |||
| Arrays.copyOfRange(aesKey, 0, 16)); | |||
| Arrays.copyOfRange(this.aesKey, 0, 16)); | |||
| cipher.init(Cipher.DECRYPT_MODE, key_spec, iv); | |||
| // 使用BASE64对密文进行解码 | |||
| @@ -264,7 +229,7 @@ public class WxCryptUtil { | |||
| } | |||
| // appid不相同的情况 | |||
| if (!from_appid.equals(appidOrCorpid)) { | |||
| if (!from_appid.equals(this.appidOrCorpid)) { | |||
| throw new RuntimeException("AppID不正确"); | |||
| } | |||
| @@ -277,7 +242,7 @@ public class WxCryptUtil { | |||
| * | |||
| * @param number | |||
| */ | |||
| private byte[] number2BytesInNetworkOrder(int number) { | |||
| private static byte[] number2BytesInNetworkOrder(int number) { | |||
| byte[] orderBytes = new byte[4]; | |||
| orderBytes[3] = (byte) (number & 0xFF); | |||
| orderBytes[2] = (byte) (number >> 8 & 0xFF); | |||
| @@ -291,7 +256,7 @@ public class WxCryptUtil { | |||
| * | |||
| * @param bytesInNetworkOrder | |||
| */ | |||
| private int bytesNetworkOrder2Number(byte[] bytesInNetworkOrder) { | |||
| private static int bytesNetworkOrder2Number(byte[] bytesInNetworkOrder) { | |||
| int sourceNumber = 0; | |||
| for (int i = 0; i < 4; i++) { | |||
| sourceNumber <<= 8; | |||
| @@ -303,7 +268,7 @@ public class WxCryptUtil { | |||
| /** | |||
| * 随机生成16位字符串 | |||
| */ | |||
| private String genRandomStr() { | |||
| private static String genRandomStr() { | |||
| String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |||
| Random random = new Random(); | |||
| StringBuffer sb = new StringBuffer(); | |||
| @@ -323,8 +288,8 @@ public class WxCryptUtil { | |||
| * @param nonce 随机字符串 | |||
| * @return 生成的xml字符串 | |||
| */ | |||
| private String generateXml(String encrypt, String signature, String timestamp, | |||
| String nonce) { | |||
| private static String generateXml(String encrypt, String signature, | |||
| String timestamp, String nonce) { | |||
| String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n" | |||
| + "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n" | |||
| + "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n" | |||
| @@ -17,37 +17,25 @@ public class FileUtils { | |||
| * @param tmpDirFile 临时文件夹目录 | |||
| */ | |||
| public static File createTmpFile(InputStream inputStream, String name, String ext, File tmpDirFile) throws IOException { | |||
| FileOutputStream fos = null; | |||
| try { | |||
| File tmpFile; | |||
| if (tmpDirFile == null) { | |||
| tmpFile = File.createTempFile(name, '.' + ext); | |||
| } else { | |||
| tmpFile = File.createTempFile(name, '.' + ext, tmpDirFile); | |||
| } | |||
| tmpFile.deleteOnExit(); | |||
| fos = new FileOutputStream(tmpFile); | |||
| 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); | |||
| } | |||
| fos.flush(); | |||
| return tmpFile; | |||
| } finally { | |||
| if (inputStream != null) { | |||
| try { | |||
| inputStream.close(); | |||
| } catch (IOException e) { | |||
| } | |||
| } | |||
| if (fos != null) { | |||
| try { | |||
| fos.close(); | |||
| } catch (IOException e) { | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| @@ -103,43 +103,45 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { | |||
| private void prepare() { | |||
| Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() | |||
| .register("http", this.plainConnectionSocketFactory) | |||
| .register("https", this.sslConnectionSocketFactory) | |||
| .build(); | |||
| .register("http", this.plainConnectionSocketFactory) | |||
| .register("https", this.sslConnectionSocketFactory) | |||
| .build(); | |||
| @SuppressWarnings("resource") | |||
| PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); | |||
| connectionManager.setMaxTotal(this.maxTotalConn); | |||
| connectionManager.setDefaultMaxPerRoute(this.maxConnPerHost); | |||
| connectionManager.setDefaultSocketConfig( | |||
| SocketConfig.copy(SocketConfig.DEFAULT) | |||
| .setSoTimeout(this.soTimeout) | |||
| .build() | |||
| SocketConfig.copy(SocketConfig.DEFAULT) | |||
| .setSoTimeout(this.soTimeout) | |||
| .build() | |||
| ); | |||
| this.idleConnectionMonitorThread = new IdleConnectionMonitorThread( | |||
| connectionManager, this.idleConnTimeout, this.checkWaitTime); | |||
| connectionManager, this.idleConnTimeout, this.checkWaitTime); | |||
| this.idleConnectionMonitorThread.setDaemon(true); | |||
| this.idleConnectionMonitorThread.start(); | |||
| this.httpClientBuilder = HttpClients.custom() | |||
| .setConnectionManager(connectionManager) | |||
| .setDefaultRequestConfig( | |||
| RequestConfig.custom() | |||
| .setSocketTimeout(this.soTimeout) | |||
| .setConnectTimeout(this.connectionTimeout) | |||
| .setConnectionRequestTimeout(this.connectionRequestTimeout) | |||
| .build() | |||
| ) | |||
| .setRetryHandler(this.httpRequestRetryHandler); | |||
| .setConnectionManager(connectionManager) | |||
| .setConnectionManagerShared(true) | |||
| .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)) { | |||
| && StringUtils.isNotBlank(this.httpProxyUsername)) { | |||
| // 使用代理服务器 需要用户认证的代理服务器 | |||
| CredentialsProvider provider = new BasicCredentialsProvider(); | |||
| provider.setCredentials( | |||
| new AuthScope(this.httpProxyHost, this.httpProxyPort), | |||
| new UsernamePasswordCredentials(this.httpProxyUsername, | |||
| this.httpProxyPassword)); | |||
| new AuthScope(this.httpProxyHost, this.httpProxyPort), | |||
| new UsernamePasswordCredentials(this.httpProxyUsername, | |||
| this.httpProxyPassword)); | |||
| this.httpClientBuilder.setDefaultCredentialsProvider(provider); | |||
| } | |||
| @@ -180,7 +182,7 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { | |||
| wait(this.checkWaitTime); | |||
| this.connMgr.closeExpiredConnections(); | |||
| this.connMgr.closeIdleConnections(this.idleConnTimeout, | |||
| TimeUnit.MILLISECONDS); | |||
| TimeUnit.MILLISECONDS); | |||
| } | |||
| } | |||
| } catch (InterruptedException ignore) { | |||
| @@ -14,6 +14,7 @@ public class InputStreamResponseHandler implements ResponseHandler<InputStream> | |||
| public static final ResponseHandler<InputStream> INSTANCE = new InputStreamResponseHandler(); | |||
| @Override | |||
| public InputStream handleResponse(final HttpResponse response) throws IOException { | |||
| final StatusLine statusLine = response.getStatusLine(); | |||
| final HttpEntity entity = response.getEntity(); | |||
| @@ -1,15 +1,14 @@ | |||
| package me.chanjar.weixin.common.util.http; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import jodd.http.HttpRequest; | |||
| import jodd.http.HttpResponse; | |||
| import jodd.http.ProxyInfo; | |||
| import jodd.http.net.SocketHttpConnectionProvider; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import java.io.IOException; | |||
| /** | |||
| * 简单的GET请求执行器,请求的参数是String, 返回的结果也是String | |||
| @@ -20,7 +19,7 @@ public class JoddGetRequestExecutor implements RequestExecutor<String, String> { | |||
| @Override | |||
| public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, | |||
| String queryParam) throws WxErrorException, IOException { | |||
| String queryParam) throws WxErrorException { | |||
| if (queryParam != null) { | |||
| if (uri.indexOf('?') == -1) { | |||
| uri += '?'; | |||
| @@ -1,15 +1,14 @@ | |||
| package me.chanjar.weixin.common.util.http; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import jodd.http.HttpRequest; | |||
| import jodd.http.HttpResponse; | |||
| import jodd.http.ProxyInfo; | |||
| import jodd.http.net.SocketHttpConnectionProvider; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import java.io.IOException; | |||
| /** | |||
| * 简单的POST请求执行器,请求的参数是String, 返回的结果也是String | |||
| @@ -20,7 +19,7 @@ public class JoddPostRequestExecutor implements RequestExecutor<String, String> | |||
| @Override | |||
| public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, | |||
| String postEntity) throws WxErrorException, IOException { | |||
| String postEntity) throws WxErrorException { | |||
| SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); | |||
| if (httpProxy != null) { | |||
| @@ -20,7 +20,7 @@ import java.util.regex.Pattern; | |||
| /** | |||
| * 下载媒体文件请求执行器,请求的参数是String, 返回的结果是File | |||
| * | |||
| * 视频文件不支持下载 | |||
| * @author Daniel Qian | |||
| */ | |||
| public class MediaDownloadRequestExecutor implements RequestExecutor<File, String> { | |||
| @@ -28,15 +28,12 @@ public class MediaDownloadRequestExecutor implements RequestExecutor<File, Strin | |||
| private File tmpDirFile; | |||
| public MediaDownloadRequestExecutor() { | |||
| super(); | |||
| } | |||
| public MediaDownloadRequestExecutor(File tmpDirFile) { | |||
| super(); | |||
| this.tmpDirFile = tmpDirFile; | |||
| } | |||
| @Override | |||
| public File execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { | |||
| if (queryParam != null) { | |||
| @@ -52,26 +49,26 @@ public class MediaDownloadRequestExecutor implements RequestExecutor<File, Strin | |||
| httpGet.setConfig(config); | |||
| } | |||
| try (CloseableHttpResponse response = httpclient.execute(httpGet)) { | |||
| try (CloseableHttpResponse response = httpclient.execute(httpGet); | |||
| InputStream inputStream = InputStreamResponseHandler.INSTANCE | |||
| .handleResponse(response)) { | |||
| Header[] contentTypeHeader = response.getHeaders("Content-Type"); | |||
| if (contentTypeHeader != null && contentTypeHeader.length > 0) { | |||
| // 下载媒体文件出错 | |||
| if (ContentType.TEXT_PLAIN.getMimeType().equals(contentTypeHeader[0].getValue())) { | |||
| if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { | |||
| // application/json; encoding=utf-8 下载媒体文件出错 | |||
| String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); | |||
| throw new WxErrorException(WxError.fromJson(responseContent)); | |||
| } | |||
| } | |||
| InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response); | |||
| // 视频文件不支持下载 | |||
| String fileName = getFileName(response); | |||
| if (StringUtils.isBlank(fileName)) { | |||
| return null; | |||
| } | |||
| String[] name_ext = fileName.split("\\."); | |||
| File localFile = FileUtils.createTmpFile(inputStream, name_ext[0], name_ext[1], tmpDirFile); | |||
| return localFile; | |||
| String[] nameAndExt = fileName.split("\\."); | |||
| return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); | |||
| } finally { | |||
| httpGet.releaseConnection(); | |||
| @@ -79,13 +76,18 @@ public class MediaDownloadRequestExecutor implements RequestExecutor<File, Strin | |||
| } | |||
| protected String getFileName(CloseableHttpResponse response) { | |||
| 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()); | |||
| } | |||
| Pattern p = Pattern.compile(".*filename=\"(.*)\""); | |||
| Matcher m = p.matcher(contentDispositionHeader[0].getValue()); | |||
| m.matches(); | |||
| String fileName = m.group(1); | |||
| return fileName; | |||
| if(m.matches()){ | |||
| return m.group(1); | |||
| } | |||
| throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); | |||
| } | |||
| } | |||
| @@ -2,7 +2,6 @@ package me.chanjar.weixin.common.util.http; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.client.ClientProtocolException; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import java.io.IOException; | |||
| @@ -21,7 +20,6 @@ public interface RequestExecutor<T, E> { | |||
| * @param uri uri | |||
| * @param data 数据 | |||
| * @throws WxErrorException | |||
| * @throws ClientProtocolException | |||
| * @throws IOException | |||
| */ | |||
| T execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, E data) throws WxErrorException, IOException; | |||
| @@ -1,7 +1,7 @@ | |||
| package me.chanjar.weixin.common.util.http; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import java.io.IOException; | |||
| import org.apache.http.Consts; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.client.config.RequestConfig; | |||
| @@ -10,7 +10,8 @@ import org.apache.http.client.methods.HttpPost; | |||
| import org.apache.http.entity.StringEntity; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import java.io.IOException; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| /** | |||
| * 简单的POST请求执行器,请求的参数是String, 返回的结果也是String | |||
| @@ -34,6 +35,17 @@ public class SimplePostRequestExecutor implements RequestExecutor<String, String | |||
| try (CloseableHttpResponse response = httpclient.execute(httpPost)) { | |||
| String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); | |||
| if (responseContent.isEmpty()) { | |||
| throw new WxErrorException( | |||
| WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") | |||
| .build()); | |||
| } | |||
| if (responseContent.startsWith("<xml>")) { | |||
| //xml格式输出直接返回 | |||
| return responseContent; | |||
| } | |||
| WxError error = WxError.fromJson(responseContent); | |||
| if (error.getErrorCode() != 0) { | |||
| throw new WxErrorException(error); | |||
| @@ -35,7 +35,7 @@ public class URIUtil { | |||
| private static String getHex(byte buf[]) { | |||
| StringBuilder o = new StringBuilder(buf.length * 3); | |||
| for (int i = 0; i < buf.length; i++) { | |||
| int n = (int) buf[i] & 0xff; | |||
| int n = buf[i] & 0xff; | |||
| o.append("%"); | |||
| if (n < 0x10) { | |||
| o.append("0"); | |||
| @@ -19,6 +19,7 @@ public class Utf8ResponseHandler implements ResponseHandler<String> { | |||
| public static final ResponseHandler<String> INSTANCE = new Utf8ResponseHandler(); | |||
| @Override | |||
| public String handleResponse(final HttpResponse response) throws IOException { | |||
| final StatusLine statusLine = response.getStatusLine(); | |||
| final HttpEntity entity = response.getEntity(); | |||
| @@ -9,6 +9,10 @@ | |||
| package me.chanjar.weixin.common.util.json; | |||
| import java.util.List; | |||
| import com.google.common.collect.Lists; | |||
| import com.google.gson.JsonArray; | |||
| import com.google.gson.JsonElement; | |||
| import com.google.gson.JsonObject; | |||
| @@ -112,4 +116,21 @@ public class GsonHelper { | |||
| return r == null ? 0f : r; | |||
| } | |||
| public static Integer[] getIntArray(JsonObject o, String string) { | |||
| JsonArray jsonArray = getAsJsonArray(o.getAsJsonArray(string)); | |||
| if (jsonArray == null) { | |||
| return null; | |||
| } | |||
| List<Integer> result = Lists.newArrayList(); | |||
| for (int i = 0; i < jsonArray.size(); i++) { | |||
| result.add(jsonArray.get(i).getAsInt()); | |||
| } | |||
| return result.toArray(new Integer[0]); | |||
| } | |||
| public static JsonArray getAsJsonArray(JsonElement element) { | |||
| return element == null ? null : element.getAsJsonArray(); | |||
| } | |||
| } | |||
| @@ -18,6 +18,7 @@ import java.lang.reflect.Type; | |||
| */ | |||
| public class WxAccessTokenAdapter implements JsonDeserializer<WxAccessToken> { | |||
| @Override | |||
| public WxAccessToken deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||
| WxAccessToken accessToken = new WxAccessToken(); | |||
| JsonObject accessTokenJsonObject = json.getAsJsonObject(); | |||
| @@ -18,6 +18,7 @@ import java.lang.reflect.Type; | |||
| */ | |||
| public class WxErrorAdapter implements JsonDeserializer<WxError> { | |||
| @Override | |||
| public WxError deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||
| WxError wxError = new WxError(); | |||
| JsonObject wxErrorJsonObject = json.getAsJsonObject(); | |||
| @@ -18,6 +18,7 @@ import java.lang.reflect.Type; | |||
| */ | |||
| public class WxMediaUploadResultAdapter implements JsonDeserializer<WxMediaUploadResult> { | |||
| @Override | |||
| public WxMediaUploadResult deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||
| WxMediaUploadResult uploadResult = new WxMediaUploadResult(); | |||
| JsonObject uploadResultJsonObject = json.getAsJsonObject(); | |||
| @@ -29,6 +29,7 @@ import me.chanjar.weixin.common.bean.menu.WxMenuRule; | |||
| */ | |||
| public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializer<WxMenu> { | |||
| @Override | |||
| public JsonElement serialize(WxMenu menu, Type typeOfSrc, JsonSerializationContext context) { | |||
| JsonObject json = new JsonObject(); | |||
| @@ -75,6 +76,7 @@ public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializ | |||
| return matchRule; | |||
| } | |||
| @Override | |||
| public WxMenu deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||
| /* | |||
| * 操蛋的微信 | |||
| @@ -47,7 +47,7 @@ import java.util.*; | |||
| public class StringManager { | |||
| private static final Map<String, Map<Locale, StringManager>> managers = | |||
| new Hashtable<String, Map<Locale, StringManager>>(); | |||
| new Hashtable<>(); | |||
| private static int LOCALE_CACHE_SIZE = 10; | |||
| /** | |||
| * The ResourceBundle for this StringManager. | |||
| @@ -81,10 +81,10 @@ public class StringManager { | |||
| } | |||
| } | |||
| } | |||
| bundle = bnd; | |||
| this.bundle = bnd; | |||
| // Get the actual locale, which may be different from the requested one | |||
| if (bundle != null) { | |||
| Locale bundleLocale = bundle.getLocale(); | |||
| if (this.bundle != null) { | |||
| Locale bundleLocale = this.bundle.getLocale(); | |||
| if (bundleLocale.equals(Locale.ROOT)) { | |||
| this.locale = Locale.ENGLISH; | |||
| } else { | |||
| @@ -192,8 +192,8 @@ public class StringManager { | |||
| try { | |||
| // Avoid NPE if bundle is null and treat it like an MRE | |||
| if (bundle != null) { | |||
| str = bundle.getString(key); | |||
| if (this.bundle != null) { | |||
| str = this.bundle.getString(key); | |||
| } | |||
| } catch (MissingResourceException mre) { | |||
| //bad: shouldn't mask an exception the following way: | |||
| @@ -227,7 +227,7 @@ public class StringManager { | |||
| } | |||
| MessageFormat mf = new MessageFormat(value); | |||
| mf.setLocale(locale); | |||
| mf.setLocale(this.locale); | |||
| return mf.format(args, new StringBuffer(), null).toString(); | |||
| } | |||
| @@ -235,6 +235,6 @@ public class StringManager { | |||
| * Identify the Locale this StringManager is associated with | |||
| */ | |||
| public Locale getLocale() { | |||
| return locale; | |||
| return this.locale; | |||
| } | |||
| } | |||
| @@ -1,5 +1,7 @@ | |||
| package me.chanjar.weixin.common.util.xml; | |||
| import java.io.Writer; | |||
| import com.thoughtworks.xstream.XStream; | |||
| import com.thoughtworks.xstream.core.util.QuickWriter; | |||
| import com.thoughtworks.xstream.io.HierarchicalStreamWriter; | |||
| @@ -8,8 +10,6 @@ import com.thoughtworks.xstream.io.xml.XppDriver; | |||
| import com.thoughtworks.xstream.security.NullPermission; | |||
| import com.thoughtworks.xstream.security.PrimitiveTypePermission; | |||
| import java.io.Writer; | |||
| public class XStreamInitializer { | |||
| public static XStream getInstance() { | |||
| @@ -25,15 +25,20 @@ public class XStreamInitializer { | |||
| @Override | |||
| protected void writeText(QuickWriter writer, String text) { | |||
| if (text.startsWith(PREFIX_CDATA) && text.endsWith(SUFFIX_CDATA)) { | |||
| if (text.startsWith(this.PREFIX_CDATA) && text.endsWith(this.SUFFIX_CDATA)) { | |||
| writer.write(text); | |||
| } else if (text.startsWith(PREFIX_MEDIA_ID) && text.endsWith(SUFFIX_MEDIA_ID)) { | |||
| } else if (text.startsWith(this.PREFIX_MEDIA_ID) && text.endsWith(this.SUFFIX_MEDIA_ID)) { | |||
| writer.write(text); | |||
| } else { | |||
| super.writeText(writer, text); | |||
| } | |||
| } | |||
| @Override | |||
| public String encodeNode(String name) { | |||
| return name;//防止将_转换成__ | |||
| } | |||
| }; | |||
| } | |||
| }); | |||
| @@ -106,7 +106,7 @@ public class SessionTest { | |||
| } | |||
| @Test(dataProvider = "getSessionManager") | |||
| public void testMaxActive(WxSessionManager sessionManager) throws InterruptedException { | |||
| public void testMaxActive(WxSessionManager sessionManager) { | |||
| InternalSessionManager ism = (InternalSessionManager) sessionManager; | |||
| ism.setMaxActiveSessions(2); | |||
| @@ -118,7 +118,7 @@ public class SessionTest { | |||
| } | |||
| @Test(dataProvider = "getSessionManager", expectedExceptions = TooManyActiveSessionsException.class) | |||
| public void testMaxActive2(WxSessionManager sessionManager) throws InterruptedException { | |||
| public void testMaxActive2(WxSessionManager sessionManager) { | |||
| InternalSessionManager ism = (InternalSessionManager) sessionManager; | |||
| ism.setMaxActiveSessions(2); | |||
| @@ -34,8 +34,8 @@ public class WxCryptUtilTest { | |||
| String afterAesEncrypt2 = "jn1L23DB+6ELqJ+6bruv23M2GmYfkv0xBh2h+XTBOKVKcgDFHle6gqcZ1cZrk3e1qjPQ1F4RsLWzQRG9udbKWesxlkupqcEcW7ZQweImX9+wLMa0GaUzpkycA8+IamDBxn5loLgZpnS7fVAbExOkK5DYHBmv5tptA9tklE/fTIILHR8HLXa5nQvFb3tYPKAlHF3rtTeayNf0QuM+UW/wM9enGIDIJHF7CLHiDNAYxr+r+OrJCmPQyTy8cVWlu9iSvOHPT/77bZqJucQHQ04sq7KZI27OcqpQNSto2OdHCoTccjggX5Z9Mma0nMJBU+jLKJ38YB1fBIz+vBzsYjrTmFQ44YfeEuZ+xRTQwr92vhA9OxchWVINGC50qE/6lmkwWTwGX9wtQpsJKhP+oS7rvTY8+VdzETdfakjkwQ5/Xka042OlUb1/slTwo4RscuQ+RdxSGvDahxAJ6+EAjLt9d8igHngxIbf6YyqqROxuxqIeIch3CssH/LqRs+iAcILvApYZckqmA7FNERspKA5f8GoJ9sv8xmGvZ9Yrf57cExWtnX8aCMMaBropU/1k+hKP5LVdzbWCG0hGwx/dQudYR/eXp3P0XxjlFiy+9DMlaFExWUZQDajPkdPrEeOwofJb"; | |||
| public void testNormal() throws ParserConfigurationException, SAXException, IOException { | |||
| WxCryptUtil pc = new WxCryptUtil(token, encodingAesKey, appId); | |||
| String encryptedXml = pc.encrypt(replyMsg); | |||
| WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId); | |||
| String encryptedXml = pc.encrypt(this.replyMsg); | |||
| System.out.println(encryptedXml); | |||
| @@ -56,31 +56,31 @@ public class WxCryptUtilTest { | |||
| String nonce = root.getElementsByTagName("Nonce").item(0).getTextContent(); | |||
| System.out.println(nonce); | |||
| String messageText = String.format(xmlFormat, cipherText); | |||
| String messageText = String.format(this.xmlFormat, cipherText); | |||
| System.out.println(messageText); | |||
| // 第三方收到企业号平台发送的消息 | |||
| String plainMessage = pc.decrypt(cipherText); | |||
| System.out.println(plainMessage); | |||
| assertEquals(plainMessage, replyMsg); | |||
| assertEquals(plainMessage, this.replyMsg); | |||
| } | |||
| public void testAesEncrypt() { | |||
| WxCryptUtil pc = new WxCryptUtil(token, encodingAesKey, appId); | |||
| assertEquals(pc.encrypt(randomStr, replyMsg), afterAesEncrypt); | |||
| WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId); | |||
| assertEquals(pc.encrypt(this.randomStr, this.replyMsg), this.afterAesEncrypt); | |||
| } | |||
| public void testAesEncrypt2() { | |||
| WxCryptUtil pc = new WxCryptUtil(token, encodingAesKey, appId); | |||
| assertEquals(pc.encrypt(randomStr, replyMsg2), afterAesEncrypt2); | |||
| WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId); | |||
| assertEquals(pc.encrypt(this.randomStr, this.replyMsg2), this.afterAesEncrypt2); | |||
| } | |||
| public void testValidateSignatureError() throws ParserConfigurationException, SAXException, | |||
| IOException { | |||
| try { | |||
| WxCryptUtil pc = new WxCryptUtil(token, encodingAesKey, appId); | |||
| String afterEncrpt = pc.encrypt(replyMsg); | |||
| WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId); | |||
| String afterEncrpt = pc.encrypt(this.replyMsg); | |||
| DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | |||
| DocumentBuilder db = dbf.newDocumentBuilder(); | |||
| StringReader sr = new StringReader(afterEncrpt); | |||
| @@ -91,8 +91,8 @@ public class WxCryptUtilTest { | |||
| NodeList nodelist1 = root.getElementsByTagName("Encrypt"); | |||
| String encrypt = nodelist1.item(0).getTextContent(); | |||
| String fromXML = String.format(xmlFormat, encrypt); | |||
| pc.decrypt("12345", timestamp, nonce, fromXML); // 这里签名错误 | |||
| String fromXML = String.format(this.xmlFormat, encrypt); | |||
| pc.decrypt("12345", this.timestamp, this.nonce, fromXML); // 这里签名错误 | |||
| } catch (RuntimeException e) { | |||
| assertEquals(e.getMessage(), "加密消息签名校验失败"); | |||
| return; | |||
| @@ -6,7 +6,7 @@ | |||
| <parent> | |||
| <groupId>com.github.binarywang</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>2.1.0</version> | |||
| <version>2.2.0</version> | |||
| </parent> | |||
| <artifactId>weixin-java-cp</artifactId> | |||
| @@ -55,13 +55,13 @@ public interface WxCpConfigStorage { | |||
| String getOauth2redirectUri(); | |||
| String getHttp_proxy_host(); | |||
| String getHttpProxyHost(); | |||
| int getHttp_proxy_port(); | |||
| int getHttpProxyPort(); | |||
| String getHttp_proxy_username(); | |||
| String getHttpProxyUsername(); | |||
| String getHttp_proxy_password(); | |||
| String getHttpProxyPassword(); | |||
| File getTmpDirFile(); | |||
| @@ -1,10 +1,13 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| 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.http.ApacheHttpClientBuilder; | |||
| import java.io.File; | |||
| /** | |||
| * 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化 | |||
| * | |||
| @@ -23,10 +26,10 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| protected volatile String oauth2redirectUri; | |||
| protected volatile String http_proxy_host; | |||
| protected volatile int http_proxy_port; | |||
| protected volatile String http_proxy_username; | |||
| protected volatile String http_proxy_password; | |||
| protected volatile String httpProxyHost; | |||
| protected volatile int httpProxyPort; | |||
| protected volatile String httpProxyUsername; | |||
| protected volatile String httpProxyPassword; | |||
| protected volatile String jsapiTicket; | |||
| protected volatile long jsapiTicketExpiresTime; | |||
| @@ -35,6 +38,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| private volatile ApacheHttpClientBuilder apacheHttpClientBuilder; | |||
| @Override | |||
| public String getAccessToken() { | |||
| return this.accessToken; | |||
| } | |||
| @@ -43,18 +47,22 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| this.accessToken = accessToken; | |||
| } | |||
| @Override | |||
| public boolean isAccessTokenExpired() { | |||
| return System.currentTimeMillis() > this.expiresTime; | |||
| } | |||
| @Override | |||
| public void expireAccessToken() { | |||
| this.expiresTime = 0; | |||
| } | |||
| @Override | |||
| public synchronized void updateAccessToken(WxAccessToken accessToken) { | |||
| updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); | |||
| } | |||
| @Override | |||
| public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) { | |||
| this.accessToken = accessToken; | |||
| this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l; | |||
| @@ -62,7 +70,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| @Override | |||
| public String getJsapiTicket() { | |||
| return jsapiTicket; | |||
| return this.jsapiTicket; | |||
| } | |||
| public void setJsapiTicket(String jsapiTicket) { | |||
| @@ -70,27 +78,31 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| } | |||
| public long getJsapiTicketExpiresTime() { | |||
| return jsapiTicketExpiresTime; | |||
| return this.jsapiTicketExpiresTime; | |||
| } | |||
| public void setJsapiTicketExpiresTime(long jsapiTicketExpiresTime) { | |||
| this.jsapiTicketExpiresTime = jsapiTicketExpiresTime; | |||
| } | |||
| @Override | |||
| public boolean isJsapiTicketExpired() { | |||
| return System.currentTimeMillis() > this.jsapiTicketExpiresTime; | |||
| } | |||
| @Override | |||
| public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { | |||
| this.jsapiTicket = jsapiTicket; | |||
| // 预留200秒的时间 | |||
| this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l; | |||
| } | |||
| @Override | |||
| public void expireJsapiTicket() { | |||
| this.jsapiTicketExpiresTime = 0; | |||
| } | |||
| @Override | |||
| public String getCorpId() { | |||
| return this.corpId; | |||
| } | |||
| @@ -99,6 +111,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| this.corpId = corpId; | |||
| } | |||
| @Override | |||
| public String getCorpSecret() { | |||
| return this.corpSecret; | |||
| } | |||
| @@ -107,6 +120,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| this.corpSecret = corpSecret; | |||
| } | |||
| @Override | |||
| public String getToken() { | |||
| return this.token; | |||
| } | |||
| @@ -115,6 +129,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| this.token = token; | |||
| } | |||
| @Override | |||
| public long getExpiresTime() { | |||
| return this.expiresTime; | |||
| } | |||
| @@ -123,16 +138,18 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| this.expiresTime = expiresTime; | |||
| } | |||
| @Override | |||
| public String getAesKey() { | |||
| return aesKey; | |||
| return this.aesKey; | |||
| } | |||
| public void setAesKey(String aesKey) { | |||
| this.aesKey = aesKey; | |||
| } | |||
| @Override | |||
| public String getAgentId() { | |||
| return agentId; | |||
| return this.agentId; | |||
| } | |||
| public void setAgentId(String agentId) { | |||
| @@ -148,60 +165,50 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||
| this.oauth2redirectUri = oauth2redirectUri; | |||
| } | |||
| public String getHttp_proxy_host() { | |||
| return http_proxy_host; | |||
| @Override | |||
| public String getHttpProxyHost() { | |||
| return this.httpProxyHost; | |||
| } | |||
| public void setHttp_proxy_host(String http_proxy_host) { | |||
| this.http_proxy_host = http_proxy_host; | |||
| public void setHttpProxyHost(String httpProxyHost) { | |||
| this.httpProxyHost = httpProxyHost; | |||
| } | |||
| public int getHttp_proxy_port() { | |||
| return http_proxy_port; | |||
| @Override | |||
| public int getHttpProxyPort() { | |||
| return this.httpProxyPort; | |||
| } | |||
| public void setHttp_proxy_port(int http_proxy_port) { | |||
| this.http_proxy_port = http_proxy_port; | |||
| public void setHttpProxyPort(int httpProxyPort) { | |||
| this.httpProxyPort = httpProxyPort; | |||
| } | |||
| public String getHttp_proxy_username() { | |||
| return http_proxy_username; | |||
| @Override | |||
| public String getHttpProxyUsername() { | |||
| return this.httpProxyUsername; | |||
| } | |||
| public void setHttp_proxy_username(String http_proxy_username) { | |||
| this.http_proxy_username = http_proxy_username; | |||
| public void setHttpProxyUsername(String httpProxyUsername) { | |||
| this.httpProxyUsername = httpProxyUsername; | |||
| } | |||
| public String getHttp_proxy_password() { | |||
| return http_proxy_password; | |||
| @Override | |||
| public String getHttpProxyPassword() { | |||
| return this.httpProxyPassword; | |||
| } | |||
| public void setHttp_proxy_password(String http_proxy_password) { | |||
| this.http_proxy_password = http_proxy_password; | |||
| public void setHttpProxyPassword(String httpProxyPassword) { | |||
| this.httpProxyPassword = httpProxyPassword; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return "WxCpInMemoryConfigStorage{" + | |||
| "corpId='" + corpId + '\'' + | |||
| ", corpSecret='" + corpSecret + '\'' + | |||
| ", token='" + token + '\'' + | |||
| ", accessToken='" + accessToken + '\'' + | |||
| ", aesKey='" + aesKey + '\'' + | |||
| ", agentId='" + agentId + '\'' + | |||
| ", expiresTime=" + expiresTime + | |||
| ", http_proxy_host='" + http_proxy_host + '\'' + | |||
| ", http_proxy_port=" + http_proxy_port + | |||
| ", http_proxy_username='" + http_proxy_username + '\'' + | |||
| ", http_proxy_password='" + http_proxy_password + '\'' + | |||
| ", jsapiTicket='" + jsapiTicket + '\'' + | |||
| ", jsapiTicketExpiresTime='" + jsapiTicketExpiresTime + '\'' + | |||
| ", tmpDirFile='" + tmpDirFile + '\'' + | |||
| '}'; | |||
| return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); | |||
| } | |||
| @Override | |||
| public File getTmpDirFile() { | |||
| return tmpDirFile; | |||
| return this.tmpDirFile; | |||
| } | |||
| public void setTmpDirFile(File tmpDirFile) { | |||
| @@ -29,10 +29,10 @@ public class WxCpJedisConfigStorage implements WxCpConfigStorage { | |||
| private volatile String oauth2redirectUri; | |||
| private volatile String http_proxy_host; | |||
| private volatile int http_proxy_port; | |||
| private volatile String http_proxy_username; | |||
| private volatile String http_proxy_password; | |||
| private volatile String httpProxyHost; | |||
| private volatile int httpProxyPort; | |||
| private volatile String httpProxyUsername; | |||
| private volatile String httpProxyPassword; | |||
| private volatile File tmpDirFile; | |||
| @@ -185,23 +185,23 @@ public class WxCpJedisConfigStorage implements WxCpConfigStorage { | |||
| } | |||
| @Override | |||
| public String getHttp_proxy_host() { | |||
| return this.http_proxy_host; | |||
| public String getHttpProxyHost() { | |||
| return this.httpProxyHost; | |||
| } | |||
| @Override | |||
| public int getHttp_proxy_port() { | |||
| return this.http_proxy_port; | |||
| public int getHttpProxyPort() { | |||
| return this.httpProxyPort; | |||
| } | |||
| @Override | |||
| public String getHttp_proxy_username() { | |||
| return this.http_proxy_username; | |||
| public String getHttpProxyUsername() { | |||
| return this.httpProxyUsername; | |||
| } | |||
| @Override | |||
| public String getHttp_proxy_password() { | |||
| return this.http_proxy_password; | |||
| public String getHttpProxyPassword() { | |||
| return this.httpProxyPassword; | |||
| } | |||
| @Override | |||
| @@ -240,20 +240,20 @@ public class WxCpJedisConfigStorage implements WxCpConfigStorage { | |||
| this.oauth2redirectUri = oauth2redirectUri; | |||
| } | |||
| public void setHttp_proxy_host(String http_proxy_host) { | |||
| this.http_proxy_host = http_proxy_host; | |||
| public void setHttpProxyHost(String httpProxyHost) { | |||
| this.httpProxyHost = httpProxyHost; | |||
| } | |||
| public void setHttp_proxy_port(int http_proxy_port) { | |||
| this.http_proxy_port = http_proxy_port; | |||
| public void setHttpProxyPort(int httpProxyPort) { | |||
| this.httpProxyPort = httpProxyPort; | |||
| } | |||
| public void setHttp_proxy_username(String http_proxy_username) { | |||
| this.http_proxy_username = http_proxy_username; | |||
| public void setHttpProxyUsername(String httpProxyUsername) { | |||
| this.httpProxyUsername = httpProxyUsername; | |||
| } | |||
| public void setHttp_proxy_password(String http_proxy_password) { | |||
| this.http_proxy_password = http_proxy_password; | |||
| public void setHttpProxyPassword(String httpProxyPassword) { | |||
| this.httpProxyPassword = httpProxyPassword; | |||
| } | |||
| public void setTmpDirFile(File tmpDirFile) { | |||
| @@ -52,7 +52,7 @@ public class WxCpMessageRouter { | |||
| private static final int DEFAULT_THREAD_POOL_SIZE = 100; | |||
| protected final Logger log = LoggerFactory.getLogger(WxCpMessageRouter.class); | |||
| private final List<WxCpMessageRouterRule> rules = new ArrayList<WxCpMessageRouterRule>(); | |||
| private final List<WxCpMessageRouterRule> rules = new ArrayList<>(); | |||
| private final WxCpService wxCpService; | |||
| @@ -142,9 +142,9 @@ public class WxCpMessageRouter { | |||
| return null; | |||
| } | |||
| final List<WxCpMessageRouterRule> matchRules = new ArrayList<WxCpMessageRouterRule>(); | |||
| final List<WxCpMessageRouterRule> matchRules = new ArrayList<>(); | |||
| // 收集匹配的规则 | |||
| for (final WxCpMessageRouterRule rule : rules) { | |||
| for (final WxCpMessageRouterRule rule : this.rules) { | |||
| if (rule.test(wxMessage)) { | |||
| matchRules.add(rule); | |||
| if (!rule.isReEnter()) { | |||
| @@ -158,39 +158,40 @@ public class WxCpMessageRouter { | |||
| } | |||
| WxCpXmlOutMessage res = null; | |||
| final List<Future> futures = new ArrayList<Future>(); | |||
| final List<Future> futures = new ArrayList<>(); | |||
| for (final WxCpMessageRouterRule rule : matchRules) { | |||
| // 返回最后一个非异步的rule的执行结果 | |||
| if (rule.isAsync()) { | |||
| futures.add( | |||
| executorService.submit(new Runnable() { | |||
| this.executorService.submit(new Runnable() { | |||
| @Override | |||
| public void run() { | |||
| rule.service(wxMessage, wxCpService, sessionManager, exceptionHandler); | |||
| rule.service(wxMessage, WxCpMessageRouter.this.wxCpService, WxCpMessageRouter.this.sessionManager, WxCpMessageRouter.this.exceptionHandler); | |||
| } | |||
| }) | |||
| ); | |||
| } else { | |||
| res = rule.service(wxMessage, wxCpService, sessionManager, exceptionHandler); | |||
| res = rule.service(wxMessage, this.wxCpService, this.sessionManager, this.exceptionHandler); | |||
| // 在同步操作结束,session访问结束 | |||
| log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | |||
| this.log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | |||
| sessionEndAccess(wxMessage); | |||
| } | |||
| } | |||
| if (futures.size() > 0) { | |||
| executorService.submit(new Runnable() { | |||
| this.executorService.submit(new Runnable() { | |||
| @Override | |||
| public void run() { | |||
| for (Future future : futures) { | |||
| try { | |||
| future.get(); | |||
| log.debug("End session access: async=true, sessionId={}", wxMessage.getFromUserName()); | |||
| WxCpMessageRouter.this.log.debug("End session access: async=true, sessionId={}", wxMessage.getFromUserName()); | |||
| // 异步操作结束,session访问结束 | |||
| sessionEndAccess(wxMessage); | |||
| } catch (InterruptedException e) { | |||
| log.error("Error happened when wait task finish", e); | |||
| WxCpMessageRouter.this.log.error("Error happened when wait task finish", e); | |||
| } catch (ExecutionException e) { | |||
| log.error("Error happened when wait task finish", e); | |||
| WxCpMessageRouter.this.log.error("Error happened when wait task finish", e); | |||
| } | |||
| } | |||
| } | |||
| @@ -213,7 +214,7 @@ public class WxCpMessageRouter { | |||
| messageId = String.valueOf(wxMessage.getMsgId()); | |||
| } | |||
| return messageDuplicateChecker.isDuplicate(messageId); | |||
| return this.messageDuplicateChecker.isDuplicate(messageId); | |||
| } | |||
| @@ -224,7 +225,7 @@ public class WxCpMessageRouter { | |||
| */ | |||
| protected void sessionEndAccess(WxCpXmlMessage wxMessage) { | |||
| InternalSession session = ((InternalSessionManager) sessionManager).findSession(wxMessage.getFromUserName()); | |||
| InternalSession session = ((InternalSessionManager) this.sessionManager).findSession(wxMessage.getFromUserName()); | |||
| if (session != null) { | |||
| session.endAccess(); | |||
| } | |||
| @@ -36,9 +36,9 @@ public class WxCpMessageRouterRule { | |||
| private Integer agentId; | |||
| private List<WxCpMessageHandler> handlers = new ArrayList<WxCpMessageHandler>(); | |||
| private List<WxCpMessageHandler> handlers = new ArrayList<>(); | |||
| private List<WxCpMessageInterceptor> interceptors = new ArrayList<WxCpMessageInterceptor>(); | |||
| private List<WxCpMessageInterceptor> interceptors = new ArrayList<>(); | |||
| protected WxCpMessageRouterRule(WxCpMessageRouter routerBuilder) { | |||
| this.routerBuilder = routerBuilder; | |||
| @@ -235,7 +235,7 @@ public class WxCpMessageRouterRule { | |||
| try { | |||
| Map<String, Object> context = new HashMap<String, Object>(); | |||
| Map<String, Object> context = new HashMap<>(); | |||
| // 如果拦截器不通过 | |||
| for (WxCpMessageInterceptor interceptor : this.interceptors) { | |||
| if (!interceptor.intercept(wxMessage, context, wxCpService, sessionManager)) { | |||
| @@ -300,7 +300,7 @@ public class WxCpMessageRouterRule { | |||
| } | |||
| public boolean isAsync() { | |||
| return async; | |||
| return this.async; | |||
| } | |||
| public void setAsync(boolean async) { | |||
| @@ -308,7 +308,7 @@ public class WxCpMessageRouterRule { | |||
| } | |||
| public boolean isReEnter() { | |||
| return reEnter; | |||
| return this.reEnter; | |||
| } | |||
| public void setReEnter(boolean reEnter) { | |||
| @@ -1,12 +1,28 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.List; | |||
| import java.util.UUID; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.client.ClientProtocolException; | |||
| import org.apache.http.client.config.RequestConfig; | |||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||
| import org.apache.http.client.methods.HttpGet; | |||
| import org.apache.http.impl.client.BasicResponseHandler; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import 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.internal.Streams; | |||
| import com.google.gson.reflect.TypeToken; | |||
| import com.google.gson.stream.JsonReader; | |||
| import me.chanjar.weixin.common.bean.WxAccessToken; | |||
| import me.chanjar.weixin.common.bean.WxJsapiSignature; | |||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
| @@ -20,30 +36,20 @@ import me.chanjar.weixin.common.util.RandomUtils; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| import me.chanjar.weixin.common.util.crypto.SHA1; | |||
| import me.chanjar.weixin.common.util.fs.FileUtils; | |||
| import me.chanjar.weixin.common.util.http.*; | |||
| import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; | |||
| import me.chanjar.weixin.common.util.http.DefaultApacheHttpClientBuilder; | |||
| import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; | |||
| import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | |||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
| import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | |||
| import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||
| import me.chanjar.weixin.common.util.http.URIUtil; | |||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||
| 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; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.client.ClientProtocolException; | |||
| import org.apache.http.client.config.RequestConfig; | |||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||
| import org.apache.http.client.methods.HttpGet; | |||
| import org.apache.http.impl.client.BasicResponseHandler; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.StringReader; | |||
| import java.security.NoSuchAlgorithmException; | |||
| import java.util.List; | |||
| import java.util.UUID; | |||
| public class WxCpServiceImpl implements WxCpService { | |||
| @@ -59,7 +65,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| */ | |||
| protected final Object globalJsapiTicketRefreshLock = new Object(); | |||
| protected WxCpConfigStorage wxCpConfigStorage; | |||
| protected WxCpConfigStorage configStorage; | |||
| protected CloseableHttpClient httpClient; | |||
| @@ -72,42 +78,48 @@ public class WxCpServiceImpl implements WxCpService { | |||
| private int retrySleepMillis = 1000; | |||
| private int maxRetryTimes = 5; | |||
| @Override | |||
| public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { | |||
| try { | |||
| return SHA1.gen(wxCpConfigStorage.getToken(), timestamp, nonce, data).equals(msgSignature); | |||
| return SHA1.gen(this.configStorage.getToken(), timestamp, nonce, data) | |||
| .equals(msgSignature); | |||
| } catch (Exception e) { | |||
| return false; | |||
| } | |||
| } | |||
| @Override | |||
| public void userAuthenticated(String userId) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; | |||
| get(url, null); | |||
| } | |||
| @Override | |||
| public String getAccessToken() throws WxErrorException { | |||
| return getAccessToken(false); | |||
| } | |||
| @Override | |||
| public String getAccessToken(boolean forceRefresh) throws WxErrorException { | |||
| if (forceRefresh) { | |||
| wxCpConfigStorage.expireAccessToken(); | |||
| this.configStorage.expireAccessToken(); | |||
| } | |||
| if (wxCpConfigStorage.isAccessTokenExpired()) { | |||
| synchronized (globalAccessTokenRefreshLock) { | |||
| if (wxCpConfigStorage.isAccessTokenExpired()) { | |||
| if (this.configStorage.isAccessTokenExpired()) { | |||
| synchronized (this.globalAccessTokenRefreshLock) { | |||
| if (this.configStorage.isAccessTokenExpired()) { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?" | |||
| + "&corpid=" + wxCpConfigStorage.getCorpId() | |||
| + "&corpsecret=" + wxCpConfigStorage.getCorpSecret(); | |||
| + "&corpid=" + this.configStorage.getCorpId() | |||
| + "&corpsecret=" + this.configStorage.getCorpSecret(); | |||
| try { | |||
| HttpGet httpGet = new HttpGet(url); | |||
| if (httpProxy != null) { | |||
| RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); | |||
| if (this.httpProxy != null) { | |||
| RequestConfig config = RequestConfig.custom() | |||
| .setProxy(this.httpProxy).build(); | |||
| httpGet.setConfig(config); | |||
| } | |||
| CloseableHttpClient httpclient = getHttpclient(); | |||
| String resultContent = null; | |||
| try (CloseableHttpResponse response = httpclient.execute(httpGet)) { | |||
| try (CloseableHttpClient httpclient = getHttpclient(); | |||
| CloseableHttpResponse response = httpclient.execute(httpGet)) { | |||
| resultContent = new BasicResponseHandler().handleResponse(response); | |||
| } finally { | |||
| httpGet.releaseConnection(); | |||
| @@ -117,7 +129,8 @@ public class WxCpServiceImpl implements WxCpService { | |||
| throw new WxErrorException(error); | |||
| } | |||
| WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); | |||
| wxCpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); | |||
| this.configStorage.updateAccessToken( | |||
| accessToken.getAccessToken(), accessToken.getExpiresIn()); | |||
| } catch (ClientProtocolException e) { | |||
| throw new RuntimeException(e); | |||
| } catch (IOException e) { | |||
| @@ -126,59 +139,60 @@ public class WxCpServiceImpl implements WxCpService { | |||
| } | |||
| } | |||
| } | |||
| return wxCpConfigStorage.getAccessToken(); | |||
| return this.configStorage.getAccessToken(); | |||
| } | |||
| @Override | |||
| public String getJsapiTicket() throws WxErrorException { | |||
| return getJsapiTicket(false); | |||
| } | |||
| @Override | |||
| public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { | |||
| if (forceRefresh) { | |||
| wxCpConfigStorage.expireJsapiTicket(); | |||
| this.configStorage.expireJsapiTicket(); | |||
| } | |||
| if (wxCpConfigStorage.isJsapiTicketExpired()) { | |||
| synchronized (globalJsapiTicketRefreshLock) { | |||
| if (wxCpConfigStorage.isJsapiTicketExpired()) { | |||
| if (this.configStorage.isJsapiTicketExpired()) { | |||
| synchronized (this.globalJsapiTicketRefreshLock) { | |||
| if (this.configStorage.isJsapiTicketExpired()) { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; | |||
| String responseContent = execute(new SimpleGetRequestExecutor(), url, null); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); | |||
| String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); | |||
| int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); | |||
| wxCpConfigStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds); | |||
| this.configStorage.updateJsapiTicket(jsapiTicket, | |||
| expiresInSeconds); | |||
| } | |||
| } | |||
| } | |||
| return wxCpConfigStorage.getJsapiTicket(); | |||
| return this.configStorage.getJsapiTicket(); | |||
| } | |||
| @Override | |||
| public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { | |||
| long timestamp = System.currentTimeMillis() / 1000; | |||
| String noncestr = RandomUtils.getRandomStr(); | |||
| String jsapiTicket = getJsapiTicket(false); | |||
| try { | |||
| String signature = SHA1.genWithAmple( | |||
| "jsapi_ticket=" + jsapiTicket, | |||
| "noncestr=" + noncestr, | |||
| "timestamp=" + timestamp, | |||
| "url=" + url | |||
| ); | |||
| WxJsapiSignature jsapiSignature = new WxJsapiSignature(); | |||
| jsapiSignature.setTimestamp(timestamp); | |||
| jsapiSignature.setNoncestr(noncestr); | |||
| jsapiSignature.setUrl(url); | |||
| jsapiSignature.setSignature(signature); | |||
| // Fixed bug | |||
| jsapiSignature.setAppid(this.wxCpConfigStorage.getCorpId()); | |||
| return jsapiSignature; | |||
| } catch (NoSuchAlgorithmException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| String signature = SHA1.genWithAmple( | |||
| "jsapi_ticket=" + jsapiTicket, | |||
| "noncestr=" + noncestr, | |||
| "timestamp=" + timestamp, | |||
| "url=" + url | |||
| ); | |||
| WxJsapiSignature jsapiSignature = new WxJsapiSignature(); | |||
| jsapiSignature.setTimestamp(timestamp); | |||
| jsapiSignature.setNoncestr(noncestr); | |||
| jsapiSignature.setUrl(url); | |||
| jsapiSignature.setSignature(signature); | |||
| // Fixed bug | |||
| jsapiSignature.setAppid(this.configStorage.getCorpId()); | |||
| return jsapiSignature; | |||
| } | |||
| @Override | |||
| public void messageSend(WxCpMessage message) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; | |||
| post(url, message.toJson()); | |||
| @@ -186,18 +200,19 @@ public class WxCpServiceImpl implements WxCpService { | |||
| @Override | |||
| public void menuCreate(WxMenu menu) throws WxErrorException { | |||
| menuCreate(wxCpConfigStorage.getAgentId(), menu); | |||
| menuCreate(this.configStorage.getAgentId(), menu); | |||
| } | |||
| @Override | |||
| public void menuCreate(String agentId, WxMenu menu) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" + wxCpConfigStorage.getAgentId(); | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" | |||
| + this.configStorage.getAgentId(); | |||
| post(url, menu.toJson()); | |||
| } | |||
| @Override | |||
| public void menuDelete() throws WxErrorException { | |||
| menuDelete(wxCpConfigStorage.getAgentId()); | |||
| menuDelete(this.configStorage.getAgentId()); | |||
| } | |||
| @Override | |||
| @@ -208,7 +223,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| @Override | |||
| public WxMenu menuGet() throws WxErrorException { | |||
| return menuGet(wxCpConfigStorage.getAgentId()); | |||
| return menuGet(this.configStorage.getAgentId()); | |||
| } | |||
| @Override | |||
| @@ -226,42 +241,52 @@ public class WxCpServiceImpl implements WxCpService { | |||
| } | |||
| } | |||
| @Override | |||
| public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) | |||
| throws WxErrorException, IOException { | |||
| return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); | |||
| } | |||
| @Override | |||
| public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; | |||
| return execute(new MediaUploadRequestExecutor(), url, file); | |||
| } | |||
| @Override | |||
| public File mediaDownload(String media_id) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; | |||
| return execute(new MediaDownloadRequestExecutor(wxCpConfigStorage.getTmpDirFile()), url, "media_id=" + media_id); | |||
| return execute( | |||
| new MediaDownloadRequestExecutor( | |||
| this.configStorage.getTmpDirFile()), | |||
| url, "media_id=" + media_id); | |||
| } | |||
| @Override | |||
| public Integer departCreate(WxCpDepart depart) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; | |||
| String responseContent = execute( | |||
| new SimplePostRequestExecutor(), | |||
| url, | |||
| depart.toJson()); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); | |||
| } | |||
| @Override | |||
| public void departUpdate(WxCpDepart group) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; | |||
| post(url, group.toJson()); | |||
| } | |||
| @Override | |||
| public void departDelete(Integer departId) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; | |||
| get(url, null); | |||
| } | |||
| @Override | |||
| public List<WxCpDepart> departGet() throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; | |||
| String responseContent = get(url, null); | |||
| @@ -269,7 +294,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } | |||
| * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } | |||
| */ | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| return WxCpGsonBuilder.INSTANCE.create() | |||
| .fromJson( | |||
| tmpJsonElement.getAsJsonObject().get("department"), | |||
| @@ -329,7 +354,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| } | |||
| String responseContent = get(url, params); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| return WxCpGsonBuilder.INSTANCE.create() | |||
| .fromJson( | |||
| tmpJsonElement.getAsJsonObject().get("userlist"), | |||
| @@ -352,7 +377,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| } | |||
| String responseContent = get(url, params); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| return WxCpGsonBuilder.INSTANCE.create() | |||
| .fromJson( | |||
| tmpJsonElement.getAsJsonObject().get("userlist"), | |||
| @@ -367,7 +392,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| JsonObject o = new JsonObject(); | |||
| o.addProperty("tagname", tagName); | |||
| String responseContent = post(url, o.toString()); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); | |||
| } | |||
| @@ -390,7 +415,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| public List<WxCpTag> tagGet() throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; | |||
| String responseContent = get(url, null); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| return WxCpGsonBuilder.INSTANCE.create() | |||
| .fromJson( | |||
| tmpJsonElement.getAsJsonObject().get("taglist"), | |||
| @@ -403,7 +428,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| public List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; | |||
| String responseContent = get(url, null); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| return WxCpGsonBuilder.INSTANCE.create() | |||
| .fromJson( | |||
| tmpJsonElement.getAsJsonObject().get("userlist"), | |||
| @@ -450,7 +475,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| @Override | |||
| public String oauth2buildAuthorizationUrl(String state) { | |||
| return this.oauth2buildAuthorizationUrl( | |||
| this.wxCpConfigStorage.getOauth2redirectUri(), | |||
| this.configStorage.getOauth2redirectUri(), | |||
| state | |||
| ); | |||
| } | |||
| @@ -458,7 +483,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| @Override | |||
| public String oauth2buildAuthorizationUrl(String redirectUri, String state) { | |||
| String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; | |||
| url += "appid=" + wxCpConfigStorage.getCorpId(); | |||
| url += "appid=" + this.configStorage.getCorpId(); | |||
| url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); | |||
| url += "&response_type=code"; | |||
| url += "&scope=snsapi_base"; | |||
| @@ -471,7 +496,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| @Override | |||
| public String[] oauth2getUserInfo(String code) throws WxErrorException { | |||
| return oauth2getUserInfo(wxCpConfigStorage.getAgentId(), code); | |||
| return oauth2getUserInfo(this.configStorage.getAgentId(), code); | |||
| } | |||
| @Override | |||
| @@ -480,7 +505,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| + "code=" + code | |||
| + "&agendid=" + agentId; | |||
| String responseText = get(url, null); | |||
| JsonElement je = Streams.parse(new JsonReader(new StringReader(responseText))); | |||
| JsonElement je = new JsonParser().parse(responseText); | |||
| JsonObject jo = je.getAsJsonObject(); | |||
| return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId")}; | |||
| } | |||
| @@ -494,7 +519,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| jsonObject.addProperty("invite_tips", inviteTips); | |||
| } | |||
| String responseContent = post(url, jsonObject.toString()); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); | |||
| } | |||
| @@ -502,7 +527,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| public String[] getCallbackIp() throws WxErrorException { | |||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; | |||
| String responseContent = get(url, null); | |||
| JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||
| JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | |||
| JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); | |||
| String[] ips = new String[jsonArray.size()]; | |||
| for (int i = 0; i < jsonArray.size(); i++) { | |||
| @@ -511,10 +536,12 @@ public class WxCpServiceImpl implements WxCpService { | |||
| return ips; | |||
| } | |||
| @Override | |||
| public String get(String url, String queryParam) throws WxErrorException { | |||
| return execute(new SimpleGetRequestExecutor(), url, queryParam); | |||
| } | |||
| @Override | |||
| public String post(String url, String postData) throws WxErrorException { | |||
| return execute(new SimplePostRequestExecutor(), url, postData); | |||
| } | |||
| @@ -522,6 +549,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| /** | |||
| * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 | |||
| */ | |||
| @Override | |||
| public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | |||
| int retryTimes = 0; | |||
| do { | |||
| @@ -533,9 +561,10 @@ public class WxCpServiceImpl implements WxCpService { | |||
| * -1 系统繁忙, 1000ms后重试 | |||
| */ | |||
| if (error.getErrorCode() == -1) { | |||
| int sleepMillis = retrySleepMillis * (1 << retryTimes); | |||
| int sleepMillis = this.retrySleepMillis * (1 << retryTimes); | |||
| try { | |||
| log.debug("微信系统繁忙,{}ms 后重试(第{}次)", sleepMillis, retryTimes + 1); | |||
| this.log.debug("微信系统繁忙,{}ms 后重试(第{}次)", sleepMillis, | |||
| retryTimes + 1); | |||
| Thread.sleep(sleepMillis); | |||
| } catch (InterruptedException e1) { | |||
| throw new RuntimeException(e1); | |||
| @@ -544,7 +573,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| throw e; | |||
| } | |||
| } | |||
| } while (++retryTimes < maxRetryTimes); | |||
| } while (++retryTimes < this.maxRetryTimes); | |||
| throw new RuntimeException("微信服务端异常,超出重试次数"); | |||
| } | |||
| @@ -559,7 +588,8 @@ public class WxCpServiceImpl implements WxCpService { | |||
| uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; | |||
| try { | |||
| return executor.execute(getHttpclient(), httpProxy, uriWithAccessToken, data); | |||
| return executor.execute(getHttpclient(), this.httpProxy, | |||
| uriWithAccessToken, data); | |||
| } catch (WxErrorException e) { | |||
| WxError error = e.getError(); | |||
| /* | |||
| @@ -569,7 +599,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| */ | |||
| if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { | |||
| // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | |||
| wxCpConfigStorage.expireAccessToken(); | |||
| this.configStorage.expireAccessToken(); | |||
| return execute(executor, uri, data); | |||
| } | |||
| if (error.getErrorCode() != 0) { | |||
| @@ -584,21 +614,28 @@ public class WxCpServiceImpl implements WxCpService { | |||
| } | |||
| protected CloseableHttpClient getHttpclient() { | |||
| return httpClient; | |||
| return this.httpClient; | |||
| } | |||
| @Override | |||
| public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { | |||
| this.wxCpConfigStorage = wxConfigProvider; | |||
| ApacheHttpClientBuilder apacheHttpClientBuilder = wxCpConfigStorage.getApacheHttpClientBuilder(); | |||
| this.configStorage = wxConfigProvider; | |||
| ApacheHttpClientBuilder apacheHttpClientBuilder = this.configStorage | |||
| .getApacheHttpClientBuilder(); | |||
| if (null == apacheHttpClientBuilder) { | |||
| apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); | |||
| } | |||
| apacheHttpClientBuilder.httpProxyHost(wxCpConfigStorage.getHttp_proxy_host()) | |||
| .httpProxyPort(wxCpConfigStorage.getHttp_proxy_port()) | |||
| .httpProxyUsername(wxCpConfigStorage.getHttp_proxy_username()) | |||
| .httpProxyPassword(wxCpConfigStorage.getHttp_proxy_password()); | |||
| httpClient = apacheHttpClientBuilder.build(); | |||
| apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost()) | |||
| .httpProxyPort(this.configStorage.getHttpProxyPort()) | |||
| .httpProxyUsername(this.configStorage.getHttpProxyUsername()) | |||
| .httpProxyPassword(this.configStorage.getHttpProxyPassword()); | |||
| if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) { | |||
| this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort()); | |||
| } | |||
| this.httpClient = apacheHttpClientBuilder.build(); | |||
| } | |||
| @Override | |||
| @@ -614,18 +651,18 @@ public class WxCpServiceImpl implements WxCpService { | |||
| @Override | |||
| public WxSession getSession(String id) { | |||
| if (sessionManager == null) { | |||
| if (this.sessionManager == null) { | |||
| return null; | |||
| } | |||
| return sessionManager.getSession(id); | |||
| return this.sessionManager.getSession(id); | |||
| } | |||
| @Override | |||
| public WxSession getSession(String id, boolean create) { | |||
| if (sessionManager == null) { | |||
| if (this.sessionManager == null) { | |||
| return null; | |||
| } | |||
| return sessionManager.getSession(id, create); | |||
| return this.sessionManager.getSession(id, create); | |||
| } | |||
| @@ -657,7 +694,7 @@ public class WxCpServiceImpl implements WxCpService { | |||
| } | |||
| public File getTmpDirFile() { | |||
| return tmpDirFile; | |||
| return this.tmpDirFile; | |||
| } | |||
| public void setTmpDirFile(File tmpDirFile) { | |||
| @@ -11,6 +11,10 @@ import java.io.Serializable; | |||
| */ | |||
| public class WxCpDepart implements Serializable { | |||
| /** | |||
| * | |||
| */ | |||
| private static final long serialVersionUID = -5028321625140879571L; | |||
| private Integer id; | |||
| private String name; | |||
| private Integer parentId; | |||
| @@ -21,7 +25,7 @@ public class WxCpDepart implements Serializable { | |||
| } | |||
| public Integer getId() { | |||
| return id; | |||
| return this.id; | |||
| } | |||
| public void setId(Integer id) { | |||
| @@ -29,7 +33,7 @@ public class WxCpDepart implements Serializable { | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| return this.name; | |||
| } | |||
| public void setName(String name) { | |||
| @@ -37,7 +41,7 @@ public class WxCpDepart implements Serializable { | |||
| } | |||
| public Integer getParentId() { | |||
| return parentId; | |||
| return this.parentId; | |||
| } | |||
| public void setParentId(Integer parentId) { | |||
| @@ -45,7 +49,7 @@ public class WxCpDepart implements Serializable { | |||
| } | |||
| public Integer getOrder() { | |||
| return order; | |||
| return this.order; | |||
| } | |||
| public void setOrder(Integer order) { | |||
| @@ -59,10 +63,10 @@ public class WxCpDepart implements Serializable { | |||
| @Override | |||
| public String toString() { | |||
| return "WxCpDepart{" + | |||
| "id=" + id + | |||
| ", name='" + name + '\'' + | |||
| ", parentId=" + parentId + | |||
| ", order=" + order + | |||
| "id=" + this.id + | |||
| ", name='" + this.name + '\'' + | |||
| ", parentId=" + this.parentId + | |||
| ", order=" + this.order + | |||
| '}'; | |||
| } | |||
| } | |||
| @@ -14,6 +14,10 @@ import java.util.List; | |||
| */ | |||
| public class WxCpMessage implements Serializable { | |||
| /** | |||
| * | |||
| */ | |||
| private static final long serialVersionUID = -2082278303476631708L; | |||
| private String toUser; | |||
| private String toParty; | |||
| private String toTag; | |||
| @@ -27,7 +31,7 @@ public class WxCpMessage implements Serializable { | |||
| private String musicUrl; | |||
| private String hqMusicUrl; | |||
| private String safe; | |||
| private List<WxArticle> articles = new ArrayList<WxArticle>(); | |||
| private List<WxArticle> articles = new ArrayList<>(); | |||
| /** | |||
| * 获得文本消息builder | |||
| @@ -72,7 +76,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getToUser() { | |||
| return toUser; | |||
| return this.toUser; | |||
| } | |||
| public void setToUser(String toUser) { | |||
| @@ -80,7 +84,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getToParty() { | |||
| return toParty; | |||
| return this.toParty; | |||
| } | |||
| public void setToParty(String toParty) { | |||
| @@ -88,7 +92,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getToTag() { | |||
| return toTag; | |||
| return this.toTag; | |||
| } | |||
| public void setToTag(String toTag) { | |||
| @@ -96,7 +100,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getAgentId() { | |||
| return agentId; | |||
| return this.agentId; | |||
| } | |||
| public void setAgentId(String agentId) { | |||
| @@ -104,7 +108,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getMsgType() { | |||
| return msgType; | |||
| return this.msgType; | |||
| } | |||
| /** | |||
| @@ -125,7 +129,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getSafe() { | |||
| return safe; | |||
| return this.safe; | |||
| } | |||
| public void setSafe(String safe) { | |||
| @@ -133,7 +137,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getContent() { | |||
| return content; | |||
| return this.content; | |||
| } | |||
| public void setContent(String content) { | |||
| @@ -141,7 +145,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| return this.mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| @@ -149,7 +153,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getThumbMediaId() { | |||
| return thumbMediaId; | |||
| return this.thumbMediaId; | |||
| } | |||
| public void setThumbMediaId(String thumbMediaId) { | |||
| @@ -157,7 +161,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getTitle() { | |||
| return title; | |||
| return this.title; | |||
| } | |||
| public void setTitle(String title) { | |||
| @@ -165,7 +169,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getDescription() { | |||
| return description; | |||
| return this.description; | |||
| } | |||
| public void setDescription(String description) { | |||
| @@ -173,7 +177,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getMusicUrl() { | |||
| return musicUrl; | |||
| return this.musicUrl; | |||
| } | |||
| public void setMusicUrl(String musicUrl) { | |||
| @@ -181,7 +185,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getHqMusicUrl() { | |||
| return hqMusicUrl; | |||
| return this.hqMusicUrl; | |||
| } | |||
| public void setHqMusicUrl(String hqMusicUrl) { | |||
| @@ -189,7 +193,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public List<WxArticle> getArticles() { | |||
| return articles; | |||
| return this.articles; | |||
| } | |||
| public void setArticles(List<WxArticle> articles) { | |||
| @@ -208,7 +212,7 @@ public class WxCpMessage implements Serializable { | |||
| private String picUrl; | |||
| public String getTitle() { | |||
| return title; | |||
| return this.title; | |||
| } | |||
| public void setTitle(String title) { | |||
| @@ -216,7 +220,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getDescription() { | |||
| return description; | |||
| return this.description; | |||
| } | |||
| public void setDescription(String description) { | |||
| @@ -224,7 +228,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getUrl() { | |||
| return url; | |||
| return this.url; | |||
| } | |||
| public void setUrl(String url) { | |||
| @@ -232,7 +236,7 @@ public class WxCpMessage implements Serializable { | |||
| } | |||
| public String getPicUrl() { | |||
| return picUrl; | |||
| return this.picUrl; | |||
| } | |||
| public void setPicUrl(String picUrl) { | |||
| @@ -9,6 +9,11 @@ import java.io.Serializable; | |||
| */ | |||
| public class WxCpTag implements Serializable { | |||
| /** | |||
| * | |||
| */ | |||
| private static final long serialVersionUID = -7243320279646928402L; | |||
| private String id; | |||
| private String name; | |||
| @@ -28,7 +33,7 @@ public class WxCpTag implements Serializable { | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| return this.name; | |||
| } | |||
| public void setName(String name) { | |||
| @@ -36,7 +41,7 @@ public class WxCpTag implements Serializable { | |||
| } | |||
| public String getId() { | |||
| return id; | |||
| return this.id; | |||
| } | |||
| public void setId(String id) { | |||
| @@ -13,7 +13,11 @@ import java.util.List; | |||
| */ | |||
| public class WxCpUser implements Serializable { | |||
| private final List<Attr> extAttrs = new ArrayList<Attr>(); | |||
| /** | |||
| * | |||
| */ | |||
| private static final long serialVersionUID = -5696099236344075582L; | |||
| private final List<Attr> extAttrs = new ArrayList<>(); | |||
| private String userId; | |||
| private String name; | |||
| private Integer[] departIds; | |||
| @@ -32,7 +36,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getUserId() { | |||
| return userId; | |||
| return this.userId; | |||
| } | |||
| public void setUserId(String userId) { | |||
| @@ -40,7 +44,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| return this.name; | |||
| } | |||
| public void setName(String name) { | |||
| @@ -48,7 +52,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public Integer[] getDepartIds() { | |||
| return departIds; | |||
| return this.departIds; | |||
| } | |||
| public void setDepartIds(Integer[] departIds) { | |||
| @@ -56,7 +60,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getGender() { | |||
| return gender; | |||
| return this.gender; | |||
| } | |||
| public void setGender(String gender) { | |||
| @@ -64,7 +68,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getPosition() { | |||
| return position; | |||
| return this.position; | |||
| } | |||
| public void setPosition(String position) { | |||
| @@ -72,7 +76,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getMobile() { | |||
| return mobile; | |||
| return this.mobile; | |||
| } | |||
| public void setMobile(String mobile) { | |||
| @@ -80,7 +84,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getTel() { | |||
| return tel; | |||
| return this.tel; | |||
| } | |||
| public void setTel(String tel) { | |||
| @@ -88,7 +92,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getEmail() { | |||
| return email; | |||
| return this.email; | |||
| } | |||
| public void setEmail(String email) { | |||
| @@ -96,7 +100,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getWeiXinId() { | |||
| return weiXinId; | |||
| return this.weiXinId; | |||
| } | |||
| public void setWeiXinId(String weiXinId) { | |||
| @@ -104,7 +108,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getAvatar() { | |||
| return avatar; | |||
| return this.avatar; | |||
| } | |||
| public void setAvatar(String avatar) { | |||
| @@ -112,7 +116,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public Integer getStatus() { | |||
| return status; | |||
| return this.status; | |||
| } | |||
| public void setStatus(Integer status) { | |||
| @@ -120,7 +124,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public Integer getEnable() { | |||
| return enable; | |||
| return this.enable; | |||
| } | |||
| public void setEnable(Integer enable) { | |||
| @@ -132,7 +136,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public List<Attr> getExtAttrs() { | |||
| return extAttrs; | |||
| return this.extAttrs; | |||
| } | |||
| public String toJson() { | |||
| @@ -150,7 +154,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| return this.name; | |||
| } | |||
| public void setName(String name) { | |||
| @@ -158,7 +162,7 @@ public class WxCpUser implements Serializable { | |||
| } | |||
| public String getValue() { | |||
| return value; | |||
| return this.value; | |||
| } | |||
| public void setValue(String value) { | |||
| @@ -32,6 +32,11 @@ public class WxCpXmlMessage implements Serializable { | |||
| // 以下都是微信推送过来的消息的xml的element所对应的属性 | |||
| /////////////////////// | |||
| /** | |||
| * | |||
| */ | |||
| private static final long serialVersionUID = -1042994982179476410L; | |||
| @XStreamAlias("AgentID") | |||
| private Integer agentId; | |||
| @@ -200,7 +205,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Integer getAgentId() { | |||
| return agentId; | |||
| return this.agentId; | |||
| } | |||
| public void setAgentId(Integer agentId) { | |||
| @@ -208,7 +213,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getToUserName() { | |||
| return toUserName; | |||
| return this.toUserName; | |||
| } | |||
| public void setToUserName(String toUserName) { | |||
| @@ -216,7 +221,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Long getCreateTime() { | |||
| return createTime; | |||
| return this.createTime; | |||
| } | |||
| public void setCreateTime(Long createTime) { | |||
| @@ -236,7 +241,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| * </pre> | |||
| */ | |||
| public String getMsgType() { | |||
| return msgType; | |||
| return this.msgType; | |||
| } | |||
| /** | |||
| @@ -256,7 +261,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getContent() { | |||
| return content; | |||
| return this.content; | |||
| } | |||
| public void setContent(String content) { | |||
| @@ -264,7 +269,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Long getMsgId() { | |||
| return msgId; | |||
| return this.msgId; | |||
| } | |||
| public void setMsgId(Long msgId) { | |||
| @@ -272,7 +277,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getPicUrl() { | |||
| return picUrl; | |||
| return this.picUrl; | |||
| } | |||
| public void setPicUrl(String picUrl) { | |||
| @@ -280,7 +285,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| return this.mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| @@ -288,7 +293,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getFormat() { | |||
| return format; | |||
| return this.format; | |||
| } | |||
| public void setFormat(String format) { | |||
| @@ -296,7 +301,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getThumbMediaId() { | |||
| return thumbMediaId; | |||
| return this.thumbMediaId; | |||
| } | |||
| public void setThumbMediaId(String thumbMediaId) { | |||
| @@ -304,7 +309,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Double getLocationX() { | |||
| return locationX; | |||
| return this.locationX; | |||
| } | |||
| public void setLocationX(Double locationX) { | |||
| @@ -312,7 +317,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Double getLocationY() { | |||
| return locationY; | |||
| return this.locationY; | |||
| } | |||
| public void setLocationY(Double locationY) { | |||
| @@ -320,7 +325,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Double getScale() { | |||
| return scale; | |||
| return this.scale; | |||
| } | |||
| public void setScale(Double scale) { | |||
| @@ -328,7 +333,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getLabel() { | |||
| return label; | |||
| return this.label; | |||
| } | |||
| public void setLabel(String label) { | |||
| @@ -336,7 +341,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getTitle() { | |||
| return title; | |||
| return this.title; | |||
| } | |||
| public void setTitle(String title) { | |||
| @@ -344,7 +349,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getDescription() { | |||
| return description; | |||
| return this.description; | |||
| } | |||
| public void setDescription(String description) { | |||
| @@ -352,7 +357,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getUrl() { | |||
| return url; | |||
| return this.url; | |||
| } | |||
| public void setUrl(String url) { | |||
| @@ -360,7 +365,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getEvent() { | |||
| return event; | |||
| return this.event; | |||
| } | |||
| public void setEvent(String event) { | |||
| @@ -368,7 +373,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getEventKey() { | |||
| return eventKey; | |||
| return this.eventKey; | |||
| } | |||
| public void setEventKey(String eventKey) { | |||
| @@ -376,7 +381,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getTicket() { | |||
| return ticket; | |||
| return this.ticket; | |||
| } | |||
| public void setTicket(String ticket) { | |||
| @@ -384,7 +389,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Double getLatitude() { | |||
| return latitude; | |||
| return this.latitude; | |||
| } | |||
| public void setLatitude(Double latitude) { | |||
| @@ -392,7 +397,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Double getLongitude() { | |||
| return longitude; | |||
| return this.longitude; | |||
| } | |||
| public void setLongitude(Double longitude) { | |||
| @@ -400,7 +405,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Double getPrecision() { | |||
| return precision; | |||
| return this.precision; | |||
| } | |||
| public void setPrecision(Double precision) { | |||
| @@ -408,7 +413,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getRecognition() { | |||
| return recognition; | |||
| return this.recognition; | |||
| } | |||
| public void setRecognition(String recognition) { | |||
| @@ -416,7 +421,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getFromUserName() { | |||
| return fromUserName; | |||
| return this.fromUserName; | |||
| } | |||
| public void setFromUserName(String fromUserName) { | |||
| @@ -424,7 +429,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getStatus() { | |||
| return status; | |||
| return this.status; | |||
| } | |||
| public void setStatus(String status) { | |||
| @@ -432,7 +437,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Integer getTotalCount() { | |||
| return totalCount; | |||
| return this.totalCount; | |||
| } | |||
| public void setTotalCount(Integer totalCount) { | |||
| @@ -440,7 +445,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Integer getFilterCount() { | |||
| return filterCount; | |||
| return this.filterCount; | |||
| } | |||
| public void setFilterCount(Integer filterCount) { | |||
| @@ -448,7 +453,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Integer getSentCount() { | |||
| return sentCount; | |||
| return this.sentCount; | |||
| } | |||
| public void setSentCount(Integer sentCount) { | |||
| @@ -456,7 +461,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public Integer getErrorCount() { | |||
| return errorCount; | |||
| return this.errorCount; | |||
| } | |||
| public void setErrorCount(Integer errorCount) { | |||
| @@ -464,7 +469,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public WxCpXmlMessage.ScanCodeInfo getScanCodeInfo() { | |||
| return scanCodeInfo; | |||
| return this.scanCodeInfo; | |||
| } | |||
| public void setScanCodeInfo(WxCpXmlMessage.ScanCodeInfo scanCodeInfo) { | |||
| @@ -472,7 +477,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public WxCpXmlMessage.SendPicsInfo getSendPicsInfo() { | |||
| return sendPicsInfo; | |||
| return this.sendPicsInfo; | |||
| } | |||
| public void setSendPicsInfo(WxCpXmlMessage.SendPicsInfo sendPicsInfo) { | |||
| @@ -480,7 +485,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public WxCpXmlMessage.SendLocationInfo getSendLocationInfo() { | |||
| return sendLocationInfo; | |||
| return this.sendLocationInfo; | |||
| } | |||
| public void setSendLocationInfo(WxCpXmlMessage.SendLocationInfo sendLocationInfo) { | |||
| @@ -490,39 +495,39 @@ public class WxCpXmlMessage implements Serializable { | |||
| @Override | |||
| public String toString() { | |||
| return "WxCpXmlMessage{" + | |||
| "agentId=" + agentId + | |||
| ", toUserName='" + toUserName + '\'' + | |||
| ", fromUserName='" + fromUserName + '\'' + | |||
| ", createTime=" + createTime + | |||
| ", msgType='" + msgType + '\'' + | |||
| ", content='" + content + '\'' + | |||
| ", msgId=" + msgId + | |||
| ", picUrl='" + picUrl + '\'' + | |||
| ", mediaId='" + mediaId + '\'' + | |||
| ", format='" + format + '\'' + | |||
| ", thumbMediaId='" + thumbMediaId + '\'' + | |||
| ", locationX=" + locationX + | |||
| ", locationY=" + locationY + | |||
| ", scale=" + scale + | |||
| ", label='" + label + '\'' + | |||
| ", title='" + title + '\'' + | |||
| ", description='" + description + '\'' + | |||
| ", url='" + url + '\'' + | |||
| ", event='" + event + '\'' + | |||
| ", eventKey='" + eventKey + '\'' + | |||
| ", ticket='" + ticket + '\'' + | |||
| ", latitude=" + latitude + | |||
| ", longitude=" + longitude + | |||
| ", precision=" + precision + | |||
| ", recognition='" + recognition + '\'' + | |||
| ", status='" + status + '\'' + | |||
| ", totalCount=" + totalCount + | |||
| ", filterCount=" + filterCount + | |||
| ", sentCount=" + sentCount + | |||
| ", errorCount=" + errorCount + | |||
| ", scanCodeInfo=" + scanCodeInfo + | |||
| ", sendPicsInfo=" + sendPicsInfo + | |||
| ", sendLocationInfo=" + sendLocationInfo + | |||
| "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 + | |||
| '}'; | |||
| } | |||
| @@ -542,7 +547,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| */ | |||
| public String getScanType() { | |||
| return scanType; | |||
| return this.scanType; | |||
| } | |||
| public void setScanType(String scanType) { | |||
| @@ -553,7 +558,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| * 扫描结果,即二维码对应的字符串信息 | |||
| */ | |||
| public String getScanResult() { | |||
| return scanResult; | |||
| return this.scanResult; | |||
| } | |||
| public void setScanResult(String scanResult) { | |||
| @@ -566,12 +571,12 @@ public class WxCpXmlMessage implements Serializable { | |||
| public static class SendPicsInfo { | |||
| @XStreamAlias("PicList") | |||
| protected final List<Item> picList = new ArrayList<Item>(); | |||
| protected final List<Item> picList = new ArrayList<>(); | |||
| @XStreamAlias("Count") | |||
| private Long count; | |||
| public Long getCount() { | |||
| return count; | |||
| return this.count; | |||
| } | |||
| public void setCount(Long count) { | |||
| @@ -579,7 +584,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public List<Item> getPicList() { | |||
| return picList; | |||
| return this.picList; | |||
| } | |||
| @XStreamAlias("item") | |||
| @@ -590,11 +595,11 @@ public class WxCpXmlMessage implements Serializable { | |||
| private String PicMd5Sum; | |||
| public String getPicMd5Sum() { | |||
| return PicMd5Sum; | |||
| return this.PicMd5Sum; | |||
| } | |||
| public void setPicMd5Sum(String picMd5Sum) { | |||
| PicMd5Sum = picMd5Sum; | |||
| this.PicMd5Sum = picMd5Sum; | |||
| } | |||
| } | |||
| } | |||
| @@ -623,7 +628,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| private String poiname; | |||
| public String getLocationX() { | |||
| return locationX; | |||
| return this.locationX; | |||
| } | |||
| public void setLocationX(String locationX) { | |||
| @@ -631,7 +636,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getLocationY() { | |||
| return locationY; | |||
| return this.locationY; | |||
| } | |||
| public void setLocationY(String locationY) { | |||
| @@ -639,7 +644,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getScale() { | |||
| return scale; | |||
| return this.scale; | |||
| } | |||
| public void setScale(String scale) { | |||
| @@ -647,7 +652,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getLabel() { | |||
| return label; | |||
| return this.label; | |||
| } | |||
| public void setLabel(String label) { | |||
| @@ -655,7 +660,7 @@ public class WxCpXmlMessage implements Serializable { | |||
| } | |||
| public String getPoiname() { | |||
| return poiname; | |||
| return this.poiname; | |||
| } | |||
| public void setPoiname(String poiname) { | |||
| @@ -17,7 +17,7 @@ public class WxCpXmlOutImageMessage extends WxCpXmlOutMessage { | |||
| } | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| return this.mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| @@ -62,7 +62,7 @@ public abstract class WxCpXmlOutMessage { | |||
| } | |||
| public String getToUserName() { | |||
| return toUserName; | |||
| return this.toUserName; | |||
| } | |||
| public void setToUserName(String toUserName) { | |||
| @@ -70,7 +70,7 @@ public abstract class WxCpXmlOutMessage { | |||
| } | |||
| public String getFromUserName() { | |||
| return fromUserName; | |||
| return this.fromUserName; | |||
| } | |||
| public void setFromUserName(String fromUserName) { | |||
| @@ -78,7 +78,7 @@ public abstract class WxCpXmlOutMessage { | |||
| } | |||
| public Long getCreateTime() { | |||
| return createTime; | |||
| return this.createTime; | |||
| } | |||
| public void setCreateTime(Long createTime) { | |||
| @@ -86,7 +86,7 @@ public abstract class WxCpXmlOutMessage { | |||
| } | |||
| public String getMsgType() { | |||
| return msgType; | |||
| return this.msgType; | |||
| } | |||
| public void setMsgType(String msgType) { | |||
| @@ -12,7 +12,7 @@ import java.util.List; | |||
| public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | |||
| @XStreamAlias("Articles") | |||
| protected final List<Item> articles = new ArrayList<Item>(); | |||
| protected final List<Item> articles = new ArrayList<>(); | |||
| @XStreamAlias("ArticleCount") | |||
| protected int articleCount; | |||
| @@ -21,7 +21,7 @@ public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | |||
| } | |||
| public int getArticleCount() { | |||
| return articleCount; | |||
| return this.articleCount; | |||
| } | |||
| public void addArticle(Item item) { | |||
| @@ -30,7 +30,7 @@ public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | |||
| } | |||
| public List<Item> getArticles() { | |||
| return articles; | |||
| return this.articles; | |||
| } | |||
| @@ -54,35 +54,35 @@ public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | |||
| private String Url; | |||
| public String getTitle() { | |||
| return Title; | |||
| return this.Title; | |||
| } | |||
| public void setTitle(String title) { | |||
| Title = title; | |||
| this.Title = title; | |||
| } | |||
| public String getDescription() { | |||
| return Description; | |||
| return this.Description; | |||
| } | |||
| public void setDescription(String description) { | |||
| Description = description; | |||
| this.Description = description; | |||
| } | |||
| public String getPicUrl() { | |||
| return PicUrl; | |||
| return this.PicUrl; | |||
| } | |||
| public void setPicUrl(String picUrl) { | |||
| PicUrl = picUrl; | |||
| this.PicUrl = picUrl; | |||
| } | |||
| public String getUrl() { | |||
| return Url; | |||
| return this.Url; | |||
| } | |||
| public void setUrl(String url) { | |||
| Url = url; | |||
| this.Url = url; | |||
| } | |||
| } | |||
| @@ -17,7 +17,7 @@ public class WxCpXmlOutTextMessage extends WxCpXmlOutMessage { | |||
| } | |||
| public String getContent() { | |||
| return content; | |||
| return this.content; | |||
| } | |||
| public void setContent(String content) { | |||
| @@ -16,27 +16,27 @@ public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { | |||
| } | |||
| public String getMediaId() { | |||
| return video.getMediaId(); | |||
| return this.video.getMediaId(); | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| video.setMediaId(mediaId); | |||
| this.video.setMediaId(mediaId); | |||
| } | |||
| public String getTitle() { | |||
| return video.getTitle(); | |||
| return this.video.getTitle(); | |||
| } | |||
| public void setTitle(String title) { | |||
| video.setTitle(title); | |||
| this.video.setTitle(title); | |||
| } | |||
| public String getDescription() { | |||
| return video.getDescription(); | |||
| return this.video.getDescription(); | |||
| } | |||
| public void setDescription(String description) { | |||
| video.setDescription(description); | |||
| this.video.setDescription(description); | |||
| } | |||
| @@ -56,7 +56,7 @@ public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { | |||
| private String description; | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| return this.mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| @@ -64,7 +64,7 @@ public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { | |||
| } | |||
| public String getTitle() { | |||
| return title; | |||
| return this.title; | |||
| } | |||
| public void setTitle(String title) { | |||
| @@ -72,7 +72,7 @@ public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { | |||
| } | |||
| public String getDescription() { | |||
| return description; | |||
| return this.description; | |||
| } | |||
| public void setDescription(String description) { | |||
| @@ -17,7 +17,7 @@ public class WxCpXmlOutVoiceMessage extends WxCpXmlOutMessage { | |||
| } | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| return this.mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| @@ -23,6 +23,7 @@ public final class FileBuilder extends BaseBuilder<FileBuilder> { | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpMessage build() { | |||
| WxCpMessage m = super.build(); | |||
| m.setMediaId(this.mediaId); | |||
| @@ -23,6 +23,7 @@ public final class ImageBuilder extends BaseBuilder<ImageBuilder> { | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpMessage build() { | |||
| WxCpMessage m = super.build(); | |||
| m.setMediaId(this.mediaId); | |||
| @@ -17,7 +17,7 @@ import java.util.List; | |||
| */ | |||
| public final class NewsBuilder extends BaseBuilder<NewsBuilder> { | |||
| private List<WxCpMessage.WxArticle> articles = new ArrayList<WxCpMessage.WxArticle>(); | |||
| private List<WxCpMessage.WxArticle> articles = new ArrayList<>(); | |||
| public NewsBuilder() { | |||
| this.msgType = WxConsts.CUSTOM_MSG_NEWS; | |||
| @@ -28,6 +28,7 @@ public final class NewsBuilder extends BaseBuilder<NewsBuilder> { | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpMessage build() { | |||
| WxCpMessage m = super.build(); | |||
| m.setArticles(this.articles); | |||
| @@ -23,6 +23,7 @@ public final class TextBuilder extends BaseBuilder<TextBuilder> { | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpMessage build() { | |||
| WxCpMessage m = super.build(); | |||
| m.setContent(this.content); | |||
| @@ -47,12 +47,13 @@ public final class VideoBuilder extends BaseBuilder<VideoBuilder> { | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpMessage build() { | |||
| WxCpMessage m = super.build(); | |||
| m.setMediaId(this.mediaId); | |||
| m.setTitle(title); | |||
| m.setDescription(description); | |||
| m.setThumbMediaId(thumbMediaId); | |||
| m.setTitle(this.title); | |||
| m.setDescription(this.description); | |||
| m.setThumbMediaId(this.thumbMediaId); | |||
| return m; | |||
| } | |||
| } | |||
| @@ -23,6 +23,7 @@ public final class VoiceBuilder extends BaseBuilder<VoiceBuilder> { | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpMessage build() { | |||
| WxCpMessage m = super.build(); | |||
| m.setMediaId(this.mediaId); | |||
| @@ -16,6 +16,7 @@ public final class ImageBuilder extends BaseBuilder<ImageBuilder, WxCpXmlOutImag | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpXmlOutImageMessage build() { | |||
| WxCpXmlOutImageMessage m = new WxCpXmlOutImageMessage(); | |||
| setCommon(m); | |||
| @@ -13,16 +13,17 @@ import java.util.List; | |||
| */ | |||
| public final class NewsBuilder extends BaseBuilder<NewsBuilder, WxCpXmlOutNewsMessage> { | |||
| protected final List<Item> articles = new ArrayList<Item>(); | |||
| protected final List<Item> articles = new ArrayList<>(); | |||
| public NewsBuilder addArticle(Item item) { | |||
| this.articles.add(item); | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpXmlOutNewsMessage build() { | |||
| WxCpXmlOutNewsMessage m = new WxCpXmlOutNewsMessage(); | |||
| for (Item item : articles) { | |||
| for (Item item : this.articles) { | |||
| m.addArticle(item); | |||
| } | |||
| setCommon(m); | |||
| @@ -15,6 +15,7 @@ public final class TextBuilder extends BaseBuilder<TextBuilder, WxCpXmlOutTextMe | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpXmlOutTextMessage build() { | |||
| WxCpXmlOutTextMessage m = new WxCpXmlOutTextMessage(); | |||
| setCommon(m); | |||
| @@ -28,12 +28,13 @@ public final class VideoBuilder extends BaseBuilder<VideoBuilder, WxCpXmlOutVide | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpXmlOutVideoMessage build() { | |||
| WxCpXmlOutVideoMessage m = new WxCpXmlOutVideoMessage(); | |||
| setCommon(m); | |||
| m.setTitle(title); | |||
| m.setDescription(description); | |||
| m.setMediaId(mediaId); | |||
| m.setTitle(this.title); | |||
| m.setDescription(this.description); | |||
| m.setMediaId(this.mediaId); | |||
| return m; | |||
| } | |||
| @@ -16,10 +16,11 @@ public final class VoiceBuilder extends BaseBuilder<VoiceBuilder, WxCpXmlOutVoic | |||
| return this; | |||
| } | |||
| @Override | |||
| public WxCpXmlOutVoiceMessage build() { | |||
| WxCpXmlOutVoiceMessage m = new WxCpXmlOutVoiceMessage(); | |||
| setCommon(m); | |||
| m.setMediaId(mediaId); | |||
| m.setMediaId(this.mediaId); | |||
| return m; | |||
| } | |||
| @@ -19,6 +19,7 @@ import java.lang.reflect.Type; | |||
| */ | |||
| public class WxCpDepartGsonAdapter implements JsonSerializer<WxCpDepart>, JsonDeserializer<WxCpDepart> { | |||
| @Override | |||
| public JsonElement serialize(WxCpDepart group, Type typeOfSrc, JsonSerializationContext context) { | |||
| JsonObject json = new JsonObject(); | |||
| if (group.getId() != null) { | |||
| @@ -36,6 +37,7 @@ public class WxCpDepartGsonAdapter implements JsonSerializer<WxCpDepart>, JsonDe | |||
| return json; | |||
| } | |||
| @Override | |||
| public WxCpDepart deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) | |||
| throws JsonParseException { | |||
| WxCpDepart depart = new WxCpDepart(); | |||
| @@ -20,6 +20,7 @@ import java.lang.reflect.Type; | |||
| */ | |||
| public class WxCpMessageGsonAdapter implements JsonSerializer<WxCpMessage> { | |||
| @Override | |||
| public JsonElement serialize(WxCpMessage message, Type typeOfSrc, JsonSerializationContext context) { | |||
| JsonObject messageJson = new JsonObject(); | |||
| messageJson.addProperty("agentid", message.getAgentId()); | |||
| @@ -19,6 +19,7 @@ import java.lang.reflect.Type; | |||
| */ | |||
| public class WxCpTagGsonAdapter implements JsonSerializer<WxCpTag>, JsonDeserializer<WxCpTag> { | |||
| @Override | |||
| public JsonElement serialize(WxCpTag tag, Type typeOfSrc, JsonSerializationContext context) { | |||
| JsonObject o = new JsonObject(); | |||
| o.addProperty("tagid", tag.getId()); | |||
| @@ -26,6 +27,7 @@ public class WxCpTagGsonAdapter implements JsonSerializer<WxCpTag>, JsonDeserial | |||
| return o; | |||
| } | |||
| @Override | |||
| public WxCpTag deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) | |||
| throws JsonParseException { | |||
| JsonObject jsonObject = json.getAsJsonObject(); | |||
| @@ -19,6 +19,7 @@ import java.lang.reflect.Type; | |||
| */ | |||
| public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSerializer<WxCpUser> { | |||
| @Override | |||
| public WxCpUser deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) | |||
| throws JsonParseException { | |||
| JsonObject o = json.getAsJsonObject(); | |||
| @@ -45,7 +45,7 @@ public class XStreamTransformer { | |||
| } | |||
| private static Map<Class, XStream> configXStreamInstance() { | |||
| Map<Class, XStream> map = new HashMap<Class, XStream>(); | |||
| Map<Class, XStream> map = new HashMap<>(); | |||
| map.put(WxCpXmlMessage.class, config_WxCpXmlMessage()); | |||
| map.put(WxCpXmlOutNewsMessage.class, config_WxCpXmlOutNewsMessage()); | |||
| map.put(WxCpXmlOutTextMessage.class, config_WxCpXmlOutTextMessage()); | |||
| @@ -1,12 +1,14 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| 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 java.io.InputStream; | |||
| import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||
| public class ApiTestModule implements Module { | |||
| @@ -19,13 +21,18 @@ public class ApiTestModule implements Module { | |||
| @Override | |||
| public void configure(Binder binder) { | |||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||
| WxXmlCpInMemoryConfigStorage config = fromXml(WxXmlCpInMemoryConfigStorage.class, is1); | |||
| WxCpServiceImpl wxService = new WxCpServiceImpl(); | |||
| wxService.setWxCpConfigStorage(config); | |||
| binder.bind(WxCpServiceImpl.class).toInstance(wxService); | |||
| binder.bind(WxCpConfigStorage.class).toInstance(config); | |||
| try (InputStream is1 = ClassLoader | |||
| .getSystemResourceAsStream("test-config.xml")) { | |||
| WxXmlCpInMemoryConfigStorage config = fromXml( | |||
| WxXmlCpInMemoryConfigStorage.class, is1); | |||
| WxCpServiceImpl wxService = new WxCpServiceImpl(); | |||
| wxService.setWxCpConfigStorage(config); | |||
| binder.bind(WxCpServiceImpl.class).toInstance(wxService); | |||
| binder.bind(WxCpConfigStorage.class).toInstance(config); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| @XStreamAlias("xml") | |||
| @@ -38,7 +45,7 @@ public class ApiTestModule implements Module { | |||
| protected String tagId; | |||
| public String getUserId() { | |||
| return userId; | |||
| return this.userId; | |||
| } | |||
| public void setUserId(String userId) { | |||
| @@ -46,7 +53,7 @@ public class ApiTestModule implements Module { | |||
| } | |||
| public String getDepartmentId() { | |||
| return departmentId; | |||
| return this.departmentId; | |||
| } | |||
| public void setDepartmentId(String departmentId) { | |||
| @@ -54,7 +61,7 @@ public class ApiTestModule implements Module { | |||
| } | |||
| public String getTagId() { | |||
| return tagId; | |||
| return this.tagId; | |||
| } | |||
| public void setTagId(String tagId) { | |||
| @@ -64,9 +71,9 @@ public class ApiTestModule implements Module { | |||
| @Override | |||
| public String toString() { | |||
| return super.toString() + " > WxXmlCpConfigStorage{" + | |||
| "userId='" + userId + '\'' + | |||
| ", departmentId='" + departmentId + '\'' + | |||
| ", tagId='" + tagId + '\'' + | |||
| "userId='" + this.userId + '\'' + | |||
| ", departmentId='" + this.departmentId + '\'' + | |||
| ", tagId='" + this.tagId + '\'' + | |||
| '}'; | |||
| } | |||
| } | |||
| @@ -1,12 +1,14 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| /** | |||
| * 基础API测试 | |||
| * | |||
| @@ -20,9 +22,9 @@ public class WxCpBaseAPITest { | |||
| protected WxCpServiceImpl wxService; | |||
| public void testRefreshAccessToken() throws WxErrorException { | |||
| WxCpConfigStorage configStorage = wxService.wxCpConfigStorage; | |||
| WxCpConfigStorage configStorage = this.wxService.configStorage; | |||
| String before = configStorage.getAccessToken(); | |||
| wxService.getAccessToken(false); | |||
| this.wxService.getAccessToken(false); | |||
| String after = configStorage.getAccessToken(); | |||
| @@ -1,16 +1,17 @@ | |||
| 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.util.http.RequestExecutor; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Test; | |||
| import java.util.concurrent.ExecutionException; | |||
| import java.util.concurrent.ExecutorService; | |||
| import java.util.concurrent.Executors; | |||
| import java.util.concurrent.Future; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
| @Test | |||
| public class WxCpBusyRetryTest { | |||
| @@ -19,7 +20,9 @@ public class WxCpBusyRetryTest { | |||
| WxCpService service = new WxCpServiceImpl() { | |||
| @Override | |||
| protected <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | |||
| protected synchronized <T, E> T executeInternal( | |||
| RequestExecutor<T, E> executor, String uri, E data) | |||
| throws WxErrorException { | |||
| WxError error = new WxError(); | |||
| error.setErrorCode(-1); | |||
| throw new WxErrorException(error); | |||
| @@ -1,13 +1,15 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
| import java.util.List; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import java.util.List; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
| /** | |||
| * 测试部门接口 | |||
| @@ -24,22 +26,23 @@ public class WxCpDepartAPITest { | |||
| protected WxCpDepart depart; | |||
| public void testDepartCreate() throws WxErrorException { | |||
| WxCpDepart depart = new WxCpDepart(); | |||
| depart.setName("子部门" + System.currentTimeMillis()); | |||
| depart.setParentId(1); | |||
| depart.setOrder(1); | |||
| Integer departId = wxCpService.departCreate(depart); | |||
| WxCpDepart cpDepart = new WxCpDepart(); | |||
| cpDepart.setName("子部门" + System.currentTimeMillis()); | |||
| cpDepart.setParentId(1); | |||
| cpDepart.setOrder(1); | |||
| Integer departId = this.wxCpService.departCreate(cpDepart); | |||
| System.out.println(departId); | |||
| } | |||
| @Test(dependsOnMethods = "testDepartCreate") | |||
| public void testDepartGet() throws WxErrorException { | |||
| System.out.println("=================获取部门"); | |||
| List<WxCpDepart> departList = wxCpService.departGet(); | |||
| List<WxCpDepart> departList = this.wxCpService.departGet(); | |||
| Assert.assertNotNull(departList); | |||
| Assert.assertTrue(departList.size() > 0); | |||
| for (WxCpDepart g : departList) { | |||
| depart = g; | |||
| System.out.println(depart.getId() + ":" + depart.getName()); | |||
| this.depart = g; | |||
| System.out.println(this.depart.getId() + ":" + this.depart.getName()); | |||
| Assert.assertNotNull(g.getName()); | |||
| } | |||
| } | |||
| @@ -47,15 +50,15 @@ public class WxCpDepartAPITest { | |||
| @Test(dependsOnMethods = {"testDepartGet", "testDepartCreate"}) | |||
| public void testDepartUpdate() throws WxErrorException { | |||
| System.out.println("=================更新部门"); | |||
| depart.setName("子部门改名" + System.currentTimeMillis()); | |||
| wxCpService.departUpdate(depart); | |||
| this.depart.setName("子部门改名" + System.currentTimeMillis()); | |||
| this.wxCpService.departUpdate(this.depart); | |||
| } | |||
| @Test(dependsOnMethods = "testDepartUpdate") | |||
| public void testDepartDelete() throws WxErrorException { | |||
| System.out.println("=================删除部门"); | |||
| System.out.println(depart.getId() + ":" + depart.getName()); | |||
| wxCpService.departDelete(depart.getId()); | |||
| System.out.println(this.depart.getId() + ":" + this.depart.getName()); | |||
| this.wxCpService.departDelete(this.depart.getId()); | |||
| } | |||
| } | |||
| @@ -1,18 +1,20 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| 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 java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| 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; | |||
| /** | |||
| * 测试多媒体文件上传下载 | |||
| @@ -27,21 +29,25 @@ public class WxCpMediaAPITest { | |||
| @Inject | |||
| protected WxCpServiceImpl wxService; | |||
| private List<String> media_ids = new ArrayList<String>(); | |||
| private List<String> media_ids = new ArrayList<>(); | |||
| @Test(dataProvider = "uploadMedia") | |||
| public void testUploadMedia(String mediaType, String fileType, String fileName) throws WxErrorException, IOException { | |||
| InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName); | |||
| WxMediaUploadResult res = wxService.mediaUpload(mediaType, fileType, inputStream); | |||
| Assert.assertNotNull(res.getType()); | |||
| Assert.assertNotNull(res.getCreatedAt()); | |||
| Assert.assertTrue(res.getMediaId() != null || res.getThumbMediaId() != null); | |||
| try (InputStream inputStream = ClassLoader | |||
| .getSystemResourceAsStream(fileName);) { | |||
| WxMediaUploadResult res = this.wxService.mediaUpload(mediaType, fileType, | |||
| inputStream); | |||
| Assert.assertNotNull(res.getType()); | |||
| Assert.assertNotNull(res.getCreatedAt()); | |||
| Assert.assertTrue( | |||
| res.getMediaId() != null || res.getThumbMediaId() != null); | |||
| if (res.getMediaId() != null) { | |||
| media_ids.add(res.getMediaId()); | |||
| } | |||
| if (res.getThumbMediaId() != null) { | |||
| media_ids.add(res.getThumbMediaId()); | |||
| if (res.getMediaId() != null) { | |||
| this.media_ids.add(res.getMediaId()); | |||
| } | |||
| if (res.getThumbMediaId() != null) { | |||
| this.media_ids.add(res.getThumbMediaId()); | |||
| } | |||
| } | |||
| } | |||
| @@ -57,7 +63,7 @@ public class WxCpMediaAPITest { | |||
| @Test(dependsOnMethods = {"testUploadMedia"}, dataProvider = "downloadMedia") | |||
| public void testDownloadMedia(String media_id) throws WxErrorException { | |||
| wxService.mediaDownload(media_id); | |||
| this.wxService.mediaDownload(media_id); | |||
| } | |||
| @DataProvider | |||
| @@ -1,11 +1,13 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.cp.bean.WxCpMessage; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| /*** | |||
| * 测试发送消息 | |||
| @@ -20,21 +22,21 @@ public class WxCpMessageAPITest { | |||
| protected WxCpServiceImpl wxService; | |||
| public void testSendCustomMessage() throws WxErrorException { | |||
| ApiTestModule.WxXmlCpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlCpInMemoryConfigStorage) wxService.wxCpConfigStorage; | |||
| ApiTestModule.WxXmlCpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlCpInMemoryConfigStorage) this.wxService.configStorage; | |||
| WxCpMessage message1 = new WxCpMessage(); | |||
| message1.setAgentId(configStorage.getAgentId()); | |||
| message1.setMsgType(WxConsts.CUSTOM_MSG_TEXT); | |||
| message1.setToUser(configStorage.getUserId()); | |||
| message1.setContent("欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>"); | |||
| wxService.messageSend(message1); | |||
| this.wxService.messageSend(message1); | |||
| WxCpMessage message2 = WxCpMessage | |||
| .TEXT() | |||
| .agentId(configStorage.getAgentId()) | |||
| .toUser(configStorage.getUserId()) | |||
| .content("欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>") | |||
| .content("欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>") | |||
| .build(); | |||
| wxService.messageSend(message2); | |||
| this.wxService.messageSend(message2); | |||
| } | |||
| @@ -286,7 +286,7 @@ public class WxCpMessageRouterTest { | |||
| @Override | |||
| public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService wxCpService, | |||
| WxSessionManager sessionManager) { | |||
| sb.append(this.echoStr).append(','); | |||
| this.sb.append(this.echoStr).append(','); | |||
| return null; | |||
| } | |||
| @@ -23,44 +23,44 @@ public class WxCpTagAPITest { | |||
| protected String tagId; | |||
| public void testTagCreate() throws Exception { | |||
| tagId = wxService.tagCreate("测试标签4"); | |||
| System.out.println(tagId); | |||
| this.tagId = this.wxService.tagCreate("测试标签4"); | |||
| System.out.println(this.tagId); | |||
| } | |||
| @Test(dependsOnMethods = "testTagCreate") | |||
| public void testTagUpdate() throws Exception { | |||
| wxService.tagUpdate(tagId, "测试标签-改名"); | |||
| this.wxService.tagUpdate(this.tagId, "测试标签-改名"); | |||
| } | |||
| @Test(dependsOnMethods = "testTagUpdate") | |||
| public void testTagGet() throws Exception { | |||
| List<WxCpTag> tags = wxService.tagGet(); | |||
| List<WxCpTag> tags = this.wxService.tagGet(); | |||
| Assert.assertNotEquals(tags.size(), 0); | |||
| } | |||
| @Test(dependsOnMethods = "testTagGet") | |||
| public void testTagAddUsers() throws Exception { | |||
| List<String> userIds = new ArrayList<String>(); | |||
| userIds.add(((ApiTestModule.WxXmlCpInMemoryConfigStorage) configStorage).getUserId()); | |||
| wxService.tagAddUsers(tagId, userIds, null); | |||
| List<String> userIds = new ArrayList<>(); | |||
| userIds.add(((ApiTestModule.WxXmlCpInMemoryConfigStorage) this.configStorage).getUserId()); | |||
| this.wxService.tagAddUsers(this.tagId, userIds, null); | |||
| } | |||
| @Test(dependsOnMethods = "testTagAddUsers") | |||
| public void testTagGetUsers() throws Exception { | |||
| List<WxCpUser> users = wxService.tagGetUsers(tagId); | |||
| List<WxCpUser> users = this.wxService.tagGetUsers(this.tagId); | |||
| Assert.assertNotEquals(users.size(), 0); | |||
| } | |||
| @Test(dependsOnMethods = "testTagGetUsers") | |||
| public void testTagRemoveUsers() throws Exception { | |||
| List<String> userIds = new ArrayList<String>(); | |||
| userIds.add(((ApiTestModule.WxXmlCpInMemoryConfigStorage) configStorage).getUserId()); | |||
| wxService.tagRemoveUsers(tagId, userIds); | |||
| List<String> userIds = new ArrayList<>(); | |||
| userIds.add(((ApiTestModule.WxXmlCpInMemoryConfigStorage) this.configStorage).getUserId()); | |||
| this.wxService.tagRemoveUsers(this.tagId, userIds); | |||
| } | |||
| @Test(dependsOnMethods = "testTagRemoveUsers") | |||
| public void testTagDelete() throws Exception { | |||
| wxService.tagDelete(tagId); | |||
| this.wxService.tagDelete(this.tagId); | |||
| } | |||
| } | |||
| @@ -35,7 +35,7 @@ public class WxCpUserAPITest { | |||
| user.setPosition("woman"); | |||
| user.setTel("3300393"); | |||
| user.addExtAttr("爱好", "table"); | |||
| wxCpService.userCreate(user); | |||
| this.wxCpService.userCreate(user); | |||
| } | |||
| @Test(dependsOnMethods = "testUserCreate") | |||
| @@ -44,23 +44,23 @@ public class WxCpUserAPITest { | |||
| user.setUserId("some.woman"); | |||
| user.setName("Some Woman"); | |||
| user.addExtAttr("爱好", "table2"); | |||
| wxCpService.userUpdate(user); | |||
| this.wxCpService.userUpdate(user); | |||
| } | |||
| @Test(dependsOnMethods = "testUserUpdate") | |||
| public void testUserGet() throws WxErrorException { | |||
| WxCpUser user = wxCpService.userGet("some.woman"); | |||
| WxCpUser user = this.wxCpService.userGet("some.woman"); | |||
| Assert.assertNotNull(user); | |||
| } | |||
| @Test(dependsOnMethods = "testUserGet") | |||
| public void testDepartGetUsers() throws WxErrorException { | |||
| List<WxCpUser> users = wxCpService.departGetUsers(1, true, 0); | |||
| List<WxCpUser> users = this.wxCpService.departGetUsers(1, true, 0); | |||
| Assert.assertNotEquals(users.size(), 0); | |||
| } | |||
| @Test(dependsOnMethods = "testDepartGetUsers") | |||
| public void testUserDelete() throws WxErrorException { | |||
| wxCpService.userDelete("some.woman"); | |||
| this.wxCpService.userDelete("some.woman"); | |||
| } | |||
| } | |||
| @@ -24,17 +24,17 @@ public class WxMenuAPITest { | |||
| @Test(dataProvider = "menu") | |||
| public void testCreateMenu(WxMenu wxMenu) throws WxErrorException { | |||
| wxService.menuCreate(wxMenu); | |||
| this.wxService.menuCreate(wxMenu); | |||
| } | |||
| @Test(dependsOnMethods = {"testCreateMenu"}) | |||
| public void testGetMenu() throws WxErrorException { | |||
| Assert.assertNotNull(wxService.menuGet()); | |||
| Assert.assertNotNull(this.wxService.menuGet()); | |||
| } | |||
| @Test(dependsOnMethods = {"testGetMenu"}) | |||
| public void testDeleteMenu() throws WxErrorException { | |||
| wxService.menuDelete(); | |||
| this.wxService.menuDelete(); | |||
| } | |||
| @DataProvider(name = "menu") | |||
| @@ -21,8 +21,8 @@ class WxCpDemoInMemoryConfigStorage extends WxCpInMemoryConfigStorage { | |||
| @Override | |||
| public String toString() { | |||
| return "SimpleWxConfigProvider [appidOrCorpid=" + corpId + ", corpSecret=" + corpSecret + ", accessToken=" + accessToken | |||
| + ", expiresTime=" + expiresTime + ", token=" + token + ", aesKey=" + aesKey + "]"; | |||
| return "SimpleWxConfigProvider [appidOrCorpid=" + this.corpId + ", corpSecret=" + this.corpSecret + ", accessToken=" + this.accessToken | |||
| + ", expiresTime=" + this.expiresTime + ", token=" + this.token + ", aesKey=" + this.aesKey + "]"; | |||
| } | |||
| } | |||
| @@ -1,16 +1,22 @@ | |||
| package me.chanjar.weixin.cp.demo; | |||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||
| import me.chanjar.weixin.cp.api.*; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage; | |||
| 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 java.io.InputStream; | |||
| import java.util.Map; | |||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | |||
| import me.chanjar.weixin.cp.api.WxCpMessageHandler; | |||
| import me.chanjar.weixin.cp.api.WxCpMessageRouter; | |||
| import me.chanjar.weixin.cp.api.WxCpService; | |||
| import me.chanjar.weixin.cp.api.WxCpServiceImpl; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage; | |||
| public class WxCpDemoServer { | |||
| @@ -36,55 +42,48 @@ public class WxCpDemoServer { | |||
| server.join(); | |||
| } | |||
| private static void initWeixin() { | |||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||
| WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(is1); | |||
| wxCpConfigStorage = config; | |||
| wxCpService = new WxCpServiceImpl(); | |||
| wxCpService.setWxCpConfigStorage(config); | |||
| WxCpMessageHandler handler = new WxCpMessageHandler() { | |||
| @Override | |||
| public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, | |||
| WxCpService wxCpService, WxSessionManager sessionManager) { | |||
| WxCpXmlOutTextMessage m = WxCpXmlOutMessage | |||
| .TEXT() | |||
| .content("测试加密消息") | |||
| .fromUser(wxMessage.getToUserName()) | |||
| .toUser(wxMessage.getFromUserName()) | |||
| .build(); | |||
| return m; | |||
| } | |||
| }; | |||
| WxCpMessageHandler oauth2handler = new WxCpMessageHandler() { | |||
| @Override | |||
| public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, | |||
| WxCpService wxCpService, WxSessionManager sessionManager) { | |||
| String href = "<a href=\"" + wxCpService.oauth2buildAuthorizationUrl(wxCpConfigStorage.getOauth2redirectUri(), null) | |||
| + "\">测试oauth2</a>"; | |||
| return WxCpXmlOutMessage | |||
| .TEXT() | |||
| .content(href) | |||
| .fromUser(wxMessage.getToUserName()) | |||
| .toUser(wxMessage.getFromUserName()).build(); | |||
| } | |||
| }; | |||
| wxCpMessageRouter = new WxCpMessageRouter(wxCpService); | |||
| wxCpMessageRouter | |||
| .rule() | |||
| .async(false) | |||
| .content("哈哈") // 拦截内容为“哈哈”的消息 | |||
| .handler(handler) | |||
| .end() | |||
| .rule() | |||
| .async(false) | |||
| .content("oauth") | |||
| .handler(oauth2handler) | |||
| .end() | |||
| ; | |||
| private static void initWeixin() throws IOException { | |||
| try (InputStream is1 = ClassLoader | |||
| .getSystemResourceAsStream("test-config.xml")) { | |||
| WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage | |||
| .fromXml(is1); | |||
| wxCpConfigStorage = config; | |||
| wxCpService = new WxCpServiceImpl(); | |||
| wxCpService.setWxCpConfigStorage(config); | |||
| WxCpMessageHandler handler = new WxCpMessageHandler() { | |||
| @Override | |||
| public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, | |||
| Map<String, Object> context, WxCpService wxService, | |||
| WxSessionManager sessionManager) { | |||
| WxCpXmlOutTextMessage m = WxCpXmlOutMessage.TEXT().content("测试加密消息") | |||
| .fromUser(wxMessage.getToUserName()) | |||
| .toUser(wxMessage.getFromUserName()).build(); | |||
| return m; | |||
| } | |||
| }; | |||
| WxCpMessageHandler oauth2handler = new WxCpMessageHandler() { | |||
| @Override | |||
| public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, | |||
| Map<String, Object> context, WxCpService wxService, | |||
| WxSessionManager sessionManager) { | |||
| String href = "<a href=\"" | |||
| + wxService.oauth2buildAuthorizationUrl( | |||
| wxCpConfigStorage.getOauth2redirectUri(), null) | |||
| + "\">测试oauth2</a>"; | |||
| return WxCpXmlOutMessage.TEXT().content(href) | |||
| .fromUser(wxMessage.getToUserName()) | |||
| .toUser(wxMessage.getFromUserName()).build(); | |||
| } | |||
| }; | |||
| wxCpMessageRouter = new WxCpMessageRouter(wxCpService); | |||
| wxCpMessageRouter.rule().async(false).content("哈哈") // 拦截内容为“哈哈”的消息 | |||
| .handler(handler).end().rule().async(false).content("oauth") | |||
| .handler(oauth2handler).end(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,5 +1,11 @@ | |||
| package me.chanjar.weixin.cp.demo; | |||
| import java.io.IOException; | |||
| import javax.servlet.http.HttpServlet; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | |||
| import me.chanjar.weixin.cp.api.WxCpMessageRouter; | |||
| @@ -8,17 +14,11 @@ import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||
| import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; | |||
| import javax.servlet.ServletException; | |||
| import javax.servlet.http.HttpServlet; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.IOException; | |||
| /** | |||
| * @author Daniel Qian | |||
| */ | |||
| public class WxCpEndpointServlet extends HttpServlet { | |||
| private static final long serialVersionUID = 1L; | |||
| protected WxCpConfigStorage wxCpConfigStorage; | |||
| protected WxCpService wxCpService; | |||
| protected WxCpMessageRouter wxCpMessageRouter; | |||
| @@ -32,7 +32,7 @@ public class WxCpEndpointServlet extends HttpServlet { | |||
| @Override | |||
| protected void service(HttpServletRequest request, HttpServletResponse response) | |||
| throws ServletException, IOException { | |||
| throws IOException { | |||
| response.setContentType("text/html;charset=utf-8"); | |||
| response.setStatus(HttpServletResponse.SC_OK); | |||
| @@ -43,12 +43,12 @@ public class WxCpEndpointServlet extends HttpServlet { | |||
| String echostr = request.getParameter("echostr"); | |||
| if (StringUtils.isNotBlank(echostr)) { | |||
| if (!wxCpService.checkSignature(msgSignature, timestamp, nonce, echostr)) { | |||
| if (!this.wxCpService.checkSignature(msgSignature, timestamp, nonce, echostr)) { | |||
| // 消息签名不正确,说明不是公众平台发过来的消息 | |||
| response.getWriter().println("非法请求"); | |||
| return; | |||
| } | |||
| WxCpCryptUtil cryptUtil = new WxCpCryptUtil(wxCpConfigStorage); | |||
| WxCpCryptUtil cryptUtil = new WxCpCryptUtil(this.wxCpConfigStorage); | |||
| String plainText = cryptUtil.decrypt(echostr); | |||
| // 说明是一个仅仅用来验证的请求,回显echostr | |||
| response.getWriter().println(plainText); | |||
| @@ -56,10 +56,10 @@ public class WxCpEndpointServlet extends HttpServlet { | |||
| } | |||
| WxCpXmlMessage inMessage = WxCpXmlMessage | |||
| .fromEncryptedXml(request.getInputStream(), wxCpConfigStorage, timestamp, nonce, msgSignature); | |||
| WxCpXmlOutMessage outMessage = wxCpMessageRouter.route(inMessage); | |||
| .fromEncryptedXml(request.getInputStream(), this.wxCpConfigStorage, timestamp, nonce, msgSignature); | |||
| WxCpXmlOutMessage outMessage = this.wxCpMessageRouter.route(inMessage); | |||
| if (outMessage != null) { | |||
| response.getWriter().write(outMessage.toEncryptedXml(wxCpConfigStorage)); | |||
| response.getWriter().write(outMessage.toEncryptedXml(this.wxCpConfigStorage)); | |||
| } | |||
| return; | |||
| @@ -1,16 +1,17 @@ | |||
| package me.chanjar.weixin.cp.demo; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.cp.api.WxCpService; | |||
| import java.io.IOException; | |||
| import java.util.Arrays; | |||
| import javax.servlet.ServletException; | |||
| import javax.servlet.http.HttpServlet; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.IOException; | |||
| import java.util.Arrays; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.cp.api.WxCpService; | |||
| public class WxCpOAuth2Servlet extends HttpServlet { | |||
| private static final long serialVersionUID = 1L; | |||
| protected WxCpService wxCpService; | |||
| @@ -20,7 +21,7 @@ public class WxCpOAuth2Servlet extends HttpServlet { | |||
| @Override | |||
| protected void service(HttpServletRequest request, HttpServletResponse response) | |||
| throws ServletException, IOException { | |||
| throws IOException { | |||
| response.setContentType("text/html;charset=utf-8"); | |||
| response.setStatus(HttpServletResponse.SC_OK); | |||
| @@ -30,7 +31,7 @@ public class WxCpOAuth2Servlet extends HttpServlet { | |||
| response.getWriter().println("<h1>code</h1>"); | |||
| response.getWriter().println(code); | |||
| String[] res = wxCpService.oauth2getUserInfo(code); | |||
| String[] res = this.wxCpService.oauth2getUserInfo(code); | |||
| response.getWriter().println("<h1>result</h1>"); | |||
| response.getWriter().println(Arrays.toString(res)); | |||
| } catch (WxErrorException e) { | |||
| @@ -1,12 +1,12 @@ | |||
| <?xml version="1.0"?> | |||
| <project | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>com.github.binarywang</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>2.1.0</version> | |||
| <version>2.2.0</version> | |||
| </parent> | |||
| <artifactId>weixin-java-mp</artifactId> | |||
| <name>WeiXin Java Tools - MP</name> | |||
| @@ -47,7 +47,7 @@ | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-servlet</artifactId> | |||
| <scope>test</scope> | |||
| </dependency><!-- https://mvnrepository.com/artifact/joda-time/joda-time --> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>joda-time</groupId> | |||
| <artifactId>joda-time</artifactId> | |||
| @@ -6,8 +6,7 @@ import me.chanjar.weixin.mp.bean.result.WxMpCardResult; | |||
| /** | |||
| * 卡券相关接口 | |||
| * Created by Binary Wang on 2016/7/27. | |||
| * @author binarywang(https://github.com/binarywang) | |||
| * @author YuJian(mgcnrx11@hotmail.com) on 01/11/2016 | |||
| */ | |||
| public interface WxMpCardService { | |||
| @@ -1,69 +0,0 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.WxMpGroup; | |||
| import java.util.List; | |||
| /** | |||
| * 用户分组相关操作接口 | |||
| * @author Binary Wang | |||
| * | |||
| */ | |||
| public interface WxMpGroupService { | |||
| /** | |||
| * <pre> | |||
| * 分组管理接口 - 创建分组 | |||
| * 最多支持创建500个分组 | |||
| * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 | |||
| * </pre> | |||
| * | |||
| * @param name 分组名字(30个字符以内) | |||
| */ | |||
| WxMpGroup groupCreate(String name) throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 分组管理接口 - 查询所有分组 | |||
| * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 | |||
| * </pre> | |||
| */ | |||
| List<WxMpGroup> groupGet() throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 分组管理接口 - 查询用户所在分组 | |||
| * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 | |||
| * </pre> | |||
| * | |||
| * @param openid 微信用户的openid | |||
| */ | |||
| long userGetGroup(String openid) throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 分组管理接口 - 修改分组名 | |||
| * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 | |||
| * | |||
| * 如果id为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误 | |||
| * </pre> | |||
| * | |||
| * @param group 要更新的group,group的id,name必须设置 | |||
| */ | |||
| void groupUpdate(WxMpGroup group) throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 分组管理接口 - 移动用户分组 | |||
| * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 | |||
| * | |||
| * 如果to_groupid为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误 | |||
| * </pre> | |||
| * | |||
| * @param openid 用户openid | |||
| * @param to_groupid 移动到的分组id | |||
| */ | |||
| void userUpdateGroup(String openid, long to_groupid) throws WxErrorException; | |||
| } | |||
| @@ -1,12 +1,18 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; | |||
| import me.chanjar.weixin.mp.bean.kefu.result.*; | |||
| import java.io.File; | |||
| import java.util.Date; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.WxMpCustomMessage; | |||
| import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; | |||
| import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; | |||
| import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfMsgList; | |||
| import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; | |||
| import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; | |||
| import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; | |||
| import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; | |||
| /** | |||
| * 客服接口 , | |||
| * 命名采用kefu拼音的原因是: | |||
| @@ -17,6 +23,14 @@ import java.util.Date; | |||
| */ | |||
| public interface WxMpKefuService { | |||
| /** | |||
| * <pre> | |||
| * 发送客服消息 | |||
| * 详情请见: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547&token=&lang=zh_CN">发送客服消息</a> | |||
| * </pre> | |||
| */ | |||
| boolean customMessageSend(WxMpCustomMessage message) throws WxErrorException; | |||
| //*******************客服管理接口***********************// | |||
| /** | |||
| @@ -10,10 +10,12 @@ import java.io.IOException; | |||
| import java.io.InputStream; | |||
| /** | |||
| * <pre> | |||
| * Created by Binary Wang on 2016/7/21. | |||
| * 素材管理的相关接口,包括媒体管理的接口, | |||
| * 即以https://api.weixin.qq.com/cgi-bin/material | |||
| * 和 https://api.weixin.qq.com/cgi-bin/media开头的接口 | |||
| * </pre> | |||
| */ | |||
| public interface WxMpMaterialService { | |||
| @@ -1,24 +1,25 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.concurrent.ExecutionException; | |||
| import java.util.concurrent.ExecutorService; | |||
| import java.util.concurrent.Executors; | |||
| import java.util.concurrent.Future; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import me.chanjar.weixin.common.api.WxErrorExceptionHandler; | |||
| import me.chanjar.weixin.common.api.WxMessageDuplicateChecker; | |||
| import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker; | |||
| import me.chanjar.weixin.common.session.InternalSession; | |||
| import me.chanjar.weixin.common.session.InternalSessionManager; | |||
| import me.chanjar.weixin.common.session.StandardSessionManager; | |||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||
| import me.chanjar.weixin.common.util.LogExceptionHandler; | |||
| import me.chanjar.weixin.common.api.WxErrorExceptionHandler; | |||
| import me.chanjar.weixin.common.api.WxMessageDuplicateChecker; | |||
| import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.concurrent.ExecutionException; | |||
| import java.util.concurrent.ExecutorService; | |||
| import java.util.concurrent.Executors; | |||
| import java.util.concurrent.Future; | |||
| /** | |||
| * <pre> | |||
| @@ -155,7 +156,7 @@ public class WxMpMessageRouter { | |||
| } | |||
| WxMpXmlOutMessage res = null; | |||
| final List<Future> futures = new ArrayList<>(); | |||
| final List<Future<?>> futures = new ArrayList<>(); | |||
| for (final WxMpMessageRouterRule rule : matchRules) { | |||
| // 返回最后一个非异步的rule的执行结果 | |||
| if(rule.isAsync()) { | |||
| @@ -170,7 +171,7 @@ public class WxMpMessageRouter { | |||
| } else { | |||
| res = rule.service(wxMessage, this.wxMpService, this.sessionManager, this.exceptionHandler); | |||
| // 在同步操作结束,session访问结束 | |||
| this.log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | |||
| this.log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUser()); | |||
| sessionEndAccess(wxMessage); | |||
| } | |||
| } | |||
| @@ -179,10 +180,10 @@ public class WxMpMessageRouter { | |||
| this.executorService.submit(new Runnable() { | |||
| @Override | |||
| public void run() { | |||
| for (Future future : futures) { | |||
| for (Future<?> future : futures) { | |||
| try { | |||
| future.get(); | |||
| WxMpMessageRouter.this.log.debug("End session access: async=true, sessionId={}", wxMessage.getFromUserName()); | |||
| WxMpMessageRouter.this.log.debug("End session access: async=true, sessionId={}", wxMessage.getFromUser()); | |||
| // 异步操作结束,session访问结束 | |||
| sessionEndAccess(wxMessage); | |||
| } catch (InterruptedException e) { | |||
| @@ -202,7 +203,7 @@ public class WxMpMessageRouter { | |||
| StringBuffer messageId = new StringBuffer(); | |||
| if (wxMessage.getMsgId() == null) { | |||
| messageId.append(wxMessage.getCreateTime()) | |||
| .append("-").append(wxMessage.getFromUserName()) | |||
| .append("-").append(wxMessage.getFromUser()) | |||
| .append("-").append(wxMessage.getEventKey() == null ? "" : wxMessage.getEventKey()) | |||
| .append("-").append(wxMessage.getEvent() == null ? "" : wxMessage.getEvent()) | |||
| ; | |||
| @@ -220,7 +221,7 @@ public class WxMpMessageRouter { | |||
| */ | |||
| protected void sessionEndAccess(WxMpXmlMessage wxMessage) { | |||
| InternalSession session = ((InternalSessionManager)this.sessionManager).findSession(wxMessage.getFromUserName()); | |||
| InternalSession session = ((InternalSessionManager)this.sessionManager).findSession(wxMessage.getFromUser()); | |||
| if (session != null) { | |||
| session.endAccess(); | |||
| } | |||
| @@ -168,7 +168,7 @@ public class WxMpMessageRouterRule { | |||
| */ | |||
| protected boolean test(WxMpXmlMessage wxMessage) { | |||
| return | |||
| (this.fromUser == null || this.fromUser.equals(wxMessage.getFromUserName())) | |||
| (this.fromUser == null || this.fromUser.equals(wxMessage.getFromUser())) | |||
| && | |||
| (this.msgType == null || this.msgType.toLowerCase().equals((wxMessage.getMsgType()==null?null:wxMessage.getMsgType().toLowerCase()))) | |||
| && | |||