微信公众平台Java开发完整教程
本教程将引导你使用 Java 语言开发一个微信公众号的后端服务,我们将使用流行的 Spring Boot 框架来简化开发过程。

目录
- 前置准备:理解微信公众平台类型
- 第一步:准备工作(服务器与域名)
- 第二步:创建公众号并获取必要信息
- 第三步:Java后端项目搭建(Spring Boot)
- 第四步:实现服务器配置(Token验证)
- 第五步:核心功能:接收与回复用户消息
- 1 接收文本消息
- 2 回复文本消息
- 3 处理其他类型消息(关注、点击菜单等)
- 第六步:高级API开发
- 1 网页授权获取用户信息
- 2 发送模板消息
- 第七步:部署上线
- 总结与进阶
前置准备:理解微信公众平台类型
微信公众平台主要分为三种账号,它们的开发权限和能力差异巨大,请务必先确认你要开发的是哪一种:
-
订阅号
- 功能:主要为用户提供信息和资讯,每天可以推送一次消息。
- 开发权限:有基本的自定义菜单、自动回复等开发接口,但没有微信支付、高级接口(如用户信息获取、模板消息)等核心能力。
- 适用场景:媒体、个人博主、内容创作者。
-
服务号
- 功能:主要为用户提供服务和服务通知,每月可以推送四次消息(重要服务通知会及时送达)。
- 开发权限:拥有所有高级接口,包括微信支付、用户信息获取、模板消息、JS-SDK等,这是企业级应用开发的首选。
- 适用场景:企业、政府、银行等需要提供服务或电商交易的组织。
-
小程序
(图片来源网络,侵删)- 功能:一种不需要下载安装即可使用的应用,用完即走。
- 开发:开发方式与公众号不同,有自己的开发者工具和API体系,本教程不涉及小程序开发。
如果你的目标是开发一个能提供完整服务(如会员、电商、通知)的应用,你需要一个服务号。
第一步:准备工作(服务器与域名)
在开始编码前,你需要准备一个可以公网访问的服务器和一个备案的域名。
- 服务器:推荐使用云服务器,如阿里云、腾讯云、华为云等,系统可以是 Linux (如 CentOS, Ubuntu) 或 Windows Server,但 Linux 更为常见和推荐。
- 域名:需要备案(如果服务器在国内),在公众号后台配置时,需要使用这个域名。
第二步:创建公众号并获取必要信息
- 访问 微信公众平台官网,使用你的邮箱注册一个服务号(或订阅号)。
- 登录后台,在 “开发” -> “基本配置” 中,你会看到服务器配置信息。
你需要获取以下关键信息:
- AppID (开发者ID):公众号的唯一标识。
- AppSecret (开发者密码):与AppID配对,用于调用高级API,请务必保密。
- 服务器配置(URL, Token, EncodingAESKey):
- URL:你的Java后端服务器的公网访问地址,必须以
http://或https://开头,并且支持80端口(或443端口)的80-bit消息体验证。 - Token:可以任意填写,用作开发者服务器与微信服务器之间的验证令牌。
- EncodingAESKey:用于消息加解密,可以随机生成,如果你的公众号属于“企业号”或“服务号”,建议启用加密模式。
- URL:你的Java后端服务器的公网访问地址,必须以
第三步:Java后端项目搭建(Spring Boot)
我们将使用 Spring Boot 快速搭建一个Web项目。

