小程序登录
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
package com.cool.store.context;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.cool.store.vo.PartnerUserInfoVO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* C端登录用户信息
|
||||
*/
|
||||
public class PartnerUserHolder {
|
||||
|
||||
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
|
||||
|
||||
public static PartnerUserInfoVO getUser() {
|
||||
String userStr = contextHolder.get();
|
||||
if (StringUtils.isNotBlank(userStr)) {
|
||||
return JSON.parseObject(userStr, PartnerUserInfoVO.class);
|
||||
}
|
||||
return new PartnerUserInfoVO();
|
||||
}
|
||||
|
||||
public static void setUser(String user) {
|
||||
contextHolder.set(user);
|
||||
}
|
||||
|
||||
public static void removeUser(){
|
||||
contextHolder.remove();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
package com.cool.store.http;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cool.store.dto.response.ResultDTO;
|
||||
import com.cool.store.dto.wx.CodeSessionDTO;
|
||||
import com.cool.store.dto.wx.PhoneInfoDTO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.utils.RestTemplateUtil;
|
||||
import com.cool.store.mq.util.HttpRestTemplateService;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -23,24 +27,81 @@ import java.util.Objects;
|
||||
@Service
|
||||
public class WechatRest {
|
||||
|
||||
@Resource
|
||||
private RedisUtilPool redisUtilPool;
|
||||
|
||||
@Resource
|
||||
private HttpRestTemplateService httpRestTemplateService;
|
||||
|
||||
/**
|
||||
* 小程序Token 地址
|
||||
*/
|
||||
String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||
/**
|
||||
* 获取手机号码 地址
|
||||
*/
|
||||
String GET_USERPHONENUMBER = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s";
|
||||
|
||||
|
||||
public CodeSessionDTO miniProgramJsCodeSession(String appId, String secret, String jsCode){
|
||||
String url = "https://api.weixin.qq.com/sns/jscode2session";
|
||||
Map requestMap = new HashMap<String, String>();
|
||||
requestMap.put("appId", appId);
|
||||
HashMap requestMap = new HashMap();
|
||||
requestMap.put("appid", appId);
|
||||
requestMap.put("secret", secret);
|
||||
requestMap.put("jsCode", jsCode);
|
||||
ResponseEntity<CodeSessionDTO> responseEntity = null;
|
||||
requestMap.put("js_code", jsCode);
|
||||
requestMap.put("grant_type","authorization_code");
|
||||
ResultDTO responseEntity = null;
|
||||
try {
|
||||
responseEntity = RestTemplateUtil.get(url, CodeSessionDTO.class);
|
||||
log.info("url:{}, response:{}", url, JSONObject.toJSONString(responseEntity));
|
||||
if(Objects.nonNull(responseEntity.getBody()) && responseEntity.getBody().isSuccess()){
|
||||
return responseEntity.getBody();
|
||||
responseEntity = httpRestTemplateService.getForObject(url, ResultDTO.class, requestMap);
|
||||
log.info("WechatRest#miniProgramJsCodeSession, url:{}, response:{}", url, JSONObject.toJSONString(responseEntity));
|
||||
if(Objects.nonNull(responseEntity.getData()) && responseEntity.isSuccess()){
|
||||
return JSONObject.parseObject(JSONObject.toJSONString(responseEntity.getData()), CodeSessionDTO.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("调用微信服务异常{}", e);
|
||||
throw new ServiceException(ErrorCodeEnum.WX_SERVICE_ERROR);
|
||||
log.error("调用微信服务异常", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getAccessToken(String appId, String secret) {
|
||||
String cacheAccessToken = "mini_" + appId;
|
||||
String accessToken = redisUtilPool.getString(cacheAccessToken);
|
||||
if (StringUtils.isNotBlank(accessToken)) {
|
||||
return accessToken;
|
||||
}
|
||||
String reqUrl = String.format(ACCESS_TOKEN, appId, secret);
|
||||
ResultDTO responseEntity = null;
|
||||
try {
|
||||
responseEntity = httpRestTemplateService.getForObject(reqUrl, ResultDTO.class, null);
|
||||
log.info("WechatRest#getAccessToken, reqUrl:{}, response:{}", reqUrl, JSONObject.toJSONString(responseEntity));
|
||||
if(Objects.nonNull(responseEntity.getData()) && responseEntity.isSuccess()){
|
||||
JSONObject jsonObject = JSON.parseObject(JSONObject.toJSONString(responseEntity.getData()));
|
||||
String token = jsonObject.getString("access_token");
|
||||
if (StringUtils.isBlank(token)) {
|
||||
throw new ServiceException(ErrorCodeEnum.GET_ACCESSTOKEN_ERROR);
|
||||
}
|
||||
redisUtilPool.setString(cacheAccessToken, token, 7000);
|
||||
accessToken = token;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取微信小程序token异常", e);
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
|
||||
public PhoneInfoDTO getUserPhoneNumber(String code, String accessToken){
|
||||
String reqUrl = String.format(GET_USERPHONENUMBER, accessToken);
|
||||
HashMap requestMap = new HashMap();
|
||||
requestMap.put("code", code);
|
||||
PhoneInfoDTO phoneInfoDTO = null;
|
||||
try {
|
||||
phoneInfoDTO = httpRestTemplateService.postForObject(reqUrl, requestMap, PhoneInfoDTO.class);
|
||||
log.info("WechatRest#getUserPhoneNumber, reqUrl:{}, response:{}", reqUrl, JSONObject.toJSONString(phoneInfoDTO));
|
||||
} catch (Exception e) {
|
||||
log.error("获取手机号异常", e);
|
||||
}
|
||||
return phoneInfoDTO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
public interface PartnerUserInfoService {
|
||||
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
import com.cool.store.dto.wx.MiniProgramLoginDTO;
|
||||
import com.cool.store.dto.wx.MiniProgramMsgDTO;
|
||||
import com.cool.store.vo.wx.CodeSessionVO;
|
||||
import com.cool.store.vo.wx.MiniProgramUserVO;
|
||||
|
||||
import com.cool.store.request.MobileUpdateRequest;
|
||||
import com.cool.store.vo.PartnerUserInfoVO;
|
||||
/**
|
||||
* @author zhangchenbiao
|
||||
* @FileName: WechatMiniAppService
|
||||
@@ -14,9 +12,9 @@ import com.cool.store.vo.wx.MiniProgramUserVO;
|
||||
public interface WechatMiniAppService {
|
||||
|
||||
|
||||
CodeSessionVO miniProgramLogin(MiniProgramLoginDTO param);
|
||||
PartnerUserInfoVO miniProgramLogin(MiniProgramLoginDTO param);
|
||||
|
||||
CodeSessionVO getUserPhoneNumber(MiniProgramLoginDTO param);
|
||||
Boolean updateUserPhoneNumber(MobileUpdateRequest request, PartnerUserInfoVO userInfoVO);
|
||||
|
||||
CodeSessionVO queryMiniProgramUser(MiniProgramMsgDTO param);
|
||||
PartnerUserInfoVO getUserInfo(String mobile, String openId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import com.cool.store.dao.HyPartnerUserInfoDAO;
|
||||
import com.cool.store.service.PartnerUserInfoService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PartnerUserInfoServiceImpl implements PartnerUserInfoService {
|
||||
|
||||
@Autowired
|
||||
private HyPartnerUserInfoDAO hyPartnerUserInfoDAO;
|
||||
|
||||
}
|
||||
@@ -1,24 +1,36 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.dao.HyPartnerLineInfoDAO;
|
||||
import com.cool.store.dao.HyPartnerUserInfoDAO;
|
||||
import com.cool.store.dao.HyPartnerUserPlatformBindDAO;
|
||||
import com.cool.store.dto.wx.CodeSessionDTO;
|
||||
import com.cool.store.dto.wx.MiniProgramLoginDTO;
|
||||
import com.cool.store.dto.wx.MiniProgramMsgDTO;
|
||||
import com.cool.store.dto.wx.PhoneInfoDTO;
|
||||
import com.cool.store.entity.HyPartnerLineInfoDO;
|
||||
import com.cool.store.entity.HyPartnerUserInfoDO;
|
||||
import com.cool.store.entity.HyPartnerUserPlatformBindDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.enums.UserPlatformTypeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.http.WechatRest;
|
||||
import com.cool.store.request.MobileUpdateRequest;
|
||||
import com.cool.store.service.WechatMiniAppService;
|
||||
import com.cool.store.utils.AesUtil;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
import com.cool.store.vo.wx.CodeSessionVO;
|
||||
import com.cool.store.utils.UUIDUtils;
|
||||
import com.cool.store.vo.PartnerUserInfoVO;
|
||||
import com.cool.store.vo.wx.MiniProgramUserVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -35,49 +47,105 @@ public class WechatMiniAppServiceImpl implements WechatMiniAppService {
|
||||
private RedisUtilPool redisUtilPool;
|
||||
@Resource
|
||||
private WechatRest wechatRest;
|
||||
@Resource
|
||||
private HyPartnerUserInfoDAO hyPartnerUserInfoDAO;
|
||||
@Resource
|
||||
private HyPartnerUserPlatformBindDAO hyPartnerUserPlatformBindDAO;
|
||||
@Resource
|
||||
private HyPartnerLineInfoDAO hyPartnerLineInfoDAO;
|
||||
|
||||
@Value("${weixin.appId}")
|
||||
private String wxAppId;
|
||||
@Value("${weixin.appSecret}")
|
||||
private String wxAppSecret;
|
||||
|
||||
|
||||
@Override
|
||||
public CodeSessionVO miniProgramLogin(MiniProgramLoginDTO param) {
|
||||
public PartnerUserInfoVO miniProgramLogin(MiniProgramLoginDTO param) {
|
||||
PartnerUserInfoVO userInfoVO = new PartnerUserInfoVO();
|
||||
String jsCode = param.getJsCode();
|
||||
String lockKey = "codeSession:" + param.getAppid() + CommonConstants.MOSAICS + jsCode;
|
||||
String lockKey = "codeSession:" + wxAppId + CommonConstants.MOSAICS + jsCode;
|
||||
boolean lock = redisUtilPool.lock(lockKey);
|
||||
if (!lock) {
|
||||
throw new ServiceException(ErrorCodeEnum.OPERATION_OVER_TIME);
|
||||
}
|
||||
String appid = param.getAppid();
|
||||
String secret = redisUtilPool.getString(MessageFormat.format(CommonConstants.WX_APP_SECRET_KEY, appid));
|
||||
if(StringUtils.isBlank(secret)){
|
||||
throw new ServiceException(ErrorCodeEnum.GET_APP_SECRET_ERROR);
|
||||
}
|
||||
CodeSessionDTO codeSession = wechatRest.miniProgramJsCodeSession(appid, secret, jsCode);
|
||||
CodeSessionDTO codeSession = wechatRest.miniProgramJsCodeSession(wxAppId, wxAppSecret, jsCode);
|
||||
String openid = codeSession.getOpenid();
|
||||
String sessionCacheKey = MessageFormat.format(CommonConstants.MINI_PROGRAM_SESSION_KEY, appid, openid);
|
||||
String sessionCacheKey = MessageFormat.format(CommonConstants.MINI_PROGRAM_SESSION_KEY, wxAppId, openid);
|
||||
redisUtilPool.setString(sessionCacheKey, codeSession.getSessionKey(), CommonConstants.THREE_DAY_SECONDS);
|
||||
String unionId = codeSession.getUnionId();
|
||||
log.info("小程序登录:{}", unionId);
|
||||
//todo 保存授权信息 判断是否第一次授权
|
||||
return CodeSessionVO.builder().openid(openid).unionId(unionId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeSessionVO getUserPhoneNumber(MiniProgramLoginDTO param) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeSessionVO queryMiniProgramUser(MiniProgramMsgDTO param) {
|
||||
String sessionCacheKey = MessageFormat.format(CommonConstants.MINI_PROGRAM_SESSION_KEY, param.getAppid(), param.getOpenid());
|
||||
String sessionKey = redisUtilPool.getString(sessionCacheKey);
|
||||
if (StringUtils.isBlank(sessionKey)) {
|
||||
throw new ServiceException(ErrorCodeEnum.SESSION_KEY_ERROR);
|
||||
}
|
||||
log.info("sessionKey {}", sessionKey);
|
||||
String decryptUser = AesUtil.decryptWechat(sessionKey, param.getEncryptedData(), param.getIvStr());
|
||||
log.info("sessionKey {}", codeSession.getSessionKey());
|
||||
String decryptUser = AesUtil.decryptWechat(codeSession.getSessionKey(), param.getEncryptedData(), param.getIvStr());
|
||||
log.info("解密用户信息:{}", decryptUser);
|
||||
MiniProgramUserVO miniProgramUser = JSON.parseObject(decryptUser, MiniProgramUserVO.class);
|
||||
if (Objects.isNull(miniProgramUser)) {
|
||||
throw new ServiceException(ErrorCodeEnum.GET_WECHAT_USER_INFO_FAIL);
|
||||
}
|
||||
return new CodeSessionVO();
|
||||
// 获取小程序token
|
||||
String accessToken = wechatRest.getAccessToken(wxAppId, wxAppSecret);
|
||||
// 获取手机号码
|
||||
PhoneInfoDTO phoneInfoDTO = wechatRest.getUserPhoneNumber(param.getMobileCode(), accessToken);
|
||||
if(phoneInfoDTO != null && phoneInfoDTO.getPhoneInfo() != null && StringUtils.isNotBlank(phoneInfoDTO.getPhoneInfo().getPhoneNumber())){
|
||||
HyPartnerUserInfoDO hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByMobile(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
|
||||
if(hyPartnerUserInfoDO == null){
|
||||
hyPartnerUserInfoDO = new HyPartnerUserInfoDO();
|
||||
hyPartnerUserInfoDO.setMobile(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
|
||||
hyPartnerUserInfoDO.setUsername(miniProgramUser.getNickName());
|
||||
hyPartnerUserInfoDO.setPartnerId(UUIDUtils.get32UUID());
|
||||
hyPartnerUserInfoDAO.insertSelective(hyPartnerUserInfoDO);
|
||||
// 生成一条线索
|
||||
HyPartnerLineInfoDO hyPartnerLineInfoDO = new HyPartnerLineInfoDO();
|
||||
hyPartnerLineInfoDO.setPartnerId(hyPartnerUserInfoDO.getPartnerId());
|
||||
hyPartnerLineInfoDAO.insertSelective(hyPartnerLineInfoDO);
|
||||
}
|
||||
HyPartnerUserPlatformBindDO hyPartnerUserPlatformBindDO = hyPartnerUserPlatformBindDAO.getByPlatformTypeAndUserId(UserPlatformTypeEnum.WECHAT.getCode(), openid);
|
||||
if(hyPartnerUserPlatformBindDO == null){
|
||||
hyPartnerUserPlatformBindDO = new HyPartnerUserPlatformBindDO();
|
||||
hyPartnerUserPlatformBindDO.setPlatformType(UserPlatformTypeEnum.WECHAT.getCode());
|
||||
hyPartnerUserPlatformBindDO.setPlatformUserId(openid);
|
||||
hyPartnerUserPlatformBindDO.setBindTime(new Date());
|
||||
hyPartnerUserPlatformBindDO.setPartnerId(hyPartnerUserInfoDO.getPartnerId());
|
||||
hyPartnerUserPlatformBindDAO.insertSelective(hyPartnerUserPlatformBindDO);
|
||||
}
|
||||
userInfoVO.setPartnerId(hyPartnerUserInfoDO.getPartnerId());
|
||||
userInfoVO.setMobile(hyPartnerUserInfoDO.getMobile());
|
||||
userInfoVO.setUsername(hyPartnerUserInfoDO.getUsername());
|
||||
}
|
||||
userInfoVO.setOpenid(openid);
|
||||
userInfoVO.setUnionId(unionId);
|
||||
return userInfoVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateUserPhoneNumber(MobileUpdateRequest request, PartnerUserInfoVO userInfoVO) {
|
||||
HyPartnerUserInfoDO oldUserInfo = hyPartnerUserInfoDAO.selectByMobile(userInfoVO.getMobile());
|
||||
if (oldUserInfo == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.PARTNER_USER_NOT_EXIST);
|
||||
}
|
||||
// 获取小程序token
|
||||
String accessToken = wechatRest.getAccessToken(wxAppId, wxAppSecret);
|
||||
// 获取手机号码
|
||||
PhoneInfoDTO phoneInfoDTO = wechatRest.getUserPhoneNumber(request.getMobileCode(), accessToken);
|
||||
if(phoneInfoDTO != null && phoneInfoDTO.getPhoneInfo() != null && StringUtils.isNotBlank(phoneInfoDTO.getPhoneInfo().getPhoneNumber())){
|
||||
HyPartnerUserInfoDO newUserInfo = hyPartnerUserInfoDAO.selectByMobile(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
|
||||
if (newUserInfo != null) {
|
||||
throw new ServiceException(ErrorCodeEnum.NEW_MOBILE_HAS_EXIST);
|
||||
}
|
||||
oldUserInfo.setMobile(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
|
||||
hyPartnerUserInfoDAO.updateByPrimaryKeySelective(oldUserInfo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartnerUserInfoVO getUserInfo(String mobile, String openId) {
|
||||
PartnerUserInfoVO userInfoVO = new PartnerUserInfoVO();
|
||||
HyPartnerUserInfoDO hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByMobile(mobile);
|
||||
BeanUtil.copyProperties(hyPartnerUserInfoDO, userInfoVO);
|
||||
HyPartnerUserPlatformBindDO hyPartnerUserPlatformBindDO = hyPartnerUserPlatformBindDAO.getByPartnerId(hyPartnerUserInfoDO.getPartnerId());
|
||||
userInfoVO.setOpenid(hyPartnerUserPlatformBindDO.getPlatformUserId());
|
||||
return userInfoVO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user