package edu.fudan.weixin.utils; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.jdom2.CDATA; import org.jdom2.Content; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; import com.mongodb.BasicDBObject; import com.mongodb.util.JSON; import edu.fudan.eservice.common.utils.CommonUtil; import edu.fudan.eservice.common.utils.Config; import edu.fudan.eservice.common.utils.EncodeHelper; /** * 微信XML消息与MongoDB的数据对象的互相转换 * * @author wking * */ public class WeixinMessageHelper { /** * 将微信XML转换化DBO * * @param xml * MESSAGE XML * @return DBO */ public static BasicDBObject xml2dbo(Document xml) { if (xml == null) return null; List<Element> params = xml.getRootElement().getChildren(); if (params == null || params.size() <= 0) return null; //log.info(xml2str(xml)); BasicDBObject dbo = new BasicDBObject(); for (Element e : params) { List<Content> cs = e.getContent(); if (cs != null && cs.size() > 0) { for (Content c : cs) { if (c != null) { Object o = null; switch (c.getCType()) { case Text: case CDATA: o = c.getValue(); break; default:; } if (!CommonUtil.isEmpty(o)) { if (e.getName().equalsIgnoreCase("createtime")) o = Integer.parseInt(o.toString()); dbo.append(e.getName(), o); } } } } } return dbo; } /** * 从InputStream中的XML文档生成DBO * * @param input * @return * @throws JDOMException * @throws IOException */ public static BasicDBObject stream2dbo(InputStream input) throws JDOMException, IOException { return xml2dbo(new SAXBuilder().build(input)); } /** * 将DBO转换为xml消息 * * @param dbo * @return */ public static Document dbo2xml(Map<String, Object> message) { return new Document(msg2xml(message, "xml")); } /** * 将Message转换为xml节点 * * @param message * @param rootname * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static Element msg2xml(Object message, String rootname) { Element root = new Element(rootname); if (message instanceof Map) for (Entry<String, Object> entry : ((Map<String, Object>) message) .entrySet()) { if (!CommonUtil.isEmpty(entry.getValue())) { setValue(root, entry.getValue(), entry.getKey()); } } if (message instanceof List) for (Object o : (List) message) { if (!CommonUtil.isEmpty(o)) { setValue(root, o, "item"); } } return root; } private static void setValue(Element e, Object v, String name) { if (v instanceof Map) e.addContent(msg2xml(v, name)); else if (v instanceof List) e.addContent(msg2xml(v, name)); else { Element n = new Element(name); if (v instanceof Number || v instanceof Boolean) n.addContent(String.valueOf(v)); else { n.addContent(new CDATA(String.valueOf(v))); } e.addContent(n); } } /** * XML Document对象转换为pretty样式的字符串,当doc为null时返回空字符串 * * @param doc * @return */ public static String xml2str(Document doc) { if (doc == null) return ""; return new XMLOutputter(Format.getPrettyFormat().setOmitDeclaration(true)).outputString(doc); } /** * 将XML Document对象写到输出流 * * @param doc * @param out * @throws IOException */ public static void xml2stream(Document doc, OutputStream out) throws IOException { if (doc != null) new XMLOutputter(Format.getPrettyFormat().setOmitDeclaration(true)) .output(doc, out); } /** * 检测请求是否来自微信服务器 * * @param signature * @param timestamp * @param nonce * @return */ public static boolean checksum(String signature, String timestamp, String nonce) { try { String[] strs = new String[] { Config.getInstance().get("weixin.token"), timestamp, nonce }; Arrays.sort(strs); StringBuilder sb = new StringBuilder(); for (String s : strs) { sb.append(s); } String hash = EncodeHelper.digest(sb.toString(), "SHA1"); if (hash.equalsIgnoreCase(signature)) return true; } catch (Exception e) { } return false; } /** * 将消息转换为JSON字串,用于向微信服务器接口提交请求 * * @param message * @return */ public static String msg2jsonstr(Map<String, Object> message) { return JSON.serialize(message); } /** * 将为JSON字串格式的消息转换成DBO对象,用于存储到数据库 * * @param JSON * String * @return */ @SuppressWarnings("unchecked") public static Map<String, Object> jsonString2dbo(String jsonstr) { return (Map<String, Object>) JSON.parse(jsonstr); } }