Java Development WeChat Official Account Passive Reply to User Message-Reply to Graphic Message

I. Introduction

Hello friends, everyone. The topic of this article is use Java开发微信公众号之被动回复用户消息-回复图文消息. For those who don’t know the WeChat official account passively responding to user messages (文本消息、图片消息), please take a look at the article I wrote earlier: Java Development of WeChat Official Account Passive Reply to user message-reply to text message , don't talk nonsense, start to enter the topic below.

WeChat development document: WeChat official document-passively respond to user messages

Two, version description

  • spring boot.version: v2.1.7.RELEASE
  • java.version: 1.8
  • weixin-java-mp.version: 3.5.0

Three, passively reply to messages

When a user sends a message to the official account (or when an event triggered by a specific user operation is pushed), a POSTrequest is generated . The developer can Getreturn a specific XML structure in the response package ( ) to respond to the message (now support Response 文本, 图片, 图文, 语音, 视频, 音乐). Strictly speaking, sending a passive response message is not actually an interface, but a reply to the message sent by the WeChat server.

Four, message re-weighting

After the WeChat server sends the user's message to the developer server URLaddress of the official account (configured in the Developer Center), the WeChat server will disconnect the connection if it does not receive a response within five seconds, and re-initiate the request, a total of three retries. If you Debugfind that the user cannot receive the response message during debugging, you can check whether the message processing has timed out. In general debugdebugging, the response will not be received after more than 5 seconds. Regarding retry message duplication, every message should retain its idempotent, pushed in xmlthe data structure, there are msgidmessages recommended msgidduplication. If it is an event type message, it is recommended to use it FromUserName + CreateTimefor re-resetting.

5. How to guarantee processing and reply within five seconds

If the server cannot guarantee to process and reply within five seconds, it must make the following reply, so that the WeChat server will not do anything about it and will not initiate a retry (in this case, you can use the customer service message interface for asynchronous Reply), otherwise, a serious error message will appear. See the description below for details:

  • 1. Reply directly success(recommended method)
  • 2. Reply to an empty string directly (refers to an empty string with a byte length of 0, not the content of the field in the XMLstructure contentis empty)

Once it encounters the server without processing within five seconds and responds to the reply or the developer responds with abnormal data, such as JSONdata, etc.; WeChat will send a system prompt to the user in the official account session “该公众号暂时无法提供服务,请稍后再试”;

6. How to reply to graphic messages

When replying to multimedia messages with pictures (GIF is not supported), temporary materials need to be uploaded to the WeChat server through the material management interface in advance; you can also upload permanent materials in the material management interface to the WeChat WeChat server, but the temporary materials are stored on the WeChat server The validity period of is only 3 days, and the permanent material is always valid. Since the number of WeChat permanent materials is limited, if your project environment has a large demand for media material files, use permanent materials to upload with caution and use temporary materials; but also It does not matter, the WeChat developer documentation also provides an interface for deleting permanent materials and deleting temporary materials, which can be used reasonably according to the scene.
After uploading temporary or permanent materials through the material management interface, the interface will return a key field called mediaId. After this is mediaIdreturned to us, we need to store it ourselves. When we need to use the multimedia file material, it is passed mediaIdto the interface parameter , the micro-channel will be based on the server mediaIdto find the corresponding source file, and then do the corresponding return processing, such as image info reply, reply graphic information, and so on.

Seven, upload picture materials in advance

Please note : As previously emphasized, when replying to (不支持gif动图)multimedia messages such as pictures , you need to upload temporary materials to the WeChat server through the material management interface in advance. You can use temporary materials in material management or permanent materials.
Therefore, before we realize the function of passively replying to the message-replying to the graphic message, we need to upload the temporary image material or the permanent image material to the WeChat platform first, and then we first observe the requirements xml格式and parameter descriptions of the graphic message .

1. Reply to graphic message in xml format

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>12345678</CreateTime>
  <MsgType><![CDATA[news]]></MsgType>
  <ArticleCount>1</ArticleCount>
  <Articles>
    <item>
      <Title><![CDATA[title1]]></Title>
      <Description><![CDATA[description1]]></Description>
      <PicUrl><![CDATA[picurl]]></PicUrl>
      <Url><![CDATA[url]]></Url>
    </item>
  </Articles>
</xml>

2. Description of parameters for replying to graphic messages

parameter Do you have to Description
ToUserName Yes Recipient account (OpenID received)
FromUserName Yes Developer Wechat
CreateTime Yes Message creation time (integer)
MsgType Yes Message type, picture and text are news
ArticleCount Yes The number of graphic messages; when the user sends six types of messages: text, picture, voice, video, graphic, text, and geographic location, the developer can only reply to 1 graphic message; the rest of the scenes can reply up to 8 graphic messages
Articles Yes Picture and text message information, note that if the number of pictures and text exceeds the limit, only the number within the limit will be sent
Title Yes Graphic message title
Description Yes Graphic message description
PicUrl Yes Image links, support JPG, PNG formats, better results for the big picture 360 200 Small chart 200 200
Url Yes Click the link of the graphic message

3. Upload permanent image material

/**
 * @desc:
 * @author: cao_wencao
 * @date: 2020-05-21 13:47
 */
@Slf4j
@RestController
@RequestMapping("/wx/material")
public class WxMaterialController {
    
    

   private static final SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );

    @Autowired
    private WeChatMaterialUtils materialUtils;

    /**
     * 上传单个图片文件
     */
    @PostMapping("/uploadImg")
    public ApiResult uploadImg(@RequestParam("imgFile") MultipartFile imgFile) throws IOException {
    
    
        log.info("multipartFile = " + imgFile);
        log.info("ContentType = " + imgFile.getContentType());
        log.info("OriginalFilename = " + imgFile.getOriginalFilename());
        log.info("Name = " + imgFile.getName());
        log.info("Size = " + imgFile.getSize());
        String fileExt = imgFile.getOriginalFilename().substring(imgFile.getOriginalFilename().lastIndexOf(".") + 1);
        log.info("fileExt = " + fileExt);

        WxMpMaterialUploadResult wxMpMaterialUploadResult
                 = materialUtils.uploadFilesToWeChat("image", fileExt ,imgFile.getName(), imgFile.getInputStream());
        if(null == wxMpMaterialUploadResult){
    
    
            return ApiResult.error("上传图片失败");
        }
        log.info("wxMpMaterialUploadResult = : " + JSON.toJSONString(wxMpMaterialUploadResult));
        return ApiResult.succee(wxMpMaterialUploadResult,"上传图片成功");
    }
   }

4. PostMan test image upload

4.1 The parameters are as follows

  • headers

“key”:“Content-Type”, “value”:“multipart/form-data”

  • body
    Insert picture description here
  • Response result
{
    
    
    "code": 200,
    "message": "上传图片成功",
    "data": {
    
    
        "mediaId": "1C72rnlYrj7ZqBiRGdKCoUUudPCjA5qMkJZeODvTN9U",
        "url": "http://mmbiz.qpic.cn/mmbiz_jpg/DwMlrmia5oVQrbNsb6GJ64xlUtfTXspTcyuV1m6ykgiaGJQYR374WWfGGrgibJOibYc1df7Wyicw4u9f5CV3u7oAzow/0?wx_fmt=jpeg"
    }
}
  • Access url
    Insert picture description here

Eight, package graphic message Handler

  • TextMsgHandler.java
package com.thinkingcao.weixin.handler;

import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @desc: 文本类型消息处理-TEXT
 * @link: XmlMsgType.TEXT
 * @author: cao_wencao
 * @date: 2020-05-20 15:15
 */
@Component
public class TextMsgHandler extends AbstractHandler {
    
    

    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> map, WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException {
    
    
        //判断传递过来的消息,类型是否为TEXT
        if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.TEXT)) {
    
    
            //TODO: 如果需要做微信消息日志存储,可以在这里进行日志存储到数据库,这里省略不写。
        }
        // 获取微信用户基本信息
        WxMpUser userWxInfo = wxMpService.getUserService().userInfo(wxMessage.getFromUser(), "zh_CN");
        if (null == userWxInfo){
    
    
            return null;
        }
        String content = wxMessage.getContent();
        if ("文本".equals(content)){
    
    
            //下面两种响应方式都可以
            //return new TextBuilder().build("您的一互动,泛起了我内心的涟漪。",wxMessage,wxMpService);
            return WxMpXmlOutMessage
                    .TEXT()
                    .content("您的一互动,就激起了我内心的无限可能")
                    .fromUser(wxMessage.getToUser())
                    .toUser(wxMessage.getFromUser())
                    .build();
        }
        if ("图片".equals(content)){
    
    
            return WxMpXmlOutMessage
                    .IMAGE()
                    .mediaId("1C72rnlYrj7ZqBiRGdKCoS54AXQwSo4iULd9qRhOC-U")
                    .fromUser(wxMessage.getToUser())
                    .toUser(wxMessage.getFromUser())
                    .build();
        }
        if ("图文".equals(content)){
    
    
            List<WxMpXmlOutNewsMessage.Item> articles = new ArrayList<>();
            WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item();
            item.setDescription("使用Java语言进行开发微信公众号发送图文消息");
            item.setPicUrl("http://mmbiz.qpic.cn/mmbiz_jpg/DwMlrmia5oVQrbNsb6GJ64xlUtfTXspTcgAU6Jvbt3uL72LqN3ToB4ibiaWkTZT7SD0IUD56uGiaFRXpI8vBYtYrAQ/0?wx_fmt=jpeg");
            item.setTitle("SpringBoot开发微信公众号");
            item.setUrl("https://blog.csdn.net/thinkingcao/category_9277860.html");

            articles.add(item);
            return WxMpXmlOutMessage
                    .NEWS()
                    .addArticle(item)
                    .articles(articles)
                    .fromUser(wxMessage.getToUser())
                    .toUser(wxMessage.getFromUser())
                    .build();
        }
        return null;
    }
}

