微信公众号开发之回复图文消息(十一)

时间:2024-02-21 07:34:27

有时候我们希望用户点击我们的菜单时候,微信公众号给他回复我们自定义的图文消息,先看开发文档接口

回复图文消息

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

参数是否必须说明
ToUserName 接收方帐号(收到的OpenID)
FromUserName 开发者微信号
CreateTime 消息创建时间 (整型)
MsgType 消息类型,图文为news
ArticleCount 图文消息个数;当用户发送文本、图片、视频、图文、地理位置这五种消息时,开发者只能回复1条图文消息;其余场景最多可回复8条图文消息
Articles 图文消息信息,注意,如果图文数超过限制,则将只发限制内的条数
Title 图文消息标题
Description 图文消息描述
PicUrl 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
Url 点击图文消息跳转链接

先定义我们的发送体POJO,一个是Article,一个是NewsMessage

Article.java
package com.xu.wemall.pojo.message;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
  * 
  * @Description: 图文model
  * @Parameters: 
  * @Return: 
  * @Create Date: 
  * @Version: V1.00
  * @author: 来日可期
  */
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class Article {

    //图文消息名称
    private String Title;

    //图文消息描述
    private String Description;

    //图片链接,支持JPG、PNG格式,较好的效果为大图640像素*320像素,小图80像素*80像素
    private String PicUrl;

    //点击图文消息跳转链接
    private String Url;

}

NewsMessage.java
package com.xu.wemall.pojo.message;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 *
 * @Description: 图文消息
 * @Parameters:
 * @Return:
 * @Create Date:
 * @Version: V1.00
 * @author: 来日可期
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class NewsMessage extends BaseMessage {

    //图文消息个数,限制为10条以内
    private int ArticleCount;

    //多条图文消息信息,默认第一个item为大图
    private List<Article> Articles;

}

定义一个方法回复图文消息

/**
 * 回复文本图片
 * @param toUserName
 * @param fromUserName
 * @param articles
 * @return
 */
public String replyForArticles(String toUserName, String fromUserName, List<Article> articles) throws Exception{

    log.info("这是图文消息回复!");
    NewsMessage newsMessage = new NewsMessage();
    //必填
    newsMessage.setFromUserName(toUserName);
    //必填
    newsMessage.setToUserName(fromUserName);
    //必填
    newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);
    //必填
    newsMessage.setCreateTime( LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());

    //当用户发送文本、图片、视频、图文、地理位置这五种消息时,开发者只能回复1条图文消息
    newsMessage.setArticleCount(1);

    if (!articles.isEmpty()) {
        newsMessage.setArticles(articles);
        String xmlString = MessageUtil.newsMessageToXml(newsMessage);
        log.info(xmlString);

        return xmlString;
    }
    return null;
}

这里有个MessageUtil.newsMessageToXml(newsMessage)方法

/**
 * @param newsMessage
 * @return xml
 * @Description: 图文消息对象转换成xml
 * @date 2016-12-01
 */

public static String newsMessageToXml(NewsMessage newsMessage) {
    xstream.alias("xml", newsMessage.getClass());
    xstream.alias("item", new Article().getClass());
    return xstream.toXML(newsMessage);
}

现在测试一下我们的代码,我们需要在我们的菜单里触发我们的方法,我们这里采用

如果需要重新生成菜单,请重新生成一次,然后我们在微信接入的核心controller中写我们的响应代码

package com.xu.wemall.controller.weixin;

import com.alibaba.fastjson.JSONObject;
import com.xu.wemall.commons.utils.CheckUtil;
import com.xu.wemall.components.weixin.MessageUtil;
import com.xu.wemall.components.weixin.WeiXinUserUtil;
import com.xu.wemall.pojo.message.Article;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 类名称: LoginController
 * 类描述: 与微信对接登陆验证
 *
 * @author RonnieXu
 * 创建时间:2017年12月5日上午10:52:13
 */
@Slf4j
@RestController
@Api(tags = "接入验证接口")
@RequestMapping(value = "/weChart")
public class WeiXinController {

