import java.text.ParseException;
import java.text.SimpleDateFormat;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;
import com.alibaba.fastjson.JSON;
.....
/**
* 线下报文通用服务类,
* Description: 负责报文的通用服务,包括:输入输出报文(初始化报文和检测接收到的报文);检测报文签名
* @date 2017年1月6日
*/
public class OfflinePacketsService {
protected static final Logger logger = Logger.getLogger(OfflinePacketsService.class);
/**
* 解析加密请求报文并验证报文头参数
* @param requestJson
* @return EncryptRequestPackets
* @throws BussinessExceptionNeedCatch
*/
public static EncryptRequestPackets parseEncryptRequestPacketAndValidHead(String requestJson) throws BussinessExceptionNeedCatch {
EncryptRequestPackets encryptRequestPackets = JSON.toJavaObject(JSON.parseObject(requestJson), EncryptRequestPackets.class);
if (null == encryptRequestPackets || null == encryptRequestPackets.getHead() ) {
throw new BussinessExceptionNeedCatch(ErrorCode.PARA_SP_CODE_XML_IS_NULL,
GenerateMonitorDataFactory.buildErrorMonitorData(WarnBussinessTypeEnum.P_OTHER_SERVICE, null));
}
validRequestParameterHead(encryptRequestPackets.getHead());
return encryptRequestPackets;
}
/** 验证请求报文头参数 **/
private static void validRequestParameterHead(PacketsHead requestHead) throws BussinessExceptionNeedCatch {
if (requestHead instanceof RequestPacketsHead) {
RequestPacketsHead head = (RequestPacketsHead) requestHead;
if (StringUtils.isEmpty(head.getSpCode())) {
throw new BussinessExceptionNeedCatch(ErrorCode.PARA_SP_CODE_XML_IS_NULL,
GenerateMonitorDataFactory.buildErrorMonitorData(WarnBussinessTypeEnum.P_OTHER_SERVICE, null));
}
if (StringUtils.isEmpty(head.getBussinessCode()) || null == resolveBussinessType(head.getBussinessCode())) {
throw new BussinessExceptionNeedCatch(ErrorCode.SYS_UNKNOW_BUSSINESS_CODE,
GenerateMonitorDataFactory.buildErrorMonitorData(WarnBussinessTypeEnum.P_OTHER_SERVICE, null));
}
if (StringUtils.isEmpty(head.getSigned())) {
throw new BussinessExceptionNeedCatch(ErrorCode.SYS_SIGNED_ERROR,
GenerateMonitorDataFactory.buildErrorMonitorData(WarnBussinessTypeEnum.P_OTHER_SERVICE, null));
}
if (StringUtils.isEmpty(head.getVersion())) {
throw new BussinessExceptionNeedCatch(ErrorCode.RESULT_SYSTEM_VERSION_ERROR,
GenerateMonitorDataFactory.buildErrorMonitorData(WarnBussinessTypeEnum.P_OTHER_SERVICE, null));
}
if (StringUtils.isEmpty(head.getTimeStamp())) {
throw new BussinessExceptionNeedCatch(ErrorCode.SYS_TIMESTAMP_IS_NULL,
GenerateMonitorDataFactory.buildErrorMonitorData(WarnBussinessTypeEnum.P_OTHER_SERVICE, null));
}
} else {
throw new BussinessExceptionNeedCatch(ErrorCode.PARA_FORMAT_MISS,
GenerateMonitorDataFactory.buildErrorMonitorData(WarnBussinessTypeEnum.P_OTHER_SERVICE, null));
}
}
/** 解析并检验请求报文 **/
public static RequestPackets parseRequestPackets(RequestPacketsHead requestHead, String jsonString,
ScInterfaceDetailVo scInterfaceDetailVo) throws BussinessExceptionNeedCatch {
String decryptBody = OfflinePacketsService.decryptBody(jsonString, scInterfaceDetailVo.getSecretKey());
if (null == decryptBody) {
throw new BussinessExceptionNeedCatch(ErrorCode.SYS_SECRET_KEY_ERROR,
GenerateMonitorDataFactory.buildErrorMonitorData(
WarnBussinessTypeEnum.OTM_SALE_REFUND_SETTLEMENT,
"解密失败,body[" + jsonString + "]"));
}
BussinessEnum bussinessEnum = null;
try {
bussinessEnum = BussinessEnum.parseBussinessCodeToEnum(requestHead.getBussinessCode());
} catch (ComponentExceptionNeedConvert e) {
throw new BussinessExceptionNeedCatch(e.getErrorCode(),
GenerateMonitorDataFactory.buildBussinessMonitorData(WarnBussinessTypeEnum.BASE_PACKAET_PARSED,
requestHead.getSpCode(), null, requestHead.toString(), e.getMessage()));
}
RequestPacketsBody reqBody = null;
switch (bussinessEnum) {
case SALE_REFUND_SETTLEMENT:
reqBody = JSON.toJavaObject(JSON.parseObject(decryptBody), RequestSaleAggregatePacketsBody.class);
break;
case USED_RATE_REPORT:
reqBody = JSON.toJavaObject(JSON.parseObject(decryptBody), RequestUsedRateAggregatePacketsBody.class);
break;
case USED_DAY_REPORT:
reqBody = JSON.toJavaObject(JSON.parseObject(decryptBody), RequestUsedDayAggregatePacketsBody.class);
break;
case OFFLINE_EXCHANGE_TICKET:
reqBody = JSON.toJavaObject(JSON.parseObject(decryptBody), RequestOfflineExchangeTicketBody.class);
break;
case OFFLINE_UPDATE_APPLY_ORDER:
reqBody = JSON.toJavaObject(JSON.parseObject(decryptBody), RequestOfflineUpdateApplyOrderBody.class);
break;
case QUERY_APPLY_ORDER:
reqBody = JSON.toJavaObject(JSON.parseObject(decryptBody), RequestQueryApplyOrderBody.class);
break;
case OFFLINE_UPDATE_GOODS:
reqBody = JSON.toJavaObject(JSON.parseObject(decryptBody), RequestOfflineUpdateGoodsBody.class);
break;
default:
throw new BussinessExceptionNeedCatch(ErrorCode.SYS_UNKNOW_BUSSINESS_CODE,
GenerateMonitorDataFactory.buildBussinessMonitorData(WarnBussinessTypeEnum.BASE_PACKAET_PARSED,
requestHead.getSpCode(), null, requestHead.toString(), "解析请求参数体失败"));
}
RequestPackets requestPackets = new RequestPackets();
requestPackets.setHead(requestHead);
requestPackets.setBody(reqBody);
logger.debug("解密收到的request:" + requestPackets.toJSON());
return requestPackets;
}
/**
* 方法用途: 组装消息体消息头
* 实现步骤:
* @param requestPackets
* @param responseBody
* @param statucCode
* @param responsePacket
* @throws ComponentExceptionNeedConvert
*/
public static ResponsePackets generateReturnPackets(RequestPackets requestPackets, ResponsePacketsBody responseBody,
IErrorCodeInterface statucCode) throws BussinessExceptionNeedCatch {
ResponsePackets responsePacket = new ResponsePackets();
ResponsePacketsHead responseHead = new ResponsePacketsHead();
String spCode = null;
String reqBodyJson = null;
try {
responseHead.setStatusCode(statucCode.getCode());
responseHead.setMessage(statucCode.getMessage());
reqBodyJson = requestPackets.toJSON();
RequestPacketsHead requestHead = (RequestPacketsHead)requestPackets.getHead();
responseHead.setVersion(requestHead.getVersion());
responseHead.setTimeStamp(requestHead.getTimeStamp());
spCode = requestHead.getSpCode();
responsePacket.setHead(responseHead);
responsePacket.setBody(responseBody);
responseHead.setSigned(OfflinePacketsService.generateSigned(responsePacket));
} catch (ComponentExceptionNeedConvert e) {
throw new BussinessExceptionNeedCatch(e.getErrorCode(),
GenerateMonitorDataFactory.buildBussinessMonitorData(
WarnBussinessTypeEnum.BASE_PACKAET_PARSED, spCode, null, reqBodyJson,
e.getMessage()));
} catch (Exception e) {
throw new BussinessExceptionNeedCatch(ErrorCode.PARA_ERROR,
GenerateMonitorDataFactory.buildBussinessMonitorData(
WarnBussinessTypeEnum.BASE_PACKAET_PARSED, spCode, null, reqBodyJson,
e.getMessage()));
}
return responsePacket;
}
/**
* 生成加密的报文
* 根据 respons报文做判断,如果该报文异常,则创建携带错误信息的new response
* @param requestPackets
* @param responsePacket
* @param resultEx
* @param scInterfaceDetailVo
* @return
* @throws BussinessExceptionNeedCatch
*/
public static String generateEncryptResponsePackets(RequestPackets requestPackets, ResponsePackets responsePacket,
IErrorCodeInterface statucCode, String spCode, ScInterfaceDetailVo scInterfaceDetailVo ) throws BussinessExceptionNeedCatch {
String strBodyJson = null;
if (null == responsePacket || null == responsePacket.getHead()
|| StringUtils.isEmpty(((ResponsePacketsHead)responsePacket.getHead()).getStatusCode())){
RequestPacketsHead requestHead = (RequestPacketsHead)requestPackets.getHead();
if (responsePacket == null) responsePacket = new ResponsePackets();
ResponsePacketsHead responseHead = new ResponsePacketsHead();
responseHead.setStatusCode(statucCode.getCode());
responseHead.setMessage(statucCode.getMessage());
responseHead.setVersion(requestHead.getVersion());
responseHead.setTimeStamp(requestHead.getTimeStamp());
responsePacket.setHead(responseHead);
responsePacket.setBody(null);
try {
responseHead.setSigned(generateSigned(responsePacket));
} catch (ComponentExceptionNeedConvert e) {
throw new BussinessExceptionNeedCatch(e.getErrorCode(),
GenerateMonitorDataFactory.buildBussinessMonitorData(
WarnBussinessTypeEnum.BASE_PACKAET_PARSED, requestPackets.getHead().getSpCode(), null, "签名错误",
e.getMessage()));
}
}
logger.debug("待加密的 responsePacket:" + responsePacket.toJSON());
//如果未取得sp,则无法加密,只能放弃加密
if(scInterfaceDetailVo!=null ){
EncryptResponsePackets encryptResponsePackets = new EncryptResponsePackets(); //加密报文返回
encryptResponsePackets.setHead((ResponsePacketsHead) responsePacket.getHead());
String secretKey = (scInterfaceDetailVo!=null ? scInterfaceDetailVo.getSecretKey():null);
String encryptBody = encryptBody(strBodyJson, secretKey );
encryptResponsePackets.setBody(encryptBody);
return encryptResponsePackets.toJSON();
} else {
//无法签名
throw new BussinessExceptionNeedCatch(ErrorCode.PARA_SP_CODE_IS_ERROR,
GenerateMonitorDataFactory.buildBussinessMonitorData(
WarnBussinessTypeEnum.BASE_PACKAET_PARSED, spCode, null, null,
"找不到业务运营商(" + spCode + ")"));
}
}
/**
* 生成报文签名
* @return
* @throws ComponentExceptionNeedConvert
*/
public static String generateSigned(JsonFormatPackets packets) throws ComponentExceptionNeedConvert {
if (null == packets) {
throw new ComponentExceptionNeedConvert(ErrorCode.PARA_FORMAT_MISS, "Request format error! packets is null:"
+ packets);
}
if (packets instanceof RequestPackets) {
RequestPackets reqPackets =(RequestPackets)packets;
RequestPacketsHead curHead = (RequestPacketsHead) reqPackets.getHead();
String strBody = reqPackets.getBody() == null ? "" : reqPackets.getBody().toJSON();
return Base64.encode(Md5.encode(curHead.getVersion() + curHead.getTimeStamp() + curHead.getSpCode()
+ curHead.getBussinessCode() + strBody.length()));
} else if (packets instanceof ResponsePackets) {
ResponsePackets respPackets =(ResponsePackets)packets;
ResponsePacketsHead curHead = (ResponsePacketsHead) respPackets.getHead();
String strBody = respPackets.getBody() == null ? "" : respPackets.getBody().toJSON();
return Base64.encode(Md5.encode(curHead.getVersion() + curHead.getTimeStamp() + curHead.getStatusCode()
+ strBody.length()));
} else {
throw new ComponentExceptionNeedConvert(ErrorCode.PARA_FORMAT_MISS, "Packets format error! packets:"
+ packets);
}
}
/**
* 验证签名
* @param packets 待验证的报文
* @throws ComponentExceptionNeedConvert
*/
public static void validateSinged(JsonFormatPackets packets) throws ComponentExceptionNeedConvert {
String sign = generateSigned(packets);
String packetsSign ;
if (packets instanceof RequestPackets) {
RequestPackets reqPackets =(RequestPackets)packets;
RequestPacketsHead curHead = (RequestPacketsHead) reqPackets.getHead();
packetsSign = curHead.getSigned();
} else if (packets instanceof ResponsePackets) {
ResponsePackets respPackets =(ResponsePackets)packets;
ResponsePacketsHead curHead = (ResponsePacketsHead) respPackets.getHead();
packetsSign = curHead.getSigned();
} else {
throw new ComponentExceptionNeedConvert(ErrorCode.PARA_FORMAT_MISS, "Packets format error! packets:"
+ packets);
}
if (!sign.equals(packetsSign)) {
throw new ComponentExceptionNeedConvert(ErrorCode.SYS_SIGNED_ERROR, "request sign is: "
+ packetsSign + ", but body make sign is : " + sign);
}
}
/**
* 解密报文
* @param encodeBody
* @param secretKey
* @return
*/
public static String decryptBody(String encodeBody, String secretKey) {
return DesSecret.decrypt(Base64.decode(encodeBody), secretKey);
}
/** 加密报文 **/
public static String encryptBody(String body, String secretKey) {
return Base64.encode(DesSecret.encrypt(body, secretKey));
}
private static BussinessEnum resolveBussinessType(String bussinessCode) {
BussinessEnum bussinessTypeCode = null;
try{
if (null != bussinessCode && null != BussinessEnum.valueOf(bussinessCode) ){
bussinessTypeCode = BussinessEnum.valueOf(bussinessCode);
}
}catch(IllegalArgumentException e1){
logger.error("can't get bussnisee type! BussinessEnum=" + bussinessCode);
}
return bussinessTypeCode;
}
}