微信登录接口

master
382696293@qq.com 2 years ago
parent b08a50b1d6
commit 46d81cf1bb

@ -0,0 +1,31 @@
package com.flossom.system.api;
import com.flossom.common.core.constant.SecurityConstants;
import com.flossom.common.core.constant.ServiceNameConstants;
import com.flossom.common.core.domain.R;
import com.flossom.system.api.domain.LoginBody;
import com.flossom.system.api.domain.RegisterBody;
import com.flossom.system.api.domain.SysUser;
import com.flossom.system.api.factory.RemoteUserFallbackFactory;
import com.flossom.system.api.model.LoginUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
*
*
* @author flossom
*/
@FeignClient(contextId = "remoteAuthService", value = ServiceNameConstants.AUTH_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteAuthService
{
@PostMapping("login")
public R<Map<String, String>> login(@RequestBody LoginBody form);
@PostMapping("register")
public R<?> register(@RequestBody RegisterBody registerBody);
}

@ -0,0 +1,39 @@
package com.flossom.system.api.domain;
/**
*
*
* @author flossom
*/
public class LoginBody
{
/**
*
*/
private String username;
/**
*
*/
private String password;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}

@ -0,0 +1,11 @@
package com.flossom.system.api.domain;
/**
*
*
* @author flossom
*/
public class RegisterBody extends LoginBody
{
}

@ -0,0 +1,42 @@
package com.flossom.system.api.factory;
import com.flossom.common.core.domain.R;
import com.flossom.system.api.RemoteAuthService;
import com.flossom.system.api.RemoteUserService;
import com.flossom.system.api.domain.LoginBody;
import com.flossom.system.api.domain.RegisterBody;
import com.flossom.system.api.domain.SysUser;
import com.flossom.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
*
*
* @author flossom
*/
@Component
public class RemoteAuthFallbackFactory implements FallbackFactory<RemoteAuthService> {
private static final Logger log = LoggerFactory.getLogger(RemoteAuthFallbackFactory.class);
@Override
public RemoteAuthService create(Throwable throwable) {
log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteAuthService() {
@Override
public R<Map<String, String>> login(LoginBody form) {
return R.fail("用户登录失败:" + throwable.getMessage());
}
@Override
public R<?> register(RegisterBody registerBody) {
return R.fail("用户注册失败:" + throwable.getMessage());
}
};
}
}

@ -56,4 +56,9 @@ public class CacheConstants
* IP cache key
*/
public static final String SYS_LOGIN_BLACKIPLIST = SYS_CONFIG_KEY + "sys.login.blackIPList";
/**
* session_key
*/
public static final String wx_session_key_cache = "wx_session_key:";
}

@ -77,4 +77,11 @@ public class UserConstants
public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20;
/**
*
*/
public static final String WX_SYSTEM_USER_USERNAME = "wxhz";
public static final String WX_SYSTEM_USER_PASSWORD = "hzAnonymous9090.@";
}

@ -2,20 +2,20 @@ package com.flossom.hzMapper.mapper;
import com.flossom.hzMapper.domain.WxUserMember;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Mapper
*
*
* @author flossom
* @date 2023-12-08
*/
public interface WxUserMemberMapper
{
public interface WxUserMemberMapper {
/**
*
*
*
* @param id
* @return
*/
@ -23,7 +23,7 @@ public interface WxUserMemberMapper
/**
*
*
*
* @param wxUserMember
* @return
*/
@ -31,7 +31,7 @@ public interface WxUserMemberMapper
/**
*
*
*
* @param wxUserMember
* @return
*/
@ -39,7 +39,7 @@ public interface WxUserMemberMapper
/**
*
*
*
* @param wxUserMember
* @return
*/
@ -47,7 +47,7 @@ public interface WxUserMemberMapper
/**
*
*
*
* @param id
* @return
*/
@ -55,9 +55,19 @@ public interface WxUserMemberMapper
/**
*
*
*
* @param ids
* @return
*/
public int deleteWxUserMemberByIds(Long[] ids);
/**
*
*
* @param wxUserMember
* @return
*/
public void insertTouristUser(WxUserMember wxUserMember);
WxUserMember selectWxUserMemberByOpenId(@Param("openid") String openid);
}

@ -75,7 +75,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectWxUserMemberVo"/>
where id = #{id}
</select>
<select id="selectWxUserMemberByOpenId" parameterType="String" resultType="com.flossom.hzMapper.domain.WxUserMember">
<include refid="selectWxUserMemberVo"/>
WHERE openid = #{openid}
</select>
<insert id="insertWxUserMember" parameterType="WxUserMember" useGeneratedKeys="true" keyProperty="id">
insert into wx_user_member
<trim prefix="(" suffix=")" suffixOverrides=",">
@ -188,4 +192,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{id}
</foreach>
</delete>
<insert id="insertTouristUser" parameterType="WxUserMember" useGeneratedKeys="true" keyProperty="id">
INSERT INTO `wx_user_member` (login_time, create_time) VALUES(sysdate(), sysdate());
</insert>
</mapper>

@ -78,6 +78,12 @@
<artifactId>flossom-common-swagger</artifactId>
</dependency>
<!-- flossom Api System -->
<dependency>
<groupId>com.flossom</groupId>
<artifactId>flossom-api-system</artifactId>
</dependency>
<dependency>
<groupId>com.flossom</groupId>
<artifactId>flossom-common-hzMapper</artifactId>

@ -1,13 +1,8 @@
package com.flossom.miniProgram.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.flossom.common.core.web.controller.BaseController;
import com.flossom.common.core.web.domain.AjaxResult;
import com.flossom.miniProgram.domain.vo.WxCode2SessionRet;
import com.flossom.miniProgram.service.IWxUserMemberService;
import com.flossom.miniProgram.utils.MiniProgramUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -22,49 +17,22 @@ public class UserMemberController extends BaseController {
private IWxUserMemberService wxUserMemberService;
/**
* userNo \
* 使 userNo id
*
*
* @param code
* @param rawData
* @param signature 使 sha1( rawData + sessionkey )
* @return
* @throws Exception
*/
@PostMapping("/obtainUserMemberInfo")
public AjaxResult obtainUserMemberInfo(@RequestParam(value = "userNo", required = false) Long userNo) {
return AjaxResult.success(wxUserMemberService.obtainUserMemberInfo(userNo));
}
@PostMapping("/login")
public AjaxResult getJwt(@RequestParam(value = "code") String code,
@RequestParam(value = "rawData", required = false) String rawData,
@RequestParam(value = "signature", required = false) String signature) throws Exception {
// 1. 使用临时凭证code获取 appi + appsecret + code
WxCode2SessionRet wxCode2SessionRet = JSON.parseObject(MiniProgramUtils.getSessionKeyAndOpenId(code), WxCode2SessionRet.class);
if (0 != wxCode2SessionRet.getErrcode()) {
return AjaxResult.error(wxCode2SessionRet.getErrmsg());
}
// 2.校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey)
String signature2 = DigestUtils.sha1Hex(rawData + wxCode2SessionRet.getSession_key());
if (!signature.equals(signature2)) {
return AjaxResult.error("签名校验失败");
}
// 5.根据返回的User实体类判断用户是否是新用户是的话将用户信息存到数据库
// 用户非敏感信息rawData
// 签名signature
JSONObject rawDataJson = JSON.parseObject(rawData);
// LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
// lqw.eq(User::getOpenId, openid);
// User user = userService.getOne(lqw);
// if (user == null) {
// // 用户信息入库
// String nickName = rawDataJson.getString("nickName");
// String avatarUrl = rawDataJson.getString("avatarUrl");
// user = new User();
// user.setOpenId(openid);
// user.setAvatar(avatarUrl);
// user.setNickName(nickName);
// userService.save(user);
// }
return AjaxResult.success();
public AjaxResult login(
@RequestParam(value = "code") String code,
@RequestParam(value = "rawData") String rawData,
@RequestParam(value = "signature") String signature,
@RequestParam(value = "userNo", required = false) Long userNo) throws Exception {
return AjaxResult.success(wxUserMemberService.login(code, rawData, signature));
}
}

@ -0,0 +1,40 @@
package com.flossom.miniProgram.domain.vo;
import com.flossom.hzMapper.domain.WxUserMember;
public class LoginUserVo extends WxUserMember {
/**
*
*/
private String accessToken;
/**
*
*/
private String expiresIn;
public LoginUserVo() {
}
public LoginUserVo(String accessToken, String expiresIn) {
this.accessToken = accessToken;
this.expiresIn = expiresIn;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(String expiresIn) {
this.expiresIn = expiresIn;
}
}

@ -1,9 +1,11 @@
package com.flossom.miniProgram.service;
import com.flossom.hzMapper.domain.WxUserMember;
import com.flossom.miniProgram.domain.vo.LoginUserVo;
public interface IWxUserMemberService {
WxUserMember obtainUserMemberInfo(Long userNo);
LoginUserVo obtainUserMemberInfo(Long userNo);
LoginUserVo login(String code, String rawData, String signature) throws Exception;
}

@ -1,27 +1,156 @@
package com.flossom.miniProgram.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.flossom.common.core.constant.CacheConstants;
import com.flossom.common.core.constant.UserConstants;
import com.flossom.common.core.domain.R;
import com.flossom.common.core.exception.ServiceException;
import com.flossom.common.core.web.domain.AjaxResult;
import com.flossom.common.redis.service.RedisService;
import com.flossom.hzMapper.domain.WxUserMember;
import com.flossom.hzMapper.mapper.WxUserMemberMapper;
import com.flossom.miniProgram.domain.vo.LoginUserVo;
import com.flossom.miniProgram.domain.vo.WxCode2SessionRet;
import com.flossom.miniProgram.service.IWxUserMemberService;
import com.flossom.miniProgram.utils.MiniProgramUtils;
import com.flossom.system.api.RemoteAuthService;
import com.flossom.system.api.RemoteUserService;
import com.flossom.system.api.domain.LoginBody;
import com.flossom.system.api.domain.RegisterBody;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class WxUserMemberServiceImpl implements IWxUserMemberService {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private WxUserMemberMapper wxUserMemberMapper;
@Autowired
private RemoteAuthService remoteAuthService;
@Autowired
private RemoteUserService remoteUserService;
@Autowired
private RedisService redisService;
@Override
public WxUserMember obtainUserMemberInfo(Long userNo) {
public LoginUserVo obtainUserMemberInfo(Long userNo) {
WxUserMember wxUserMember = new WxUserMember();
if (userNo != null) {
// 根据 userNo 查询用户信息
wxUserMember = wxUserMemberMapper.selectWxUserMemberById(userNo);
}
if (userNo == null || wxUserMember == null) {
// 未注册用户,就注册游客账户
// 微信用户表注册
wxUserMemberMapper.insertTouristUser(wxUserMember);
// 系统表注册
RegisterBody registerBody = new RegisterBody();
registerBody.setUsername(UserConstants.WX_SYSTEM_USER_USERNAME + wxUserMember.getId());
registerBody.setPassword(UserConstants.WX_SYSTEM_USER_PASSWORD);
R<?> registerResult = remoteAuthService.register(registerBody);
if (R.FAIL == registerResult.getCode()) {
throw new ServiceException(registerResult.getMsg());
}
}
// 获取token
LoginBody loginBody = new LoginBody();
loginBody.setUsername(UserConstants.WX_SYSTEM_USER_USERNAME + wxUserMember.getId());
loginBody.setPassword(UserConstants.WX_SYSTEM_USER_PASSWORD);
R<Map<String, String>> loginResult = remoteAuthService.login(loginBody);
if (loginResult.getCode() == R.FAIL) {
throw new ServiceException(loginResult.getMsg());
}
LoginUserVo loginUserVo = new LoginUserVo();
BeanUtils.copyProperties(wxUserMember, loginUserVo);
loginUserVo.setAccessToken(loginResult.getData().get("access_token"));
loginUserVo.setExpiresIn(loginResult.getData().get("expires_in"));
return loginUserVo;
}
@Override
public LoginUserVo login(String code, String rawData, String signature) throws Exception {
// 1、使用临时凭证 code 获取 appi + appsecret + code
WxCode2SessionRet wxCode2SessionRet = JSON.parseObject(MiniProgramUtils.getSessionKeyAndOpenId(code), WxCode2SessionRet.class);
if (0 != wxCode2SessionRet.getErrcode()) {
logger.error(wxCode2SessionRet.getErrmsg());
return null;
}
// 2、校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey)
String signature2 = DigestUtils.sha1Hex(rawData + wxCode2SessionRet.getSession_key());
if (!signature.equals(signature2)) {
logger.error("签名校验失败code = {}", code);
return null;
}
// 3、根据 openid 查询用户信息
WxUserMember wxUserMember = wxUserMemberMapper.selectWxUserMemberByOpenId(wxCode2SessionRet.getOpenid());
if (wxUserMember == null) {
// 未注册用户,就注册游客账户
// 2.1、封装微信用户信息
/**
* rawData:
* {
* "nickName": "Band",
* "avatarUrl": "http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0"
* "gender": 1,//不再返回
* "language": "zh_CN", //强制返回 “zh_CN”
* "city": "Guangzhou", //不再返回
* "province": "Guangdong", //不再返回
* "country": "CN", //不再返回
* }
*/
JSONObject rawDataJson = JSON.parseObject(rawData);
wxUserMember.setNickname(rawDataJson.getString("nickName"));
wxUserMember.setHeadimg(rawDataJson.getString("avatarUrl"));
wxUserMember.setOpenid(wxCode2SessionRet.getOpenid());
wxUserMember.setUnionid(wxCode2SessionRet.getUnionid());
/**
* TODO: session_keyredis
*/
redisService.setCacheObject(CacheConstants.wx_session_key_cache + wxUserMember.getId(), wxCode2SessionRet.getSession_key());
// 3.2、微信用户表注册
wxUserMemberMapper.insertWxUserMember(wxUserMember);
// 3.3、系统表注册
RegisterBody registerBody = new RegisterBody();
registerBody.setUsername(UserConstants.WX_SYSTEM_USER_USERNAME + wxUserMember.getId());
registerBody.setPassword(UserConstants.WX_SYSTEM_USER_PASSWORD);
R<?> registerResult = remoteAuthService.register(registerBody);
if (R.FAIL == registerResult.getCode()) {
throw new ServiceException(registerResult.getMsg());
}
}
// 4、获取 token
LoginBody loginBody = new LoginBody();
loginBody.setUsername(UserConstants.WX_SYSTEM_USER_USERNAME + wxUserMember.getId());
loginBody.setPassword(UserConstants.WX_SYSTEM_USER_PASSWORD);
R<Map<String, String>> loginResult = remoteAuthService.login(loginBody);
if (loginResult.getCode() == R.FAIL) {
throw new ServiceException(loginResult.getMsg());
}
return wxUserMember;
// 5、返回登录信息
LoginUserVo loginUserVo = new LoginUserVo();
BeanUtils.copyProperties(wxUserMember, loginUserVo);
loginUserVo.setAccessToken(loginResult.getData().get("access_token"));
loginUserVo.setExpiresIn(loginResult.getData().get("expires_in"));
return loginUserVo;
}
}

Loading…
Cancel
Save