java版微信公众平台后台接入

下面是“Java版微信公众平台后台接入”的完整攻略。

什么是微信公众平台后台接入

微信公众平台后台接入,又称为微信公众号开发,指的是将自己的服务与微信公众平台对接,实现在微信公众号中提供各种服务的开发行为。接入微信公众平台后,就能够使用微信公众平台提供的各种能力,比如自定义菜单、消息推送、客服消息、素材管理等。

步骤

1. 注册成为微信公众号开发者

首先需要在微信公众平台注册成为开发者,然后进入开发者中心获取开发者ID和开发者密钥。注册地址:https://mp.weixin.qq.com/

2. 构建本地开发环境

需要安装Java开发环境(JDK)、Maven(项目管理工具)和一个Java Web框架,比如Spring MVC。

3. 接入微信公众平台

3.1 配置服务器URL和token

在微信公众平台开发者中心,设置服务器URL和token,使得微信公众平台能够向开发者服务器发送请求。将token和微信服务器传送过来的参数进行比较从而验证微信服务器的身份信息。

示例:

服务器URL:http://example.com/weixin

token:MyToken

3.2 验证开发者服务器与微信服务器通信

  1. 在公众平台开发者中心,可以设置接口配置信息,输入服务器配置URL和Token,微信服务器会向开发者服务器验证身份。首先进入“开发者中心”,然后进入“基本配置”,将服务器“URL”和“Token”填入,保存即可完成服务器配置。

  2. 验证token接口。微信服务器在配置服务器后会首先尝试访问token接口,比较token的值是否和设置的值相同,从而确认身份信息。验证方法需要在开发者服务器上编写一个Controller,代码如下:

public class TokenController {
    // 与开发者中心的Token一致
    public static final String TOKEN = "MyToken";

    // 处理微信服务器发来的GET请求,进行身份验证
    @RequestMapping(value = "/", method = RequestMethod.GET)
    @ResponseBody
    public String validate(@RequestParam(value = "signature") String signature,
                           @RequestParam(value = "timestamp") String timestamp,
                           @RequestParam(value = "nonce") String nonce,
                           @RequestParam(value = "echostr") String echostr) {
        String[] arr = {TOKEN, timestamp, nonce};
        // 将Token、timestamp、nonce三个参数进行字典序排序
        Arrays.sort(arr);

        StringBuilder sb = new StringBuilder();
        for (String s : arr) {
            sb.append(s);
        }

        // 对三个参数字符串拼接成一个字符串进行SHA1加密
        String result = DigestUtils.sha1Hex(sb.toString());
        // 将加密后的字符串与signature进行比较
        if (result.equals(signature)) {
            // 验证成功后返回echostr,表示验证成功
            return echostr;
        } else {
            // 验证失败返回空
            return "";
        }
    }
}
  1. 以SpringMVC为例,将该Controller配置到web.xml文件中。
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/weixin</url-pattern>
</servlet-mapping>

4. 接收和回复消息

当用户向公众号发送消息时,微信服务器把消息传递到开发者服务器,开发者服务器接收消息后进行处理并返回响应给微信服务器,微信服务器再把响应返回给用户。

4.1 配置消息接收URL

和配置服务器URL和token一样,在微信公众平台开发者中心设置接收消息的URL。

URL:http://example.com/weixin/message

4.2 接收消息

将微信服务器发来的XML数据进行解析,将消息内容封装成Msg对象。根据不同类型的消息进行处理,比如回复文本消息、回复图片消息等。

示例:

public class MessageController {
    @RequestMapping(value = "/message", method = RequestMethod.POST)
    @ResponseBody
    public String receive(HttpServletRequest request) {
        Msg msg = parseRequestMessage(request);

        String respXml = "";
        switch (msg.getMsgType()) {
            case "text":
                respXml = buildTextResponseXml(msg, "你好,我是机器人!");
                break;
            case "image":
                respXml = buildImageResponseXml(msg, "media_id");
                break;
            default:
                break;
        }

        return respXml;
    }

