Spring Boot developing WeChat public address background

Hello, everyone, little brother, today, I want to talk to you about an interesting topic, which is to use WeChat Boot to develop the background of WeChat public address.

Many little friends may notice SongGe's personal website( http://www.javaboy.org A few days ago, the function of unlocking the website articles was released on a public address, and the function of the super 2TB free video tutorials was obtained from some previous public passwords. Free video tutorial These two are based on Spring Boot. Recently, song Ge intends to introduce a series of articles to introduce to the partners how to develop the public background through Spring Boot.

1. origin

In May of this year, I wanted to share some of my previous video tutorials with the little partners on the public numbers, but these video tutorials were too big to share at once. The single share sharing link immediately failed. In order to share these videos to everyone, I split the video into many copies, and then set up different passwords. Background No. 1 can get these videos by replying to the password. There are more than 100 passwords before and after. I manually configure them in the wechat background one by one. It's a lot of work. It took about three nights to get these things done.

So I was thinking, it's time to write some code.

Last month, I bought a server and put it on file. Some of them were there, so I decided to implement these resources with code, because I did not have any difficulty in developing public numbers when I was in University.

2. Implementation ideas

In fact, the implementation principle of song GE's reply password to obtain video link is very simple. To put it bluntly, it's just a data query operation. The reply password is the query keyword, and the reply content is the query result. The principle is simple.

On the other hand, we need to understand the process of sending the WeChat public's background development message. Let's look at the following picture:

This is the situation where people respond to key words in the background of public numbers. So what is the delivery process of this message? Let's take a look at the following picture:

Let me explain this picture to you.

  1. First, the javaboy4096 character is sent from the public address to the WeChat server.
  2. Next, wechat server will forward javaboy4096 to my own server
  3. After receiving the character javaboy4096, I went to the database to query, and returned the query results in the XML format required by Tencent.
  4. Wechat server sends the information received from my server back to wechat, and then the kids see the returned results.

This is the general process.

Let's take a look at the implementation details.

3. public number background configuration

The first step of development is to verify whether our own wechat server is effective.

First, we log in to the official website of wechat public platform, check the agreement to become a developer on the development basic settings page of the official website of the public platform, and then click the "modify configuration" button to fill in:

  • Server address (URL)
  • Token
  • EncodingAESKey

After the URL here is configured, we need to develop two interfaces for this URL, one is the GET request interface, which is used to verify the validity of the server, and the other is the POST request interface, which is used to receive the messages sent by the wechat server. In other words, wechat server messages are sent to me through POST requests.

The Token can be filled in by the developer at will and used as the generation signature (the Token will be compared with the Token contained in the interface URL to verify the security).

Encoding aeskey is manually filled in or randomly generated by the developer and will be used as the encryption and decryption key of the message body.

At the same time, developers can choose message encryption and decryption mode: plaintext mode, compatibility mode and security mode. The clear text mode is that when our own server receives the message sent by wechat server, it is a clear text string, which can be read and parsed directly. The security mode is that the message sent by wechat server is an encrypted message, which can only be used after we manually parse it.

4. development

After the configuration of the public address is completed, we can write the code next.

4.1 server validity verification

First, we will create a common Spring Boot project. When creating, we will introduce the Spring Boot starter web dependency. After the project is created successfully, we will create a Controller and add the following interfaces:

@GetMapping("/verify_wx_token")
public void login(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
    request.setCharacterEncoding("UTF-8");
    String signature = request.getParameter("signature");
    String timestamp = request.getParameter("timestamp");
    String nonce = request.getParameter("nonce");
    String echostr = request.getParameter("echostr");
    PrintWriter out = null;
    try {
        out = response.getWriter();
        if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
            out.write(echostr);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        out.close();
    }
}

