refactor(wxOfficial): 优化公众号配置和access_token获取逻辑
- 增加SettingService和WxService注入,提高配置获取灵活性 - 将access_token获取方法重载,支持按租户动态读取 - 新增getOfficialToken、getOfficialEncodingAESKey、getOfficialAppId方法,从系统设置读取配置 - 解密消息时改用动态获取的token、EncodingAESKey和AppId - 微信用户信息请求改为支持按租户获取access_token - access_token获取失败时添加异常日志并回退到兼容逻辑 - 移除硬编码逻辑,增强配置读取的可扩展性与健壮性
This commit is contained in:
@@ -24,10 +24,12 @@ import com.gxwebsoft.common.system.entity.*;
|
|||||||
import com.gxwebsoft.common.system.param.RoleParam;
|
import com.gxwebsoft.common.system.param.RoleParam;
|
||||||
import com.gxwebsoft.common.system.param.UserParam;
|
import com.gxwebsoft.common.system.param.UserParam;
|
||||||
import com.gxwebsoft.common.system.service.RoleService;
|
import com.gxwebsoft.common.system.service.RoleService;
|
||||||
|
import com.gxwebsoft.common.system.service.SettingService;
|
||||||
import com.gxwebsoft.common.system.service.UserOauthService;
|
import com.gxwebsoft.common.system.service.UserOauthService;
|
||||||
import com.gxwebsoft.common.system.service.UserRoleService;
|
import com.gxwebsoft.common.system.service.UserRoleService;
|
||||||
import com.gxwebsoft.common.system.service.UserService;
|
import com.gxwebsoft.common.system.service.UserService;
|
||||||
import com.gxwebsoft.common.system.service.UserSyncService;
|
import com.gxwebsoft.common.system.service.UserSyncService;
|
||||||
|
import com.gxwebsoft.common.system.service.WxService;
|
||||||
import com.gxwebsoft.common.system.vo.WxOfficialButton;
|
import com.gxwebsoft.common.system.vo.WxOfficialButton;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
@@ -88,6 +90,10 @@ public class WxOfficialController extends BaseController {
|
|||||||
@Resource
|
@Resource
|
||||||
private UserOauthService userOauthService;
|
private UserOauthService userOauthService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private SettingService settingService;
|
||||||
|
@Resource
|
||||||
|
private WxService wxService;
|
||||||
|
@Resource
|
||||||
private RedisUtil redisUtil;
|
private RedisUtil redisUtil;
|
||||||
|
|
||||||
@Operation(summary = "验证微信服务器")
|
@Operation(summary = "验证微信服务器")
|
||||||
@@ -98,7 +104,7 @@ public class WxOfficialController extends BaseController {
|
|||||||
if (tenantId == null) {
|
if (tenantId == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String token = TOKEN;
|
String token = getOfficialToken();
|
||||||
String[] array = new String[]{token, timestamp, nonce};
|
String[] array = new String[]{token, timestamp, nonce};
|
||||||
// 将token、timestamp、nonce三个参数进行字典序排序
|
// 将token、timestamp、nonce三个参数进行字典序排序
|
||||||
Arrays.sort(array);
|
Arrays.sort(array);
|
||||||
@@ -133,7 +139,7 @@ public class WxOfficialController extends BaseController {
|
|||||||
// 如果有加密参数,进行解密
|
// 如果有加密参数,进行解密
|
||||||
if (StrUtil.isNotBlank(msg_signature) && StrUtil.isNotBlank(xmlData) && xmlData.contains("Encrypt")) {
|
if (StrUtil.isNotBlank(msg_signature) && StrUtil.isNotBlank(xmlData) && xmlData.contains("Encrypt")) {
|
||||||
try {
|
try {
|
||||||
WXBizJsonMsgCrypt crypt = new WXBizJsonMsgCrypt(TOKEN, ENCODING_AES_KEY, "");
|
WXBizJsonMsgCrypt crypt = new WXBizJsonMsgCrypt(getOfficialToken(), getOfficialEncodingAESKey(), getOfficialAppId(tenantId));
|
||||||
xmlData = crypt.DecryptMsg(msg_signature, timestamp, nonce, xmlData);
|
xmlData = crypt.DecryptMsg(msg_signature, timestamp, nonce, xmlData);
|
||||||
System.out.println("解密后xmlData = " + xmlData);
|
System.out.println("解密后xmlData = " + xmlData);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -189,7 +195,7 @@ public class WxOfficialController extends BaseController {
|
|||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
if (StrUtil.isNotBlank(openId)) {
|
if (StrUtil.isNotBlank(openId)) {
|
||||||
// 获取用户基本信息(UnionID机制)
|
// 获取用户基本信息(UnionID机制)
|
||||||
final String userStr = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + getAccessToken() + "&openid=" + openId + "&lang=zh_CN");
|
final String userStr = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + getAccessToken(tenantId) + "&openid=" + openId + "&lang=zh_CN");
|
||||||
final JSONObject jsonObject = JSONObject.parseObject(userStr);
|
final JSONObject jsonObject = JSONObject.parseObject(userStr);
|
||||||
final String unionid = jsonObject.getString("unionid");
|
final String unionid = jsonObject.getString("unionid");
|
||||||
final String subscribe = jsonObject.getString("subscribe");
|
final String subscribe = jsonObject.getString("subscribe");
|
||||||
@@ -451,30 +457,65 @@ public class WxOfficialController extends BaseController {
|
|||||||
|
|
||||||
// 调用接口凭证
|
// 调用接口凭证
|
||||||
private String getAccessToken() {
|
private String getAccessToken() {
|
||||||
|
return getAccessToken(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getAccessToken(Integer tenantId) {
|
||||||
|
try {
|
||||||
|
return wxService.getOfficialAccessToken(tenantId);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("从系统设置获取公众号access_token失败,回退到兼容逻辑: {}", ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
String key = MP_OFFICIAL.concat(":access_token:5");
|
String key = MP_OFFICIAL.concat(":access_token:5");
|
||||||
// 从缓存获取access_token
|
|
||||||
String value = redisUtil.get(key);
|
String value = redisUtil.get(key);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
// 解析access_token
|
|
||||||
JSONObject response = JSON.parseObject(value);
|
JSONObject response = JSON.parseObject(value);
|
||||||
return response.getString("access_token");
|
return response.getString("access_token");
|
||||||
}
|
}
|
||||||
// 微信获取凭证接口https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
|
|
||||||
String apiUrl = "https://api.weixin.qq.com/cgi-bin/token";
|
String apiUrl = "https://api.weixin.qq.com/cgi-bin/token";
|
||||||
// 组装url参数
|
|
||||||
String url = apiUrl.concat("?grant_type=client_credential").concat("&appid=").concat(appid).concat("&secret=").concat(secret);
|
String url = apiUrl.concat("?grant_type=client_credential").concat("&appid=").concat(appid).concat("&secret=").concat(secret);
|
||||||
// 执行get请求
|
|
||||||
String result = HttpUtil.get(url);
|
String result = HttpUtil.get(url);
|
||||||
// 解析access_token
|
|
||||||
JSONObject response = JSON.parseObject(result);
|
JSONObject response = JSON.parseObject(result);
|
||||||
if (response.getString("access_token") != null) {
|
if (response.getString("access_token") != null) {
|
||||||
// 存入缓存
|
|
||||||
redisUtil.set(key, result, 7000L, TimeUnit.SECONDS);
|
redisUtil.set(key, result, 7000L, TimeUnit.SECONDS);
|
||||||
return response.getString("access_token");
|
return response.getString("access_token");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getOfficialToken() {
|
||||||
|
try {
|
||||||
|
JSONObject config = settingService.getBySettingKey("wx-official");
|
||||||
|
String token = config.getString("token");
|
||||||
|
return StrUtil.isNotBlank(token) ? token : TOKEN;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("读取公众号token配置失败,回退到硬编码值: {}", ex.getMessage());
|
||||||
|
return TOKEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getOfficialEncodingAESKey() {
|
||||||
|
try {
|
||||||
|
JSONObject config = settingService.getBySettingKey("wx-official");
|
||||||
|
String encodingAESKey = config.getString("encodingAESKey");
|
||||||
|
return StrUtil.isNotBlank(encodingAESKey) ? encodingAESKey : ENCODING_AES_KEY;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("读取公众号EncodingAESKey配置失败,回退到硬编码值: {}", ex.getMessage());
|
||||||
|
return ENCODING_AES_KEY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getOfficialAppId(Integer tenantId) {
|
||||||
|
try {
|
||||||
|
return wxService.getOfficialAppId(tenantId);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("读取公众号AppId配置失败,回退到硬编码值: {}", ex.getMessage());
|
||||||
|
return appid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "创建公众号菜单接口")
|
@Operation(summary = "创建公众号菜单接口")
|
||||||
@PostMapping("/createMenu")
|
@PostMapping("/createMenu")
|
||||||
public ApiResult<?> createMenu() {
|
public ApiResult<?> createMenu() {
|
||||||
|
|||||||
Reference in New Issue
Block a user