package com.walker.wxtools.support;
|
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.walker.infrastructure.utils.JsonUtils;
|
import com.walker.wxtools.AbstractOfficialAccountEngine;
|
import com.walker.wxtools.BasicAccessToken;
|
import com.walker.wxtools.Constants;
|
import com.walker.wxtools.JsTicket;
|
import com.walker.wxtools.WxRemoteException;
|
import com.walker.wxtools.WxUserInfo;
|
import org.springframework.web.client.RestTemplate;
|
|
import java.util.HashMap;
|
import java.util.Map;
|
import java.util.concurrent.ConcurrentHashMap;
|
|
/**
|
* 微信公众号引擎默认实现。
|
* <p>子类可继承该对象,重写方法,以满足自己应用,例如:缓存'Redis'缓存等。</p>
|
* @author 时克英
|
* @date 2023-04-20
|
*/
|
public class DefaultOfficialAccountEngine extends AbstractOfficialAccountEngine {
|
|
@Override
|
protected JsTicket acquireCachedJsTicket(String cacheKey) {
|
return this.innerJsTicketCache.get(cacheKey);
|
}
|
|
@Override
|
protected void writeJsTicketToCache(String cacheKey, JsTicket jsTicket) {
|
if(this.innerJsTicketCache.get(cacheKey) != null){
|
this.innerJsTicketCache.remove(cacheKey);
|
}
|
this.innerJsTicketCache.put(cacheKey, jsTicket);
|
logger.info("写入'jsTicket'缓存");
|
}
|
|
@Override
|
protected JsTicket acquireRemoteJsTicket(String basicAccessToken) throws WxRemoteException {
|
this.checkRestTemplate();
|
Map<String, Object> paramMap = new HashMap<>(4);
|
paramMap.put("type", "jsapi");
|
paramMap.put("access_token", basicAccessToken);
|
|
try {
|
String entity = restTemplate.getForObject(Constants.URL_JS_TICKET, String.class, paramMap);
|
if(entity == null){
|
throw new RuntimeException("调用'jsTicket'返回空数据, basicAccessToken = " + basicAccessToken);
|
}
|
if(this.logger.isDebugEnabled()){
|
this.logger.debug(entity);
|
}
|
ObjectNode objectNode = JsonUtils.jsonStringToObjectNode(entity);
|
if(objectNode.get(Constants.NAME_ERROR_CODE).intValue() != 0){
|
throw new WxRemoteException(objectNode.get(Constants.NAME_ERROR_MESSAGE).asText(), "微信获取'jsTicket'返回错误", null);
|
}
|
|
JsTicket jsTicket = new JsTicket();
|
jsTicket.setTicket(objectNode.get("ticket").asText());
|
jsTicket.setExpireSeconds(objectNode.get(Constants.NAME_EXPIRES_IN).longValue());
|
jsTicket.setCreateTime(System.currentTimeMillis());
|
return jsTicket;
|
|
} catch (Exception ex){
|
StringBuilder error = new StringBuilder("微信远程获取'jsTicket'失败, basicAccessToken=").append(basicAccessToken);
|
if(ex instanceof WxRemoteException){
|
WxRemoteException wex = (WxRemoteException) ex;
|
throw wex;
|
} else {
|
error.append(", error = ").append(ex.getMessage());
|
}
|
throw new WxRemoteException(error.toString(), ex.getMessage(), ex);
|
}
|
}
|
|
@Override
|
protected BasicAccessToken acquireCachedBasicAccessToken(String cacheKey) {
|
// 默认实现,基于内存,获取时,需要看是否超时
|
return this.innerAccessTokenCache.get(cacheKey);
|
}
|
|
@Override
|
protected void writeBasicAccessTokenToCache(String cacheKey, BasicAccessToken basicAccessToken) {
|
if(this.innerAccessTokenCache.get(cacheKey) != null){
|
this.innerAccessTokenCache.remove(cacheKey);
|
}
|
this.innerAccessTokenCache.put(cacheKey, basicAccessToken);
|
logger.info("写入'basicAccessToken'缓存");
|
}
|
|
@Override
|
protected BasicAccessToken acquireRemoteBasicAccessToken(String appId, String secret) throws WxRemoteException {
|
this.checkRestTemplate();
|
Map<String, Object> paramMap = new HashMap<>(4);
|
paramMap.put("appid", appId);
|
paramMap.put("secret", secret);
|
paramMap.put("grant_type", "client_credential");
|
try {
|
// 必须用:get 方式
|
// ResponseEntity<String> entity = restTemplate.postForEntity(Constants.URL_BASIC_ACCESS_TOKEN, paramMap, String.class);
|
String entity = restTemplate.getForObject(Constants.URL_BASIC_ACCESS_TOKEN, String.class, paramMap);
|
if(entity == null){
|
throw new RuntimeException("调用'BasicAccessToken'返回空数据, appId = " + appId);
|
}
|
if(this.logger.isDebugEnabled()){
|
// this.logger.debug(entity.getBody());
|
this.logger.debug(entity);
|
}
|
// ObjectNode objectNode = JsonUtils.jsonStringToObjectNode(entity.getBody());
|
ObjectNode objectNode = JsonUtils.jsonStringToObjectNode(entity);
|
if(objectNode.has(Constants.NAME_ERROR_CODE)){
|
throw new WxRemoteException(objectNode.get(Constants.NAME_ERROR_MESSAGE).asText(), "微信获取'BasicAccessToken'返回错误", null);
|
}
|
BasicAccessToken basicAccessToken = new BasicAccessToken();
|
basicAccessToken.setAccessToken(objectNode.get(Constants.NAME_ACCESS_TOKEN).asText());
|
basicAccessToken.setExpireSeconds(objectNode.get(Constants.NAME_EXPIRES_IN).longValue());
|
basicAccessToken.setCreateTime(System.currentTimeMillis());
|
return basicAccessToken;
|
|
} catch (Exception ex){
|
StringBuilder error = new StringBuilder("微信远程获取'BasicAccessToken'失败, appId=");
|
error.append(appId);
|
if(ex instanceof WxRemoteException){
|
WxRemoteException wex = (WxRemoteException) ex;
|
error.append(", error = ").append(wex.getError());
|
}
|
throw new WxRemoteException(error.toString(), ex.getMessage(), ex);
|
}
|
}
|
|
@Override
|
protected WxUserInfo acquireRemoteUserInfoSub(String openId, String basicAccessToken) throws WxRemoteException {
|
this.checkRestTemplate();
|
Map<String, Object> paramMap = new HashMap<>(4);
|
paramMap.put("access_token", basicAccessToken);
|
paramMap.put("openid", openId);
|
paramMap.put("lang", "zh_CN");
|
|
try {
|
String entity = restTemplate.getForObject(Constants.URL_USER_INFO_SUB, String.class, paramMap);
|
if(entity == null){
|
throw new RuntimeException("调用'userInfoSub'返回空数据, openId = " + openId + ", access_token=" + basicAccessToken);
|
}
|
ObjectNode objectNode = JsonUtils.jsonStringToObjectNode(entity);
|
if(objectNode.has(Constants.NAME_ERROR_CODE)){
|
throw new WxRemoteException(objectNode.get(Constants.NAME_ERROR_MESSAGE).asText(), "微信获取'userInfoSub'返回错误", null);
|
}
|
WxUserInfo userInfo = JsonUtils.jsonStringToObject(entity, WxUserInfo.class);
|
return userInfo;
|
|
} catch (Exception ex){
|
StringBuilder error = new StringBuilder("微信远程获取'userInfoSub'失败, openId=");
|
error.append(openId);
|
if(ex instanceof WxRemoteException){
|
WxRemoteException wex = (WxRemoteException) ex;
|
// error.append(", error = ").append(wex.getError());
|
throw wex;
|
} else {
|
error.append(", error = ").append(ex.getMessage());
|
}
|
throw new WxRemoteException(error.toString(), ex.getMessage(), ex);
|
}
|
}
|
|
private void checkRestTemplate(){
|
if(this.restTemplate == null){
|
throw new IllegalArgumentException("RestTemplate未配置!");
|
}
|
}
|
|
public void setRestTemplate(RestTemplate restTemplate) {
|
this.restTemplate = restTemplate;
|
}
|
|
private final Map<String, JsTicket> innerJsTicketCache = new ConcurrentHashMap<>(8);
|
private final Map<String, BasicAccessToken> innerAccessTokenCache = new ConcurrentHashMap<>(8);
|
private RestTemplate restTemplate;
|
}
|