| @@ -109,6 +109,11 @@ | |||||
| <artifactId>jetty-servlet</artifactId> | <artifactId>jetty-servlet</artifactId> | ||||
| <scope>test</scope> | <scope>test</scope> | ||||
| </dependency> | </dependency> | ||||
| <dependency> | |||||
| <groupId>org.assertj</groupId> | |||||
| <artifactId>assertj-guava</artifactId> | |||||
| <scope>test</scope> | |||||
| </dependency> | |||||
| </dependencies> | </dependencies> | ||||
| <build> | <build> | ||||
| @@ -0,0 +1,24 @@ | |||||
| package me.chanjar.weixin.common.util; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| /** | |||||
| * <pre> | |||||
| * 数据处理工具类 | |||||
| * Created by BinaryWang on 2018/5/8. | |||||
| * </pre> | |||||
| * | |||||
| * @author <a href="https://github.com/binarywang">Binary Wang</a> | |||||
| */ | |||||
| public class DataUtils { | |||||
| /** | |||||
| * 将数据中包含的secret字符使用星号替换,防止日志打印时被输出 | |||||
| */ | |||||
| public static <E> E handleDataWithSecret(E data) { | |||||
| E dataForLog = data; | |||||
| if(data instanceof String && StringUtils.contains((String)data, "&secret=")){ | |||||
| dataForLog = (E) StringUtils.replaceAll((String)data,"&secret=\\w+&","&secret=******&"); | |||||
| } | |||||
| return dataForLog; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,23 @@ | |||||
| package me.chanjar.weixin.common.util; | |||||
| import org.testng.annotations.Test; | |||||
| import static org.assertj.core.api.Assertions.assertThat; | |||||
| import static org.testng.Assert.*; | |||||
| /** | |||||
| * <pre> | |||||
| * Created by BinaryWang on 2018/5/8. | |||||
| * </pre> | |||||
| * | |||||
| * @author <a href="https://github.com/binarywang">Binary Wang</a> | |||||
| */ | |||||
| public class DataUtilsTest { | |||||
| @Test | |||||
| public void testHandleDataWithSecret() { | |||||
| String data = "js_code=001tZveq0SMoiq1AEXeq0ECJeq0tZveZ&secret=5681022fa1643845392367ea88888888&grant_type=authorization_code&appid=wxe156d4848d999999"; | |||||
| final String s = DataUtils.handleDataWithSecret(data); | |||||
| assertThat(s).contains("&secret=******&"); | |||||
| } | |||||
| } | |||||
| @@ -5,13 +5,12 @@ import com.google.gson.JsonElement; | |||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
| import com.google.gson.JsonParser; | import com.google.gson.JsonParser; | ||||
| import me.chanjar.weixin.common.bean.WxJsapiSignature; | import me.chanjar.weixin.common.bean.WxJsapiSignature; | ||||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | |||||
| import me.chanjar.weixin.common.bean.result.WxError; | import me.chanjar.weixin.common.bean.result.WxError; | ||||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||||
| import me.chanjar.weixin.common.exception.WxErrorException; | import me.chanjar.weixin.common.exception.WxErrorException; | ||||
| import me.chanjar.weixin.common.session.StandardSessionManager; | import me.chanjar.weixin.common.session.StandardSessionManager; | ||||
| import me.chanjar.weixin.common.session.WxSession; | import me.chanjar.weixin.common.session.WxSession; | ||||
| import me.chanjar.weixin.common.session.WxSessionManager; | import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.common.util.DataUtils; | |||||
| import me.chanjar.weixin.common.util.RandomUtils; | import me.chanjar.weixin.common.util.RandomUtils; | ||||
| import me.chanjar.weixin.common.util.crypto.SHA1; | import me.chanjar.weixin.common.util.crypto.SHA1; | ||||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | import me.chanjar.weixin.common.util.http.RequestExecutor; | ||||
| @@ -21,14 +20,11 @@ import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||||
| import me.chanjar.weixin.cp.api.*; | import me.chanjar.weixin.cp.api.*; | ||||
| import me.chanjar.weixin.cp.bean.*; | import me.chanjar.weixin.cp.bean.*; | ||||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | import me.chanjar.weixin.cp.config.WxCpConfigStorage; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | |||||
| import java.util.List; | |||||
| public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, RequestHttp<H, P> { | public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, RequestHttp<H, P> { | ||||
| protected final Logger log = LoggerFactory.getLogger(this.getClass()); | protected final Logger log = LoggerFactory.getLogger(this.getClass()); | ||||
| @@ -201,6 +197,8 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||||
| } | } | ||||
| protected <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | protected <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | ||||
| E dataForLog = DataUtils.handleDataWithSecret(data); | |||||
| if (uri.contains("access_token=")) { | if (uri.contains("access_token=")) { | ||||
| throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | ||||
| } | } | ||||
| @@ -210,7 +208,7 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||||
| try { | try { | ||||
| T result = executor.execute(uriWithAccessToken, data); | T result = executor.execute(uriWithAccessToken, data); | ||||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); | |||||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); | |||||
| return result; | return result; | ||||
| } catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
| WxError error = e.getError(); | WxError error = e.getError(); | ||||
| @@ -227,12 +225,12 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||||
| } | } | ||||
| if (error.getErrorCode() != 0) { | if (error.getErrorCode() != 0) { | ||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); | |||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); | |||||
| throw new WxErrorException(error, e); | throw new WxErrorException(error, e); | ||||
| } | } | ||||
| return null; | return null; | ||||
| } catch (IOException e) { | } catch (IOException e) { | ||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); | |||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); | |||||
| throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
| } | } | ||||
| } | } | ||||
| @@ -16,6 +16,7 @@ import com.google.common.base.Joiner; | |||||
| import me.chanjar.weixin.common.bean.WxAccessToken; | import me.chanjar.weixin.common.bean.WxAccessToken; | ||||
| import me.chanjar.weixin.common.bean.result.WxError; | import me.chanjar.weixin.common.bean.result.WxError; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | import me.chanjar.weixin.common.exception.WxErrorException; | ||||
| import me.chanjar.weixin.common.util.DataUtils; | |||||
| import me.chanjar.weixin.common.util.crypto.SHA1; | import me.chanjar.weixin.common.util.crypto.SHA1; | ||||
| import me.chanjar.weixin.common.util.http.HttpType; | import me.chanjar.weixin.common.util.http.HttpType; | ||||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | import me.chanjar.weixin.common.util.http.RequestExecutor; | ||||
| @@ -24,6 +25,7 @@ import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | |||||
| import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | ||||
| import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | ||||
| import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.apache.http.HttpHost; | import org.apache.http.HttpHost; | ||||
| import org.apache.http.client.config.RequestConfig; | import org.apache.http.client.config.RequestConfig; | ||||
| import org.apache.http.client.methods.CloseableHttpResponse; | import org.apache.http.client.methods.CloseableHttpResponse; | ||||
| @@ -38,6 +40,9 @@ import java.util.HashMap; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.concurrent.locks.Lock; | import java.util.concurrent.locks.Lock; | ||||
| import static cn.binarywang.wx.miniapp.constant.WxMaConstants.*; | |||||
| import static cn.binarywang.wx.miniapp.constant.WxMaConstants.ErrorCode.*; | |||||
| /** | /** | ||||
| * @author <a href="https://github.com/binarywang">Binary Wang</a> | * @author <a href="https://github.com/binarywang">Binary Wang</a> | ||||
| */ | */ | ||||
| @@ -212,7 +217,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||||
| throw new RuntimeException("微信服务端异常,超出重试次数"); | throw new RuntimeException("微信服务端异常,超出重试次数"); | ||||
| } | } | ||||
| public <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | |||||
| private <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | |||||
| E dataForLog = DataUtils.handleDataWithSecret(data); | |||||
| if (uri.contains("access_token=")) { | if (uri.contains("access_token=")) { | ||||
| throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | ||||
| } | } | ||||
| @@ -222,16 +229,16 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||||
| try { | try { | ||||
| T result = executor.execute(uriWithAccessToken, data); | T result = executor.execute(uriWithAccessToken, data); | ||||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); | |||||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); | |||||
| return result; | return result; | ||||
| } catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
| WxError error = e.getError(); | WxError error = e.getError(); | ||||
| /* | /* | ||||
| * 发生以下情况时尝试刷新access_token | * 发生以下情况时尝试刷新access_token | ||||
| */ | */ | ||||
| if (error.getErrorCode() == WxMaConstants.ErrorCode.ERR_40001 | |||||
| || error.getErrorCode() == WxMaConstants.ErrorCode.ERR_42001 | |||||
| || error.getErrorCode() == WxMaConstants.ErrorCode.ERR_40014) { | |||||
| if (error.getErrorCode() == ERR_40001 | |||||
| || error.getErrorCode() == ERR_42001 | |||||
| || error.getErrorCode() == ERR_40014) { | |||||
| // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | ||||
| this.getWxMaConfig().expireAccessToken(); | this.getWxMaConfig().expireAccessToken(); | ||||
| if (this.getWxMaConfig().autoRefreshToken()) { | if (this.getWxMaConfig().autoRefreshToken()) { | ||||
| @@ -240,12 +247,12 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||||
| } | } | ||||
| if (error.getErrorCode() != 0) { | if (error.getErrorCode() != 0) { | ||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); | |||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); | |||||
| throw new WxErrorException(error, e); | throw new WxErrorException(error, e); | ||||
| } | } | ||||
| return null; | return null; | ||||
| } catch (IOException e) { | } catch (IOException e) { | ||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); | |||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); | |||||
| throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
| } | } | ||||
| } | } | ||||
| @@ -9,6 +9,7 @@ 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.session.StandardSessionManager; | import me.chanjar.weixin.common.session.StandardSessionManager; | ||||
| import me.chanjar.weixin.common.session.WxSessionManager; | import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.common.util.DataUtils; | |||||
| import me.chanjar.weixin.common.util.RandomUtils; | import me.chanjar.weixin.common.util.RandomUtils; | ||||
| import me.chanjar.weixin.common.util.crypto.SHA1; | import me.chanjar.weixin.common.util.crypto.SHA1; | ||||
| import me.chanjar.weixin.common.util.http.*; | import me.chanjar.weixin.common.util.http.*; | ||||
| @@ -265,6 +266,8 @@ public abstract class WxMpServiceBaseImpl<H, P> implements WxMpService, RequestH | |||||
| } | } | ||||
| public <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | public <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | ||||
| E dataForLog = DataUtils.handleDataWithSecret(data); | |||||
| if (uri.contains("access_token=")) { | if (uri.contains("access_token=")) { | ||||
| throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | ||||
| } | } | ||||
| @@ -275,7 +278,7 @@ public abstract class WxMpServiceBaseImpl<H, P> implements WxMpService, RequestH | |||||
| try { | try { | ||||
| T result = executor.execute(uriWithAccessToken, data); | T result = executor.execute(uriWithAccessToken, data); | ||||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); | |||||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); | |||||
| return result; | return result; | ||||
| } catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
| WxError error = e.getError(); | WxError error = e.getError(); | ||||
| @@ -294,12 +297,12 @@ public abstract class WxMpServiceBaseImpl<H, P> implements WxMpService, RequestH | |||||
| } | } | ||||
| if (error.getErrorCode() != 0) { | if (error.getErrorCode() != 0) { | ||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); | |||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); | |||||
| throw new WxErrorException(error, e); | throw new WxErrorException(error, e); | ||||
| } | } | ||||
| return null; | return null; | ||||
| } catch (IOException e) { | } catch (IOException e) { | ||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); | |||||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); | |||||
| throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); | throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); | ||||
| } | } | ||||
| } | } | ||||