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 微信二维码的类型

微信提供两种类型的二维码:

  1. 临时二维码(带 scene_id,最多 30 天)

    • 适用于短期推广活动,如优惠券、限时活动
    • 生成的二维码会过期,但数量几乎无限制
  2. 永久二维码(带 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 微信授权的两种方式

微信提供了 两种授权方式:

  1. 静默授权(snsapi_base)

    • 无需用户确认,直接获取用户 openid(唯一标识)。
    • 适用于 自动登录、数据统计 场景。
  2. 弹出授权(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 和 用户信息)
✅ 测试授权效果(浏览器打开授权链接)

到这里,你已经掌握了 微信公众号的用户信息授权,可以用于 登录、用户绑定、个性化推荐 等功能! 🚀

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