SpringCloud 大型系列课程正在制造中,欢迎大家重视与提意见。
本文章是系列文章中的一篇
- SpringCloud 整合Gateway服务网关 【SpringCloud系列5】
- SpringCloud 事务管理后台 经过FeignClient来调用oauth/token接口【SpringCloud系列11】
- Spring Security OAuth2.0 多点登录与单点登录【SpringCloud系列12】
- # SpringCloud 微信小程序授权登录 获取openId SessionKey【SpringCloud系列13】
完成微信小程序用户登录的方案有三种,本文章完成的是第二种。
- 方案一 只获取用户对应的openId,来创立符号用户
- 方案二 获取用户对应的openId与微信绑定的手机来,来创立符号用户
- 方案三 获取微信用户的基本信息,来创立符号用户。
1 微信小程序的登录页面
我这儿仅仅放了一个登录按钮
<view style='width:100%;padding-left:30rpx;font-size: 30rpx;margin-top:20rpx;'>
3. 赞同当前小程序获取手机号;
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>
</view>
对应的页面 js
Page({
/**
* 页面的初始数据
*/
data: {
sessionKey:'',
openId:'',
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
let that = this;
wx.login({
success: function (loginRes) {
let code = loginRes.code;
//获取sessionKey
wx.request({
url: api.AuthLoginGetSessionKey,
method: "post",
header: {
'appId': ''
},
data: {
code: code,
},
success: function (res) {
console.log('login success');
let sessionKey = res.data.data.sessionKey;
let openId = res.data.data.openId;
that.setData({
sessionKey: sessionKey,
openId:openId
});
},
fail: function (error) {
//调用服务端登录接口失利
console.log(error);
wx.showModal({
title: '提示',
showCancel: false,
content: '授权失利',
success: function (res) {
console.log(res)
// 拒绝授权确认后到逻辑处理
wx.navigateBack();
}
})
}
});
},
fail: function (err) {
wx.showModal({
title: '提示',
showCancel: false,
content: '授权失利',
success: function (res) {
console.log(res)
// 拒绝授权确认后到逻辑处理
wx.navigateBack();
}
})
}
});
},
getPhoneNumber: function (e) {
var that = this;
console.log(e.detail.errMsg == "getPhoneNumber:ok");
if (e.detail.errMsg == "getPhoneNumber:ok") {
wx.request({
url: api.AuthLoginByPhone,
method: "post",
header: {
'appId': 'wx27c83f987452ccec'
},
data: {
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
sessionKey: that.data.sessionKey,
openId: that.data.openId,
uid: "",
},
method: "post",
success: function (res) {
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();
}
})
}
},
})
这儿完成获取手机号一键登录功用的过程如下:
- 第一步 进入页面时,获取暂时登录令牌 code
- 第二步 依据 code , 调用自己事务后接口,获取 openId 与 sessionKey
- 第三步 页面中点击按钮获取微信绑定的手机号,这个需求用户触发
- 第四步 获取手机号授权后,调用自己事务后台接口进行用户登录
2 事务后台
首先是依据code来获取sessionKey 与 openId , 这个接口是小程序中,用户在进入登录页面里直接调用的
@Slf4j
@RestController
@RequestMapping("/wx")
public class LoginController {
@Resource
private FeignWxClient feignWxClient;
/**
* @return sessionKey 与 openId
*/
@PostMapping(value = "/login_get_session")
public CommonResult getSession(@RequestBody MiniLoginCodeRequest request, @RequestHeader String appId) {
log.info("微信登录 port {}", serverPort);
request.setAppId(appId);
Map<String, Object> map = feignWxClient.miniLoginBySession(request);
return CommonResult.success(map);
}
}
如下图是本项目 微服务的调用关系,小程序统一拜访 mini-api 服务,然后依据 code 去调用 wx-service 服务中的微信认证接口。
@FeignClient("wx-service")
public interface FeignWxClient {
/**
* 经过code 获取 openId 以及 sessionKey
* @param loginDTO
* @return
*/
@RequestMapping(method = RequestMethod.POST, value = "/wx/login_by_code")
Map<String,Object> miniLoginBySession(@RequestBody MiniLoginCodeRequest loginDTO);
}
然后在小程序中,当用户点击按钮获取手机号授权后,调用登录接口
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wx")
public class WxUserController {
@Autowired
private WxAppLoginService wxAppLoginService;
@ApiOperation(value = "获取用电话")
@PostMapping("/login_by_phone")
public Map<String,Object> phone(@RequestBody MiniLoginRequest loginDTO) throws WxErrorException {
return wxAppLoginService.phone(loginDTO);
}
}
对应的 Service 完成类如下
@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> phone(MiniLoginRequest loginDTO) {
final WxMaService wxService = getWxMaService(loginDTO.getAppId());
String iv = loginDTO.getIv();
String encryptedData = loginDTO.getEncryptedData();
String sessionKey = loginDTO.getSessionKey();
// 解密
WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
Map<String, Object> map = new HashMap<>();
map.put("phone", phoneNoInfo.getPhoneNumber());
map.put("sessionKey", sessionKey);
map.put("code", 200);
return map;
}
}
本项目 SpringCloud 源码 gitee.com/android.lon… 本项目 管理后台web 源码gitee.com/android.lon… 本项目 小程序 源码gitee.com/android.lon… 如果有兴趣可以重视一下大众号 biglead ,每周都会有 java、Flutter、小程序、js 、英语相关的内容共享
本文正在参与「金石方案」