Browse Source

微信第三方平台

dev_shibei_match
zxc 5 years ago
parent
commit
6c5f1a01b5
  1. 19
      epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/controller/ComponentVerifyTicketController.java
  2. 8
      epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/service/ComponentVerifyTicketService.java
  3. 79
      epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/service/impl/ComponentVerifyTicketServiceImpl.java
  4. 172
      epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/util/XmlUtil.java

19
epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/controller/ComponentVerifyTicketController.java

@ -1,11 +1,13 @@
package com.epmet.controller;
import com.epmet.constant.ModuleConstant;
import com.epmet.service.ComponentVerifyTicketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author zxc
@ -20,20 +22,11 @@ public class ComponentVerifyTicketController {
private ComponentVerifyTicketService componentVerifyTicketService;
/**
* @Description 获取验证票据
* @param timestamp
* @param nonce
* @param msgSignature
* @param postData
* @Description 获取验证票据3
* @author zxc
*/
@PostMapping(value = "/callback")
public String componentVerifyTicket(@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("msg_signature") String msgSignature,
@RequestBody String postData) {
log.info("timestamp = "+timestamp,"nonce = "+nonce,"msgSignature = "+msgSignature,"postData = "+postData);
componentVerifyTicketService.componentVerifyTicket(timestamp,nonce,msgSignature,postData);
return "success";
public String componentVerifyTicket(HttpServletRequest request, HttpServletResponse response) {
return componentVerifyTicketService.componentVerifyTicket(request,response);
}
}

8
epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/service/ComponentVerifyTicketService.java

@ -1,5 +1,6 @@
package com.epmet.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
@ -10,15 +11,10 @@ public interface ComponentVerifyTicketService {
/**
* 获得授权事件的票据
*
* @param timestamp 时间戳
* @param nonce 随机数
* @param msgSignature 消息体签名
* @param postData 消息体
* @return 如果获得只需要返回 SUCCESS
* @Author zxc
*/
void componentVerifyTicket(String timestamp,String nonce,String msgSignature,String postData);
String componentVerifyTicket(HttpServletRequest request, HttpServletResponse response);
/**
* @Description 定时获取 (令牌component_access_token)

79
epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/service/impl/ComponentVerifyTicketServiceImpl.java

@ -2,26 +2,28 @@ package com.epmet.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.client.config.utils.IOUtils;
import com.epmet.commons.tools.constant.NumConstant;
import com.epmet.commons.tools.utils.HttpClientManager;
import com.epmet.constant.ModuleConstant;
import com.epmet.constant.ThirdPlatformConstant;
import com.epmet.dao.ComponentVerifyTicketDao;
import com.epmet.dto.form.ComponentVerifyTicketFormDTO;
import com.epmet.dto.result.AuthorizationInfoResultDTO;
import com.epmet.exception.AesException;
import com.epmet.redis.RedisThird;
import com.epmet.service.ComponentVerifyTicketService;
import com.epmet.util.WXBizMsgCrypt;
import com.epmet.util.WXXmlToMapUtil;
import com.epmet.util.XmlUtil;
import com.github.pagehelper.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
@ -48,31 +50,64 @@ public class ComponentVerifyTicketServiceImpl implements ComponentVerifyTicketSe
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void componentVerifyTicket(String timeStamp,String nonce,String msgSignature,String postData) {
public String componentVerifyTicket(HttpServletRequest request, HttpServletResponse response) {
log.info(ModuleConstant.START_RECEIVE);
try {
//这个类是微信官网提供的解密类,需要用到消息校验Token 消息加密Key和服务平台appid
WXBizMsgCrypt pc = new WXBizMsgCrypt(ThirdPlatformConstant.PLATFORM_COMPONENT_TOKEN, ThirdPlatformConstant.PLATFORM_AES_KEY, ThirdPlatformConstant.PLATFORM_APP_ID);
String xml = pc.decryptMsg(msgSignature, timeStamp, nonce, postData);
// 将xml转为map
Map<String, String> result = WXXmlToMapUtil.xmlToMap(xml);
String componentVerifyTicket = MapUtils.getString(result, ModuleConstant.TICKET_KEY);
if (StringUtils.isNotEmpty(componentVerifyTicket)) {
// 缓存 ticket
redisThird.setComponentVerifyTicket(componentVerifyTicket);
// 存数据库
ComponentVerifyTicketFormDTO ticketFormDTO = new ComponentVerifyTicketFormDTO();
ticketFormDTO.setAppid(PLATFORM_APP_ID);
ticketFormDTO.setComponentVerifyTicket(componentVerifyTicket);
ticketDao.insertComponentVerifyTicket(ticketFormDTO);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 微信加密签名
String msgSignature = request.getParameter("msg_signature");
// 时间戳
String timeStamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 从请求中读取整个post数据
InputStream inputStream;
String postData = null;
inputStream = request.getInputStream();
postData= IOUtils.toString(inputStream, "UTF-8");
//从XML中获取<Encrypt></Encrypt>标签内的密文文本
String encrypt = XmlUtil.toXml(postData);
log.info("Encrypt:"+encrypt);
//格式化密文文本,否则没有<ToUserName>标签,会解密失败,参考官方的加解密代码JAVA版本
String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";
String fromXML = String.format(format, encrypt);
String msg = ""; //解密后的明文
WXBizMsgCrypt wxcpt;
if(StringUtil.isEmpty(encrypt)) {
msg = fromXML;
} else {
log.error(ModuleConstant.ERROR_TICKET);
throw new RuntimeException(ModuleConstant.ERROR_TICKET);
wxcpt = new WXBizMsgCrypt(PLATFORM_COMPONENT_TOKEN,PLATFORM_AES_KEY, PLATFORM_APP_ID);
// 解密消息
msg = wxcpt.decryptMsg(msgSignature, timeStamp, nonce, fromXML);
}
} catch (AesException e) {
e.printStackTrace();
log.info("msg:"+msg);
// 将xml转为map
Map<String, String> result = WXXmlToMapUtil.xmlToMap(msg);
String infotype = result.get("InfoType"); //获取infotype,注:微信开放平台文档中标明固定为:"component_verify_ticket",但参考其他代码,还包含authorized???
log.info(infotype);
switch (infotype){
case "component_verify_ticket": //验证票据
String ComponentVerifyTicket = result.get("ComponentVerifyTicket");
// 缓存 ticket
redisThird.setComponentVerifyTicket(ComponentVerifyTicket);
// 存数据库
ComponentVerifyTicketFormDTO ticketFormDTO = new ComponentVerifyTicketFormDTO();
ticketFormDTO.setAppid(PLATFORM_APP_ID);
ticketFormDTO.setComponentVerifyTicket(ComponentVerifyTicket);
ticketDao.insertComponentVerifyTicket(ticketFormDTO);
log.info("component_verify_ticket:"+ComponentVerifyTicket);
break;
case "unauthorized"://用户取消授权
return "";
}
} catch (Exception e) {
log.error(e.getMessage());
return "";
}
log.info(ModuleConstant.END_TICKET);
return "success";
}
/**

172
epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/util/XmlUtil.java

@ -0,0 +1,172 @@
package com.epmet.util;
import com.google.common.collect.Lists;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.CompactWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class XmlUtil {
/**
* 转换不带CDDATA的XML
*
* @return
* @
*/
private static XStream getXStream() {
// 实例化XStream基本对象
XStream xstream = new XStream(new DomDriver(StandardCharsets.UTF_8.name(), new NoNameCoder() {
// 不对特殊字符进行转换,避免出现重命名字段时的“双下划线”
@Override
public String encodeNode(String name) {
return name;
}
}));
// 忽视XML与JAVABEAN转换时,XML中的字段在JAVABEAN中不存在的部分
xstream.ignoreUnknownElements();
return xstream;
}
/**
* 转换带CDDATA的XML
*
* @return
* @
*/
private static XStream getXStreamWithCData(List<String> ignoreCDATA) {
// 实例化XStream扩展对象
XStream xstream = new XStream(new XppDriver() {
// 扩展xstream,使其支持CDATA块
@Override
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
boolean cdata = true;
// 不对特殊字符进行转换,避免出现重命名字段时的“双下划线”
@Override
public String encodeNode(String name) {
if(!ignoreCDATA.isEmpty()){
for(String str:ignoreCDATA){
if(str.equals(name)){
cdata=false;
return name;
}
}
}
cdata=true;
return name;
}
// 对xml节点的转换都增加CDATA标记
@Override
protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
// 忽视XML与JAVABEAN转换时,XML中的字段在JAVABEAN中不存在的部分
xstream.ignoreUnknownElements();
return xstream;
}
/**
* 以压缩的方式输出XML
*
* @param obj
* @return
*/
public static String toCompressXml(Object obj) {
XStream xstream = getXStream();
StringWriter sw = new StringWriter();
// 识别obj类中的注解
xstream.processAnnotations(obj.getClass());
// 设置JavaBean的类别名
xstream.aliasType("xml", obj.getClass());
xstream.marshal(obj, new CompactWriter(sw));
return sw.toString();
}
/**
* 以格式化的方式输出XML
*
* @param obj
* @return
*/
public static String toXml(Object obj) {
XStream xstream = getXStream();
// 识别obj类中的注解
xstream.processAnnotations(obj.getClass());
// 设置JavaBean的类别名
xstream.aliasType("xml", obj.getClass());
return xstream.toXML(obj);
}
/**
* 转换成JavaBean
*
* @param xmlStr
* @param cls
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T toBean(String xmlStr, Class<T> cls) {
XStream xstream = getXStream();
// 识别cls类中的注解
xstream.processAnnotations(cls);
// 设置JavaBean的类别名
xstream.aliasType("xml", cls);
T t = (T) xstream.fromXML(xmlStr);
return t;
}
/**
* 以格式化的方式输出XML
*
* @param obj
* @return
*/
public static String toXmlWithCData(Object obj,List<String> ignoreCDAA) {
XStream xstream = getXStreamWithCData(ignoreCDAA);
// 识别obj类中的注解
xstream.processAnnotations(obj.getClass());
// 设置JavaBean的类别名
xstream.aliasType("xml", obj.getClass());
return xstream.toXML(obj);
}
/**
* 转换成JavaBean
*
* @param xmlStr
* @param cls
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T toBeanWithCData(String xmlStr, Class<T> cls) {
XStream xstream = getXStreamWithCData(null);
// 识别cls类中的注解
xstream.processAnnotations(cls);
// 设置JavaBean的类别名
xstream.alias("xml", cls);
T t = (T) xstream.fromXML(xmlStr);
return t;
}
}
Loading…
Cancel
Save