微信公众平台_发送被动响应消息接口 实体类转换为xml工具类


首先,微信公众平台发送被动响应消息接口官网wiki:

http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF


如,回复文本消息必须是如下格式:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>

回复图片消息格式:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
   <MediaId><![CDATA[media_id]]></MediaId>
</Image>
</xml>


不得不吐槽下,这个回复消息格式不是json格式也罢,甚至连xml格式都不是。用传统的JOX(PS:不想用DOM)是无法将实体类直接转成这个API要求的xml格式的,吐槽归吐槽,但人家TX店大欺客,你不用也得用。


下面讲下笔者这里的处理方法-->


首先,有一个rsp模板类:

/**
 * 被动响应消息模板基类,其他Msg类需extends其
 * 注:Msg类属性命名方式未遵循驼峰模式,因为需要和微信接口定义保持一致。
 * @author will_awoke
 * @version 2014-6-24
 * @see TemplateRspMsg
 * @since
 */
public class TemplateRspMsg
{ 

    // 响应消息时,接收方帐号(收到的OpenID)
    protected String ToUserName;

    // 响应消息时,开发者微信号(公众平台原始ID)
    protected String FromUserName;

    // 消息创建时间  Long型
    protected String CreateTime;

    // 消息类型
    protected String MsgType;

    /**
     * 构造器
     */
    public TemplateRspMsg()
    {

    }

    //setter getter
    
    public String getMsgType()
    {
        return MsgType;
    }

    //protected for msgTypeSetter
    protected void setMsgType(String msgType)
    {
        MsgType = msgType;
    }

    public String getFromUserName()
    {
        return FromUserName;
    }

    public void setFromUserName(String fromUserName)
    {
        FromUserName = fromUserName;
    }

    public String getToUserName()
    {
        return ToUserName;
    }

    public void setToUserName(String toUserName)
    {
        ToUserName = toUserName;
    }

    public String getCreateTime()
    {
        return CreateTime;
    }

    public void setCreateTime(String createTime)
    {
        CreateTime = createTime;
    }

}

文本类回复消息类,extends 模板类:

/**
 * 文本类响应消息 MsgType=text
 * @author will_awoke
 * @version 2014-6-24
 * @see TextRspMsg
 * @since
 */
public class TextRspMsg extends TemplateRspMsg
{    

    //文本消息内容
    private String Content;

    /**
     * 构造器,同时初始化MsgType
     */
    public TextRspMsg()
    {
        setMsgType("text");
    }

    @Override
    public String toString()
    {
        StringBuilder builder = new StringBuilder();
        builder.append("TextRspMsg [Content=").append(Content).append(",ToUserName=").append(
            ToUserName).append(",FromUserName=").append(FromUserName).append(",CreateTime=").append(
            CreateTime).append(",MsgType=").append(MsgType).append("]");
        return builder.toString();
    }

    //setter getter

    public String getContent()
    {
        return Content;
    }

    public void setContent(String content)
    {
        Content = content;
    }

}


图片类回复消息类,extends 模板类:

import java.util.HashMap;
import java.util.Map;


/**
 * 图片类型客服消息
 * @author will_awoke
 * @version 2014-6-25
 * @see ImageRspMsg
 * @since
 */
public class ImageRspMsg extends TemplateRspMsg
{
  
    //用于拼装形如  <Image><MediaId><![CDATA[media_id]]></MediaId></Image>专有属性
    private Map<String,Object> Image;

    /**
     * 构造器,同时初始化MsgType
     */
    public ImageRspMsg()
    {
        setMsgType("image");
    }

    /**
     * 格式化成符合微信API要求的实体
     * @param ToUserName 普通用户openid
     * @param FromUserName  开发者微信号(公众平台原始ID)
     * @param MediaId  通过上传多媒体文件,得到的id。
     * @return 符合API要求的实体
     * @see
     */
    public ImageRspMsg xmlFormatBean(String ToUserName,String FromUserName,String MediaId)
    {
        this.setToUserName(ToUserName);
        this.setFromUserName(FromUserName);
        //由于微信服务端需要的时间整形是以秒为单位的,故需要除以1000L
        this.setCreateTime(String.valueOf(System.currentTimeMillis() / 1000L));
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("MediaId",MediaId);
        this.setImage(map);
        return this;
    }

    //setter getter

    public Map<String,Object> getImage()
    {
        return Image;
    }

    public void setImage(Map<String,Object> image)
    {
        Image = image;
    }

}


下面是核心工具类:

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.xx.wechat.model.rsp.ImageRspMsg;
import com.xx.wechat.model.rsp.TextRspMsg;


/**
 * 
 * 将被动响应消息实体类转换成符合微信接口API要求的xml格式。
 * 如:
 * <xml>
 * <ToUserName><![CDATA[toUser]]></ToUserName>
 * <FromUserName><![CDATA[fromUser]]></FromUserName>
 * <CreateTime>12345678</CreateTime>
 * <MsgType><![CDATA[image]]></MsgType>
 * <Image>
 *   <MediaId><![CDATA[media_id]]></MediaId>
 * </Image>
 * </xml>
 * 注意:根节点是xml而非实体名,且无xml头文件,每个节点的首字母是大写。
 * 而此功能是JOX转换不具有的,故造此轮子工具类
 * 另请参见:wechat.model.rsp包
 * 
 * @author will_awoke
 * @version 2014-6-25
 * @see Bean2WeChatXml
 * @since
 */
