我们在实现微信登录的业务逻辑时,往往最需要的是能够拿到识别该微信用户的唯一凭证———openid。小程序官方文档有说明,用户授权登录后,通过小程序给出的接口 wx.login 可以获得临时登录凭证code,再通过后端将code作为参数,请求小程序服务器地址得到openid后,传入客户端进行有效期限的本地存储(注:小程序官方不建议将openid暴露出来,所以在服务端获取到openid时,可以选择将openid进行加密方式传到客户端),即可完成登录流程,官方文档地址有说明请求地址、参数和返回参数:
官方文档链接
前端页面的展示大概是这个样子,这里直接上代码
login.wxml的页面
申请获取以下权限
获得你的公开信息(昵称,头像,手机等)
请升级微信版本
login.wxss
.headView {
margin: 90rpx 50rpx 90rpx 50rpx; /*上右下左*/
}
.headImageView {
display: block;
margin-left: 25px;
margin-top: 25px;
margin-right: 25px;
margin-bottom: 0px;
height: 50px;
}
.headImage{
display: flex;
width: 50px;
height: 50px;
position: relative;
left: 250rpx;
}
.titleText {
margin-left: 25px;
margin-top: 25px;
margin-bottom: 10px;
font-size: 14px;
color: #020e0f;
text-align: center;
}
.contentText {
margin-left: 25px;
margin-top: 0px;
margin-bottom: 0px;
font-size: 14px;
color: #666;
text-align: center;
}
.authBtn {
margin-top: 35px;
margin-left: 25px;
margin-right: 25px;
height: 45px;
font-size: 17.5px;
}
login.js (这里 request请求我封装过了,也可以直接使用微信官方API wx.request进行请求)
Page({
/**
* 页面的初始数据
*/
data: {
canIUse: wx.canIUse('button.open-type.getUserInfo'),
isHide: false
},
bindGetUserInfo: function (e) {
const userInfo = e.detail.userInfo
if (e.detail.userInfo) {
var that = this;;
wx.login({
//通过wx.login接口获取到临时code
success: function(res) {
//将临时code发送到后端
request({
url: '/user/login',
data: {
code: res.code,
nickname: userInfo.nickName,
city: userInfo.city,
province: userInfo.province,
avartar: userInfo.avatarUrl
},
method: 'post'
}).then(res => {
//将后端进行加密后返回回来的openid作为userID存储入本地,实现登录缓存
wx.setStorageSync('userId', res.data.result);
console.log(wx.getStorageSync('userId'));
//授权登录成功后跳转首页
wx.reLaunch({
url: '/pages/home/home',
});
console.log(res.data.result);
}).catch(err => {
console.log('请求失败');
})
}
})
//授权成功后,隐藏授权页面
that.setData({
isHide: false
});
} else {
//用户按了拒绝按钮
wx.showModal({
title: '警告',
content: '您点击了拒绝授权,将无法进入小程序,请授权之后再进入!!!',
showCancel: false,
confirmText: '返回授权',
success: function (res) {
// 用户没有授权成功,不需要改变 isHide 的值
if (res.confirm) {
console.log('用户点击了“返回授权”');
}
}
});
}
}
})
app.js
/**
* 当小程序初始化完成时,对存储的userId进行查询,如果usrId不为空则直接进入首页反之,跳转到登录页面。
*/
onLaunch: function () {
const userId=wx.getStorageSync('userId');
console.log(userId);
if(userId && userId.length!=0){
wx.reLaunch({
url: '/pages/home/home',
})
}else{
wx.reLaunch({
url: '/pages/login/login',
})
}
}
UrlUtil .java 后端拿到code后需要对官方文档中的地址进行GET请求,所以我们应该创建一个HTTP的请求工具类(这一段代码完全复制粘贴)
package com.example.utils;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class UrlUtil {
public static String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
// 创建http GET请求
HttpGet httpGet = new HttpGet(uri);
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGet(String url) {
return doGet(url, null);
}
public static String doPost(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPost(String url) {
return doPost(url, null);
}
public static String doPostJson(String url, String json) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
}
UserController.java中的部分代码(1):使用工具类对请求地址发送请求,请求参数appId与secret在开发者设置中进行查看
private JSONObject getUserWXLoginInfo(String wxCode) {
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
Map<String,String> requestUrlParam = new HashMap<String,String>();
requestUrlParam.put("appid", appId); //小程序 appId
requestUrlParam.put("secret", appKey); //小程序 appSecret
appSecret
requestUrlParam.put("js_code", wxCode); //登录时获取的 code
requestUrlParam.put("grant_type", "authorization_code"); //授权类型,此处固定
JSONObject jsonObject = JSON.parseObject(UrlUtil.doGet(requestUrl, requestUrlParam));
return jsonObject;
}
UserController.java中的部分代码(2):对请求返回的数据进行加工,如:录入数据库,加密openid等
@PostMapping("login")
public ResultMap login(@RequestBody LoginUser loginUser) throws ParseException {
JSONObject jsonObject = getUserWXLoginInfo(loginUser.getCode());
if(jsonObject!=null&&!jsonObject.containsKey("openid")) {
return new ResultMap(CommonConstant.ERROR,CommonConstant.RESULT_ERROR);
}
String openid = (String)jsonObject.get("openid");
//这里我是用MD5的方式将openid进行加密
String userId= MDUtil.getEncrpytedPassword(openid);
User user=userService.getById(userId);
if(user==null){
userService.insert(userId,loginUser);
}
return new ResultMap(CommonConstant.SUCCESS,CommonConstant.RESULT_SUCCESS,userId);
}