package cc.mrbird.febs.pay.util;
import cc.mrbird.febs.common.utils.MallUtils;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.rabbit.producter.AgentProducer;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.dom4j.io.SAXReader;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import org.dom4j.Document;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.io.InputStream;
import java.util.*;
/**
*
* 微信消息工具类:事件通知、自动回复、
*
*
* @author shenshao
*/
@Service(value="wechatEventUtil")
public class WechatEventUtil {
@Autowired
private AgentProducer agentProducer;
private static Logger log = LoggerFactory.getLogger(WechatEventUtil.class);
/**
* 公众号《事件通知》服务器校验
*
* @param req 请求
* @return 校验结果
*/
public String verification(HttpServletRequest req, String wechatToken) {
// 接收微信服务器发送请求时传递过来的参数
String signature = req.getParameter("signature");
String timestamp = req.getParameter("timestamp");
String nonce = req.getParameter("nonce");
// 将token、timestamp、nonce三个参数进行字典序排序,并拼接为一个字符串
String sortStr = sort(wechatToken, timestamp, nonce);
// 字符串进行shal加密
String mySignature = shal(sortStr);
// 校验微信服务器传递过来的签名 和 加密后的字符串是否一致, 若一致则签名通过
if (!"".equals(signature) && !"".equals(mySignature) && signature.equals(mySignature)) {
log.info("-----签名校验通过-----");
return req.getParameter("echostr");
} else {
log.error("-----校验签名失败-----");
return "";
}
}
/**
* 消息事件监控:关注、取消关注等事件
* @param req
* @return
*/
public String messageEvent(HttpServletRequest req) {
String result = null;
Map map = xmlToMap(req);
String fromUserName = map.get("FromUserName");
String toUserName = map.get("ToUserName");
String msgType = map.get("MsgType");
String content = map.get("Content");
String eventType = map.get("Event");
log.info("事件处理:event:{}、msgType:{}、toUserName:{}、fromUserName:{}", eventType, msgType, toUserName, fromUserName);
if ("event".equals(msgType)) {
if ("subscribe".equals(eventType)) {
result = imgTextMsg(toUserName, fromUserName, "欢迎光临", "欢迎光临【药王谷铺子】,点击左下角【药王谷铺子】-【商城】,进入商城。", "图片地址", "点击后跳转的路径");
log.info("新增关注事件:toUserName{}、fromUserName{}", toUserName, fromUserName);
StringBuffer stringBuffer = new StringBuffer();
if(map.containsKey("EventKey")){
/**
* 扫带参数二维码
*/
String eventKey = map.get("EventKey");
if(StrUtil.isNotEmpty(eventKey)){
stringBuffer.append(eventKey);
stringBuffer.append("-");
stringBuffer.append(fromUserName);
agentProducer.sendMemberSubScanMsg(stringBuffer.toString());
}
}
/**
* 普通关注事件
*/
agentProducer.sendMemberSubMsg(fromUserName);
} else if ("unsubscribe".equals(eventType)) {
log.info("取消关注事件:toUserName{}、fromUserName{}", toUserName, fromUserName);
}
}
return result;
}
/**
* 组装图文消息(懒得封装对象转XML方法,直接字符串拼装,大伙勿喷)
* @param toUserName 开发者微信号
* @param fromUserName 接收人openId
* @param title 图文消息上的备注
* @param description 图文消息上的备注
* @param picUrl 图文消息上的图片
* @param url 点击图文消息跳转的路径
* @return
*/
public static String imgTextMsg(String toUserName, String fromUserName, String title, String description, String picUrl, String url){
return ""
+ ""
+ ""
+ ""+new Date().getTime()+""
+ ""
+ "1"
+ ""
+ "- "
+ ""
+ ""
+ ""
+ ""
+ "
"
+ ""
+ "";
}
/**
* 解析微信发来的请求(XML)
*
* @param request 请求
* @return map
* @throws Exception 异常
*/
public static Map xmlToMap(HttpServletRequest request) {
// 将解析结果存储在HashMap中
Map map = new HashMap<>(16);
// 从request中取得输入流
try (InputStream inputStream = request.getInputStream()) {
System.out.println("获取输入流");
// 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List elementList = root.elements();
// 遍历所有子节点
for (Element e : elementList) {
System.out.println(e.getName() + " | " + e.getText());
map.put(e.getName(), e.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
/**
* 参数排序
*
* @param token 服务器配置,自定义的Token
* @param timestamp timestamp
* @param nonce nonce
* @return 排序后拼接字符串
*/
public static String sort(String token, String timestamp, String nonce) {
String[] strArray = {token, timestamp, nonce};
Arrays.sort(strArray);
StringBuilder sb = new StringBuilder();
for (String str : strArray) {
sb.append(str);
}
return sb.toString();
}
/**
* 字符串进行shal加密
*
* @param str 字符串
* @return 密文
*/
public static String shal(String str) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(str.getBytes());
byte messageDigest[] = digest.digest();
StringBuilder hexString = new StringBuilder();
// 字节数组转换为 十六进制 数
for (int i = 0; i < messageDigest.length; i++) {
String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
@Autowired
RedisUtils redisUtils;
/**
* 获取ticket
*
* @param qrCodeParam
* @return
*/
public String getTicket(String qrCodeParam) {
RestTemplate restTemplate = new RestTemplate();
String ticket = null;
// 拼接请求地址
String CREATE_QRCODE_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
String requestUrl = CREATE_QRCODE_URL.replace("TOKEN", "70_ECdQaX-QtNXZP9ugU_JEJGRYEADWrlQZNYrT2I2IRHsx6hx4_O8RY4VasWI97_ixia8vANTdnNRI_cT00toK7CX98513sQI8535eTFw3b-VQChEFZrRqTfNPdSoGYXgAIAVNM");
// String requestUrl = CREATE_QRCODE_URL.replace("TOKEN", redisUtils.get(WechatConfigure.WX_ACCESS_TOKEN_REDIS_KEY).toString());
// 创建临时带参二维码
JSONObject jsonObject = restTemplate.postForObject(requestUrl,
"{\"expire_seconds\": 604800, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": "+qrCodeParam+"}}}",
JSONObject.class);
// JSONObject jsonObject = HttpsUtil.request(requestUrl, "POST", "{\"expire_seconds\": 604800, \"action_name\": \"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": 123}}}");
if (ObjectUtil.isNotEmpty(jsonObject)) {
String response = JSON.toJSONString(jsonObject);
if (!jsonObject.containsKey("errcode")) {
ticket = jsonObject.getString("ticket");
System.out.println("临时带参二维码ticket成功" + response);
} else {
log.error("临时带参二维码ticket失败:" + response);
}
}
return ticket;
}
/**
* 通过ticket换取二维码并保存二维码图片
*
* @param ticket
* @param savePath
* @return
*/
//图片上传路径
public static final String IMG_UPLOAD_PATH="/home/javaweb/webresource/ywg/h5/wxcode";
public String getQRcode(String ticket) {
String SHOW_QRCODE_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
String requestUrl = SHOW_QRCODE_URL.replace("TICKET", ticket);
String randomNum = MallUtils.getRandomNum(5);
String imgName="/user_" + randomNum + "_acode_1.jpg";
String urlPrefix="https://ywgouth.meiao.biz/wxcode";
String imgPath=IMG_UPLOAD_PATH+imgName;
if(!FileUtil.exist(imgPath)){
try {
HttpResponse execute = HttpRequest.get(requestUrl).execute();
InputStream inputStream = execute.bodyStream();
File file = new File(imgPath);
FileUtil.writeFromStream(inputStream, file);
long uploadUrl = FileUtil.size(file);
//小于10kb重新生成
if(uploadUrl<=10240){
log.error("生成微信小程序码失败:图片大小异常:{}",uploadUrl);
return null;
}
} catch (Exception e) {
log.error("生成微信小程序码失败",e);
return null;
}
}else{
//判断文件是否正常 不正常 删除
File file = new File(imgPath);
long uploadUrl = FileUtil.size(file);
if(uploadUrl<=10240){
FileUtil.del(file);
return null;
}
}
System.out.println("根据ticket换取二维码成功,路径:" + imgPath);
return urlPrefix+"/"+imgName;
}
public static void main(String[] args) {
}
}