    private Msg parseRequestMessage(HttpServletRequest request) {
        // 解析XML数据
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(request.getInputStream());
            Element root = doc.getDocumentElement();

            String toUserName = root.getElementsByTagName("ToUserName").item(0).getTextContent();
            String fromUserName = root.getElementsByTagName("FromUserName").item(0).getTextContent();
            String createTime = root.getElementsByTagName("CreateTime").item(0).getTextContent();
            String msgType = root.getElementsByTagName("MsgType").item(0).getTextContent();
            String content = root.getElementsByTagName("Content").item(0).getTextContent();
            String msgId = root.getElementsByTagName("MsgId").item(0).getTextContent();

            return new Msg(toUserName, fromUserName, createTime, msgType, content, msgId);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private String buildTextResponseXml(Msg msg, String text) {
        // 生成回复XML
        WxOutTextMessage outMsg = new WxOutTextMessage();
        outMsg.setContentType("text");
        outMsg.setToUserName(msg.getFromUserName());
        outMsg.setFromUserName(msg.getToUserName());
        outMsg.setCreateTime(new Date().getTime());
        outMsg.setContent(text);

        return outMsg.toXml();
    }

    private String buildImageResponseXml(Msg msg, String mediaId) {
        // 生成回复XML
        WxOutImageMessage outMsg = new WxOutImageMessage();
        outMsg.setContentType("image");
        outMsg.setToUserName(msg.getFromUserName());
        outMsg.setFromUserName(msg.getToUserName());
        outMsg.setCreateTime(new Date().getTime());
        outMsg.setMediaId(mediaId);

        return outMsg.toXml();
    }
}

4.3 回复消息

根据用户发送的消息内容,确定需要回复的消息类型和内容,生成对应类型的消息XML数据。示例中,给出回复文本消息和回复图片消息的代码。

5. 其他功能实现

通过公众号开发者文档,了解微信公众平台提供的其他能力,如自定义菜单、模板消息、微信支付等,并在自己的服务中实现。

示例

示例代码:https://github.com/qianmingzhe/weixin-java-demo

示例1

实现对用户发送的文本信息自动回复。

  1. 编写一个 Controller,用于处理接收到的消息请求。
@Controller
@RequestMapping("/weixin")
public class WeixinController {
    @RequestMapping(method = RequestMethod.GET)
    public @ResponseBody String handleGetRequest(@RequestParam(value = "signature") String signature,
                                                  @RequestParam(value = "timestamp") String timestamp,
                                                  @RequestParam(value = "nonce") String nonce,
                                                  @RequestParam(value = "echostr") String echostr) {
        if (checkSignature(signature, timestamp, nonce)) {
            return echostr;
        } else {
            return "";
        }
    }

