package com.igoxin.weixin.custom;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.igoxin.base.UrlRoute;
import com.igoxin.base.WeiXinConfig;
import com.igoxin.util.CommonUtil;
import net.sf.json.JSONObject;
/**
* 微信公众号的自定义处理Controller
*
* 整体是微信公众号的自定义操作 1.自定义回复 2.自定义界面布局
*
* @author fanglanfeng
*
*/
@Controller
@RequestMapping(UrlRoute.WEIXIN)
public class CustomController {
// 解析微信传递过来的内容,并处理需要返回的数据
public String analyticalWechatMag(String xml) {
/** 解析xml数据 */
ReceiveXmlEntity xmlEntity = new ReceiveXmlProcess().getMsgEntity(xml);
/** 回复内容 */
String result = "直接在公众号内留言即可,我们会第一时间为您处理留言格式为:订单号 + 收货人姓名 + 手机号码 + 问题";// "详情请咨询购信官网:http://www.igoxin.com";
String msgType = xmlEntity.getMsgType();
/*
* TODO - 后期做扩展用 // 文本消息 if
* (msgType.equals(MessageType.REQ_MESSAGE_TYPE_TEXT)) { result =
* "您发送的是文本消息!"; } // 图片消息 else if
* (msgType.equals(MessageType.REQ_MESSAGE_TYPE_IMAGE)) { result =
* "您发送的是图片消息!"; } // 地理位置消息 else if
* (msgType.equals(MessageType.REQ_MESSAGE_TYPE_LOCATION)) { result =
* "您发送的是地理位置消息!"; } // 链接消息 else if
* (msgType.equals(MessageType.REQ_MESSAGE_TYPE_LINK)) { result =
* "您发送的是链接消息!"; } // 音频消息 else if
* (msgType.equals(MessageType.REQ_MESSAGE_TYPE_VOICE)) { result =
* "您发送的是音频消息!"; }
*/
// 判断事件
if (MessageType.REQ_MESSAGE_TYPE_EVENT.endsWith(msgType)) {
// 点击了自定义菜单点击事件
if ("CLICK".endsWith(xmlEntity.getEvent())) {
if ("customerService".endsWith(xmlEntity.getEventKey())) {
result = "直接在公众号内留言即可,我们会第一时间为您处理留言格式为:订单号 + 收货人姓名 + 手机号码 + 问题";
}
// 这里是关注和取消关注
} else {
result = "客官好!终于等到您了。点击【购信拼团】,开启品质新生活。" + "【购信鲜花】现已正式上线,推出单品包月,混合花束包月,首单赠送精美条纹花瓶。"
+ "点击【购信鲜花】,同您一起open happiness1!" + "~TIPS:1.售后问题请直接联系服务号,给服务号留言即可;"
+ "或直接拨打客服电话:400-033-06122.购信拼团每日为您精挑细选15款高品质拼团商品。";
}
}
// 事件推送之外的所有处理
else {
String str = xmlEntity.getContent();
result = processingString(str);
}
System.out.println("analyticalWechatMag=====result====" + result);
return result;
}
// TODO - 回复处理 - 为了后期扩展用,单独处理
private String processingString(String str) {
String result = "";
System.out.println("WechatProcess==The content you entered is====" + str);
if (str.contains("+")) {
result = "不要着急,物流的派送时间为3天呢";
return result;
} else { // 如果没有指定的关键字,统一回复为鲜花二维码图片
result = "image";
return result;
}
}
/**
* - - 公众号消息被动回复 - -
*/
@RequestMapping(UrlRoute.WEIXIN_MESSAGE_XIAO)
@ResponseBody
public void xiaoMessage(HttpServletRequest request, HttpServletResponse response) throws IOException {
flowerMessage(request, response);
}
@RequestMapping(UrlRoute.WEIXIN_MESSAGE_FLOWER)
@ResponseBody
public void flowerMessage(HttpServletRequest request, HttpServletResponse response) throws IOException {
/** 判断是否是微信接入激活验证,只有首次接入验证时才会收到echostr参数,此时需要把它直接返回 */
String echostr = request.getParameter("echostr");
// 判断是否是第一次
if (echostr != null && echostr.length() > 1){
System.out.println("For the first time ======one====");
echostrMessageVerification(request, response);
} else {
System.out.println("For the not first time ======notOne====");
System.out.println("flowerMessage=========request==========" + request);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String openid = request.getParameter("openid");
/** 读取接收到的xml消息 */
StringBuffer sb = new StringBuffer();
InputStream is = request.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String s = "";
while ((s = br.readLine()) != null) {
sb.append(s);
}
String xml = sb.toString(); // 为接收到微信端发送过来的xml数据
// 对微信发过来的数据进行解析
String xmlString = analyticalWechatMag(xml);
//最后返回给微信的xml数据
String result = "";
// 2.1 - 拿到access_token
String appid = WeiXinConfig.APPID;
String secret = WeiXinConfig.APPSECRET;
String get_token = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid
+ "&secret=" + secret;
// 请求 token
JSONObject jsonObjectToken = CommonUtil.httpsRequest(get_token, "GET", null);
String access_token = (String) jsonObjectToken.get("access_token");
if (!xmlString.contains("image")) {
result = new WechatProcess().processWechatMagtText(xml, openid, xmlString);
}
// 统一回复为鲜花二维码图片
else {
// 2.开始正常的处理
// String url =
// "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=";
// 2.2 - 生成图片
// 二维码图片的内容
String content = "http://packsale.gocent.net/index.html#/tab/index?sharerId=" + openid;
String imagePath = "image/" + openid + ".png";
// File fileImagePath = new File(imagePath);
// if(fileImagePath.exists()){
// }
QRCodeUtils qrcode = new QRCodeUtils();
// BufferedImage bufferIamge = qrcode.qRCodeCommon(content, "png",7);
// 2.2.2这里会将图片临时存放在项目的一个目录中,可随时删除处理,由于一个图片只有5k左右,所以在现有项目中的量不是很大
qrcode.encoderQRCode(content, imagePath, "png", 7);
// 2.3 - 将生成的图片上传到微信素材中心
/**
* 上传(这里是根据项目做的临时的图片上传处理),获得media * access_token 获取到的access_token *
* imagePath 图片的位置(相对位置)
*/
// 2.3.1 - 微信返回的数据 - 这里最主要是获取到图片在微信中的 media_id,
// 因为在发送图片给用户的时候,需要media_id(在微信素材库的唯一标识),而不是图片的url(更不是二进制数据)
String jadonMedias = HttpUploadFile.uploadImage(access_token, imagePath);
jadonMedias = jadonMedias.substring(1, jadonMedias.length() - 2);
System.out.println("jadonMedias===" + jadonMedias);
String[] strings = jadonMedias.split(",");
System.out.println("strings===" + strings);
Object media = "";
Map mediasMap = new HashMap();
for (String sss : strings) {
String[] ms = sss.split(":");
ms[0] = ms[0].substring(1, ms[0].length() - 1);
ms[1] = ms[1].substring(1, ms[1].length() - 1);
System.out.println("ms[0]===" + ms[0] + "ms[1]===" + ms[1]);
if ("media_id".equals(ms[0])) {
media = ms[1];
}
mediasMap.put(ms[0], ms[1]);
}
System.out.println("mediasMap.toString() === " + mediasMap.toString());
String media_id = (String) mediasMap.get("media_id");
// Object created_at = mediasMap.get("created_at");
System.out.println("flowerMessage=====media_id========" + media);
result = new WechatProcess().processWechatMagImage(xml, openid, media_id);
}
// 2.4 - 判断用户提交的内容、触发的事件,判断处理,返回给用户对应的信息
try {
OutputStream os = response.getOutputStream();
os.write(result.getBytes("UTF-8"));
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("flowerMessage==================result" + result);
}
}
// ===================== -下面是--第一次在公众号里面配置的时候用--- ==================
/**
* - - 公众号消息被动回复 - 验证token 第一次配置的时候用 - 也可以直接将接口写在下面使用
*
*/
public void echostrMessageVerification(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String signature = request.getParameter("signature");
String echostr = request.getParameter("echostr");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
PrintWriter out = response.getWriter();
if (checkSignature(signature, timestamp, nonce)) {
System.out.println("check ok");
out.print(echostr);
}
out.close();
System.out.println("flowerMessage=========================" + request);
}
private boolean checkSignature(String signature, String timestamp, String nonce) {
String token = "xiao2016";
String[] arr = new String[] { token, timestamp, nonce };
Arrays.sort(arr);
String content = arr[0] + arr[1] + arr[2];
MessageDigest md = null;
String result = "";
try {
md = MessageDigest.getInstance("SHA-1");
byte[] date = md.digest(content.toString().getBytes());
// 将字节数组转换成字符串
result = bytesToStr(date);
System.out.println("加密后的" + result);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result != null ? (result.equals(signature.toUpperCase())) : false;
}
// 将直接数组转换成十六进制字符串
private static String bytesToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
// 将一个字节转换成16进制字符串
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] temp1 = new char[2];
temp1[0] = Digit[mByte >>> 4 & 0X0F];
temp1[1] = Digit[mByte & 0X0F];
String str = new String(temp1);
return str;
}
// ===================== -上面是:--第一次在公众号里面配置的时候用--- ==================
}