mirror of
				https://gitee.com/binary/weixin-java-tools.git
				synced 2025-10-31 18:46:10 +08:00 
			
		
		
		
	🎨 #2115 优化公众号、小程序、企业微信的access token自动刷新逻辑,避免循环递归调用
This commit is contained in:
		| @ -241,7 +241,7 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH | |||||||
|     int retryTimes = 0; |     int retryTimes = 0; | ||||||
|     do { |     do { | ||||||
|       try { |       try { | ||||||
|         return this.executeInternal(executor, uri, data); |         return this.executeInternal(executor, uri, data, false); | ||||||
|       } catch (WxErrorException e) { |       } catch (WxErrorException e) { | ||||||
|         if (retryTimes + 1 > this.maxRetryTimes) { |         if (retryTimes + 1 > this.maxRetryTimes) { | ||||||
|           log.warn("重试达到最大次数【{}】", this.maxRetryTimes); |           log.warn("重试达到最大次数【{}】", this.maxRetryTimes); | ||||||
| @ -271,7 +271,7 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH | |||||||
|     throw new WxRuntimeException("微信服务端异常,超出重试次数"); |     throw new WxRuntimeException("微信服务端异常,超出重试次数"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   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, boolean doNotAutoRefresh) throws WxErrorException { | ||||||
|     E dataForLog = DataUtils.handleDataWithSecret(data); |     E dataForLog = DataUtils.handleDataWithSecret(data); | ||||||
|  |  | ||||||
|     if (uri.contains("access_token=")) { |     if (uri.contains("access_token=")) { | ||||||
| @ -291,9 +291,11 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH | |||||||
|       if (WxConsts.ACCESS_TOKEN_ERROR_CODES.contains(error.getErrorCode())) { |       if (WxConsts.ACCESS_TOKEN_ERROR_CODES.contains(error.getErrorCode())) { | ||||||
|         // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token |         // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | ||||||
|         this.configStorage.expireAccessToken(); |         this.configStorage.expireAccessToken(); | ||||||
|         if (this.getWxCpConfigStorage().autoRefreshToken()) { |         if (this.getWxCpConfigStorage().autoRefreshToken() && !doNotAutoRefresh) { | ||||||
|           log.warn("即将重新获取新的access_token,错误代码:{},错误信息:{}", error.getErrorCode(), error.getErrorMsg()); |           log.warn("即将重新获取新的access_token,错误代码:{},错误信息:{}", error.getErrorCode(), error.getErrorMsg()); | ||||||
|           return this.execute(executor, uri, data); |           //下一次不再自动重试 | ||||||
|  |           //当小程序误调用第三方平台专属接口时,第三方无法使用小程序的access token,如果可以继续自动获取token会导致无限循环重试,直到栈溢出 | ||||||
|  |           return this.executeInternal(executor, uri, data, true); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ public class WxCpBusyRetryTest { | |||||||
|  |  | ||||||
|       @Override |       @Override | ||||||
|       public synchronized <T, E> T executeInternal( |       public synchronized <T, E> T executeInternal( | ||||||
|         RequestExecutor<T, E> executor, String uri, E data) |         RequestExecutor<T, E> executor, String uri, E data, boolean doNotAutoRefresh) | ||||||
|         throws WxErrorException { |         throws WxErrorException { | ||||||
|         log.info("Executed"); |         log.info("Executed"); | ||||||
|         throw new WxErrorException("something"); |         throw new WxErrorException("something"); | ||||||
|  | |||||||
| @ -1,13 +1,26 @@ | |||||||
| package me.chanjar.weixin.cp.api.impl; | package me.chanjar.weixin.cp.api.impl; | ||||||
|  |  | ||||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||||
|  | import me.chanjar.weixin.common.error.WxError; | ||||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||||
|  | import me.chanjar.weixin.common.error.WxMpErrorMsgEnum; | ||||||
|  | import me.chanjar.weixin.common.util.http.HttpType; | ||||||
|  | import me.chanjar.weixin.common.util.http.RequestExecutor; | ||||||
| import me.chanjar.weixin.cp.api.ApiTestModule; | import me.chanjar.weixin.cp.api.ApiTestModule; | ||||||
| import me.chanjar.weixin.cp.api.WxCpService; | import me.chanjar.weixin.cp.api.WxCpService; | ||||||
|  | import me.chanjar.weixin.cp.config.WxCpConfigStorage; | ||||||
|  | import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl; | ||||||
|  | import org.mockito.Mockito; | ||||||
|  | import org.testng.Assert; | ||||||
| import org.testng.annotations.Guice; | import org.testng.annotations.Guice; | ||||||
| import org.testng.annotations.Test; | import org.testng.annotations.Test; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.concurrent.atomic.AtomicInteger; | ||||||
|  |  | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.mockito.Mockito.mock; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * <pre> |  * <pre> | ||||||
| @ -37,4 +50,59 @@ public class BaseWxCpServiceImplTest { | |||||||
|   public void testGetProviderToken() throws WxErrorException { |   public void testGetProviderToken() throws WxErrorException { | ||||||
|     assertThat(this.wxService.getProviderToken("111", "123")).isNotNull(); |     assertThat(this.wxService.getProviderToken("111", "123")).isNotNull(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void testExecuteAutoRefreshToken() throws WxErrorException, IOException { | ||||||
|  |     //测试access token获取时的重试机制 | ||||||
|  |     WxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl(); | ||||||
|  |     BaseWxCpServiceImpl service = new BaseWxCpServiceImpl() { | ||||||
|  |       @Override | ||||||
|  |       public Object getRequestHttpClient() { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public Object getRequestHttpProxy() { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public HttpType getRequestType() { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public String getAccessToken(boolean forceRefresh) throws WxErrorException { | ||||||
|  |         return "模拟一个过期的access token:" + System.currentTimeMillis(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public void initHttp() { | ||||||
|  |  | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public WxCpConfigStorage getWxCpConfigStorage() { | ||||||
|  |         return config; | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |     config.setAgentId(1); | ||||||
|  |     service.setWxCpConfigStorage(config); | ||||||
|  |     RequestExecutor<Object, Object> re = mock(RequestExecutor.class); | ||||||
|  |  | ||||||
|  |     AtomicInteger counter = new AtomicInteger(); | ||||||
|  |     Mockito.when(re.execute(Mockito.anyString(), Mockito.any(), Mockito.any())).thenAnswer(invocation -> { | ||||||
|  |       counter.incrementAndGet(); | ||||||
|  |       WxError error = WxError.builder().errorCode(WxMpErrorMsgEnum.CODE_40001.getCode()).errorMsg(WxMpErrorMsgEnum.CODE_40001.getMsg()).build(); | ||||||
|  |       throw new WxErrorException(error); | ||||||
|  |     }); | ||||||
|  |     try { | ||||||
|  |       Object execute = service.execute(re, "http://baidu.com", new HashMap<>()); | ||||||
|  |       Assert.assertTrue(false, "代码应该不会执行到这里"); | ||||||
|  |     } catch (WxErrorException e) { | ||||||
|  |       Assert.assertEquals(WxMpErrorMsgEnum.CODE_40001.getCode(), e.getError().getErrorCode()); | ||||||
|  |       Assert.assertEquals(2, counter.get()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -207,7 +207,7 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH | |||||||
|     int retryTimes = 0; |     int retryTimes = 0; | ||||||
|     do { |     do { | ||||||
|       try { |       try { | ||||||
|         return this.executeInternal(executor, uri, data); |         return this.executeInternal(executor, uri, data, false); | ||||||
|       } catch (WxErrorException e) { |       } catch (WxErrorException e) { | ||||||
|         if (retryTimes + 1 > this.maxRetryTimes) { |         if (retryTimes + 1 > this.maxRetryTimes) { | ||||||
|           log.warn("重试达到最大次数【{}】", maxRetryTimes); |           log.warn("重试达到最大次数【{}】", maxRetryTimes); | ||||||
| @ -238,7 +238,7 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH | |||||||
|     throw new WxRuntimeException("微信服务端异常,超出重试次数"); |     throw new WxRuntimeException("微信服务端异常,超出重试次数"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private <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, boolean doNotAutoRefreshToken) throws WxErrorException { | ||||||
|     E dataForLog = DataUtils.handleDataWithSecret(data); |     E dataForLog = DataUtils.handleDataWithSecret(data); | ||||||
|  |  | ||||||
|     if (uri.contains("access_token=")) { |     if (uri.contains("access_token=")) { | ||||||
| @ -271,9 +271,11 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH | |||||||
|         } finally { |         } finally { | ||||||
|           lock.unlock(); |           lock.unlock(); | ||||||
|         } |         } | ||||||
|         if (this.getWxMaConfig().autoRefreshToken()) { |         if (this.getWxMaConfig().autoRefreshToken() && !doNotAutoRefreshToken) { | ||||||
|           log.warn("即将重新获取新的access_token,错误代码:{},错误信息:{}", error.getErrorCode(), error.getErrorMsg()); |           log.warn("即将重新获取新的access_token,错误代码:{},错误信息:{}", error.getErrorCode(), error.getErrorMsg()); | ||||||
|           return this.execute(executor, uri, data); |           //下一次不再自动重试 | ||||||
|  |           //当小程序误调用第三方平台专属接口时,第三方无法使用小程序的access token,如果可以继续自动获取token会导致无限循环重试,直到栈溢出 | ||||||
|  |           return this.executeInternal(executor, uri, data, true); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | |||||||
| @ -2,14 +2,25 @@ package cn.binarywang.wx.miniapp.api.impl; | |||||||
|  |  | ||||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | import cn.binarywang.wx.miniapp.api.WxMaService; | ||||||
| import cn.binarywang.wx.miniapp.config.WxMaConfig; | import cn.binarywang.wx.miniapp.config.WxMaConfig; | ||||||
|  | import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; | ||||||
| import cn.binarywang.wx.miniapp.test.ApiTestModule; | import cn.binarywang.wx.miniapp.test.ApiTestModule; | ||||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||||
|  | import me.chanjar.weixin.common.error.WxError; | ||||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||||
|  | import me.chanjar.weixin.common.error.WxMpErrorMsgEnum; | ||||||
|  | import me.chanjar.weixin.common.util.http.RequestExecutor; | ||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
|  | import org.mockito.Mockito; | ||||||
|  | import org.testng.Assert; | ||||||
| import org.testng.annotations.Guice; | import org.testng.annotations.Guice; | ||||||
| import org.testng.annotations.Test; | import org.testng.annotations.Test; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.concurrent.atomic.AtomicInteger; | ||||||
|  |  | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.mockito.Mockito.mock; | ||||||
| import static org.testng.Assert.assertNotEquals; | import static org.testng.Assert.assertNotEquals; | ||||||
| import static org.testng.Assert.assertTrue; | import static org.testng.Assert.assertTrue; | ||||||
|  |  | ||||||
| @ -101,6 +112,35 @@ public class WxMaServiceImplTest { | |||||||
|   public void testExecute() { |   public void testExecute() { | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void testExecuteAutoRefreshToken() throws WxErrorException, IOException { | ||||||
|  |     //测试access token获取时的重试机制 | ||||||
|  |     WxMaServiceImpl service = new WxMaServiceImpl() { | ||||||
|  |       @Override | ||||||
|  |       public String getAccessToken(boolean forceRefresh) throws WxErrorException { | ||||||
|  |         return "模拟一个过期的access token:" + System.currentTimeMillis(); | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |     WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); | ||||||
|  |     config.setAppid("1"); | ||||||
|  |     service.setWxMaConfig(config); | ||||||
|  |     RequestExecutor<Object, Object> re = mock(RequestExecutor.class); | ||||||
|  |  | ||||||
|  |     AtomicInteger counter = new AtomicInteger(); | ||||||
|  |     Mockito.when(re.execute(Mockito.anyString(), Mockito.any(), Mockito.any())).thenAnswer(invocation -> { | ||||||
|  |       counter.incrementAndGet(); | ||||||
|  |       WxError error = WxError.builder().errorCode(WxMpErrorMsgEnum.CODE_40001.getCode()).errorMsg(WxMpErrorMsgEnum.CODE_40001.getMsg()).build(); | ||||||
|  |       throw new WxErrorException(error); | ||||||
|  |     }); | ||||||
|  |     try { | ||||||
|  |       Object execute = service.execute(re, "http://baidu.com", new HashMap<>()); | ||||||
|  |       Assert.assertTrue(false, "代码应该不会执行到这里"); | ||||||
|  |     } catch (WxErrorException e) { | ||||||
|  |       Assert.assertEquals(WxMpErrorMsgEnum.CODE_40001.getCode(), e.getError().getErrorCode()); | ||||||
|  |       Assert.assertEquals(2, counter.get()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @Test |   @Test | ||||||
|   public void testGetWxMaConfig() { |   public void testGetWxMaConfig() { | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -341,7 +341,7 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH | |||||||
|     int retryTimes = 0; |     int retryTimes = 0; | ||||||
|     do { |     do { | ||||||
|       try { |       try { | ||||||
|         return this.executeInternal(executor, uri, data); |         return this.executeInternal(executor, uri, data, false); | ||||||
|       } catch (WxErrorException e) { |       } catch (WxErrorException e) { | ||||||
|         WxError error = e.getError(); |         WxError error = e.getError(); | ||||||
|         // -1 系统繁忙, 1000ms后重试 |         // -1 系统繁忙, 1000ms后重试 | ||||||
| @ -370,7 +370,7 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH | |||||||
|     throw new WxRuntimeException("微信服务端异常,超出重试次数"); |     throw new WxRuntimeException("微信服务端异常,超出重试次数"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   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, boolean doNotAutoRefresh) throws WxErrorException { | ||||||
|     E dataForLog = DataUtils.handleDataWithSecret(data); |     E dataForLog = DataUtils.handleDataWithSecret(data); | ||||||
|  |  | ||||||
|     if (uri.contains("access_token=")) { |     if (uri.contains("access_token=")) { | ||||||
| @ -399,9 +399,11 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH | |||||||
|         } finally { |         } finally { | ||||||
|           lock.unlock(); |           lock.unlock(); | ||||||
|         } |         } | ||||||
|         if (this.getWxMpConfigStorage().autoRefreshToken()) { |         if (this.getWxMpConfigStorage().autoRefreshToken() && !doNotAutoRefresh) { | ||||||
|           log.warn("即将重新获取新的access_token,错误代码:{},错误信息:{}", error.getErrorCode(), error.getErrorMsg()); |           log.warn("即将重新获取新的access_token,错误代码:{},错误信息:{}", error.getErrorCode(), error.getErrorMsg()); | ||||||
|           return this.execute(executor, uri, data); |           //下一次不再自动重试 | ||||||
|  |           //当小程序误调用第三方平台专属接口时,第三方无法使用小程序的access token,如果可以继续自动获取token会导致无限循环重试,直到栈溢出 | ||||||
|  |           return this.executeInternal(executor, uri, data, true); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| package me.chanjar.weixin.mp.api; | package me.chanjar.weixin.mp.api; | ||||||
|  |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| import me.chanjar.weixin.common.error.WxError; |  | ||||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||||
| import me.chanjar.weixin.common.error.WxRuntimeException; | import me.chanjar.weixin.common.error.WxRuntimeException; | ||||||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | import me.chanjar.weixin.common.util.http.RequestExecutor; | ||||||
| import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl; | import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl; | ||||||
| import org.testng.annotations.*; | import org.testng.annotations.DataProvider; | ||||||
|  | import org.testng.annotations.Test; | ||||||
|  |  | ||||||
| import java.util.concurrent.ExecutionException; | import java.util.concurrent.ExecutionException; | ||||||
| import java.util.concurrent.ExecutorService; | import java.util.concurrent.ExecutorService; | ||||||
| @ -23,7 +23,7 @@ public class WxMpBusyRetryTest { | |||||||
|  |  | ||||||
|       @Override |       @Override | ||||||
|       public synchronized <T, E> T executeInternal( |       public synchronized <T, E> T executeInternal( | ||||||
|         RequestExecutor<T, E> executor, String uri, E data) |         RequestExecutor<T, E> executor, String uri, E data, boolean doNotAutoRefresh) | ||||||
|         throws WxErrorException { |         throws WxErrorException { | ||||||
|         log.info("Executed"); |         log.info("Executed"); | ||||||
|         throw new WxErrorException("something"); |         throw new WxErrorException("something"); | ||||||
|  | |||||||
| @ -2,27 +2,35 @@ package me.chanjar.weixin.mp.api.impl; | |||||||
|  |  | ||||||
| import com.google.common.collect.Sets; | import com.google.common.collect.Sets; | ||||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||||
| import java.util.Set; |  | ||||||
| import java.util.concurrent.ExecutorService; |  | ||||||
| import java.util.concurrent.Executors; |  | ||||||
| import java.util.concurrent.TimeUnit; |  | ||||||
| import me.chanjar.weixin.common.api.WxConsts; | import me.chanjar.weixin.common.api.WxConsts; | ||||||
| import me.chanjar.weixin.common.bean.WxJsapiSignature; | import me.chanjar.weixin.common.bean.WxJsapiSignature; | ||||||
| import me.chanjar.weixin.common.bean.WxNetCheckResult; | import me.chanjar.weixin.common.bean.WxNetCheckResult; | ||||||
|  | import me.chanjar.weixin.common.error.WxError; | ||||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||||
|  | import me.chanjar.weixin.common.error.WxMpErrorMsgEnum; | ||||||
|  | import me.chanjar.weixin.common.util.http.HttpType; | ||||||
|  | import me.chanjar.weixin.common.util.http.RequestExecutor; | ||||||
| import me.chanjar.weixin.mp.api.WxMpService; | import me.chanjar.weixin.mp.api.WxMpService; | ||||||
| import me.chanjar.weixin.mp.api.test.ApiTestModule; | import me.chanjar.weixin.mp.api.test.ApiTestModule; | ||||||
|  | import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; | ||||||
| import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder; | import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder; | ||||||
|  | import org.mockito.Mockito; | ||||||
| import org.testng.Assert; | import org.testng.Assert; | ||||||
| import org.testng.annotations.Guice; | import org.testng.annotations.Guice; | ||||||
| import org.testng.annotations.Test; | import org.testng.annotations.Test; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Set; | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  | import java.util.concurrent.atomic.AtomicInteger; | ||||||
|  |  | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| import static org.testng.Assert.assertEquals; | import static org.mockito.Mockito.mock; | ||||||
| import static org.testng.Assert.assertFalse; | import static org.testng.Assert.*; | ||||||
| import static org.testng.Assert.assertTrue; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * <pre> |  * <pre> | ||||||
| @ -190,7 +198,57 @@ public class BaseWxMpServiceImplTest { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   @Test |   @Test | ||||||
|   public void testExecute() { |   public void testExecute() throws WxErrorException, IOException { | ||||||
|  |  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void testExecuteAutoRefreshToken() throws WxErrorException, IOException { | ||||||
|  |     //测试access token获取时的重试机制 | ||||||
|  |     BaseWxMpServiceImpl<Object, Object> service = new BaseWxMpServiceImpl() { | ||||||
|  |       @Override | ||||||
|  |       public String getAccessToken(boolean forceRefresh) throws WxErrorException { | ||||||
|  |         return "模拟一个过期的access token:" + System.currentTimeMillis(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public void initHttp() { | ||||||
|  |  | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public Object getRequestHttpClient() { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public Object getRequestHttpProxy() { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       @Override | ||||||
|  |       public HttpType getRequestType() { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |     WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl(); | ||||||
|  |     config.setAppId("1"); | ||||||
|  |     service.setWxMpConfigStorage(config); | ||||||
|  |     RequestExecutor<Object, Object> re = mock(RequestExecutor.class); | ||||||
|  |  | ||||||
|  |     AtomicInteger counter = new AtomicInteger(); | ||||||
|  |     Mockito.when(re.execute(Mockito.anyString(), Mockito.any(), Mockito.any())).thenAnswer(invocation -> { | ||||||
|  |       counter.incrementAndGet(); | ||||||
|  |       WxError error = WxError.builder().errorCode(WxMpErrorMsgEnum.CODE_40001.getCode()).errorMsg(WxMpErrorMsgEnum.CODE_40001.getMsg()).build(); | ||||||
|  |       throw new WxErrorException(error); | ||||||
|  |     }); | ||||||
|  |     try { | ||||||
|  |       Object execute = service.execute(re, "http://baidu.com", new HashMap<>()); | ||||||
|  |       Assert.assertTrue(false, "代码应该不会执行到这里"); | ||||||
|  |     } catch (WxErrorException e) { | ||||||
|  |       Assert.assertEquals(WxMpErrorMsgEnum.CODE_40001.getCode(), e.getError().getErrorCode()); | ||||||
|  |       Assert.assertEquals(2, counter.get()); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @Test |   @Test | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 hywr
					hywr