微信服务平台接口开发实战:自定义菜单、自动回复功能实现(Java 版)

微信公众号服务平台的自定义菜单、关注自动回复、关键词回复是提升用户交互体验的核心功能。本文将基于 Java 语言,结合微信官方接口规范,完整实现这三类功能的接口开发,并通过可运行的案例代码,讲解从环境准备到功能落地的全流程。

一、开发前准备

1.1 核心依赖

本次开发基于 Spring Boot 框架,需引入以下核心依赖(pom.xml):

<dependencies>
    <!-- Spring Boot核心依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- HTTP请求工具 -->
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.10.0</version>
    </dependency>
    <!-- JSON解析工具 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>2.0.25</version>
    </dependency>
    <!-- 加解密工具(微信消息验签) -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.15</version>
    </dependency>
</dependencies>

1.2 微信公众号配置

  1. 登录微信公众平台(服务号 / 订阅号),进入「开发 - 基本配置」:
    • 获取AppIDAppSecret
    • 配置服务器 IP 白名单(接口调用需校验);
    • 配置服务器地址(URL)、令牌(Token)、EncodingAESKey(消息加解密用)。
  2. 权限确认:确保公众号已开通「自定义菜单」「自动回复」接口权限(服务号默认开通,订阅号需认证)。

1.3 核心常量定义

创建WeChatConstant类,统一管理微信接口地址和配置:

public class WeChatConstant {
    // 获取access_token接口
    public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    // 自定义菜单创建接口
    public static final String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s";
    // 自动回复规则创建接口(关注回复/关键词回复)
    public static final String AUTO_REPLY_SET_URL = "https://api.weixin.qq.com/cgi-bin/reply/set_autoreply_info?access_token=%s";
    // 公众号AppID(替换为自己的)
    public static final String APP_ID = "your_appid";
    // 公众号AppSecret(替换为自己的)
    public static final String APP_SECRET = "your_appsecret";
}

二、核心工具类开发

2.1 AccessToken 获取工具

微信接口调用需先获取access_token(有效期 2 小时,需缓存),创建WeChatTokenUtil

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class WeChatTokenUtil {
    private static OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .build();
    
    // 缓存access_token,实际项目建议用Redis
    private static String accessToken;
    private static long expireTime;

    /**
     * 获取有效的access_token
     */
    public static String getAccessToken() throws IOException {
        // 检查token是否过期
        if (accessToken == null || System.currentTimeMillis() > expireTime) {
            String url = String.format(WeChatConstant.ACCESS_TOKEN_URL, 
                    WeChatConstant.APP_ID, WeChatConstant.APP_SECRET);
            Request request = new Request.Builder().url(url).get().build();
            try (Response response = client.newCall(request).execute()) {
                String respJson = response.body().string();
                JSONObject json = JSONObject.parseObject(respJson);
                accessToken = json.getString("access_token");
                // 过期时间提前10秒,避免网络延迟导致失效
                expireTime = System.currentTimeMillis() + (json.getInteger("expires_in") - 10) * 1000;
            }
        }
        return accessToken;
    }
}

2.2 HTTP 请求工具

创建WeChatHttpUtil,封装 POST 请求(接口调用主要用 POST):

import okhttp3.MediaType;
import okhttp3.RequestBody;
import java.io.IOException;

public class WeChatHttpUtil {
    private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
    private static OkHttpClient client = new OkHttpClient();

    /**
     * 发送POST请求(JSON参数)
     */
    public static String post(String url, String json) throws IOException {
        RequestBody body = RequestBody.create(json, JSON);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }
}

三、功能实现

3.1 自定义菜单实现

3.1.1 菜单数据结构设计

微信自定义菜单支持「点击推事件」「跳转 URL」等类型,本次案例创建包含 2 个一级菜单、1 个二级菜单的结构:

import com.alibaba.fastjson.JSONObject;

