mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-04-05 17:38:05 +08:00
🆕 #3084【公众号】增加获取稳定版接口调用凭据的接口
This commit is contained in:
parent
e5b0498401
commit
c5e9f17607
@ -40,6 +40,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.*;
|
||||
@ -251,6 +252,55 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
|
||||
return getAccessToken(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
if (!forceRefresh && !this.getWxMpConfigStorage().isAccessTokenExpired()) {
|
||||
return this.getWxMpConfigStorage().getAccessToken();
|
||||
}
|
||||
|
||||
Lock lock = this.getWxMpConfigStorage().getAccessTokenLock();
|
||||
boolean locked = false;
|
||||
try {
|
||||
do {
|
||||
locked = lock.tryLock(100, TimeUnit.MILLISECONDS);
|
||||
if (!forceRefresh && !this.getWxMpConfigStorage().isAccessTokenExpired()) {
|
||||
return this.getWxMpConfigStorage().getAccessToken();
|
||||
}
|
||||
} while (!locked);
|
||||
|
||||
String response;
|
||||
if (getWxMpConfigStorage().isStableAccessToken()) {
|
||||
response = doGetStableAccessTokenRequest(forceRefresh);
|
||||
} else {
|
||||
response = doGetAccessTokenRequest();
|
||||
}
|
||||
return extractAccessToken(response);
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new WxRuntimeException(e);
|
||||
} finally {
|
||||
if (locked) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过网络请求获取AccessToken
|
||||
*
|
||||
* @return .
|
||||
* @throws IOException .
|
||||
*/
|
||||
protected abstract String doGetAccessTokenRequest() throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* 通过网络请求获取稳定版接口调用凭据
|
||||
*
|
||||
* @return .
|
||||
* @throws IOException .
|
||||
*/
|
||||
protected abstract String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException;
|
||||
|
||||
@Override
|
||||
public String shortUrl(String longUrl) throws WxErrorException {
|
||||
if (longUrl.contains("&access_token=")) {
|
||||
|
@ -1,23 +1,24 @@
|
||||
package me.chanjar.weixin.mp.api.impl;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxRuntimeException;
|
||||
import me.chanjar.weixin.common.util.http.HttpType;
|
||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
|
||||
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
|
||||
import me.chanjar.weixin.mp.bean.WxMpStableAccessTokenRequest;
|
||||
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
|
||||
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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_ACCESS_TOKEN_URL;
|
||||
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_STABLE_ACCESS_TOKEN_URL;
|
||||
|
||||
/**
|
||||
* apache http client方式实现.
|
||||
@ -64,42 +65,62 @@ public class WxMpServiceHttpClientImpl extends BaseWxMpServiceImpl<CloseableHttp
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
final WxMpConfigStorage config = this.getWxMpConfigStorage();
|
||||
if (!config.isAccessTokenExpired() && !forceRefresh) {
|
||||
return config.getAccessToken();
|
||||
}
|
||||
protected String doGetAccessTokenRequest() throws IOException {
|
||||
String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(getWxMpConfigStorage()), getWxMpConfigStorage().getAppId(), getWxMpConfigStorage().getSecret());
|
||||
|
||||
Lock lock = config.getAccessTokenLock();
|
||||
boolean locked = false;
|
||||
HttpGet httpGet = null;
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
do {
|
||||
locked = lock.tryLock(100, TimeUnit.MILLISECONDS);
|
||||
if (!forceRefresh && !config.isAccessTokenExpired()) {
|
||||
return config.getAccessToken();
|
||||
}
|
||||
} while (!locked);
|
||||
|
||||
String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(config), config.getAppId(), config.getSecret());
|
||||
try {
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
if (this.getRequestHttpProxy() != null) {
|
||||
RequestConfig requestConfig = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
|
||||
httpGet.setConfig(requestConfig);
|
||||
}
|
||||
try (CloseableHttpResponse response = getRequestHttpClient().execute(httpGet)) {
|
||||
return this.extractAccessToken(new BasicResponseHandler().handleResponse(response));
|
||||
} finally {
|
||||
httpGet.releaseConnection();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new WxRuntimeException(e);
|
||||
httpGet = new HttpGet(url);
|
||||
if (this.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
|
||||
httpGet.setConfig(config);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new WxRuntimeException(e);
|
||||
response = getRequestHttpClient().execute(httpGet);
|
||||
return new BasicResponseHandler().handleResponse(response);
|
||||
} finally {
|
||||
if (locked) {
|
||||
lock.unlock();
|
||||
if (httpGet != null) {
|
||||
httpGet.releaseConnection();
|
||||
}
|
||||
if (response != null) {
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
|
||||
String url = GET_STABLE_ACCESS_TOKEN_URL.getUrl(getWxMpConfigStorage());
|
||||
|
||||
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);
|
||||
}
|
||||
WxMpStableAccessTokenRequest wxMaAccessTokenRequest = new WxMpStableAccessTokenRequest();
|
||||
wxMaAccessTokenRequest.setAppid(this.getWxMpConfigStorage().getAppId());
|
||||
wxMaAccessTokenRequest.setSecret(this.getWxMpConfigStorage().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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,15 +4,16 @@ import jodd.http.HttpConnectionProvider;
|
||||
import jodd.http.HttpRequest;
|
||||
import jodd.http.ProxyInfo;
|
||||
import jodd.http.net.SocketHttpConnectionProvider;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxRuntimeException;
|
||||
import jodd.net.MimeTypes;
|
||||
import me.chanjar.weixin.common.util.http.HttpType;
|
||||
import me.chanjar.weixin.mp.bean.WxMpStableAccessTokenRequest;
|
||||
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_ACCESS_TOKEN_URL;
|
||||
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_STABLE_ACCESS_TOKEN_URL;
|
||||
|
||||
/**
|
||||
* jodd-http方式实现.
|
||||
@ -51,39 +52,39 @@ public class WxMpServiceJoddHttpImpl extends BaseWxMpServiceImpl<HttpConnectionP
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
final WxMpConfigStorage config = this.getWxMpConfigStorage();
|
||||
if (!config.isAccessTokenExpired() && !forceRefresh) {
|
||||
return config.getAccessToken();
|
||||
protected String doGetAccessTokenRequest() throws IOException {
|
||||
String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(getWxMpConfigStorage()), getWxMpConfigStorage().getAppId(), getWxMpConfigStorage().getSecret());
|
||||
|
||||
HttpRequest request = HttpRequest.get(url);
|
||||
if (this.getRequestHttpProxy() != null) {
|
||||
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
|
||||
provider.useProxy(getRequestHttpProxy());
|
||||
|
||||
request.withConnectionProvider(provider);
|
||||
}
|
||||
return request.send().bodyText();
|
||||
}
|
||||
|
||||
Lock lock = config.getAccessTokenLock();
|
||||
boolean locked = false;
|
||||
try {
|
||||
do {
|
||||
locked = lock.tryLock(100, TimeUnit.MILLISECONDS);
|
||||
if (!forceRefresh && !config.isAccessTokenExpired()) {
|
||||
return config.getAccessToken();
|
||||
}
|
||||
} while (!locked);
|
||||
String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(config), config.getAppId(), config.getSecret());
|
||||
@Override
|
||||
protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
|
||||
String url = GET_STABLE_ACCESS_TOKEN_URL.getUrl(getWxMpConfigStorage());
|
||||
|
||||
HttpRequest request = HttpRequest.get(url);
|
||||
if (this.getRequestHttpProxy() != null) {
|
||||
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
|
||||
provider.useProxy(getRequestHttpProxy());
|
||||
WxMpStableAccessTokenRequest wxMaAccessTokenRequest = new WxMpStableAccessTokenRequest();
|
||||
wxMaAccessTokenRequest.setAppid(this.getWxMpConfigStorage().getAppId());
|
||||
wxMaAccessTokenRequest.setSecret(this.getWxMpConfigStorage().getSecret());
|
||||
wxMaAccessTokenRequest.setGrantType("client_credential");
|
||||
wxMaAccessTokenRequest.setForceRefresh(forceRefresh);
|
||||
|
||||
request.withConnectionProvider(provider);
|
||||
}
|
||||
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());
|
||||
|
||||
return this.extractAccessToken(request.send().bodyText());
|
||||
} catch (InterruptedException e) {
|
||||
throw new WxRuntimeException(e);
|
||||
} finally {
|
||||
if (locked) {
|
||||
lock.unlock();
|
||||
}
|
||||
request.withConnectionProvider(provider);
|
||||
}
|
||||
return request.send().bodyText();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,19 +1,17 @@
|
||||
package me.chanjar.weixin.mp.api.impl;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.error.WxRuntimeException;
|
||||
import me.chanjar.weixin.common.util.http.HttpType;
|
||||
import me.chanjar.weixin.common.util.http.okhttp.DefaultOkHttpClientBuilder;
|
||||
import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
|
||||
import me.chanjar.weixin.mp.bean.WxMpStableAccessTokenRequest;
|
||||
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
|
||||
import okhttp3.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_ACCESS_TOKEN_URL;
|
||||
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_STABLE_ACCESS_TOKEN_URL;
|
||||
|
||||
/**
|
||||
* okhttp实现.
|
||||
@ -39,38 +37,6 @@ public class WxMpServiceOkHttpImpl extends BaseWxMpServiceImpl<OkHttpClient, OkH
|
||||
return HttpType.OK_HTTP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
final WxMpConfigStorage config = this.getWxMpConfigStorage();
|
||||
if (!config.isAccessTokenExpired() && !forceRefresh) {
|
||||
return config.getAccessToken();
|
||||
}
|
||||
|
||||
Lock lock = config.getAccessTokenLock();
|
||||
boolean locked = false;
|
||||
try {
|
||||
do {
|
||||
locked = lock.tryLock(100, TimeUnit.MILLISECONDS);
|
||||
if (!forceRefresh && !config.isAccessTokenExpired()) {
|
||||
return config.getAccessToken();
|
||||
}
|
||||
} while (!locked);
|
||||
String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(config), config.getAppId(), config.getSecret());
|
||||
|
||||
Request request = new Request.Builder().url(url).get().build();
|
||||
Response response = getRequestHttpClient().newCall(request).execute();
|
||||
return this.extractAccessToken(Objects.requireNonNull(response.body()).string());
|
||||
} catch (IOException e) {
|
||||
throw new WxRuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new WxRuntimeException(e);
|
||||
} finally {
|
||||
if (locked) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initHttp() {
|
||||
WxMpConfigStorage wxMpConfigStorage = getWxMpConfigStorage();
|
||||
@ -99,4 +65,30 @@ public class WxMpServiceOkHttpImpl extends BaseWxMpServiceImpl<OkHttpClient, OkH
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetAccessTokenRequest() throws IOException {
|
||||
String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(getWxMpConfigStorage()), getWxMpConfigStorage().getAppId(), getWxMpConfigStorage().getSecret());
|
||||
|
||||
Request request = new Request.Builder().url(url).get().build();
|
||||
try (Response response = getRequestHttpClient().newCall(request).execute()) {
|
||||
return Objects.requireNonNull(response.body()).string();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
|
||||
String url = GET_STABLE_ACCESS_TOKEN_URL.getUrl(getWxMpConfigStorage());
|
||||
|
||||
WxMpStableAccessTokenRequest wxMaAccessTokenRequest = new WxMpStableAccessTokenRequest();
|
||||
wxMaAccessTokenRequest.setAppid(this.getWxMpConfigStorage().getAppId());
|
||||
wxMaAccessTokenRequest.setSecret(this.getWxMpConfigStorage().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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package me.chanjar.weixin.mp.bean;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author SKYhuangjing
|
||||
* 微信公众号 获取稳定版接口调用凭据 请求参数
|
||||
*/
|
||||
@Data
|
||||
public class WxMpStableAccessTokenRequest 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 WxMpGsonBuilder.create().toJson(this);
|
||||
}
|
||||
}
|
@ -20,6 +20,19 @@ public interface WxMpConfigStorage {
|
||||
*/
|
||||
String getAccessToken();
|
||||
|
||||
/**
|
||||
* Is use stable access token api
|
||||
* @Link https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/getStableAccessToken.html
|
||||
* @return the boolean
|
||||
*/
|
||||
boolean isStableAccessToken();
|
||||
|
||||
/**
|
||||
* Set use stable access token api
|
||||
* @param useStableAccessToken true is use, false is not
|
||||
*/
|
||||
void useStableAccessToken(boolean useStableAccessToken);
|
||||
|
||||
/**
|
||||
* Gets access token lock.
|
||||
*
|
||||
|
@ -24,6 +24,10 @@ public class WxMpDefaultConfigImpl implements WxMpConfigStorage, Serializable {
|
||||
|
||||
protected volatile String appId;
|
||||
protected volatile String secret;
|
||||
/**
|
||||
* 是否使用稳定版 Access Token
|
||||
*/
|
||||
private boolean useStableAccessToken;
|
||||
protected volatile String token;
|
||||
protected volatile String templateId;
|
||||
protected volatile String accessToken;
|
||||
@ -60,6 +64,16 @@ public class WxMpDefaultConfigImpl implements WxMpConfigStorage, Serializable {
|
||||
|
||||
private WxMpHostConfig hostConfig = null;
|
||||
|
||||
@Override
|
||||
public boolean isStableAccessToken() {
|
||||
return this.useStableAccessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void useStableAccessToken(boolean useStableAccessToken) {
|
||||
this.useStableAccessToken = useStableAccessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccessTokenExpired() {
|
||||
return System.currentTimeMillis() > this.expiresTime;
|
||||
|
@ -129,6 +129,10 @@ public interface WxMpApiUrl {
|
||||
* 获取access_token.
|
||||
*/
|
||||
GET_ACCESS_TOKEN_URL(API_DEFAULT_HOST_URL, "/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"),
|
||||
/**
|
||||
* 获取稳定版 access_token.
|
||||
*/
|
||||
GET_STABLE_ACCESS_TOKEN_URL(API_DEFAULT_HOST_URL, "/cgi-bin/stable_token"),
|
||||
/**
|
||||
* 获得各种类型的ticket.
|
||||
*/
|
||||
|
@ -211,6 +211,16 @@ public class BaseWxMpServiceImplTest {
|
||||
return "模拟一个过期的access token:" + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetAccessTokenRequest() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initHttp() {
|
||||
|
||||
|
@ -59,4 +59,15 @@ public class WxMpServiceImplTest {
|
||||
Assert.assertNotEquals(before, after);
|
||||
Assert.assertTrue(StringUtils.isNotBlank(after));
|
||||
}
|
||||
|
||||
public void testStableRefreshAccessToken() throws WxErrorException {
|
||||
WxMpConfigStorage configStorage = this.wxService.getWxMpConfigStorage();
|
||||
configStorage.useStableAccessToken(true);
|
||||
String before = configStorage.getAccessToken();
|
||||
this.wxService.getAccessToken(false);
|
||||
|
||||
String after = configStorage.getAccessToken();
|
||||
Assert.assertNotEquals(before, after);
|
||||
Assert.assertTrue(StringUtils.isNotBlank(after));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user