微信公众号自定义菜单设置【API方式】

前言

官方文档

微信公众平台: 传送门
公众号官方文档: 传送门

基础设置

查看权限

  • 点击微信公众号平台的传送门: 使用公众号登录
    :进来就是这样的
    在这里插入图片描述
  • 设置与开发 -> 接口权限 -> 对话服务 -> 界面丰富
    在这里插入图片描述
    先看看公众号是否有接口权限 没有权限 先去申请

开发设置

设置与开发 -> 基本配置
在这里插入图片描述

  • 配置开发需要的东西
    在这里插入图片描述

相关文档

  • 点击公众号官方文档的传送门在这里插入图片描述

自定义菜单文档

在这里插入图片描述

处理点击事件

在这里插入图片描述
ps : 这里面有好多都可以处理菜单点击事件 你们自己看文档吧,我懒得打字了,我用的是客服消息

查询菜单配置

  • 菜单配置 和 菜单 返回不同 但是也大差不差 API配置方式和公众号后台配置的返回也不同, 注意看文档.
  • 查询菜单接口文档
import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @Author: 小新
 * @Date: 2024/1/18 15:08
 */
@Slf4j
public class OfficialAccountMenu {
    public static void main(String[] args) {
        String accessToken = getAccessToken();
        String apiUrl = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=" + accessToken; // 查询菜单
        //String apiUrl = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=" + accessToken; // 查询个性化菜单配置

        try {
            URL url = new URL(apiUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Accept", "application/json");

            int responseCode = connection.getResponseCode();
            System.out.println("Response Code : " + responseCode);

            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
            System.out.println("返回结果" + response.toString().replace("\\",""));
            JSONObject jsonObject = new JSONObject(response.toString());
            // 检查是否存在"selfmenu_info"键
            if (jsonObject.has("selfmenu_info")) {
                JSONObject selfmenuInfo = jsonObject.getJSONObject("selfmenu_info");

                // 检查是否存在"button"数组
                if (selfmenuInfo.has("button")) {
                    JSONArray button = selfmenuInfo.getJSONArray("button");
                    System.out.println("button : " + button.toString());
                } else {
                    System.out.println("button 没找到");
                }
            } else {
                System.out.println("selfmenu_info 没找到");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取accessToken
     * @return
     */
    public static String getAccessToken() {
        JSONObject requestBody = new JSONObject();
        requestBody.put("grant_type", "client_credential");
        requestBody.put("appid", "xxxxxxxxxxx");
        requestBody.put("secret", "xxxxxxxxxx");
        try {
            String response = performHttpPost("https://api.weixin.qq.com/cgi-bin/stable_token", requestBody.toString());
            JSONObject jsonObject = new JSONObject(response);
            if (jsonObject.has("access_token")) {
                log.info("access_token  返回:{}",jsonObject);
                return jsonObject.getString("access_token");
            } else {
                log.info("JSON响应中没有access_token字段");
                return "";
            }
        } catch (Exception e) {
            log.info("获取accessToken  发生异常:{}",e.getMessage());
            return "";
        }
    }

    /**
     * post求
     * @param url
     * @param requestBody
     * @return
     * @throws Exception
     */
    public static   String performHttpPost(String url, String requestBody) throws Exception {
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/json");
        con.setDoOutput(true);

        try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
            wr.writeBytes(requestBody);
            wr.flush();
        }

        int responseCode = con.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            return response.toString();
        } else {
            return "";
        }
    }
}

创建菜单

  • 菜单不支持修改 只能进行覆盖 本次配置将会覆盖上次配置
package com.farbun.fission.mapper;

import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

/**
 * @Author: 小新
 * @Date: 2024/1/18 15:08
 */
@Slf4j
public class CreateOfficialAccountMenu {
    public static void main(String[] args) {
        String accessToken = getAccessToken();
        String apiUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + accessToken; // 创建菜单

        JSONObject menuData = new JSONObject();
        // 构建子菜单
        JSONArray subButton1 = new JSONArray();
        subButton1.put(new JSONObject()
                .put("type", "view")
                .put("name", "功能视频")
                .put("url", "xxxxxxx"));

        JSONArray subButton2 = new JSONArray();
        subButton2.put(new JSONObject()
                .put("type", "view")
                .put("name", "常见问题")
                .put("url", "xxxxxxx"));

        // 构建一级菜单
        JSONObject downloadButton = new JSONObject()
                .put("type", "view")
                .put("name", "xxxxx")
                .put("url", "xxxxx"); // 跳转地址
                //.put("sub_button", new JSONArray());

        JSONObject aiButton = new JSONObject()
                //.put("type", "miniprogram")  // 小程序
                .put("type", "click")
                .put("name","xxxxx")
                .put("key","clickMiniMessage");
                //.put("name", "xxxxx")
                /*.put("name", "xxxx")
                .put("url", "xxxxx")
                .put("appid", "小程序Id")
                .put("pagepath", "小程序页面路径");*/
                //.put("sub_button", new JSONArray());

        JSONArray lectureHallSubButtons = new JSONArray();
        lectureHallSubButtons.put(subButton1.getJSONObject(0));
        lectureHallSubButtons.put(subButton2.getJSONObject(0));

        //JSONObject listJSONObject = new JSONObject();
        //listJSONObject.put("list",lectureHallSubButtons);
        JSONObject lectureHallButton = new JSONObject()
                .put("name", "xxxxx")
                .put("sub_button", lectureHallSubButtons);

        JSONArray buttons = new JSONArray();
        buttons.put(downloadButton);
        buttons.put(aiButton);
        buttons.put(lectureHallButton);

        // 设置整个菜单结构
        menuData.put("button", buttons);
        String requestBody = menuData.toString();
        System.out.println("请求参数:" + requestBody);
        try {
            String response = performHttpPost2(apiUrl, requestBody);
            System.out.println(response.toString());
        } catch (Exception e) {
            System.out.println("request error");
        }
    }

    public static String getAccessToken() {
        JSONObject requestBody = new JSONObject();
        requestBody.put("grant_type", "client_credential");
        requestBody.put("appid", "xxxxxxxxxxxxx");
        requestBody.put("secret", "xxxxxxxxxxxx");
        try {
            String response = performHttpPost("https://api.weixin.qq.com/cgi-bin/stable_token", requestBody.toString());
            JSONObject jsonObject = new JSONObject(response);
            if (jsonObject.has("access_token")) {
                log.info("access_token  返回:{}",jsonObject);
                return jsonObject.getString("access_token");
            } else {
                log.info("JSON响应中没有access_token字段");
                return "";
            }
        } catch (Exception e) {
            log.info("获取accessToken  发生异常:{}",e.getMessage());
            return "";
        }
    }

    public static   String performHttpPost(String url, String requestBody) throws Exception {
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/json");
        con.setDoOutput(true);

        try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
            wr.writeBytes(requestBody);
            wr.flush();
        }

        int responseCode = con.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            return response.toString();
        } else {
            return "";
        }
    }

