【公众号开发】如何写出第一个公众号开发程序 · 动态自定义自动回复

news2024/11/19 14:47:23

【公众号开发】(1)

在这里插入图片描述

文章目录

  • 【公众号开发】(1)
    • 1. 获得一个测试号
    • 2. 公众号开发原理
    • 3. 创建开发者服务器
    • 4. 内网穿透
    • 5. 验证开发者服务器的url
      • 5.1 公众号服务器对url发送get请求
      • 5.2 消息的验证逻辑
      • 5.3 代码实现
    • 6. 接受并解析用户发来的消息
      • 6.1 查看post请求的数据格式
      • 6.2 解析xml字符串
      • 6.3 将xml字符串解析结构构造回复消息
        • 6.3.1 消息对象
        • 6.3.2 将map封装成消息对象
        • 6.3.3 将消息对象进行序列化为xml
        • 6.3.4 在controller实现(调用方法)

【公众号开发】(1)

公众号的使用和作用不必多说,很多企业都会选择公众号这种与客户粘性大的方式去推广自己或者其他的动作…

而本专栏主要讲解的就是公众号的基本开发,不囊括所有,但是可以从0到1,之后的1生万物由你完成!

我这里不列举公众号开发能咋开发,你可以查看开发者文档:开发前必读 / 首页 (qq.com)

在这里插入图片描述

这些是微信公众号自带的功能,但我们要满足我们自己的需求,当然是需要进行开发的

这些功能就是字面意思~

本专栏已开发为主,很少有理论的讲解,直接进入实战吧,公众号有啥功能我们可以开发,进入实战即可见分晓~

1. 获得一个测试号

正式的公众号的申请需要门槛,所以为了方便我们开发者上手,专门有一个“接口测试公众号”用来练习,只不过没有一些高级的接口,这些无伤大雅,有了基础就可以去学习高级接口了

开始开发 / 接口测试号申请 (qq.com)

在这里插入图片描述

按照指引注册即可,如果已经注册,登录微信即可

  • 由于是测试号,还不能登录公众号后台管理平台~
    • 所以没有那些现成的公众号提供的一些固定的操作~
  • 这个之后申请正式的公众号去登录用一用就会了~

在这里插入图片描述

这些消息可能你会有一些没有,不过没关系,之后慢慢展开

在这里插入图片描述

  • 用你的手机扫码关注后,你将在右侧看到你的关注用户

在这里插入图片描述

  • 这个之后再说

在这里插入图片描述

  • 这些就是测试号的体验的接口总览咯,使用上限,点击链接跳转到对于的开发手册页面
    • 需要就学即可
  • 我不会全讲也不会按顺序讲~

2. 公众号开发原理

在这里插入图片描述

大概就是这样的,微信公众号并不是什么功能都能实现,只能实现一些公众号提供的接口(就是刚才那些)

因为用户并不是直接访问开发者,开发者也不是直接响应给用户,微信公众号提供较为统一的页面给用户,和较为统一的接口给开发者

这样的介入,提高公众号的统一性,用户可以依照经验使用,又有公众号的特性,提供的接口给开发者开发自定义!

  • 功能的限制,对用户的请求和返回的响应需要经过公众号的检验,也提高微信的安全性和健康性

3. 创建开发者服务器

我们先创建一个项目(SpringBoot),作为开发者服务器

  • 由于涉及Spring web开发,如果没有此基础学不了,建议先去学!
  • 推荐资料:【JavaEE】让“单车变摩托”的神级框架—Spring MVC的深入讲解-CSDN博客

在这里插入图片描述

这里就是创建好的了

  1. 我导入了lombok依赖(在一开始选上就好)

  2. 我的配置文件为application.yml:

    spring:
      application:
        name: 微信公众号测试 # 项目的名称
      output:
        ansi:
          enabled: ALWAYS # 配置控制台输出的效果,彩色
      # JSON序列化配置
      jackson:
        date-format: yyyy-MM-dd HH:mm:ss # ⽇期格式
        default-property-inclusion: NON_NULL # 不为null序列化
    server:
      port: 8080
    
    logging:
      pattern:
        dateformat: MM-dd HH:mm:ss # 日期显示格式
      level:
        root: info # 日志默认级别
      file:
        path: D:/log/project/wx
    

4. 内网穿透

由于微信公众号服务器在千里之外,要想访问我们的开发者服务器,必然是要通过外网去访问的,所以我们需要一个外网ip!

  1. 云服务器
  2. 内网穿透工具

