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

This commit is contained in:
FreeOfYou 2023-05-06 19:38:12 +08:00 committed by GitHub
parent 24c18b8bbc
commit c33ee14574
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 213 additions and 10 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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) {
}
}
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

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

View File

@ -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;

View File

@ -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());

View File

@ -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 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 cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import com.google.inject.Binder;
import com.google.inject.Module;
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);
}

View File

@ -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
@ -284,6 +293,16 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
return wxOpenConfigStorage.getAuthorizerAccessToken(appId);
}
@Override
public boolean isStableAccessToken() {
return this.useStableAccessToken;
}
@Override
public void useStableAccessToken(boolean useStableAccessToken) {
this.useStableAccessToken = useStableAccessToken;
}
@Override
public Lock getAccessTokenLock() {
return this.accessTokenLock;