public class WeChatMenuService {
    /**
     * 创建自定义菜单
     */
    public String createMenu() throws IOException {
        // 1. 构建菜单JSON
        JSONObject menuJson = new JSONObject();
        JSONObject buttonJson = new JSONObject();
        
        // 一级菜单1:首页(跳转URL)
        JSONObject menu1 = new JSONObject();
        menu1.put("name", "官网首页");
        menu1.put("type", "view");
        menu1.put("url", "https://www.example.com");
        
        // 一级菜单2:我的服务(包含二级菜单)
        JSONObject menu2 = new JSONObject();
        menu2.put("name", "我的服务");
        JSONObject subButton = new JSONObject();
        
        // 二级菜单1:个人中心(点击事件)
        JSONObject subMenu1 = new JSONObject();
        subMenu1.put("name", "个人中心");
        subMenu1.put("type", "click");
        subMenu1.put("key", "USER_CENTER");
        
        // 二级菜单2:帮助中心(跳转URL)
        JSONObject subMenu2 = new JSONObject();
        subMenu2.put("name", "帮助中心");
        subMenu2.put("type", "view");
        subMenu2.put("url", "https://www.example.com/help");
        
        subButton.put("sub_button", new JSONObject[]{subMenu1, subMenu2});
        menu2.put("sub_button", subButton.getJSONArray("sub_button"));
        
        buttonJson.put("button", new JSONObject[]{menu1, menu2});
        menuJson.put("button", buttonJson.getJSONArray("button"));
        
        // 2. 获取access_token,拼接接口URL
        String accessToken = WeChatTokenUtil.getAccessToken();
        String url = String.format(WeChatConstant.MENU_CREATE_URL, accessToken);
        
        // 3. 调用接口
        return WeChatHttpUtil.post(url, menuJson.toJSONString());
    }
}

3.2 关注自动回复实现

关注自动回复是用户首次关注公众号时触发的回复,支持「文本」「图片」「图文」等类型,本次实现文本回复:

public class WeChatAutoReplyService {
    /**
     * 设置关注自动回复
     */
    public String setSubscribeReply() throws IOException {
        // 1. 构建回复规则JSON
        JSONObject replyJson = new JSONObject();
        
        // 关注回复配置
        JSONObject subscribeReply = new JSONObject();
        subscribeReply.put("type", "text"); // 回复类型:文本
        JSONObject textContent = new JSONObject();
        textContent.put("content", "欢迎关注XXX公众号!回复【帮助】查看使用指南,回复【客服】联系人工~");
        subscribeReply.put("text", textContent);
        
        replyJson.put("subscribe_autoreply_info", subscribeReply);
        
        // 2. 获取access_token,拼接接口URL
        String accessToken = WeChatTokenUtil.getAccessToken();
        String url = String.format(WeChatConstant.AUTO_REPLY_SET_URL, accessToken);
        
        // 3. 调用接口
        return WeChatHttpUtil.post(url, replyJson.toJSONString());
    }
}

3.3 关键词回复实现

关键词回复支持「精确匹配」「模糊匹配」,本次实现 2 个关键词规则:

  • 精确匹配「帮助」:回复使用指南;
  • 模糊匹配「客服」:回复人工客服联系方式。

注意:微信关键词回复接口(set_autoreply_info)需同时传入关注回复和关键词回复,因此需整合配置:

public class WeChatKeywordReplyService {
    /**
     * 设置关键词回复(含关注回复)
     */
    public String setKeywordReply() throws IOException {
        // 1. 构建完整回复规则JSON
        JSONObject replyJson = new JSONObject();
        
        // 1.1 关注回复(复用之前的配置)
        JSONObject subscribeReply = new JSONObject();
        subscribeReply.put("type", "text");
        JSONObject subscribeText = new JSONObject();
        subscribeText.put("content", "欢迎关注XXX公众号!回复【帮助】查看使用指南,回复【客服】联系人工~");
        subscribeReply.put("text", subscribeText);
        replyJson.put("subscribe_autoreply_info", subscribeReply);
        
        // 1.2 关键词回复配置
        JSONObject keywordReply = new JSONObject();
        keywordReply.put("is_add_rule", true); // 新增规则(false为覆盖)
        
        // 规则1:精确匹配「帮助」
        JSONObject rule1 = new JSONObject();
        rule1.put("rule_name", "帮助指南");
        rule1.put("match_mode", "exact"); // 精确匹配
        rule1.put("keyword_list_info", new JSONObject[]{
                new JSONObject().fluentPut("keyword", "帮助")
        });
        // 规则1回复内容
        JSONObject reply1 = new JSONObject();
        reply1.put("type", "text");
        JSONObject text1 = new JSONObject();
        text1.put("content", "【使用指南】\n1. 回复【我的订单】查看订单状态\n2. 回复【优惠券】领取新人福利\n3. 回复【客服】联系人工");
        reply1.put("text", text1);
        rule1.put("reply_list_info", new JSONObject[]{reply1});
        
        // 规则2:模糊匹配「客服」
        JSONObject rule2 = new JSONObject();
        rule2.put("rule_name", "客服联系");
        rule2.put("match_mode", "contain"); // 模糊匹配
        rule2.put("keyword_list_info", new JSONObject[]{
                new JSONObject().fluentPut("keyword", "客服")
        });
        // 规则2回复内容
        JSONObject reply2 = new JSONObject();
        reply2.put("type", "text");
        JSONObject text2 = new JSONObject();
        text2.put("content", "人工客服联系方式:\n电话:400-XXXX-XXXX\n工作时间:9:00-18:00");
        reply2.put("text", text2);
        rule2.put("reply_list_info", new JSONObject[]{reply2});
        
        keywordReply.put("keyword_autoreply_info", new JSONObject(){
            {
                put("list", new JSONObject[]{rule1, rule2});
            }
        });
        replyJson.put("keyword_autoreply_info", keywordReply.getJSONObject("keyword_autoreply_info"));
        
        // 2. 获取access_token,拼接接口URL
        String accessToken = WeChatTokenUtil.getAccessToken();
        String url = String.format(WeChatConstant.AUTO_REPLY_SET_URL, accessToken);
        
        // 3. 调用接口
        return WeChatHttpUtil.post(url, replyJson.toJSONString());
    }
}

