Commit a5825c86 by 郑云飞

小程序静默登录获取openid

小程序获取手机号
parent 85f00e2f
...@@ -8,6 +8,7 @@ import com.yongqi.common.core.domain.entity.SysUser; ...@@ -8,6 +8,7 @@ import com.yongqi.common.core.domain.entity.SysUser;
import com.yongqi.common.core.domain.model.LoginBody; import com.yongqi.common.core.domain.model.LoginBody;
import com.yongqi.common.core.domain.model.LoginUser; import com.yongqi.common.core.domain.model.LoginUser;
import com.yongqi.common.core.domain.model.SmsLoginBody; import com.yongqi.common.core.domain.model.SmsLoginBody;
import com.yongqi.common.core.domain.model.XcxLoginUser;
import com.yongqi.common.helper.LoginHelper; import com.yongqi.common.helper.LoginHelper;
import com.yongqi.system.domain.vo.RouterVo; import com.yongqi.system.domain.vo.RouterVo;
import com.yongqi.system.service.ISysMenuService; import com.yongqi.system.service.ISysMenuService;
...@@ -73,7 +74,7 @@ public class SysLoginController { ...@@ -73,7 +74,7 @@ public class SysLoginController {
} }
/** /**
* 小程序登录(示例) * 小程序登录(静态登录)
* *
* @param xcxCode 小程序code * @param xcxCode 小程序code
* @return 结果 * @return 结果
...@@ -84,6 +85,23 @@ public class SysLoginController { ...@@ -84,6 +85,23 @@ public class SysLoginController {
Map<String, Object> ajax = new HashMap<>(); Map<String, Object> ajax = new HashMap<>();
// 生成令牌 // 生成令牌
String token = loginService.xcxLogin(xcxCode); String token = loginService.xcxLogin(xcxCode);
ajax.put("openId", token);
return R.ok(ajax);
}
/**
* 小程序登录(手机号登录)
*
* @param xcxCode 小程序code
* @return 结果
*/
@SaIgnore
@PostMapping("/xcxPhoneLogin")
public R<Map<String, Object>> xcxPhoneLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode
, @NotBlank(message = "{xcx.code.not.blank}") String openId) {
Map<String, Object> ajax = new HashMap<>();
// 生成令牌
String token = loginService.xcxPhoneLogin(xcxCode, openId);
ajax.put(Constants.TOKEN, token); ajax.put(Constants.TOKEN, token);
return R.ok(ajax); return R.ok(ajax);
} }
......
...@@ -169,13 +169,13 @@ sms: ...@@ -169,13 +169,13 @@ sms:
sdkAppId: sdkAppId:
wx: wx:
# pay: pay:
# appId: wx312fb4fecd3ee803 #微信公众号或者小程序等的appid appId: wx312fb4fecd3ee803 #微信公众号或者小程序等的appid
# mchId: #微信支付商户号 mchId: 1640607392 #微信支付商户号
# mchKey: #微信支付商户密钥 mchKey: fdfgg56hdfgh52sdf35dfgscfg84wsed #微信支付商户密钥
# subAppId: #服务商模式下的子商户公众账号ID subAppId: #服务商模式下的子商户公众账号ID
# subMchId: #服务商模式下的子商户号 subMchId: #服务商模式下的子商户号
# keyPath: # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头) keyPath: C:\\ProgramData\\certKey\xinrenli\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
# mp: # mp:
# useRedis: false # useRedis: false
# redisConfig: # redisConfig:
......
...@@ -137,7 +137,12 @@ security: ...@@ -137,7 +137,12 @@ security:
# actuator 监控配置 # actuator 监控配置
- /actuator - /actuator
- /actuator/** - /actuator/**
- /** # 登录
- /login
- /captchaImage
- /smsLogin
- /xcxLogin
- /xcxPhoneLogin
# MyBatisPlus配置 # MyBatisPlus配置
# https://baomidou.com/config/ # https://baomidou.com/config/
......
//package com.yongqi.common.core.config; package com.yongqi.common.core.config;
//
//import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.config.WxPayConfig;
//import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.WxPayService;
//import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
//import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
//import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
//import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
//import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
//
///** /**
// * @author Binary Wang * @author Binary Wang
// */ */
//@Configuration @Configuration
//@ConditionalOnClass(WxPayService.class) @ConditionalOnClass(WxPayService.class)
//@EnableConfigurationProperties(WxPayProperties.class) @EnableConfigurationProperties(WxPayProperties.class)
//@AllArgsConstructor @AllArgsConstructor
//public class WxPayConfiguration { public class WxPayConfiguration {
// private WxPayProperties properties; private WxPayProperties properties;
//
// @Bean @Bean
// @ConditionalOnMissingBean @ConditionalOnMissingBean
// public WxPayService wxService() { public WxPayService wxService() {
// WxPayConfig payConfig = new WxPayConfig(); WxPayConfig payConfig = new WxPayConfig();
// payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId())); payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
// payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId())); payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
// payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey())); payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
// payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId())); payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
// payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId())); payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
// payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath())); payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
//
// // 可以指定是否使用沙箱环境 // 可以指定是否使用沙箱环境
// payConfig.setUseSandboxEnv(false); payConfig.setUseSandboxEnv(false);
//
// WxPayService wxPayService = new WxPayServiceImpl(); WxPayService wxPayService = new WxPayServiceImpl();
// wxPayService.setConfig(payConfig); wxPayService.setConfig(payConfig);
// return wxPayService; return wxPayService;
// } }
//
//} }
//package com.yongqi.common.core.config; package com.yongqi.common.core.config;
//
//import lombok.Data; import lombok.Data;
//import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
//
///** /**
// * wxpay pay properties. * wxpay pay properties.
// * *
// * @author Binary Wang * @author Binary Wang
// */ */
//@Data @Data
//@ConfigurationProperties(prefix = "wx.pay") @ConfigurationProperties(prefix = "wx.pay")
//public class WxPayProperties { public class WxPayProperties {
// /** /**
// * 设置微信公众号或者小程序等的appid * 设置微信公众号或者小程序等的appid
// */ */
// private String appId; private String appId;
//
// /** /**
// * 微信支付商户号 * 微信支付商户号
// */ */
// private String mchId; private String mchId;
//
// /** /**
// * 微信支付商户密钥 * 微信支付商户密钥
// */ */
// private String mchKey; private String mchKey;
//
// /** /**
// * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除 * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
// */ */
// private String subAppId; private String subAppId;
//
// /** /**
// * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除 * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
// */ */
// private String subMchId; private String subMchId;
//
// /** /**
// * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定 * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
// */ */
// private String keyPath; private String keyPath;
//
//} }
...@@ -35,6 +35,11 @@ ...@@ -35,6 +35,11 @@
<artifactId>yongqi-sms</artifactId> <artifactId>yongqi-sms</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.yongqi</groupId>
<artifactId>yongqi-xinrenli</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>
package com.yongqi.system.service; package com.yongqi.system.service;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.secure.BCrypt; import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yongqi.common.constant.CacheConstants; import com.yongqi.common.constant.CacheConstants;
import com.yongqi.common.constant.Constants; import com.yongqi.common.constant.Constants;
import com.yongqi.common.core.domain.event.LogininforEvent; import com.yongqi.common.core.domain.event.LogininforEvent;
...@@ -27,12 +31,18 @@ import com.yongqi.common.utils.StringUtils; ...@@ -27,12 +31,18 @@ import com.yongqi.common.utils.StringUtils;
import com.yongqi.common.utils.redis.RedisUtils; import com.yongqi.common.utils.redis.RedisUtils;
import com.yongqi.common.utils.spring.SpringUtils; import com.yongqi.common.utils.spring.SpringUtils;
import com.yongqi.system.mapper.SysUserMapper; import com.yongqi.system.mapper.SysUserMapper;
import com.yongqi.xinrenli.domain.DbWxUser;
import com.yongqi.xinrenli.enums.DeleteStatusEnum;
import com.yongqi.xinrenli.mapper.DbWxUserMapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.rmi.ServerException;
import java.time.Duration; import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
...@@ -56,6 +66,10 @@ public class SysLoginService { ...@@ -56,6 +66,10 @@ public class SysLoginService {
@Value("${user.password.lockTime}") @Value("${user.password.lockTime}")
private Integer lockTime; private Integer lockTime;
@Autowired
private WxMaService wxMaService;
@Autowired
private DbWxUserMapper wxUserMapper;
/** /**
* 登录验证 * 登录验证
...@@ -105,20 +119,48 @@ public class SysLoginService { ...@@ -105,20 +119,48 @@ public class SysLoginService {
// xcxCode 为 小程序调用 wx.login 授权后获取 // xcxCode 为 小程序调用 wx.login 授权后获取
// todo 以下自行实现 // todo 以下自行实现
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
String openid = ""; WxMaJscode2SessionResult sessionInfo = null;
SysUser user = loadUserByOpenid(openid); try {
sessionInfo = wxMaService.getUserService().getSessionInfo(xcxCode);
} catch (WxErrorException e) {
log.error("获取微信openid失败:{}",e.getMessage());
e.printStackTrace();
}
if (sessionInfo == null) {
throw new RuntimeException("获取微信信息失败");
}
DbWxUser user = loadUserByOpenid(sessionInfo, null);
return user.getOpenId();
}
public String xcxPhoneLogin(String xcxCode, String openId) {
// xcxCode 为 小程序调用 wx.login 授权后获取
// todo 以下自行实现
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
WxMaPhoneNumberInfo newPhoneNoInfo = null;
try {
newPhoneNoInfo = wxMaService.getUserService().getNewPhoneNoInfo(xcxCode);
} catch (WxErrorException e) {
log.error("获取微信openid失败:{}",e.getMessage());
e.printStackTrace();
}
if (newPhoneNoInfo == null) {
throw new RuntimeException("获取微信信息失败");
}
WxMaJscode2SessionResult sessionInfo = new WxMaJscode2SessionResult();
sessionInfo.setOpenid(openId);
DbWxUser user = loadUserByOpenid(sessionInfo, newPhoneNoInfo.getPhoneNumber());
// 此处可根据登录用户的数据不同 自行创建 loginUser // 此处可根据登录用户的数据不同 自行创建 loginUser
XcxLoginUser loginUser = new XcxLoginUser(); XcxLoginUser loginUser = new XcxLoginUser();
loginUser.setUserId(user.getUserId()); loginUser.setUserId(user.getId());
loginUser.setUsername(user.getUserName()); loginUser.setUsername(user.getNickname());
loginUser.setUserType(user.getUserType()); loginUser.setUserType(DeviceType.XCX.getDevice());
loginUser.setOpenid(openid); loginUser.setOpenid(sessionInfo.getOpenid());
// 生成token // 生成token
LoginHelper.loginByDevice(loginUser, DeviceType.XCX); LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")); recordLogininfor(user.getNickname(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
recordLoginInfo(user.getUserId(), user.getUserName()); recordLoginInfo(user.getId(), user.getNickname());
return StpUtil.getTokenValue(); return StpUtil.getTokenValue();
} }
...@@ -212,16 +254,23 @@ public class SysLoginService { ...@@ -212,16 +254,23 @@ public class SysLoginService {
return userMapper.selectUserByPhonenumber(phonenumber); return userMapper.selectUserByPhonenumber(phonenumber);
} }
private SysUser loadUserByOpenid(String openid) { private DbWxUser loadUserByOpenid(WxMaJscode2SessionResult sessionInfo, String phone) {
// 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户 // 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
// todo 自行实现 userService.selectUserByOpenid(openid); DbWxUser user = wxUserMapper.selectOne(Wrappers.<DbWxUser>lambdaQuery().eq(DbWxUser::getOpenId, sessionInfo.getOpenid()));
SysUser user = new SysUser();
if (ObjectUtil.isNull(user)) { if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", openid); log.info("登录用户:{} 不存在.", sessionInfo.getOpenid());
// todo 用户不存在 业务逻辑自行实现 user = new DbWxUser();
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { user.setOpenId(sessionInfo.getOpenid());
log.info("登录用户:{} 已被停用.", openid); user.setSessionKey(sessionInfo.getSessionKey());
// todo 用户已被停用 业务逻辑自行实现 user.setUnionId(sessionInfo.getUnionid());
wxUserMapper.insert(user);
} else if (DeleteStatusEnum.DELETED.getCode().equals(user.getDeleteFlag())) {
log.info("登录用户:{} 已被停用.", sessionInfo.getOpenid());
throw new RuntimeException("当前用户已停用,请联系管理员");
} else if (StringUtils.isNotEmpty(phone) && StringUtils.isNotEmpty(user.getMobile())) {
user.setMobile(phone);
user.setAuthMobile(phone);
wxUserMapper.updateById(user);
} }
return user; return user;
} }
......
...@@ -28,10 +28,6 @@ public class DbWxUser { ...@@ -28,10 +28,6 @@ public class DbWxUser {
*/ */
private String openId; private String openId;
/** /**
* 是否是团长:1:是,2:否
*/
private Integer headOrNot;
/**
* 用户昵称 * 用户昵称
*/ */
private String nickname; private String nickname;
...@@ -68,14 +64,6 @@ public class DbWxUser { ...@@ -68,14 +64,6 @@ public class DbWxUser {
*/ */
private String authMobile; private String authMobile;
/** /**
* 商场编码
*/
private String mallCode;
/**
* 会员卡号
*/
private String userCode;
/**
* *
*/ */
private String sessionKey; private String sessionKey;
...@@ -92,21 +80,13 @@ public class DbWxUser { ...@@ -92,21 +80,13 @@ public class DbWxUser {
*/ */
private String wechatOriginalId; private String wechatOriginalId;
/** /**
* 下单次数 * 创建时间
*/
private Long orderNum;
/**
* 累计消费
*/
private BigDecimal cumulativeConsumption;
/**
* 最近消费时间
*/ */
private Date lastConsumptionTime; private Date createTime;
/** /**
* 创建人Code * 创建人
*/ */
private String createCode; private String createBy;
/** /**
* 更新时间 * 更新时间
*/ */
......
...@@ -62,7 +62,7 @@ public class DbWxUserServiceImpl implements IDbWxUserService { ...@@ -62,7 +62,7 @@ public class DbWxUserServiceImpl implements IDbWxUserService {
Map<String, Object> params = bo.getParams(); Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<DbWxUser> lqw = Wrappers.lambdaQuery(); LambdaQueryWrapper<DbWxUser> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getOpenId()), DbWxUser::getOpenId, bo.getOpenId()); lqw.eq(StringUtils.isNotBlank(bo.getOpenId()), DbWxUser::getOpenId, bo.getOpenId());
lqw.eq(bo.getHeadOrNot() != null, DbWxUser::getHeadOrNot, bo.getHeadOrNot());
lqw.like(StringUtils.isNotBlank(bo.getNickname()), DbWxUser::getNickname, bo.getNickname()); lqw.like(StringUtils.isNotBlank(bo.getNickname()), DbWxUser::getNickname, bo.getNickname());
lqw.eq(bo.getSex() != null, DbWxUser::getSex, bo.getSex()); lqw.eq(bo.getSex() != null, DbWxUser::getSex, bo.getSex());
lqw.eq(StringUtils.isNotBlank(bo.getProvince()), DbWxUser::getProvince, bo.getProvince()); lqw.eq(StringUtils.isNotBlank(bo.getProvince()), DbWxUser::getProvince, bo.getProvince());
...@@ -72,16 +72,10 @@ public class DbWxUserServiceImpl implements IDbWxUserService { ...@@ -72,16 +72,10 @@ public class DbWxUserServiceImpl implements IDbWxUserService {
lqw.eq(StringUtils.isNotBlank(bo.getUnionId()), DbWxUser::getUnionId, bo.getUnionId()); lqw.eq(StringUtils.isNotBlank(bo.getUnionId()), DbWxUser::getUnionId, bo.getUnionId());
lqw.eq(StringUtils.isNotBlank(bo.getMobile()), DbWxUser::getMobile, bo.getMobile()); lqw.eq(StringUtils.isNotBlank(bo.getMobile()), DbWxUser::getMobile, bo.getMobile());
lqw.eq(StringUtils.isNotBlank(bo.getAuthMobile()), DbWxUser::getAuthMobile, bo.getAuthMobile()); lqw.eq(StringUtils.isNotBlank(bo.getAuthMobile()), DbWxUser::getAuthMobile, bo.getAuthMobile());
lqw.eq(StringUtils.isNotBlank(bo.getMallCode()), DbWxUser::getMallCode, bo.getMallCode());
lqw.eq(StringUtils.isNotBlank(bo.getUserCode()), DbWxUser::getUserCode, bo.getUserCode());
lqw.eq(StringUtils.isNotBlank(bo.getSessionKey()), DbWxUser::getSessionKey, bo.getSessionKey()); lqw.eq(StringUtils.isNotBlank(bo.getSessionKey()), DbWxUser::getSessionKey, bo.getSessionKey());
lqw.eq(bo.getWechatSubscribe() != null, DbWxUser::getWechatSubscribe, bo.getWechatSubscribe()); lqw.eq(bo.getWechatSubscribe() != null, DbWxUser::getWechatSubscribe, bo.getWechatSubscribe());
lqw.eq(bo.getCancelSubscribe() != null, DbWxUser::getCancelSubscribe, bo.getCancelSubscribe()); lqw.eq(bo.getCancelSubscribe() != null, DbWxUser::getCancelSubscribe, bo.getCancelSubscribe());
lqw.eq(StringUtils.isNotBlank(bo.getWechatOriginalId()), DbWxUser::getWechatOriginalId, bo.getWechatOriginalId()); lqw.eq(StringUtils.isNotBlank(bo.getWechatOriginalId()), DbWxUser::getWechatOriginalId, bo.getWechatOriginalId());
lqw.eq(bo.getOrderNum() != null, DbWxUser::getOrderNum, bo.getOrderNum());
lqw.eq(bo.getCumulativeConsumption() != null, DbWxUser::getCumulativeConsumption, bo.getCumulativeConsumption());
lqw.eq(bo.getLastConsumptionTime() != null, DbWxUser::getLastConsumptionTime, bo.getLastConsumptionTime());
lqw.eq(StringUtils.isNotBlank(bo.getCreateCode()), DbWxUser::getCreateCode, bo.getCreateCode());
lqw.eq(bo.getModifyTime() != null, DbWxUser::getModifyTime, bo.getModifyTime()); lqw.eq(bo.getModifyTime() != null, DbWxUser::getModifyTime, bo.getModifyTime());
lqw.eq(StringUtils.isNotBlank(bo.getModifyBy()), DbWxUser::getModifyBy, bo.getModifyBy()); lqw.eq(StringUtils.isNotBlank(bo.getModifyBy()), DbWxUser::getModifyBy, bo.getModifyBy());
lqw.eq(StringUtils.isNotBlank(bo.getModifyCode()), DbWxUser::getModifyCode, bo.getModifyCode()); lqw.eq(StringUtils.isNotBlank(bo.getModifyCode()), DbWxUser::getModifyCode, bo.getModifyCode());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment