feat(企业微信): 新增多应用支持及优化企业微信相关功能

- 新增获取模板应用ID列表接口
- 新增根据corpid查询企业授权信息接口
- 优化企业微信消息任务支持多应用
- 重构企业微信相关服务调用逻辑
- 增加企业微信令牌自动刷新机制
This commit is contained in:
dzq 2025-09-18 15:47:24 +08:00
parent d50b06403d
commit c6b2c98bd8
21 changed files with 222 additions and 87 deletions

View File

@ -13,6 +13,8 @@ import com.agileboot.domain.common.dto.CurrentLoginUserDTO;
import com.agileboot.domain.common.dto.TokenDTO;
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity;
import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoService;
import com.agileboot.domain.qywx.user.QyUserApplicationService;
import com.agileboot.domain.qywx.user.dto.QyUserDTO;
import com.agileboot.domain.qywx.userQySys.SysUserQyUserApplicationService;
@ -71,6 +73,8 @@ public class LoginController {
private final QyUserApplicationService qyUserApplicationService;
private final QyAuthCorpInfoService qyAuthCorpInfoService;
/**
* 访问首页提示语
*/
@ -179,7 +183,12 @@ public class LoginController {
@GetMapping("/getQyUserinfo")
public ResponseDTO<String> getQyUserinfo(String corpid, String code) {
try {
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
QyAuthCorpInfoEntity qyAuthCorpInfo = qyAuthCorpInfoService.selectByCorpid(corpid);
if (qyAuthCorpInfo == null) {
log.error("获取企业微信应用配置失败, corpid: {}", corpid);
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "无效的corpid参数"));
}
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid(qyAuthCorpInfo.getAppid(), corpid);
String url = String.format(
"https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=%s&code=%s",
qyAccessToken.getAccessToken(), code);

View File

@ -13,6 +13,8 @@ import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
import com.agileboot.domain.qywx.api.QywxApiUtil;
import com.agileboot.domain.qywx.api.response.OpenidResponse;
import com.agileboot.domain.qywx.api.response.UserIdResponse;
import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity;
import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoService;
import com.agileboot.domain.qywx.user.QyUserApplicationService;
import com.agileboot.domain.qywx.user.command.AddQyUserCommand;
import com.agileboot.domain.qywx.user.command.UpdateQyUserCommand;
@ -38,6 +40,7 @@ public class QyUserController extends BaseController {
private final QyUserApplicationService qyUserApplicationService;
private final QywxScheduleJob qywxScheduleJob;
private final AccessTokenApplicationService accessTokenApplicationService;
private final QyAuthCorpInfoService qyAuthCorpInfoService;
@Operation(summary = "用户列表")
@GetMapping
@ -94,13 +97,21 @@ public class QyUserController extends BaseController {
@GetMapping("/convertToOpenid")
public ResponseDTO<String> convertToOpenid(String corpid, String userid) {
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
QyAuthCorpInfoEntity authCorpInfo = qyAuthCorpInfoService.selectByCorpid(corpid);
if (authCorpInfo == null) {
return ResponseDTO.fail("corpid不存在");
}
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), corpid);
OpenidResponse response = QywxApiUtil.convertToOpenid(accessToken.getAccessToken(), userid);
return ResponseDTO.ok(JSONUtil.toJsonStr(response));
}
@GetMapping("/convertToUserid")
public ResponseDTO<String> convertToUserid(String corpid, String openid) {
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
QyAuthCorpInfoEntity authCorpInfo = qyAuthCorpInfoService.selectByCorpid(corpid);
if (authCorpInfo == null) {
return ResponseDTO.fail("corpid不存在");
}
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), corpid);
UserIdResponse response = QywxApiUtil.convertToUserid(accessToken.getAccessToken(), openid);
return ResponseDTO.ok(JSONUtil.toJsonStr(response));
}

View File

