package edu.fudan.weixin.model;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom2.Document;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import com.mongodb.BasicDBObject;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import edu.fudan.eservice.common.utils.Config;
import edu.fudan.eservice.common.utils.MongoUtil;
import edu.fudan.weixin.model.processor.MessageProcessor;
import edu.fudan.weixin.utils.WeixinMessageHelper;
/**
* 微信收到消息的处理入口
*
* @author wking
*
*/
public class ProcessWeixinMessage {
private static Log log = LogFactory.getLog(ProcessWeixinMessage.class);
private static HashMap<String, MessageProcessor> procs = init();
public static HashMap<String, MessageProcessor> init() {
HashMap<String, MessageProcessor> ret = new HashMap<String, MessageProcessor>();
String[] processors = Config.getInstance().get("weixin.processors")
.split("[;;,,]");
for (String pstr : processors) {
try {
ret.put(pstr, (MessageProcessor) (Class
.forName("edu.fudan.weixin.model.processor." + pstr)
.newInstance()));
} catch (Exception e) {
// e.printStackTrace();
log.error(e);
}
}
return ret;
}
public static void process(HttpServletRequest request,
HttpServletResponse response) {
try {
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String enctype=request.getParameter("encrypt_type");
String msgsig=request.getParameter("msg_signature");
/*
log.info("signature:"+signature);
log.info("timestamp:"+timestamp);
log.info("nonce:"+nonce);
log.info("enctype:"+enctype);
log.info("msgsig:"+msgsig);
*/
BasicDBObject obj=null;
WXBizMsgCrypt crypt=null;
Config conf=Config.getInstance();
if(enctype!=null &&enctype.equalsIgnoreCase("aes"))
{
BufferedReader rd=request.getReader();
StringBuffer reqsb=new StringBuffer();
String ln;
while((ln=rd.readLine())!=null)
{
reqsb.append(ln);
}
crypt=new WXBizMsgCrypt(conf.get("weixin.token"),conf.get("weixin.aeskey"),conf.get("weixin.appid"));
String decstr=crypt.decryptMsg(msgsig, timestamp, nonce, reqsb.toString());
obj=WeixinMessageHelper.xml2dbo(new SAXBuilder().build(new StringReader(decstr)));
//log.info(decstr);
}else if(WeixinMessageHelper.checksum(signature, timestamp, nonce)||"127.0.0.1".equals(request.getRemoteAddr()))
{
obj=WeixinMessageHelper.stream2dbo(request.getInputStream());
}
// 无消息内容,认为是接口验证
if (obj != null) {
// 将消息存入MongoDB
MongoUtil.getInstance().getDB().getCollection("Messages")
.save(obj);
log.info("Receive:" + obj.toString());
if ("voice".equalsIgnoreCase(obj.getString("MsgType"))) {
obj.put("Content", obj.get("Recognition"));
}
// 这里以后做一个可配置的队列或者栈,将不同的MessageProcesser实现实例化后处理,直到产生消息回复对象,然后直接返回
Map<String, Object> dbo = null;
String[] processors = conf
.get("weixin.processors").split("[;;,,]");
for (String pstr : processors) {
try {
MessageProcessor p = procs.get(pstr);
if (p == null) {
p = (MessageProcessor) (Class
.forName("edu.fudan.weixin.model.processor."
+ pstr).newInstance());
procs.put(pstr, p);
}
dbo = p.process(obj);
} catch (Exception e) {
// e.printStackTrace();
log.error(e);
}
if (dbo != null)
break;
}
if (dbo.size() > 0) {
dbo.put("ToUserName", obj.get("FromUserName"));
dbo.put("FromUserName", obj.get("ToUserName"));
long now=System.currentTimeMillis();
dbo.put("CreateTime",
(int) (now/ 1000));
// 回复用户
response.setCharacterEncoding("utf-8");
response.setContentType("application/xml");
Document doc=
WeixinMessageHelper.dbo2xml(dbo);
if(crypt==null)
WeixinMessageHelper.xml2stream(doc, response.getOutputStream());
else
{
String enc=crypt.encryptMsg(new XMLOutputter(Format.getPrettyFormat().setOmitDeclaration(true)).outputString(doc), Long.toString(now), nonce);
//log.info("SEND:"+enc);
response.getWriter().write(enc);
response.flushBuffer();
}
// 将回复的消息 存入MongoDB
MongoUtil.getInstance().getDB().getCollection("Messages")
.save(new BasicDBObject(dbo));
}
}
} catch (Exception e) {
log.error(e);
}
}
}