微信公众号:关注取关事件

1.需求:关注取关发送用户消息

微信操作事件回调

回调地址需要在微信公众号配置

(1)controller

 /**
     * 微信操作事件回调
     * @param request
     * @return
     */
    @RequestMapping(value = "/check", method = {RequestMethod.GET,RequestMethod.POST})
    public void check(HttpServletRequest request,HttpServletResponse resp) throws Exception {
        // xml请求解析
        Map<String, String> requestMap = MessageUtil.xmlToMap(request);
        log.info("xml请求解析返回参数,{}", requestMap);
        String messageRequest = WechatService.newMessageRequest(requestMap);
        if (messageRequest!= null){
            resp.getWriter().write(messageRequest);
        }
    }

(2)微信回调操作

package com.ty.message.wxMsg;
import com.ty.common.utils.CryptoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.Map;

@Slf4j
@Service
public class WechatService {

    public static String newMessageRequest(Map<String, String> requestMap) {
       String respMessage = null;
       try {
           // 发送方帐号(open_id)
           String fromUserName = requestMap.get("FromUserName");
           // 公众帐号
           String toUserName = requestMap.get("ToUserName");
           // 消息类型
           String msgType = requestMap.get("MsgType");
           // 消息内容
           String content = requestMap.get("Content");
           log.info("FromUserName is:" + fromUserName + ", ToUserName is:" + toUserName + ", MsgType is:" + msgType );
           // 文本消息
           if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
               //这里根据关键字执行相应的逻辑
               //自动回复
               if (content.equals(contentName)){
                   String contentText = menuText(unionId);
                   respMessage = initText(toUserName, fromUserName, contentText);
               }
           }
           // 事件推送
           else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
               String eventType = requestMap.get("Event");// 事件类型
               // 订阅
               if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
                   //文本消息
                   String contentText = menuText();
                   respMessage = initText(toUserName, fromUserName, contentText);
               }
               // 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息
               // 取消订阅
               else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
                   log.error("用户已取关");
               }
           }
       }catch (Exception e){
           e.printStackTrace();
       }
        return respMessage;
    }

    /**
     * 发送用户信息
     * @param toUserName
     * @param fromUserName
     * @param content
     * @return
     */
    public static String initText(String toUserName, String fromUserName, String content){
        WechatOutTextMsg text = new WechatOutTextMsg();
        text.setFromUserName(toUserName);
        text.setToUserName(fromUserName);
        text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
        text.setCreateTime(new Date().getTime());
        text.setContent(content);
        return MessageUtil.toXml(text);
    }

    /**
     * 发送内容
     * @return
     */
    public static String menuText(){
        StringBuffer sb = new StringBuffer();
        sb.append("您好!欢迎关注~");
        return sb.toString();
    }

}

(3)工具类

package com.ty.message.wxMsg;
import com.thoughtworks.xstream.XStream;
import com.ty.common.utils.http.HttpHelper;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.DocumentException;
import org.json.XML;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;

@Slf4j
public class MessageUtil {

    /**
     * 返回消息类型:文本
     */
    public static final String RESP_MESSAGE_TYPE_TEXT = "text";

    /**
     * 返回消息类型:音乐
     */
    public static final String RESP_MESSAGE_TYPE_MUSIC = "music";

    /**
     * 返回消息类型:图文
     */
    public static final String RESP_MESSAGE_TYPE_NEWS = "news";

    /**
     * 请求消息类型:文本
     */
    public static final String REQ_MESSAGE_TYPE_TEXT = "text";

    /**
     * 请求消息类型:图片
     */
    public static final String REQ_MESSAGE_TYPE_IMAGE = "image";

    /**
     * 请求消息类型:链接
     */
    public static final String REQ_MESSAGE_TYPE_LINK = "link";

    /**
     * 请求消息类型:地理位置
     */
    public static final String REQ_MESSAGE_TYPE_LOCATION = "location";

    /**
     * 请求消息类型:音频
     */
    public static final String REQ_MESSAGE_TYPE_VOICE = "voice";

    /**
     * 请求消息类型:推送
     */
    public static final String REQ_MESSAGE_TYPE_EVENT = "event";
    /**
     * 事件类型:subscribe(订阅)
     */
    public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

    /**
     * 事件类型:unsubscribe(取消订阅)
     */
    public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

