mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2026-03-10 00:13:40 +08:00
code clean up for common module
This commit is contained in:
@@ -62,20 +62,6 @@ 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<String, String>();
|
||||||
static {
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_SUCCESS, "发送成功");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_FAIL, "发送失败");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌广告, "涉嫌广告");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌政治, "涉嫌政治");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌社会, "涉嫌社会");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌色情, "涉嫌色情");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌违法犯罪, "涉嫌违法犯罪");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌欺诈, "涉嫌欺诈");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌版权, "涉嫌版权");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌互推_互相宣传, "涉嫌互推_互相宣传");
|
|
||||||
MASS_ST_2_DESC.put(MASS_ST_涉嫌其他, "涉嫌其他");
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// 微信端推送过来的事件类型
|
// 微信端推送过来的事件类型
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@@ -103,11 +89,9 @@ public class WxConsts {
|
|||||||
public static final String EVT_USER_VIEW_CARD = "user_view_card";
|
public static final String EVT_USER_VIEW_CARD = "user_view_card";
|
||||||
public static final String EVT_USER_ENTER_SESSION_FROM_CARD = "user_enter_session_from_card";
|
public static final String EVT_USER_ENTER_SESSION_FROM_CARD = "user_enter_session_from_card";
|
||||||
public static final String EVT_CARD_SKU_REMIND = "card_sku_remind"; // 库存报警
|
public static final String EVT_CARD_SKU_REMIND = "card_sku_remind"; // 库存报警
|
||||||
|
|
||||||
public static final String EVT_KF_CREATE_SESSION = "kf_create_session"; // 客服接入会话
|
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_CLOSE_SESSION = "kf_close_session"; // 客服关闭会话
|
||||||
public static final String EVT_KF_SWITCH_SESSION = "kf_switch_session"; // 客服转接会话
|
public static final String EVT_KF_SWITCH_SESSION = "kf_switch_session"; // 客服转接会话
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// 上传多媒体文件的类型
|
// 上传多媒体文件的类型
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@@ -116,7 +100,6 @@ public class WxConsts {
|
|||||||
public static final String MEDIA_VIDEO = "video";
|
public static final String MEDIA_VIDEO = "video";
|
||||||
public static final String MEDIA_THUMB = "thumb";
|
public static final String MEDIA_THUMB = "thumb";
|
||||||
public static final String MEDIA_FILE = "file";
|
public static final String MEDIA_FILE = "file";
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// 文件类型
|
// 文件类型
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@@ -124,40 +107,63 @@ public class WxConsts {
|
|||||||
public static final String FILE_MP3 = "mp3";
|
public static final String FILE_MP3 = "mp3";
|
||||||
public static final String FILE_AMR = "amr";
|
public static final String FILE_AMR = "amr";
|
||||||
public static final String FILE_MP4 = "mp4";
|
public static final String FILE_MP4 = "mp4";
|
||||||
|
/**
|
||||||
|
* 点击推事件
|
||||||
|
*/
|
||||||
|
public static final String BUTTON_CLICK = "click";
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// 自定义菜单的按钮类型
|
// 自定义菜单的按钮类型
|
||||||
///////////////////////
|
///////////////////////
|
||||||
/** 点击推事件 */
|
/**
|
||||||
public static final String BUTTON_CLICK = "click";
|
* 跳转URL
|
||||||
/** 跳转URL */
|
*/
|
||||||
public static final String BUTTON_VIEW = "view";
|
public static final String BUTTON_VIEW = "view";
|
||||||
/** 扫码推事件 */
|
/**
|
||||||
|
* 扫码推事件
|
||||||
|
*/
|
||||||
public static final String BUTTON_SCANCODE_PUSH = "scancode_push";
|
public static final String BUTTON_SCANCODE_PUSH = "scancode_push";
|
||||||
/** 扫码推事件且弹出“消息接收中”提示框 */
|
/**
|
||||||
|
* 扫码推事件且弹出“消息接收中”提示框
|
||||||
|
*/
|
||||||
public static final String BUTTON_SCANCODE_WAITMSG = "scancode_waitmsg";
|
public static final String BUTTON_SCANCODE_WAITMSG = "scancode_waitmsg";
|
||||||
/** 弹出系统拍照发图 */
|
/**
|
||||||
|
* 弹出系统拍照发图
|
||||||
|
*/
|
||||||
public static final String BUTTON_PIC_SYSPHOTO = "pic_sysphoto";
|
public static final String BUTTON_PIC_SYSPHOTO = "pic_sysphoto";
|
||||||
/** 弹出拍照或者相册发图 */
|
/**
|
||||||
|
* 弹出拍照或者相册发图
|
||||||
|
*/
|
||||||
public static final String BUTTON_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
|
public static final String BUTTON_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
|
||||||
/** 弹出微信相册发图器 */
|
/**
|
||||||
|
* 弹出微信相册发图器
|
||||||
|
*/
|
||||||
public static final String BUTTON_PIC_WEIXIN = "pic_weixin";
|
public static final String BUTTON_PIC_WEIXIN = "pic_weixin";
|
||||||
/** 弹出地理位置选择器 */
|
/**
|
||||||
|
* 弹出地理位置选择器
|
||||||
|
*/
|
||||||
public static final String BUTTON_LOCATION_SELECT = "location_select";
|
public static final String BUTTON_LOCATION_SELECT = "location_select";
|
||||||
/** 下发消息(除文本消息) */
|
/**
|
||||||
|
* 下发消息(除文本消息)
|
||||||
|
*/
|
||||||
public static final String BUTTON_MEDIA_ID = "media_id";
|
public static final String BUTTON_MEDIA_ID = "media_id";
|
||||||
/** 跳转图文消息URL */
|
/**
|
||||||
|
* 跳转图文消息URL
|
||||||
|
*/
|
||||||
public static final String BUTTON_VIEW_LIMITED = "view_limited";
|
public static final String BUTTON_VIEW_LIMITED = "view_limited";
|
||||||
|
/**
|
||||||
|
* 不弹出授权页面,直接跳转,只能获取用户openid
|
||||||
|
*/
|
||||||
|
public static final String OAUTH2_SCOPE_BASE = "snsapi_base";
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// oauth2网页授权的scope
|
// oauth2网页授权的scope
|
||||||
///////////////////////
|
///////////////////////
|
||||||
/** 不弹出授权页面,直接跳转,只能获取用户openid */
|
/**
|
||||||
public static final String OAUTH2_SCOPE_BASE = "snsapi_base";
|
* 弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息
|
||||||
/** 弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息 */
|
*/
|
||||||
public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo";
|
public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo";
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// 永久素材类型
|
// 永久素材类型
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@@ -165,4 +171,18 @@ public class WxConsts {
|
|||||||
public static final String MATERIAL_VOICE = "voice";
|
public static final String MATERIAL_VOICE = "voice";
|
||||||
public static final String MATERIAL_IMAGE = "image";
|
public static final String MATERIAL_IMAGE = "image";
|
||||||
public static final String MATERIAL_VIDEO = "video";
|
public static final String MATERIAL_VIDEO = "video";
|
||||||
|
|
||||||
|
static {
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_SUCCESS, "发送成功");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_FAIL, "发送失败");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌广告, "涉嫌广告");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌政治, "涉嫌政治");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌社会, "涉嫌社会");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌色情, "涉嫌色情");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌违法犯罪, "涉嫌违法犯罪");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌欺诈, "涉嫌欺诈");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌版权, "涉嫌版权");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌互推_互相宣传, "涉嫌互推_互相宣传");
|
||||||
|
MASS_ST_2_DESC.put(MASS_ST_涉嫌其他, "涉嫌其他");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,16 @@ public interface WxMessageDuplicateChecker {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <h2>公众号的排重方式</h2>
|
* <h2>公众号的排重方式</h2>
|
||||||
*
|
* <p>
|
||||||
* <p>普通消息:关于重试的消息排重,推荐使用msgid排重。<a href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html">文档参考</a>。</p>
|
* <p>普通消息:关于重试的消息排重,推荐使用msgid排重。<a href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html">文档参考</a>。</p>
|
||||||
* <p>事件消息:关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。<a href="http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html">文档参考</a></p>
|
* <p>事件消息:关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。<a href="http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html">文档参考</a></p>
|
||||||
*
|
* <p>
|
||||||
* <h2>企业号的排重方式</h2>
|
* <h2>企业号的排重方式</h2>
|
||||||
*
|
* <p>
|
||||||
* 官方文档完全没有写,参照公众号的方式排重。
|
* 官方文档完全没有写,参照公众号的方式排重。
|
||||||
*
|
* <p>
|
||||||
* <p>或者可以采取更简单的方式,如果有MsgId就用MsgId排重,如果没有就用FromUserName+CreateTime排重</p>
|
* <p>或者可以采取更简单的方式,如果有MsgId就用MsgId排重,如果没有就用FromUserName+CreateTime排重</p>
|
||||||
|
*
|
||||||
* @param messageId messageId需要根据上面讲的方式构造
|
* @param messageId messageId需要根据上面讲的方式构造
|
||||||
* @return 如果是重复消息,返回true,否则返回false
|
* @return 如果是重复消息,返回true,否则返回false
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* WxMsgIdInMemoryDuplicateChecker构造函数
|
* WxMsgIdInMemoryDuplicateChecker构造函数
|
||||||
* @param timeToLive 一个消息ID在内存的过期时间:毫秒
|
*
|
||||||
|
* @param timeToLive 一个消息ID在内存的过期时间:毫秒
|
||||||
* @param clearPeriod 每隔多少周期检查消息ID是否过期:毫秒
|
* @param clearPeriod 每隔多少周期检查消息ID是否过期:毫秒
|
||||||
*/
|
*/
|
||||||
public WxMessageInMemoryDuplicateChecker(Long timeToLive, Long clearPeriod) {
|
public WxMessageInMemoryDuplicateChecker(Long timeToLive, Long clearPeriod) {
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ public class WxAccessToken implements Serializable {
|
|||||||
|
|
||||||
private int expiresIn = -1;
|
private int expiresIn = -1;
|
||||||
|
|
||||||
|
public static WxAccessToken fromJson(String json) {
|
||||||
|
return WxGsonBuilder.create().fromJson(json, WxAccessToken.class);
|
||||||
|
}
|
||||||
|
|
||||||
public String getAccessToken() {
|
public String getAccessToken() {
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
@@ -27,8 +31,4 @@ public class WxAccessToken implements Serializable {
|
|||||||
this.expiresIn = expiresIn;
|
this.expiresIn = expiresIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WxAccessToken fromJson(String json) {
|
|
||||||
return WxGsonBuilder.create().fromJson(json, WxAccessToken.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,11 +51,11 @@ public class WxJsapiSignature implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getAppid() {
|
public String getAppid() {
|
||||||
return appid;
|
return appid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAppid(String appid) {
|
public void setAppid(String appid) {
|
||||||
this.appid = appid;
|
this.appid = appid;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package me.chanjar.weixin.common.bean;
|
package me.chanjar.weixin.common.bean;
|
||||||
|
|
||||||
|
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -7,12 +9,10 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业号菜单
|
* 企业号菜单
|
||||||
* @author Daniel Qian
|
|
||||||
*
|
*
|
||||||
|
* @author Daniel Qian
|
||||||
*/
|
*/
|
||||||
public class WxMenu implements Serializable {
|
public class WxMenu implements Serializable {
|
||||||
|
|
||||||
@@ -22,6 +22,22 @@ public class WxMenu implements Serializable {
|
|||||||
|
|
||||||
private WxMenuRule matchRule;
|
private WxMenuRule matchRule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
|
||||||
|
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式,外层多套了一个menu
|
||||||
|
*/
|
||||||
|
public static WxMenu fromJson(String json) {
|
||||||
|
return WxGsonBuilder.create().fromJson(json, WxMenu.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
|
||||||
|
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式,外层多套了一个menu
|
||||||
|
*/
|
||||||
|
public static WxMenu fromJson(InputStream is) {
|
||||||
|
return WxGsonBuilder.create().fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), WxMenu.class);
|
||||||
|
}
|
||||||
|
|
||||||
public List<WxMenuButton> getButtons() {
|
public List<WxMenuButton> getButtons() {
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
@@ -42,27 +58,11 @@ public class WxMenu implements Serializable {
|
|||||||
return WxGsonBuilder.create().toJson(this);
|
return WxGsonBuilder.create().toJson(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
|
|
||||||
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式,外层多套了一个menu
|
|
||||||
*/
|
|
||||||
public static WxMenu fromJson(String json) {
|
|
||||||
return WxGsonBuilder.create().fromJson(json, WxMenu.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
|
|
||||||
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式,外层多套了一个menu
|
|
||||||
*/
|
|
||||||
public static WxMenu fromJson(InputStream is) {
|
|
||||||
return WxGsonBuilder.create().fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), WxMenu.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "WxMenu{" +
|
return "WxMenu{" +
|
||||||
"buttons=" + buttons +
|
"buttons=" + buttons +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class WxMenuButton {
|
public static class WxMenuButton {
|
||||||
@@ -117,12 +117,12 @@ public class WxMenu implements Serializable {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "WxMenuButton{" +
|
return "WxMenuButton{" +
|
||||||
"type='" + type + '\'' +
|
"type='" + type + '\'' +
|
||||||
", name='" + name + '\'' +
|
", name='" + name + '\'' +
|
||||||
", key='" + key + '\'' +
|
", key='" + key + '\'' +
|
||||||
", url='" + url + '\'' +
|
", url='" + url + '\'' +
|
||||||
", subButtons=" + subButtons +
|
", subButtons=" + subButtons +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,14 +194,14 @@ public class WxMenu implements Serializable {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "matchrule:{" +
|
return "matchrule:{" +
|
||||||
"tag_id='" + tagId + '\'' +
|
"tag_id='" + tagId + '\'' +
|
||||||
", sex='" + sex + '\'' +
|
", sex='" + sex + '\'' +
|
||||||
", country" + country + '\'' +
|
", country" + country + '\'' +
|
||||||
", province" + province + '\'' +
|
", province" + province + '\'' +
|
||||||
", city" + city + '\'' +
|
", city" + city + '\'' +
|
||||||
", client_platform_type" + clientPlatformType + '\'' +
|
", client_platform_type" + clientPlatformType + '\'' +
|
||||||
", language" + language + '\'' +
|
", language" + language + '\'' +
|
||||||
"}";
|
"}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import java.io.Serializable;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信错误码说明,请阅读: <a href="http://mp.weixin.qq.com/wiki/10/6380dc743053a91c544ffd2b7c959166.html">全局返回码说明</a>
|
* 微信错误码说明,请阅读: <a href="http://mp.weixin.qq.com/wiki/10/6380dc743053a91c544ffd2b7c959166.html">全局返回码说明</a>
|
||||||
* @author Daniel Qian
|
|
||||||
*
|
*
|
||||||
|
* @author Daniel Qian
|
||||||
*/
|
*/
|
||||||
public class WxError implements Serializable {
|
public class WxError implements Serializable {
|
||||||
|
|
||||||
@@ -19,6 +19,15 @@ public class WxError implements Serializable {
|
|||||||
|
|
||||||
private String json;
|
private String json;
|
||||||
|
|
||||||
|
public static WxError fromJson(String json) {
|
||||||
|
WxError error = WxGsonBuilder.create().fromJson(json, WxError.class);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder newBuilder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
public int getErrorCode() {
|
public int getErrorCode() {
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
@@ -43,24 +52,15 @@ public class WxError implements Serializable {
|
|||||||
this.json = json;
|
this.json = json;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WxError fromJson(String json) {
|
|
||||||
WxError error = WxGsonBuilder.create().fromJson(json, WxError.class);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if(json != null){
|
if (json != null) {
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
return "错误: Code=" + errorCode + ", Msg=" + errorMsg;
|
return "错误: Code=" + errorCode + ", Msg=" + errorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder newBuilder(){
|
public static class Builder {
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder{
|
|
||||||
private int errorCode;
|
private int errorCode;
|
||||||
private String errorMsg;
|
private String errorMsg;
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ public class WxError implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WxError build(){
|
public WxError build() {
|
||||||
WxError wxError = new WxError();
|
WxError wxError = new WxError();
|
||||||
wxError.setErrorCode(this.errorCode);
|
wxError.setErrorCode(this.errorCode);
|
||||||
wxError.setErrorMsg(this.errorMsg);
|
wxError.setErrorMsg(this.errorMsg);
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ public class WxMediaUploadResult implements Serializable {
|
|||||||
private String thumbMediaId;
|
private String thumbMediaId;
|
||||||
private long createdAt;
|
private long createdAt;
|
||||||
|
|
||||||
|
public static WxMediaUploadResult fromJson(String json) {
|
||||||
|
return WxGsonBuilder.create().fromJson(json, WxMediaUploadResult.class);
|
||||||
|
}
|
||||||
|
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -44,14 +48,10 @@ public class WxMediaUploadResult implements Serializable {
|
|||||||
this.thumbMediaId = thumbMediaId;
|
this.thumbMediaId = thumbMediaId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WxMediaUploadResult fromJson(String json) {
|
|
||||||
return WxGsonBuilder.create().fromJson(json, WxMediaUploadResult.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "WxUploadResult [type=" + type + ", media_id=" + mediaId + ", thumb_media_id=" + thumbMediaId
|
return "WxUploadResult [type=" + type + ", media_id=" + mediaId + ", thumb_media_id=" + thumbMediaId
|
||||||
+ ", created_at=" + createdAt + "]";
|
+ ", created_at=" + createdAt + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,6 @@ package me.chanjar.weixin.common.session;
|
|||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
public static final String Package = "me.chanjar.weixin.common.session";
|
public static final String Package = "me.chanjar.weixin.common.session";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ public interface InternalSession {
|
|||||||
*/
|
*/
|
||||||
WxSession getSession();
|
WxSession getSession();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the <code>isValid</code> flag for this session.
|
||||||
|
*/
|
||||||
|
boolean isValid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the <code>isValid</code> flag for this session.
|
* Set the <code>isValid</code> flag for this session.
|
||||||
*
|
*
|
||||||
@@ -15,11 +20,6 @@ public interface InternalSession {
|
|||||||
*/
|
*/
|
||||||
void setValid(boolean isValid);
|
void setValid(boolean isValid);
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the <code>isValid</code> flag for this session.
|
|
||||||
*/
|
|
||||||
boolean isValid();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the session identifier for this session.
|
* Return the session identifier for this session.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ public interface InternalSessionManager {
|
|||||||
* specified session id (if any); otherwise return <code>null</code>.
|
* specified session id (if any); otherwise return <code>null</code>.
|
||||||
*
|
*
|
||||||
* @param id The session id for the session to be returned
|
* @param id The session id for the session to be returned
|
||||||
*
|
* @throws IllegalStateException if a new session cannot be
|
||||||
* @exception IllegalStateException if a new session cannot be
|
* instantiated for any reason
|
||||||
* instantiated for any reason
|
* @throws java.io.IOException if an input/output error occurs while
|
||||||
* @exception java.io.IOException if an input/output error occurs while
|
* processing this request
|
||||||
* processing this request
|
|
||||||
*/
|
*/
|
||||||
InternalSession findSession(String id);
|
InternalSession findSession(String id);
|
||||||
|
|
||||||
@@ -23,10 +22,10 @@ public interface InternalSessionManager {
|
|||||||
* <code>null</code>.
|
* <code>null</code>.
|
||||||
*
|
*
|
||||||
* @param sessionId The session id which should be used to create the
|
* @param sessionId The session id which should be used to create the
|
||||||
* new session; if <code>null</code>, a new session id will be
|
* new session; if <code>null</code>, a new session id will be
|
||||||
* generated
|
* generated
|
||||||
* @exception IllegalStateException if a new session cannot be
|
* @throws IllegalStateException if a new session cannot be
|
||||||
* instantiated for any reason
|
* instantiated for any reason
|
||||||
*/
|
*/
|
||||||
InternalSession createSession(String sessionId);
|
InternalSession createSession(String sessionId);
|
||||||
|
|
||||||
@@ -40,8 +39,8 @@ public interface InternalSessionManager {
|
|||||||
/**
|
/**
|
||||||
* Remove this Session from the active Sessions for this Manager.
|
* Remove this Session from the active Sessions for this Manager.
|
||||||
*
|
*
|
||||||
* @param session Session to be removed
|
* @param session Session to be removed
|
||||||
* @param update Should the expiration statistics be updated
|
* @param update Should the expiration statistics be updated
|
||||||
*/
|
*/
|
||||||
void remove(InternalSession session, boolean update);
|
void remove(InternalSession session, boolean update);
|
||||||
|
|
||||||
@@ -59,6 +58,7 @@ public interface InternalSessionManager {
|
|||||||
* @return number of sessions active
|
* @return number of sessions active
|
||||||
*/
|
*/
|
||||||
int getActiveSessions();
|
int getActiveSessions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a session from the recycled ones or create a new empty one.
|
* Get a session from the recycled ones or create a new empty one.
|
||||||
* The PersistentManager manager does not need to create session data
|
* The PersistentManager manager does not need to create session data
|
||||||
@@ -88,6 +88,7 @@ public interface InternalSessionManager {
|
|||||||
* 要和{@link #setBackgroundProcessorDelay(int)}联合起来看
|
* 要和{@link #setBackgroundProcessorDelay(int)}联合起来看
|
||||||
* 如果把这个数字设置为6(默认),那么就是说manager要等待 6 * backgroundProcessorDay的时间才会清理过期session
|
* 如果把这个数字设置为6(默认),那么就是说manager要等待 6 * backgroundProcessorDay的时间才会清理过期session
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @param processExpiresFrequency the new manager checks frequency
|
* @param processExpiresFrequency the new manager checks frequency
|
||||||
*/
|
*/
|
||||||
void setProcessExpiresFrequency(int processExpiresFrequency);
|
void setProcessExpiresFrequency(int processExpiresFrequency);
|
||||||
@@ -97,6 +98,7 @@ public interface InternalSessionManager {
|
|||||||
* Set the manager background processor delay
|
* Set the manager background processor delay
|
||||||
* 设置manager sleep几秒,尝试执行一次background操作(清理过期session)
|
* 设置manager sleep几秒,尝试执行一次background操作(清理过期session)
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @param backgroundProcessorDelay
|
* @param backgroundProcessorDelay
|
||||||
*/
|
*/
|
||||||
void setBackgroundProcessorDelay(int backgroundProcessorDelay);
|
void setBackgroundProcessorDelay(int backgroundProcessorDelay);
|
||||||
@@ -106,6 +108,7 @@ public interface InternalSessionManager {
|
|||||||
* Set the maximum number of active Sessions allowed, or -1 for
|
* Set the maximum number of active Sessions allowed, or -1 for
|
||||||
* no limit.
|
* no limit.
|
||||||
* 设置最大活跃session数,默认无限
|
* 设置最大活跃session数,默认无限
|
||||||
|
*
|
||||||
* @param max The new maximum number of sessions
|
* @param max The new maximum number of sessions
|
||||||
*/
|
*/
|
||||||
void setMaxActiveSessions(int max);
|
void setMaxActiveSessions(int max);
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
applicationSession.session.ise=invalid session state
|
applicationSession.session.ise=invalid session state
|
||||||
applicationSession.value.iae=null value
|
applicationSession.value.iae=null value
|
||||||
fileStore.saving=Saving Session {0} to file {1}
|
fileStore.saving=Saving Session {0} to file {1}
|
||||||
|
|||||||
@@ -12,17 +12,68 @@ public class StandardSession implements WxSession, InternalSession {
|
|||||||
* The string manager for this package.
|
* The string manager for this package.
|
||||||
*/
|
*/
|
||||||
protected static final StringManager sm =
|
protected static final StringManager sm =
|
||||||
StringManager.getManager(Constants.Package);
|
StringManager.getManager(Constants.Package);
|
||||||
|
/**
|
||||||
|
* Type array.
|
||||||
|
*/
|
||||||
|
protected static final String EMPTY_ARRAY[] = new String[0];
|
||||||
// ------------------------------ WxSession
|
// ------------------------------ WxSession
|
||||||
protected Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
|
protected Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
|
||||||
|
/**
|
||||||
|
* The session identifier of this Session.
|
||||||
|
*/
|
||||||
|
protected String id = null;
|
||||||
|
/**
|
||||||
|
* Flag indicating whether this session is valid or not.
|
||||||
|
*/
|
||||||
|
protected volatile boolean isValid = false;
|
||||||
|
/**
|
||||||
|
* We are currently processing a session expiration, so bypass
|
||||||
|
* certain IllegalStateException tests. NOTE: This value is not
|
||||||
|
* included in the serialized version of this object.
|
||||||
|
*/
|
||||||
|
protected transient volatile boolean expiring = false;
|
||||||
|
/**
|
||||||
|
* The Manager with which this Session is associated.
|
||||||
|
*/
|
||||||
|
protected transient InternalSessionManager manager = null;
|
||||||
|
|
||||||
|
// ------------------------------ InternalSession
|
||||||
|
/**
|
||||||
|
* The time this session was created, in milliseconds since midnight,
|
||||||
|
* January 1, 1970 GMT.
|
||||||
|
*/
|
||||||
|
protected long creationTime = 0L;
|
||||||
|
/**
|
||||||
|
* The current accessed time for this session.
|
||||||
|
*/
|
||||||
|
protected volatile long thisAccessedTime = creationTime;
|
||||||
|
/**
|
||||||
|
* The default maximum inactive interval for Sessions created by
|
||||||
|
* this Manager.
|
||||||
|
*/
|
||||||
|
protected int maxInactiveInterval = 30 * 60;
|
||||||
|
/**
|
||||||
|
* The facade associated with this session. NOTE: This value is not
|
||||||
|
* included in the serialized version of this object.
|
||||||
|
*/
|
||||||
|
protected transient StandardSessionFacade facade = null;
|
||||||
|
/**
|
||||||
|
* The access count for this session.
|
||||||
|
*/
|
||||||
|
protected transient AtomicInteger accessCount = null;
|
||||||
|
|
||||||
|
public StandardSession(InternalSessionManager manager) {
|
||||||
|
this.manager = manager;
|
||||||
|
this.accessCount = new AtomicInteger();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getAttribute(String name) {
|
public Object getAttribute(String name) {
|
||||||
|
|
||||||
if (!isValidInternal())
|
if (!isValidInternal())
|
||||||
throw new IllegalStateException
|
throw new IllegalStateException
|
||||||
(sm.getString("sessionImpl.getAttribute.ise"));
|
(sm.getString("sessionImpl.getAttribute.ise"));
|
||||||
|
|
||||||
if (name == null) return null;
|
if (name == null) return null;
|
||||||
|
|
||||||
@@ -33,7 +84,7 @@ public class StandardSession implements WxSession, InternalSession {
|
|||||||
public Enumeration<String> getAttributeNames() {
|
public Enumeration<String> getAttributeNames() {
|
||||||
if (!isValidInternal())
|
if (!isValidInternal())
|
||||||
throw new IllegalStateException
|
throw new IllegalStateException
|
||||||
(sm.getString("sessionImpl.getAttributeNames.ise"));
|
(sm.getString("sessionImpl.getAttributeNames.ise"));
|
||||||
|
|
||||||
Set<String> names = new HashSet<String>();
|
Set<String> names = new HashSet<String>();
|
||||||
names.addAll(attributes.keySet());
|
names.addAll(attributes.keySet());
|
||||||
@@ -45,7 +96,7 @@ public class StandardSession implements WxSession, InternalSession {
|
|||||||
// Name cannot be null
|
// Name cannot be null
|
||||||
if (name == null)
|
if (name == null)
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException
|
||||||
(sm.getString("sessionImpl.setAttribute.namenull"));
|
(sm.getString("sessionImpl.setAttribute.namenull"));
|
||||||
|
|
||||||
// Null value is the same as removeAttribute()
|
// Null value is the same as removeAttribute()
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
@@ -56,97 +107,32 @@ public class StandardSession implements WxSession, InternalSession {
|
|||||||
// Validate our current state
|
// Validate our current state
|
||||||
if (!isValidInternal())
|
if (!isValidInternal())
|
||||||
throw new IllegalStateException(sm.getString(
|
throw new IllegalStateException(sm.getString(
|
||||||
"sessionImpl.setAttribute.ise", getIdInternal()));
|
"sessionImpl.setAttribute.ise", getIdInternal()));
|
||||||
|
|
||||||
attributes.put(name, value);
|
attributes.put(name, value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAttribute(String name) {
|
public void removeAttribute(String name) {
|
||||||
removeAttributeInternal(name);
|
removeAttributeInternal(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
if (!isValidInternal())
|
if (!isValidInternal())
|
||||||
throw new IllegalStateException
|
throw new IllegalStateException
|
||||||
(sm.getString("sessionImpl.invalidate.ise"));
|
(sm.getString("sessionImpl.invalidate.ise"));
|
||||||
|
|
||||||
// Cause this session to expire
|
// Cause this session to expire
|
||||||
expire();
|
expire();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------ InternalSession
|
|
||||||
/**
|
|
||||||
* The session identifier of this Session.
|
|
||||||
*/
|
|
||||||
protected String id = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag indicating whether this session is valid or not.
|
|
||||||
*/
|
|
||||||
protected volatile boolean isValid = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We are currently processing a session expiration, so bypass
|
|
||||||
* certain IllegalStateException tests. NOTE: This value is not
|
|
||||||
* included in the serialized version of this object.
|
|
||||||
*/
|
|
||||||
protected transient volatile boolean expiring = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Manager with which this Session is associated.
|
|
||||||
*/
|
|
||||||
protected transient InternalSessionManager manager = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type array.
|
|
||||||
*/
|
|
||||||
protected static final String EMPTY_ARRAY[] = new String[0];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The time this session was created, in milliseconds since midnight,
|
|
||||||
* January 1, 1970 GMT.
|
|
||||||
*/
|
|
||||||
protected long creationTime = 0L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current accessed time for this session.
|
|
||||||
*/
|
|
||||||
protected volatile long thisAccessedTime = creationTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default maximum inactive interval for Sessions created by
|
|
||||||
* this Manager.
|
|
||||||
*/
|
|
||||||
protected int maxInactiveInterval = 30 * 60;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The facade associated with this session. NOTE: This value is not
|
|
||||||
* included in the serialized version of this object.
|
|
||||||
*/
|
|
||||||
protected transient StandardSessionFacade facade = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The access count for this session.
|
|
||||||
*/
|
|
||||||
protected transient AtomicInteger accessCount = null;
|
|
||||||
|
|
||||||
|
|
||||||
public StandardSession(InternalSessionManager manager) {
|
|
||||||
this.manager = manager;
|
|
||||||
this.accessCount = new AtomicInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WxSession getSession() {
|
public WxSession getSession() {
|
||||||
|
|
||||||
if (facade == null){
|
if (facade == null) {
|
||||||
facade = new StandardSessionFacade(this);
|
facade = new StandardSessionFacade(this);
|
||||||
}
|
}
|
||||||
return (facade);
|
return (facade);
|
||||||
@@ -161,16 +147,6 @@ public class StandardSession implements WxSession, InternalSession {
|
|||||||
return this.isValid;
|
return this.isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the <code>isValid</code> flag for this session.
|
|
||||||
*
|
|
||||||
* @param isValid The new value for the <code>isValid</code> flag
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setValid(boolean isValid) {
|
|
||||||
this.isValid = isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
if (!this.isValid) {
|
if (!this.isValid) {
|
||||||
@@ -197,6 +173,16 @@ public class StandardSession implements WxSession, InternalSession {
|
|||||||
return this.isValid;
|
return this.isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the <code>isValid</code> flag for this session.
|
||||||
|
*
|
||||||
|
* @param isValid The new value for the <code>isValid</code> flag
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setValid(boolean isValid) {
|
||||||
|
this.isValid = isValid;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIdInternal() {
|
public String getIdInternal() {
|
||||||
return (this.id);
|
return (this.id);
|
||||||
|
|||||||
@@ -13,16 +13,65 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
*/
|
*/
|
||||||
public class StandardSessionManager implements WxSessionManager, InternalSessionManager {
|
public class StandardSessionManager implements WxSessionManager, InternalSessionManager {
|
||||||
|
|
||||||
protected final Logger log = LoggerFactory.getLogger(StandardSessionManager.class);
|
|
||||||
|
|
||||||
protected static final StringManager sm =
|
protected static final StringManager sm =
|
||||||
StringManager.getManager(Constants.Package);
|
StringManager.getManager(Constants.Package);
|
||||||
|
/**
|
||||||
|
* The descriptive name of this Manager implementation (for logging).
|
||||||
|
*/
|
||||||
|
private static final String name = "SessionManagerImpl";
|
||||||
|
protected final Logger log = LoggerFactory.getLogger(StandardSessionManager.class);
|
||||||
|
private final Object maxActiveUpdateLock = new Object();
|
||||||
|
/**
|
||||||
|
* 后台清理线程是否已经开启
|
||||||
|
*/
|
||||||
|
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------- InternalSessionManager
|
||||||
/**
|
/**
|
||||||
* The set of currently active Sessions for this Manager, keyed by
|
* The set of currently active Sessions for this Manager, keyed by
|
||||||
* session identifier.
|
* session identifier.
|
||||||
*/
|
*/
|
||||||
protected Map<String, InternalSession> sessions = new ConcurrentHashMap<String, InternalSession>();
|
protected Map<String, InternalSession> sessions = new ConcurrentHashMap<String, InternalSession>();
|
||||||
|
/**
|
||||||
|
* The maximum number of active Sessions allowed, or -1 for no limit.
|
||||||
|
*/
|
||||||
|
protected int maxActiveSessions = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of session creations that failed due to maxActiveSessions.
|
||||||
|
*/
|
||||||
|
protected int rejectedSessions = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default maximum inactive interval for Sessions created by
|
||||||
|
* this Manager.
|
||||||
|
*/
|
||||||
|
protected int maxInactiveInterval = 30 * 60;
|
||||||
|
|
||||||
|
// Number of sessions created by this manager
|
||||||
|
protected long sessionCounter = 0;
|
||||||
|
|
||||||
|
protected volatile int maxActive = 0;
|
||||||
|
/**
|
||||||
|
* Processing time during session expiration.
|
||||||
|
*/
|
||||||
|
protected long processingTime = 0;
|
||||||
|
/**
|
||||||
|
* Frequency of the session expiration, and related manager operations.
|
||||||
|
* Manager operations will be done once for the specified amount of
|
||||||
|
* backgrondProcess calls (ie, the lower the amount, the most often the
|
||||||
|
* checks will occur).
|
||||||
|
*/
|
||||||
|
protected int processExpiresFrequency = 6;
|
||||||
|
/**
|
||||||
|
* background processor delay in seconds
|
||||||
|
*/
|
||||||
|
protected int backgroundProcessorDelay = 10;
|
||||||
|
/**
|
||||||
|
* Iteration count for background processing.
|
||||||
|
*/
|
||||||
|
private int count = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WxSession getSession(String sessionId) {
|
public WxSession getSession(String sessionId) {
|
||||||
@@ -33,7 +82,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
|
|||||||
public WxSession getSession(String sessionId, boolean create) {
|
public WxSession getSession(String sessionId, boolean create) {
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
throw new IllegalStateException
|
throw new IllegalStateException
|
||||||
(sm.getString("sessionManagerImpl.getSession.ise"));
|
(sm.getString("sessionManagerImpl.getSession.ise"));
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalSession session = findSession(sessionId);
|
InternalSession session = findSession(sessionId);
|
||||||
@@ -60,64 +109,6 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
|
|||||||
return session.getSession();
|
return session.getSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------- InternalSessionManager
|
|
||||||
/**
|
|
||||||
* The descriptive name of this Manager implementation (for logging).
|
|
||||||
*/
|
|
||||||
private static final String name = "SessionManagerImpl";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum number of active Sessions allowed, or -1 for no limit.
|
|
||||||
*/
|
|
||||||
protected int maxActiveSessions = -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of session creations that failed due to maxActiveSessions.
|
|
||||||
*/
|
|
||||||
protected int rejectedSessions = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default maximum inactive interval for Sessions created by
|
|
||||||
* this Manager.
|
|
||||||
*/
|
|
||||||
protected int maxInactiveInterval = 30 * 60;
|
|
||||||
|
|
||||||
// Number of sessions created by this manager
|
|
||||||
protected long sessionCounter=0;
|
|
||||||
|
|
||||||
protected volatile int maxActive=0;
|
|
||||||
|
|
||||||
private final Object maxActiveUpdateLock = new Object();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processing time during session expiration.
|
|
||||||
*/
|
|
||||||
protected long processingTime = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iteration count for background processing.
|
|
||||||
*/
|
|
||||||
private int count = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frequency of the session expiration, and related manager operations.
|
|
||||||
* Manager operations will be done once for the specified amount of
|
|
||||||
* backgrondProcess calls (ie, the lower the amount, the most often the
|
|
||||||
* checks will occur).
|
|
||||||
*/
|
|
||||||
protected int processExpiresFrequency = 6;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* background processor delay in seconds
|
|
||||||
*/
|
|
||||||
protected int backgroundProcessorDelay = 10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 后台清理线程是否已经开启
|
|
||||||
*/
|
|
||||||
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(InternalSession session) {
|
public void remove(InternalSession session) {
|
||||||
remove(session, false);
|
remove(session, false);
|
||||||
@@ -131,7 +122,6 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InternalSession findSession(String id) {
|
public InternalSession findSession(String id) {
|
||||||
|
|
||||||
@@ -145,15 +135,15 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
|
|||||||
public InternalSession createSession(String sessionId) {
|
public InternalSession createSession(String sessionId) {
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
throw new IllegalStateException
|
throw new IllegalStateException
|
||||||
(sm.getString("sessionManagerImpl.createSession.ise"));
|
(sm.getString("sessionManagerImpl.createSession.ise"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((maxActiveSessions >= 0) &&
|
if ((maxActiveSessions >= 0) &&
|
||||||
(getActiveSessions() >= maxActiveSessions)) {
|
(getActiveSessions() >= maxActiveSessions)) {
|
||||||
rejectedSessions++;
|
rejectedSessions++;
|
||||||
throw new TooManyActiveSessionsException(
|
throw new TooManyActiveSessionsException(
|
||||||
sm.getString("sessionManagerImpl.createSession.tmase"),
|
sm.getString("sessionManagerImpl.createSession.tmase"),
|
||||||
maxActiveSessions);
|
maxActiveSessions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recycle or create a Session instance
|
// Recycle or create a Session instance
|
||||||
@@ -216,9 +206,9 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
|
|||||||
|
|
||||||
sessions.put(session.getIdInternal(), session);
|
sessions.put(session.getIdInternal(), session);
|
||||||
int size = getActiveSessions();
|
int size = getActiveSessions();
|
||||||
if( size > maxActive ) {
|
if (size > maxActive) {
|
||||||
synchronized(maxActiveUpdateLock) {
|
synchronized (maxActiveUpdateLock) {
|
||||||
if( size > maxActive ) {
|
if (size > maxActive) {
|
||||||
maxActive = size;
|
maxActive = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,19 +241,19 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
|
|||||||
|
|
||||||
long timeNow = System.currentTimeMillis();
|
long timeNow = System.currentTimeMillis();
|
||||||
InternalSession sessions[] = findSessions();
|
InternalSession sessions[] = findSessions();
|
||||||
int expireHere = 0 ;
|
int expireHere = 0;
|
||||||
|
|
||||||
if(log.isDebugEnabled())
|
if (log.isDebugEnabled())
|
||||||
log.debug("Start expire sessions {} at {} sessioncount {}", getName(), timeNow, sessions.length);
|
log.debug("Start expire sessions {} at {} sessioncount {}", getName(), timeNow, sessions.length);
|
||||||
for (int i = 0; i < sessions.length; i++) {
|
for (int i = 0; i < sessions.length; i++) {
|
||||||
if (sessions[i]!=null && !sessions[i].isValid()) {
|
if (sessions[i] != null && !sessions[i].isValid()) {
|
||||||
expireHere++;
|
expireHere++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long timeEnd = System.currentTimeMillis();
|
long timeEnd = System.currentTimeMillis();
|
||||||
if(log.isDebugEnabled())
|
if (log.isDebugEnabled())
|
||||||
log.debug("End expire sessions {} processingTime {} expired sessions: {}", getName(), timeEnd - timeNow, expireHere);
|
log.debug("End expire sessions {} processingTime {} expired sessions: {}", getName(), timeEnd - timeNow, expireHere);
|
||||||
processingTime += ( timeEnd - timeNow );
|
processingTime += (timeEnd - timeNow);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,37 +21,34 @@ package me.chanjar.weixin.common.session;
|
|||||||
* reached and the server is refusing to create any new sessions.
|
* reached and the server is refusing to create any new sessions.
|
||||||
*/
|
*/
|
||||||
public class TooManyActiveSessionsException
|
public class TooManyActiveSessionsException
|
||||||
extends IllegalStateException
|
extends IllegalStateException {
|
||||||
{
|
private static final long serialVersionUID = 1L;
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of active sessions the server will tolerate.
|
* The maximum number of active sessions the server will tolerate.
|
||||||
*/
|
*/
|
||||||
private final int maxActiveSessions;
|
private final int maxActiveSessions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new TooManyActiveSessionsException.
|
* Creates a new TooManyActiveSessionsException.
|
||||||
*
|
*
|
||||||
* @param message A description for the exception.
|
* @param message A description for the exception.
|
||||||
* @param maxActive The maximum number of active sessions allowed by the
|
* @param maxActive The maximum number of active sessions allowed by the
|
||||||
* session manager.
|
* session manager.
|
||||||
*/
|
*/
|
||||||
public TooManyActiveSessionsException(String message,
|
public TooManyActiveSessionsException(String message,
|
||||||
int maxActive)
|
int maxActive) {
|
||||||
{
|
super(message);
|
||||||
super(message);
|
|
||||||
|
|
||||||
maxActiveSessions = maxActive;
|
maxActiveSessions = maxActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the maximum number of sessions allowed by the session manager.
|
* Gets the maximum number of sessions allowed by the session manager.
|
||||||
*
|
*
|
||||||
* @return The maximum number of sessions allowed by the session manager.
|
* @return The maximum number of sessions allowed by the session manager.
|
||||||
*/
|
*/
|
||||||
public int getMaxActiveSessions()
|
public int getMaxActiveSessions() {
|
||||||
{
|
return maxActiveSessions;
|
||||||
return maxActiveSessions;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public class StringUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Checks if a CharSequence is whitespace, empty ("") or null.</p>
|
* <p>Checks if a CharSequence is whitespace, empty ("") or null.</p>
|
||||||
*
|
* <p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* StringUtils.isBlank(null) = true
|
* StringUtils.isBlank(null) = true
|
||||||
* StringUtils.isBlank("") = true
|
* StringUtils.isBlank("") = true
|
||||||
@@ -16,9 +16,8 @@ public class StringUtils {
|
|||||||
* StringUtils.isBlank(" bob ") = false
|
* StringUtils.isBlank(" bob ") = false
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param cs the CharSequence to check, may be null
|
* @param cs the CharSequence to check, may be null
|
||||||
* @return {@code true} if the CharSequence is null, empty or whitespace
|
* @return {@code true} if the CharSequence is null, empty or whitespace
|
||||||
* @since 2.0
|
|
||||||
* @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
|
* @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
|
||||||
*/
|
*/
|
||||||
public static boolean isBlank(CharSequence cs) {
|
public static boolean isBlank(CharSequence cs) {
|
||||||
@@ -36,7 +35,7 @@ public class StringUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
|
* <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
|
||||||
*
|
* <p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* StringUtils.isNotBlank(null) = false
|
* StringUtils.isNotBlank(null) = false
|
||||||
* StringUtils.isNotBlank("") = false
|
* StringUtils.isNotBlank("") = false
|
||||||
@@ -45,10 +44,9 @@ public class StringUtils {
|
|||||||
* StringUtils.isNotBlank(" bob ") = true
|
* StringUtils.isNotBlank(" bob ") = true
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param cs the CharSequence to check, may be null
|
* @param cs the CharSequence to check, may be null
|
||||||
* @return {@code true} if the CharSequence is
|
* @return {@code true} if the CharSequence is
|
||||||
* not empty and not null and not whitespace
|
* not empty and not null and not whitespace
|
||||||
* @since 2.0
|
|
||||||
* @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
|
* @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
|
||||||
*/
|
*/
|
||||||
public static boolean isNotBlank(CharSequence cs) {
|
public static boolean isNotBlank(CharSequence cs) {
|
||||||
@@ -57,7 +55,7 @@ public class StringUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Checks if a CharSequence is empty ("") or null.</p>
|
* <p>Checks if a CharSequence is empty ("") or null.</p>
|
||||||
*
|
* <p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* StringUtils.isEmpty(null) = true
|
* StringUtils.isEmpty(null) = true
|
||||||
* StringUtils.isEmpty("") = true
|
* StringUtils.isEmpty("") = true
|
||||||
@@ -65,12 +63,12 @@ public class StringUtils {
|
|||||||
* StringUtils.isEmpty("bob") = false
|
* StringUtils.isEmpty("bob") = false
|
||||||
* StringUtils.isEmpty(" bob ") = false
|
* StringUtils.isEmpty(" bob ") = false
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
* <p>
|
||||||
* <p>NOTE: This method changed in Lang version 2.0.
|
* <p>NOTE: This method changed in Lang version 2.0.
|
||||||
* It no longer trims the CharSequence.
|
* It no longer trims the CharSequence.
|
||||||
* That functionality is available in isBlank().</p>
|
* That functionality is available in isBlank().</p>
|
||||||
*
|
*
|
||||||
* @param cs the CharSequence to check, may be null
|
* @param cs the CharSequence to check, may be null
|
||||||
* @return {@code true} if the CharSequence is empty or null
|
* @return {@code true} if the CharSequence is empty or null
|
||||||
* @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
|
* @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
|
||||||
*/
|
*/
|
||||||
@@ -80,7 +78,7 @@ public class StringUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Checks if a CharSequence is not empty ("") and not null.</p>
|
* <p>Checks if a CharSequence is not empty ("") and not null.</p>
|
||||||
*
|
* <p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* StringUtils.isNotEmpty(null) = false
|
* StringUtils.isNotEmpty(null) = false
|
||||||
* StringUtils.isNotEmpty("") = false
|
* StringUtils.isNotEmpty("") = false
|
||||||
@@ -89,7 +87,7 @@ public class StringUtils {
|
|||||||
* StringUtils.isNotEmpty(" bob ") = true
|
* StringUtils.isNotEmpty(" bob ") = true
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param cs the CharSequence to check, may be null
|
* @param cs the CharSequence to check, may be null
|
||||||
* @return {@code true} if the CharSequence is not empty and not null
|
* @return {@code true} if the CharSequence is not empty and not null
|
||||||
* @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
|
* @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,24 +3,24 @@ package me.chanjar.weixin.common.util.crypto;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class ByteGroup {
|
public class ByteGroup {
|
||||||
ArrayList<Byte> byteContainer = new ArrayList<Byte>();
|
ArrayList<Byte> byteContainer = new ArrayList<Byte>();
|
||||||
|
|
||||||
public byte[] toBytes() {
|
public byte[] toBytes() {
|
||||||
byte[] bytes = new byte[byteContainer.size()];
|
byte[] bytes = new byte[byteContainer.size()];
|
||||||
for (int i = 0; i < byteContainer.size(); i++) {
|
for (int i = 0; i < byteContainer.size(); i++) {
|
||||||
bytes[i] = byteContainer.get(i);
|
bytes[i] = byteContainer.get(i);
|
||||||
}
|
}
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteGroup addBytes(byte[] bytes) {
|
public ByteGroup addBytes(byte[] bytes) {
|
||||||
for (byte b : bytes) {
|
for (byte b : bytes) {
|
||||||
byteContainer.add(b);
|
byteContainer.add(b);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return byteContainer.size();
|
return byteContainer.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,53 +16,53 @@ import java.util.Arrays;
|
|||||||
*/
|
*/
|
||||||
public class PKCS7Encoder {
|
public class PKCS7Encoder {
|
||||||
|
|
||||||
private static final Charset CHARSET = Charset.forName("utf-8");
|
private static final Charset CHARSET = Charset.forName("utf-8");
|
||||||
private static final int BLOCK_SIZE = 32;
|
private static final int BLOCK_SIZE = 32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得对明文进行补位填充的字节.
|
* 获得对明文进行补位填充的字节.
|
||||||
*
|
*
|
||||||
* @param count 需要进行填充补位操作的明文字节个数
|
* @param count 需要进行填充补位操作的明文字节个数
|
||||||
* @return 补齐用的字节数组
|
* @return 补齐用的字节数组
|
||||||
*/
|
*/
|
||||||
public static byte[] encode(int count) {
|
public static byte[] encode(int count) {
|
||||||
// 计算需要填充的位数
|
// 计算需要填充的位数
|
||||||
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
|
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
|
||||||
if (amountToPad == 0) {
|
if (amountToPad == 0) {
|
||||||
amountToPad = BLOCK_SIZE;
|
amountToPad = BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
// 获得补位所用的字符
|
// 获得补位所用的字符
|
||||||
char padChr = chr(amountToPad);
|
char padChr = chr(amountToPad);
|
||||||
String tmp = new String();
|
String tmp = new String();
|
||||||
for (int index = 0; index < amountToPad; index++) {
|
for (int index = 0; index < amountToPad; index++) {
|
||||||
tmp += padChr;
|
tmp += padChr;
|
||||||
}
|
}
|
||||||
return tmp.getBytes(CHARSET);
|
return tmp.getBytes(CHARSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除解密后明文的补位字符
|
* 删除解密后明文的补位字符
|
||||||
*
|
*
|
||||||
* @param decrypted 解密后的明文
|
* @param decrypted 解密后的明文
|
||||||
* @return 删除补位字符后的明文
|
* @return 删除补位字符后的明文
|
||||||
*/
|
*/
|
||||||
public static byte[] decode(byte[] decrypted) {
|
public static byte[] decode(byte[] decrypted) {
|
||||||
int pad = (int) decrypted[decrypted.length - 1];
|
int pad = (int) decrypted[decrypted.length - 1];
|
||||||
if (pad < 1 || pad > 32) {
|
if (pad < 1 || pad > 32) {
|
||||||
pad = 0;
|
pad = 0;
|
||||||
}
|
}
|
||||||
return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
|
return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将数字转化成ASCII码对应的字符,用于对明文进行补码
|
* 将数字转化成ASCII码对应的字符,用于对明文进行补码
|
||||||
*
|
*
|
||||||
* @param a 需要转化的数字
|
* @param a 需要转化的数字
|
||||||
* @return 转化得到的字符
|
* @return 转化得到的字符
|
||||||
*/
|
*/
|
||||||
public static char chr(int a) {
|
public static char chr(int a) {
|
||||||
byte target = (byte) (a & 0xFF);
|
byte target = (byte) (a & 0xFF);
|
||||||
return (char) target;
|
return (char) target;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package me.chanjar.weixin.common.util.crypto;
|
package me.chanjar.weixin.common.util.crypto;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Daniel Qian on 14/10/19.
|
* Created by Daniel Qian on 14/10/19.
|
||||||
*/
|
*/
|
||||||
@@ -37,4 +37,4 @@ public class SHA1 {
|
|||||||
}
|
}
|
||||||
return DigestUtils.sha1Hex(sb.toString());
|
return DigestUtils.sha1Hex(sb.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
* 对公众平台发送给公众账号的消息加解密示例代码.
|
* 对公众平台发送给公众账号的消息加解密示例代码.
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 1998-2014 Tencent Inc.
|
* @copyright Copyright (c) 1998-2014 Tencent Inc.
|
||||||
|
* <p>
|
||||||
|
* 针对org.apache.commons.codec.binary.Base64,
|
||||||
|
* 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
|
||||||
|
* 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@@ -62,12 +66,51 @@ public class WxCryptUtil {
|
|||||||
* @param appidOrCorpid 公众平台appid/corpid
|
* @param appidOrCorpid 公众平台appid/corpid
|
||||||
*/
|
*/
|
||||||
public WxCryptUtil(String token, String encodingAesKey,
|
public WxCryptUtil(String token, String encodingAesKey,
|
||||||
String appidOrCorpid) {
|
String appidOrCorpid) {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.appidOrCorpid = appidOrCorpid;
|
this.appidOrCorpid = appidOrCorpid;
|
||||||
this.aesKey = Base64.decodeBase64(encodingAesKey + "=");
|
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();
|
||||||
|
Document document = db.parse(new InputSource(new StringReader(xml)));
|
||||||
|
|
||||||
|
Element root = document.getDocumentElement();
|
||||||
|
return root.getElementsByTagName("Encrypt").item(0).getTextContent();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将公众平台回复用户的消息加密打包.
|
* 将公众平台回复用户的消息加密打包.
|
||||||
* <ol>
|
* <ol>
|
||||||
@@ -107,7 +150,7 @@ public class WxCryptUtil {
|
|||||||
byte[] randomStringBytes = randomStr.getBytes(CHARSET);
|
byte[] randomStringBytes = randomStr.getBytes(CHARSET);
|
||||||
byte[] plainTextBytes = plainText.getBytes(CHARSET);
|
byte[] plainTextBytes = plainText.getBytes(CHARSET);
|
||||||
byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder(
|
byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder(
|
||||||
plainTextBytes.length);
|
plainTextBytes.length);
|
||||||
byte[] appIdBytes = appidOrCorpid.getBytes(CHARSET);
|
byte[] appIdBytes = appidOrCorpid.getBytes(CHARSET);
|
||||||
|
|
||||||
// randomStr + networkBytesOrder + text + appid
|
// randomStr + networkBytesOrder + text + appid
|
||||||
@@ -157,7 +200,7 @@ public class WxCryptUtil {
|
|||||||
* @return 解密后的原文
|
* @return 解密后的原文
|
||||||
*/
|
*/
|
||||||
public String decrypt(String msgSignature, String timeStamp, String nonce,
|
public String decrypt(String msgSignature, String timeStamp, String nonce,
|
||||||
String encryptedXml) {
|
String encryptedXml) {
|
||||||
// 密钥,公众账号的app corpSecret
|
// 密钥,公众账号的app corpSecret
|
||||||
// 提取密文
|
// 提取密文
|
||||||
String cipherText = extractEncryptPart(encryptedXml);
|
String cipherText = extractEncryptPart(encryptedXml);
|
||||||
@@ -190,7 +233,7 @@ public class WxCryptUtil {
|
|||||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||||
SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
|
SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
|
||||||
IvParameterSpec iv = new IvParameterSpec(
|
IvParameterSpec iv = new IvParameterSpec(
|
||||||
Arrays.copyOfRange(aesKey, 0, 16));
|
Arrays.copyOfRange(aesKey, 0, 16));
|
||||||
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
|
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
|
||||||
|
|
||||||
// 使用BASE64对密文进行解码
|
// 使用BASE64对密文进行解码
|
||||||
@@ -213,9 +256,9 @@ public class WxCryptUtil {
|
|||||||
int xmlLength = bytesNetworkOrder2Number(networkOrder);
|
int xmlLength = bytesNetworkOrder2Number(networkOrder);
|
||||||
|
|
||||||
xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength),
|
xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength),
|
||||||
CHARSET);
|
CHARSET);
|
||||||
from_appid = new String(
|
from_appid = new String(
|
||||||
Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET);
|
Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -229,33 +272,6 @@ public class WxCryptUtil {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信公众号支付签名算法(详见: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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将一个数字转换成生成4个字节的网络字节序bytes数组
|
* 将一个数字转换成生成4个字节的网络字节序bytes数组
|
||||||
*
|
*
|
||||||
@@ -308,24 +324,12 @@ public class WxCryptUtil {
|
|||||||
* @return 生成的xml字符串
|
* @return 生成的xml字符串
|
||||||
*/
|
*/
|
||||||
private String generateXml(String encrypt, String signature, String timestamp,
|
private String generateXml(String encrypt, String signature, String timestamp,
|
||||||
String nonce) {
|
String nonce) {
|
||||||
String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n"
|
String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n"
|
||||||
+ "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n"
|
+ "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n"
|
||||||
+ "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n"
|
+ "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n"
|
||||||
+ "</xml>";
|
+ "</xml>";
|
||||||
return String.format(format, encrypt, signature, timestamp, nonce);
|
return String.format(format, encrypt, signature, timestamp, nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String extractEncryptPart(String xml) {
|
|
||||||
try {
|
|
||||||
DocumentBuilder db = builderLocal.get();
|
|
||||||
Document document = db.parse(new InputSource(new StringReader(xml)));
|
|
||||||
|
|
||||||
Element root = document.getDocumentElement();
|
|
||||||
return root.getElementsByTagName("Encrypt").item(0).getTextContent();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,17 +10,18 @@ public class FileUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建临时文件
|
* 创建临时文件
|
||||||
|
*
|
||||||
* @param inputStream
|
* @param inputStream
|
||||||
* @param name 文件名
|
* @param name 文件名
|
||||||
* @param ext 扩展名
|
* @param ext 扩展名
|
||||||
* @param tmpDirFile 临时文件夹目录
|
* @param tmpDirFile 临时文件夹目录
|
||||||
*/
|
*/
|
||||||
public static File createTmpFile(InputStream inputStream, String name, String ext, File tmpDirFile) throws IOException {
|
public static File createTmpFile(InputStream inputStream, String name, String ext, File tmpDirFile) throws IOException {
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
try {
|
try {
|
||||||
File tmpFile;
|
File tmpFile;
|
||||||
if (tmpDirFile == null) {
|
if (tmpDirFile == null) {
|
||||||
tmpFile = File.createTempFile(name, '.' + ext);
|
tmpFile = File.createTempFile(name, '.' + ext);
|
||||||
} else {
|
} else {
|
||||||
tmpFile = File.createTempFile(name, '.' + ext, tmpDirFile);
|
tmpFile = File.createTempFile(name, '.' + ext, tmpDirFile);
|
||||||
}
|
}
|
||||||
@@ -51,9 +52,10 @@ public class FileUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建临时文件
|
* 创建临时文件
|
||||||
|
*
|
||||||
* @param inputStream
|
* @param inputStream
|
||||||
* @param name 文件名
|
* @param name 文件名
|
||||||
* @param ext 扩展名
|
* @param ext 扩展名
|
||||||
*/
|
*/
|
||||||
public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException {
|
public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException {
|
||||||
return createTmpFile(inputStream, name, ext, null);
|
return createTmpFile(inputStream, name, ext, null);
|
||||||
|
|||||||
@@ -10,36 +10,42 @@ public interface ApacheHttpClientBuilder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建httpclient实例
|
* 构建httpclient实例
|
||||||
|
*
|
||||||
* @return new instance of CloseableHttpClient
|
* @return new instance of CloseableHttpClient
|
||||||
*/
|
*/
|
||||||
CloseableHttpClient build();
|
CloseableHttpClient build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代理服务器地址
|
* 代理服务器地址
|
||||||
|
*
|
||||||
* @param httpProxyHost
|
* @param httpProxyHost
|
||||||
*/
|
*/
|
||||||
ApacheHttpClientBuilder httpProxyHost(String httpProxyHost);
|
ApacheHttpClientBuilder httpProxyHost(String httpProxyHost);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代理服务器端口
|
* 代理服务器端口
|
||||||
|
*
|
||||||
* @param httpProxyPort
|
* @param httpProxyPort
|
||||||
*/
|
*/
|
||||||
ApacheHttpClientBuilder httpProxyPort(int httpProxyPort);
|
ApacheHttpClientBuilder httpProxyPort(int httpProxyPort);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代理服务器用户名
|
* 代理服务器用户名
|
||||||
|
*
|
||||||
* @param httpProxyUsername
|
* @param httpProxyUsername
|
||||||
*/
|
*/
|
||||||
ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername);
|
ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代理服务器密码
|
* 代理服务器密码
|
||||||
|
*
|
||||||
* @param httpProxyPassword
|
* @param httpProxyPassword
|
||||||
*/
|
*/
|
||||||
ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword);
|
ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ssl连接socket工厂
|
* ssl连接socket工厂
|
||||||
|
*
|
||||||
* @param sslConnectionSocketFactory
|
* @param sslConnectionSocketFactory
|
||||||
*/
|
*/
|
||||||
ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory);
|
ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class DefaultApacheHttpHttpClientBuilder implements ApacheHttpClientBuild
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory){
|
public ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory) {
|
||||||
this.sslConnectionSocketFactory = sslConnectionSocketFactory;
|
this.sslConnectionSocketFactory = sslConnectionSocketFactory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -103,18 +103,18 @@ public class DefaultApacheHttpHttpClientBuilder implements ApacheHttpClientBuild
|
|||||||
return idleConnectionMonitorThread;
|
return idleConnectionMonitorThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepare(){
|
private void prepare() {
|
||||||
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
|
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
|
||||||
.register("http", plainConnectionSocketFactory)
|
.register("http", plainConnectionSocketFactory)
|
||||||
.register("https", sslConnectionSocketFactory)
|
.register("https", sslConnectionSocketFactory)
|
||||||
.build();
|
.build();
|
||||||
connectionManager = new PoolingHttpClientConnectionManager(registry);
|
connectionManager = new PoolingHttpClientConnectionManager(registry);
|
||||||
connectionManager.setMaxTotal(maxTotalConn);
|
connectionManager.setMaxTotal(maxTotalConn);
|
||||||
connectionManager.setDefaultMaxPerRoute(maxConnPerHost);
|
connectionManager.setDefaultMaxPerRoute(maxConnPerHost);
|
||||||
connectionManager.setDefaultSocketConfig(
|
connectionManager.setDefaultSocketConfig(
|
||||||
SocketConfig.copy(SocketConfig.DEFAULT)
|
SocketConfig.copy(SocketConfig.DEFAULT)
|
||||||
.setSoTimeout(soTimeout)
|
.setSoTimeout(soTimeout)
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
idleConnectionMonitorThread = new IdleConnectionMonitorThread(connectionManager, idleConnTimeout, checkWaitTime);
|
idleConnectionMonitorThread = new IdleConnectionMonitorThread(connectionManager, idleConnTimeout, checkWaitTime);
|
||||||
@@ -122,22 +122,22 @@ public class DefaultApacheHttpHttpClientBuilder implements ApacheHttpClientBuild
|
|||||||
idleConnectionMonitorThread.start();
|
idleConnectionMonitorThread.start();
|
||||||
|
|
||||||
httpClientBuilder = HttpClients.custom()
|
httpClientBuilder = HttpClients.custom()
|
||||||
.setConnectionManager(connectionManager)
|
.setConnectionManager(connectionManager)
|
||||||
.setDefaultRequestConfig(
|
.setDefaultRequestConfig(
|
||||||
RequestConfig.custom()
|
RequestConfig.custom()
|
||||||
.setSocketTimeout(soTimeout)
|
.setSocketTimeout(soTimeout)
|
||||||
.setConnectTimeout(connectionTimeout)
|
.setConnectTimeout(connectionTimeout)
|
||||||
.setConnectionRequestTimeout(connectionRequestTimeout)
|
.setConnectionRequestTimeout(connectionRequestTimeout)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
.setRetryHandler(httpRequestRetryHandler);
|
.setRetryHandler(httpRequestRetryHandler);
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(httpProxyHost) && StringUtils.isNotBlank(httpProxyUsername)) {
|
if (StringUtils.isNotBlank(httpProxyHost) && StringUtils.isNotBlank(httpProxyUsername)) {
|
||||||
// 使用代理服务器 需要用户认证的代理服务器
|
// 使用代理服务器 需要用户认证的代理服务器
|
||||||
CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||||
credsProvider.setCredentials(
|
credsProvider.setCredentials(
|
||||||
new AuthScope(httpProxyHost, httpProxyPort),
|
new AuthScope(httpProxyHost, httpProxyPort),
|
||||||
new UsernamePasswordCredentials(httpProxyUsername, httpProxyPassword));
|
new UsernamePasswordCredentials(httpProxyUsername, httpProxyPassword));
|
||||||
httpClientBuilder.setDefaultCredentialsProvider(credsProvider);
|
httpClientBuilder.setDefaultCredentialsProvider(credsProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ public class DefaultApacheHttpHttpClientBuilder implements ApacheHttpClientBuild
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CloseableHttpClient build() {
|
public CloseableHttpClient build() {
|
||||||
if(!prepared){
|
if (!prepared) {
|
||||||
prepare();
|
prepare();
|
||||||
prepared = true;
|
prepared = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package me.chanjar.weixin.common.util.http;
|
package me.chanjar.weixin.common.util.http;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.StatusLine;
|
import org.apache.http.StatusLine;
|
||||||
@@ -10,6 +7,9 @@ import org.apache.http.client.HttpResponseException;
|
|||||||
import org.apache.http.client.ResponseHandler;
|
import org.apache.http.client.ResponseHandler;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class InputStreamResponseHandler implements ResponseHandler<InputStream> {
|
public class InputStreamResponseHandler implements ResponseHandler<InputStream> {
|
||||||
|
|
||||||
public static final ResponseHandler<InputStream> INSTANCE = new InputStreamResponseHandler();
|
public static final ResponseHandler<InputStream> INSTANCE = new InputStreamResponseHandler();
|
||||||
|
|||||||
@@ -18,39 +18,39 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class JoddGetRequestExecutor implements RequestExecutor<String, String> {
|
public class JoddGetRequestExecutor implements RequestExecutor<String, String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri,
|
public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri,
|
||||||
String queryParam) throws WxErrorException, IOException {
|
String queryParam) throws WxErrorException, IOException {
|
||||||
if (queryParam != null) {
|
if (queryParam != null) {
|
||||||
if (uri.indexOf('?') == -1) {
|
if (uri.indexOf('?') == -1) {
|
||||||
uri += '?';
|
uri += '?';
|
||||||
}
|
}
|
||||||
uri += uri.endsWith("?") ? queryParam : '&' + queryParam;
|
uri += uri.endsWith("?") ? queryParam : '&' + queryParam;
|
||||||
}
|
|
||||||
|
|
||||||
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
|
|
||||||
|
|
||||||
if (httpProxy != null) {
|
|
||||||
ProxyInfo proxyInfoObj = new ProxyInfo(
|
|
||||||
ProxyInfo.ProxyType.HTTP,
|
|
||||||
httpProxy.getHostName(),
|
|
||||||
httpProxy.getPort(), "", "");
|
|
||||||
provider.useProxy(proxyInfoObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpRequest request = HttpRequest.get(uri);
|
|
||||||
request.method("GET");
|
|
||||||
request.charset("UTF-8");
|
|
||||||
|
|
||||||
HttpResponse response = request.open(provider).send();
|
|
||||||
response.charset("UTF-8");
|
|
||||||
String result = response.bodyText();
|
|
||||||
|
|
||||||
WxError error = WxError.fromJson(result);
|
|
||||||
if (error.getErrorCode() != 0) {
|
|
||||||
throw new WxErrorException(error);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
|
||||||
|
|
||||||
|
if (httpProxy != null) {
|
||||||
|
ProxyInfo proxyInfoObj = new ProxyInfo(
|
||||||
|
ProxyInfo.ProxyType.HTTP,
|
||||||
|
httpProxy.getHostName(),
|
||||||
|
httpProxy.getPort(), "", "");
|
||||||
|
provider.useProxy(proxyInfoObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequest request = HttpRequest.get(uri);
|
||||||
|
request.method("GET");
|
||||||
|
request.charset("UTF-8");
|
||||||
|
|
||||||
|
HttpResponse response = request.open(provider).send();
|
||||||
|
response.charset("UTF-8");
|
||||||
|
String result = response.bodyText();
|
||||||
|
|
||||||
|
WxError error = WxError.fromJson(result);
|
||||||
|
if (error.getErrorCode() != 0) {
|
||||||
|
throw new WxErrorException(error);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,33 +18,33 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class JoddPostRequestExecutor implements RequestExecutor<String, String> {
|
public class JoddPostRequestExecutor implements RequestExecutor<String, String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri,
|
public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri,
|
||||||
String postEntity) throws WxErrorException, IOException {
|
String postEntity) throws WxErrorException, IOException {
|
||||||
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
|
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
|
||||||
|
|
||||||
if (httpProxy != null) {
|
if (httpProxy != null) {
|
||||||
ProxyInfo proxyInfoObj = new ProxyInfo(
|
ProxyInfo proxyInfoObj = new ProxyInfo(
|
||||||
ProxyInfo.ProxyType.HTTP,
|
ProxyInfo.ProxyType.HTTP,
|
||||||
httpProxy.getAddress().getHostAddress(),
|
httpProxy.getAddress().getHostAddress(),
|
||||||
httpProxy.getPort(), "", "");
|
httpProxy.getPort(), "", "");
|
||||||
provider.useProxy(proxyInfoObj);
|
provider.useProxy(proxyInfoObj);
|
||||||
}
|
|
||||||
|
|
||||||
HttpRequest request = HttpRequest.get(uri);
|
|
||||||
request.method("POST");
|
|
||||||
request.charset("UTF-8");
|
|
||||||
request.bodyText(postEntity);
|
|
||||||
|
|
||||||
HttpResponse response = request.open(provider).send();
|
|
||||||
response.charset("UTF-8");
|
|
||||||
String result = response.bodyText();
|
|
||||||
|
|
||||||
WxError error = WxError.fromJson(result);
|
|
||||||
if (error.getErrorCode() != 0) {
|
|
||||||
throw new WxErrorException(error);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpRequest request = HttpRequest.get(uri);
|
||||||
|
request.method("POST");
|
||||||
|
request.charset("UTF-8");
|
||||||
|
request.bodyText(postEntity);
|
||||||
|
|
||||||
|
HttpResponse response = request.open(provider).send();
|
||||||
|
response.charset("UTF-8");
|
||||||
|
String result = response.bodyText();
|
||||||
|
|
||||||
|
WxError error = WxError.fromJson(result);
|
||||||
|
if (error.getErrorCode() != 0) {
|
||||||
|
throw new WxErrorException(error);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import me.chanjar.weixin.common.util.StringUtils;
|
|||||||
import me.chanjar.weixin.common.util.fs.FileUtils;
|
import me.chanjar.weixin.common.util.fs.FileUtils;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
@@ -21,8 +20,8 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载媒体文件请求执行器,请求的参数是String, 返回的结果是File
|
* 下载媒体文件请求执行器,请求的参数是String, 返回的结果是File
|
||||||
* @author Daniel Qian
|
|
||||||
*
|
*
|
||||||
|
* @author Daniel Qian
|
||||||
*/
|
*/
|
||||||
public class MediaDownloadRequestExecutor implements RequestExecutor<File, String> {
|
public class MediaDownloadRequestExecutor implements RequestExecutor<File, String> {
|
||||||
|
|
||||||
@@ -74,7 +73,7 @@ public class MediaDownloadRequestExecutor implements RequestExecutor<File, Strin
|
|||||||
File localFile = FileUtils.createTmpFile(inputStream, name_ext[0], name_ext[1], tmpDirFile);
|
File localFile = FileUtils.createTmpFile(inputStream, name_ext[0], name_ext[1], tmpDirFile);
|
||||||
return localFile;
|
return localFile;
|
||||||
|
|
||||||
}finally {
|
} finally {
|
||||||
httpGet.releaseConnection();
|
httpGet.releaseConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
|||||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
@@ -19,8 +18,8 @@ import java.io.IOException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传媒体文件请求执行器,请求的参数是File, 返回的结果是String
|
* 上传媒体文件请求执行器,请求的参数是File, 返回的结果是String
|
||||||
* @author Daniel Qian
|
|
||||||
*
|
*
|
||||||
|
* @author Daniel Qian
|
||||||
*/
|
*/
|
||||||
public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUploadResult, File> {
|
public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUploadResult, File> {
|
||||||
|
|
||||||
@@ -33,10 +32,10 @@ public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUpload
|
|||||||
}
|
}
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
HttpEntity entity = MultipartEntityBuilder
|
HttpEntity entity = MultipartEntityBuilder
|
||||||
.create()
|
.create()
|
||||||
.addBinaryBody("media", file)
|
.addBinaryBody("media", file)
|
||||||
.setMode(HttpMultipartMode.RFC6532)
|
.setMode(HttpMultipartMode.RFC6532)
|
||||||
.build();
|
.build();
|
||||||
httpPost.setEntity(entity);
|
httpPost.setEntity(entity);
|
||||||
httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString());
|
httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString());
|
||||||
}
|
}
|
||||||
@@ -47,7 +46,7 @@ public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUpload
|
|||||||
throw new WxErrorException(error);
|
throw new WxErrorException(error);
|
||||||
}
|
}
|
||||||
return WxMediaUploadResult.fromJson(responseContent);
|
return WxMediaUploadResult.fromJson(responseContent);
|
||||||
}finally {
|
} finally {
|
||||||
httpPost.releaseConnection();
|
httpPost.releaseConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package me.chanjar.weixin.common.util.http;
|
package me.chanjar.weixin.common.util.http;
|
||||||
|
|
||||||
import java.io.IOException;
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http请求执行器
|
* http请求执行器
|
||||||
@@ -17,11 +16,10 @@ import me.chanjar.weixin.common.exception.WxErrorException;
|
|||||||
public interface RequestExecutor<T, E> {
|
public interface RequestExecutor<T, E> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param httpclient 传入的httpClient
|
* @param httpclient 传入的httpClient
|
||||||
* @param httpProxy http代理对象,如果没有配置代理则为空
|
* @param httpProxy http代理对象,如果没有配置代理则为空
|
||||||
* @param uri uri
|
* @param uri uri
|
||||||
* @param data 数据
|
* @param data 数据
|
||||||
* @throws WxErrorException
|
* @throws WxErrorException
|
||||||
* @throws ClientProtocolException
|
* @throws ClientProtocolException
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package me.chanjar.weixin.common.util.http;
|
|||||||
import me.chanjar.weixin.common.bean.result.WxError;
|
import me.chanjar.weixin.common.bean.result.WxError;
|
||||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
@@ -13,8 +12,8 @@ import java.io.IOException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 简单的GET请求执行器,请求的参数是String, 返回的结果也是String
|
* 简单的GET请求执行器,请求的参数是String, 返回的结果也是String
|
||||||
* @author Daniel Qian
|
|
||||||
*
|
*
|
||||||
|
* @author Daniel Qian
|
||||||
*/
|
*/
|
||||||
public class SimpleGetRequestExecutor implements RequestExecutor<String, String> {
|
public class SimpleGetRequestExecutor implements RequestExecutor<String, String> {
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ public class SimpleGetRequestExecutor implements RequestExecutor<String, String>
|
|||||||
throw new WxErrorException(error);
|
throw new WxErrorException(error);
|
||||||
}
|
}
|
||||||
return responseContent;
|
return responseContent;
|
||||||
}finally {
|
} finally {
|
||||||
httpGet.releaseConnection();
|
httpGet.releaseConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import me.chanjar.weixin.common.bean.result.WxError;
|
|||||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
@@ -15,8 +14,8 @@ import java.io.IOException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 简单的POST请求执行器,请求的参数是String, 返回的结果也是String
|
* 简单的POST请求执行器,请求的参数是String, 返回的结果也是String
|
||||||
* @author Daniel Qian
|
|
||||||
*
|
*
|
||||||
|
* @author Daniel Qian
|
||||||
*/
|
*/
|
||||||
public class SimplePostRequestExecutor implements RequestExecutor<String, String> {
|
public class SimplePostRequestExecutor implements RequestExecutor<String, String> {
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ public class SimplePostRequestExecutor implements RequestExecutor<String, String
|
|||||||
throw new WxErrorException(error);
|
throw new WxErrorException(error);
|
||||||
}
|
}
|
||||||
return responseContent;
|
return responseContent;
|
||||||
}finally {
|
} finally {
|
||||||
httpPost.releaseConnection();
|
httpPost.releaseConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package me.chanjar.weixin.common.util.http;
|
package me.chanjar.weixin.common.util.http;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
@@ -10,10 +8,12 @@ import org.apache.http.client.HttpResponseException;
|
|||||||
import org.apache.http.client.ResponseHandler;
|
import org.apache.http.client.ResponseHandler;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* copy from {@link org.apache.http.impl.client.BasicResponseHandler}
|
* copy from {@link org.apache.http.impl.client.BasicResponseHandler}
|
||||||
* @author Daniel Qian
|
|
||||||
*
|
*
|
||||||
|
* @author Daniel Qian
|
||||||
*/
|
*/
|
||||||
public class Utf8ResponseHandler implements ResponseHandler<String> {
|
public class Utf8ResponseHandler implements ResponseHandler<String> {
|
||||||
|
|
||||||
|
|||||||
@@ -15,101 +15,101 @@ import com.google.gson.JsonObject;
|
|||||||
|
|
||||||
public class GsonHelper {
|
public class GsonHelper {
|
||||||
|
|
||||||
public static boolean isNull(JsonElement element) {
|
public static boolean isNull(JsonElement element) {
|
||||||
return element == null || element.isJsonNull();
|
return element == null || element.isJsonNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNotNull(JsonElement element) {
|
public static boolean isNotNull(JsonElement element) {
|
||||||
return !isNull(element);
|
return !isNull(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Long getLong(JsonObject json, String property) {
|
public static Long getLong(JsonObject json, String property) {
|
||||||
return getAsLong(json.get(property));
|
return getAsLong(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getPrimitiveLong(JsonObject json, String property) {
|
public static long getPrimitiveLong(JsonObject json, String property) {
|
||||||
return getAsPrimitiveLong(json.get(property));
|
return getAsPrimitiveLong(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Integer getInteger(JsonObject json, String property) {
|
public static Integer getInteger(JsonObject json, String property) {
|
||||||
return getAsInteger(json.get(property));
|
return getAsInteger(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getPrimitiveInteger(JsonObject json, String property) {
|
public static int getPrimitiveInteger(JsonObject json, String property) {
|
||||||
return getAsPrimitiveInt(json.get(property));
|
return getAsPrimitiveInt(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Double getDouble(JsonObject json, String property) {
|
public static Double getDouble(JsonObject json, String property) {
|
||||||
return getAsDouble(json.get(property));
|
return getAsDouble(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double getPrimitiveDouble(JsonObject json, String property) {
|
public static double getPrimitiveDouble(JsonObject json, String property) {
|
||||||
return getAsPrimitiveDouble(json.get(property));
|
return getAsPrimitiveDouble(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Float getFloat(JsonObject json, String property) {
|
public static Float getFloat(JsonObject json, String property) {
|
||||||
return getAsFloat(json.get(property));
|
return getAsFloat(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float getPrimitiveFloat(JsonObject json, String property) {
|
public static float getPrimitiveFloat(JsonObject json, String property) {
|
||||||
return getAsPrimitiveFloat(json.get(property));
|
return getAsPrimitiveFloat(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean getBoolean(JsonObject json, String property) {
|
public static Boolean getBoolean(JsonObject json, String property) {
|
||||||
return getAsBoolean(json.get(property));
|
return getAsBoolean(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getString(JsonObject json, String property) {
|
public static String getString(JsonObject json, String property) {
|
||||||
return getAsString(json.get(property));
|
return getAsString(json.get(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getAsString(JsonElement element) {
|
public static String getAsString(JsonElement element) {
|
||||||
return isNull(element) ? null : element.getAsString();
|
return isNull(element) ? null : element.getAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Long getAsLong(JsonElement element) {
|
public static Long getAsLong(JsonElement element) {
|
||||||
return isNull(element) ? null : element.getAsLong();
|
return isNull(element) ? null : element.getAsLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getAsPrimitiveLong(JsonElement element) {
|
public static long getAsPrimitiveLong(JsonElement element) {
|
||||||
Long r = getAsLong(element);
|
Long r = getAsLong(element);
|
||||||
return r == null ? 0l : r;
|
return r == null ? 0l : r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Integer getAsInteger(JsonElement element) {
|
public static Integer getAsInteger(JsonElement element) {
|
||||||
return isNull(element) ? null : element.getAsInt();
|
return isNull(element) ? null : element.getAsInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getAsPrimitiveInt(JsonElement element) {
|
public static int getAsPrimitiveInt(JsonElement element) {
|
||||||
Integer r = getAsInteger(element);
|
Integer r = getAsInteger(element);
|
||||||
return r == null ? 0 : r;
|
return r == null ? 0 : r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean getAsBoolean(JsonElement element) {
|
public static Boolean getAsBoolean(JsonElement element) {
|
||||||
return isNull(element) ? null : element.getAsBoolean();
|
return isNull(element) ? null : element.getAsBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean getAsPrimitiveBool(JsonElement element) {
|
public static boolean getAsPrimitiveBool(JsonElement element) {
|
||||||
Boolean r = getAsBoolean(element);
|
Boolean r = getAsBoolean(element);
|
||||||
return r != null && r.booleanValue();
|
return r != null && r.booleanValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Double getAsDouble(JsonElement element) {
|
public static Double getAsDouble(JsonElement element) {
|
||||||
return isNull(element) ? null : element.getAsDouble();
|
return isNull(element) ? null : element.getAsDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double getAsPrimitiveDouble(JsonElement element) {
|
public static double getAsPrimitiveDouble(JsonElement element) {
|
||||||
Double r = getAsDouble(element);
|
Double r = getAsDouble(element);
|
||||||
return r == null ? 0d : r;
|
return r == null ? 0d : r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Float getAsFloat(JsonElement element) {
|
public static Float getAsFloat(JsonElement element) {
|
||||||
return isNull(element) ? null : element.getAsFloat();
|
return isNull(element) ? null : element.getAsFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float getAsPrimitiveFloat(JsonElement element) {
|
public static float getAsPrimitiveFloat(JsonElement element) {
|
||||||
Float r = getAsFloat(element);
|
Float r = getAsFloat(element);
|
||||||
return r == null ? 0f : r;
|
return r == null ? 0f : r;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Daniel Qian
|
* @author Daniel Qian
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class WxAccessTokenAdapter implements JsonDeserializer<WxAccessToken> {
|
public class WxAccessTokenAdapter implements JsonDeserializer<WxAccessToken> {
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ import me.chanjar.weixin.common.bean.result.WxError;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Daniel Qian
|
* @author Daniel Qian
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class WxErrorAdapter implements JsonDeserializer<WxError> {
|
public class WxErrorAdapter implements JsonDeserializer<WxError> {
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ package me.chanjar.weixin.common.util.json;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||||
import me.chanjar.weixin.common.bean.WxMenu;
|
import me.chanjar.weixin.common.bean.WxMenu;
|
||||||
import me.chanjar.weixin.common.bean.result.WxError;
|
import me.chanjar.weixin.common.bean.result.WxError;
|
||||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
|
||||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||||
|
|
||||||
public class WxGsonBuilder {
|
public class WxGsonBuilder {
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Daniel Qian
|
* @author Daniel Qian
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class WxMediaUploadResultAdapter implements JsonDeserializer<WxMediaUploadResult> {
|
public class WxMediaUploadResultAdapter implements JsonDeserializer<WxMediaUploadResult> {
|
||||||
|
|
||||||
|
|||||||
@@ -8,22 +8,13 @@
|
|||||||
*/
|
*/
|
||||||
package me.chanjar.weixin.common.util.json;
|
package me.chanjar.weixin.common.util.json;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.*;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
|
||||||
import com.google.gson.JsonDeserializer;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParseException;
|
|
||||||
import com.google.gson.JsonSerializationContext;
|
|
||||||
import com.google.gson.JsonSerializer;
|
|
||||||
import me.chanjar.weixin.common.bean.WxMenu;
|
import me.chanjar.weixin.common.bean.WxMenu;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Daniel Qian
|
* @author Daniel Qian
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializer<WxMenu> {
|
public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializer<WxMenu> {
|
||||||
|
|
||||||
@@ -60,15 +51,15 @@ public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializ
|
|||||||
return buttonJson;
|
return buttonJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JsonObject convertToJson(WxMenu.WxMenuRule menuRule){
|
protected JsonObject convertToJson(WxMenu.WxMenuRule menuRule) {
|
||||||
JsonObject matchRule = new JsonObject();
|
JsonObject matchRule = new JsonObject();
|
||||||
matchRule.addProperty("tag_id",menuRule.getTagId());
|
matchRule.addProperty("tag_id", menuRule.getTagId());
|
||||||
matchRule.addProperty("sex",menuRule.getSex());
|
matchRule.addProperty("sex", menuRule.getSex());
|
||||||
matchRule.addProperty("country",menuRule.getCountry());
|
matchRule.addProperty("country", menuRule.getCountry());
|
||||||
matchRule.addProperty("province",menuRule.getProvince());
|
matchRule.addProperty("province", menuRule.getProvince());
|
||||||
matchRule.addProperty("city",menuRule.getCity());
|
matchRule.addProperty("city", menuRule.getCity());
|
||||||
matchRule.addProperty("client_platform_type",menuRule.getClientPlatformType());
|
matchRule.addProperty("client_platform_type", menuRule.getClientPlatformType());
|
||||||
matchRule.addProperty("language",menuRule.getLanguage());
|
matchRule.addProperty("language", menuRule.getLanguage());
|
||||||
return matchRule;
|
return matchRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,30 +18,24 @@
|
|||||||
package me.chanjar.weixin.common.util.res;
|
package me.chanjar.weixin.common.util.res;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.Enumeration;
|
import java.util.*;
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.MissingResourceException;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An internationalization / localization helper class which reduces
|
* An internationalization / localization helper class which reduces
|
||||||
* the bother of handling ResourceBundles and takes care of the
|
* the bother of handling ResourceBundles and takes care of the
|
||||||
* common cases of message formating which otherwise require the
|
* common cases of message formating which otherwise require the
|
||||||
* creation of Object arrays and such.
|
* creation of Object arrays and such.
|
||||||
*
|
* <p>
|
||||||
* <p>The StringManager operates on a package basis. One StringManager
|
* <p>The StringManager operates on a package basis. One StringManager
|
||||||
* per package can be created and accessed via the getManager method
|
* per package can be created and accessed via the getManager method
|
||||||
* call.
|
* call.
|
||||||
*
|
* <p>
|
||||||
* <p>The StringManager will look for a ResourceBundle named by
|
* <p>The StringManager will look for a ResourceBundle named by
|
||||||
* the package name given plus the suffix of "LocalStrings". In
|
* the package name given plus the suffix of "LocalStrings". In
|
||||||
* practice, this means that the localized information will be contained
|
* practice, this means that the localized information will be contained
|
||||||
* in a LocalStrings.properties file located in the package
|
* in a LocalStrings.properties file located in the package
|
||||||
* directory of the classpath.
|
* directory of the classpath.
|
||||||
*
|
* <p>
|
||||||
* <p>Please see the documentation for java.util.ResourceBundle for
|
* <p>Please see the documentation for java.util.ResourceBundle for
|
||||||
* more information.
|
* more information.
|
||||||
*
|
*
|
||||||
@@ -52,152 +46,80 @@ import java.util.ResourceBundle;
|
|||||||
*/
|
*/
|
||||||
public class StringManager {
|
public class StringManager {
|
||||||
|
|
||||||
private static int LOCALE_CACHE_SIZE = 10;
|
private static final Map<String, Map<Locale, StringManager>> managers =
|
||||||
|
new Hashtable<String, Map<Locale, StringManager>>();
|
||||||
|
private static int LOCALE_CACHE_SIZE = 10;
|
||||||
|
/**
|
||||||
|
* The ResourceBundle for this StringManager.
|
||||||
|
*/
|
||||||
|
private final ResourceBundle bundle;
|
||||||
|
private final Locale locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ResourceBundle for this StringManager.
|
* Creates a new StringManager for a given package. This is a
|
||||||
*/
|
* private method and all access to it is arbitrated by the
|
||||||
private final ResourceBundle bundle;
|
* static getManager method call so that only one StringManager
|
||||||
private final Locale locale;
|
* per package will be created.
|
||||||
|
*
|
||||||
/**
|
* @param packageName Name of package to create StringManager for.
|
||||||
* Creates a new StringManager for a given package. This is a
|
*/
|
||||||
* private method and all access to it is arbitrated by the
|
private StringManager(String packageName, Locale locale) {
|
||||||
* static getManager method call so that only one StringManager
|
String bundleName = packageName + ".LocalStrings";
|
||||||
* per package will be created.
|
ResourceBundle bnd = null;
|
||||||
*
|
try {
|
||||||
* @param packageName Name of package to create StringManager for.
|
bnd = ResourceBundle.getBundle(bundleName, locale);
|
||||||
*/
|
} catch (MissingResourceException ex) {
|
||||||
private StringManager(String packageName, Locale locale) {
|
// Try from the current loader (that's the case for trusted apps)
|
||||||
String bundleName = packageName + ".LocalStrings";
|
// Should only be required if using a TC5 style classloader structure
|
||||||
ResourceBundle bnd = null;
|
// where common != shared != server
|
||||||
|
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||||
|
if (cl != null) {
|
||||||
try {
|
try {
|
||||||
bnd = ResourceBundle.getBundle(bundleName, locale);
|
bnd = ResourceBundle.getBundle(bundleName, locale, cl);
|
||||||
} catch( MissingResourceException ex ) {
|
} catch (MissingResourceException ex2) {
|
||||||
// Try from the current loader (that's the case for trusted apps)
|
// Ignore
|
||||||
// Should only be required if using a TC5 style classloader structure
|
|
||||||
// where common != shared != server
|
|
||||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
|
||||||
if( cl != null ) {
|
|
||||||
try {
|
|
||||||
bnd = ResourceBundle.getBundle(bundleName, locale, cl);
|
|
||||||
} catch(MissingResourceException ex2) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bundle = bnd;
|
|
||||||
// Get the actual locale, which may be different from the requested one
|
|
||||||
if (bundle != null) {
|
|
||||||
Locale bundleLocale = bundle.getLocale();
|
|
||||||
if (bundleLocale.equals(Locale.ROOT)) {
|
|
||||||
this.locale = Locale.ENGLISH;
|
|
||||||
} else {
|
|
||||||
this.locale = bundleLocale;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.locale = null;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
bundle = bnd;
|
||||||
/**
|
// Get the actual locale, which may be different from the requested one
|
||||||
Get a string from the underlying resource bundle or return
|
if (bundle != null) {
|
||||||
null if the String is not found.
|
Locale bundleLocale = bundle.getLocale();
|
||||||
|
if (bundleLocale.equals(Locale.ROOT)) {
|
||||||
@param key to desired resource String
|
this.locale = Locale.ENGLISH;
|
||||||
@return resource String matching <i>key</i> from underlying
|
} else {
|
||||||
bundle or null if not found.
|
this.locale = bundleLocale;
|
||||||
@throws IllegalArgumentException if <i>key</i> is null.
|
}
|
||||||
*/
|
} else {
|
||||||
public String getString(String key) {
|
this.locale = null;
|
||||||
if(key == null){
|
|
||||||
String msg = "key may not have a null value";
|
|
||||||
|
|
||||||
throw new IllegalArgumentException(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
String str = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Avoid NPE if bundle is null and treat it like an MRE
|
|
||||||
if (bundle != null) {
|
|
||||||
str = bundle.getString(key);
|
|
||||||
}
|
|
||||||
} catch(MissingResourceException mre) {
|
|
||||||
//bad: shouldn't mask an exception the following way:
|
|
||||||
// str = "[cannot find message associated with key '" + key +
|
|
||||||
// "' due to " + mre + "]";
|
|
||||||
// because it hides the fact that the String was missing
|
|
||||||
// from the calling code.
|
|
||||||
//good: could just throw the exception (or wrap it in another)
|
|
||||||
// but that would probably cause much havoc on existing
|
|
||||||
// code.
|
|
||||||
//better: consistent with container pattern to
|
|
||||||
// simply return null. Calling code can then do
|
|
||||||
// a null check.
|
|
||||||
str = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a string from the underlying resource bundle and format
|
* Get the StringManager for a particular package. If a manager for
|
||||||
* it with the given set of arguments.
|
* a package already exists, it will be reused, else a new
|
||||||
*
|
* StringManager will be created and returned.
|
||||||
* @param key
|
*
|
||||||
* @param args
|
* @param packageName The package name
|
||||||
*/
|
*/
|
||||||
public String getString(final String key, final Object... args) {
|
public static final synchronized StringManager getManager(
|
||||||
String value = getString(key);
|
String packageName) {
|
||||||
if (value == null) {
|
return getManager(packageName, Locale.getDefault());
|
||||||
value = key;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
MessageFormat mf = new MessageFormat(value);
|
/**
|
||||||
mf.setLocale(locale);
|
* Get the StringManager for a particular package and Locale. If a manager
|
||||||
return mf.format(args, new StringBuffer(), null).toString();
|
* for a package/Locale combination already exists, it will be reused, else
|
||||||
}
|
* a new StringManager will be created and returned.
|
||||||
|
*
|
||||||
|
* @param packageName The package name
|
||||||
|
* @param locale The Locale
|
||||||
|
*/
|
||||||
|
public static final synchronized StringManager getManager(
|
||||||
|
String packageName, Locale locale) {
|
||||||
|
|
||||||
/**
|
Map<Locale, StringManager> map = managers.get(packageName);
|
||||||
* Identify the Locale this StringManager is associated with
|
if (map == null) {
|
||||||
*/
|
|
||||||
public Locale getLocale() {
|
|
||||||
return locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------
|
|
||||||
// STATIC SUPPORT METHODS
|
|
||||||
// --------------------------------------------------------------
|
|
||||||
|
|
||||||
private static final Map<String, Map<Locale,StringManager>> managers =
|
|
||||||
new Hashtable<String, Map<Locale,StringManager>>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the StringManager for a particular package. If a manager for
|
|
||||||
* a package already exists, it will be reused, else a new
|
|
||||||
* StringManager will be created and returned.
|
|
||||||
*
|
|
||||||
* @param packageName The package name
|
|
||||||
*/
|
|
||||||
public static final synchronized StringManager getManager(
|
|
||||||
String packageName) {
|
|
||||||
return getManager(packageName, Locale.getDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the StringManager for a particular package and Locale. If a manager
|
|
||||||
* for a package/Locale combination already exists, it will be reused, else
|
|
||||||
* a new StringManager will be created and returned.
|
|
||||||
*
|
|
||||||
* @param packageName The package name
|
|
||||||
* @param locale The Locale
|
|
||||||
*/
|
|
||||||
public static final synchronized StringManager getManager(
|
|
||||||
String packageName, Locale locale) {
|
|
||||||
|
|
||||||
Map<Locale,StringManager> map = managers.get(packageName);
|
|
||||||
if (map == null) {
|
|
||||||
/*
|
/*
|
||||||
* Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE.
|
* Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE.
|
||||||
* Expansion occurs when size() exceeds capacity. Therefore keep
|
* Expansion occurs when size() exceeds capacity. Therefore keep
|
||||||
@@ -206,43 +128,113 @@ public class StringManager {
|
|||||||
* for removal needs to use one less than the maximum desired size
|
* for removal needs to use one less than the maximum desired size
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
map = new LinkedHashMap<Locale,StringManager>(LOCALE_CACHE_SIZE, 1, true) {
|
map = new LinkedHashMap<Locale, StringManager>(LOCALE_CACHE_SIZE, 1, true) {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@Override
|
|
||||||
protected boolean removeEldestEntry(
|
|
||||||
Map.Entry<Locale,StringManager> eldest) {
|
|
||||||
return size() > (LOCALE_CACHE_SIZE - 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
managers.put(packageName, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringManager mgr = map.get(locale);
|
@Override
|
||||||
if (mgr == null) {
|
protected boolean removeEldestEntry(
|
||||||
mgr = new StringManager(packageName, locale);
|
Map.Entry<Locale, StringManager> eldest) {
|
||||||
map.put(locale, mgr);
|
return size() > (LOCALE_CACHE_SIZE - 1);
|
||||||
}
|
}
|
||||||
return mgr;
|
};
|
||||||
|
managers.put(packageName, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
StringManager mgr = map.get(locale);
|
||||||
* Retrieve the StringManager for a list of Locales. The first StringManager
|
if (mgr == null) {
|
||||||
* found will be returned.
|
mgr = new StringManager(packageName, locale);
|
||||||
*
|
map.put(locale, mgr);
|
||||||
* @param requestedLocales the list of Locales
|
|
||||||
*
|
|
||||||
* @return the found StringManager or the default StringManager
|
|
||||||
*/
|
|
||||||
public static StringManager getManager(String packageName,
|
|
||||||
Enumeration<Locale> requestedLocales) {
|
|
||||||
while (requestedLocales.hasMoreElements()) {
|
|
||||||
Locale locale = requestedLocales.nextElement();
|
|
||||||
StringManager result = getManager(packageName, locale);
|
|
||||||
if (result.getLocale().equals(locale)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Return the default
|
|
||||||
return getManager(packageName);
|
|
||||||
}
|
}
|
||||||
|
return mgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
// STATIC SUPPORT METHODS
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the StringManager for a list of Locales. The first StringManager
|
||||||
|
* found will be returned.
|
||||||
|
*
|
||||||
|
* @param requestedLocales the list of Locales
|
||||||
|
* @return the found StringManager or the default StringManager
|
||||||
|
*/
|
||||||
|
public static StringManager getManager(String packageName,
|
||||||
|
Enumeration<Locale> requestedLocales) {
|
||||||
|
while (requestedLocales.hasMoreElements()) {
|
||||||
|
Locale locale = requestedLocales.nextElement();
|
||||||
|
StringManager result = getManager(packageName, locale);
|
||||||
|
if (result.getLocale().equals(locale)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return the default
|
||||||
|
return getManager(packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string from the underlying resource bundle or return
|
||||||
|
* null if the String is not found.
|
||||||
|
*
|
||||||
|
* @param key to desired resource String
|
||||||
|
* @return resource String matching <i>key</i> from underlying
|
||||||
|
* bundle or null if not found.
|
||||||
|
* @throws IllegalArgumentException if <i>key</i> is null.
|
||||||
|
*/
|
||||||
|
public String getString(String key) {
|
||||||
|
if (key == null) {
|
||||||
|
String msg = "key may not have a null value";
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
String str = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Avoid NPE if bundle is null and treat it like an MRE
|
||||||
|
if (bundle != null) {
|
||||||
|
str = bundle.getString(key);
|
||||||
|
}
|
||||||
|
} catch (MissingResourceException mre) {
|
||||||
|
//bad: shouldn't mask an exception the following way:
|
||||||
|
// str = "[cannot find message associated with key '" + key +
|
||||||
|
// "' due to " + mre + "]";
|
||||||
|
// because it hides the fact that the String was missing
|
||||||
|
// from the calling code.
|
||||||
|
//good: could just throw the exception (or wrap it in another)
|
||||||
|
// but that would probably cause much havoc on existing
|
||||||
|
// code.
|
||||||
|
//better: consistent with container pattern to
|
||||||
|
// simply return null. Calling code can then do
|
||||||
|
// a null check.
|
||||||
|
str = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string from the underlying resource bundle and format
|
||||||
|
* it with the given set of arguments.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
public String getString(final String key, final Object... args) {
|
||||||
|
String value = getString(key);
|
||||||
|
if (value == null) {
|
||||||
|
value = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageFormat mf = new MessageFormat(value);
|
||||||
|
mf.setLocale(locale);
|
||||||
|
return mf.format(args, new StringBuffer(), null).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify the Locale this StringManager is associated with
|
||||||
|
*/
|
||||||
|
public Locale getLocale() {
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package me.chanjar.weixin.common.util.xml;
|
package me.chanjar.weixin.common.util.xml;
|
||||||
|
|
||||||
import java.io.Writer;
|
|
||||||
|
|
||||||
import com.thoughtworks.xstream.XStream;
|
import com.thoughtworks.xstream.XStream;
|
||||||
import com.thoughtworks.xstream.core.util.QuickWriter;
|
import com.thoughtworks.xstream.core.util.QuickWriter;
|
||||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||||
@@ -10,6 +8,8 @@ import com.thoughtworks.xstream.io.xml.XppDriver;
|
|||||||
import com.thoughtworks.xstream.security.NullPermission;
|
import com.thoughtworks.xstream.security.NullPermission;
|
||||||
import com.thoughtworks.xstream.security.PrimitiveTypePermission;
|
import com.thoughtworks.xstream.security.PrimitiveTypePermission;
|
||||||
|
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
public class XStreamInitializer {
|
public class XStreamInitializer {
|
||||||
|
|
||||||
public static XStream getInstance() {
|
public static XStream getInstance() {
|
||||||
@@ -22,6 +22,7 @@ public class XStreamInitializer {
|
|||||||
protected String SUFFIX_CDATA = "]]>";
|
protected String SUFFIX_CDATA = "]]>";
|
||||||
protected String PREFIX_MEDIA_ID = "<MediaId>";
|
protected String PREFIX_MEDIA_ID = "<MediaId>";
|
||||||
protected String SUFFIX_MEDIA_ID = "</MediaId>";
|
protected String SUFFIX_MEDIA_ID = "</MediaId>";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeText(QuickWriter writer, String text) {
|
protected void writeText(QuickWriter writer, String text) {
|
||||||
if (text.startsWith(PREFIX_CDATA) && text.endsWith(SUFFIX_CDATA)) {
|
if (text.startsWith(PREFIX_CDATA) && text.endsWith(SUFFIX_CDATA)) {
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import org.testng.annotations.Test;
|
|||||||
@Test
|
@Test
|
||||||
public class WxMenuTest {
|
public class WxMenuTest {
|
||||||
|
|
||||||
@Test(dataProvider="wxReturnMenu")
|
@Test(dataProvider = "wxReturnMenu")
|
||||||
public void testFromJson(String json) {
|
public void testFromJson(String json) {
|
||||||
WxMenu menu = WxMenu.fromJson(json);
|
WxMenu menu = WxMenu.fromJson(json);
|
||||||
Assert.assertEquals(menu.getButtons().size(), 3);
|
Assert.assertEquals(menu.getButtons().size(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dataProvider="wxPushMenu")
|
@Test(dataProvider = "wxPushMenu")
|
||||||
public void testToJson(String json) {
|
public void testToJson(String json) {
|
||||||
WxMenu menu = new WxMenu();
|
WxMenu menu = new WxMenu();
|
||||||
WxMenuButton button1 = new WxMenuButton();
|
WxMenuButton button1 = new WxMenuButton();
|
||||||
@@ -81,78 +81,78 @@ public class WxMenuTest {
|
|||||||
|
|
||||||
@DataProvider
|
@DataProvider
|
||||||
public Object[][] wxReturnMenu() {
|
public Object[][] wxReturnMenu() {
|
||||||
Object[][] res = menuJson();
|
Object[][] res = menuJson();
|
||||||
String json = "{ \"menu\" : " + res[0][0] + " }";
|
String json = "{ \"menu\" : " + res[0][0] + " }";
|
||||||
return new Object[][] {
|
return new Object[][]{
|
||||||
new Object[] { json }
|
new Object[]{json}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@DataProvider(name="wxPushMenu")
|
@DataProvider(name = "wxPushMenu")
|
||||||
public Object[][] menuJson() {
|
public Object[][] menuJson() {
|
||||||
String json =
|
String json =
|
||||||
"{"
|
"{"
|
||||||
+"\"button\":["
|
+ "\"button\":["
|
||||||
+"{"
|
+ "{"
|
||||||
+"\"type\":\"click\","
|
+ "\"type\":\"click\","
|
||||||
+"\"name\":\"今日歌曲\","
|
+ "\"name\":\"今日歌曲\","
|
||||||
+"\"key\":\"V1001_TODAY_MUSIC\""
|
+ "\"key\":\"V1001_TODAY_MUSIC\""
|
||||||
+"},"
|
+ "},"
|
||||||
+"{"
|
+ "{"
|
||||||
+"\"type\":\"click\","
|
+ "\"type\":\"click\","
|
||||||
+"\"name\":\"歌手简介\","
|
+ "\"name\":\"歌手简介\","
|
||||||
+"\"key\":\"V1001_TODAY_SINGER\""
|
+ "\"key\":\"V1001_TODAY_SINGER\""
|
||||||
+"},"
|
+ "},"
|
||||||
+"{"
|
+ "{"
|
||||||
+"\"name\":\"菜单\","
|
+ "\"name\":\"菜单\","
|
||||||
+"\"sub_button\":["
|
+ "\"sub_button\":["
|
||||||
+"{"
|
+ "{"
|
||||||
+"\"type\":\"view\","
|
+ "\"type\":\"view\","
|
||||||
+"\"name\":\"搜索\","
|
+ "\"name\":\"搜索\","
|
||||||
+"\"url\":\"http://www.soso.com/\""
|
+ "\"url\":\"http://www.soso.com/\""
|
||||||
+"},"
|
+ "},"
|
||||||
+"{"
|
+ "{"
|
||||||
+"\"type\":\"view\","
|
+ "\"type\":\"view\","
|
||||||
+"\"name\":\"视频\","
|
+ "\"name\":\"视频\","
|
||||||
+"\"url\":\"http://v.qq.com/\""
|
+ "\"url\":\"http://v.qq.com/\""
|
||||||
+"},"
|
+ "},"
|
||||||
+"{"
|
+ "{"
|
||||||
+"\"type\":\"click\","
|
+ "\"type\":\"click\","
|
||||||
+"\"name\":\"赞一下我们\","
|
+ "\"name\":\"赞一下我们\","
|
||||||
+"\"key\":\"V1001_GOOD\""
|
+ "\"key\":\"V1001_GOOD\""
|
||||||
+"}"
|
+ "}"
|
||||||
+"]"
|
+ "]"
|
||||||
+"}"
|
+ "}"
|
||||||
+"]"
|
+ "]"
|
||||||
+"}";
|
+ "}";
|
||||||
return new Object[][] {
|
return new Object[][]{
|
||||||
new Object[] { json }
|
new Object[]{json}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@DataProvider(name = "wxAddConditionalMenu")
|
@DataProvider(name = "wxAddConditionalMenu")
|
||||||
public Object[][] addConditionalMenuJson(){
|
public Object[][] addConditionalMenuJson() {
|
||||||
String json =
|
String json =
|
||||||
"{"
|
"{"
|
||||||
+"\"button\":["
|
+ "\"button\":["
|
||||||
+"{"
|
+ "{"
|
||||||
+"\"type\":\"click\","
|
+ "\"type\":\"click\","
|
||||||
+"\"name\":\"今日歌曲\","
|
+ "\"name\":\"今日歌曲\","
|
||||||
+"\"key\":\"V1001_TODAY_MUSIC\""
|
+ "\"key\":\"V1001_TODAY_MUSIC\""
|
||||||
+"}"
|
+ "}"
|
||||||
+"],"
|
+ "],"
|
||||||
+"\"matchrule\":{"
|
+ "\"matchrule\":{"
|
||||||
+"\"group_id\":\"2\","
|
+ "\"group_id\":\"2\","
|
||||||
+"\"sex\":\"1\","
|
+ "\"sex\":\"1\","
|
||||||
+"\"country\":\"中国\","
|
+ "\"country\":\"中国\","
|
||||||
+"\"province\":\"广东\","
|
+ "\"province\":\"广东\","
|
||||||
+"\"city\":\"广州\","
|
+ "\"city\":\"广州\","
|
||||||
+"\"client_platform_type\":\"2\","
|
+ "\"client_platform_type\":\"2\","
|
||||||
+"\"language\":\"zh_CN\""
|
+ "\"language\":\"zh_CN\""
|
||||||
+"}"
|
+ "}"
|
||||||
+"}";
|
+ "}";
|
||||||
return new Object[][]{
|
return new Object[][]{
|
||||||
new Object[]{json}
|
new Object[]{json}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ public class SessionTest {
|
|||||||
@DataProvider
|
@DataProvider
|
||||||
public Object[][] getSessionManager() {
|
public Object[][] getSessionManager() {
|
||||||
|
|
||||||
return new Object[][] {
|
return new Object[][]{
|
||||||
new Object[] { new StandardSessionManager() }
|
new Object[]{new StandardSessionManager()}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import org.testng.annotations.Test;
|
|||||||
public class WxMessageInMemoryDuplicateCheckerTest {
|
public class WxMessageInMemoryDuplicateCheckerTest {
|
||||||
|
|
||||||
public void test() throws InterruptedException {
|
public void test() throws InterruptedException {
|
||||||
Long[] msgIds = new Long[] { 1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l };
|
Long[] msgIds = new Long[]{1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l};
|
||||||
WxMessageInMemoryDuplicateChecker checker = new WxMessageInMemoryDuplicateChecker(2000l, 1000l);
|
WxMessageInMemoryDuplicateChecker checker = new WxMessageInMemoryDuplicateChecker(2000l, 1000l);
|
||||||
|
|
||||||
// 第一次检查
|
// 第一次检查
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class WxCryptUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testValidateSignatureError() throws ParserConfigurationException, SAXException,
|
public void testValidateSignatureError() throws ParserConfigurationException, SAXException,
|
||||||
IOException {
|
IOException {
|
||||||
try {
|
try {
|
||||||
WxCryptUtil pc = new WxCryptUtil(token, encodingAesKey, appId);
|
WxCryptUtil pc = new WxCryptUtil(token, encodingAesKey, appId);
|
||||||
String afterEncrpt = pc.encrypt(replyMsg);
|
String afterEncrpt = pc.encrypt(replyMsg);
|
||||||
|
|||||||
Reference in New Issue
Block a user