Uniapp实现微信小程序登录

整体流程就是

  1. uniapp调用login方法,指定为微信登录,将用户的授权码(临时票据)发送至后端
  2. 后端使用该临时票据,发送请求,请求用户的openid

没办法获取用户信息了,像昵称这种东西只能是用户授权微信登录后自行填写

uniapp代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
uni.login({
"provider": "weixin",
"onlyAuthorize": true, // 微信登录仅请求授权认证
success: async function (event) {
const { code } = event
//客户端成功获取授权临时票据(code),向业务服务器发起登录请求。
console.log('正在请求后端接口,获取openid,code为:', code)
const res = await http<string>({
method: 'POST',
url: '/user/login',
data: {
code
}
})
console.log('前端收到的返回结果:', res)
nickName.value = res.data.nickName
avatarUrl.value = res.data.avatarUrl
userStore.setProfile({
account: (res.data as userLoginVo).account,
token: (res.data as userLoginVo).token,
nickName: (res.data as userLoginVo).nickName,
openid: (res.data as userLoginVo).openid,
})
uni.showToast({
title: '登录成功',
icon: 'success',
})
isLogin.value = true
},
fail: function (err) {
// 登录授权失败
// err.code是错误码
}
})

后端实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 登录接口重写,注册接口删掉,只实现微信登录
*/
@ApiOperation("微信登录")
@PostMapping("/login")
public Result login(@RequestBody WxLoginDto wxLoginDto) {
log.info("微信用户登录,授权码:{}", wxLoginDto.getCode());
User user = userService.wxLogin(wxLoginDto);
// 登录成功,生成token

Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.USER_ID, user.getUserId());

String token = JwtUtils.createJWT(
jwtProperties.getUserSecretKey(),
jwtProperties.getUserTtl(),
claims);
UserLoginVo userLoginVo = new UserLoginVo();
BeanUtils.copyProperties(user, userLoginVo);
userLoginVo.setToken(token);
return Result.success(userLoginVo);
}

Service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public User wxLogin(WxLoginDto wxLoginDto) {
String openid = getString(wxLoginDto);
// 判断其openid是否为空
if (openid == null) {
throw new BaseException("登陆失败");
}
log.info("用户的openid为:{}", openid);

// 根据openid在数据库中查询,如果存在该openid则表示用户已注册,反之自动为用户进行注册
User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getOpenid, openid));
if (user == null) {
// 新用户,则进行注册
user = User.builder().openid(openid).build();
userMapper.insert(user);
}
// 已注册,则直接返回
return user;
}

getString方法,用于通过code获取用户的openid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
/**
* 将根据userLoginDTO获取openId的片段抽取成一个方法
*
* @return
*/
private String getString(WxLoginDto wxLoginDto) {
// 1. 调用微信接口服务 获取openId
Map<String, String> paramMap = new HashMap<>();
paramMap.put("appId", wechatProperties.getAppid());
paramMap.put("secret", wechatProperties.getSecret());
paramMap.put("js_code", wxLoginDto.getCode());
paramMap.put("grant_type", "authorization_code");

String json = HttpClientUtil.doGet(WX_LOGIN, paramMap);

JSONObject jsonObject = JSON.parseObject(json);
String openId = jsonObject.getString("openid");
return openId;
}

后端HttpClientUtil代码及依赖

1
2
3
4
5
6
<!--        httpClient  -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package com.zzmr.fgback.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
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.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;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* Http工具类
*/
public class HttpClientUtil {

static final int TIMEOUT_MSEC = 5 * 1000;

/**
* 发送GET方式请求
* @param url
* @param paramMap
* @return
*/
public static String doGet(String url,Map<String,String> paramMap){
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();

String result = "";
CloseableHttpResponse response = null;

try{
URIBuilder builder = new URIBuilder(url);
if(paramMap != null){
for (String key : paramMap.keySet()) {
builder.addParameter(key,paramMap.get(key));
}
}
URI uri = builder.build();

//创建GET请求
HttpGet httpGet = new HttpGet(uri);

//发送请求
response = httpClient.execute(httpGet);

//判断响应状态
if(response.getStatusLine().getStatusCode() == 200){
result = EntityUtils.toString(response.getEntity(),"UTF-8");
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
response.close();
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}

return result;
}

/**
* 发送POST方式请求
* @param url
* @param paramMap
* @return
* @throws IOException
*/
public static String doPost(String url, Map<String, String> paramMap) throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";

try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);

// 创建参数列表
if (paramMap != null) {
List<NameValuePair> paramList = new ArrayList();
for (Map.Entry<String, String> param : paramMap.entrySet()) {
paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}

httpPost.setConfig(builderRequestConfig());

// 执行http请求
response = httpClient.execute(httpPost);

resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (Exception e) {
throw e;
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}

return resultString;
}

/**
* 发送POST方式请求
* @param url
* @param paramMap
* @return
* @throws IOException
*/
public static String doPost4Json(String url, Map<String, String> paramMap) throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";

try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);

if (paramMap != null) {
//构造json格式数据
JSONObject jsonObject = new JSONObject();
for (Map.Entry<String, String> param : paramMap.entrySet()) {
jsonObject.put(param.getKey(),param.getValue());
}
StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");
//设置请求编码
entity.setContentEncoding("utf-8");
//设置数据类型
entity.setContentType("application/json");
httpPost.setEntity(entity);
}

httpPost.setConfig(builderRequestConfig());

// 执行http请求
response = httpClient.execute(httpPost);

resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (Exception e) {
throw e;
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}

return resultString;
}
private static RequestConfig builderRequestConfig() {
return RequestConfig.custom()
.setConnectTimeout(TIMEOUT_MSEC)
.setConnectionRequestTimeout(TIMEOUT_MSEC)
.setSocketTimeout(TIMEOUT_MSEC).build();
}

}