فهرست منبع

:new: #2998 【小程序】增加获取稳定版接口调用凭据的接口,通过设置WxMaConfig#useStableAccessToken方法去开启使用稳定版接口

FreeOfYou 2 سال پیش
والد
کامیت
c33ee14574

+ 2 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java

@@ -22,6 +22,8 @@ public interface WxMaService extends WxService {
    * 获取access_token.
    */
   String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
+  String GET_STABLE_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/stable_token";
+
 
   /**
    * The constant JSCODE_TO_SESSION_URL.

+ 16 - 1
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java

@@ -174,7 +174,13 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH
           return this.getWxMaConfig().getAccessToken();
         }
       } while (!locked);
-      String response = doGetAccessTokenRequest();
+
+      String response;
+      if (getWxMaConfig().isStableAccessToken()) {
+        response = doGetStableAccessTokenRequest(forceRefresh);
+      } else {
+        response = doGetAccessTokenRequest();
+      }
       return extractAccessToken(response);
     } catch (IOException | InterruptedException e) {
       throw new WxRuntimeException(e);
@@ -193,6 +199,15 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH
    */
   protected abstract String doGetAccessTokenRequest() throws IOException;
 
+
+  /**
+   * 通过网络请求获取稳定版接口调用凭据
+   *
+   * @return .
+   * @throws IOException .
+   */
+  protected abstract String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException;
+
   @Override
   public String get(String url, String queryParam) throws WxErrorException {
     return execute(SimpleGetRequestExecutor.create(this), url, queryParam);

+ 40 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceHttpClientImpl.java

@@ -1,6 +1,7 @@
 package cn.binarywang.wx.miniapp.api.impl;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.WxMaStableAccessTokenRequest;
 import cn.binarywang.wx.miniapp.config.WxMaConfig;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.util.http.HttpType;
@@ -11,6 +12,9 @@ import org.apache.http.HttpHost;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.BasicResponseHandler;
 import org.apache.http.impl.client.CloseableHttpClient;
 
@@ -93,4 +97,40 @@ public class WxMaServiceHttpClientImpl extends BaseWxMaServiceImpl {
     }
   }
 
+  @Override
+  protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
+    String url = StringUtils.isNotEmpty(this.getWxMaConfig().getAccessTokenUrl()) ?
+      this.getWxMaConfig().getAccessTokenUrl() : StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ?
+      GET_STABLE_ACCESS_TOKEN.replace("https://api.weixin.qq.com", this.getWxMaConfig().getApiHostUrl()) :
+      GET_STABLE_ACCESS_TOKEN;
+
+    HttpPost httpPost = null;
+    CloseableHttpResponse response = null;
+    try {
+      httpPost = new HttpPost(url);
+      if (this.getRequestHttpProxy() != null) {
+        RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
+        httpPost.setConfig(config);
+      }
+      WxMaStableAccessTokenRequest wxMaAccessTokenRequest = new WxMaStableAccessTokenRequest();
+      wxMaAccessTokenRequest.setAppid(this.getWxMaConfig().getAppid());
+      wxMaAccessTokenRequest.setSecret(this.getWxMaConfig().getSecret());
+      wxMaAccessTokenRequest.setGrantType("client_credential");
+      wxMaAccessTokenRequest.setForceRefresh(forceRefresh);
+      httpPost.setEntity(new StringEntity(wxMaAccessTokenRequest.toJson(), ContentType.APPLICATION_JSON));
+      response = getRequestHttpClient().execute(httpPost);
+      return new BasicResponseHandler().handleResponse(response);
+    } finally {
+      if (httpPost != null) {
+        httpPost.releaseConnection();
+      }
+      if (response != null) {
+        try {
+          response.close();
+        } catch (IOException e) {
+        }
+      }
+    }
+  }
+
 }

+ 29 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceJoddHttpImpl.java

@@ -1,15 +1,18 @@
 package cn.binarywang.wx.miniapp.api.impl;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.WxMaStableAccessTokenRequest;
 import cn.binarywang.wx.miniapp.config.WxMaConfig;
 import jodd.http.HttpConnectionProvider;
 import jodd.http.HttpRequest;
 import jodd.http.ProxyInfo;
 import jodd.http.net.SocketHttpConnectionProvider;
