Spring后端HttpClient实现微信小程序登录

news/2025/1/15 13:36:02/

这是微信官方提供的时序图。我们需要关注的是前后端的交互,以及服务端如何收发网络请求。
api-login.2fcc9f35.jpg

小程序端

封装基本网络请求

我们先封装一个基本的网络请求。

const baseUrl="localhost:8080"
export default{sendRequsetAsync
}
/* e
url:目标页面,带斜杠:/user
method:方法,默认GET
data:json格式的数据
*/
async function sendRequsetAsync(e) {let responseconsole.log("发送异步网络请求")console.log(e)let promise = await new Promise((resolve, reject) => {wx.request({url: baseUrl + e.url,method: e.method || "GET",data: e.data || {},success: (res) => {resolve(res)},fail: (error) => {reject(error)}})})console.log(promise);return promise
}

指定baseUrl为本地8080端口。之后所有的小程序网络请求都基于这个方法。
这样当服务端地址变更时,只需要修改这里的baseUrl,而不需要对每个涉及网络请求的js文件都作修改。
使用promise获取服务端返回的数据。直接接受wx.request()的返回值,得到的是一个网络请求任务对象。
image.png
赋值采用的是JS特有的括号()方法。如果用等号可能会赋值失败。
如果没有await,创建对象直接直接输出,得到的是一个promise对象。
image.png
这是因为promise是一个异步请求对象。在执行结束前,设计的数据会随时变动。
如果要等待异步请求结束,查看最终结算,则需要加上await
image.png
方法内使用await的前提是方法外使用async
image.png

实现小程序登录

我们已经封装了基本的网络请求,根据微信官方提供的时序图,我们接下来需要获取用户登录授权码code
调用wx.login()方法可以直接获取:
image.png
wx.login()会弹出提示请求用户授权,这也是一个异步请求,如果要等接收到用户反馈之后再执行下一步操作,也需要添加await

let loginResultLocal = await wx.login()
console.log(loginResultLocal)
if (loginResultLocal.errMsg == "login:ok") {//本地请求登录,获取codelet loginResultServer = await loginByCode(loginResultLocal.code)//尝试通过code登陆if (loginResultServer.state == 0) {//用户未注册console.log("用户未注册")} else if (loginResultServer.state == 1) {//用户已注册console.log("用户已注册");}
} else {//如果用户不同意登录,跳转到拒绝服务页面,直到同意wx.reLaunch({url: '/pages/user/userRegister/userRegister'})
}

当然,这段代码也需要封装进工具类中,也需要调用之前封装好的其他工具类。
导入其他工具类只需要这一行代码,照葫芦画瓢即可:import webRequest from "./webRequest.js";
现在已经获取到了code,也封装了基本网络请求。接下来需要实现登陆方法,将小程序端获取到的code发送到服务端,接收服务端返回的openid等信息。
现在我们还没介绍服务端的业务逻辑,无论发送什么内容,返回数据都是“收到”。

async function loginByCode(code) {//通过code登录console.log("通过code登录:"+code);let e = {"url": "/user/user/login","method": "POST","data": {"loginMethod": "code","code": code}}let requestResult = await webRequest.sendRequsetAsync(e)return requestResult
}

控制台输出

image.png
服务端好像收到了小程序端发送到数据,但服务端接受的实际内容、服务端的业务逻辑,我们目前还是不清楚的。

服务端

小程序端以json形式,以POST方法发送了用户凭证code
openid需要从服务端通过GET方法获取
可以得出,服务端应能够:

  • 解析json
  • 响应post方法
  • 发送get请求

解析JSON,响应POST方法

image.png
根据开发文档,我们需要提前准备好appid和secret。如果不知道在哪里,可以直接私我。
image.png
按照上面的格式添加到配置文件中。
这并没有通过全局静态常量的方式保存在类中。因为小程序信息可能会经常用到,之后也可能会发生改变,通过引用的方式,可以只修改这一处。

@Value("${wechat.appid}")
private String appid;
@Value("${wechat.secret}")
private String secret;

通过@Value注解将配置文件中的值赋值给下面的字符串。
GET方法的参数暴露在Url中,可以选择用简单粗暴的字符串拼接方式发送GET请求。
服务端发送登录请求还需要code,这由小程序端通过POST请求传入。