首先,云服务器是必然的,最终一定是要部署到云服务器去维持服务,但是我们开发阶段,频繁的修改和测验,云服务器的方式太麻烦了,所以我们要用内网穿透工具,将我们的内网映射成外网,让外接可以访问!

官网:NATAPP-内网穿透 基于ngrok的国内高速内网映射工具

在这里插入图片描述

在这里插入图片描述

安装到本地,并解压缩,到达natapp.exe的所在目录下:

在这里插入图片描述

右键在命令行打开:

在这里插入图片描述

回到官网注册/登录

在这里插入图片描述

这两项去做一下:

在这里插入图片描述

购买免费隧道:

在这里插入图片描述

进入配置页:

在这里插入图片描述

可以看到刚才的信息了,复制authtoken(等一下要用):

在这里插入图片描述

回到命令行输入(authtoken输入自己的):

./natapp -authtoken=72810d6d1ab6e1fe

这个就是映射的地址(综合了ip与端口的字符串):

在这里插入图片描述

不过注意的是,按ctrl c或者直接关闭或者电脑关机(甚至你没有关闭,过一段时间就变了),这个字符串的映射就失效了,并且下次生成的也不一样哦!

  • 所以,有时候公众号访问不了,那就是这个字符串变了;之后正式公众号和部署到云服务就不会出现这种情况了

在这里插入图片描述

我们写一个接口,检测一下这个字符串是否有效:

在这里插入图片描述

浏览器访问:

在这里插入图片描述

命令行有请求的记录:

在这里插入图片描述

5. 验证开发者服务器的url

其实就是这个地方的接口配置设置:

在这里插入图片描述

点击修改:

  • URL为刚才的内网穿透的字符串
  • Token为自定义令牌字符串

在这里插入图片描述

但是点击提交后,并不会显示成功:

在这里插入图片描述

这是因为微信公众号服务器要确保这个url是开发者的url,有这些好处(我认为):

  1. 这个可以先将地址访问问题单独拎出来,如果通过,那么以后发生的问题就不会是地址的问题(除非你的外网ip变了)
  2. 这个令牌Token只有公众号和开发者知道,开发者可以通过这个验证这个请求来自微信公众号服务器,保证信息安全

具体是啥原因,太底层不需要了解,我们“坐享其成,遵循规矩”

在这里插入图片描述

点击提交:

在这里插入图片描述

但是你现在纳闷了,“凭什么我不行?”,这是因为你的服务器并没有进行相关操作~

5.1 公众号服务器对url发送get请求

公众号会对我们填写的url的根目录(就是后面不带路由,也就是/)发送一个GET请求,这个请求的目的就是验证

但是浏览器访问是这样的:

在这里插入图片描述

原因是缺少参数,我们可以在开发者文档查看:开始开发 / 接入指南 (qq.com)

5.2 消息的验证逻辑

重点看这里:

在这里插入图片描述

他的意思就是,他的请求携带了这四个参数,而我们开发者如果返回echostr这个回显字符串的话,那么就是验证成功,公众号也就确认你是,并且授权了,所以就可以匹配成功

那么我们要咋样才可以返回echostr呢?

原理就是:

在这里插入图片描述

这里 Token是只有公众号和开发者知道

所以以此与timestamp和nonce拼接之后的字符串, 加密之后的字符串作为建议身份的标志 非常合理科学

一般加密是不可逆的,所以我们并没有办法将signature解密出Token,而是将 加密出一个字符串与之对比!