+import jodd.net.MimeTypes;
 import me.chanjar.weixin.common.util.http.HttpType;
 import org.apache.commons.lang3.StringUtils;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 /**
  * jodd-http方式实现.
@@ -62,4 +65,30 @@ public class WxMaServiceJoddHttpImpl extends BaseWxMaServiceImpl<HttpConnectionP
     return request.send().bodyText();
   }
 
+  @Override
+  protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
+
+    String url = StringUtils.isNotEmpty(this.getWxMaConfig().getAccessTokenUrl()) ?
+      this.getWxMaConfig().getAccessTokenUrl() : StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ?
+      GET_STABLE_ACCESS_TOKEN.replace("https://api.weixin.qq.com", this.getWxMaConfig().getApiHostUrl()) :
+      GET_STABLE_ACCESS_TOKEN;
+
+    WxMaStableAccessTokenRequest wxMaAccessTokenRequest = new WxMaStableAccessTokenRequest();
+    wxMaAccessTokenRequest.setAppid(this.getWxMaConfig().getAppid());
+    wxMaAccessTokenRequest.setSecret(this.getWxMaConfig().getSecret());
+    wxMaAccessTokenRequest.setGrantType("client_credential");
+    wxMaAccessTokenRequest.setForceRefresh(forceRefresh);
+
+    HttpRequest request = HttpRequest.post(url)
+      .contentType(MimeTypes.MIME_APPLICATION_JSON, StandardCharsets.UTF_8.name())
+      .body(wxMaAccessTokenRequest.toJson());
+    if (this.getRequestHttpProxy() != null) {
+      SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
+      provider.useProxy(getRequestHttpProxy());
+
+      request.withConnectionProvider(provider);
+    }
+    return request.send().bodyText();
+  }
+
 }

+ 19 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceOkHttpImpl.java

@@ -1,6 +1,7 @@
 package cn.binarywang.wx.miniapp.api.impl;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.WxMaStableAccessTokenRequest;
 import cn.binarywang.wx.miniapp.config.WxMaConfig;
 import me.chanjar.weixin.common.util.http.HttpType;
 import me.chanjar.weixin.common.util.http.okhttp.DefaultOkHttpClientBuilder;
@@ -74,4 +75,22 @@ public class WxMaServiceOkHttpImpl extends BaseWxMaServiceImpl<OkHttpClient, OkH
       return Objects.requireNonNull(response.body()).string();
     }
   }
+
+  @Override
+  protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
+    String url = StringUtils.isNotEmpty(this.getWxMaConfig().getAccessTokenUrl()) ?
+      this.getWxMaConfig().getAccessTokenUrl() : StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ?
+      GET_STABLE_ACCESS_TOKEN.replace("https://api.weixin.qq.com", this.getWxMaConfig().getApiHostUrl()) :
+      GET_STABLE_ACCESS_TOKEN;
+    WxMaStableAccessTokenRequest wxMaAccessTokenRequest = new WxMaStableAccessTokenRequest();
+    wxMaAccessTokenRequest.setAppid(this.getWxMaConfig().getAppid());
+    wxMaAccessTokenRequest.setSecret(this.getWxMaConfig().getSecret());
+    wxMaAccessTokenRequest.setGrantType("client_credential");
+    wxMaAccessTokenRequest.setForceRefresh(forceRefresh);
+    RequestBody body = RequestBody.Companion.create(wxMaAccessTokenRequest.toJson(), MediaType.parse("application/json; charset=utf-8"));
+    Request request = new Request.Builder().url(url).post(body).build();
+    try (Response response = getRequestHttpClient().newCall(request).execute()) {
+      return Objects.requireNonNull(response.body()).string();
+    }
+  }
 }

+ 34 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaStableAccessTokenRequest.java

@@ -0,0 +1,34 @@
+package cn.binarywang.wx.miniapp.bean;
+
+import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 小程序码.
+ *
+ * @author Element
+ * created on  2017/7/27
+ */
+@Data
+public class WxMaStableAccessTokenRequest implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  @SerializedName("grant_type")
+  private String grantType = "client_credential";
+
+  @SerializedName("appid")
+  private String appid;
+  @SerializedName("secret")
+  private String secret;
+
+  @SerializedName("force_refresh")
+  private boolean forceRefresh;
+
+  public String toJson() {
+    return WxMaGsonBuilder.create().toJson(this);
+  }
+}

+ 7 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java