-
使用 Spring Initializr 创建项目
- 访问 start.spring.io
- Project: Maven Project
- Language: Java
- Spring Boot: 选择一个稳定版本(如 2.7.x 或 3.x.x)
- Project Metadata:
- Group:
com.example - Artifact:
wechat-demo - Name:
wechat-demo - Packaging: Jar
- Java: 8 或更高版本
- Group:
- Dependencies: 添加
Spring Web依赖。 - 点击 "GENERATE" 下载项目压缩包,并用你的IDE(如 IntelliJ IDEA 或 Eclipse)打开。
-
项目结构 你的项目会自动生成一个主启动类
WechatDemoApplication.java。
第四步:实现服务器配置(Token验证)
这是接入微信开发的第一步,也是最关键的一步,微信服务器会向你的 URL 发送一个 GET 请求,以验证你的服务器是合法的。
-
编写Controller 在
src/main/java/com/example/wechatdemo目录下,创建一个新的 Controller 类WeChatController.java。package com.example.wechatdemo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @RestController @RequestMapping("/wechat") public class WeChatController { // 在微信公众平台后台填写的Token private static final String TOKEN = "your_token"; @GetMapping public String verify(@RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr) { // 1. 将token、timestamp、nonce三个参数进行字典序排序 String[] arr = {TOKEN, timestamp, nonce}; Arrays.sort(arr); // 2. 将三个参数字符串拼接成一个字符串进行sha1加密 StringBuilder content = new StringBuilder(); for (String s : arr) { content.append(s); } String tmpStr = ""; try { MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToHex(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } // 3. 将sha1加密后的字符串可与signature对比 if (tmpStr != null && tmpStr.equals(signature)) { // 请求来自微信,原样返回echostr参数内容 return echostr; } else { // 请求来自非微信,验证失败 return "error"; } } /** * 字节数组转十六进制字符串 */ private static String byteToHex(byte[] bytes) { char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; char[] chars = new char[bytes.length * 2]; int k = 0; for (byte b : bytes) { chars[k++] = hexDigits[b >>> 4 & 0xf]; chars[k++] = hexDigits[b & 0xf]; } return new String(chars); } } -
配置运行参数
-
如果你使用 IDE:在
Run/Debug Configuration中,为WechatDemoApplication设置以下 VM options:-Dserver.port=80微信服务器配置要求使用80端口。
-
如果你使用打包部署:在
application.properties或application.yml中配置端口为80。server.port=80
-
-
启动项目并进行验证
- 运行
WechatDemoApplication。 - 在你的浏览器中访问
http://你的服务器IP地址/wechat,应该会看到错误信息 "error",这是正常的,因为缺少了微信验证所需的参数。 - 回到微信公众平台后台,填写服务器配置信息:
- URL:
http://你的域名或IP/wechat(http://123.456.789.101/wechat) - Token:
your_token(与代码中填写的完全一致) - EncodingAESKey: 随机生成或填写
- URL:
- 点击 “提交”,如果一切配置正确,会提示“成功”。
- 运行
第五步:核心功能:接收与回复用户消息
当用户与你的公众号互动时(如发送文本、点击菜单、关注公众号),微信服务器会向你的 URL 发送一个 POST 请求,我们需要解析这个请求,并根据业务逻辑回复消息。
-
消息接收与回复原理
- 接收:微信服务器将用户消息打包成 XML 格式,通过
POST请求发送到你的服务器。 - 回复:你的服务器处理完消息后,需要返回一个同样格式的 XML 响应给微信服务器,微信服务器再将这个响应转发给用户。
- 接收:微信服务器将用户消息打包成 XML 格式,通过
-
添加依赖 为了方便解析和生成XML,我们添加
Jackson依赖(Spring Boot Web 默认包含)和dom4j。在
pom.xml中添加:<dependency> <groupId>org.dom4j</groupId> <artifactId>dom4j</artifactId> <version>2.1.3</version> </dependency> -
创建消息处理类 创建一个
MessageHandler类来专门处理接收到的消息。package com.example.wechatdemo; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; @Component public class MessageHandler { public String handle(HttpServletRequest request) { try (InputStream is = request.getInputStream()) { SAXReader reader = new SAXReader(); Document document = reader.read(is); Element root = document.getRootElement(); // 获取消息类型 String msgType = root.element("MsgType").getTextTrim(); switch (msgType) { case "text": return handleTextMessage(root); case "event": return handleEventMessage(root); default: // 其他类型的消息暂不处理 return ""; } } catch (Exception e) { e.printStackTrace(); return ""; } } private String handleTextMessage(Element root) { // 获取用户发送的文本内容 String content = root.element("Content").getTextTrim(); // 获取发送者OpenID String fromUser = root.element("FromUserName").getTextTrim(); // 获取接收者公众号的OpenID String toUser = root.element("ToUserName").getTextTrim(); // 构造回复文本消息 String replyContent = "你发送的是: " + content; return buildTextMessage(toUser, fromUser, replyContent); } private String handleEventMessage(Element root) { String eventType = root.element("Event").getTextTrim(); String fromUser = root.element("FromUserName").getTextTrim(); String toUser = root.element("ToUserName").getTextTrim(); if ("subscribe".equals(eventType)) { // 用户关注事件 return buildTextMessage(toUser, fromUser, "感谢关注!欢迎来到我们的公众号!"); } else if ("unsubscribe".equals(eventType)) { // 用户取消关注事件 // 这里可以做一些清理工作,比如从数据库删除用户信息 System.out.println("用户 " + fromUser + " 取消关注了"); } // 其他事件(如点击菜单CLICK)可以在这里处理 return ""; } /** * 构造回复文本消息的XML */ private String buildTextMessage(String toUser, String fromUser, String content) { return "<xml>" + "<ToUserName><![CDATA[" + toUser + "]]></ToUserName>" + "<FromUserName><![CDATA[" + fromUser + "]]></FromUserName>" + "<CreateTime>" + System.currentTimeMillis() / 1000 + "</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[" + content + "]]></Content>" + "</xml>"; } } -
修改Controller以处理POST请求 修改
WeChatController,增加一个POST方法来处理消息。// ... (之前的GET方法保持不变) import org.springframework.web.bind.annotation.PostMapping; // ... 其他import @RestController @RequestMapping("/wechat") public class WeChatController { // ... TOKEN常量 @Autowired private MessageHandler messageHandler; // ... GET方法用于验证 @PostMapping public String handlePost(HttpServletRequest request) { // 将消息处理逻辑委托给MessageHandler return messageHandler.handle(request); } } -
测试
- 重新启动你的Spring Boot应用。
- 用你的个人微信关注这个公众号。
- 给公众号发送任意文本消息,你应该会收到 "你发送的是: [你发送的内容]" 的回复。
- 取消关注后再关注,应该会收到 "感谢关注!" 的消息。
第六步:高级API开发
现在你已经掌握了基础消息交互,让我们来调用一些高级API,这需要用到之前获取的 AppID 和 AppSecret。
1 网页授权获取用户信息
当用户通过公众号菜单或消息中的链接访问你的网页时,你可以通过网页授权获取用户的 OpenID 和基本信息。
-
实现一个获取Access Token的工具类
package com.example.wechatdemo.utils; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.stereotype.Component; import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; @Component public class WeChatApiUtil { private static final String APPID = "your_appid"; private static final String APPSECRET = "your_appsecret"; private static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APPID + "&secret=" + APPSECRET; private static final String GET_USERINFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN"; // 获取Access Token (注意:有2小时有效期,建议缓存) public String getAccessToken() throws IOException, InterruptedException { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(GET_ACCESS_TOKEN_URL)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); ObjectMapper mapper = new ObjectMapper(); JsonNode node = mapper.readTree(response.body()); return node.get("access_token").asText(); } // 通过网页授权Code获取OpenID和Access Token public JsonNode getSnsAccessToken(String code) throws IOException, InterruptedException { String url = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", APPID, APPSECRET, code); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); return new ObjectMapper().readTree(response.body()); } // 获取用户信息 public JsonNode getUserInfo(String openId, String accessToken) throws IOException, InterruptedException { String url = String.format(GET_USERINFO_URL, accessToken, openId); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); return new ObjectMapper().readTree(response.body()); } } -
配置网页授权
- 在微信公众平台后台,进入 “开发” -> “接口权限” -> “网页授权获取用户基本信息”。
- 点击 “修改”,将你的回调域名填入,你的网页地址是
http://yourdomain.com/callback,那么就填yourdomain.com(不要带协议和路径)。
-
实现OAuth2授权流程
- 在你的Controller中添加一个方法来处理回调。
// 在 WeChatController 中添加 @Autowired private WeChatApiUtil weChatApiUtil; @GetMapping("/oauth/callback") public String oauthCallback(@RequestParam("code") String code) throws IOException, InterruptedException { // 1. 通过code获取access_token和openid JsonNode snsTokenNode = weChatApiUtil.getSnsAccessToken(code); String openId = snsTokenNode.get("openid").asText(); String accessToken = snsTokenNode.get("access_token").asText(); // 2. 使用access_token和openid获取用户信息 JsonNode userInfoNode = weChatApiUtil.getUserInfo(openId, accessToken); String nickname = userInfoNode.get("nickname").asText(); String headImgUrl = userInfoNode.get("headimgurl").asText(); // 3. 在这里可以将用户信息存入数据库或进行其他业务处理 System.out.println("获取到用户信息: " + userInfoNode.toString()); return "欢迎, " + nickname + "!"; } -
生成授权链接 当用户需要授权时,构造如下链接并发送给用户(通常在菜单项或H5页面中):
https://open.weixin.qq.com/connect/oauth2/authorize?appid=YOUR_APPID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirectYOUR_APPID: 你的AppIDYOUR_REDIRECT_URI: 你的回调地址,如http://yourdomain.com/wechat/oauth/callback(必须与后台配置的域名一致)scope:snsapi_userinfo表示弹出授权页面,获取用户信息;snsapi_base表示静默授权,只获取OpenID。
2 发送模板消息
模板消息用于向用户发送重要的服务通知,如订单确认、物流更新等。
-
配置模板
- 在微信公众平台后台,进入 “模板消息”,选择一个合适的行业模板,并添加到你的账号中,你会得到一个 模板ID。
-
实现发送模板消息的工具方法 在
WeChatApiUtil中添加一个方法:// 在 WeChatApiUtil 中添加 private static final String SEND_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s"; public void sendTemplateMessage(String accessToken, String openId, String templateId, String url, Map<String, TemplateData> data) throws IOException, InterruptedException { // 构造请求体JSON Map<String, Object> requestBody = new HashMap<>(); requestBody.put("touser", openId); requestBody.put("template_id", templateId); requestBody.put("url", url); requestBody.put("data", data); ObjectMapper mapper = new ObjectMapper(); String jsonBody = mapper.writeValueAsString(requestBody); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(String.format(SEND_TEMPLATE_URL, accessToken))) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(jsonBody)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("发送模板消息响应: " + response.body()); } // 定义一个内部类来表示模板数据项 public static class TemplateData { private String value; private String color; public TemplateData(String value, String color) { this.value = value; this.color = color; } // Getters and Setters public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } -
调用发送方法 在你的业务逻辑中(比如用户下单后),调用这个方法:
// 在某个Service或Controller中 @Autowired private WeChatApiUtil weChatApiUtil; public void onOrderPlaced(String openId) { try { String accessToken = weChatApiUtil.getAccessToken(); // 获取全局access_token String templateId = "your_template_id"; // 你的模板ID String url = "http://yourdomain.com/order/123"; // 点击消息后跳转的链接 Map<String, TemplateData> data = new HashMap<>(); data.put("first", new TemplateData("您有新的订单待处理!", "#173177")); data.put("keyword1", new TemplateData("202510270001", "#173177")); data.put("keyword2", new TemplateData("¥99.00", "#173177")); data.put("remark", new TemplateData("请尽快处理,谢谢!", "#173177")); weChatApiUtil.sendTemplateMessage(accessToken, openId, templateId, url, data); } catch (Exception e) { e.printStackTrace(); } }
第七步:部署上线
开发完成后,你需要将你的应用部署到公网服务器上。
-
打包项目:在项目根目录执行
mvn clean package,会生成一个.jar文件。 -
上传JAR包:将生成的
.jar文件上传到你的云服务器。 -
运行应用:
- 确保服务器已安装 JDK。
- 使用
nohup命令让程序在后台运行,并将日志输出到文件:nohup java -jar wechat-demo.jar > wechat.log 2>&1 &
-
配置Nginx (可选但推荐):
-
使用 Nginx 作为反向代理,可以处理80/443端口,并提供HTTPS(需要SSL证书)。
-
Nginx 配置示例:
server { listen 80; server_name yourdomain.com; location /wechat { proxy_pass http://127.0.0.1:80; # 假设你的Spring Boot应用监听在80端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
-
总结与进阶
恭喜!你已经完成了微信公众平台Java开发的核心部分。
- 我们学习了如何搭建Spring Boot项目、如何接入微信服务器、如何处理用户消息,以及如何调用网页授权和模板消息等高级API。
- 进阶方向:
- 微信支付:集成微信支付,实现扫码支付、JSAPI支付等。
- JS-SDK:在网页中调用微信原生能力,如拍照、选图、分享、地理位置等。
- 多公众号管理:设计一套系统来管理多个公众号。
- 更完善的架构:使用消息队列(如RabbitMQ)来解耦消息处理,使用缓存(如Redis)来存储Access Token。
- 代码优化:使用更优雅的XML处理库(如JAXB),或者将消息处理逻辑模块化。
这份教程为你打下了坚实的基础,希望你在微信开发的路上越走越远!