@ -79,7 +79,7 @@ public class QywxScheduleJob {
* 企业微信应用ID常量
* 用于标识当前集成的第三方应用对应企业微信服务商后台配置的应用凭证
*/
private static final String appid2 = "QWTONG_YS_WXSHOP";
// private static final String appid2 = "QWTONG_YS_WXSHOP";
/**
* 定时获取第三方应用凭证suite_access_token
@ -96,16 +96,13 @@ public class QywxScheduleJob {
*/
@Scheduled(cron = "0 10 * * * *")
public void getSuiteAccessTokenTask() {
/*try {
List<String> appidList = templateApplicationService.getTemplateAppidList();
for (String appid : appidList) {
try {
getSuiteAccessToken(appid);
} catch (Exception e) {
log.error("getSuiteAccessTokenTask appid: " + appid, e);
}*/
try {
getSuiteAccessToken(appid2);
} catch (Exception e) {
log.error("getSuiteAccessTokenTask appid: " + appid2, e);
}
}
}
@ -154,10 +151,13 @@ public class QywxScheduleJob {
log.error("getAccessTokenTask error appid: " + appid, e);
}*/
List<String> appidList = templateApplicationService.getTemplateAppidList();
for (String appid : appidList) {
try {
getAccessToken(appid2);
getAccessToken(appid);
} catch (Exception e) {
log.error("getAccessTokenTask error appid: " + appid2, e);
log.error("getAccessTokenTask error appid: " + appid, e);
}
}
}
@ -208,16 +208,19 @@ public class QywxScheduleJob {
log.error("syncDepartmentInfoTask error appid: " + appid, e);
}*/
List<String> appidList = templateApplicationService.getTemplateAppidList();
for (String appid : appidList) {
try {
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid2);
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
if (null == authCorpInfoList || authCorpInfoList.isEmpty()) {
return;
}
for (QyAuthCorpInfoEntity authCorpInfo : authCorpInfoList) {
syncDepartmentInfo(appid2, authCorpInfo);
syncDepartmentInfo(appid, authCorpInfo);
}
} catch (Exception e) {
log.error("syncDepartmentInfoTask error appid: " + appid2, e);
log.error("syncDepartmentInfoTask error appid: " + appid, e);
}
}
}
@ -382,16 +385,19 @@ public class QywxScheduleJob {
log.error("syncUserInfoTask error appid: " + appid, e);
}*/
List<String> appidList = templateApplicationService.getTemplateAppidList();
for (String appid : appidList) {
try {
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid2);
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
if (null == authCorpInfoList || authCorpInfoList.isEmpty()) {
return;
}
for (QyAuthCorpInfoEntity authCorpInfo : authCorpInfoList) {
syncUserInfo(appid2, authCorpInfo);
syncUserInfo(appid, authCorpInfo);
}
} catch (Exception e) {
log.error("syncUserInfoTask error appid: " + appid2, e);
log.error("syncUserInfoTask error appid: " + appid, e);
}
}
}
@ -613,10 +619,14 @@ public class QywxScheduleJob {
*/
@Scheduled(cron = "0 45 * * * *")
public void getAuthInfoTask() {
List<String> appidList = templateApplicationService.getTemplateAppidList();
for (String appid : appidList) {
try {
getAuthInfo(appid2);
getAuthInfo(appid);
} catch (Exception e) {
log.error("getAuthInfoTask error appid: " + appid2, e);
log.error("getAuthInfoTask error appid: " + appid, e);
}
}
}
@ -687,7 +697,7 @@ public class QywxScheduleJob {
try {
syncUserBindings();
} catch (Exception e) {
log.error("syncUserBindingsTask error appid: " + appid2, e);
log.error("syncUserBindingsTask error: ", e);
}
}

View File

@ -151,12 +151,8 @@ public class DeadlineOrderJob {
// 发送审核消息
try {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoList.stream()
.filter(a -> order.getCorpid().equals(a.getCorpid()))
.findFirst().orElse(null);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, authCorpInfo.getCorpid());
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(order.getCorpid());
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), authCorpInfo.getCorpid());
sendReviewNotification(order, orderGoods, authCorpInfo, accessToken, returnDeadlineDays, deadlineDate);
} catch (Exception e) {
log.error("发送逾期未归还通知失败", e);

View File

@ -58,13 +58,6 @@ public class QywxMessageJob {
private final CabinetCellService cabinetCellService;
private final SmartCabinetService smartCabinetService;
// private static final String appid = "QYTONG_YS_WXSHOP";
/**
* 企业微信应用ID常量
* 用于标识当前集成的第三方应用对应企业微信服务商后台配置的应用凭证
*/
private static final String appid2 = "QWTONG_YS_WXSHOP";
/**
* 每天向逾期未归还商品的用户发送提醒消息
* 执行时间每天10点
@ -72,16 +65,23 @@ public class QywxMessageJob {
@Scheduled(cron = "0 0 10 * * *")
public void sendOverdueGoodsReminderTask() {
try {
List<String> appidList = templateApplicationService.getTemplateAppidList();
if (CollectionUtils.isEmpty(appidList)) {
log.info("没有找到已授权的应用ID");
return;
}
for (String appid : appidList) {
// 1. 获取所有已授权企业信息
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid2);
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
if (CollectionUtils.isEmpty(authCorpInfoList)) {
log.info("没有找到已授权的企业信息");
return;
continue;
}
// 2. 遍历企业处理
for (QyAuthCorpInfoEntity authCorpInfo : authCorpInfoList) {
sendOverdueReminderForCorp(appid2, authCorpInfo);
sendOverdueReminderForCorp(appid, authCorpInfo);
}
}
} catch (Exception e) {
log.error("发送逾期商品提醒任务失败", e);

View File

@ -25,6 +25,8 @@ import com.agileboot.domain.common.cache.RedisCacheService;
import com.agileboot.admin.customize.async.AsyncTaskFactory;
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
import com.agileboot.domain.qywx.authCorpInfo.AuthCorpInfoApplicationService;
import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity;
import com.agileboot.domain.qywx.userQySys.SysUserQyUserApplicationService;
import com.agileboot.infrastructure.thread.ThreadPoolManager;
import com.agileboot.admin.customize.service.login.dto.CaptchaDTO;
@ -75,6 +77,7 @@ public class LoginService {
private final FakeUserDetailsServiceImpl fakeUserDetailsService;
private final SysUserQyUserApplicationService sysUserQyUserApplicationService;
private final AuthCorpInfoApplicationService authCorpInfoApplicationService;
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@ -258,7 +261,11 @@ public class LoginService {
private String getQyUserid(String corpid, String code) {
try {
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(corpid);
if (authCorpInfo == null) {
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "corpid不存在");
}
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), corpid);
String url = String.format(
"https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=%s&code=%s",
qyAccessToken.getAccessToken(), code);

View File

@ -181,7 +181,8 @@ public class PaymentController {
@GetMapping("/login/qy")
public ResponseDTO<QyLoginDTO> qyLogin(String corpid, String code, String state) {
try {
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(corpid);
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), corpid);
// 通过企业微信code获取用户ID
String userid = QywxApiUtil.getQyUserid(qyAccessToken.getAccessToken(), code);
// 根据企业微信用户ID查询系统用户名
@ -225,7 +226,8 @@ public class PaymentController {
@GetMapping("/login/qy/fake")
public ResponseDTO<QyLoginDTO> fakeQyLogin(String corpid, String userid) {
try {
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(corpid);
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), corpid);
// 通过企业微信code获取用户ID
// 根据企业微信用户ID查询系统用户名
SysUserEntity sysUserEntity = sysUserQyUserApplicationService.getSysUserByQyUserid(userid);
@ -294,9 +296,8 @@ public class PaymentController {
*/
@GetMapping("/getBalance")
public ResponseDTO<GetBalanceResponse> getBalance(@RequestParam String corpid, @RequestParam String openid) {
String appid = "QWTONG_YS_WXSHOP";
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, corpid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(corpid);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), corpid);
UserIdResponse userIdResponse = QywxApiUtil.convertToUserid(accessToken.getAccessToken(), openid);
QyUserEntity qyUser = qyUserApplicationService.getUserByUserIdAndCorpid(userIdResponse.getUserid(), corpid);
if (qyUser == null) {

View File

@ -5,6 +5,7 @@ import com.agileboot.api.customize.async.QyAsyncTaskFactory;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.utils.weixin.aes.WXBizMsgCrypt;
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
import com.agileboot.domain.qywx.api.QywxApiUtil;
import com.agileboot.domain.qywx.api.response.GetAuthInfoResult;
import com.agileboot.domain.qywx.auth.AuthApplicationService;
@ -23,6 +24,7 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
@ -47,6 +49,7 @@ public class QywxController {
private final TemplateApplicationService templateApplicationService;
private final AuthApplicationService authApplicationService;
private final AuthCorpInfoApplicationService authCorpInfoApplicationService;
private final AccessTokenApplicationService accessTokenApplicationService;
@GetMapping("/getPermanentCode")
public String getPermanentCode(
@ -105,6 +108,7 @@ public class QywxController {
String token = template.getToken();
String encodingAesKey = template.getEncodingAESKey();
String corpId = template.getCorpid();
log.info("validateDataCallback, token: {}, encodingAesKey: {}, corpId: {}", token, encodingAesKey, corpId);
WXBizMsgCrypt wxCrypt = new WXBizMsgCrypt(token, encodingAesKey, corpId);
return wxCrypt.VerifyURL(msg_signature, timestamp, nonce, echostr);
} catch (Exception e) {
@ -162,7 +166,18 @@ public class QywxController {
@RequestParam String nonce,
@RequestParam String echostr,
@RequestParam String appid) {
return validateDataCallback(msg_signature, timestamp, nonce, echostr, appid);
try {
QyTemplateEntity template = templateApplicationService.getByAppid(appid);
String token = template.getToken();
String encodingAesKey = template.getEncodingAESKey();
String corpId = template.getCorpid();
log.info("validateCommandCallback, token: {}, encodingAesKey: {}, corpId: {}", token, encodingAesKey, corpId);
WXBizMsgCrypt wxCrypt = new WXBizMsgCrypt(token, encodingAesKey, corpId);
return wxCrypt.VerifyURL(msg_signature, timestamp, nonce, echostr);
} catch (Exception e) {
log.error("验证失败", e);
throw new ApiException(ErrorCode.FAILED, "验证失败", e);
}
}
@PostMapping("/callback/command")
@ -197,6 +212,8 @@ public class QywxController {
authCommand.setSuiteTicket(SuiteTicket);
authApplicationService.addAuth(authCommand);
templateApplicationService.checkAndRefreshSuiteAccessToken(appid);
}
break;
case "create_auth":
@ -218,6 +235,13 @@ public class QywxController {
// 提交异步任务
// ThreadPoolManager.execute(QyAsyncTaskFactory.getPermanentCodeTask(suiteAccessToken, AuthCode));
QyAsyncTaskFactory.getPermanentCode(suiteAccessToken, AuthCode, appid);
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
if (CollectionUtils.isNotEmpty(authCorpInfoList)) {
for (QyAuthCorpInfoEntity authCorpInfo : authCorpInfoList) {
accessTokenApplicationService.getAccessToken(authCorpInfo.getCorpid(), authCorpInfo.getPermanentCode(), appid);
}
}
}
break;
default:

View File

@ -66,6 +66,8 @@ public class QyAsyncTaskFactory {
AuthCorpInfoApplicationService authCorpInfoApplicationService = SpringUtil.getBean(AuthCorpInfoApplicationService.class);
authCorpInfoApplicationService.addAuthCorpInfo(command);
// UpdateAuthCorpInfoCommand updateAuthCorpInfoCommand = new UpdateAuthCorpInfoCommand();
// BeanUtils.copyProperties(command, updateAuthCorpInfoCommand);
/*try {

View File

@ -179,12 +179,8 @@ public class AssetApplicationService {
ShopGoodsEntity firstGoods = shopGoodsService.getGoodsByExternalGoodsId(postAssetApprovalCommand.getCorpid(), postAssetApprovalCommand.getGoodsInfoList().get(0).getExternalGoodsId());
// 发送审核消息
try {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoList.stream()
.filter(a -> postAssetApprovalCommand.getCorpid().equals(a.getCorpid()))
.findFirst().orElse(null);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, postAssetApprovalCommand.getCorpid());
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(postAssetApprovalCommand.getCorpid());
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), postAssetApprovalCommand.getCorpid());
// 获取用户ID
List<String> adminUserIds = qyUserService.selectAdminUserIds(postAssetApprovalCommand.getCorpid());
String toUser = String.join("|", adminUserIds);

View File

@ -60,6 +60,25 @@ public class AccessTokenApplicationService {
return accessTokenService.getByAppid(appid, corpid);
}
public void checkAndRefreshAccessToken(String appid, String corpid, String corpsecret) {
QyAccessTokenEntity accessToken = accessTokenService.getByAppid(appid, corpid);
if (null == accessToken) {
getAccessToken(corpid, corpsecret, appid);
} else {
// 计算令牌是否已经过期或即将过期提前10分钟刷新
Date now = new Date();
long getTokenTime = accessToken.getGettokenTime().getTime();
long currentTime = now.getTime();
long elapsedTime = (currentTime - getTokenTime) / 1000; // 转换为秒
// 如果已经过期或剩余时间少于30分钟1800秒则刷新令牌
if (elapsedTime >= accessToken.getExpiresIn() ||
(accessToken.getExpiresIn() - elapsedTime) < 1800) {
getAccessToken(corpid, corpsecret, appid);
}
}
}
public void getAccessToken(String corpid, String corpsecret, String appid) {
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="+corpid+"&corpsecret="+corpsecret;

View File

@ -58,4 +58,8 @@ public class AuthCorpInfoApplicationService {
public QyAuthCorpInfoEntity selectByAppidAndCorpid(String appid, String corpid) {
return authCorpInfoService.selectByAppidAndCorpid(appid, corpid);
}
public QyAuthCorpInfoEntity selectByCorpid(String corpid) {
return authCorpInfoService.selectByCorpid(corpid);
}
}

View File

@ -38,4 +38,7 @@ public interface QyAuthCorpInfoMapper extends BaseMapper<QyAuthCorpInfoEntity> {
@Select("SELECT * FROM qy_auth_corp_info WHERE appid = #{appid} AND corpid = #{corpid} LIMIT 1")
QyAuthCorpInfoEntity selectByAppidAndCorpid(@Param("appid")String appid, @Param("corpid")String corpid);
@Select("SELECT * FROM qy_auth_corp_info WHERE corpid = #{corpid} LIMIT 1")
QyAuthCorpInfoEntity selectByCorpid(@Param("corpid")String corpid);
}

View File

@ -24,4 +24,6 @@ public interface QyAuthCorpInfoService extends IService<QyAuthCorpInfoEntity> {
List<QyAuthCorpInfoEntity> getByAppid(String appid);
QyAuthCorpInfoEntity selectByAppidAndCorpid(String appid, String corpid);
QyAuthCorpInfoEntity selectByCorpid(String corpid);
}

View File

@ -38,4 +38,9 @@ public class QyAuthCorpInfoServiceImpl extends ServiceImpl<QyAuthCorpInfoMapper,
public QyAuthCorpInfoEntity selectByAppidAndCorpid(String appid, String corpid) {
return baseMapper.selectByAppidAndCorpid(appid, corpid);
}
@Override
public QyAuthCorpInfoEntity selectByCorpid(String corpid) {
return baseMapper.selectByCorpid(corpid);
}
}

View File

@ -12,12 +12,15 @@ import com.agileboot.domain.qywx.template.model.TemplateModel;
import com.agileboot.domain.qywx.template.model.TemplateModelFactory;
import com.agileboot.domain.qywx.template.query.SearchQyTemplateQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
@ -102,4 +105,37 @@ public class TemplateApplicationService {
return jsonObject.getStr("suite_access_token");
}
public void checkAndRefreshSuiteAccessToken(String appid) {
QyTemplateEntity template = getByAppid(appid);
if (template == null) {
log.error("checkAndRefreshSuiteAccessToken template is null, appid: {}", appid);
return;
}
// 计算令牌是否已经过期或即将过期提前10分钟刷新
Date now = new Date();
long getTokenTime = template.getGettokenTime().getTime();
long currentTime = now.getTime();
long elapsedTime = (currentTime - getTokenTime) / 1000; // 转换为秒
// 如果已经过期或剩余时间少于30分钟1800秒则刷新令牌
if (StringUtils.isBlank(template.getSuiteAccessToken()) || elapsedTime >= template.getExpiresIn() ||
(template.getExpiresIn() - elapsedTime) < 1800) {
String suiteAccessToken = getSuiteAccessToken(template.getSuiteId(), template.getSecret(), template.getSuiteTicket());
if (StringUtils.isNotBlank(suiteAccessToken)) {
template.setSuiteAccessToken(suiteAccessToken);
template.setGettokenTime(now);
templateService.updateById(template);
} else {
log.error("checkAndRefreshSuiteAccessToken getSuiteAccessToken failed, appid: {}", appid);
}
}
}
public List<String> getTemplateAppidList() {
return templateService.getTemplateAppidList();
}
}

View File

@ -43,4 +43,7 @@ public interface QyTemplateMapper extends BaseMapper<QyTemplateEntity> {
@Select("SELECT * FROM qy_template WHERE appid = #{appid} LIMIT 1")
QyTemplateEntity selectByAppid(String appid);
@Select("SELECT DISTINCT appid FROM qy_template WHERE enable = '1'")
List<String> getTemplateAppidList();
}

View File

@ -23,4 +23,6 @@ public interface QyTemplateService extends IService<QyTemplateEntity> {
QyTemplateEntity getBySuiteId(String suiteId);
public QyTemplateEntity getByAppid(String appid);
public List<String> getTemplateAppidList();
}

View File

@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
@Service
@ -37,4 +39,11 @@ public class QyTemplateServiceImpl extends ServiceImpl<QyTemplateMapper, QyTempl
public QyTemplateEntity getByAppid(String appid) {
return baseMapper.selectByAppid(appid);
}
@Override
public List<String> getTemplateAppidList() {
return baseMapper.getTemplateAppidList().stream().distinct().collect(Collectors.toList());
}
}

View File

@ -253,7 +253,8 @@ public class ReturnApprovalApplicationService {
} else if (Objects.equals(orderModel.getPaymentMethod(), "balance")) {
// 余额退款
try {
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", model.getCorpid());
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(model.getCorpid());
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), model.getCorpid());
String userid = QywxApiUtil.convertToUserid(accessToken.getAccessToken(), orderModel.getOpenid()).getUserid();
QyUserEntity qyUser = userService.getUserByUserIdAndCorpid(userid, model.getCorpid());
if (null != qyUser) {
@ -795,12 +796,8 @@ public class ReturnApprovalApplicationService {
// 发送审核消息
try {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoList.stream()
.filter(a -> command.getCorpid().equals(a.getCorpid()))
.findFirst().orElse(null);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, authCorpInfo.getCorpid());
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(command.getCorpid());
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), command.getCorpid());
// 获取用户ID
List<String> adminUserIds = qyUserService.selectAdminUserIds(command.getCorpid());
String toUser = String.join("|", adminUserIds);

View File

@ -260,12 +260,11 @@ public class OrderApplicationService {
// 发送审核消息
try {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoList.stream()
.filter(a -> command.getCorpid().equals(a.getCorpid()))
.findFirst().orElse(null);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, authCorpInfo.getCorpid());
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.selectByCorpid(command.getCorpid());
if (authCorpInfo == null) {
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "corpid不存在");
}
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(authCorpInfo.getAppid(), authCorpInfo.getCorpid());
// 获取用户ID
List<String> adminUserIds = qyUserService.selectAdminUserIds(submitOrderCommand.getCorpid());
String toUser = String.join("|", adminUserIds);