@@ -19,6 +19,13 @@ public interface WxMaConfig {
    */
   String getAccessToken();
 
+  //region 稳定版access token
+  boolean isStableAccessToken();
+
+  void useStableAccessToken(boolean useStableAccessToken);
+  //endregion
+
+
   /**
    * Gets access token lock.
    *

+ 21 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/WxMaDefaultConfigImpl.java

@@ -2,6 +2,7 @@ package cn.binarywang.wx.miniapp.config.impl;
 
 import cn.binarywang.wx.miniapp.config.WxMaConfig;
 import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
+import lombok.AccessLevel;
 import lombok.Getter;
 import me.chanjar.weixin.common.bean.WxAccessToken;
 import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
@@ -19,6 +20,13 @@ import java.util.concurrent.locks.ReentrantLock;
 public class WxMaDefaultConfigImpl implements WxMaConfig {
   protected volatile String appid;
   protected volatile String token;
+
+  /**
+   * 是否使用稳定版获取accessToken接口
+   */
+  @Getter(value = AccessLevel.NONE)
+  private boolean useStableAccessToken;
+
   /**
    * 小程序原始ID
    */
@@ -81,6 +89,19 @@ public class WxMaDefaultConfigImpl implements WxMaConfig {
     this.accessToken = accessToken;
   }
 
+  //region 使用稳定版接口获取accessToken
+  @Override
+  public boolean isStableAccessToken() {
+    return this.useStableAccessToken;
+  }
+
+  @Override
+  public void useStableAccessToken(boolean useStableAccessToken) {
+    this.useStableAccessToken = useStableAccessToken;
+  }
+  //endregion
+
+
   @Override
   public Lock getAccessTokenLock() {
     return this.accessTokenLock;

+ 13 - 1
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImplTest.java

@@ -33,6 +33,8 @@ public class WxMaServiceImplTest {
 
   @Inject
   private WxMaService wxService;
+  @Inject
+  private WxMaServiceOkHttpImpl wxMaServiceOkHttp;
 
   public void testRefreshAccessToken() throws WxErrorException {
     WxMaConfig configStorage = this.wxService.getWxMaConfig();
@@ -44,6 +46,16 @@ public class WxMaServiceImplTest {
     assertTrue(StringUtils.isNotBlank(after));
   }
 
+  public void testStableRefreshAccessToken() throws WxErrorException {
+    WxMaConfig configStorage = this.wxMaServiceOkHttp.getWxMaConfig();
+    configStorage.useStableAccessToken(true);
+    String before = configStorage.getAccessToken();
+    this.wxMaServiceOkHttp.getAccessToken(false);
+    String after = configStorage.getAccessToken();
+    assertNotEquals(before, after);
+    assertTrue(StringUtils.isNotBlank(after));
+  }
+
   @Test(expectedExceptions = {WxErrorException.class})
   public void testGetPaidUnionId() throws WxErrorException {
     final String unionId = this.wxService.getPaidUnionId("1", null, "3", "4");
@@ -134,7 +146,7 @@ public class WxMaServiceImplTest {
     });
     try {
       Object execute = service.execute(re, "http://baidu.com", new HashMap<>());
-      Assert.assertTrue(false, "代码应该不会执行到这里");
+      Assert.fail("代码应该不会执行到这里");
     } catch (WxErrorException e) {
       Assert.assertEquals(WxMpErrorMsgEnum.CODE_40001.getCode(), e.getError().getErrorCode());
       Assert.assertEquals(2, counter.get());

+ 13 - 8
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/test/ApiTestModule.java

@@ -1,17 +1,17 @@
 package cn.binarywang.wx.miniapp.test;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.locks.ReentrantLock;
-
-import me.chanjar.weixin.common.error.WxRuntimeException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.api.impl.WxMaServiceOkHttpImpl;
 import cn.binarywang.wx.miniapp.config.WxMaConfig;
 import com.google.inject.Binder;
 import com.google.inject.Module;
+import me.chanjar.weixin.common.error.WxRuntimeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * @author <a href="https://github.com/binarywang">Binary Wang</a>
@@ -34,6 +34,11 @@ public class ApiTestModule implements Module {
 
       binder.bind(WxMaService.class).toInstance(wxService);
       binder.bind(WxMaConfig.class).toInstance(config);
+
+      WxMaServiceOkHttpImpl wxMaServiceOkHttp = new cn.binarywang.wx.miniapp.api.impl.WxMaServiceOkHttpImpl();
+      wxMaServiceOkHttp.setWxMaConfig(config);
+      binder.bind(WxMaServiceOkHttpImpl.class).toInstance(wxMaServiceOkHttp);
+
     } catch (IOException e) {
       this.log.error(e.getMessage(), e);
     }

+ 19 - 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java

@@ -2,7 +2,10 @@ package me.chanjar.weixin.open.api.impl;
 
 
 import cn.binarywang.wx.miniapp.config.WxMaConfig;
+import lombok.AccessLevel;
 import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
 import me.chanjar.weixin.common.bean.WxAccessToken;
 import me.chanjar.weixin.common.enums.TicketType;
 import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
@@ -258,6 +261,12 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
     private WxMpHostConfig hostConfig;
     private String apiHostUrl;
     private String accessTokenUrl;
+    /**
+     * 是否使用稳定版获取accessToken接口
+     */
+    @Getter(value = AccessLevel.NONE)
+    @Setter(value = AccessLevel.NONE)
+    private boolean useStableAccessToken;
 
     /**
      * 小程序原始ID
@@ -285,6 +294,16 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
     }
 
     @Override
+    public boolean isStableAccessToken() {
+      return this.useStableAccessToken;
+    }
+
+    @Override
+    public void useStableAccessToken(boolean useStableAccessToken) {
+      this.useStableAccessToken = useStableAccessToken;
+    }
+
+    @Override
     public Lock getAccessTokenLock() {
       return this.accessTokenLock;
     }