微信公众号完成自动回复,自定义菜单

微信公众号完成自动回复,自定义菜单

  • 首先要获取到微信公众号的开发者权限,这一步省略,可以自行百度

  • 微信公众号对接自己的服务器

 首先第一步需要有自己的服务器和固定的ip,

其中,80/443端口需要有其中一个,

80端口对应http服务,

443端口对应https服务。

然后需要在自己的服务器上编写服务端代码,对应微信公众号的token和秘钥,在微信公众号上填写相应地址,调试通过后对接完成。

对接完成后,用户向龚总好发送的消息会被转发至服务端,你可以根据用户发送的消息做对应的处理

具体操作流程如下:

点击基本服务,然后点击修改配置。

填写自己的服务端地址和接口,填写对应的token和秘钥,服务端必须和客户端保持一致,然后点击提交,成功的话页面会有提示,然后返回上一层页面点击启用即可。

需要注意的是,启用后我们之前在公众号上的菜单将会失效,需要我们用api的方式重新提交一次,所以说,有做过菜单的需要注意,下面是创建菜单的步骤

首先我们需要通过接口获取token

   /*
获取token
 */
    @RequestMapping("/getToken")
    public String getToken() {

        String appId = "xxxxxxxxx"; // 替换为你的AppID
        String appSecret = "xxxxxxxx"; // 替换为你的AppSecret

        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;

        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);

        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                JSONObject jsonObject = new JSONObject(result);

                // 提取access_token
                String accessToken = jsonObject.getString("access_token");
                token = accessToken;

                // 输出access_token
                System.out.println("Access Token: " + accessToken);
                // 在这里你可以解析返回的JSON字符串以获取access_token
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        return null;

    }

然后获取之前的菜单的结构json,有菜单的在此之前请不要启用服务器配置

/*
获取自定义菜单
 */
@RequestMapping("/getMenu")
public String getMenu() {

    String token = "xxxxxxxxxxxxxxxxxxx"; // 替换为你的AppSecret

    String url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=" + token;

    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpGet httpGet = new HttpGet(url);

    try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            String result = EntityUtils.toString(entity, "UTF-8");
            JSONObject jsonObject = new JSONObject(result);

            // 提取access_token


            // 输出access_token
            System.out.println("menu: " + jsonObject);
            // 在这里你可以解析返回的JSON字符串以获取access_token
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            httpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return null;
}

通过此程序你可以获取自己的菜单结构,如下所示

{ 

   "is_menu_open": 1, 

   "selfmenu_info": { 

       "button": [ 

           { 

               "type": "click", 

               "name": "今日歌曲", 

               "key": "V1001_TODAY_MUSIC"

           }, 

           { 

               "name": "菜单", 

               "sub_button": { 

                   "list": [ 

                       { 

                           "type": "view", 

                           "name": "搜索", 

                           "url": "http://www.soso.com/"

                       }, 

                       { 

                           "type": "view", 

                           "name": "视频", 

                           "url": "http://v.qq.com/"

                       }, 

                       { 

                           "type": "click", 

                           "name": "赞一下我们", 

                           "key": "V1001_GOOD"

                       }

                   ]

               }

           }

       ]

   }}

然后你只需将此json通过创建接口重新创建即可,我这里都用的java。需要在启用服务器后进行配置

 String url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + token;

    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost(url);

    // 设置请求体参数为您提供的 JSON 数据
    String jsonBody = 你的菜单结构


    StringEntity requestEntity = new StringEntity(jsonBody, ContentType.APPLICATION_JSON);
    httpPost.setEntity(requestEntity);

    // 设置请求头 Content-Type 为 application/json
    httpPost.setHeader("Content-Type", "application/json");

    try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            String result = EntityUtils.toString(entity, "UTF-8");
            JSONObject jsonObject = new JSONObject(result);

            // 提取access_token

            // 输出access_token
            System.out.println("menu: " + jsonObject);
            // 在这里您可以解析返回的JSON字符串以获取access_token
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            httpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