加密算法:

  1. timestamp、nonce、Token按字典序排列
  2. 将排列后的字符串进行拼接
  3. 将拼接字符串进行加密(加密结果为字节数组
  4. 字节数组每个字节按照十六进制进行拼接

最后,加密拼接字符串与signature进行比较

5.3 代码实现

所需依赖

<dependency>
   <groupId>org.dom4j</groupId>
   <artifactId>dom4j</artifactId>
   <version>2.1.3</version>
</dependency>
@GetMapping("/")
public String check(@RequestParam("signature") String signature,
                    @RequestParam("timestamp") String timestamp,
                    @RequestParam("nonce") String nonce,
                    @RequestParam("echostr") String echostr) {
    if(!StringUtils.hasLength(signature) || !StringUtils.hasLength(timestamp)
            || !StringUtils.hasLength(nonce) || !StringUtils.hasLength(echostr)) {
        return "";
    }
    // 1) 将token 、 timestamp 、 nonce 三个参数进行字典序排序
    String token = "maras103";
    String[] list = {token, timestamp, nonce};
    Arrays.sort(list);
    // 2) 将三个字符串以此顺序进行拼接
    StringBuilder builder = new StringBuilder();
    for(String s : list) {
        builder.append(s);
    }
    // 2.1) 加密
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("sha1");
        byte[] digest = messageDigest.digest(builder.toString().getBytes(StandardCharsets.UTF_8));
        // 2.2) 将加密后的byte数组转换为signature一样的格式(每个字节都转换为十六进制进行拼接)
        builder = new StringBuilder();
        for(byte b : digest) {
            // builder.append(Integer.toHexString(b));不能这么弄因为这样弄b如果是负,那么就凉凉
            // 这样写保证两位十六进制都存在并且正确
            builder.append(Integer.toHexString((b >> 4) & 15));//前四个字节转换为十六进制
            builder.append(Integer.toHexString(b & 15));//后四个字节转换为十六进制
        }
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
    // 3) 核对请求是否来自于微信(加密解析后的字符串与signature比较)
    if(builder.toString().equals(signature)) {
        // 相同才返回回显字符串
        // 并且返回echostr代表开发者确认了这是公众号服务器发来的请求,公众号就进行配置
        return echostr;
    } else {
        // 否则返回null
        return null;
    }
}

在这里插入图片描述

6. 接受并解析用户发来的消息

用户有时候会发一些消息给公众号,那我们的服务器怎么针对这些消息做出一些自定义的动作呢?

原理是这样的

  • 具体参考开发者文档,我这里直接说了

在这里插入图片描述

当用户发消息给公众号:

在这里插入图片描述

就相当于发请求给微服务公众号服务器,访问了它的一个接口,微信公众号就会打包我们的数据构造post请求访问我们的开发者服务器(根路径/

并且是以xml的格式!

6.1 查看post请求的数据格式

获取请求的输入流对象,读取数据

@PostMapping("/")
public String receiveMessage(HttpServletRequest request) throws IOException {
    ServletInputStream inputStream = request.getInputStream();
    byte[] b = new byte[1024];
    int len = 0;
    while((len = inputStream.read(b)) != -1) {
        System.out.println((new String(b, 0, len)));
    }
    return "";
}

注意:返回空字符串,代表什么都不回~

我们向公众号发一条消息:

在这里插入图片描述

在这里插入图片描述

6.2 解析xml字符串

@PostMapping("/")
public String receiveMessage(HttpServletRequest request) throws IOException {
    Map<String, String> map = new HashMap<>();
    SAXReader reader = new SAXReader();
    // xml字符串解析方法
    try {
        //通过请求的输入流,获取Document对象
        Document document = reader.read(request.getInputStream());
        // 获取root节点
        Element root = document.getRootElement();
        // 获取所有子节点
        List<Element> elements = root.elements();
        // 遍历集合
        for(Element e : elements) {
            map.put(e.getName(), e.getStringValue());
        }
        log.info(map.toString());
    } catch (DocumentException e) {
        throw new RuntimeException(e);
    }
    return "";
}

在这里插入图片描述

查看日志:
在这里插入图片描述

解析成功~

6.3 将xml字符串解析结构构造回复消息

注意:回复消息字符串必须是xml字符串格式,否则微信公众号不做任何动作

所需依赖

<dependency>
   <groupId>com.thoughtworks.xstream</groupId>
   <artifactId>xstream</artifactId>
   <version>1.4.11.1</version>
</dependency>
6.3.1 消息对象
@Data
@XStreamAlias("xml")
public class TextMessage {
    @XStreamAlias("ToUserName")
    private String toUserName;

    @XStreamAlias("FromUserName")
    private String fromUserName;

    @XStreamAlias("CreateTime")
    private long createTime;

    @XStreamAlias("MsgType")
    private String msgType;

    @XStreamAlias("Content")
    private String content;
}

在这里插入图片描述

这个对象进行序列化一个对象为xml字符串的时候,默认以类名为父标签,各个属性的属性名为子标签,如果一个属性为自定义类型,则这个对象也是树形结构xml标签嵌套于此xml标签(套娃套娃套娃…)

6.3.2 将map封装成消息对象
public static TextMessage getReplyTextMessage(Map<String, String> map) {
    TextMessage message = new TextMessage();
    message.setToUserName(map.get("FromUserName"));
    message.setFromUserName(map.get("ToUserName"));
    message.setCreateTime(System.currentTimeMillis() / 1000);
    message.setMsgType("text");
    message.setContent("回复" + map.get("Content") + ":就不告诉你");
    return message;
}

这里其实回复的消息可以是很多种(文本、图片、音频等等等…)

  • 复杂的回复体系这里暂时不讲,之后业务上做好分支即可~

(这里简单的回复个文本消息)

(发起者和接收者的username进行调换)

(时间戳是秒级别为当前时间)

6.3.3 将消息对象进行序列化为xml
/**
 * 将TextMessage对象序列化为xml字符串返回
 * @param message
 * @return
 */
public static String getXML(TextMessage message) {
    //获取序列化工具XStream对象
    XStream xStream = new XStream();
    //指定类型
    xStream.processAnnotations(TextMessage.class);
    //转化为xml字符串
    String xml = xStream.toXML(message);
    //返回
    return xml;
}

无非就是调用一些库方法

6.3.4 在controller实现(调用方法)
@PostMapping("/")
public String receiveMessage(HttpServletRequest request) throws IOException {
    //        ServletInputStream inputStream = request.getInputStream();
    //        byte[] b = new byte[1024];
    //        int len = 0;
    //        while((len = inputStream.read(b)) != -1) {
    //            System.out.println((new String(b, 0, len)));
    //        }
    Map<String, String> map = new HashMap<>();
    SAXReader reader = new SAXReader();
    // xml字符串解析方法
    try {
        //通过请求的输入流,获取Document对象
        Document document = reader.read(request.getInputStream());
        // 获取root节点
        Element root = document.getRootElement();
        // 获取所有子节点
        List<Element> elements = root.elements();
        // 遍历集合
        for(Element e : elements) {
            map.put(e.getName(), e.getStringValue());
        }
        log.info(map.toString());
    } catch (DocumentException e) {
        throw new RuntimeException(e);
    }
    // 回复消息
    // 1. 封装对象
    TextMessage textMessage = TextMessage.getReplyTextMessage(map);
    // 2. 序列化对象
    String message = TextMessage.getXML(textMessage);
    System.out.println(message);
    return message;
}

公众号发消息测试:

在这里插入图片描述

成功啦!

我想这么一个用户与公众号交互的程序,让大家对公众号开发有了初步的认知!


文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆

代码:wx-demo · 游离态/马拉圈2023年10月 - 码云 - 开源中国 (gitee.com)


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java数字处理类-- Math类--数学运算

在Java中提供了一个执行数学基本运算的Math类,该类包括了常用的数学运算方法和常量&#xff0c;包括【三角函数方法】&#xff0c;【指数函数方法】&#xff0c;【取整函数方法】、【取最大值函数方法】、【取最小值函数方法】、【取平均值函数方法】、【对数函数方法】&#x…

C# Onnx Yolov8 Detect 路面坑洼检测

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace Onnx…

使用 VS Code 作为 VC6 的编辑器

使用 VS Code 作为 VC 6.0 的编辑器 由于一些众所周知的原因&#xff0c;我们不得不使用经典&#xff08;过时&#xff09;的比我们年龄还大的已有 25 年历史的 VC 6.0 来学习 C 语言。而对于现在来说&#xff0c;这个经典的 IDE 过于简陋&#xff0c;并且早已不兼容新的操作系…

kubernetes(2)

pod管理 应用部署 上传测试镜像 [rootk8s1 docker]# docker push reg.westos.org/library/myapp:v1 [rootk8s1 docker]# docker push reg.westos.org/library/myapp:v2创建自助式pod&#xff08;生产不推荐&#xff09; [rootk8s2 ~]# kubectl run demo --imagemyapp:v1[ro…

iZotope RX 10for Mac /Windows- 音频修复的终极解决方案

随着音乐和电影制作的复杂性日益增加&#xff0c;高质量的音频修复变得越来越重要。iZotope RX 10&#xff0c;作为业界公认的专业音频修复软件&#xff0c;为你提供了强大、精确的工具&#xff0c;让你的声音变得清晰、纯净。 在音频修复领域&#xff0c;iZotope RX 10凭借其…

【vue3】组件间通讯

1.上级传给下级 父级组件&#xff1a; <ReqTab ref"crontabRef" hide"openCronfalse" fill"crontabFill" :expression"expression" :method"method" ></ReqTab> 函数中赋值&#xff1a; 子组件&#xff1a; …

IP协议(上)

目录 一、初步认识IP协议 二、认识IP地址 三、协议报头格式 1.报头和有效载荷分离 2.20字节的固定数据 四、网段划分 1.一个小例子 2.认识IP地址的划分 3.数据的传输过程 4.特殊的IP地址 5.通信运营商 &#xff08;1&#xff09;通信运营商的作用 &#xff08;2&a…

Unity可视化Shader工具ASE介绍——9、整理节点让复杂的Shader条理更清晰

阿赵的Unity可视化Shader工具ASE介绍目录 大家好&#xff0c;我是阿赵。   继续介绍Unity可视化Shader编辑工具ASE。上一篇介绍UI特效Shader的时候&#xff0c;连接了一个Shader 这个shader不是很复杂&#xff0c;但看起来也有点乱七八糟的。接下来通过对这个shader的节点连…

微信小程序设计之主体文件app-json-pages

一、新建一个项目 首先&#xff0c;下载微信小程序开发工具&#xff0c;具体下载方式可以参考文章《微信小程序开发者工具下载》。 然后&#xff0c;注册小程序账号&#xff0c;具体注册方法&#xff0c;可以参考文章《微信小程序个人账号申请和配置详细教程》。 在得到了测…

Linux生产者消费者模型

生产者消费者模型 生产者消费者模型生产者消费者模型的概念生产者消费者模型的特点生产者消费者模型优点 基于BlockingQueue的生产者消费者模型基于阻塞队列的生产者消费者模型模拟实现基于阻塞队列的生产消费模型 生产者消费者模型 生产者消费者模型的概念 生产者消费者模式就…

ChatGPT AIGC自动生成多条件复杂计算函数

在Excel中经常会遇到多条件判断,根据不同的条件与内容显示不同的值。 例如: 需要给每个员工根据入职年限,员工等级,满意度等维度给员工发年终奖。 这在职场办公过程中经常要面临的一个问题。如销售额达到多少,取多少提成,如学生成绩在什么区间是设置为优秀还是良好等一…

Windows开启telnet功能

打开控制面板&#xff0c;找到「程序和功能」&#xff0c;点击「启动或关闭Windows功能」 勾选「Telnet客户端」 点击确定&#xff0c;等待Windows完成设置。 然后就可以啦~ 今日金句&#xff1a; 煞笔给我退退退&#xff01;&#xff01;&#xff01;

ELK 单机安装

一丶软件下载 elasticsearch: https://www.elastic.co/downloads/past-releases kibana: https://www.elastic.co/downloads/past-releases 选择对应的版本的下载即可 二、es 安装es比较简单 rpm -ivh elasticsearch-2.4.2.rpm 修改配置文件 /etc/elasticsearch/elas…

基于SSM+Vue的体育馆管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

vue3插件开发,上传npm

创建插件 在vue3工程下&#xff0c;创建组件vue页: toolset.vue。并设置组件名称。注册全局组件。新建index.js文件。内容如下&#xff0c;可在main.js中引入index.js&#xff0c;注册该组件进行测试。![在这里插入图片描述](https://img-blog.csdnimg.cn/a3409d2cbeec41c797d5…

大数据Flink(九十九):SQL 函数的解析顺序和系统内置函数

文章目录 SQL 函数的解析顺序和系统内置函数 一、​​​​​​​SQL 函数

k8s kubernetes 1.23.6 + flannel公网环境安装

准备环境&#xff0c;必须是同一个云服务厂商&#xff0c;如&#xff1a;华为&#xff0c;阿里、腾讯等&#xff0c;不要存在跨平台安装K8S&#xff0c;跨平台安装需要处理网络隧道才能实现所有节点在一个网络集群中&#xff0c;这里推荐使用同一家云服务厂商安装即可 这里使用…

微信小程序实现类似于 vue中ref管理调用子组件函数的方式

微信小程序中确实有类似于 vue 中 ref管理子组件的方式、 这里 我给子组件定义了一个 class 只要是 css选择器拿得到的 都没什么问题 但你要保证唯一性 建议前端开发还是慎重一点 就算是不能重复也尽量用class 因为id总还是有风险的 然后 我在子组件中顶一个了一个函数 start…

AQS中lock源码解析

什么是AQS&#xff1f; 就是基于双向链表CAS实现的锁的一种机制或者方法思想。就是AbstractQueuedSynchronizer&#xff0c;是Java并发包下的一个基类基于AQS实现的同步器包括&#xff1a;ReentrantLock、CountDownLatch、Samaphone、FutureTask、ReentrantWriteLock Abstrac…

基于nodejs+vue云旅青城系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…