| @@ -109,6 +109,11 @@ | |||
| <artifactId>jetty-servlet</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.assertj</groupId> | |||
| <artifactId>assertj-guava</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| </dependencies> | |||
| <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.JsonParser; | |||
| import me.chanjar.weixin.common.bean.WxJsapiSignature; | |||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.session.StandardSessionManager; | |||
| import me.chanjar.weixin.common.session.WxSession; | |||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||
| import me.chanjar.weixin.common.util.DataUtils; | |||
| import me.chanjar.weixin.common.util.RandomUtils; | |||
| import me.chanjar.weixin.common.util.crypto.SHA1; | |||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
| @@ -21,14 +20,11 @@ import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||
| import me.chanjar.weixin.cp.api.*; | |||
| import me.chanjar.weixin.cp.bean.*; | |||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.List; | |||
| public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, RequestHttp<H, P> { | |||
| 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 { | |||
| E dataForLog = DataUtils.handleDataWithSecret(data); | |||
| if (uri.contains("access_token=")) { | |||
| throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | |||
| } | |||
| @@ -210,7 +208,7 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||
| try { | |||
| T result = executor.execute(uriWithAccessToken, data); | |||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); | |||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); | |||
| return result; | |||
| } catch (WxErrorException e) { | |||
| WxError error = e.getError(); | |||
| @@ -227,12 +225,12 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ | |||
| } | |||
| if (error.getErrorCode() != 0) { | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); | |||
| throw new WxErrorException(error, e); | |||
| } | |||
| return null; | |||
| } catch (IOException e) { | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| @@ -16,6 +16,7 @@ import com.google.common.base.Joiner; | |||
| import me.chanjar.weixin.common.bean.WxAccessToken; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.DataUtils; | |||
| import me.chanjar.weixin.common.util.crypto.SHA1; | |||
| import me.chanjar.weixin.common.util.http.HttpType; | |||
| 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.apache.ApacheHttpClientBuilder; | |||
| import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.client.config.RequestConfig; | |||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||
| @@ -38,6 +40,9 @@ import java.util.HashMap; | |||
| import java.util.Map; | |||
| 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> | |||
| */ | |||
| @@ -212,7 +217,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
| 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=")) { | |||
| throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | |||
| } | |||
| @@ -222,16 +229,16 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
| try { | |||
| T result = executor.execute(uriWithAccessToken, data); | |||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); | |||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); | |||
| return result; | |||
| } catch (WxErrorException e) { | |||
| WxError error = e.getError(); | |||
| /* | |||
| * 发生以下情况时尝试刷新access_token | |||
| */ | |||
| 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 | |||
| this.getWxMaConfig().expireAccessToken(); | |||
| if (this.getWxMaConfig().autoRefreshToken()) { | |||
| @@ -240,12 +247,12 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
| } | |||
| if (error.getErrorCode() != 0) { | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); | |||
| throw new WxErrorException(error, e); | |||
| } | |||
| return null; | |||
| } catch (IOException e) { | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| @@ -9,6 +9,7 @@ import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.session.StandardSessionManager; | |||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||
| import me.chanjar.weixin.common.util.DataUtils; | |||
| import me.chanjar.weixin.common.util.RandomUtils; | |||
| import me.chanjar.weixin.common.util.crypto.SHA1; | |||
| import me.chanjar.weixin.common.util.http.*; | |||
| @@ -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 { | |||
| E dataForLog = DataUtils.handleDataWithSecret(data); | |||
| if (uri.contains("access_token=")) { | |||
| throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | |||
| } | |||
| @@ -275,7 +278,7 @@ public abstract class WxMpServiceBaseImpl<H, P> implements WxMpService, RequestH | |||
| try { | |||
| T result = executor.execute(uriWithAccessToken, data); | |||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, data, result); | |||
| this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); | |||
| return result; | |||
| } catch (WxErrorException e) { | |||
| WxError error = e.getError(); | |||
| @@ -294,12 +297,12 @@ public abstract class WxMpServiceBaseImpl<H, P> implements WxMpService, RequestH | |||
| } | |||
| if (error.getErrorCode() != 0) { | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, data, error); | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); | |||
| throw new WxErrorException(error, e); | |||
| } | |||
| return null; | |||
| } catch (IOException e) { | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); | |||
| this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); | |||
| throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); | |||
| } | |||
| } | |||