    /**
     * 事件类型:CLICK(自定义菜单点击事件)
     */
    public static final String EVENT_TYPE_CLICK = "CLICK";

    private static final XStream xStream = XStreamFactory.getXStream();

    /*
     *
     * 将xml转换成map集合
     *
     * */
    public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{
        String wxRestStr = HttpHelper.getBodyString(request);
        log.info("微信回调报文:{}",wxRestStr);
        org.json.JSONObject jsonObject = XML.toJSONObject(wxRestStr);
        Map<String, Object> wxMap = jsonObject.toMap();
        Map<String, String> map = (Map<String, String>) wxMap.get("xml");
        return map;
    }

    /**
     * 对象转xml
     * @param obj 对象
     * @return
     */
    public static String toXml(Object obj) {
        xStream.processAnnotations(obj.getClass());
        return xStream.toXML(obj);
    }
}

(4)转xml实体类

package com.ty.message.wxMsg;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import java.io.Serializable;

@Data
@XStreamAlias("xml")
public class WechatOutTextMsg implements Serializable {

    private static final long serialVersionUID = -1883441132514476532L;
    /**
     * 接收方账号(收到的OpenID)
     */
    @XStreamAlias("ToUserName")
    @XStreamCDATA
    private String toUserName;
    /**
     * 开发者微信号
     */
    @XStreamAlias("FromUserName")
    @XStreamCDATA
    private String fromUserName;
    /**
     * 消息创建时间(整形)
     */
    @XStreamAlias("CreateTime")
    private Long createTime;
    /**
     * 消息类型
     */
    @XStreamAlias("MsgType")
    @XStreamCDATA
    private String msgType;
    /**
     * 回复的消息内容
     */
    @XStreamAlias("Content")
    @XStreamCDATA
    private String content;

}

(5)XStreamCDATA

package com.ty.message.wxMsg;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @program: ty
 * @description:
 * @author: HQY
 * @create: 2021-06-09 13:05
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface XStreamCDATA {

}

(6)实体转xml[data]

package com.ty.message.wxMsg;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.naming.NameCoder;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDomDriver;
import java.io.Writer;
import java.lang.reflect.Field;


public class XStreamFactory {
    public static final String CDATA_PREFIX = "<![CDATA[";
    public static final String CDATA_SUFFIX = "]]>";
    public static XStream getXStream() {
        final NameCoder nameCoder = new NoNameCoder();
        XStream xStream = new XStream(new XppDomDriver(nameCoder) {
            @Override
            public HierarchicalStreamWriter createWriter(Writer out) {
                return new PrettyPrintWriter(out, nameCoder) {
                    boolean cdataFlag = false;
                    Class<?> targetClass = null;
                    @Override
                    public void startNode(String name, Class clazz) {
                        super.startNode(name, clazz);
                        if (targetClass == null) {
                            targetClass = clazz;
                        }
                        cdataFlag = isCDATA(targetClass, name);
                    }
                    @Override
                    public void writeText(QuickWriter writer, String text) {
                        if (cdataFlag) {
                            writer.write(XStreamFactory.CDATA_PREFIX);
                            writer.write(text);
                            writer.write(XStreamFactory.CDATA_SUFFIX);
                        } else {
                            writer.write(text);
                        }
                    }
                };
            }
        });
        return xStream;
    }
    private static boolean isCDATA(Class<?> clazz, String fieldAlias) {
        //检查类本身
        boolean cdataFlag = isExistCDATA(clazz, fieldAlias);
        if (cdataFlag) {
            return cdataFlag;
        }
        //继续检查父类
        Class<?> superClazz = clazz.getSuperclass();
        while (!superClazz.equals(Object.class)) {
            cdataFlag = isExistCDATA(superClazz, fieldAlias);
            if (cdataFlag) {
                return cdataFlag;
            }
            superClazz = superClazz.getClass().getSuperclass();
        }
        return false;
    }
    /**
     * 检查是否有 @XStreamCDATA 注解
     * @param clazz clazz
     * @param fieldAlias fieldAlias
     * @return
     */
    private static boolean isExistCDATA(Class<?> clazz, String fieldAlias) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.getAnnotation(XStreamCDATA.class) != null) {
                XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class);
                if (xStreamAlias != null && fieldAlias.equals(xStreamAlias.value())) {
                    return true;
                } else {
                    if (fieldAlias.equals(field.getName())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值