修复checkstyle检查出来的部分代码问题

This commit is contained in:
Binary Wang
2017-11-07 15:29:10 +08:00
parent 97d6f90ac4
commit 67abc9216f
21 changed files with 217 additions and 138 deletions

View File

@@ -40,7 +40,7 @@
<property name="allowNonPrintableEscapes" value="true"/> <property name="allowNonPrintableEscapes" value="true"/>
</module> </module>
<module name="LineLength"> <module name="LineLength">
<property name="max" value="100"/> <property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/> <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module> </module>
<module name="AvoidStarImport"/> <module name="AvoidStarImport"/>
@@ -52,7 +52,7 @@
</module> </module>
<module name="NeedBraces"/> <module name="NeedBraces"/>
<module name="LeftCurly"> <module name="LeftCurly">
<property name="maxLineLength" value="100"/> <property name="maxLineLength" value="120"/>
</module> </module>
<module name="RightCurly"> <module name="RightCurly">
<property name="id" value="RightCurlySame"/> <property name="id" value="RightCurlySame"/>

View File

@@ -4,13 +4,13 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* 微信开发所使用到的常量类 * 微信开发所使用到的常量类.
* *
* @author chanjarster & binarywang * @author chanjarster & binarywang
*/ */
public class WxConsts { public class WxConsts {
/** /**
* 微信推送过来的消息的类型和发送给微信xml格式消息的消息类型 * 微信推送过来的消息的类型和发送给微信xml格式消息的消息类型.
*/ */
public static class XmlMsgType { public static class XmlMsgType {
public static final String TEXT = "text"; public static final String TEXT = "text";
@@ -31,24 +31,57 @@ public class WxConsts {
} }
/** /**
* 主动发送消息(即客服消息)的消息类型 * 主动发送消息(即客服消息)的消息类型.
*/ */
public static class KefuMsgType { public static class KefuMsgType {
public static final String TEXT = "text";//文本消息 /**
public static final String IMAGE = "image";//图片消息 * 文本消息.
public static final String VOICE = "voice";//语音消息 */
public static final String VIDEO = "video";//视频消息 public static final String TEXT = "text";
public static final String MUSIC = "music";//音乐消息 /**
public static final String NEWS = "news";//图文消息(点击跳转到外链) * 图片消息.
public static final String MPNEWS = "mpnews";//图文消息(点击跳转到图文消息页面) */
public static final String FILE = "file";//发送文件CP专用 public static final String IMAGE = "image";
public static final String TEXTCARD = "textcard";//文本卡片消息CP专用 /**
public static final String WXCARD = "wxcard";//卡券消息 * 语音消息.
*/
public static final String VOICE = "voice";
/**
* 视频消息.
*/
public static final String VIDEO = "video";
/**
* 音乐消息.
*/
public static final String MUSIC = "music";
/**
* 图文消息(点击跳转到外链).
*/
public static final String NEWS = "news";
/**
* 图文消息(点击跳转到图文消息页面).
*/
public static final String MPNEWS = "mpnews";
/**
* 发送文件CP专用.
*/
public static final String FILE = "file";
/**
* 文本卡片消息CP专用.
*/
public static final String TEXTCARD = "textcard";
/**
* 卡券消息.
*/
public static final String WXCARD = "wxcard";
/**
* 转发到客服的消息.
*/
public static final String TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; public static final String TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";
} }
/** /**
* 表示是否是保密消息0表示否1表示是默认0 * 表示是否是保密消息0表示否1表示是默认0.
*/ */
public static class KefuMsgSafe { public static class KefuMsgSafe {
public static final String NO = "0"; public static final String NO = "0";
@@ -56,7 +89,7 @@ public class WxConsts {
} }
/** /**
* 群发消息的消息类型 * 群发消息的消息类型.
*/ */
public static class MassMsgType { public static class MassMsgType {
public static final String MPNEWS = "mpnews"; public static final String MPNEWS = "mpnews";
@@ -67,7 +100,7 @@ public class WxConsts {
} }
/** /**
* 群发消息后微信端推送给服务器的反馈消息 * 群发消息后微信端推送给服务器的反馈消息.
*/ */
public static class MassMsgStatus { public static class MassMsgStatus {
public static final String SEND_SUCCESS = "send success"; public static final String SEND_SUCCESS = "send success";
@@ -83,7 +116,7 @@ public class WxConsts {
public static final String ERR_21000 = "err(21000)"; public static final String ERR_21000 = "err(21000)";
/** /**
* 群发反馈消息代码所对应的文字描述 * 群发反馈消息代码所对应的文字描述.
*/ */
public static final Map<String, String> STATUS_DESC = new HashMap<>(); public static final Map<String, String> STATUS_DESC = new HashMap<>();
@@ -103,7 +136,7 @@ public class WxConsts {
} }
/** /**
* 微信端推送过来的事件类型 * 微信端推送过来的事件类型.
*/ */
public static class EventType { public static class EventType {
public static final String SUBSCRIBE = "subscribe"; public static final String SUBSCRIBE = "subscribe";
@@ -124,7 +157,7 @@ public class WxConsts {
} }
/** /**
* 上传多媒体(临时素材)文件的类型 * 上传多媒体(临时素材)文件的类型.
*/ */
public static class MediaFileType { public static class MediaFileType {
public static final String IMAGE = "image"; public static final String IMAGE = "image";
@@ -135,78 +168,78 @@ public class WxConsts {
} }
/** /**
* 自定义菜单的按钮类型 * 自定义菜单的按钮类型.
*/ */
public static class MenuButtonType { public static class MenuButtonType {
/** /**
* 点击推事件 * 点击推事件.
*/ */
public static final String CLICK = "click"; public static final String CLICK = "click";
/** /**
* 跳转URL * 跳转URL.
*/ */
public static final String VIEW = "view"; public static final String VIEW = "view";
/** /**
* 跳转到小程序 * 跳转到小程序.
*/ */
public static final String MINIPROGRAM = "miniprogram"; public static final String MINIPROGRAM = "miniprogram";
/** /**
* 扫码推事件 * 扫码推事件.
*/ */
public static final String SCANCODE_PUSH = "scancode_push"; public static final String SCANCODE_PUSH = "scancode_push";
/** /**
* 扫码推事件且弹出“消息接收中”提示框 * 扫码推事件且弹出“消息接收中”提示框.
*/ */
public static final String SCANCODE_WAITMSG = "scancode_waitmsg"; public static final String SCANCODE_WAITMSG = "scancode_waitmsg";
/** /**
* 弹出系统拍照发图 * 弹出系统拍照发图.
*/ */
public static final String PIC_SYSPHOTO = "pic_sysphoto"; public static final String PIC_SYSPHOTO = "pic_sysphoto";
/** /**
* 弹出拍照或者相册发图 * 弹出拍照或者相册发图.
*/ */
public static final String PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"; public static final String PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
/** /**
* 弹出微信相册发图器 * 弹出微信相册发图器.
*/ */
public static final String PIC_WEIXIN = "pic_weixin"; public static final String PIC_WEIXIN = "pic_weixin";
/** /**
* 弹出地理位置选择器 * 弹出地理位置选择器.
*/ */
public static final String LOCATION_SELECT = "location_select"; public static final String LOCATION_SELECT = "location_select";
/** /**
* 下发消息(除文本消息) * 下发消息(除文本消息).
*/ */
public static final String MEDIA_ID = "media_id"; public static final String MEDIA_ID = "media_id";
/** /**
* 跳转图文消息URL * 跳转图文消息URL.
*/ */
public static final String VIEW_LIMITED = "view_limited"; public static final String VIEW_LIMITED = "view_limited";
} }
/** /**
* oauth2网页授权的scope * oauth2网页授权的scope.
*/ */
public static class OAuth2Scope { public static class OAuth2Scope {
/** /**
* 不弹出授权页面直接跳转只能获取用户openid * 不弹出授权页面直接跳转只能获取用户openid.
*/ */
public static final String SNSAPI_BASE = "snsapi_base"; public static final String SNSAPI_BASE = "snsapi_base";
/** /**
* 弹出授权页面可通过openid拿到昵称、性别、所在地。并且即使在未关注的情况下只要用户授权也能获取其信息 * 弹出授权页面可通过openid拿到昵称、性别、所在地。并且即使在未关注的情况下只要用户授权也能获取其信息.
*/ */
public static final String SNSAPI_USERINFO = "snsapi_userinfo"; public static final String SNSAPI_USERINFO = "snsapi_userinfo";
} }
/** /**
* 网页应用登录授权作用域 * 网页应用登录授权作用域.
*/ */
public static class QrConnectScope { public static class QrConnectScope {
public static final String SNSAPI_LOGIN = "snsapi_login"; public static final String SNSAPI_LOGIN = "snsapi_login";
} }
/** /**
* 永久素材类型 * 永久素材类型.
*/ */
public static class MaterialType { public static class MaterialType {
public static final String NEWS = "news"; public static final String NEWS = "news";

View File

@@ -3,7 +3,7 @@ package me.chanjar.weixin.common.api;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
/** /**
* WxErrorException处理器 * WxErrorException处理器.
*/ */
public interface WxErrorExceptionHandler { public interface WxErrorExceptionHandler {

View File

@@ -2,22 +2,21 @@ package me.chanjar.weixin.common.api;
/** /**
* <pre> * <pre>
* 消息重复检查器 * 消息重复检查器.
* 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次
* </pre> * </pre>
*/ */
public interface WxMessageDuplicateChecker { 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>
* 官方文档完全没有写,参照公众号的方式排重。
* <p>
* <p>或者可以采取更简单的方式如果有MsgId就用MsgId排重如果没有就用FromUserName+CreateTime排重</p> * <p>或者可以采取更简单的方式如果有MsgId就用MsgId排重如果没有就用FromUserName+CreateTime排重</p>
* *
* @param messageId messageId需要根据上面讲的方式构造 * @param messageId messageId需要根据上面讲的方式构造

View File

@@ -6,46 +6,46 @@ import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* <pre> * <pre>
* 默认消息重复检查器 * 默认消息重复检查器.
* 将每个消息id保存在内存里每隔5秒清理已经过期的消息id每个消息id的过期时间是15秒 * 将每个消息id保存在内存里每隔5秒清理已经过期的消息id每个消息id的过期时间是15秒
* </pre> * </pre>
*/ */
public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChecker { public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChecker {
/** /**
* 一个消息ID在内存的过期时间15秒 * 一个消息ID在内存的过期时间15秒.
*/ */
private final Long timeToLive; private final Long timeToLive;
/** /**
* 每隔多少周期检查消息ID是否过期5秒 * 每隔多少周期检查消息ID是否过期5秒.
*/ */
private final Long clearPeriod; private final Long clearPeriod;
/** /**
* 消息id->消息时间戳的map * 消息id->消息时间戳的map.
*/ */
private final ConcurrentHashMap<String, Long> msgId2Timestamp = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, Long> msgId2Timestamp = new ConcurrentHashMap<>();
/** /**
* 后台清理线程是否已经开启 * 后台清理线程是否已经开启.
*/ */
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false); private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
/** /**
* WxMsgIdInMemoryDuplicateChecker构造函数 * 无参构造方法.
* <pre> * <pre>
* 一个消息ID在内存的过期时间15秒 * 一个消息ID在内存的过期时间15秒
* 每隔多少周期检查消息ID是否过期5秒 * 每隔多少周期检查消息ID是否过期5秒
* </pre> * </pre>
*/ */
public WxMessageInMemoryDuplicateChecker() { public WxMessageInMemoryDuplicateChecker() {
this.timeToLive = 15 * 1000l; this.timeToLive = 15 * 1000L;
this.clearPeriod = 5 * 1000l; this.clearPeriod = 5 * 1000L;
} }
/** /**
* WxMsgIdInMemoryDuplicateChecker构造函数 * 构造方法.
* *
* @param timeToLive 一个消息ID在内存的过期时间毫秒 * @param timeToLive 一个消息ID在内存的过期时间毫秒
* @param clearPeriod 每隔多少周期检查消息ID是否过期毫秒 * @param clearPeriod 每隔多少周期检查消息ID是否过期毫秒
@@ -66,7 +66,8 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec
while (true) { while (true) {
Thread.sleep(WxMessageInMemoryDuplicateChecker.this.clearPeriod); Thread.sleep(WxMessageInMemoryDuplicateChecker.this.clearPeriod);
Long now = System.currentTimeMillis(); Long now = System.currentTimeMillis();
for (Map.Entry<String, Long> entry : WxMessageInMemoryDuplicateChecker.this.msgId2Timestamp.entrySet()) { for (Map.Entry<String, Long> entry :
WxMessageInMemoryDuplicateChecker.this.msgId2Timestamp.entrySet()) {
if (now - entry.getValue() > WxMessageInMemoryDuplicateChecker.this.timeToLive) { if (now - entry.getValue() > WxMessageInMemoryDuplicateChecker.this.timeToLive) {
WxMessageInMemoryDuplicateChecker.this.msgId2Timestamp.entrySet().remove(entry); WxMessageInMemoryDuplicateChecker.this.msgId2Timestamp.entrySet().remove(entry);
} }

View File

@@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* 菜单(公众号和企业号共用的) * 菜单(公众号和企业号共用的).
* *
* @author Daniel Qian * @author Daniel Qian
*/ */
@@ -36,7 +36,8 @@ public class WxMenu implements Serializable {
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式外层多套了一个menu * 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式外层多套了一个menu
*/ */
public static WxMenu fromJson(InputStream is) { public static WxMenu fromJson(InputStream is) {
return WxGsonBuilder.create().fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), WxMenu.class); return WxGsonBuilder.create()
.fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), WxMenu.class);
} }
public List<WxMenuButton> getButtons() { public List<WxMenuButton> getButtons() {

View File

@@ -12,7 +12,7 @@ public class WxMenuButton implements Serializable {
/** /**
* <pre> * <pre>
* 菜单的响应动作类型 * 菜单的响应动作类型.
* view表示网页类型 * view表示网页类型
* click表示点击类型 * click表示点击类型
* miniprogram表示小程序类型 * miniprogram表示小程序类型
@@ -21,13 +21,13 @@ public class WxMenuButton implements Serializable {
private String type; private String type;
/** /**
* 菜单标题不超过16个字节子菜单不超过60个字节 * 菜单标题不超过16个字节子菜单不超过60个字节.
*/ */
private String name; private String name;
/** /**
* <pre> * <pre>
* 菜单KEY值用于消息接口推送不超过128字节 * 菜单KEY值用于消息接口推送不超过128字节.
* click等点击类型必须 * click等点击类型必须
* </pre> * </pre>
*/ */
@@ -35,7 +35,8 @@ public class WxMenuButton implements Serializable {
/** /**
* <pre> * <pre>
* 网页链接用户点击菜单可打开链接不超过1024字节。type为miniprogram时不支持小程序的老版本客户端将打开本url。 * 网页链接.
* 用户点击菜单可打开链接不超过1024字节。type为miniprogram时不支持小程序的老版本客户端将打开本url。
* view、miniprogram类型必须 * view、miniprogram类型必须
* </pre> * </pre>
*/ */
@@ -43,7 +44,7 @@ public class WxMenuButton implements Serializable {
/** /**
* <pre> * <pre>
* 调用新增永久素材接口返回的合法media_id * 调用新增永久素材接口返回的合法media_id.
* media_id类型和view_limited类型必须 * media_id类型和view_limited类型必须
* </pre> * </pre>
*/ */
@@ -52,7 +53,7 @@ public class WxMenuButton implements Serializable {
/** /**
* <pre> * <pre>
* 小程序的appid * 小程序的appid.
* miniprogram类型必须 * miniprogram类型必须
* </pre> * </pre>
*/ */
@@ -61,7 +62,7 @@ public class WxMenuButton implements Serializable {
/** /**
* <pre> * <pre>
* 小程序的页面路径 * 小程序的页面路径.
* miniprogram类型必须 * miniprogram类型必须
* </pre> * </pre>
*/ */

View File

@@ -9,7 +9,7 @@ public class WxMenuRule implements Serializable {
private static final long serialVersionUID = -4587181819499286670L; private static final long serialVersionUID = -4587181819499286670L;
/** /**
* 变态的微信接口,反序列化时这里反人类的使用和序列化时不一样的名字 * 变态的微信接口,反序列化时这里反人类的使用和序列化时不一样的名字.
*/ */
@SerializedName(value = "tag_id", alternate = "group_id") @SerializedName(value = "tag_id", alternate = "group_id")
private String tagId; private String tagId;

View File

@@ -5,7 +5,7 @@ import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable; 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
*/ */
@@ -73,6 +73,9 @@ 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);

View File

@@ -4,51 +4,41 @@ import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
/** /**
* httpclient build interface * httpclient build interface.
* *
* @author kakotor * @author kakotor
*/ */
public interface ApacheHttpClientBuilder { public interface ApacheHttpClientBuilder {
/** /**
* 构建httpclient实例 * 构建httpclient实例.
* *
* @return new instance of CloseableHttpClient * @return new instance of CloseableHttpClient
*/ */
CloseableHttpClient build(); CloseableHttpClient build();
/** /**
* 代理服务器地址 * 代理服务器地址.
*
* @param httpProxyHost
*/ */
ApacheHttpClientBuilder httpProxyHost(String httpProxyHost); ApacheHttpClientBuilder httpProxyHost(String httpProxyHost);
/** /**
* 代理服务器端口 * 代理服务器端口.
*
* @param httpProxyPort
*/ */
ApacheHttpClientBuilder httpProxyPort(int httpProxyPort); ApacheHttpClientBuilder httpProxyPort(int httpProxyPort);
/** /**
* 代理服务器用户名 * 代理服务器用户名.
*
* @param httpProxyUsername
*/ */
ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername); ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername);
/** /**
* 代理服务器密码 * 代理服务器密码.
*
* @param httpProxyPassword
*/ */
ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword); ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword);
/** /**
* ssl连接socket工厂 * ssl连接socket工厂.
*
* @param sslConnectionSocketFactory
*/ */
ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory); ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory);
} }

View File

@@ -29,9 +29,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* httpclient 连接管理器 自带DNS解析 * httpclient 连接管理器 自带DNS解析.
* <p> * <p>大部分代码拷贝自DefaultApacheHttpClientBuilder</p>
* 大部分代码拷贝自DefaultApacheHttpClientBuilder
* *
* @author Andy.Huo * @author Andy.Huo
*/ */
@@ -64,7 +63,7 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
private String httpProxyPassword; private String httpProxyPassword;
/** /**
* 闲置连接监控线程 * 闲置连接监控线程.
*/ */
private IdleConnectionMonitorThread idleConnectionMonitorThread; private IdleConnectionMonitorThread idleConnectionMonitorThread;
private HttpClientBuilder httpClientBuilder; private HttpClientBuilder httpClientBuilder;
@@ -162,7 +161,7 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
} }
/** /**
* 每路的最大链接数,默认10 * 每路的最大链接数,默认10.
* *
* @param maxConnPerHost 每路的最大链接数,默认10 * @param maxConnPerHost 每路的最大链接数,默认10
*/ */
@@ -171,7 +170,7 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
} }
/** /**
* 最大总连接数,默认50 * 最大总连接数,默认50.
* *
* @param maxTotalConn 最大总连接数,默认50 * @param maxTotalConn 最大总连接数,默认50
*/ */
@@ -180,7 +179,7 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
} }
/** /**
* 自定义httpclient的User Agent * 自定义httpclient的User Agent.
* *
* @param userAgent User Agent * @param userAgent User Agent
*/ */
@@ -196,9 +195,12 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
if (prepared.get()) { if (prepared.get()) {
return; return;
} }
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", this.plainConnectionSocketFactory).register("https", this.sslConnectionSocketFactory) Registry<ConnectionSocketFactory> registry =
.build(); RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", this.plainConnectionSocketFactory)
.register("https", this.sslConnectionSocketFactory)
.build();
@SuppressWarnings("resource") @SuppressWarnings("resource")
PoolingHttpClientConnectionManager connectionManager; PoolingHttpClientConnectionManager connectionManager;
@@ -219,8 +221,8 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
connectionManager connectionManager
.setDefaultSocketConfig(SocketConfig.copy(SocketConfig.DEFAULT).setSoTimeout(this.soTimeout).build()); .setDefaultSocketConfig(SocketConfig.copy(SocketConfig.DEFAULT).setSoTimeout(this.soTimeout).build());
this.idleConnectionMonitorThread = new IdleConnectionMonitorThread(connectionManager, this.idleConnTimeout, this.idleConnectionMonitorThread = new IdleConnectionMonitorThread(
this.checkWaitTime); connectionManager, this.idleConnTimeout, this.checkWaitTime);
this.idleConnectionMonitorThread.setDaemon(true); this.idleConnectionMonitorThread.setDaemon(true);
this.idleConnectionMonitorThread.start(); this.idleConnectionMonitorThread.start();
@@ -234,8 +236,8 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
if (StringUtils.isNotBlank(this.httpProxyHost) && StringUtils.isNotBlank(this.httpProxyUsername)) { if (StringUtils.isNotBlank(this.httpProxyHost) && StringUtils.isNotBlank(this.httpProxyUsername)) {
// 使用代理服务器 需要用户认证的代理服务器 // 使用代理服务器 需要用户认证的代理服务器
CredentialsProvider provider = new BasicCredentialsProvider(); CredentialsProvider provider = new BasicCredentialsProvider();
provider.setCredentials(new AuthScope(this.httpProxyHost, this.httpProxyPort), provider.setCredentials(new AuthScope(this.httpProxyHost, this.httpProxyPort)
new UsernamePasswordCredentials(this.httpProxyUsername, this.httpProxyPassword)); , new UsernamePasswordCredentials(this.httpProxyUsername, this.httpProxyPassword));
this.httpClientBuilder.setDefaultCredentialsProvider(provider); this.httpClientBuilder.setDefaultCredentialsProvider(provider);
} }
@@ -267,8 +269,10 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
private final int checkWaitTime; private final int checkWaitTime;
private volatile boolean shutdown; private volatile boolean shutdown;
public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr, int idleConnTimeout, /**
int checkWaitTime) { * 构造方法.
*/
public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr, int idleConnTimeout, int checkWaitTime) {
super("IdleConnectionMonitorThread"); super("IdleConnectionMonitorThread");
this.connMgr = connMgr; this.connMgr = connMgr;
this.idleConnTimeout = idleConnTimeout; this.idleConnTimeout = idleConnTimeout;
@@ -289,12 +293,18 @@ public class ApacheHttpDnsClientBuilder implements ApacheHttpClientBuilder {
} }
} }
/**
* 触发.
*/
public void trigger() { public void trigger() {
synchronized (this) { synchronized (this) {
notifyAll(); notifyAll();
} }
} }
/**
* 关闭.
*/
public void shutdown() { public void shutdown() {
this.shutdown = true; this.shutdown = true;
synchronized (this) { synchronized (this) {

View File

@@ -2,8 +2,8 @@ package me.chanjar.weixin.common.util.http.okhttp;
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 me.chanjar.weixin.common.util.http.HttpResponseProxy;
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;
import me.chanjar.weixin.common.util.http.HttpResponseProxy;
import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.RequestHttp;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;

View File

@@ -28,7 +28,7 @@ public class XStreamTransformer {
} }
/** /**
* 注册扩展消息的解析器 * 注册扩展消息的解析器.
* *
* @param clz 类型 * @param clz 类型
* @param xStream xml解析器 * @param xStream xml解析器

View File

@@ -3,7 +3,7 @@ package cn.binarywang.wx.miniapp.bean;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
/** /**
* 微信二维码(小程序码)包装器 * 微信二维码(小程序码)包装器.
* *
* @author Element * @author Element
*/ */

View File

@@ -15,6 +15,9 @@ public class BaseBuilder<T> {
return (T) this; return (T) this;
} }
/**
* 构造器方法.
*/
public WxMaKefuMessage build() { public WxMaKefuMessage build() {
WxMaKefuMessage m = new WxMaKefuMessage(); WxMaKefuMessage m = new WxMaKefuMessage();
m.setMsgType(this.msgType); m.setMsgType(this.msgType);

View File

@@ -36,11 +36,9 @@ public class QrCodeRequestExecutor implements RequestExecutor<File, AbstractWxMa
public File execute(String uri, AbstractWxMaQrcodeWrapper ticket) throws WxErrorException, IOException { public File execute(String uri, AbstractWxMaQrcodeWrapper ticket) throws WxErrorException, IOException {
HttpPost httpPost = new HttpPost(uri); HttpPost httpPost = new HttpPost(uri);
if (requestHttp.getRequestHttpProxy() != null) { if (requestHttp.getRequestHttpProxy() != null) {
httpPost httpPost.setConfig(
.setConfig(RequestConfig.custom() RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build()
.setProxy(requestHttp.getRequestHttpProxy()) );
.build()
);
} }
httpPost.setEntity(new StringEntity(ticket.toString())); httpPost.setEntity(new StringEntity(ticket.toString()));
@@ -48,8 +46,8 @@ public class QrCodeRequestExecutor implements RequestExecutor<File, AbstractWxMa
InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);) { InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);) {
Header[] contentTypeHeader = response.getHeaders("Content-Type"); Header[] contentTypeHeader = response.getHeaders("Content-Type");
if (contentTypeHeader != null && contentTypeHeader.length > 0 if (contentTypeHeader != null && contentTypeHeader.length > 0
&& ContentType.APPLICATION_JSON.getMimeType() && ContentType.APPLICATION_JSON.getMimeType()
.equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) { .equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) {
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
throw new WxErrorException(WxError.fromJson(responseContent)); throw new WxErrorException(WxError.fromJson(responseContent));
} }

View File

@@ -18,7 +18,7 @@ public class XStreamTransformer {
} }
/** /**
* xml -> pojo * xml -> pojo.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, String xml) { public static <T> T fromXml(Class<T> clazz, String xml) {
@@ -33,14 +33,14 @@ public class XStreamTransformer {
} }
/** /**
* pojo -> xml * pojo -> xml.
*/ */
public static <T> String toXml(Class<T> clazz, T object) { public static <T> String toXml(Class<T> clazz, T object) {
return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object); return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object);
} }
/** /**
* 注册扩展消息的解析器 * 注册扩展消息的解析器.
* *
* @param clz 类型 * @param clz 类型
* @param xStream xml解析器 * @param xStream xml解析器
@@ -50,7 +50,7 @@ public class XStreamTransformer {
} }
/** /**
* 会自动注册该类及其子类 * 会自动注册该类及其子类.
* *
* @param clz 要注册的类 * @param clz 要注册的类
*/ */

View File

@@ -5,6 +5,8 @@ import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable; import java.io.Serializable;
/** /**
* 设备抽象类.
*
* @author keungtung * @author keungtung
* @date 14/12/2016 * @date 14/12/2016
*/ */

View File

@@ -22,9 +22,13 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* Created by ecoolper on 2017/5/5. * httpclient 实现的素材请求执行器.
*
* @author ecoolper
* @date 2017/5/5
*/ */
public class ApacheMaterialNewsInfoRequestExecutor extends MaterialNewsInfoRequestExecutor<CloseableHttpClient, HttpHost> { public class ApacheMaterialNewsInfoRequestExecutor
extends MaterialNewsInfoRequestExecutor<CloseableHttpClient, HttpHost> {
private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final Logger logger = LoggerFactory.getLogger(this.getClass());
public ApacheMaterialNewsInfoRequestExecutor(RequestHttp requestHttp) { public ApacheMaterialNewsInfoRequestExecutor(RequestHttp requestHttp) {

View File

@@ -19,16 +19,17 @@ import java.util.TreeMap;
/** /**
* <pre> * <pre>
* 签名相关工具类 * 签名相关工具类.
* Created by Binary Wang on 2017-3-23. * Created by Binary Wang on 2017-3-23.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre> * </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/ */
public class SignUtils { public class SignUtils {
private static final Logger log = LoggerFactory.getLogger(SignUtils.class); private static final Logger log = LoggerFactory.getLogger(SignUtils.class);
/** /**
* 请参考并使用 {@link #createSign(Object, String, String, boolean)} * 请参考并使用 {@link #createSign(Object, String, String, boolean)}.
*/ */
@Deprecated @Deprecated
public static String createSign(Object xmlBean, String signKey) { public static String createSign(Object xmlBean, String signKey) {
@@ -36,7 +37,7 @@ public class SignUtils {
} }
/** /**
* 请参考并使用 {@link #createSign(Map, String, String, boolean)} * 请参考并使用 {@link #createSign(Map, String, String, boolean)}.
*/ */
@Deprecated @Deprecated
public static String createSign(Map<String, String> params, String signKey) { public static String createSign(Map<String, String> params, String signKey) {
@@ -44,7 +45,7 @@ public class SignUtils {
} }
/** /**
* 微信支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) * 微信支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3).
* *
* @param xmlBean Bean里的属性如果存在XML注解则使用其作为key否则使用变量名 * @param xmlBean Bean里的属性如果存在XML注解则使用其作为key否则使用变量名
* @param signType 签名类型如果为空则默认为MD5 * @param signType 签名类型如果为空则默认为MD5
@@ -57,27 +58,25 @@ public class SignUtils {
} }
/** /**
* 微信支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) * 微信支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3).
* *
* @param params 参数信息 * @param params 参数信息
* @param signType 签名类型如果为空则默认为MD5 * @param signType 签名类型如果为空则默认为MD5
* @param signKey 签名Key * @param signKey 签名Key
* @param isIgnoreSignType 签名时是否忽略signType * @param ignoreSignType 签名时是否忽略signType
* @return 签名字符串 * @return 签名字符串
*/ */
public static String createSign(Map<String, String> params, String signType, String signKey, boolean isIgnoreSignType) { public static String createSign(Map<String, String> params, String signType, String signKey, boolean ignoreSignType) {
SortedMap<String, String> sortedMap = new TreeMap<>(params); SortedMap<String, String> sortedMap = new TreeMap<>(params);
StringBuilder toSign = new StringBuilder(); StringBuilder toSign = new StringBuilder();
for (String key : sortedMap.keySet()) { for (String key : sortedMap.keySet()) {
String value = params.get(key); String value = params.get(key);
boolean shouldSign = false; boolean shouldSign = false;
if (isIgnoreSignType && "sign_type".equals(key)) { if (ignoreSignType && "sign_type".equals(key)) {
shouldSign = false; shouldSign = false;
} else if (StringUtils.isNotEmpty(value) } else if (StringUtils.isNotEmpty(value)
&& !Lists.newArrayList( && !Lists.newArrayList("sign", "key", "xmlString", "xmlDoc", "couponList").contains(key)) {
"sign", "key", "xmlString", "xmlDoc", "couponList").contains(key)
) {
shouldSign = true; shouldSign = true;
} }
@@ -88,18 +87,18 @@ public class SignUtils {
toSign.append("key=").append(signKey); toSign.append("key=").append(signKey);
if (SignType.HMAC_SHA256.equals(signType)) { if (SignType.HMAC_SHA256.equals(signType)) {
return createHMACSha256Sign(toSign.toString(), signKey); return createHmacSha256Sign(toSign.toString(), signKey);
} else { } else {
return DigestUtils.md5Hex(toSign.toString()).toUpperCase(); return DigestUtils.md5Hex(toSign.toString()).toUpperCase();
} }
} }
private static String createHMACSha256Sign(String message, String key) { private static String createHmacSha256Sign(String message, String key) {
try { try {
Mac hmacSHA256 = Mac.getInstance("HmacSHA256"); Mac sha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256");
hmacSHA256.init(secretKeySpec); sha256.init(secretKeySpec);
byte[] bytes = hmacSHA256.doFinal(message.getBytes()); byte[] bytes = sha256.doFinal(message.getBytes());
return Hex.encodeHexString(bytes).toUpperCase(); return Hex.encodeHexString(bytes).toUpperCase();
} catch (NoSuchAlgorithmException | InvalidKeyException e) { } catch (NoSuchAlgorithmException | InvalidKeyException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
@@ -109,7 +108,7 @@ public class SignUtils {
} }
/** /**
* 校验签名是否正确 * 校验签名是否正确.
* *
* @param xmlBean Bean需要标记有XML注解 * @param xmlBean Bean需要标记有XML注解
* @param signType 签名类型如果为空则默认为MD5 * @param signType 签名类型如果为空则默认为MD5
@@ -121,7 +120,7 @@ public class SignUtils {
} }
/** /**
* 校验签名是否正确 * 校验签名是否正确.
* *
* @param params 需要校验的参数Map * @param params 需要校验的参数Map
* @param signType 签名类型如果为空则默认为MD5 * @param signType 签名类型如果为空则默认为MD5

View File

@@ -2,6 +2,7 @@ package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.utils.qrcode.QrcodeUtils; import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.github.binarywang.wxpay.bean.coupon.*; import com.github.binarywang.wxpay.bean.coupon.*;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
@@ -398,9 +399,43 @@ public class WxPayServiceAbstractImplTest {
this.logger.info(result); this.logger.info(result);
} }
/**
* @see {@link com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResultTest}
* @throws Exception
*/
@Test @Test
public void testParseOrderNotifyResult() throws Exception { public void testParseOrderNotifyResult() throws Exception {
// 请参考com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResultTest里的单元测试 // 请参考com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResultTest 里的单元测试
String xmlString = "<xml>\n" +
" <appid><![CDATA[wx2421b1c4370ec43b]]></appid>\n" +
" <attach><![CDATA[支付测试]]></attach>\n" +
" <bank_type><![CDATA[CFT]]></bank_type>\n" +
" <fee_type><![CDATA[CNY]]></fee_type>\n" +
" <is_subscribe><![CDATA[Y]]></is_subscribe>\n" +
" <mch_id><![CDATA[10000100]]></mch_id>\n" +
" <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>\n" +
" <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>\n" +
" <out_trade_no><![CDATA[1409811653]]></out_trade_no>\n" +
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
" <return_code><![CDATA[SUCCESS]]></return_code>\n" +
" <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>\n" +
" <sub_mch_id><![CDATA[10000100]]></sub_mch_id>\n" +
" <time_end><![CDATA[20140903131540]]></time_end>\n" +
" <total_fee>1</total_fee>\n" +
" <trade_type><![CDATA[JSAPI]]></trade_type>\n" +
" <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>\n" +
" <coupon_count>2</coupon_count>\n" +
" <coupon_type_0><![CDATA[CASH]]></coupon_type_0>\n" +
" <coupon_id_0>10000</coupon_id_0>\n" +
" <coupon_fee_0>100</coupon_fee_0>\n" +
" <coupon_type_1><![CDATA[NO_CASH]]></coupon_type_1>\n" +
" <coupon_id_1>10001</coupon_id_1>\n" +
" <coupon_fee_1>200</coupon_fee_1>\n" +
"</xml>";
WxPayOrderNotifyResult result = this.payService.parseOrderNotifyResult(xmlString);
System.out.println(result);
} }
@Test @Test