然后就是自动回复,我们要编写代码接收到用户向公众号发送的消息,然后返回我们想要回复的消息即可:此接口必须是你对接微信服务器所填写的接口,否则无法接收:如下

    @RequestMapping("/wx")
    public @ResponseBody
    String wxGZHGetMsg(HttpServletRequest request) {
        System.out.println(request.toString());
        try {
            // 获取请求体内容
            String xmlContent = getRequestBody(request);

            // 使用 Jsoup 解析 XML 内容
            Document document = Jsoup.parse(xmlContent, "", org.jsoup.parser.Parser.xmlParser());

            // 修改 XML 内容
//            modifyXmlimg(document);
            Elements eventElements = document.select("Event");
            if (!eventElements.isEmpty()) {
                String s = modifuxmlMenu(document);

                return s;

            } else {


                return modifyXmlContent(document);
            }


            // 将修改后的 XML 内容转换为字符串

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

    private String getRequestBody(HttpServletRequest request) throws IOException {// 获取请求体内容
        StringBuilder requestBody = new StringBuilder();
        try (BufferedReader reader = request.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                requestBody.append(line);
            }
        }
        return requestBody.toString();
    }

由于微信发送的信息室xml格式的,所以我们需要进行一定的处理,我这里使用的是jsonp包所带的方法进行处理的,使用jsonp需要在

Pom文件中引入相关的依赖,如下

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.14.3</version>
</dependency>

此外,这里回复处理xml文件的过程需要大家自己根据情况进行编写,可以配合数据库进行相应的逻辑回答,这里给出xml文件的格式,微信文档中也可以查看到

这是接收到的

<xml>

  <ToUserName><![CDATA[toUser]]></ToUserName>

  <FromUserName><![CDATA[fromUser]]></FromUserName>

  <CreateTime>1348831860</CreateTime>

  <MsgType><![CDATA[text]]></MsgType>

  <Content><![CDATA[this is a test]]></Content>

  <MsgId>1234567890123456</MsgId>

  <MsgDataId>xxxx</MsgDataId>

  <Idx>xxxx</Idx></xml>

回复的话也基本相同,

回复文本消息

<xml>

  <ToUserName><![CDATA[toUser]]></ToUserName>

  <FromUserName><![CDATA[fromUser]]></FromUserName>

  <CreateTime>12345678</CreateTime>

  <MsgType><![CDATA[text]]></MsgType>

  <Content><![CDATA[你好]]></Content></xml>

回复图片消息

<xml>

  <ToUserName><![CDATA[toUser]]></ToUserName>

  <FromUserName><![CDATA[fromUser]]></FromUserName>

  <CreateTime>12345678</CreateTime>

  <MsgType><![CDATA[image]]></MsgType>

  <Image>

    <MediaId><![CDATA[media_id]]></MediaId>

  </Image></xml>

这里需要注意的是,回复消息的时候需要把ToUserNameFromUserName

的value值进行互换,具体过程大家可以自行根据需求编写。

此外,为了区分不同用户的提问状态,我这里使用了Redis进行保存用户提问数据的操作,并且设置1小时超时 ,在用户提问的时候,把用户的id存入Redis,由此可以分辨出每一位用户的问题,做出相对应的回答。

Redis可从网上自行下载安装,在java中使用可以通过pom文件引入

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

然后编写配置类

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        // 使用GenericJackson2JsonRedisSerializer来序列化和反序列化redis的value值
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}

这里我们通过 bean的方式注入,可以通过@Autowired注入的方式在程序中进行调用,Redis在springboot中的调用方式非常简单,可以使用sava ,find,delete 方式进行存储和删除修改

这里的sava方式我进行了保存时间的设定,timeou是时间参数,

TimeUnit 是时间单位(时/分/秒/毫秒),最小单位为毫秒,超时后会自动删除数据。