    @Autowired
    private WeiXinUserUtil weiXinUserUtil;

    @Autowired
    private MessageUtil messageUtil;

    @RequestMapping(value = "/connect", method = RequestMethod.GET)
    public String connect(@RequestParam(value = "signature") String signature,
                          @RequestParam(value = "timestamp") String timestamp,
                          @RequestParam(value = "nonce") String nonce,
                          @RequestParam(value = "echostr") String echostr) {

        log.info("-----开始校验签名-----");
        PrintWriter out = null;
        if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
            log.info("-----签名校验通过-----");
            return echostr;
        } else {
            log.info("-----校验签名失败-----");
            return null;
        }

    }

    @RequestMapping(value = "connect", method = RequestMethod.POST)
    public String dopost(HttpServletRequest request, HttpServletResponse response) throws Exception {

        response.setCharacterEncoding("utf-8");

        //将微信请求xml转为map格式,获取所需的参数
        Map<String, String> map = MessageUtil.parseXml(request);
        String ToUserName = map.get("ToUserName");
        String FromUserName = map.get("FromUserName");
        String MsgType = map.get("MsgType");
        String Content = map.get("Content");
        String Event = map.get("Event");
        String EventKey = map.get("EventKey");

        if(MessageUtil.REQ_MESSAGE_TYPE_EVENT.equals(MsgType)){

            if(MessageUtil.EVENT_TYPE_SUBSCRIBE.equals(Event)){
                String xmlString = messageUtil.subscribeForText(ToUserName,FromUserName);

                //关注了公众号,调用接口获得用户的详细信息并保存到后台
                JSONObject jsonObject = weiXinUserUtil.handdleWeixinUserInfo(FromUserName);
                log.info("获取用户的详细信息:{}",jsonObject.toJSONString());

                return xmlString;

            }else if(MessageUtil.EVENT_TYPE_UNSUBSCRIBE.equals(Event)){

                String xmlString = messageUtil.unsubscribeForText(ToUserName,FromUserName);
                return xmlString;

            }else if(MessageUtil.EVENT_TYPE_SCAN.equals(Event)){
                JSONObject jsonObject = weiXinUserUtil.handdleWeixinUserInfo(FromUserName);
                log.info("获取用户的详细信息:{}",jsonObject.toJSONString());

            }

        }

        //处理文本类型,实现输入1,回复相应的封装的内容
        if (MessageUtil.REQ_MESSAGE_TYPE_TEXT.equals(MsgType)) {
            String xmlString = messageUtil.replyForText(ToUserName,FromUserName,"你发送的是:" + Content);
            log.info(xmlString);
            return xmlString;

        }

        if (MessageUtil.REQ_MESSAGE_TYPE_IMAGE.equals(MsgType)) {

            String filePath = "C:\\Users\\RonnieXu\\Pictures\\2.jpg";
            String xmlString = messageUtil.replyForImage(ToUserName,FromUserName,filePath);
            return xmlString;
        }

        if ("1".equals(EventKey)) {

            List<Article> articles = new ArrayList<>();
            Article article = new Article();
            article.setTitle("Hello, Ronnie");
            article.setDescription("这是一条描述,这是一条描述");
            article.setPicUrl("https://www.baidu.com/img/superlogo_c4d7df0a003d3db9b65e9ef0fe6da1ec.png?where=super");
            article.setUrl("https://www.baidu.com/");
            articles.add(article);

            String xmlString = messageUtil.replyForArticles(ToUserName,FromUserName,articles);
            return xmlString;
        }

        return null;
    }

}

点击我们的微信公众号子菜单,触发我们的方法,可以看到我们收到了一个titile是“Hello,Ronnie”的图文消息

点击这个图文消息,我们就进入我们设置的URL页面,这里我们设置是百度首页,呵呵呵(捂脸中)

今天的内容到此为止,谢谢观看,下回再见!

 

如果您觉得此文有帮助,可以小小打赏一下,持续更新更有动力哟!