微信公众号开发之关注推送图文消息

关注/取消关注事件

用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。

微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。

关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

推送XML数据包示例:

<xml><ToUserName>< ![CDATA[toUser] ]></ToUserName><FromUserName>< ![CDATA[FromUser] ]></FromUserName><CreateTime>123456789</CreateTime><MsgType>< ![CDATA[event] ]></MsgType><Event>< ![CDATA[subscribe] ]></Event></xml>

参数说明:

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,subscribe(订阅)、unsubscribe(取消订阅)

回复图文消息

<xml><ToUserName>< ![CDATA[toUser] ]></ToUserName><FromUserName>< ![CDATA[fromUser] ]></FromUserName><CreateTime>12345678</CreateTime><MsgType>< ![CDATA[news] ]></MsgType><ArticleCount>2</ArticleCount><Articles><item><Title>< ![CDATA[title1] ]></Title> <Description>< ![CDATA[description1] ]></Description><PicUrl>< ![CDATA[picurl] ]></PicUrl><Url>< ![CDATA[url] ]></Url></item><item><Title>< ![CDATA[title] ]></Title><Description>< ![CDATA[description] ]></Description><PicUrl>< ![CDATA[picurl] ]></PicUrl><Url>< ![CDATA[url] ]></Url></item></Articles></xml>
参数 是否必须 说明
ToUserName 接收方帐号(收到的OpenID)
FromUserName 开发者微信号
CreateTime 消息创建时间 (整型)
MsgType news
ArticleCount 图文消息个数,限制为8条以内
Articles 多条图文消息信息,默认第一个item为大图,注意,如果图文数超过8,则将会无响应
Title 图文消息标题
Description 图文消息描述
PicUrl 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
Url 点击图文消息跳转链接
详细代码如下
News.java
public class News {
    private String Title;//图文标题
    private String Description;//图文描述
    private String PicUrl;//图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
    private String Url;//点击图文消息跳转链接

    public News(String title, String description, String picUrl, String url) {
        this.Title = title;
        this.Description = description;
        this.PicUrl = picUrl;
        this.Url = url;
    }
    public News(){super();}

    public String getTitle() {
        return Title;
    }

    public void setTitle(String title) {
        this.Title = title;
    }

    public String getDescription() {
        return Description;
    }

    public void setDescription(String description) {
        this.Description = description;
    }

    public String getPicUrl() {
        return PicUrl;
    }

    public void setPicUrl(String picUrl) {
        this.PicUrl = picUrl;
    }

    public String getUrl() {
        return Url;
    }

    public void setUrl(String url) {
        this.Url = url;
    }
}

NewsMessage.java

public class NewsMessage extends BaseMessage {
    private int ArticleCount;//图文消息个数,限制为8条以内
    private List<News> Articles;//多条图文消息信息,默认第一个item为大图,注意,如果图文数超过8,则将会无响应
    public NewsMessage(String toUserName, String fromUserName, Long createTime, String msgType, Integer articleCount, List<News> articles) {
        super(toUserName, fromUserName, createTime, msgType);
        this.ArticleCount = articleCount;
        this.Articles = articles;
    }

    public NewsMessage() {
        super();
    }


    public int getArticleCount() {
        return ArticleCount;
    }

    public void setArticleCount(int articleCount) {
        this.ArticleCount = articleCount;
    }

    public List<News> getArticles() {
        return Articles;
    }

    public void setArticles(List<News> articles) {
        this.Articles = articles;
    }
}

初始化图文消息:

    /**
     * 初始化图文消息
     */
    public static String initNewsMessage(String toUSerName, String fromUserName) {
        List<News> newsList = new ArrayList<News>();
        NewsMessage newsMessage = new NewsMessage();
        //组建一条图文↓ ↓ ↓
        News newsItem = new News();
        newsItem.setTitle("欢迎关注我的公众号");
        newsItem.setDescription("进行操作之前请先注册!");
        newsItem.setPicUrl(WXConstants.BASE_SERVER + "/image/wx/login_article_cover.png");
        newsItem.setUrl("https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WXConstants.APPID + "&redirect_uri=" + WXConstants.BASE_SERVER + "/wxuser/toRegister&response_type=code&scope=snsapi_base&state=BINDFACE#wechat_redirect");
        newsList.add(newsItem);
        //组装图文消息相关信息
        newsMessage.setToUserName(fromUserName);
        newsMessage.setFromUserName(toUSerName);
        newsMessage.setCreateTime(new Date().getTime());
        newsMessage.setMsgType(WXConstants.MESSAGE_NEWS);
        newsMessage.setArticles(newsList);
        newsMessage.setArticleCount(newsList.size());
        //调用newsMessageToXml将图文消息转化为XML结构并返回
        return MessageUtil.newsMessageToXml(newsMessage);
    }
    /**
     * 图文消息转XML结构方法
     */
    public static String newsMessageToXml(NewsMessage message) {
        XStream xs = new XStream();
        //由于转换后xml根节点默认为class类,需转化为<xml>
        xs.alias("xml", message.getClass());
        xs.alias("item", new News().getClass());
        return xs.toXML(message);
    }

测试关注:

@Controller
@RequestMapping("/wechat")
public class WxController {

    private final static String MEDIATYPE_CHARSET_JSON_UTF8 = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8";
    private static Logger log = LoggerFactory.getLogger(WxController.class);

    @RequestMapping(value = "/chat", method = {RequestMethod.GET, RequestMethod.POST}, produces = MEDIATYPE_CHARSET_JSON_UTF8)
    public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //如果为get请求,则为开发者模式验证
        if ("get".equals(request.getMethod().toLowerCase())) {
            doGet();//在开发者模式验证中已处理,在此省略
        } else {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();
            try {
                Map<String, String> map = MessageUtil.xmlToMap(request);
                String ToUserName = map.get("ToUserName");
                String FromUserName = map.get("FromUserName");
                request.getSession().setAttribute("openid",FromUserName);
                String CreateTime = map.get("CreateTime");
                String MsgType = map.get("MsgType");
                String message = null;
                if (MsgType.equals(WXConstants.MESSAGE_EVENT)) {
                    //从集合中,获取是哪一种事件传入
                    String eventType = map.get("Event");
                    if (eventType.equals(WXConstants.MESSAGE_SUBSCRIBE)) {
                        message = MessageUtil.initNewsMessage(ToUserName, FromUserName);
                    }
                }
                out.print(message); //返回转换后的XML字符串
            } catch (DocumentException e) {
                e.printStackTrace();
            }
            out.close();
        }
    }
}

关注测试号,弹出如下结果:


猜你喜欢

转载自blog.csdn.net/qq_23543983/article/details/80227720