SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见。
本文章是系列文章中的一篇
- 1、SpringCloud 项目基础工程搭建 【SpringCloud系列1】
- 2、SpringCloud 集成Nacos注册中心 【SpringCloud系列2】
- 3、SpringCloud Feign远程调用 【SpringCloud系列3】
- 4、SpringCloud Feign远程调用公共类抽取 【SpringCloud系列4】
- 5、SpringCloud 整合Gateway服务网关 【SpringCloud系列5】
- 6、SpringCloud 整合 Spring Security 认证鉴权【SpringCloud系列6】
- SpringCloud网关Gateway认证鉴权【SpringCloud系列7】
- SpringCloud Gateway 通过redis实现限流【SpringCloud系列8】
- SpringCloud Gateway 整合阿里 Sentinel网关流控、熔断、降级【SpringCloud系列9】
- SpringCloud Gateway 整合RSA对请求参数解密、响应结果加密【SpringCloud系列10】
- SpringCloud 业务管理后台 通过FeignClient来调用oauth/token接口【SpringCloud系列11】
- Spring Security OAuth2.0 多点登录与单点登录【SpringCloud系列12】
- SpringCloud 微信小程序登录 方案一【SpringCloud系列13】
- SpringCloud 微信小程序 获取手机号一键登录 【SpringCloud系列14】
本文章实现的是微信小程序获取微信用户信息授权登录。
实现微信小程序用户登录的方案有三种,本文章实现的是第三种。
方案一 只获取用户对应的openId,来创建标记用户
方案二 获取用户对应的openId与微信绑定的手机来,来创建标记用户
方案三 获取微信用户的基本信息,来创建标记用户。
1 微信小程序代码
我这里实现的页面只是一个登录按钮
<view style='width:100%;padding-left:30rpx;font-size: 30rpx;margin-top:20rpx;'>
2. 同意当前小程序获取我的个人信息;
<button type="primary" bindtap="getUserProfile">授权微信头像与昵称</button>
</view>
然后在对应的 页面js 中,当进入这个登录页面时,调用 wx.login 获取 code 核心代码如下
let that = this;
wx.login({
success: function (loginRes) {
that.setData({
loginRes: loginRes
});
},
fail: function (err) {
wx.showModal({
title: '提示',
showCancel: false,
content: '授权失败',
success: function (res) {
console.log(res)
// 拒绝授权确定后到逻辑处理
wx.navigateBack();
}
})
}
});
这里保存了临时的 loginRes ,这个 loginRes 中的 code 只能使用一次,所以在下面调用如果出现错误 就需要退出页面重新进入,重新获取
1.1 获取 微信用户信息
用户点击按钮,调用获取微信获取用户信息的接口 wx.getUserProfile
// 获取用户昵称头像
getUserProfile() {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
// 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '用于展示个人中心头像,昵称', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res);
// 授权拿到昵称头像后处理的逻辑
//业务代码处理
this.requestAuthFunction(res);
},
fail: (err) => {
console.log(err);
wx.showModal({
title: '提示',
showCancel: false,
content: '取消授权',
success: function (res) {
console.log(res)
// 拒绝授权确定后到逻辑处理
}
})
}
});
},
1.2 获取微信用户信息
微信授权通过后,就需要请求业务接口后台,来解密用户信息
requestAuthFunction(infoRes) {
wx.request({
url: api.AuthLoginByWeixin,
method: "post",
header: {
'appId': ''
},
data: {
code: this.data.loginRes.code,
rawData: infoRes.rawData, //用户非敏感信息
signature: infoRes.signature, //签名
encryptedData: infoRes.encryptedData, //用户敏感信息
iv: infoRes.iv //解密算法的向量
},
success: function (res) {
console.log('login success');
console.log("res:", res)
wx.setStorageSync('token', res.data.data.access_token);
wx.setStorageSync('userInfo', res.data.data);
console.log("token=" + res.data.data.access_token);
wx.navigateBack();
},
fail: function (error) {
//调用服务端登录接口失败
console.log(error);
wx.navigateBack();
}
});
},
我这里请求 header 添加 了appId,是兼容支持多个小程序的配置,在业务后台处理里,需要根据 appId 来查询小程序的配置。
其实查询用户信息可以不使用 code ,我这里只是为了使用 code 来获取 openId 与 SessionKey .
2 业务后台代码
微信业务处理的功能在 wx-service 服务中,在《SpringCloud 微信小程序授权登录 获取openId SessionKey【SpringCloud系列13】》 中有概述
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wx")
public class WxUserController {
@Autowired
private WxAppLoginService wxAppLoginService;
/**
* 小程序用户登录
*
* @param request
* @param loginDTO
* @return
*/
@ApiOperation(value = "小程序用户登录=code、用户的基本信息")
@PostMapping("/login_by_userinfo")
public Map<String,Object> loginMa(HttpServletRequest request, @RequestBody MiniLoginRequest loginDTO) throws WxErrorException {
return wxAppLoginService.login(loginDTO);
}
]
然后对应的实现类
@Service
@Slf4j
public class WxAppLoginServiceImpl implements WxAppLoginService {
//查询数据库小程序配置
@Autowired
private WxAppInfoService wxAppInfoService;
private WxMaService getWxMaService(String appId) {
//查询数据库小程序的配置
WxAppInfo wxAppInfo = wxAppInfoService.queryByAppId(appId);
String appSecret = wxAppInfo.getSecret();
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
config.setAppid(appId);
config.setSecret(appSecret);
config.setMsgDataFormat("JSON");
WxMaService wxMaService = new WxMaServiceImpl();
wxMaService.setWxMaConfig(config);
return wxMaService;
}
@Override
public Map<String, Object> login(MiniLoginRequest request) throws WxErrorException {
final WxMaService wxService = getWxMaService(request.getAppId());
// 获取微信用户session
WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(request.getCode());
if (null == session) {
throw new RuntimeException("login handler error");
}
String openid = session.getOpenid();
String sessionKey = session.getSessionKey();
String unionid = session.getUnionid();
log.info("微信登录 openid {} unionid {} sessionKey {}", openid, unionid, sessionKey);
String iv = request.getIv();
String encryptedData = request.getEncryptedData();
String rawData = request.getRawData();
String signature = request.getSignature();
// 用户信息校验
if (!wxService.getUserService().checkUserInfo(sessionKey, rawData, signature)) {
}
// 解密用户信息
WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
String nickName = userInfo.getNickName();
String avatarUrl = userInfo.getAvatarUrl();
String unionId = userInfo.getUnionId();
Map<String, Object> map = new HashMap<>();
map.put("openId", openid);
map.put("unionId", unionId);
map.put("sessionKey", sessionKey);
map.put("code", 200);
map.put("nickName", nickName);
map.put("avatarUrl", avatarUrl);
return map;
}
}
本项目 SpringCloud 源码 https://gitee.com/android.long/spring-cloud-biglead/tree/master/biglead-api-11-admin
本项目 管理后台web 源码https://gitee.com/android.long/spring-cloud-biglead/tree/master/mall-admin-web-master
本项目 小程序 源码https://gitee.com/android.long/spring-cloud-biglead/tree/master/mall-app-web-master
如果有兴趣可以关注一下公众号 biglead ,每周都会有 java、Flutter、小程序、js 、英语相关的内容分享