diff --git a/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/RemoteAuthService.java b/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/RemoteAuthService.java new file mode 100644 index 0000000..e8a91d6 --- /dev/null +++ b/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/RemoteAuthService.java @@ -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> login(@RequestBody LoginBody form); + + @PostMapping("register") + public R register(@RequestBody RegisterBody registerBody); + +} diff --git a/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/domain/LoginBody.java b/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/domain/LoginBody.java new file mode 100644 index 0000000..97b52e1 --- /dev/null +++ b/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/domain/LoginBody.java @@ -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; + } +} diff --git a/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/domain/RegisterBody.java b/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/domain/RegisterBody.java new file mode 100644 index 0000000..faf01f3 --- /dev/null +++ b/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/domain/RegisterBody.java @@ -0,0 +1,11 @@ +package com.flossom.system.api.domain; + +/** + * 用户注册对象 + * + * @author flossom + */ +public class RegisterBody extends LoginBody +{ + +} diff --git a/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/factory/RemoteAuthFallbackFactory.java b/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/factory/RemoteAuthFallbackFactory.java new file mode 100644 index 0000000..778e181 --- /dev/null +++ b/flossom-api/flossom-api-system/src/main/java/com/flossom/system/api/factory/RemoteAuthFallbackFactory.java @@ -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 { + 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> login(LoginBody form) { + return R.fail("用户登录失败:" + throwable.getMessage()); + } + + @Override + public R register(RegisterBody registerBody) { + return R.fail("用户注册失败:" + throwable.getMessage()); + } + }; + } +} 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 6baa7bf..b92e26e 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 @@ -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:"; } diff --git a/flossom-common/flossom-common-core/src/main/java/com/flossom/common/core/constant/UserConstants.java b/flossom-common/flossom-common-core/src/main/java/com/flossom/common/core/constant/UserConstants.java index ecf7610..18dc3eb 100644 --- a/flossom-common/flossom-common-core/src/main/java/com/flossom/common/core/constant/UserConstants.java +++ b/flossom-common/flossom-common-core/src/main/java/com/flossom/common/core/constant/UserConstants.java @@ -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.@"; } diff --git a/flossom-common/flossom-common-hzMapper/src/main/java/com/flossom/hzMapper/mapper/WxUserMemberMapper.java b/flossom-common/flossom-common-hzMapper/src/main/java/com/flossom/hzMapper/mapper/WxUserMemberMapper.java index 92bfee4..76d6665 100644 --- a/flossom-common/flossom-common-hzMapper/src/main/java/com/flossom/hzMapper/mapper/WxUserMemberMapper.java +++ b/flossom-common/flossom-common-hzMapper/src/main/java/com/flossom/hzMapper/mapper/WxUserMemberMapper.java @@ -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,21 @@ 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); + + void upgradeMember(@Param("phoneNumber") String phoneNumber, @Param("id") String id); } diff --git a/flossom-common/flossom-common-hzMapper/src/main/resources/mapper/hzMapper/WxUserMemberMapper.xml b/flossom-common/flossom-common-hzMapper/src/main/resources/mapper/hzMapper/WxUserMemberMapper.xml index 51412d5..0a26f22 100644 --- a/flossom-common/flossom-common-hzMapper/src/main/resources/mapper/hzMapper/WxUserMemberMapper.xml +++ b/flossom-common/flossom-common-hzMapper/src/main/resources/mapper/hzMapper/WxUserMemberMapper.xml @@ -75,7 +75,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" where id = #{id} - + + insert into wx_user_member @@ -178,6 +182,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" where id = #{id} + + UPDATE `wx_user_member` + SET `user_type` = 2, + `level` = 1, + `mobile` = #{phoneNumber}, + `login_time` = sysdate(), + `update_time` = sysdate() + WHERE + `id` = #{id}; + + delete from wx_user_member where id = #{id} @@ -188,4 +203,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{id} + + + INSERT INTO `wx_user_member` (login_time, create_time) VALUES(sysdate(), sysdate()); + \ No newline at end of file diff --git a/flossom-modules/flossom-mini-program/pom.xml b/flossom-modules/flossom-mini-program/pom.xml index 1a46f19..d342ea6 100644 --- a/flossom-modules/flossom-mini-program/pom.xml +++ b/flossom-modules/flossom-mini-program/pom.xml @@ -78,6 +78,12 @@ flossom-common-swagger + + + com.flossom + flossom-api-system + + com.flossom flossom-common-hzMapper diff --git a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/controller/UserMemberController.java b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/controller/UserMemberController.java index 10faef9..5aafde5 100644 --- a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/controller/UserMemberController.java +++ b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/controller/UserMemberController.java @@ -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,32 @@ 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 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) throws Exception { + return AjaxResult.success(wxUserMemberService.login(code, rawData, signature)); } + /** + * 添加手机号,升级会员 + * 1、不再需要提前调用 wx.login 进行登录 + * 2、getPhoneNumber 返回的 code 与 wx.login 返回的 code 作用是不一样的 + * + * @param code + * @return + */ + @PostMapping("/upgradeMember") + public AjaxResult upgradeMember(@RequestParam(value = "code") String code) throws Exception { + return wxUserMemberService.upgradeMember(code); + } } diff --git a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/LoginUserVo.java b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/LoginUserVo.java new file mode 100644 index 0000000..df5cd33 --- /dev/null +++ b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/LoginUserVo.java @@ -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; + } +} diff --git a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/PhoneInfo.java b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/PhoneInfo.java new file mode 100644 index 0000000..3179923 --- /dev/null +++ b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/PhoneInfo.java @@ -0,0 +1,41 @@ +package com.flossom.miniProgram.domain.vo; + +public class PhoneInfo { + + private String phoneNumber; + private String purePhoneNumber; + private String countryCode; + + public PhoneInfo() { + } + + public PhoneInfo(String phoneNumber, String purePhoneNumber, String countryCode) { + this.phoneNumber = phoneNumber; + this.purePhoneNumber = purePhoneNumber; + this.countryCode = countryCode; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public String getPurePhoneNumber() { + return purePhoneNumber; + } + + public void setPurePhoneNumber(String purePhoneNumber) { + this.purePhoneNumber = purePhoneNumber; + } + + public String getCountryCode() { + return countryCode; + } + + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } +} diff --git a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/WxCode2PhoneRet.java b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/WxCode2PhoneRet.java new file mode 100644 index 0000000..1262412 --- /dev/null +++ b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/domain/vo/WxCode2PhoneRet.java @@ -0,0 +1,44 @@ +package com.flossom.miniProgram.domain.vo; + +/** + * 登录响应结果 + */ +public class WxCode2PhoneRet { + + private PhoneInfo phoneInfo; + private Integer errcode; + private String errmsg; + + public WxCode2PhoneRet() { + } + + public WxCode2PhoneRet(PhoneInfo phoneInfo, Integer errcode, String errmsg) { + this.phoneInfo = phoneInfo; + this.errcode = errcode; + this.errmsg = errmsg; + } + + public PhoneInfo getPhoneInfo() { + return phoneInfo; + } + + public void setPhoneInfo(PhoneInfo phoneInfo) { + this.phoneInfo = phoneInfo; + } + + public Integer getErrcode() { + return errcode; + } + + public void setErrcode(Integer errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } +} diff --git a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/service/IWxUserMemberService.java b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/service/IWxUserMemberService.java index ad05cb7..d190647 100644 --- a/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/service/IWxUserMemberService.java +++ b/flossom-modules/flossom-mini-program/src/main/java/com/flossom/miniProgram/service/IWxUserMemberService.java @@ -1,9 +1,14 @@ package com.flossom.miniProgram.service; +import com.flossom.common.core.web.domain.AjaxResult; 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; + + AjaxResult upgradeMember(String code) throws Exception; } 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 39e3b80..12b2e9e 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 @@ -1,27 +1,176 @@ 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.common.security.utils.SecurityUtils; 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.WxCode2PhoneRet; +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.apache.commons.lang3.StringUtils; +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> 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 (200 != 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_key保存在redis,无失效期,后期根据业务修改 + */ + 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> 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; } + + @Override + public AjaxResult upgradeMember(String code) throws Exception { + WxCode2PhoneRet wxCode2PhoneRet = JSON.parseObject(MiniProgramUtils.getPhone(code), WxCode2PhoneRet.class); + if (wxCode2PhoneRet.getErrcode() != 200) { + logger.error("用户手机号码获取失败"); + return AjaxResult.error("手机号获取失败"); + } + String username = SecurityUtils.getLoginUser().getUsername(); + if (StringUtils.isBlank(username)) { + logger.error("获取用户信息失败"); + return AjaxResult.error("获取用户信息失败"); + } + String id = username.replace(UserConstants.WX_SYSTEM_USER_USERNAME, ""); + wxUserMemberMapper.upgradeMember(wxCode2PhoneRet.getPhoneInfo().getPhoneNumber(), id); + return AjaxResult.success(); + } + + } 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 d035032..cdd222d 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 @@ -12,32 +12,33 @@ public class MiniProgramUtils { private static final String WX_SECRET = ""; private static final String loginUrl = "https://api.weixin.qq.com/sns/jscode2session"; + private static final String getPhoneUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"; public static String getSessionKeyAndOpenId(String jsCode) throws Exception { return getSessionKeyAndOpenId(WX_APPID, WX_SECRET, jsCode, "authorization_code"); } /** - * 通过 code 去微信服务器换取 openid 和 session_key + * 通过 code 去微信服务器换取 openid 和 session_key + * * @param appid * @param secret * @param jsCode * @param grant_type - * - * 响应结果: + * @return