I will explain this code as follows:

  1. Firstly, the four parameters of signature, timestamp, nonce and Echostar sent by wechat server are obtained through the request.getParameter method. Among them, signature represents wechat encryption signature, which combines the token parameter filled in by developers with the timestamp parameter and nonce parameter in the request, timestamp represents timestamp, nonce represents random number, and echos. TR represents a random string.
  2. The developer verifies the request by checking the signature. If the GET request is confirmed to be from the wechat server, it will return the contents of the echostr parameter as is, the access will take effect and become the developer. Otherwise, the access will fail.
  3. The specific verification is the CheckUtil.checkSignature method in SongGe. In this method, the token, timestamp and nonce parameters are first sorted in dictionary order, and then the three parameter strings are spliced into a string for sha1 encryption. Finally, the encrypted string obtained by the developer can be compared with the signature to identify that the request comes from wechat.

The verification code is as follows:

public class CheckUtil {
    private static final String token = "123456";
    public static boolean checkSignature(String signature, String timestamp, String nonce) {
        String[] str = new String[]{token, timestamp, nonce};
        //sort
        Arrays.sort(str);
        //Concatenate string
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < str.length; i++) {
            buffer.append(str[i]);
        }
        //Do sha1 encryption
        String temp = SHA1.encode(buffer.toString());
        //Match with the signature provided by wechat
        return signature.equals(temp);
    }
}
public class SHA1 {
    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }
    public static String encode(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

OK, after that, our verification interface is developed. Next, you can develop the message receiving interface.

4.2 message receiving interface

Next, we develop the message receiving interface. The message receiving interface is the same as the above server checkout interface address. It is the address that we initially configured in the public address. It's just that the message receiving interface is a POST request.

When I was configured in the background of the public address, I chose the plaintext mode in the way of message encryption and decryption, so that the messages I received in the background could be processed directly. The format of ordinary text message sent to me by wechat server is as follows:

<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>
</xml>

The meanings of these parameters are as follows:

parameter describe
ToUserName Developer wechat
FromUserName Sender account number (an OpenID)
CreateTime Message creation time (integer)
MsgType Message type, text
Content Text message content
MsgId Message id, 64 bit integer

When you see this, you will probably know. When we receive the message from wechat server, we will parse the XML, extract the information we need, perform relevant query operations, and then return the result to wechat server.

Let's start with a simple one. We will parse and print the received message:

@PostMapping("/verify_wx_token")
public void handler(HttpServletRequest request, HttpServletResponse response) throws Exception {
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");
    PrintWriter out = response.getWriter();
    Map<String, String> parseXml = MessageUtil.parseXml(request);
    String msgType = parseXml.get("MsgType");
    String content = parseXml.get("Content");
    String fromusername = parseXml.get("FromUserName");
    String tousername = parseXml.get("ToUserName");
    System.out.println(msgType);
    System.out.println(content);
    System.out.println(fromusername);
    System.out.println(tousername);
}
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
    Map<String, String> map = new HashMap<String, String>();
    InputStream inputStream = request.getInputStream();
    SAXReader reader = new SAXReader();
    Document document = reader.read(inputStream);
    Element root = document.getRootElement();
    List<Element> elementList = root.elements();
    for (Element e : elementList)
        map.put(e.getName(), e.getText());
    inputStream.close();
    inputStream = null;
    return map;
}

You can see that in fact, there are some conventional codes, so there is no difficulty.

After that, we will start the project as a jar package on the server. After the success of the startup, it is OK to confirm the background configuration of WeChat. We can send a message on the public address, so that our own server will print out the message just now.

OK, space limit. Let's talk about so much today, and then we'll talk about the analysis of different message types and the return of messages.

I don't know. Do you understand? If you have any questions, please leave a message for discussion.

Reference: wechat open document

Pay attention to the public number [Jiangnan rain], focus on Spring Boot+ micro service and front end separation and other full stack technology, regular video tutorial sharing, focus on back to Java, receive Pine's carefully prepared Java dry goods for you!

Keywords: Java Spring SHA1 xml

Added by liam1412 on Wed, 30 Oct 2019 05:28:32 +0200