四、接口调用与测试

4.1 编写 Controller

创建WeChatController,对外提供调用入口:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;

@RestController
public class WeChatController {
    private final WeChatMenuService menuService = new WeChatMenuService();
    private final WeChatAutoReplyService autoReplyService = new WeChatAutoReplyService();
    private final WeChatKeywordReplyService keywordReplyService = new WeChatKeywordReplyService();

    /**
     * 创建自定义菜单
     */
    @GetMapping("/wechat/createMenu")
    public String createMenu() {
        try {
            return menuService.createMenu();
        } catch (IOException e) {
            return "创建菜单失败:" + e.getMessage();
        }
    }

    /**
     * 设置关注自动回复
     */
    @GetMapping("/wechat/setSubscribeReply")
    public String setSubscribeReply() {
        try {
            return autoReplyService.setSubscribeReply();
        } catch (IOException e) {
            return "设置关注回复失败:" + e.getMessage();
        }
    }

    /**
     * 设置关键词回复
     */
    @GetMapping("/wechat/setKeywordReply")
    public String setKeywordReply() {
        try {
            return keywordReplyService.setKeywordReply();
        } catch (IOException e) {
            return "设置关键词回复失败:" + e.getMessage();
        }
    }
}

4.2 测试步骤

  1. 替换WeChatConstant中的APP_IDAPP_SECRET为自己的公众号信息;
  2. 启动 Spring Boot 项目,访问以下接口:
    • 创建菜单:http://localhost:8080/wechat/createMenu
    • 设置关注回复:http://localhost:8080/wechat/setSubscribeReply
    • 设置关键词回复:http://localhost:8080/wechat/setKeywordReply
  3. 接口返回{"errcode":0,"errmsg":"ok"}表示配置成功;
  4. 关注公众号测试关注回复,发送「帮助」「客服」测试关键词回复,查看菜单栏确认菜单创建成功。

五、注意事项

  1. access_token缓存:实际项目中建议用 Redis 缓存,避免频繁调用获取接口(微信限制每天调用次数);
  2. 接口权限:订阅号未认证仅支持部分接口,服务号需确保已开通对应权限;
  3. 消息加解密:若公众号配置了「安全模式」,接收用户消息时需解密,本文仅实现主动配置接口,接收消息需额外处理;
  4. 菜单更新:自定义菜单创建后,用户需重新关注或刷新公众号才能看到最新菜单;
  5. 关键词匹配:模糊匹配(contain)会匹配包含关键词的所有消息,需避免关键词冲突。

六、总结

本文通过 Java+Spring Boot 实现了微信服务平台自定义菜单、关注自动回复、关键词回复的核心接口开发。核心思路是:先获取有效的access_token,再按照微信接口规范构建 JSON 参数,通过 POST 请求调用对应接口。实际项目中,可在此基础上扩展图片 / 图文回复、菜单删除 / 查询、回复规则查询等功能,同时需做好异常处理、日志记录和接口限流,确保系统稳定运行。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canjun_wen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值