可以提前创建实体类。

public class UserLoginDTO {@Getterprivate String code;
}

响应POST请求通过@PostMapping注解实现
解析POST请求携带的JSON,作为函数参数传入,通过@RequestBody注解实现
image.png

HttpClient

HttpClient工具包用于在spring中发送网络请求。
https://hc.apache.org/httpcomponents-client-5.2.x/quickstart.html
发送请求步骤:

  1. 创建HttpClient对象
  2. 创建Http请求对象
  3. 调用HttpClient的execute方法发送请求
//创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
//创建请求对象
HttpGet httpGet = new HttpGet("https://api.weixin.qq.com/sns/jscode2session?appid=" + appid+ "&secret=" + secret+ "&js_code=" + userLoginDTO.getCode()+ "&grant_type=authorization_code");
//发送请求,接受响应结果
CloseableHttpResponse response = httpClient.execute(httpGet);        //获取服务端返回的状态码
if (response.getCode() == 200) {//获取服务端返回的数据HttpEntity entity = response.getEntity();String body = EntityUtils.toString(entity);System.out.println(body);//关闭资源response.close();httpClient.close();return body;
}

Api测试

回到小程序端。服务端返回的消息随着软件开发的完善可能会作出修改。将相关代码单独封装。

目前输出结果如下:

image.png
可以通过wx.getStorageSyncwx.setStorageSync方法把openid和会话密钥在用户本地存取。


http://www.ppmy.cn/news/1215719.html

相关文章

什么是智能井盖?万宾科技的智能井盖传感器的效果

近年来为打造智慧城市政府一直在不懈努力。加速城市基础建设是一项重要的举措,它有助于推动城市综合治理城市生命线的建设工程。在改善市民生活质量的过程中,市政部门正积极进行井盖的改进和升级工作,特别是那些看似微不足道的井盖却蕴含着重…

WordPress 文档主题模板Red Line -v0.2.2

此主题作为框架,做承载第三方页面之用,例如飞书文档等, 您可以将视频图片等资源放第三方文档上,通过使用此主题做目录用。 此主题使用前后端分离开发,也使用了一些技术尽量不影响正常的SEO,还望注意。 源码…

LeetCode(10)跳跃游戏 II【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接: 45. 跳跃游戏 II 1.题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nu…

P36[11-1]SPI通信协议

SPI相比于IIC的优缺点: 1.SPI传输速度快(IIC高电平驱动能力较弱,因此无法高速传输) 2.使用简单 3.通信线多 SCK(SCLK,CK,CLK):串行时钟线 MOSI(DO):主机输出,从机输入 MISO(DI): 主机输入,从机输出 SS(NSS,CS):从机选择(有多少个从机,主机就要用几根SS分别与从机连接…

在 SQL 中,当复合主键成为外键时应该如何被其它表引用

文章目录 当研究一个问题慢慢深入时,一个看起来简单的问题也暗藏玄机。在 SQL 中,主键成为外键这是一个很平常的问题,乍一看没啥值得注意的。但如果这个主键是一种复合主键,而另一个表又引用这个键作为它的复合主键,问…

[100天算法】-球会落何处(day 76)

题目描述 用一个大小为 m x n 的二维网格 grid 表示一个箱子。你有 n 颗球。箱子的顶部和底部都是开着的。箱子中的每个单元格都有一个对角线挡板,跨过单元格的两个角,可以将球导向左侧或者右侧。将球导向右侧的挡板跨过左上角和右下角,在网…

【Spring Boot】034-Spring Boot 整合 JUnit

【Spring Boot】034-Spring Boot 整合 JUnit 文章目录 【Spring Boot】034-Spring Boot 整合 JUnit一、单元测试1、什么是单元2、什么是单元测试3、为什么要单元测试 二、JUnit1、概述简介特点 2、JUnit4概述基本用法 3、JUnit5概述组成 4、JUnit5 与 JUnit4 的常用注解对比 三…

[100天算法】-不同路径 III(day 75)

题目描述 在二维网格 grid 上,有 4 种类型的方格:1 表示起始方格。且只有一个起始方格。 2 表示结束方格,且只有一个结束方格。 0 表示我们可以走过的空方格。 -1 表示我们无法跨越的障碍。 返回在四个方向(上、下、左、右&#…