    private static String performHttpPost2(String apiUrl, String requestBody) throws Exception {
        URL url = new URL(apiUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        connection.setDoOutput(true);

        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = requestBody.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }

        int code = connection.getResponseCode();
        if (code == HttpURLConnection.HTTP_OK) {
            StringBuilder response = new StringBuilder();
            try (BufferedReader br = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
                String line;
                while ((line = br.readLine()) != null) {
                    response.append(line).append("\n");
                }
                return response.toString();
            }
        } else {
            throw new RuntimeException("Failed : HTTP error code : " + code);
        }
    }
}

  • ps: 就把获取到的菜单结构改吧改吧就行 下面是官方的格式 照着改就行
 {
     "button":[
     {	
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "name":"菜单",
           "sub_button":[
           {	
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
            {
                 "type":"miniprogram",
                 "name":"wxa",
                 "url":"http://mp.weixin.qq.com",
                 "appid":"wx286b93c14bbf93aa",
                 "pagepath":"pages/lunar/index"
             },
            {
               "type":"click",
               "name":"赞一下我们",
               "key":"V1001_GOOD"
            }]
       }]
 }

菜单点击事件处理

  • 创建菜单时 type 为 click , key 的值为 自定义的
    在这里插入图片描述
  • 前言说过的回调地址 接收微信的推送数据并返回
    在这里插入图片描述
@PostMapping("callback")
    public String postCallback(HttpServletRequest request) throws Exception {
        InputStream inputStream = request.getInputStream();
        String strXML = FileUtil.getStringFromStream(inputStream);
        log.info("strXML=" + strXML);
        Map<String, String> reqMap = WXPayUtil.xmlToMap(strXML);
        log.info("ToUserName=" + reqMap.get("ToUserName") +
            ",FromUserName=" + reqMap.get("FromUserName") +
            ",CreateTime=" + reqMap.get("CreateTime") +
            ",MsgType=" + reqMap.get("MsgType") +
            ",Event=" + reqMap.get("Event") +
            ",EventKey=" + reqMap.get("EventKey") +
            ",Ticket=" + reqMap.get("Ticket"));
        if ("event".equals(reqMap.get("MsgType"))) {
            if ("CLICK".equals(reqMap.get("Event"))) { // 自定义点击事件
                log.info("自定义点击事件");
                String eventKey = reqMap.get("EventKey");
                String openId = reqMap.get("FromUserName");
                if (org.apache.commons.lang3.StringUtils.isNotBlank(eventKey) && "clickMiniMessage".equals(eventKey) ) { // key
                    new Thread(new ThreadSendKfMessage03(weChatOfficialAccountUtil, appId, appSecret, wxId, openId)).start();
                }
           }
        }
        return "";
    }
  • getStringFromStream()
public static String getStringFromStream(InputStream inputStream) throws IOException {
        if (inputStream == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();

        return sb.toString();
    }
  • WXPayUtil
package util.wechat;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author wy
 * @date 2018/7/10
 * @Description: TODO
 */
public class WXPayUtil {

    /**
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     * @Author SongZS
     * @Date 2017/6/30 14:57
     * <p>
     * XML格式字符串转换为Map
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            try {
                stream.close();
            } catch (Exception ex) {
                // do nothing
            }
            return data;
        } catch (Exception ex) {
            //     WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
            throw ex;
        }

    }

    /**
     * @param data Map类型数据
     * @return XML格式的字符串
     * @throws Exception
     * @Author SongZS
     * @Date 2017/6/30 14:57
     * <p>
     * 将Map转换为XML格式的字符串
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = documentBuilder.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key : data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
        try {
            writer.close();
        } catch (Exception ex) {
        }
        return output;
    }

}

  • ThreadSendKfMessage03 这个其实没必要给你们,看看就行 发送消息的时候 写个方法调就行
import com.alibaba.fastjson.JSONObject;
import com.farbun.module.bean.Material;
import com.farbun.module.repository.MaterialRepository;
import com.farbun.module.util.WeChatOfficialAccountUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Slf4j
public class ThreadSendKfMessage03 implements Runnable {

    private WeChatOfficialAccountUtil weChatOfficialAccountUtil;
    private String appId;
    private String appSecret;
    private String wxId;

    private String openId;


    @Autowired
    private MaterialRepository materialRepository;

    public ThreadSendKfMessage03(WeChatOfficialAccountUtil weChatOfficialAccountUtil, String appId,
                                 String appSecret, String wxId,
                                 String openId) {
        this.weChatOfficialAccountUtil = weChatOfficialAccountUtil;
        this.appId = appId;
        this.appSecret = appSecret;
        this.wxId = wxId;
        this.openId = openId;
    }

    @Override
    public void run() {
        weChatOfficialAccountUtil.customMessageSend(appId, appSecret, wxId, openId);
    }
}

  • customMessageSend
public void customMessageSend(String appId, String appSecret, String wxId, String openId) {
        JSONObject param = new JSONObject();
        param.put("touser", openId);
        param.put("msgtype", "text");
        JSONObject jsonObjectContent = new JSONObject();
        String str = "xxxxxxxxxx";
        jsonObjectContent.put("content",str);
        param.put("text", jsonObjectContent);
        StringBuilder url = new StringBuilder("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=");
        url.append(getAccessToken(appId, appSecret, wxId));
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept", "application/json");
        headers.add("Content-Encoding", "UTF-8");
        headers.add("Content-Type", "application/json; charset=UTF-8");
        HttpEntity<String> httpEntity = new HttpEntity<>(param.toJSONString(), headers);
        String result = restTemplate.postForObject(url.toString(), httpEntity, String.class);
        log.info("customMessageSendResult=" + result);
    }

ps: 写的比较潦草 hhhc 将就看吧 不明白的多看文档 bye。

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值