package com.gustz.dove.cli.expr.web;
import java.io.IOException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.sinovatech.fw.mvc.PtBaseController;
import com.sinovatech.rd.wcsb.cli.api.security.service.SignService;
import com.sinovatech.rd.wcsb.cpcli.api.message.service.MessageCpService;
import com.sinovatech.rd.wcsb.mpcli.api.message.service.MessageMpService;
/**
*
* TODO: 处理微信请求C
*
* @author ZHENFENG ZHANG
* @since [Jan 27, 2015]
*/
@Controller
@RequestMapping("/wechat/*")
public class WechatController extends PtBaseController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private SignService signService;
@Autowired
private MessageMpService messageMpService;
@Autowired
private MessageCpService messageCpService;
// 时间戳
private String timestamp;
// 随机数
private String nonce;
/**
* 转发订阅、服务号请求
*
* @param request
* @param response
* @throws IOException
*/
@RequestMapping("/mp/dispatcher")
public void mpDispatcher(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 填充请求的属性值 1.
timestamp = request.getParameter("timestamp"); // 时间戳
nonce = request.getParameter("nonce"); // 随机数
// 2.
String method = request.getMethod();
if ("POST".equalsIgnoreCase(method)) { // POST request
this.doMpPost(request, response, request.getParameter("encrypt_type"));
} else if ("GET".equalsIgnoreCase(method)) { // GET request
this.doMpGet(request, response);
} else {
logger.warn("接收微信订阅、服务号的请求不是GET、POST方式 method: {}\n", method);
}
}
/**
* 验证订阅、服务号签名
*
* <pre>
* 通过检验signature对请求进行校验,若校验成功则原样返回echostr,否则接入失败。
* </pre>
* @param request
* @param response
*/
private void doMpGet(HttpServletRequest request, HttpServletResponse response) {
try {
String signature = request.getParameter("signature"); // 接入的加密签名
// 验证签名
if (signService.checkMpSign(signature, this.timestamp, this.nonce)) {
// 随机字符串
response.getWriter().write(request.getParameter("echostr"));
}
} catch (IOException e) {
logger.error("验证订阅、服务号签名失败(输出随机字符串时) \n {}", e);
}
}
/**
* 接收订阅、服务号的消息
*
* <pre>
* 1、直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)
* 2、直接回复success
* </pre>
* @param request
* @param response
* @param encryptType 加密类型
* @throws IOException
*/
private void doMpPost(HttpServletRequest request, HttpServletResponse response, String encryptType) throws IOException {
response.setCharacterEncoding(request.getCharacterEncoding());
response.setContentType("text/xml");
ServletInputStream ins = null;
try {
ins = request.getInputStream();
String postData = IOUtils.toString(ins); // 加密的消息串
String msgSignature = request.getParameter("msg_signature"); // 消息体的签名
//
response.getWriter().write(
messageMpService.dispatcherMsg(encryptType, msgSignature, this.timestamp, this.nonce, postData));
} catch (IOException e) {
logger.error("接收订阅、服务号的消息异常 \n {}", e);
} finally {
if (ins != null) {
ins.close();
}
}
}
// --------------------- 企业号 --------------------- begin
/**
* 转发企业号请求
*
* @param request
* @param response
* @throws IOException
*/
@RequestMapping("/cp/dispatcher")
public void cpDispatcher(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 填充请求的属性值 1.
timestamp = request.getParameter("timestamp"); // 时间戳
nonce = request.getParameter("nonce"); // 随机数
String msgSignature = request.getParameter("msg_signature"); // 加密签名
// 2.
String method = request.getMethod();
if ("POST".equalsIgnoreCase(method)) { // POST request
this.doCpPost(request, response, msgSignature);
} else if ("GET".equalsIgnoreCase(method)) { // GET request
this.doCpGet(request, response, msgSignature);
} else {
logger.warn("接收微信企业号的请求不是GET、POST方式 method: {}\n", method);
}
}
/**
* 验证企业号签名
*
* <pre>
* 通过检验signature对请求进行校验,若校验成功则原样返回echostr,否则接入失败。
* </pre>
* @param request
* @param response
* @param msgSignature 接入的加密签名
*/
private void doCpGet(HttpServletRequest request, HttpServletResponse response, String msgSignature) {
try {
String echoStr = request.getParameter("echostr"); // 随机字符串
// 验证签名
response.getWriter().write(signService.checkCpSign(msgSignature, this.timestamp, this.nonce, echoStr));
} catch (Exception e) {
logger.error("验证企业号签名失败(输出随机字符串时) \n {}", e);
}
}
/**
* 接收企业号的消息
*
* <pre>
* 1、直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)
* 2、直接回复success
* </pre>
* @param request
* @param response
* @param msgSignature 消息的加密签名
* @throws IOException
*/
private void doCpPost(HttpServletRequest request, HttpServletResponse response, String msgSignature) throws IOException {
response.setCharacterEncoding(request.getCharacterEncoding());
response.setContentType("text/xml");
ServletInputStream ins = null;
try {
ins = request.getInputStream();
// 加密的消息串
String postData = IOUtils.toString(ins);
response.getWriter().write(messageCpService.dispatcherMsg(msgSignature, this.timestamp, this.nonce, postData));
} catch (IOException e) {
logger.error("接收企业号的消息异常 \n {}", e);
} finally {
if (ins != null) {
ins.close();
}
}
}
}