public class RedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void save(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    public Object find(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    public void delete(String key) {
        redisTemplate.delete(key);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/651425.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

按尺寸筛选轮廓图中的轮廓

1.按短边筛选 原始轮廓图&#xff1a; import cv2 import numpy as np# 读取轮廓图 contour_image cv2.imread(..\\IMGS\\pp_edge.png, cv2.IMREAD_GRAYSCALE)# 使用cv2.findContours()函数获取所有轮廓 contours, _ cv2.findContours(contour_image, cv2.RETR_EXTERNAL, cv2…

据阿谱尔APO Research调研显示,2023年全球绝缘栅双极晶体管(IGBT)市场销售额约为89.9亿美元

根据阿谱尔 (APO Research&#xff09;的统计及预测&#xff0c;2023年全球绝缘栅双极晶体管&#xff08;IGBT&#xff09;市场销售额约为89.9亿美元&#xff0c;预计在2024-2030年预测期内将以超过14.7%的CAGR&#xff08;年复合增长率&#xff09;增长。 由于各行业对电力电子…

XSKY CTO 在英特尔存储技术峰会的演讲:LLM 存储,架构至关重要

5 月 17 日&#xff0c;英特尔存储技术峰会在北京顺利举办。作为英特尔长期的合作伙伴&#xff0c;星辰天合受邀参加了此次峰会。星辰天合 CTO 王豪迈作为特邀嘉宾之一&#xff0c;作了主题为《LLM 存储&#xff1a;架构至关重要》的演讲&#xff0c;分享了大语言模型&#xff…

jmeter发送webserver请求和上传请求

有时候在项目中会遇到webserver接口和上传接口的请求&#xff0c;大致参考如下 一、发送webserver请求 先获取登录接口的token&#xff0c;再使用cookie管理器进行关联获取商品(webserver接口)&#xff0c;注意参数一般是写在消息体数据中&#xff0c;消息体有点像HTML格式 执…

Java整合EasyExcel实战——2 导出复杂表头

详情代码 实体类 Data public class ComplexHeadData {ExcelProperty({"主标题", "字符串标题"})private String string;ExcelProperty({"主标题", "日期标题"})private Date date;ExcelProperty({"主标题", "数字标…

(2024,DDDM,ODE,少量步生成,迭代生成)直接去噪扩散模型

Directly Denoising Diffusion Model 公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 3. 直接去噪扩散模型 3.1. 迭代求解 4. Psuedo-LPIPS 指标 5. 实验 7. 讨论和局限性 0. 摘…

大模型时代的具身智能系列专题(二)

李飞飞团队 李飞飞是华人在AI领域最具影响力的学者之一&#xff0c;她是斯坦福大学人工智能实验室&#xff08;SAIL&#xff09;教授&#xff0c;美国国家工程院院士&#xff0c;知名CV数据集ImageNet的牵头人&#xff0c;斯坦福视觉与学习实验室&#xff08;SVL&#xff09;的…

2024.05.27学习记录

1、面经复习&#xff1a; 实际工作经验章节 2、代码随想录刷题&#xff1a;动态规划剩下部分和单调栈 3、rosebush 组件库完成Input 和 AutoComplete部分内容

长难句打卡5.27

In fact, allowing non-lawyers to own shares in law firms would reduce costs and improve services to customers, by encouraging law firms to use technology and to employ professional managers to focus on improving firms’efficiency. 事实上&#xff0c;这通过…

can设备调试 - linux driver

这篇文章主要介绍can设备的调试相关信息&#xff0c;不具体介绍驱动的实现。 如果驱动写完&#xff0c;对can设备进行验证&#xff0c;可能会出现很多不可预见的问题。下面说说验证步骤 验证can设备可以使用工具can-utils。这个工具包中会有cansend candump等程序。可以直接通…

视频监控技术前沿探索:智能化趋势与EasyCVR视频汇聚技术应用

在数字化时代的浪潮中&#xff0c;视频监控技术以其独特的优势&#xff0c;正在安防领域书写着新的篇章。它不仅为公共安全部门提供了强大的技术支持&#xff0c;还深入到教育、政府、娱乐、医疗、酒店、运动等多个领域&#xff0c;成为维护社会秩序、保障人民安全的重要工具。…

python爬虫学习(2)——requests模块

520那天我向心仪的女孩要微信&#xff1a;“女神&#xff0c;能给我你的微信号吗&#xff1f;” 女神&#xff1a;“给我——爬&#xff01;&#xff01;&#xff01;&#xff01;” 从那天开始&#xff0c;我就决定要学好爬虫&#xff0c;爬到女神微信号&#xff01;&#xff…

分布式锁的原理和实现(Go)

文章目录 为什么需要分布式锁&#xff1f;go语言分布式锁的实现Redis自己的实现红锁是什么别人的带红锁的实现 etcdzk的实现 面试问题什么是分布式锁&#xff1f;你用过分布式锁吗&#xff1f;你使用的分布式锁性能如何&#xff0c;可以优化吗&#xff1f;怎么用Redis来实现一个…

CHI Read传输——CHI(3)

目录 一、Read操作概览 二、DMT(Direct Memory Transfer) 三、DCT (Direct Cache Transfer) 四、without Direct Data Transfer 五、ReadNoSnp and ReadOnce* structure with DMT 本篇我们来介绍一下CHI传输类型中的Read 一、Read操作概览 read操作有以下几种&#xff1…

详解CSS(二)

目录 1.背景属性 1.1背景颜色 1.2背景图片 1.3背景平铺 1.4背景位置 1.5背景尺寸 2.圆角矩形 3.元素的显示模式 3.1行内元素/内联元素&#xff08;Inline element&#xff09; 3.2块级元素&#xff08;Block-level element&#xff09; 3.3行内块元素&#xff08;In…

css-垂直居中的几种写法

图示 1、使用line-height属性&#xff08;当div有固定高度时&#xff09; 2、使用flexbox布局

AGV与智能仓储的应用案例

背景介绍 该企业的智能工厂专注于高端家用电器的生产与研发&#xff0c;包括电子坐便盖、电子坐便器、吸尘器、洗碗机等&#xff0c;覆盖8条关键产线。面对日益增长的市场需求和生产节奏的加快&#xff0c;传统的物流方式已无法满足高效、精准的生产要求。为此&#xff0c;企业…

报名倒计时!「飞天技术沙龙-CentOS 迁移替换专场」参会指南

为帮助广大用户诊断 CentOS 迁移替换过程中的疑难杂症&#xff0c;「飞天技术沙龙-CentOS 迁移替换专场」将于 5 月 29 日&#xff08;周三&#xff09;在北京举办&#xff0c;将围绕如何在确保服务的连续性和稳定性的前提下实现平滑迁移及如何最大限度地利用现有资源前提下确保…

【LeetCode】【9】回文数(1047字)

文章目录 [toc]题目描述样例输入输出与解释样例1样例2样例3 提示进阶Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;LeetCode 刷题指南&#xff1a;LeetCode刷题指南 题目描述 给一个整数x&#xff0c;如果x是一个回文整数&#xff0c;返回true&#xff1b;否…

春秋云境CVE-2018-7422

简介 WordPress Plugin Site Editor LFI 正文 1.进入靶场 2.漏洞利用 /wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path/../../../../../../flag看别人wp做的。不懂怎么弄的&#xff0c;有没有大佬讲一下的