* { - * "openid":"xxxxxx", 用户唯一标识 - * "session_key":"xxxxx", 会话密钥 - * "unionid":"xxxxx", - * "errcode":0, 错误码 - * "errmsg":"xxxxx" + * "openid":"xxxxxx", 用户唯一标识 + * "session_key":"xxxxx", 会话密钥 + * "unionid":"xxxxx", + * "errcode":0, 错误码 + * "errmsg":"xxxxx" * } - * + *

* errcode : - * 40029 code 无效 js_code 无效 - * 45011 api minute-quota reach limit mustslower retry next minute API 调用太频繁,请稍候再试 - * 40226 code blocked 高风险等级用户,小程序登录拦截 。风险等级详见用户安全解方案 - * -1 system error 系统繁忙,此时请开发者稍候再试 + * 40029 code 无效 js_code 无效 + * 45011 api minute-quota reach limit mustslower retry next minute API 调用太频繁,请稍候再试 + * 40226 code blocked 高风险等级用户,小程序登录拦截 。风险等级详见用户安全解方案 + * -1 system error 系统繁忙,此时请开发者稍候再试 */ public static String getSessionKeyAndOpenId(String appid, String secret, String jsCode, String grant_type) throws Exception { Map params = new HashMap<>(); @@ -48,5 +49,22 @@ public class MiniProgramUtils { return HttpClientUtils.getParameters(loginUrl, params); } + /** + * @param code + * @return

+ * errcode number 错误码 + * errmsg string 错误信息 + * phone_info object 用户手机号信息 + * 属性 类型 说明 + * phoneNumber string 用户绑定的手机号(国外手机号会有区号) + * purePhoneNumber string 没有区号的手机号 + * countryCode string 区号 + */ + public static String getPhone(String code) throws Exception { + Map params = new HashMap(); + params.put("code", code); + return HttpClientUtils.postParameters(getPhoneUrl, params); + } + }