diff --git a/flossom-common/flossom-common-core/src/main/java/com/flossom/common/core/constant/CacheConstants.java b/flossom-common/flossom-common-core/src/main/java/com/flossom/common/core/constant/CacheConstants.java index d3c10c5..4a644a3 100644 --- a/flossom-common/flossom-common-core/src/main/java/com/flossom/common/core/constant/CacheConstants.java +++ b/flossom-common/flossom-common-core/src/main/java/com/flossom/common/core/constant/CacheConstants.java @@ -62,5 +62,13 @@ public class CacheConstants */ public static final String WX_SESSION_KEY_CACHE = "wx_session_key:"; + /** + * 微信小程序 access_token + */ public static final String WX_ACCESS_TOKEN_CACHE = "wx_access_token_cache:"; + + /** + * 微信小程序 access_token + */ + public static final long WX_ACCESS_TOKEN_EXPIRATION = 120; } diff --git a/flossom-common/flossom-common-security/src/main/java/com/flossom/common/security/service/TokenService.java b/flossom-common/flossom-common-security/src/main/java/com/flossom/common/security/service/TokenService.java index dbce0f2..f9f7bfd 100644 --- a/flossom-common/flossom-common-security/src/main/java/com/flossom/common/security/service/TokenService.java +++ b/flossom-common/flossom-common-security/src/main/java/com/flossom/common/security/service/TokenService.java @@ -5,6 +5,7 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; +import com.flossom.common.core.domain.entity.WxUserMember; import com.flossom.common.security.utils.SecurityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -151,6 +152,10 @@ public class TokenService if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { refreshToken(loginUser); + // 判断是否是微信用户 + if(loginUser.getWxUserMember() != null) { + refreshSessionKey(loginUser); + } } } @@ -168,6 +173,21 @@ public class TokenService redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); } + /** + * 刷新session_key有效期 + * + * @param loginUser 登录信息 + */ + public void refreshSessionKey(LoginUser loginUser) + { + WxUserMember wxUserMember = loginUser.getWxUserMember(); + String sessionKey = redisService.getCacheObject(CacheConstants.WX_SESSION_KEY_CACHE + wxUserMember.getOpenid()); + if(StringUtils.isNotBlank(sessionKey)) { + redisService.setCacheObject(CacheConstants.WX_SESSION_KEY_CACHE + wxUserMember.getOpenid(), + sessionKey, CacheConstants.EXPIRATION, TimeUnit.MINUTES); + } + } + private String getTokenKey(String token) { return ACCESS_TOKEN + token; diff --git a/flossom-modules/flossom-mini-program/pom.xml b/flossom-modules/flossom-mini-program/pom.xml index bbce8c2..3344c69 100644 --- a/flossom-modules/flossom-mini-program/pom.xml +++ b/flossom-modules/flossom-mini-program/pom.xml @@ -91,6 +91,17 @@ 4.5.2 + + junit + junit + test + + + org.springframework.boot + spring-boot-starter-test + test + + diff --git a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/service/impl/WxUserMemberServiceImpl.java b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/service/impl/WxUserMemberServiceImpl.java index 138cfd2..7720cf1 100644 --- a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/service/impl/WxUserMemberServiceImpl.java +++ b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/service/impl/WxUserMemberServiceImpl.java @@ -82,7 +82,10 @@ public class WxUserMemberServiceImpl implements IWxUserMemberService { throw new ServiceException(loginResult.getMsg()); } /** - * TODO: 暂时将session_key保存在redis,后期根据业务修改 + * TODO: 将 session_key 缓存在 redis,并且由于官方没有规定 session_key 的有效期,所以使用时候要注意如下: + * 当需要使用的时候,需要前端先判断微信的登录态是否过期(wx.checkSession()) + * 1、如果过期,重新调用登录接口获取新的 session_key + * 2、如果没过期,但由于security的拦截器会判断过期时间不足120分钟时会,会对session_key进行续期:{@link com.flossom.common.security.service.TokenService#refreshSessionKey} */ redisService.setCacheObject(CacheConstants.WX_SESSION_KEY_CACHE + wxUserMember.getOpenid(), wxCode2SessionRet.getSession_key(), CacheConstants.EXPIRATION, TimeUnit.MINUTES); @@ -97,22 +100,9 @@ public class WxUserMemberServiceImpl implements IWxUserMemberService { @Override public void upgradeMember(String code) throws Exception { - /** - * TODO: 暂时将access_token保存在redis,后期根据业务修改 - */ - String accessToken = redisService.getCacheObject(CacheConstants.WX_ACCESS_TOKEN_CACHE + SecurityUtils.getLoginUser().getWxUserMember().getOpenid()); + String accessToken = MiniProgramUtils.getAccessToken(SecurityUtils.getLoginUser().getWxUserMember().getOpenid()); if (StringUtils.isBlank(accessToken)) { - // 获取 access_token - String result = MiniProgramUtils.getAccessToken(); - logger.info("请求微信服务器获取access_token返回结果:{}", result); - WxAccessTokenRet wxAccessTokenRet = JSON.parseObject(result, WxAccessTokenRet.class); - if (wxAccessTokenRet.getErrcode() != null) { - logger.error("获取access_token 失败: {}", wxAccessTokenRet.getErrmsg()); - throw new ServiceException("获取用户手机号码失败"); - } - // 保存缓存 - redisService.setCacheObject(CacheConstants.WX_ACCESS_TOKEN_CACHE + SecurityUtils.getLoginUser().getWxUserMember().getOpenid(), - wxAccessTokenRet.getAccess_token(), CacheConstants.EXPIRATION, TimeUnit.MINUTES); + throw new ServiceException("获取用户手机号码失败"); } // 获取手机号 diff --git a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/utils/MiniProgramUtils.java b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/utils/MiniProgramUtils.java index 239644e..d589999 100644 --- a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/utils/MiniProgramUtils.java +++ b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/utils/MiniProgramUtils.java @@ -1,8 +1,13 @@ package com.flossom.miniProgram.utils; +import com.alibaba.fastjson.JSON; +import com.flossom.common.core.constant.CacheConstants; import com.flossom.common.core.domain.entity.WxParameterSetting; import com.flossom.common.core.mapper.WxParameterSettingMapper; +import com.flossom.common.core.utils.StringUtils; +import com.flossom.common.redis.service.RedisService; import com.flossom.miniProgram.config.properties.WxConfig; +import com.flossom.miniProgram.domain.vo.WxAccessTokenRet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -10,6 +15,7 @@ import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; /** * 小程序工具类 @@ -17,10 +23,14 @@ import java.util.Map; @Component public class MiniProgramUtils { + protected final static Logger logger = LoggerFactory.getLogger(MiniProgramUtils.class); + private static WxConfig wxConfig; private static WxParameterSettingMapper wxParameterSettingMapper; + private static RedisService redisService; + /** * 注入 微信配置mapper,获取 appId,appKey(该配置在数据库) * @@ -31,6 +41,11 @@ public class MiniProgramUtils { MiniProgramUtils.wxParameterSettingMapper = wxParameterSettingMapper; } + @Autowired + public void setRedisService(RedisService redisService) { + MiniProgramUtils.redisService = redisService; + } + /** * 注入 微信配置类,读取请求路径(该配置在 nacos) * @@ -95,12 +110,32 @@ public class MiniProgramUtils { return HttpClientUtils.postParameters(wxConfig.getObtainPhoneUrl() + "?access_token=" + accessToken, params); } - public static String getAccessToken() throws Exception { - Map params = new HashMap(); - WxParameterSetting wxParameterSetting = wxParameterSettingMapper.selectWxParameterSettingById(1L); - params.put("appid", wxParameterSetting.getAppid()); - params.put("secret", wxParameterSetting.getAppkey()); - params.put("grant_type", "client_credential"); - return HttpClientUtils.getParameters(wxConfig.getAccessTokenUrl(), params); + public static String getAccessToken(String openid) throws Exception { + + /** + * TODO: 将 access_token 保存在 redis,官方定义说 access_token 的有效期暂定为 2个小时,使用注意事项: + * 1、从 redis 获取 access_token,存在则未过期,不存在则过期了,重新获取 access_token + */ + String accessToken = redisService.getCacheObject(CacheConstants.WX_ACCESS_TOKEN_CACHE + openid); + if (StringUtils.isBlank(accessToken)) { + // 获取 access_token + Map params = new HashMap(); + WxParameterSetting wxParameterSetting = wxParameterSettingMapper.selectWxParameterSettingById(1L); + params.put("appid", wxParameterSetting.getAppid()); + params.put("secret", wxParameterSetting.getAppkey()); + params.put("grant_type", "client_credential"); + String result = HttpClientUtils.getParameters(wxConfig.getAccessTokenUrl(), params); + logger.info("请求微信服务器获取access_token返回结果:{}", result); + WxAccessTokenRet wxAccessTokenRet = JSON.parseObject(result, WxAccessTokenRet.class); + if (wxAccessTokenRet.getErrcode() != null) { + logger.error("获取 access_token 失败: {}", wxAccessTokenRet.getErrmsg()); + return null; + } + // 保存缓存 + redisService.setCacheObject(CacheConstants.WX_ACCESS_TOKEN_CACHE + openid, + wxAccessTokenRet.getAccess_token(), CacheConstants.WX_ACCESS_TOKEN_EXPIRATION, TimeUnit.MINUTES); + return wxAccessTokenRet.getAccess_token(); + } + return accessToken; } }