public class Bean2WeChatXml
{

    /**
     * 将实体类转换成符合微信接口API要求的xml格式
     * @param obj
     * @return
     * @throws IllegalArgumentException
     * @throws IllegalAccessException 
     * @see
     */
    @SuppressWarnings("rawtypes")
    public static String beanToXML(Object obj)
        throws IllegalArgumentException,IllegalAccessException
    {
        StringBuffer sb = new StringBuffer("<xml>\n");

        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();

        //父类Class
        Class superClass = clazz.getSuperclass();
        Field[] superFields = superClass.getDeclaredFields();

        //拼装自身的字段和字段值
        String fieldName = null;
        Object mapObj = null;
        for (Field field : fields)
        {
            field.setAccessible(true);
            fieldName = field.getName();//获得字段名
            mapObj = field.get(obj);//获得字段值

            //如果字段是Map类型,形如ImageRspMsg类中Map字段
            if (mapObj instanceof Map)
            {
                //迭代map集合
                StringBuffer mapFieldValue = new StringBuffer("");
                String key = "";
                Map castMap = (Map)mapObj;
                Iterator iterator = castMap.keySet().iterator();
                while (iterator.hasNext())
                {
                    //迭代
                    key = (String)iterator.next();                   
                    mapFieldValue.append("<").append(key).append(">");
          //调用value的toString方法
          mapFieldValue.append("<![CDATA[").append(castMap.get(key).toString()).append("]]>");
          mapFieldValue.append("</").append(key).append(">\n");
                }
                sb.append("<").append(fieldName).append(">\n");
        sb.append(mapFieldValue); //map集合内的迭代结果,勿加CDATA
        sb.append("</").append(fieldName).append(">\n");
            }
            //字段非Map类型,则按照String类型处理(获得value时直接调用toString方法)
            else
            {
                sb.append("<").append(fieldName).append(">");
        sb.append("<![CDATA[").append(mapObj.toString()).append("]]>");
        sb.append("</").append(fieldName).append(">\n");
            }
        }
        
        //拼装父类的字段和字段值
        String superFieldName = "";
        for (Field field : superFields)
        {
            field.setAccessible(true);
            superFieldName = field.getName();

            sb.append("<").append(superFieldName).append(">");
      sb.append("<![CDATA[").append(field.get(obj).toString()).append("]]>");
      sb.append("</").append(superFieldName).append(">\n");
            
        }
        sb.append("</xml>");

        return sb.toString();
    }

    /**  
     * @param args 
     * @see 
     */
    public static void main(String[] args)
        throws Exception
    {
        TextRspMsg rsp = new TextRspMsg();
        rsp.setToUserName("ToUserName");
        rsp.setFromUserName("FromUserName");
        rsp.setCreateTime(String.valueOf(System.currentTimeMillis()));
        rsp.setContent("您好!welcome to subscribe will's public ...");

        System.out.println(JoxUtil.beanToXML(rsp));
        System.out.println(beanToXML(rsp));

        ImageRspMsg image = new ImageRspMsg();
        image.xmlFormatBean("ToUserName","FromUserName","MediaId");
        System.out.println("\n" + beanToXML(image));
    }

}

这个是console输出结果:

<?xml version="1.0" encoding="UTF-8"?>
<TextRspMsg>
<content>您好!welcome to subscribe will's public ...</content>
<createTime>1404286867859</createTime>
<fromUserName>FromUserName</fromUserName>
<msgType>text</msgType>
<toUserName>ToUserName</toUserName>
</TextRspMsg>

<xml>
<Content><![CDATA[您好!welcome to subscribe will's public ...]]></Content>
<ToUserName><![CDATA[ToUserName]]></ToUserName>
<FromUserName><![CDATA[FromUserName]]></FromUserName>
<CreateTime><![CDATA[1404286867859]]></CreateTime>
<MsgType><![CDATA[text]]></MsgType>
</xml>

<xml>
<Image>
<MediaId><![CDATA[MediaId]]></MediaId>
</Image>
<ToUserName><![CDATA[ToUserName]]></ToUserName>
<FromUserName><![CDATA[FromUserName]]></FromUserName>
<CreateTime><![CDATA[1404286868]]></CreateTime>
<MsgType><![CDATA[image]]></MsgType>
</xml>

可以看到传统的JOX转换来的xml是有header部分的,且多了个TextRspMsg节点,子节点都是小写(这里,JOX内部在转换为xml的时候会遵循Java命名格式,将所有的属性的首字符改成小写,所以,即使把实体类的字段属性故意写成大写也不行。)而用Bean2WeChatXml工具类转化来的xml就能完全满足API格式要求了,这也就是造这个轮子的意义所在。


完毕。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念
xml文件介绍及使用
xml编程(一)-xml语法
XML文件结构和基本语法
第2章 包装类
XML入门的常见问题(二)
Java对象的强、软、弱和虚引用
JS解析XML文件和XML字符串详解
java中枚举的详细使用介绍
了解Xml格式
XML入门的常见问题(四)
深入SQLite多线程的使用总结详解
PlayFramework完整实现一个APP(一)
XML和YAML的使用方法
XML轻松学习总节篇