Nine, test passive response to graphic messages

Enter in the official account dialog box: After the graphic keyword, the background will match the message type MsgType = text through routing, and then find the specific text message processor, that is, TextMsgHandler, and then further match the keyword "graphic", and then Assemble the reply graphic message field and reply the graphic message to the user interactor, so here is a simple sentence. In actual project development, constructing a passive message reply must achieve dynamic content, so the data generated by all fields must be To record through the database table, when constructing the passive message reply, it can be fetched from the database, so that the dynamic passive reply to the user message is realized.

  1. Background request response console log
2020-06-10 23:51:23.334 DEBUG 4812 --- [nio-8080-exec-3] m.c.w.mp.api.impl.BaseWxMpServiceImpl    : 
【请求地址】: https://api.weixin.qq.com/cgi-bin/user/info?access_token=34_Gsg49pv1E8sqzyc7DeHUXSVtUQZSxxTXkXp3h_S_MCOXYwIuqqH41B4a6eF3HpokFucpJVjJIPpPvKwQYCXFMWdAJc45Yd8BmEk-PPHWDg_iJ5INbTuWn9m3gQdHQV-zcbtFN2V8-DGDZo6WSHXfAAAWLB
【请求参数】:openid=oGjQdw2EyT7CBNfN84Te6IpmflCM&lang=zh_CN
【响应数据】:{
    
    "subscribe":1,"openid":"oGjQdw2EyT7CBNfN84Te6IpmflCM","nickname":"曹","sex":1,"language":"zh_CN","city":"墨尔本","province":"维多利亚","country":"澳大利亚","headimgurl":"http:\/\/thirdwx.qlogo.cn\/mmopen\/1ZMUBCDTp8ZAsxH99cX3icFXXDSstNaIR1FDpibnmfNPEn1J7Hf9yLXicSHJiciaEgtwgTXRicib9X2mua4bpeEg2sWNics6rXnIKKq7\/132","subscribe_time":1589956861,"remark":"","groupid":0,"tagid_list":[],"subscribe_scene":"ADD_SCENE_QR_CODE","qr_scene":0,"qr_scene_str":""}
2020-06-10 23:51:23.335 DEBUG 4812 --- [nio-8080-exec-3] m.c.weixin.mp.api.WxMpMessageRouter      : End session access: async=false, sessionId=oGjQdw2EyT7CBNfN84Te6IpmflCM
2020-06-10 23:51:23.335 DEBUG 4812 --- [pool-1-thread-4] m.c.weixin.mp.api.WxMpMessageRouter      : End session access: async=true, sessionId=oGjQdw2EyT7CBNfN84Te6IpmflCM
2020-06-10 23:51:23.336 DEBUG 4812 --- [nio-8080-exec-3] c.t.w.controller.WxPortalController      : 
组装回复信息:<xml>
  <ToUserName><![CDATA[oGjQdw2EyT7CBNfN84Te6IpmflCM]]></ToUserName>
  <FromUserName><![CDATA[gh_833ac613acf7]]></FromUserName>
  <CreateTime>1591804283</CreateTime>
  <MsgType><![CDATA[news]]></MsgType>
  <Articles>
    <item>
      <Title><![CDATA[SpringBoot开发微信公众号]]></Title>
      <Description><![CDATA[使用Java语言进行开发微信公众号发送图文消息]]></Description>
      <PicUrl><![CDATA[http://mmbiz.qpic.cn/mmbiz_jpg/DwMlrmia5oVQrbNsb6GJ64xlUtfTXspTcyuV1m6ykgiaGJQYR374WWfGGrgibJOibYc1df7Wyicw4u9f5CV3u7oAzow/0?wx_fmt=jpeg]]></PicUrl>
      <Url><![CDATA[https://blog.csdn.net/thinkingcao/category_9277860.html]]></Url>
    </item>
  </Articles>
  <ArticleCount>1</ArticleCount>
</xml>
  1. Dialog interaction
    Insert picture description here

Ten, source code

Source code: https://github.com/Thinkingcao/SpringBootLearning/tree/master/springboot-wechat

Guess you like

Origin blog.csdn.net/Thinkingcao/article/details/106677413