用户模块——扫码登陆整合测试
1. 微信 SDK 接入
在开发微信公众平台相关功能时,我们需要和微信服务器进行交互,例如获取用户信息、生成带参数二维码、处理消息等。微信官方提供了 API,但直接调用这些 API 需要自己处理 HTTP 请求、参数拼接、签名验证等,非常麻烦。因此,我们使用 weixin-java-mp SDK 来简化这一过程。
1.1 引入微信 SDK
微信的第三方 SDK weixin-java-mp 由 binarywang 维护,功能强大且文档齐全。首先,我们要在项目中引入它。
(1)在 pom.xml 中添加依赖
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.5.0</version> <!-- 请根据需要调整版本 -->
</dependency>
(2)Maven 更新依赖
在 IDEA 中,右键点击 pom.xml,选择 "Reload Project" 重新加载依赖。或者在命令行执行:
mvn clean install
1.2 配置微信的开发参数
在调用微信 API 之前,我们需要注册微信公众号,并获取 AppId、AppSecret、Token 和 AesKey。
- AppId(应用 ID):微信分配的唯一身份标识
- AppSecret(应用密钥):用于获取
access_token的凭证 - Token(令牌):用于服务器验证消息来源是否合法
- AesKey(消息加密密钥):用于加密和解密微信的消息
登录 微信公众平台 → 开发 → 基本配置,找到这些信息,并复制下来。
1.3 创建配置文件
为了方便管理这些参数,我们需要把它们写入配置文件。
(1)在 resources 目录下创建 application.yml
路径:src/main/resources/application.yml
wx:
mp:
appId: your-app-id
secret: your-app-secret
token: your-token
aesKey: your-aes-key
注意:
your-app-id等信息需要替换为你在微信公众平台获取的真实值- 不要把
AppSecret上传到 GitHub 等公共平台! 可以使用环境变量或application-${profile}.yml进行不同环境的配置
1.4 创建 WxMpConfig 配置类
在 user 模块下新建一个 config 包,并创建 WxMpConfig 配置类,负责读取 application.yml 中的微信参数,并提供 WxMpService(微信服务类)供业务层调用。
(1)创建 WxMpConfig.java
路径:com.example.user.config.WxMpConfig.java
package com.example.user.config;
import lombok.Data;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "wx.mp") // 绑定 application.yml 中的配置
public class WxMpConfig {
private String appId;
private String secret;
private String token;
private String aesKey;
@Bean
public WxMpService wxMpService() {
WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
config.setAppId(appId);
config.setSecret(secret);
config.setToken(token);
config.setAesKey(aesKey);
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(config);
return wxMpService;
}
}
代码解析:
@ConfigurationProperties(prefix = "wx.mp")让 Spring 自动读取application.yml里的微信参数WxMpService是 SDK 提供的核心类,负责处理微信的 API 请求WxMpDefaultConfigImpl负责存储微信的AppId、Secret等信息
1.5 处理微信消息
微信服务器会推送事件(如用户关注、消息发送、扫码等),我们需要创建 handler 处理这些事件。
(1)创建 handler 目录
在 user.service 目录下创建 handler 包,存放事件处理类。
(2)创建 LogHandler.java(日志处理器)
package com.example.user.service.handler;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.handler.WxMpMessageHandler;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class LogHandler implements WxMpMessageHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
log.info("收到消息:{}", wxMessage);
return null;
}
}
1.6 配置 WxMpMessageRouter(消息路由器)
为了让微信消息被正确的 handler 处理,我们需要配置 WxMpMessageRouter。
(1)创建 WxMpMessageRouterConfig.java
package com.example.user.config;
import com.example.user.service.handler.LogHandler;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@RequiredArgsConstructor
public class WxMpMessageRouterConfig {
private final WxMpService wxMpService;
private final LogHandler logHandler;
@Bean
public WxMpMessageRouter wxMpMessageRouter() {
WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);
// 记录所有收到的消息
router.rule().handler(logHandler).next();
return router;
}
}
代码解析:
WxMpMessageRouter负责分发微信的消息和事件router.rule().handler(logHandler).next();让LogHandler处理所有消息
1.7 启动项目并测试
(1)运行 Spring Boot 项目
确保 application.yml 中的 appid 和 secret 配置正确,然后启动项目。
mvn spring-boot:run
(2)使用内网穿透
微信服务器必须访问你的接口,因此需要使用 ngrok 或 frp 进行内网穿透,把本地服务映射到公网。
./ngrok http 8080
(3)配置微信服务器
- 进入 微信公众平台 → 开发 → 基本配置
- 在 服务器配置 处填写你的公网 URL,例如
https://xxxx.ngrok.io/wx/callback - Token 填写
application.yml中的token - 确认后提交
如果一切正常,微信 SDK 就接入成功了!
总结
到目前为止,我们已经完成了:
✅ 引入微信 SDK
✅ 配置 AppId、Secret 等参数
✅ 创建 WxMpService 进行 API 调用
✅ 处理微信推送消息
✅ 配置 WxMpMessageRouter 分发消息
接下来,我们可以继续实现 带参二维码接口! 🚀
2 带参二维码接口
在微信开发中,我们经常需要生成带参数的二维码,例如:
- 渠道推广:不同推广渠道(公众号菜单、公众号文章、海报等)扫描的二维码带不同参数,以统计用户来源。
- 用户绑定:用户扫描二维码后,公众号可以根据参数确定用户身份,进行绑定操作。
- 临时 vs. 永久:微信支持 临时二维码(带过期时间) 和 永久二维码(不会过期,但数量有限)。
本节我们将详细介绍如何使用 weixin-java-mp SDK 生成带参二维码,并获取扫码事件。
2.1 微信二维码的类型
微信提供两种类型的二维码:
-
临时二维码(带
scene_id,最多 30 天)- 适用于短期推广活动,如优惠券、限时活动
- 生成的二维码会过期,但数量几乎无限制
-
永久二维码(带
scene_str,不会过期)- 适用于长期场景,如用户 ID 绑定、渠道追踪
- 只能创建 10万个,不能随意删除
| 二维码类型 | 参数 | 过期时间 | 适用场景 |
|---|---|---|---|
| 临时二维码 | scene_id (1~32bit整数) | 最多 30 天 | 短期活动、推广 |
| 永久二维码 | scene_str (字符串) | 永久 | 用户绑定、渠道统计 |
2.2 生成带参二维码
(1)创建 WxQrCodeService 生成二维码
在 service 包下创建 WxQrCodeService.java:
package com.example.user.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpQrcodeService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor
public class WxQrCodeService {
private final WxMpService wxMpService;
/**
* 生成临时二维码
* @param sceneId 场景值ID(1~32位整数)
* @param expireSeconds 过期时间(最多30天)
* @return 二维码URL
*/
public String createTempQrCode(int sceneId, int expireSeconds) {
try {
WxMpQrcodeService qrCodeService = wxMpService.getQrcodeService();
WxMpQrCodeTicket ticket = qrCodeService.qrCodeCreateTmpTicket(sceneId, expireSeconds);
return qrCodeService.qrCodePictureUrl(ticket.getTicket());
} catch (WxErrorException e) {
log.error("生成临时二维码失败", e);
return null;
}
}
/**
* 生成永久二维码
* @param sceneStr 场景值(字符串)
* @return 二维码URL
*/
public String createPermanentQrCode(String sceneStr) {
try {
WxMpQrcodeService qrCodeService = wxMpService.getQrcodeService();
WxMpQrCodeTicket ticket = qrCodeService.qrCodeCreateLastTicket(sceneStr);
return qrCodeService.qrCodePictureUrl(ticket.getTicket());
} catch (WxErrorException e) {
log.error("生成永久二维码失败", e);
return null;
}
}
}
2.3 提供二维码 API
为了让前端调用二维码功能,我们需要创建 WxQrCodeController。
(1)创建 WxQrCodeController.java
在 controller 包下创建 WxQrCodeController.java:
package com.example.user.controller;
import com.example.user.service.WxQrCodeService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/wx/qrcode")
@RequiredArgsConstructor
public class WxQrCodeController {
private final WxQrCodeService wxQrCodeService;
/**
* 生成临时二维码
* @param sceneId 场景值(整数)
* @param expireSeconds 过期时间(秒)
* @return 二维码URL
*/
@GetMapping("/temp")
public String getTempQrCode(@RequestParam int sceneId, @RequestParam int expireSeconds) {
return wxQrCodeService.createTempQrCode(sceneId, expireSeconds);
}
/**
* 生成永久二维码
* @param sceneStr 场景值(字符串)
* @return 二维码URL
*/
@GetMapping("/permanent")
public String getPermanentQrCode(@RequestParam String sceneStr) {
return wxQrCodeService.createPermanentQrCode(sceneStr);
}
}
2.4 监听扫码事件
当用户扫描二维码时,微信服务器会推送 关注 或 扫码 事件,我们需要捕获这些事件,并进行处理。
(1)创建 QrCodeHandler.java
package com.example.user.service.handler;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.handler.WxMpMessageHandler;
import org.springframework.stereotype.Component;
import java.util.Map;
@Slf4j
@Component
public class QrCodeHandler implements WxMpMessageHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
String eventKey = wxMessage.getEventKey();
String openId = wxMessage.getFromUser();
log.info("用户 {} 扫描二维码,参数:{}", openId, eventKey);
// 这里可以根据 eventKey 进行业务处理,例如:
// 1. 记录用户扫码来源
// 2. 给用户返回自定义的欢迎信息
return WxMpXmlOutMessage.TEXT()
.content("感谢您的关注,您的专属二维码参数是:" + eventKey)
.fromUser(wxMessage.getToUser())
.toUser(openId)
.build();
}
}
2.5 注册扫码事件
修改 WxMpMessageRouterConfig.java,让 QrCodeHandler 处理二维码事件。
@Bean
public WxMpMessageRouter wxMpMessageRouter() {
WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);
// 处理用户扫码
router.rule().event("SCAN").handler(qrCodeHandler).next();
router.rule().event("subscribe").handler(qrCodeHandler).next();
return router;
}
2.6 测试
(1)生成二维码
请求临时二维码:
curl "http://localhost:8080/wx/qrcode/temp?sceneId=123&expireSeconds=600"
返回:
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=xxxxx
在浏览器中打开这个 URL,即可看到二维码。
请求永久二维码:
curl "http://localhost:8080/wx/qrcode/permanent?sceneStr=abc"
(2)扫描二维码
- 使用 微信扫描二维码
- 观察控制台日志,是否正确打印
用户 xxx 扫描二维码,参数:xxx - 确保微信服务器能访问你的接口(使用 ngrok 或 frp)
总结
✅ 生成 临时/永久二维码
✅ 监听 扫码事件,获取 scene_id 或 scene_str
✅ 通过二维码参数进行业务逻辑处理
带参二维码广泛用于用户绑定、渠道统计、活动推广等场景,现在你可以自由定制业务逻辑啦! 🚀
3 用户信息授权接口
在微信公众号开发中,有时候我们需要获取用户的信息,比如 头像、昵称、性别 等。为了保护用户隐私,微信提供了一套授权机制,用户同意授权后,开发者才能获取这些信息。
本节我们详细介绍 用户授权流程,并使用 weixin-java-mp SDK 实现授权登录。
3.1 用户授权的作用
在以下场景,我们可能需要获取用户信息:
✅ 个性化展示:获取昵称、头像,让用户感受到定制化体验。
✅ 用户身份验证:绑定用户信息,避免重复注册。
✅ 精准营销:结合用户性别、地区等数据,推荐合适的内容或商品。
但是,微信默认情况下不会提供用户信息,我们必须通过 OAuth2.0 授权 才能获取。
3.2 微信授权的两种方式
微信提供了 两种授权方式:
-
静默授权(snsapi_base)
- 无需用户确认,直接获取用户
openid(唯一标识)。 - 适用于 自动登录、数据统计 场景。
- 无需用户确认,直接获取用户
-
弹出授权(snsapi_userinfo)
- 用户手动确认,获取用户 昵称、头像、性别等信息。
- 适用于 个性化页面、需要用户信息的功能。
| 方式 | 需要用户确认 | 可获取的数据 | 适用场景 |
|---|---|---|---|
snsapi_base | 否 | openid | 静默登录、统计用户数量 |
snsapi_userinfo | 是 | openid、昵称、头像、性别等 | 个性化展示、用户绑定 |
3.3 用户授权流程
1️⃣ 前端跳转到微信授权页面(用户点击登录按钮)
2️⃣ 用户同意授权(如果是 snsapi_userinfo)
3️⃣ 后端获取授权码 code(微信回调到我们的接口)
4️⃣ 后端用 code 换取 access_token 和 openid
5️⃣ 使用 access_token 获取用户信息(昵称、头像等)
完整流程示意图:
用户点击登录 → 微信授权页 → 用户同意 → 微信回调后端 → 后端获取 access_token → 获取用户信息
3.4 代码实现
(1)前端跳转到授权页
前端用户点击按钮,跳转到 微信授权链接:
<a href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的APPID
&redirect_uri=你的回调地址
&response_type=code
&scope=snsapi_userinfo
&state=STATE#wechat_redirect">
微信登录
</a>
scope=snsapi_userinfo代表弹出授权
redirect_uri是用户授权后,微信会跳转的回调 URL
(2)后端处理授权
在 controller 目录下创建 WxAuthController.java 处理授权逻辑。
package com.example.user.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@RequestMapping("/wx/auth")
@RequiredArgsConstructor
public class WxAuthController {
private final WxMpService wxMpService;
/**
* 处理微信回调,获取用户 openid 和基本信息
*/
@GetMapping("/callback")
public String wxAuthCallback(@RequestParam("code") String code) {
try {
// 1. 通过 code 获取 access_token 和 openid
WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
String openId = accessToken.getOpenId();
// 2. 获取用户信息
return wxMpService.oauth2getUserInfo(accessToken, null).toString();
} catch (WxErrorException e) {
log.error("微信授权失败", e);
return "微信授权失败";
}
}
}
(3)前端拼接授权链接
前端页面需要生成授权跳转链接,拼接 redirect_uri:
const appId = "你的公众号APPID";
const redirectUri = encodeURIComponent("https://你的服务器地址/wx/auth/callback");
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`;
window.location.href = url;
3.5 公众号授权 vs. 开放平台授权
公众号授权:仅限 公众号内 使用。
开放平台授权:支持网站/APP,用于微信扫码登录网站。
如果你要做的是 网站扫码登录(类似微信 PC 扫码登录),请使用 微信开放平台 的 网页授权,流程类似但 URL 不同。
3.6 测试
(1)打开授权链接
- 在浏览器中访问
http://你的服务器/wx/auth/login - 观察是否跳转到 微信授权页面
(2)授权后回调
- 用户点击“同意”后,微信会跳转到回调地址
/wx/auth/callback - 观察后端日志,是否正确打印 openid 和用户信息
总结
✅ 理解微信授权流程(前端跳转 → 用户授权 → 回调后端)
✅ 实现授权接口(获取 openid 和 用户信息)
✅ 测试授权效果(浏览器打开授权链接)
到这里,你已经掌握了 微信公众号的用户信息授权,可以用于 登录、用户绑定、个性化推荐 等功能! 🚀
更多推荐



所有评论(0)