    @RequestMapping(method = RequestMethod.POST)
    public @ResponseBody String handlePostRequest(HttpServletRequest request) {
        try {
            BufferedReader reader = request.getReader();
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            reader.close();

            String xml = sb.toString();
            requestMsgHandler(xml);
            return "";
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

    private void requestMsgHandler(String xml) {
        XStream xstream = new XStream(new DomDriver());
        xstream.alias("xml", RequestMessage.class);
        RequestMessage msg = (RequestMessage) xstream.fromXML(xml);

        String msgType = msg.getMsgType();
        String content = msg.getContent();
        if ("text".equals(msgType)) {
            String replyXml = buildResponseXml(msg, "你好");
            System.out.println(replyXml);
        }
    }

    private String buildResponseXml(RequestMessage request, String content) {
        ResponseMessage response = new ResponseMessage();
        response.setToUserName(request.getFromUserName());
        response.setFromUserName(request.getToUserName());
        response.setCreateTime(System.currentTimeMillis());
        response.setMsgType("text");
        response.setContent(content);

        XStream xstream = new XStream(new DomDriver());
        xstream.alias("xml", ResponseMessage.class);
        return xstream.toXML(response);
    }

    private boolean checkSignature(String signature, String timestamp, String nonce) {
        List<String> fields = Arrays.asList("my_token", timestamp, nonce);
        Collections.sort(fields);
        String str = StringUtils.join(fields, "");
        String hex = DigestUtils.sha1Hex(str);
        return hex.equals(signature);
    }
}

  1. 配置菜单功能,用户点击菜单可以直接发送消息给公众号。

示例2

实现用户关注自动回复,关注后推送欢迎语。

  1. 编写一个 Controller,用于处理接收到的消息请求。
@Controller
@RequestMapping("/weixin")
public class WeixinController {
    @RequestMapping(method = RequestMethod.GET)
    public @ResponseBody String handleGetRequest(@RequestParam(value = "signature") String signature,
                                                  @RequestParam(value = "timestamp") String timestamp,
                                                  @RequestParam(value = "nonce") String nonce,
                                                  @RequestParam(value = "echostr") String echostr) {
        if (checkSignature(signature, timestamp, nonce)) {
            return echostr;
        } else {
            return "";
        }
    }

    @RequestMapping(method = RequestMethod.POST)
    public @ResponseBody String handlePostRequest(HttpServletRequest request) {
        try {
            BufferedReader reader = request.getReader();
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            reader.close();

            String xml = sb.toString();
            requestMsgHandler(xml);
            return "";
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

    private void requestMsgHandler(String xml) {
        XStream xstream = new XStream(new DomDriver());
        xstream.alias("xml", RequestMessage.class);
        RequestMessage msg = (RequestMessage) xstream.fromXML(xml);

        if ("event".equals(msg.getMsgType()) && "subscribe".equals(msg.getEvent())) {
            String replyXml = buildResponseXml(msg, "欢迎关注我的公众号");
            System.out.println(replyXml);
        }
    }

    private String buildResponseXml(RequestMessage request, String content) {
        ResponseMessage response = new ResponseMessage();
        response.setToUserName(request.getFromUserName());
        response.setFromUserName(request.getToUserName());
        response.setCreateTime(System.currentTimeMillis());
        response.setMsgType("text");
        response.setContent(content);

        XStream xstream = new XStream(new DomDriver());
        xstream.alias("xml", ResponseMessage.class);
        return xstream.toXML(response);
    }

    private boolean checkSignature(String signature, String timestamp, String nonce) {
        List<String> fields = Arrays.asList("my_token", timestamp, nonce);
        Collections.sort(fields);
        String str = StringUtils.join(fields, "");
        String hex = DigestUtils.sha1Hex(str);
        return hex.equals(signature);
    }
}

  1. 配置菜单功能,用户点击菜单可以直接发送消息给公众号。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java版微信公众平台后台接入 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • OpenMP task construct 实现原理及源码示例解析

    OpenMP task construct 实现原理及源码示例解析 一、简介 OpenMP作为一种并行编程的标准,其在多核处理器上实现并行化工作时非常常见。在OpenMP中,task construct 作为一种重要的并行化工具,可以方便地在并行执行中创建多个任务,并将这些任务分配到多个线程中。本篇攻略将详细讲解 OpenMP task construct …

    other 2023年6月26日
    00
  • C++性能剖析教程之switch语句

    C++性能剖析教程之switch语句 在C++中,switch语句是一种非常常见的控制语句,它通常用于分支选择性的流程控制。但是,由于switch语句的实现方式不同于其他一些流程控制语句,其性能可能会受到影响。因此,在需要优化程序性能时,我们需要了解如何使用和优化switch语句。 switch语句的基本用法 switch语句通常用于在多个选项中进行选择。其…

    other 2023年6月26日
    00
  • 浅析C语言中的数组及字符数组

    一、C语言中的数组 1. 定义 C语言中的数组是一种由相同数据类型构成的数据结构,它可以同时存储多个值,这些值可以被单独的标识符访问。数组有固定的大小,一旦定义了数组的大小,就不能再改变它了。 2. 声明 声明数组需要指定数组的类型、数组名和数组的长度。 数据类型 数组名[数组长度]; 例如: int arr[5]; //声明了一个长度为5的int类型的数组…

    other 2023年6月25日
    00
  • Linux文件目录结构(小白版)

    下面是关于“Linux文件目录结构(小白版)”的详细攻略: 目录 常用目录 目录树结构 其他目录 常用目录 Linux系统中有很多目录,这里列出一些常用的目录: / 根目录:Linux系统的根目录,所有目录和文件都在该目录下。 /bin 目录:系统命令(可执行文件)所在目录,如 ls、cp、mv 命令等。 /dev 目录:设备文件所在目录,Linux系统中一…

    other 2023年6月27日
    00
  • securecrt(CRT)导入会话

    SecureCRT(CRT)导入会话 SecureCRT是一款非常流行的Windows SSH和Telnet客户端,使用它可以与远程服务器进行命令行交互。在使用SecureCRT时,我们通常需要导入远程服务器的会话配置,以便快速连接到远程终端。 本文将介绍如何通过SecureCRT导入会话配置文件,并讲解如何在导入过程中遇到的常见问题的解决方案。 步骤一:打…

    其他 2023年3月28日
    00
  • 在ubuntu下安装apache

    在Ubuntu下安装Apache Apache 是一个广泛使用的 web 服务器软件,是开放源代码软件的一个典范。本文将介绍如何在 Ubuntu 操作系统下安装 Apache。 步骤一:更新软件包列表 在进行任何安装之前,最好先更新系统中的软件包列表。使用以下命令更新: sudo apt-get update 步骤二:安装 Apache 安装 Apache …

    其他 2023年3月29日
    00
  • 快速便捷关闭win7应用程序的几种方法(图文教程)

    快速便捷关闭Win7应用程序的几种方法(图文教程)攻略 在Win7系统使用过程中,经常会有需要关闭某些应用程序的情况。通过任务管理器结束进程,虽然可以关闭应用程序,但是操作过程相对较繁琐,因此此处介绍几种快速便捷关闭Win7应用程序的方法。 方法一:使用快捷键 打开需要关闭的应用程序窗口。 按下键盘上的“Alt+F4”组合键。 在弹出的对话框中选择“关闭”或…

    other 2023年6月25日
    00
  • TCP长连接实践与挑战

    TCP长连接实践与挑战 TCP是一种可靠的传输协议,而HTTP作为应用层协议的一种,使用TCP作为其传输层的协议。TCP的可靠性让其成为HTTP协议的首选传输层协议。而在HTTP/1版本中,每个HTTP请求都会建立一条TCP连接。这种“短连接”的方式在一定程度上限制了HTTP的性能。因此,HTTP/1.x开始出现了使用持久连接的方式,即“HTTP长连接”或者…

    其他 2023年3月28日
    00
合作推广
合作推广
分享本页
返回顶部