From 9a6b8574ac3f969572145398ba3acfe428f6e306 Mon Sep 17 00:00:00 2001 From: 13405411873 <1994398261@qq.com> Date: Fri, 18 Apr 2025 14:00:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83=E9=80=9A=E5=91=8A=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ruoyi/busi/utils/WeChatUtils.java | 120 ++++++++++++++++++ .../service/impl/MemberUserServiceImpl.java | 4 +- .../com/ruoyi/payConfig/WechatPayConfig.java | 1 + .../ruoyi/system/mapper/SysUserMapper.java | 28 ++-- 4 files changed, 137 insertions(+), 16 deletions(-) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/busi/utils/WeChatUtils.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/busi/utils/WeChatUtils.java b/ruoyi-admin/src/main/java/com/ruoyi/busi/utils/WeChatUtils.java new file mode 100644 index 0000000..c1ffe68 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/busi/utils/WeChatUtils.java @@ -0,0 +1,120 @@ +package com.ruoyi.busi.utils; + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.payConfig.WechatPayConfig; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.net.URLEncoder; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Component +public class WeChatUtils { + + @Resource + private WechatPayConfig wechatPayConfig; + + @Autowired + private RedisCache redisCache; + + // 获取code的接口地址 + public final static String CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; + + // 获取网页access_token的接口地址 + public final static String WEB_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code"; + + // 获取用户信息地址 + public final static String USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; + + // 获取access_token的接口地址(GET) 限2000(次/天) + public final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; + + // 发送模板消息 + public static final String SEND_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN"; + + /** + * 生成获取code的url + * + * @param backUrl 回调URL,用户同意授权后重定向的回调链接地址,需要进行URL编码 + * @param state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 + * @return 生成的获取code的URL + */ + public String getCodeUrl(String backUrl, String state) { + String requestUrl = null; + state = state == null ? "" : state; + try { + requestUrl = CODE_URL.replace("APPID", wechatPayConfig.getAppId()) + .replace("REDIRECT_URI", URLEncoder.encode(backUrl, "UTF-8")) + .replace("STATE", state); + } catch (Exception e) { + e.printStackTrace(); + } + return requestUrl; + } + + /** + * 获取微信网页access_token 和 openid + * + * @param code 用户同意授权后,通过重定向到回调链接中获取的code参数 + * @return 包含access_token和openid的JSONObject + */ + public JSONObject getWebAccessTokenAndOpenid(String code) { + String requestUrl = WEB_ACCESS_TOKEN_URL.replace("APPID", wechatPayConfig.getAppId()) + .replace("APPSECRET", wechatPayConfig.getAppSecret()) + .replace("CODE", code); + String response = HttpUtil.get(requestUrl); + return JSONUtil.parseObj(response); + } + + /** + * 网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息 + * + * @param webAccessToken 通过getWebAccessTokenAndOpenid方法获取的access_token + * @param openid 通过getWebAccessTokenAndOpenid方法获取的openid + * @return 包含用户信息的JSONObject + */ + public JSONObject getUserInfo(String webAccessToken, String openid) { + String requestUrl = USERINFO_URL.replace("ACCESS_TOKEN", webAccessToken) + .replace("OPENID", openid); + String response = HttpUtil.get(requestUrl); + return JSONUtil.parseObj(response); + } + + + /** + * 获取access_token 先从Redis获取,如果没有再调微信获取并存Redis + * + * @return 获取到的access_token + */ + public String getToken() { + String accessToken; + String redisKey = "wechat_access_token"; + + // 先从Redis获取 + accessToken = redisCache.getCacheObject(redisKey); + if (accessToken != null) { + log.debug("从Redis获取access_token: {}", accessToken); + return accessToken; + } + + // 如果Redis中没有或者强制刷新,则从微信获取 + String requestUrl = ACCESS_TOKEN_URL.replace("APPID", wechatPayConfig.getAppId()) + .replace("APPSECRET", wechatPayConfig.getAppSecret()); + String response = HttpUtil.get(requestUrl); + JSONObject jsonObject = JSONUtil.parseObj(response); + accessToken = jsonObject.getStr("access_token"); + int expiresIn = jsonObject.getInt("expires_in", 7200); // 默认有效期为7200秒 + if (accessToken != null) { + // 将access_token存入Redis,并设置有效期 + redisCache.setCacheObject(redisKey, accessToken,expiresIn - 60,TimeUnit.SECONDS); + log.debug("从微信获取access_token并存入Redis: {}", accessToken); + } + return accessToken; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/member/service/impl/MemberUserServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/member/service/impl/MemberUserServiceImpl.java index 0e80a3c..21bc757 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/member/service/impl/MemberUserServiceImpl.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/member/service/impl/MemberUserServiceImpl.java @@ -166,10 +166,10 @@ public class MemberUserServiceImpl extends ServiceImpl