parent
3ed9e89b3d
commit
1959de22a7
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.example</groupId>
|
||||||
|
<artifactId>TestChain</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dreamdt</groupId>
|
||||||
|
<artifactId>audit-sdk</artifactId>
|
||||||
|
<scope>system</scope>
|
||||||
|
<version>1.0</version>
|
||||||
|
<systemPath>${project.basedir}/src/main/resources/lib/audit-sdk-1.5.2-jar-with-dependencies.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.renchao;
|
||||||
|
|
||||||
|
import cn.dreamdt.audit.domain.AuditConfig;
|
||||||
|
import cn.dreamdt.audit.domain.MessageBean;
|
||||||
|
import cn.dreamdt.audit.main.DataAudit;
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class Demo01 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DataAudit dataAudit = DataAudit.create(AuditConfig.builder()
|
||||||
|
.appCode("zxzj").appKey("xxxxxxx").serverUrl("http://10.91.4.114:8090/DreamWeb")
|
||||||
|
.logFilePath("C:\\Users\\RENCHAO\\Desktop\\temp-sss\\log").chainConsumer(null).build());
|
||||||
|
|
||||||
|
// 数据上链 测试数据
|
||||||
|
JSONObject bizData = new JSONObject();
|
||||||
|
bizData.put("project_year", "2024");
|
||||||
|
bizData.put("code", "1");
|
||||||
|
bizData.put("name", "符合法规和数据测试数据");
|
||||||
|
bizData.put("start_date", "2022-01-01 11:00:00");
|
||||||
|
bizData.put("construction_content", "建立企业业务运营的基础数据平台测试数据");
|
||||||
|
bizData.put("uuid", "230423162136mEefCn9OLj6A7DvR8St");
|
||||||
|
//调用合约
|
||||||
|
MessageBean messageBean = dataAudit.invoke("fact", "save", bizData,"11111");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 数据批量上链 测试数据
|
||||||
|
JSONArray bizDataArray = new JSONArray();
|
||||||
|
|
||||||
|
JSONObject bizData1 = new JSONObject();
|
||||||
|
bizData1.put("project_year", "2024");
|
||||||
|
bizData1.put("code", "1");
|
||||||
|
bizData1.put("name", "符合法规和数据测试数据");
|
||||||
|
bizData1.put("start_date", "2022-01-01 11:00:00");
|
||||||
|
bizData1.put("construction_content", "建立企业业务运营的基础数据平台测试数据");
|
||||||
|
bizData1.put("uuid", "230423162136mEefCn9OLj6A7DvR8St");
|
||||||
|
bizDataArray.add(bizData1);
|
||||||
|
|
||||||
|
JSONObject bizData2 = new JSONObject();
|
||||||
|
bizData2.put("project_year", "2025");
|
||||||
|
bizData2.put("code", "2");
|
||||||
|
bizData2.put("name", "符合法规和数据测试数据111");
|
||||||
|
bizData2.put("start_date", "2022-01-01 11:00:00");
|
||||||
|
bizData2.put("construction_content", "建立企业业务运营的基础数据平台测试数据111");
|
||||||
|
bizData2.put("uuid", "330423162136mEefCn9OLj6A7DvR8St");
|
||||||
|
bizDataArray.add(bizData2);
|
||||||
|
|
||||||
|
//调用合约
|
||||||
|
ArrayList<String> bizIndexList = new ArrayList<>();
|
||||||
|
// ........
|
||||||
|
|
||||||
|
MessageBean messageBean2 = dataAudit.batchInvoke("EAPContract", "saveProject", bizDataArray, bizIndexList);
|
||||||
|
|
||||||
|
|
||||||
|
MessageBean query = dataAudit.query("supervision", "queryProject", "123456");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.dataprocess.feign;
|
||||||
|
|
||||||
|
import com.jiuyv.sptcc.carbon.pushgate.api.DataAuditApi;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上链接口
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
@FeignClient(value = "${carbon-data-process.gateway-serve}", contextId = "dataAuditFeign")
|
||||||
|
public interface DataAuditFeign extends DataAuditApi {
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.dataprocess.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public interface IDataAuditService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上链
|
||||||
|
*/
|
||||||
|
void upChain();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收区块链系统回调 更新上链结果
|
||||||
|
*/
|
||||||
|
void callback();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主动查询一直没有回调的数据
|
||||||
|
*/
|
||||||
|
void queryUpChainResult();
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.dataprocess.service.impl;
|
||||||
|
|
||||||
|
import com.jiuyv.sptcc.carbon.dataprocess.feign.DataAuditFeign;
|
||||||
|
import com.jiuyv.sptcc.carbon.dataprocess.service.IDataAuditService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上链服务
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DataAuditServiceImpl implements IDataAuditService {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(DataAuditServiceImpl.class);
|
||||||
|
|
||||||
|
private final DataAuditFeign dataAuditFeign;
|
||||||
|
|
||||||
|
public DataAuditServiceImpl(DataAuditFeign dataAuditFeign) {
|
||||||
|
this.dataAuditFeign = dataAuditFeign;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上链
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void upChain() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收区块链系统回调 更新上链结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void callback() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主动查询一直没有回调的数据
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void queryUpChainResult() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableDiscoveryClient
|
||||||
|
public class UserGateApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(UserGateApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common;
|
package com.jiuyv.sptcc.carbon.userGate.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Interface WebDict.
|
* The Interface WebDict.
|
@ -1,4 +1,4 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
package com.jiuyv.sptcc.carbon.userGate.common.util;
|
||||||
|
|
||||||
public class ByteUtil {
|
public class ByteUtil {
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
package com.jiuyv.sptcc.carbon.userGate.common.util;
|
||||||
|
|
||||||
|
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
@ -1,4 +1,4 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
package com.jiuyv.sptcc.carbon.userGate.common.util;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
package com.jiuyv.sptcc.carbon.userGate.common.util;
|
||||||
|
|
||||||
import org.bouncycastle.crypto.digests.SM3Digest;
|
import org.bouncycastle.crypto.digests.SM3Digest;
|
||||||
import org.bouncycastle.crypto.macs.HMac;
|
import org.bouncycastle.crypto.macs.HMac;
|
@ -1,4 +1,4 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
package com.jiuyv.sptcc.carbon.userGate.common.util;
|
||||||
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
|
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
|
@ -1,4 +1,4 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common;
|
package com.jiuyv.sptcc.carbon.userGate.config;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
@ -1,39 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.config;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.core.task.TaskExecutor;
|
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
@EnableAsync
|
|
||||||
@Configuration
|
|
||||||
public class NettyBusinessTaskExecutorConfig {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(NettyBusinessTaskExecutorConfig.class);
|
|
||||||
|
|
||||||
@Value("${netty.maxBusinessThread}")
|
|
||||||
private int maxBusinessThreads;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
LOGGER.info("netty server 最大业务线程数 {}", maxBusinessThreads);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean("asyncBusinessExecutor")
|
|
||||||
public TaskExecutor getAsyncExecutor() {
|
|
||||||
ThreadPoolTaskExecutor taskExecutor =
|
|
||||||
new ThreadPoolTaskExecutor();
|
|
||||||
taskExecutor.setThreadNamePrefix("netty-business-ayncTask-");
|
|
||||||
taskExecutor.setCorePoolSize(maxBusinessThreads / 2);
|
|
||||||
taskExecutor.setMaxPoolSize(maxBusinessThreads);
|
|
||||||
taskExecutor.setQueueCapacity(maxBusinessThreads * 5);
|
|
||||||
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
|
|
||||||
return taskExecutor;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,180 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.controller;
|
||||||
|
|
||||||
|
import com.jiuyv.sptcc.carbon.gate.api.IUserGateApi;
|
||||||
|
import com.jiuyv.sptcc.carbon.gate.dto.QryThreeInOneInfo;
|
||||||
|
import com.jiuyv.sptcc.carbon.gate.dto.QryUserRealnameInfo;
|
||||||
|
import com.jiuyv.sptcc.carbon.gate.dto.QryUserUID;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.common.Constant;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.common.util.Sm3Util;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.common.util.Sm4Util;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.config.BaseConfig;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.exception.ServiceException;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.RealNameRecordMsg;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.ReqQryUserMsg;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.ReqThreeRealInfoMsg;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.ReqUserRealNameInfoMsg;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.ResQryUserMsg;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.ResThreeRealInfoMsg;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.ResUserRealNameInfoMsg;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.service.INettyClientService;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.tomcat.util.buf.HexUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户中心接口
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class UserCenterController implements IUserGateApi {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(UserCenterController.class);
|
||||||
|
|
||||||
|
private final INettyClientService nettyClientService;
|
||||||
|
|
||||||
|
private final String sm4key;
|
||||||
|
|
||||||
|
public UserCenterController(INettyClientService nettyClientService, BaseConfig baseConfig) {
|
||||||
|
this.nettyClientService = nettyClientService;
|
||||||
|
this.sm4key = HexUtils.toHexString(baseConfig.getSm4key().getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2.1. 根据手机号查询三合一实名信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public QryThreeInOneInfo.RespDTO queryRealNameInfoByPhone(QryThreeInOneInfo.ReqDTO reqDTO) {
|
||||||
|
ReqThreeRealInfoMsg reqMessage = new ReqThreeRealInfoMsg();
|
||||||
|
reqMessage.setPhoneNo(reqDTO.getPhoneNo());
|
||||||
|
ResThreeRealInfoMsg rsp = nettyClientService.sendRequest(reqMessage, "2997", ResThreeRealInfoMsg.class);
|
||||||
|
|
||||||
|
QryThreeInOneInfo.RespDTO resp = new QryThreeInOneInfo.RespDTO(reqDTO.getReqId(), Constant.RespCode.SUCCESS,
|
||||||
|
Constant.RespMsg.SUCCESS, rsp.getDesc(), rsp.getCentDate(), rsp.getCentralSeq());
|
||||||
|
|
||||||
|
// 解析交易记录
|
||||||
|
ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
|
||||||
|
buffer.writeBytes(rsp.getRecordBody());
|
||||||
|
|
||||||
|
List<QryThreeInOneInfo.Record> list = new ArrayList<>();
|
||||||
|
String reqName = reqDTO.getName();
|
||||||
|
String reqCertNo = reqDTO.getCertNo();
|
||||||
|
|
||||||
|
handleRecord(reqName, reqCertNo, buffer, list);
|
||||||
|
resp.setRecords(list);
|
||||||
|
|
||||||
|
// 查询剩余部分
|
||||||
|
int snum = Integer.parseInt(rsp.getSnum());
|
||||||
|
int startNo = 1;
|
||||||
|
|
||||||
|
while (snum > 0) {
|
||||||
|
startNo = startNo + Integer.parseInt(rsp.getCnum());
|
||||||
|
reqMessage.setStartNo(Integer.toString(startNo));
|
||||||
|
rsp = nettyClientService.sendRequest(reqMessage, "2997", ResThreeRealInfoMsg.class);
|
||||||
|
buffer.clear().writeBytes(rsp.getRecordBody());
|
||||||
|
handleRecord(reqName, reqCertNo, buffer, list);
|
||||||
|
buffer.readBytes(rsp.getMessage());
|
||||||
|
snum = Integer.parseInt(rsp.getSnum());
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户实名查询/渠道用户查询
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public QryUserRealnameInfo.RespDTO qryUserRealnameInfo(@RequestBody QryUserRealnameInfo.ReqDTO reqDTO) {
|
||||||
|
ReqUserRealNameInfoMsg reqMessage = new ReqUserRealNameInfoMsg();
|
||||||
|
reqMessage.setCenterSequence(reqDTO.getCenterSequence());
|
||||||
|
reqMessage.setTransactionType(reqDTO.getTransactionType());
|
||||||
|
reqMessage.setPhoneNo(reqDTO.getPhoneNo());
|
||||||
|
reqMessage.setUserId(reqDTO.getUserId());
|
||||||
|
reqMessage.setNote(reqDTO.getNote());
|
||||||
|
ResUserRealNameInfoMsg rsp = nettyClientService.sendRequest(reqMessage, "2993", ResUserRealNameInfoMsg.class);
|
||||||
|
|
||||||
|
QryUserRealnameInfo.RespDTO resp = new QryUserRealnameInfo.RespDTO();
|
||||||
|
resp.setReqId(reqDTO.getReqId());
|
||||||
|
resp.setRespCode(Constant.RespCode.SUCCESS);
|
||||||
|
resp.setRespDesc(Constant.RespMsg.SUCCESS);
|
||||||
|
resp.setRespMsg(rsp.getDesc());
|
||||||
|
resp.setCenterDate(rsp.getCentDate());
|
||||||
|
resp.setCenterSequence(rsp.getCentralSeq());
|
||||||
|
try {
|
||||||
|
resp.setCertNo(Sm4Util.decryptEcb(sm4key, rsp.getCertNo()).trim());
|
||||||
|
resp.setCertType(Sm4Util.decryptEcb(sm4key, rsp.getCertType()).trim());
|
||||||
|
resp.setName(Sm4Util.decryptEcb(sm4key, rsp.getName()).trim());
|
||||||
|
resp.setPhoneNo(Sm4Util.decryptEcb(sm4key, rsp.getPhoneNo()).trim());
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("解密失败", e);
|
||||||
|
throw new ServiceException("解密失败");
|
||||||
|
}
|
||||||
|
// 没有证件类型默认身份证
|
||||||
|
if (StringUtils.isBlank(resp.getCertType())) {
|
||||||
|
LOGGER.info("无证件类型,默认身份证");
|
||||||
|
resp.setCertType("0");
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交通卡用户UID查询
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public QryUserUID.RespDTO qryUserUID(@RequestBody QryUserUID.ReqDTO reqDTO) {
|
||||||
|
ReqQryUserMsg reqMessage = new ReqQryUserMsg();
|
||||||
|
reqMessage.setChannleNo(reqDTO.getChannelNo());
|
||||||
|
reqMessage.setChannleUID(reqDTO.getChannelUID());
|
||||||
|
reqMessage.setNote(reqDTO.getNote());
|
||||||
|
|
||||||
|
ResQryUserMsg rsp = nettyClientService.sendRequest(reqMessage, "2994", ResQryUserMsg.class);
|
||||||
|
QryUserUID.RespDTO resp = new QryUserUID.RespDTO();
|
||||||
|
resp.setReqId(reqDTO.getReqId());
|
||||||
|
resp.setRespCode(Constant.RespCode.SUCCESS);
|
||||||
|
resp.setRespDesc(Constant.RespMsg.SUCCESS);
|
||||||
|
resp.setRespMsg(rsp.getDesc());
|
||||||
|
resp.setCenterDate(rsp.getCentDate());
|
||||||
|
resp.setCenterSequence(rsp.getCentralSeq());
|
||||||
|
resp.setUserId(rsp.getUserId());
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void handleRecord(String reqName, String reqCertNo, ByteBuf buffer, List<QryThreeInOneInfo.Record> list) {
|
||||||
|
RealNameRecordMsg recordMessage = new RealNameRecordMsg();
|
||||||
|
while (buffer.isReadable()) {
|
||||||
|
buffer.readBytes(recordMessage.getMessage());
|
||||||
|
String name;
|
||||||
|
String certNo;
|
||||||
|
String certNoCiphertext;
|
||||||
|
try {
|
||||||
|
name = Sm4Util.decryptEcb(sm4key, recordMessage.getName()).trim();
|
||||||
|
certNo = Sm4Util.decryptEcb(sm4key, recordMessage.getCertNo()).trim();
|
||||||
|
certNoCiphertext = Sm3Util.encrypt(certNo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("解密失败或hash失败", e);
|
||||||
|
throw new ServiceException("解密失败或hash失败");
|
||||||
|
}
|
||||||
|
LOGGER.debug("姓名:{},证件号:{}", name, certNoCiphertext);
|
||||||
|
if (certNoCiphertext.equals(reqCertNo) && name.equals(reqName)) {
|
||||||
|
QryThreeInOneInfo.Record record = new QryThreeInOneInfo.Record();
|
||||||
|
record.setChannelNo(recordMessage.getChannelNo());
|
||||||
|
record.setChannelId(recordMessage.getChannelId());
|
||||||
|
record.setName(name);
|
||||||
|
record.setCertNo(certNo);
|
||||||
|
record.setNote(recordMessage.getNote());
|
||||||
|
list.add(record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.exception;
|
||||||
|
|
||||||
|
import com.jiuyv.sptcc.carbon.gate.dto.BaseRespVo;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.common.Constant;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局异常处理器
|
||||||
|
*
|
||||||
|
* @author admin
|
||||||
|
*/
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler({ServiceException.class})
|
||||||
|
public BaseRespVo handleServiceException(ServiceException e) {
|
||||||
|
LOGGER.error(e.getMessage(), e);
|
||||||
|
String code = e.getCode();
|
||||||
|
return new BaseRespVo(null, code == null ? Constant.RespCode.SYS_UNKNOWN_ERROR : code, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public BaseRespVo handleException(Exception e, HttpServletRequest request) {
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
LOGGER.error("请求地址'{}',发生系统异常.", requestURI, e);
|
||||||
|
return new BaseRespVo(null, Constant.RespCode.SYS_UNKNOWN_ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务异常
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class ServiceException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回码
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
public ServiceException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceException(String code, String message) {
|
||||||
|
super(message);
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.handler;
|
||||||
|
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.Message;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报文接收处理器
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class ClientMessageHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
|
private CompletableFuture<Message> responseFuture;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||||
|
if (responseFuture != null && msg instanceof Message) {
|
||||||
|
responseFuture.complete((Message) msg);
|
||||||
|
responseFuture = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnectionPromise(CompletableFuture<Message> responseFuture) {
|
||||||
|
this.responseFuture = responseFuture;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.handler;
|
||||||
|
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.common.util.ByteUtil;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.common.util.CrcUtil;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.common.util.Util;
|
||||||
|
import com.jiuyv.sptcc.carbon.userGate.message.Message;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求报文编码器
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class MessageEncoder extends MessageToByteEncoder<Message> {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(MessageEncoder.class);
|
||||||
|
|
||||||
|
private static final Charset CHARSET_GBK = Charset.forName("GBK");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
|
||||||
|
byte[] content = msg.getBody();
|
||||||
|
int len = content.length + msg.size();
|
||||||
|
String length = String.format("%04d", len);
|
||||||
|
msg.setRecordLen(length);
|
||||||
|
|
||||||
|
byte[] macCode = ByteUtil.bytestoasciibytes(Util.toBytes((int) CrcUtil.mkCrc32(content)));
|
||||||
|
msg.setRacCode(new String(macCode));
|
||||||
|
|
||||||
|
ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
|
||||||
|
buffer.writeBytes(length.getBytes());
|
||||||
|
buffer.writeBytes(msg.getMessage());
|
||||||
|
buffer.writeBytes(content);
|
||||||
|
|
||||||
|
byte[] bytes = new byte[len + 4];
|
||||||
|
buffer.readBytes(bytes);
|
||||||
|
LOGGER.info("请求报文:{}", new String(bytes, CHARSET_GBK));
|
||||||
|
buffer.resetReaderIndex();
|
||||||
|
out.writeBytes(buffer);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2.1. 根据手机号查询三合一实名信息 交易记录体
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class RealNameRecordMsg extends AbstractMessage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每个交易记录体 408
|
||||||
|
*/
|
||||||
|
public RealNameRecordMsg() {
|
||||||
|
super(408);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渠道号
|
||||||
|
* N4
|
||||||
|
*/
|
||||||
|
public String getChannelNo() {
|
||||||
|
return arraycopy(0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渠道ID
|
||||||
|
* N128
|
||||||
|
*/
|
||||||
|
public String getChannelId() {
|
||||||
|
return arraycopy(4, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 姓名
|
||||||
|
* H128
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return arraycopy(132, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证件号
|
||||||
|
* H128
|
||||||
|
*/
|
||||||
|
public String getCertNo() {
|
||||||
|
return arraycopy(260, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
* ANS20
|
||||||
|
*/
|
||||||
|
public String getNote() {
|
||||||
|
return arraycopy(388, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.message;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class ReqQryUserMsg extends AbstractReqBodyMessage {
|
||||||
|
/**
|
||||||
|
* 本消息体长度 【不包含公共部分18】
|
||||||
|
*/
|
||||||
|
private static final int LENGTH = 194 - 18;
|
||||||
|
|
||||||
|
public ReqQryUserMsg() {
|
||||||
|
super(LENGTH);
|
||||||
|
setCenterSequence(null);
|
||||||
|
setTransactionType(null);
|
||||||
|
setPhoneNO(null);
|
||||||
|
setQueryType("0001");
|
||||||
|
setNote(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渠道号 4
|
||||||
|
*/
|
||||||
|
public void setChannleNo(String channleNo) {
|
||||||
|
if (channleNo.equals("SPTCC_APP")) {
|
||||||
|
setArray("0004", 18, 4);
|
||||||
|
} else if (channleNo.equals("ALIPAY")) {
|
||||||
|
setArray("0009", 18, 4);
|
||||||
|
} else {
|
||||||
|
// 支付渠道未知
|
||||||
|
setArray(null, 18, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渠道用户uid 128
|
||||||
|
*/
|
||||||
|
public void setChannleUID(String channleUID) {
|
||||||
|
setArray(channleUID, 22, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渠道手机号 20
|
||||||
|
*/
|
||||||
|
public void setPhoneNO(String phoneNO) {
|
||||||
|
setArray(phoneNO, 150, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询类型 4
|
||||||
|
*/
|
||||||
|
public void setQueryType(String queryType) {
|
||||||
|
if (StringUtils.isBlank(queryType)) {
|
||||||
|
queryType = "0001";
|
||||||
|
}
|
||||||
|
setArray(queryType, 170, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注 20
|
||||||
|
*/
|
||||||
|
public void setNote(String note) {
|
||||||
|
setArray(note, 174, 20);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户实名信息 TCP请求体
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class ReqUserRealNameInfoMsg extends AbstractReqBodyMessage {
|
||||||
|
/**
|
||||||
|
* 本消息体长度 【不包含公共部分18】
|
||||||
|
*/
|
||||||
|
private static final int LENGTH = 68 - 18;
|
||||||
|
|
||||||
|
public ReqUserRealNameInfoMsg() {
|
||||||
|
super(LENGTH);
|
||||||
|
setCenterSequence(null);
|
||||||
|
setTransactionType(null);
|
||||||
|
setPhoneNo(null);
|
||||||
|
setUserId(null);
|
||||||
|
setNote(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhoneNo(String phoneNo) {
|
||||||
|
setArray(phoneNo, 18, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
setArray(userId, 38, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNote(String note) {
|
||||||
|
setArray(note, 48, 20);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class ResQryUserMsg extends AbstractResBodyMessage {
|
||||||
|
/**
|
||||||
|
* 本消息体长度 【不包含公共部分62】
|
||||||
|
*/
|
||||||
|
private static final int LENGTH = 84 - 62;
|
||||||
|
|
||||||
|
public ResQryUserMsg() {
|
||||||
|
super(LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交通卡用户uid
|
||||||
|
*/
|
||||||
|
public String getUserId() {
|
||||||
|
return arraycopy(62, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交通卡用户sptccId
|
||||||
|
*/
|
||||||
|
public String getSptccId() {
|
||||||
|
return arraycopy(72, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2.1. 根据手机号查询三合一实名信息 应答报文体
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class ResThreeRealInfoMsg extends AbstractResBodyMessage {
|
||||||
|
/**
|
||||||
|
* 本消息体长度 【不包含公共部分62】
|
||||||
|
*/
|
||||||
|
private static final int LENGTH = 110 - 62;
|
||||||
|
|
||||||
|
public ResThreeRealInfoMsg() {
|
||||||
|
super(LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总记录数
|
||||||
|
* N12
|
||||||
|
*/
|
||||||
|
public String getTotNum() {
|
||||||
|
return arraycopy(62, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剩余记录数
|
||||||
|
* N12
|
||||||
|
*/
|
||||||
|
public String getSnum() {
|
||||||
|
return arraycopy(74, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本页记录数
|
||||||
|
* N12
|
||||||
|
*/
|
||||||
|
public String getCnum() {
|
||||||
|
return arraycopy(86, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 起始记录号
|
||||||
|
* N12
|
||||||
|
*/
|
||||||
|
public String getQnum() {
|
||||||
|
return arraycopy(98, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.jiuyv.sptcc.carbon.userGate.message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户实名信息 TCP响应体
|
||||||
|
*
|
||||||
|
* @author ren_chao
|
||||||
|
*/
|
||||||
|
public class ResUserRealNameInfoMsg extends AbstractResBodyMessage {
|
||||||
|
/**
|
||||||
|
* 本消息体长度 【不包含公共部分62】
|
||||||
|
*/
|
||||||
|
private static final int LENGTH = 414 - 62;
|
||||||
|
|
||||||
|
public ResUserRealNameInfoMsg() {
|
||||||
|
super(LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 姓名
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return arraycopy(62, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证件号
|
||||||
|
*/
|
||||||
|
public String getCertNo() {
|
||||||
|
return arraycopy(190, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证件类型
|
||||||
|
*/
|
||||||
|
public String getCertType() {
|
||||||
|
return arraycopy(318, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号
|
||||||
|
*/
|
||||||
|
public String getPhoneNo() {
|
||||||
|
return arraycopy(350, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.annotation.ImportResource;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
@EnableFeignClients
|
|
||||||
@EnableDiscoveryClient
|
|
||||||
public class Application {
|
|
||||||
|
|
||||||
public static ApplicationContext context;
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
// SpringApplication.run(Application.class, args);
|
|
||||||
|
|
||||||
context = SpringApplication.run(Application.class, args);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common;
|
|
||||||
|
|
||||||
import feign.Feign;
|
|
||||||
import okhttp3.Dispatcher;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
||||||
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换spring boot原有的http发送类
|
|
||||||
*
|
|
||||||
* @author it_Zhongpeng
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
@ConditionalOnClass(Feign.class)
|
|
||||||
@AutoConfigureBefore(FeignAutoConfiguration.class)
|
|
||||||
public class FeignOkHttpConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public okhttp3.OkHttpClient okHttpClient() {
|
|
||||||
Dispatcher pooledispatcher = new Dispatcher();
|
|
||||||
pooledispatcher.setMaxRequestsPerHost(10000);
|
|
||||||
pooledispatcher.setMaxRequests(10000);
|
|
||||||
return new okhttp3.OkHttpClient.Builder().dispatcher(pooledispatcher).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,209 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common;
|
|
||||||
|
|
||||||
import io.prometheus.client.Collector.MetricFamilySamples;
|
|
||||||
import io.prometheus.client.Counter;
|
|
||||||
import io.prometheus.client.Histogram;
|
|
||||||
import io.prometheus.client.Histogram.Timer;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断面摘要
|
|
||||||
*
|
|
||||||
* @author chen_yang
|
|
||||||
* @create 2018-09-05-16:24
|
|
||||||
*/
|
|
||||||
public class SectionHistogram {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(SectionHistogram.class);
|
|
||||||
|
|
||||||
/*交易合计(总数 总耗时 平均耗时)*/
|
|
||||||
private static Histogram histogram;
|
|
||||||
/*交易失败总数 交易成功总数*/
|
|
||||||
private static Counter counter;
|
|
||||||
|
|
||||||
/*交易断面合计*/
|
|
||||||
private static Histogram timingCleanHistogram;
|
|
||||||
/*定时计数器 每日0点清空*/
|
|
||||||
private static Counter timingCleanCounter;
|
|
||||||
/*定时错误计数器 每日0点清空*/
|
|
||||||
private static Counter errorTimingCleanCounter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param subsystem 子系统名称
|
|
||||||
* @param bucketParameters 桶基准值
|
|
||||||
*/
|
|
||||||
public SectionHistogram(String subsystem, double... bucketParameters) {
|
|
||||||
Histogram.Builder totalHBuilder = Histogram.build()
|
|
||||||
.subsystem(subsystem)
|
|
||||||
.name("summary_histogram")
|
|
||||||
.labelNames(LabelName.ORG_CODE, LabelName.TRANS_CODE)
|
|
||||||
.help("总请求统计,根据orgCode和transCode划分");
|
|
||||||
|
|
||||||
Histogram.Builder timingCleanHBuilder = Histogram.build()
|
|
||||||
.subsystem(subsystem)
|
|
||||||
.name("timing_clean_histogram")
|
|
||||||
.labelNames(LabelName.ORG_CODE, LabelName.TRANS_CODE)
|
|
||||||
.help("断面请求数统计,根据orgCode和transCode划分");
|
|
||||||
|
|
||||||
if (null != bucketParameters && 0 != bucketParameters.length) {
|
|
||||||
totalHBuilder = totalHBuilder.buckets(bucketParameters);
|
|
||||||
timingCleanHBuilder = timingCleanHBuilder.buckets(bucketParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
histogram = totalHBuilder.register();
|
|
||||||
timingCleanHistogram = timingCleanHBuilder.register();
|
|
||||||
|
|
||||||
// 统计 成功/失败 总次数/总耗时
|
|
||||||
counter = Counter.build()
|
|
||||||
.subsystem(subsystem)
|
|
||||||
.name("summary_counter")
|
|
||||||
.labelNames(LabelName.ORG_CODE, LabelName.TRANS_CODE, LabelName.SUMMARY_TYPE)
|
|
||||||
.help("总请求数统计,根据orgCode,transCode,成功/失败划分")
|
|
||||||
.register();
|
|
||||||
|
|
||||||
timingCleanCounter = Counter.build()
|
|
||||||
.subsystem(subsystem)
|
|
||||||
.name("timing_clean_counter")
|
|
||||||
.labelNames(LabelName.ORG_CODE, LabelName.TRANS_CODE, LabelName.SUMMARY_TYPE)
|
|
||||||
.help("每日计数器,根据orgCode,transCode,成功/失败 划分")
|
|
||||||
.register();
|
|
||||||
|
|
||||||
errorTimingCleanCounter = Counter.build()
|
|
||||||
.subsystem(subsystem)
|
|
||||||
.name("error_timing_clean_counter")
|
|
||||||
.labelNames(LabelName.ORG_CODE, LabelName.TRANS_CODE, LabelName.ERROR_CODE, LabelName.ERROR_MSG)
|
|
||||||
.help("每次错误计数器,根据orgCode,transCode,errorCode划分")
|
|
||||||
.register();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求累加
|
|
||||||
*
|
|
||||||
* @param transCode 交易代码
|
|
||||||
* @return timer计时器
|
|
||||||
*/
|
|
||||||
public TimerTuple inc(String orgCode, String transCode) {
|
|
||||||
return TimerTuple.build(
|
|
||||||
histogram.labels(orgCode, transCode).startTimer(),
|
|
||||||
timingCleanHistogram.labels(orgCode, transCode).startTimer()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 应答累加
|
|
||||||
*
|
|
||||||
* @param orgCode 请求机构代码
|
|
||||||
* @param transCode 交易代码
|
|
||||||
* @param timerTuple 请求累加时返回的计时器
|
|
||||||
* @param isSuccess 应答返回是否成功
|
|
||||||
*/
|
|
||||||
public void incResp(String orgCode, String transCode,
|
|
||||||
TimerTuple timerTuple, boolean isSuccess) {
|
|
||||||
// 请求数统计累加 & 获取 处理耗时数
|
|
||||||
timerTuple.getTotalTimer().observeDuration();
|
|
||||||
// 成功/失败 应答总数/应答总耗时 累加
|
|
||||||
ResponseType responseType =
|
|
||||||
isSuccess ? ResponseType.SUCCESS : ResponseType.FAIL;
|
|
||||||
//
|
|
||||||
counter.labels(orgCode, transCode, responseType.value).inc();
|
|
||||||
timingCleanCounter.labels(orgCode, transCode, responseType.value).inc();
|
|
||||||
timerTuple.getTimingCleanTimer().observeDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 应答累加 如果 isSuccess 值为 false 则记录 respCode到 每日累加器,每日0点清空
|
|
||||||
*
|
|
||||||
* @param orgCode 请求机构代码
|
|
||||||
* @param transCode 交易代码
|
|
||||||
* @param timerTuple 请求累加时返回的计时器
|
|
||||||
* @param respCode 应答码
|
|
||||||
* @param isSuccess 应答返回是否成功
|
|
||||||
*/
|
|
||||||
public void incResp(String orgCode, String transCode,
|
|
||||||
TimerTuple timerTuple, String respCode, String respDesc, boolean isSuccess) {
|
|
||||||
if (!isSuccess) {
|
|
||||||
errorTimingCleanCounter.labels(orgCode, transCode, respCode, respDesc).inc();
|
|
||||||
}
|
|
||||||
|
|
||||||
incResp(orgCode, transCode, timerTuple, isSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时重置接口 重置所有定时计数器
|
|
||||||
*/
|
|
||||||
public void resetTiming() {
|
|
||||||
LOGGER.info("计数器重置触发");
|
|
||||||
timingCleanCounter.clear();
|
|
||||||
timingCleanHistogram.clear();
|
|
||||||
errorTimingCleanCounter.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MetricFamilySamples> getMonitoringData() {
|
|
||||||
List<MetricFamilySamples> familySamples = histogram.collect();
|
|
||||||
familySamples.addAll(counter.collect());
|
|
||||||
familySamples.addAll(timingCleanHistogram.collect());
|
|
||||||
familySamples.addAll(timingCleanCounter.collect());
|
|
||||||
return familySamples;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 应答类型
|
|
||||||
*/
|
|
||||||
public enum ResponseType {
|
|
||||||
SUCCESS("SUCCESS", "SUCCESS_TIME"),
|
|
||||||
FAIL("FAIL", "FAIL_TIME"),
|
|
||||||
TOTAL("TOTAL", "TOTAL_TIME");
|
|
||||||
public final String value;
|
|
||||||
public final String timeValue;
|
|
||||||
|
|
||||||
ResponseType(String value, String timeValue) {
|
|
||||||
this.value = value;
|
|
||||||
this.timeValue = timeValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link Histogram}用数据标签
|
|
||||||
*/
|
|
||||||
public static class LabelName {
|
|
||||||
|
|
||||||
public static final String ORG_CODE = "orgCode";
|
|
||||||
public static final String TRANS_CODE = "transCode";
|
|
||||||
public static final String SUMMARY_TYPE = "type";
|
|
||||||
public static final String ERROR_CODE = "errorCode";
|
|
||||||
public static final String ERROR_MSG = "errorMsg";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 时间元组(存储计时器{@link Timer})
|
|
||||||
*/
|
|
||||||
public static final class TimerTuple {
|
|
||||||
|
|
||||||
public final Timer totalTimer;
|
|
||||||
public final Timer timingCleanTimer;
|
|
||||||
|
|
||||||
private TimerTuple(Timer totalTimer, Timer timingCleanTimer) {
|
|
||||||
this.totalTimer = totalTimer;
|
|
||||||
this.timingCleanTimer = timingCleanTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param totalTimer 总计时器
|
|
||||||
* @param sectionTimer 断面计时器
|
|
||||||
*/
|
|
||||||
public static TimerTuple build(Timer totalTimer, Timer sectionTimer) {
|
|
||||||
return new TimerTuple(totalTimer, sectionTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Timer getTotalTimer() {
|
|
||||||
return totalTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Timer getTimingCleanTimer() {
|
|
||||||
return timingCleanTimer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* Created on 2008-11-4
|
|
||||||
*
|
|
||||||
* 基础异常类
|
|
||||||
*/
|
|
||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.database.exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 基础异常.
|
|
||||||
*
|
|
||||||
* @author
|
|
||||||
* @version 1.0.0
|
|
||||||
* @since 2013-12-19 15:36:26
|
|
||||||
*/
|
|
||||||
public class BaseException extends Exception {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Constant serialVersionUID.
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = -2856575469726587413L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误结果代码.
|
|
||||||
*/
|
|
||||||
private String errorCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误信息.
|
|
||||||
*/
|
|
||||||
private String errorMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造函数.
|
|
||||||
*
|
|
||||||
* @param errorCode 错误代码
|
|
||||||
* @param throwable Throwable
|
|
||||||
*/
|
|
||||||
public BaseException(String errorCode, Throwable throwable) {
|
|
||||||
super(throwable.getMessage());
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
this.errorMessage = throwable.getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造函数.
|
|
||||||
*
|
|
||||||
* @param errorCode 错误代码
|
|
||||||
* @param errorMessage 错误信息
|
|
||||||
*/
|
|
||||||
public BaseException(String errorCode, String errorMessage) {
|
|
||||||
super(errorMessage);
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造函数.
|
|
||||||
*
|
|
||||||
* @param errorCode 错误代码
|
|
||||||
* @param errorMessage 错误信息
|
|
||||||
* @param throwable the throwable
|
|
||||||
*/
|
|
||||||
public BaseException(String errorCode, String errorMessage,
|
|
||||||
Throwable throwable) {
|
|
||||||
super(errorMessage, throwable);
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the errorCode
|
|
||||||
* Get 错误结果代码.
|
|
||||||
*/
|
|
||||||
public String getErrorCode() {
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param errorCode the errorCode to set
|
|
||||||
* Set 错误结果代码.
|
|
||||||
*/
|
|
||||||
public void setErrorCode(String errorCode) {
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the errorMessage
|
|
||||||
* Get 错误信息.
|
|
||||||
*/
|
|
||||||
public String getErrorMessage() {
|
|
||||||
return errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param errorMessage the errorMessage to set
|
|
||||||
* Set 错误信息.
|
|
||||||
*/
|
|
||||||
public void setErrorMessage(String errorMessage) {
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.database.exception;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.RespCode;
|
|
||||||
|
|
||||||
public class GateException extends Exception {
|
|
||||||
|
|
||||||
private String errorCode;
|
|
||||||
|
|
||||||
|
|
||||||
public GateException() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public GateException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GateException(String respCode, String message) {
|
|
||||||
super(message);
|
|
||||||
this.errorCode = respCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static GateException build68() {
|
|
||||||
return GateException.build(RespCode.TIME_OUT, RespCode.TIME_OUT_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GateException build(String message) {
|
|
||||||
return new GateException(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GateException build(String respCode, String message) {
|
|
||||||
return new GateException(respCode, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getErrorCode() {
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return null != errorCode ? errorCode.hashCode() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
// 错误码不为空&& obj 是 gateException
|
|
||||||
if (null != obj && null != errorCode && obj.getClass() == this.getClass()) {
|
|
||||||
String code = ((GateException) obj).getErrorCode();
|
|
||||||
return errorCode.equals(code) ? true : false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Created on 2008-11-4
|
|
||||||
*
|
|
||||||
* 基础异常类
|
|
||||||
*/
|
|
||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.database.exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付异常码
|
|
||||||
*
|
|
||||||
* @author
|
|
||||||
* @version 1.0.0
|
|
||||||
* @since 2013-12-19 15:36:26
|
|
||||||
*/
|
|
||||||
public class PaymentException extends Exception {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Constant serialVersionUID.
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = -2856575469726587413L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付结果代码.
|
|
||||||
*/
|
|
||||||
private String respCode;
|
|
||||||
|
|
||||||
private String errorMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回秘钥编号
|
|
||||||
*/
|
|
||||||
private String keySeq;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造函数.
|
|
||||||
*
|
|
||||||
* @param respCode 错误代码
|
|
||||||
* @param throwable Throwable
|
|
||||||
*/
|
|
||||||
public PaymentException(String respCode, String keySeq, Throwable throwable) {
|
|
||||||
super(throwable.getMessage());
|
|
||||||
this.respCode = respCode;
|
|
||||||
this.keySeq = keySeq;
|
|
||||||
this.errorMessage = throwable.getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造函数.
|
|
||||||
*
|
|
||||||
* @param respCode 错误代码
|
|
||||||
* @param errorMessage 错误信息
|
|
||||||
*/
|
|
||||||
public PaymentException(String respCode, String errorMessage, String keySeq) {
|
|
||||||
super(errorMessage);
|
|
||||||
this.respCode = respCode;
|
|
||||||
this.keySeq = keySeq;
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造函数.
|
|
||||||
*
|
|
||||||
* @param respCode 错误代码
|
|
||||||
* @param errorMessage 错误信息
|
|
||||||
* @param throwable the throwable
|
|
||||||
*/
|
|
||||||
public PaymentException(String respCode, String errorMessage, String keySeq,
|
|
||||||
Throwable throwable) {
|
|
||||||
super(errorMessage, throwable);
|
|
||||||
this.respCode = respCode;
|
|
||||||
this.keySeq = keySeq;
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the respCode
|
|
||||||
* Get 错误结果代码.
|
|
||||||
*/
|
|
||||||
public String getRespCode() {
|
|
||||||
return respCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param respCode the respCode to set
|
|
||||||
* Set 错误结果代码.
|
|
||||||
*/
|
|
||||||
public void setRespCode(String respCode) {
|
|
||||||
this.respCode = respCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the errorMessage
|
|
||||||
* Get 错误信息.
|
|
||||||
*/
|
|
||||||
public String getErrorMessage() {
|
|
||||||
return errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param errorMessage the errorMessage to set
|
|
||||||
* Set 错误信息.
|
|
||||||
*/
|
|
||||||
public void setErrorMessage(String errorMessage) {
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKeySeq() {
|
|
||||||
return keySeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKeySeq(String keySeq) {
|
|
||||||
this.keySeq = keySeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.feign;
|
|
||||||
|
|
||||||
import feign.Retryer;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
||||||
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
|
|
||||||
public class MyFeignClientsConfiguration extends FeignClientsConfiguration {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public Retryer feignRetryer() {
|
|
||||||
return Retryer.NEVER_RETRY;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty;
|
|
||||||
|
|
||||||
import com.jiuyv.bomap.common.mapper.BOMAP;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.client.ISocketClient;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.client.SyncISocketAbstractSocketClient;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketCode;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.TradeEnum;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.model.gate.vo.MsgBodyVo;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
// @Component
|
|
||||||
public class SocketHelper {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(SocketHelper.class);
|
|
||||||
public ChannelFuture server;
|
|
||||||
public ISocketClient userClient;
|
|
||||||
@Autowired
|
|
||||||
private BOMAP bomap;
|
|
||||||
@Autowired
|
|
||||||
private SocketCode socketCode;
|
|
||||||
private Map<TradeEnum, ISocketClient> clientRouteMap;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void start() throws InterruptedException {
|
|
||||||
LOGGER.info("----socket server createChannelPool");
|
|
||||||
userClient = new SyncISocketAbstractSocketClient(socketCode.userHost, socketCode.userPort, true);
|
|
||||||
LOGGER.info("----socket userClient client createChannelPool");
|
|
||||||
clientRouteMap = new HashMap<>();
|
|
||||||
clientRouteMap.put(TradeEnum.QUERY_USER_REALNAME_INFO, userClient);
|
|
||||||
clientRouteMap.put(TradeEnum.QUERY_USER_UID, userClient);
|
|
||||||
|
|
||||||
clientRouteMap.forEach((s, client) -> {
|
|
||||||
LOGGER.info("clientRouteMap transCode[{}] getSocketClientId[{}]", s, client);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param transCode
|
|
||||||
* @param msgBodyVo
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public MsgBodyVo syncSendMsg(String transCode, MsgBodyVo msgBodyVo) throws Exception {
|
|
||||||
TradeEnum tradeEnum = TradeEnum.reverseFind(transCode);
|
|
||||||
ISocketClient client = clientRouteMap.get(tradeEnum);
|
|
||||||
Assert.notNull(client, transCode + " 未配置socket client");
|
|
||||||
byte[] data = bomap.object2bytes(SocketMsg.SPTCC_MSG, msgBodyVo);
|
|
||||||
|
|
||||||
SocketMsg respMsg = client.sendMsg(SocketMsg.buildRespMsg(data));
|
|
||||||
MsgBodyVo bodyVo = null;
|
|
||||||
if (null != respMsg) {
|
|
||||||
bodyVo = (MsgBodyVo) bomap.bytes2object(SocketMsg.SPTCC_MSG, respMsg.getMessageBody());
|
|
||||||
}
|
|
||||||
return bodyVo;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,234 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.client;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.CallBackResult;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketCode;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.handler.ClientHandler;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.handler.Decoder;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.handler.Encoder;
|
|
||||||
import io.netty.bootstrap.Bootstrap;
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.EventLoop;
|
|
||||||
import io.netty.channel.EventLoopGroup;
|
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
|
||||||
import io.netty.channel.pool.AbstractChannelPoolHandler;
|
|
||||||
import io.netty.channel.pool.ChannelHealthChecker;
|
|
||||||
import io.netty.channel.pool.ChannelPoolHandler;
|
|
||||||
import io.netty.channel.pool.FixedChannelPool;
|
|
||||||
import io.netty.channel.socket.SocketChannel;
|
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
|
||||||
import io.netty.handler.timeout.IdleStateHandler;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @describe
|
|
||||||
* @auther beck5293
|
|
||||||
* @create 2018-03-27-13:52
|
|
||||||
*/
|
|
||||||
public abstract class AbstractSocketClient implements ISocketClient {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSocketClient.class);
|
|
||||||
public final String host;
|
|
||||||
public final int port;
|
|
||||||
protected final boolean isAsync;
|
|
||||||
protected final boolean isKeepAlive;
|
|
||||||
private final AbstractSocketClient client;
|
|
||||||
public Map<String, CallBackResult> callBackResults = new ConcurrentHashMap<>();
|
|
||||||
/**
|
|
||||||
* channel 归还channelPool 时进行健康检查
|
|
||||||
*/
|
|
||||||
ChannelHealthChecker channelHealthChecker = channel -> {
|
|
||||||
EventLoop loop = channel.eventLoop();
|
|
||||||
return channel.isActive() ? loop.newSucceededFuture(Boolean.TRUE) : loop.newSucceededFuture(Boolean.FALSE);
|
|
||||||
};
|
|
||||||
private int idletimeout = 30;
|
|
||||||
private FixedChannelPool channelPool;
|
|
||||||
private Bootstrap bootstrap = new Bootstrap();
|
|
||||||
private EventLoopGroup group = new NioEventLoopGroup();
|
|
||||||
|
|
||||||
protected AbstractSocketClient(String host, int port,
|
|
||||||
boolean isAsync,
|
|
||||||
boolean isKeepAlive) {
|
|
||||||
this.host = host;
|
|
||||||
this.port = port;
|
|
||||||
this.isAsync = isAsync;
|
|
||||||
this.isKeepAlive = isKeepAlive;
|
|
||||||
this.client = this;
|
|
||||||
|
|
||||||
bootstrap.group(group)
|
|
||||||
.channel(NioSocketChannel.class)
|
|
||||||
.remoteAddress(new InetSocketAddress(host, port));
|
|
||||||
|
|
||||||
createChannelPool();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建连接池
|
|
||||||
*/
|
|
||||||
public void createChannelPool() {
|
|
||||||
// 连接池处理
|
|
||||||
ChannelPoolHandler poolHandler = new AbstractChannelPoolHandler() {
|
|
||||||
@Override
|
|
||||||
public void channelCreated(Channel ch) {
|
|
||||||
SocketChannel channel = (SocketChannel) ch;
|
|
||||||
channel.config()
|
|
||||||
.setKeepAlive(true)
|
|
||||||
.setTcpNoDelay(true)
|
|
||||||
.setConnectTimeoutMillis(500);
|
|
||||||
|
|
||||||
channel.pipeline()
|
|
||||||
.addLast(new IdleStateHandler(0, 0, idletimeout, TimeUnit.SECONDS))
|
|
||||||
.addLast(new Decoder())
|
|
||||||
.addLast(new Encoder())
|
|
||||||
.addLast(new ClientHandler(client));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接池配置
|
|
||||||
**/
|
|
||||||
channelPool = new FixedChannelPool(bootstrap,
|
|
||||||
poolHandler,
|
|
||||||
channelHealthChecker,
|
|
||||||
FixedChannelPool.AcquireTimeoutAction.NEW,
|
|
||||||
SocketCode.ACQUIRE_TIMEOUT,
|
|
||||||
SocketCode.MAX_CHANNEL,
|
|
||||||
SocketCode.MAX_PEND_ACQUIRE,
|
|
||||||
true,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送数据
|
|
||||||
*
|
|
||||||
* @param socketMsg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public SocketMsg sendMsg(SocketMsg socketMsg) {
|
|
||||||
Channel channel = null;
|
|
||||||
try {
|
|
||||||
// 申请channel
|
|
||||||
channel = channelPool.acquire().get(SocketCode.ACQUIRE_TIMEOUT, TimeUnit.SECONDS);
|
|
||||||
if (null == channel) {
|
|
||||||
LOGGER.error("----socket client acquire channel timeout");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查异步/同步
|
|
||||||
if (isAsync) {
|
|
||||||
// 异步获取channel引用,直接归还;否则退化成同步连接
|
|
||||||
channelPool.release(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (TimeoutException | InterruptedException | ExecutionException e) {
|
|
||||||
LOGGER.error("----socket client,channel acquire fail", e);
|
|
||||||
releaseChannel(channel, isAsync);
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("----socket client prepare sendMsg fail", e);
|
|
||||||
releaseChannel(channel, isAsync);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录sendKey
|
|
||||||
String sendKey = genSendKey(channel, socketMsg);
|
|
||||||
LOGGER.info("=====channelId [{}] sendKey [{}]", channel.id().asShortText(), sendKey);
|
|
||||||
|
|
||||||
// 应答存储结构保存在channel中
|
|
||||||
CallBackResult backResult = new CallBackResult(sendKey);
|
|
||||||
if (null != callBackResults.putIfAbsent(sendKey, backResult)) {
|
|
||||||
LOGGER.error("----exist repeat sendKey,sendKey [{}]", sendKey);
|
|
||||||
releaseChannel(channel, isAsync);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 发送数据
|
|
||||||
channel.writeAndFlush(socketMsg);
|
|
||||||
|
|
||||||
// 同步,挂在该资源上,等待回文
|
|
||||||
backResult.getRecvsemap().tryAcquire(SocketCode.TIME_OUT, TimeUnit.SECONDS);
|
|
||||||
|
|
||||||
if (!isAsync) {// 应答回复后,同步连接释放
|
|
||||||
channelPool.release(channel);
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// 同步请求终端异常
|
|
||||||
LOGGER.error("----socket client InterruptedException", e);
|
|
||||||
this.callBackResults.remove(sendKey);
|
|
||||||
releaseChannel(channel, isAsync);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 同步应答处理
|
|
||||||
backResult = this.callBackResults.remove(sendKey);
|
|
||||||
if (null != backResult && backResult.isSuccess()) {
|
|
||||||
releaseChannel(channel, isAsync);
|
|
||||||
return backResult.getRespSocketMsg();
|
|
||||||
}
|
|
||||||
releaseChannel(channel, isAsync);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void releaseChannel(Channel channel, boolean isAsync) {
|
|
||||||
if (null != channel) {
|
|
||||||
if (isAsync) {
|
|
||||||
channelPool.release(channel);
|
|
||||||
} else {
|
|
||||||
channel.close();
|
|
||||||
channelPool.release(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param channel
|
|
||||||
* @param socketMsg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public SocketMsg receiveFromServer(Channel channel, SocketMsg socketMsg) {
|
|
||||||
String receiveKey = getReceiveKey(channel, socketMsg);
|
|
||||||
if (StringUtils.isEmpty(receiveKey)) {
|
|
||||||
LOGGER.error("----receiveKey is empty");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录应答数据
|
|
||||||
CallBackResult callBackResult = callBackResults.getOrDefault(receiveKey, null);// 根据packageNum 获取 map中记录应答的数据结构
|
|
||||||
if (null == callBackResult) {// 如果超时,packageNum对应 callBackResult被移除
|
|
||||||
LOGGER.error("----response store in callBackResult fail,callBackResult is Null,packageNum [{}]", receiveKey);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录应答数据
|
|
||||||
callBackResult.setRespSocketMsg(socketMsg);
|
|
||||||
callBackResult.setSuccess(true);
|
|
||||||
// 释放信号量
|
|
||||||
callBackResult.getRecvsemap().release();
|
|
||||||
|
|
||||||
// 短链接关闭
|
|
||||||
if (!this.isKeepAlive) {
|
|
||||||
channel.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
return socketMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract String genSendKey(Channel channel, SocketMsg socketMsg);
|
|
||||||
|
|
||||||
public abstract String getReceiveKey(Channel channel, SocketMsg socketMsg);
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.client;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketCode;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class AsyncISocketAbstractSocketClient extends AbstractSocketClient {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncISocketAbstractSocketClient.class);
|
|
||||||
|
|
||||||
public AsyncISocketAbstractSocketClient(String host, int port) {
|
|
||||||
super(host, port, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String genSendKey(Channel channel, SocketMsg socketMsg) {
|
|
||||||
return this.genSendKey(socketMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String genSendKey(SocketMsg socketMsg) {
|
|
||||||
byte[] packageLenByte = new byte[SocketCode.PACKAGE_LEN];
|
|
||||||
System.arraycopy(socketMsg.getMessageBody(), 2, packageLenByte, 0, 5);
|
|
||||||
|
|
||||||
return new String(packageLenByte, StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getReceiveKey(Channel channel, SocketMsg socketMsg) {
|
|
||||||
byte[] packageLenByte = new byte[SocketCode.PACKAGE_LEN];
|
|
||||||
System.arraycopy(socketMsg.getMessageBody(), 2, packageLenByte, 0, 5);
|
|
||||||
|
|
||||||
return new String(packageLenByte, StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.client;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
|
|
||||||
public interface ISocketClient {
|
|
||||||
/**
|
|
||||||
* 发送数据
|
|
||||||
*
|
|
||||||
* @param socketMsg@return
|
|
||||||
*/
|
|
||||||
SocketMsg sendMsg(SocketMsg socketMsg);
|
|
||||||
|
|
||||||
SocketMsg receiveFromServer(Channel channel, SocketMsg socketMsg);
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.client;
|
|
||||||
|
|
||||||
import com.jiuyv.bomap.common.mapper.BOMAP;
|
|
||||||
import com.jiuyv.bomap.common.util.MessageDigestSHA256;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.database.exception.GateException;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.SocketHelper;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.RespCode;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.util.JsonUtil;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.model.gate.vo.MsgBodyVo;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* socket client 客户端路由
|
|
||||||
*/
|
|
||||||
// @Component
|
|
||||||
public class SocketClientRoute {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(SocketClientRoute.class);
|
|
||||||
@Autowired
|
|
||||||
private BOMAP bomap;
|
|
||||||
@Autowired
|
|
||||||
private SocketHelper socketHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param transCode 交易代码
|
|
||||||
* @param reqVo dto数据
|
|
||||||
* @param tClass 响应dto数据类型
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public <T, V> T sendMsg(String transCode, V reqVo, Class<T> tClass) throws Exception {
|
|
||||||
try {
|
|
||||||
String jsonData = JsonUtil.convertToJson(reqVo);
|
|
||||||
LOGGER.info("transCode [{}] jsonData[{}]", transCode, jsonData);
|
|
||||||
MsgBodyVo sendVo = null;
|
|
||||||
// 字段重置,不需传输字段置为null
|
|
||||||
MsgBodyVo req = MsgBodyVo.build(transCode, jsonData);
|
|
||||||
MsgBodyVo receiveVo = socketHelper.syncSendMsg(transCode, req);
|
|
||||||
|
|
||||||
if (null == receiveVo) {
|
|
||||||
LOGGER.error("transCode [{}] socket client no receive resp msg", transCode);
|
|
||||||
throw GateException.build(RespCode.TIME_OUT, RespCode.TIME_OUT_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.info("socket client receive msg [{}]", JsonUtil.convertToJson(receiveVo));
|
|
||||||
|
|
||||||
// 准备摘要验证
|
|
||||||
String receiveJsonData = receiveVo.getJsonData();
|
|
||||||
// 使用bomap,填入json数据,自动生成附带json数据长度的字节数组用作签名
|
|
||||||
byte[] socketMsgBody = bomap.object2bytes(SocketMsg.SPTCC_MSG_BODY, new MsgBodyVo(receiveJsonData));
|
|
||||||
|
|
||||||
String digest = receiveVo.getDigest();
|
|
||||||
// check digest
|
|
||||||
if (!MessageDigestSHA256.digest(socketMsgBody).equals(digest)) {
|
|
||||||
LOGGER.error("socket msg check digest fail");
|
|
||||||
throw GateException.build("socket client receive respMsg check digest fail");
|
|
||||||
}
|
|
||||||
|
|
||||||
Object o = JsonUtil.json2Bean(receiveJsonData, tClass);
|
|
||||||
LOGGER.info("socket client route respVo [{}]", JsonUtil.convertToJson(o));
|
|
||||||
return (T) o;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("socketClient路由 数据准备处理异常", e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.client;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketCode;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @describe
|
|
||||||
* @auther beck5293
|
|
||||||
* @create 2018-03-27-13:52
|
|
||||||
*/
|
|
||||||
public final class SyncISocketAbstractSocketClient extends AbstractSocketClient {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(SyncISocketAbstractSocketClient.class);
|
|
||||||
|
|
||||||
private AtomicLong atomicLong = new AtomicLong();
|
|
||||||
|
|
||||||
public SyncISocketAbstractSocketClient(String host, int port,
|
|
||||||
boolean isKeepAlive) {
|
|
||||||
super(host, port, false, isKeepAlive);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param channel
|
|
||||||
* @param socketMsg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String genSendKey(Channel channel, SocketMsg socketMsg) {
|
|
||||||
String sendKey = String.valueOf(atomicLong.getAndIncrement());
|
|
||||||
channel.attr(SocketCode.SEND_KEY).set(sendKey);
|
|
||||||
|
|
||||||
return sendKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param channel
|
|
||||||
* @param socketMsg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getReceiveKey(Channel channel, SocketMsg socketMsg) {
|
|
||||||
String sendKey = channel.attr(SocketCode.SEND_KEY).get();
|
|
||||||
if (!this.isKeepAlive) {
|
|
||||||
channel.close();
|
|
||||||
}
|
|
||||||
return sendKey;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 应用常量配置
|
|
||||||
*/
|
|
||||||
public final class AppCode {
|
|
||||||
|
|
||||||
public static final String SYSTEMTRACEID = "QrCodeGateServer";
|
|
||||||
public static final String SYSTEMMODULENAME = "QrCodeGateMina";
|
|
||||||
public static final String UTF8 = "UTF-8";
|
|
||||||
public static final String DEFALUT_FLAG_0 = "0";
|
|
||||||
|
|
||||||
public static final String QUERY_USER_REALNAME_INFO = "2993"; // TODO: 用户实名信息查询
|
|
||||||
public static final String QUERY_USER_UID = "2994"; // TODO: 用户实名状态查询
|
|
||||||
|
|
||||||
public static final int SOCKET_MSG_BODY_LEN = 5;
|
|
||||||
public static final String MSG_VERSION = "00";
|
|
||||||
public static final String PACKAGE_NUM = "00001";
|
|
||||||
public static final String FAIL = "01";
|
|
||||||
public static final String SUCCESS = "00";
|
|
||||||
public static final String ERROR_INVOKE_FAIL = "调用上游服务异常";
|
|
||||||
|
|
||||||
public static final String SPTCC_RESP_ORG_CODE = "sptccRespOrgCode";// 应答机构号
|
|
||||||
}
|
|
||||||
|
|
||||||
//~ Formatted by Jindent --- http://www.jindent.com
|
|
@ -1,53 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity;
|
|
||||||
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @describe
|
|
||||||
* @auther beck5293
|
|
||||||
* @create 2018-03-29-13:16
|
|
||||||
*/
|
|
||||||
public class CallBackResult {
|
|
||||||
private boolean isSuccess = false;
|
|
||||||
private SocketMsg respSocketMsg;
|
|
||||||
private String reqSeq;
|
|
||||||
private Semaphore recvsemap = new Semaphore(0);
|
|
||||||
|
|
||||||
public CallBackResult(String sendKey) {
|
|
||||||
this.reqSeq = sendKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSuccess() {
|
|
||||||
return isSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSuccess(boolean success) {
|
|
||||||
isSuccess = success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SocketMsg getRespSocketMsg() {
|
|
||||||
return respSocketMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CallBackResult setRespSocketMsg(SocketMsg respSocketMsg) {
|
|
||||||
this.respSocketMsg = respSocketMsg;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getReqSeq() {
|
|
||||||
return reqSeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReqSeq(String reqSeq) {
|
|
||||||
this.reqSeq = reqSeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Semaphore getRecvsemap() {
|
|
||||||
return recvsemap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CallBackResult setRecvsemap(Semaphore recvsemap) {
|
|
||||||
this.recvsemap = recvsemap;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 应用常量配置
|
|
||||||
*/
|
|
||||||
public final class RespCode {
|
|
||||||
public static final String ACCOUNT_STATE_NORMAL = "1";
|
|
||||||
public static final String SUCCESS = "00";
|
|
||||||
public static final String FAIL = "01";
|
|
||||||
public static final String ERROR_INVOKE_FAIL = "调用上游服务异常";
|
|
||||||
public static final String ACCOUNT_SIGN_C = "C";
|
|
||||||
public static final String TIME_OUT = "68";
|
|
||||||
public static final String TIME_OUT_MSG = "交易超时";
|
|
||||||
|
|
||||||
public static boolean isSuccess(String code) {
|
|
||||||
return SUCCESS.equals(code);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,184 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author chen_yang
|
|
||||||
* @describe 应答码枚举类
|
|
||||||
* @create 2018-02-26-15:27
|
|
||||||
*/
|
|
||||||
public enum RespEnum {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 成功
|
|
||||||
*/
|
|
||||||
SUCCESS("00", "SUCCESS"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 失败
|
|
||||||
*/
|
|
||||||
FAIL("01", "FAIL"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无此订单
|
|
||||||
*/
|
|
||||||
NO_EXIST_ORDER("25", "无此订单"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回调地址错误
|
|
||||||
*/
|
|
||||||
T_RSP_60("60", "回调地址错误"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证角色错误
|
|
||||||
*/
|
|
||||||
T_RSP_61("61", "验证角色错误"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* auth_code验证失败
|
|
||||||
*/
|
|
||||||
T_RSP_62("62", "auth_code验证失败"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* access_token生成失败
|
|
||||||
*/
|
|
||||||
T_RSP_63("63", "access_token生成失败"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户验证失败
|
|
||||||
*/
|
|
||||||
T_RSP_64("64", "用户验证失败"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新令牌验证失败
|
|
||||||
*/
|
|
||||||
REFRESH_FAIL("65", "刷新令牌验证失败"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* access_token验证失败
|
|
||||||
*/
|
|
||||||
ACCESS_FAIL("66", "access_token验证失败"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验签失败
|
|
||||||
*/
|
|
||||||
T_RSP_67("67", "验签或解密失败"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缺少签名数据
|
|
||||||
*/
|
|
||||||
T_RSP_68("68", "缺少签名数据"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 风控拒绝
|
|
||||||
*/
|
|
||||||
T_RSP_89("89", "风控拒绝"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输入验证失败
|
|
||||||
*/
|
|
||||||
FIELD_ERROR("88", "输入验证失败"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 未查询到用户信息
|
|
||||||
*/
|
|
||||||
T_RSP_87("87", "未查询到用户信息"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 未查询到设备信息
|
|
||||||
*/
|
|
||||||
T_RSP_86("86", "未查询到设备信息"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 未查询到支付渠道信息
|
|
||||||
*/
|
|
||||||
ILLEGAL_CHANNEL("85", "未查询到支付渠道信息"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 未查询到用户虚拟卡号
|
|
||||||
*/
|
|
||||||
T_RSP_84("84", "未查询到用户虚拟卡号"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户未进行实名认证
|
|
||||||
*/
|
|
||||||
T_RSP_83("83", "用户未进行实名认证"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付账户储值额不足
|
|
||||||
*/
|
|
||||||
T_RSP_82("82", "支付账户储值额不足"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 该用户未开通二维码乘车服务
|
|
||||||
*/
|
|
||||||
T_RSP_81("81", "该用户未开通二维码乘车服务"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 该设备未非有效设备
|
|
||||||
*/
|
|
||||||
T_RSP_80("80", "该设备未非有效设备"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付账户不可用
|
|
||||||
*/
|
|
||||||
T_RSP_79("79", "支付账户不可用"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 风控系统异常
|
|
||||||
*/
|
|
||||||
T_RSP_78("78", "风控系统异常"),
|
|
||||||
|
|
||||||
/*系统熔断*/
|
|
||||||
SYSTEM_REJECT("F9", "系统拒绝更多交易"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上游服务应答超时
|
|
||||||
*/
|
|
||||||
B2BGATE_RSP_01("01", "上游服务应答超时"),
|
|
||||||
|
|
||||||
B2BGATE_RSP_02("02", "未配置第三方服务地址");
|
|
||||||
|
|
||||||
private static final Map<String, RespEnum> lookup = new HashMap();
|
|
||||||
public static String RESP_CODE_PRE = "RespCode=";
|
|
||||||
public static String RESP_MSG_PRE = ",RespMsg=";
|
|
||||||
|
|
||||||
static {
|
|
||||||
for (RespEnum anEnum : RespEnum.values()) {
|
|
||||||
lookup.put(anEnum.errorCode, anEnum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final String errorCode;
|
|
||||||
public final String errorMsg;
|
|
||||||
|
|
||||||
RespEnum(String errorCode, String errorMsg) {
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
this.errorMsg = errorMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RespEnum reverseFind(String code) {
|
|
||||||
return lookup.getOrDefault(code, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isSuccess(String errorCode) {
|
|
||||||
return SUCCESS.errorCode.equals(errorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSuccessEnum() {
|
|
||||||
return SUCCESS.errorCode.equals(this.errorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of this enum constant, as contained in the declaration. This method may be
|
|
||||||
* overridden, though it typically isn't necessary or desirable. An enum type should override
|
|
||||||
* this method when a more "programmer-friendly" string form exists.
|
|
||||||
*
|
|
||||||
* @return the name of this enum constant
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return RESP_CODE_PRE + this.errorCode + RESP_MSG_PRE + this.errorMsg;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity;
|
|
||||||
|
|
||||||
import io.netty.util.AttributeKey;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @describe
|
|
||||||
* @auther beck5293
|
|
||||||
* @create 2018-03-26-10:28
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public final class SocketCode {
|
|
||||||
public static final int PACKAGE_LEN = 5;
|
|
||||||
public static final String HEART_BEAT = "00000";
|
|
||||||
public static final byte[] HEART_BEAT_BYTE = HEART_BEAT.getBytes(StandardCharsets.UTF_8);
|
|
||||||
/**
|
|
||||||
* Async
|
|
||||||
*/
|
|
||||||
public static final AtomicLong sendSeqLong = new AtomicLong();
|
|
||||||
public static final AttributeKey<String> SEND_KEY = AttributeKey.valueOf("sendKey");
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(SocketCode.class);
|
|
||||||
public static int MAX_CHANNEL = 2;
|
|
||||||
// public static final int MIN_CHANNEL = 2;
|
|
||||||
public static long ACQUIRE_TIMEOUT = 3;// sec
|
|
||||||
public static int MAX_PEND_ACQUIRE = 10;// max pend acquire channel
|
|
||||||
public static long TIME_OUT = 30L;// sec
|
|
||||||
@Value("${netty.port}")
|
|
||||||
public int serverPort;
|
|
||||||
@Value("${netty.user.host}")
|
|
||||||
public String userHost;
|
|
||||||
@Value("${netty.user.port}")
|
|
||||||
public int userPort;
|
|
||||||
|
|
||||||
@Value("${netty.client.max_channel}")
|
|
||||||
public int max_channel;
|
|
||||||
@Value("${netty.client.acquire_timeout}")
|
|
||||||
public long acquire_timeout;// sec
|
|
||||||
@Value("${netty.client.max_pend_acquire}")
|
|
||||||
public int max_pend_acquire;// max pend acquire channel
|
|
||||||
@Value("${netty.client.wait_for_resp_timeout}")
|
|
||||||
public long wait_for_resp_timeout;// sec
|
|
||||||
|
|
||||||
@Value("${netty.sptccMarketing.host}")
|
|
||||||
public String shqrcodeHost;
|
|
||||||
@Value("${netty.sptccMarketing.port}")
|
|
||||||
public int shqrcodePort;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
|
|
||||||
LOGGER.info("----server [{}]", serverPort);
|
|
||||||
LOGGER.info("----userClient host [{}]", userHost);
|
|
||||||
LOGGER.info("----userClient port [{}]", userPort);
|
|
||||||
|
|
||||||
MAX_CHANNEL = max_channel;
|
|
||||||
ACQUIRE_TIMEOUT = acquire_timeout;
|
|
||||||
MAX_PEND_ACQUIRE = max_pend_acquire;
|
|
||||||
TIME_OUT = wait_for_resp_timeout;
|
|
||||||
|
|
||||||
LOGGER.info("----netty client maxChannel [{}]", MAX_CHANNEL);
|
|
||||||
LOGGER.info("----netty client acquire channel timeout [{}]", ACQUIRE_TIMEOUT);
|
|
||||||
LOGGER.info("----netty client max pend acquire channel [{}]", MAX_PEND_ACQUIRE);
|
|
||||||
LOGGER.info("----netty client max wait for response timeout [{}]", TIME_OUT);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mina数据包
|
|
||||||
*/
|
|
||||||
public class SocketMsg {
|
|
||||||
public static final String SPTCC_MSG = "sptcc.msg";
|
|
||||||
public static final String SPTCC_MSG_BODY = "sptcc.body";
|
|
||||||
|
|
||||||
public static final int PACKAGE_LENGTH = 5;
|
|
||||||
/* 消息包的长度 */
|
|
||||||
private int length;
|
|
||||||
/* 消息包的内容,不含头部的长度 */
|
|
||||||
private byte[] messageBody;
|
|
||||||
/* 消息包的对端ip */
|
|
||||||
private String remoteip;
|
|
||||||
/* 消息包的对端port */
|
|
||||||
private int remoteport;
|
|
||||||
|
|
||||||
public SocketMsg() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public SocketMsg(Builder builder) {
|
|
||||||
this.length = builder.length;
|
|
||||||
this.messageBody = builder.messageBody;
|
|
||||||
this.remoteip = builder.remoteip;
|
|
||||||
this.remoteport = builder.remoteport;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param body
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static SocketMsg buildRespMsg(byte[] body) {
|
|
||||||
SocketMsg respMsg = new SocketMsg();
|
|
||||||
respMsg.setLength(body.length);
|
|
||||||
respMsg.setMessageBody(body);
|
|
||||||
return respMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRemoteip() {
|
|
||||||
return remoteip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRemoteip(String remoteip) {
|
|
||||||
this.remoteip = remoteip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLength() {
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLength(int length) {
|
|
||||||
this.length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getMessageBody() {
|
|
||||||
if (this.messageBody != null) {
|
|
||||||
return this.messageBody.clone();
|
|
||||||
}
|
|
||||||
return new byte[]{};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMessageBody(byte[] messageBody) {
|
|
||||||
if (messageBody != null) {
|
|
||||||
this.messageBody = messageBody.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRemoteport() {
|
|
||||||
return remoteport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRemoteport(int remoteport) {
|
|
||||||
this.remoteport = remoteport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
|
||||||
/* 消息包的长度 */
|
|
||||||
private int length;
|
|
||||||
/* 消息包的内容,不含头部的长度 */
|
|
||||||
private byte[] messageBody;
|
|
||||||
/* 消息包的对端ip */
|
|
||||||
private String remoteip;
|
|
||||||
/* 消息包的对端port */
|
|
||||||
private int remoteport;
|
|
||||||
|
|
||||||
public Builder setLength(int length) {
|
|
||||||
this.length = length;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setMessageBody(byte[] messageBody) {
|
|
||||||
this.messageBody = messageBody;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setRemoteip(String remoteip) {
|
|
||||||
this.remoteip = remoteip;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setRemoteport(int remoteport) {
|
|
||||||
this.remoteport = remoteport;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SocketMsg build() {
|
|
||||||
return new SocketMsg(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 和交通卡系统socket交互交易代码
|
|
||||||
*
|
|
||||||
* @author chen_yang
|
|
||||||
*/
|
|
||||||
public enum TradeEnum {
|
|
||||||
|
|
||||||
QUERY_USER_REALNAME_INFO("2993", "用户实名信息查询接口", "socket"),
|
|
||||||
QUERY_USER_UID("2994", "用户UID查询接口", "socket");
|
|
||||||
|
|
||||||
private static final Map<String, TradeEnum> lookup = new HashMap();
|
|
||||||
|
|
||||||
static {
|
|
||||||
for (TradeEnum anEnum : TradeEnum.values()) {
|
|
||||||
lookup.put(anEnum.code, anEnum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final String code;
|
|
||||||
public final String msg;
|
|
||||||
public final String module;
|
|
||||||
public String orgCode;
|
|
||||||
public Class<?> rpcReq;
|
|
||||||
public Class<?> rpcResp;
|
|
||||||
|
|
||||||
TradeEnum(String code, String msg, String module) {
|
|
||||||
this.code = code;
|
|
||||||
this.msg = msg;
|
|
||||||
this.module = module;
|
|
||||||
}
|
|
||||||
|
|
||||||
TradeEnum(String code, String msg, String module, String orgCode) {
|
|
||||||
this.code = code;
|
|
||||||
this.msg = msg;
|
|
||||||
this.module = module;
|
|
||||||
this.orgCode = orgCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
TradeEnum(String code, String msg, String module, Class<?> rpcReq,
|
|
||||||
Class<?> rpcResp) {
|
|
||||||
this.code = code;
|
|
||||||
this.msg = msg;
|
|
||||||
this.module = module;
|
|
||||||
this.rpcReq = rpcReq;
|
|
||||||
this.rpcResp = rpcResp;
|
|
||||||
}
|
|
||||||
|
|
||||||
TradeEnum(String code, String msg, String module, String orgCode,
|
|
||||||
Class<?> rpcReq, Class<?> rpcResp) {
|
|
||||||
this.code = code;
|
|
||||||
this.msg = msg;
|
|
||||||
this.module = module;
|
|
||||||
this.orgCode = orgCode;
|
|
||||||
this.rpcReq = rpcReq;
|
|
||||||
this.rpcResp = rpcResp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 反向查找
|
|
||||||
*/
|
|
||||||
public static TradeEnum reverseFind(String code) {
|
|
||||||
return lookup.getOrDefault(code, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据原始交易代码查询对应信息进行装饰
|
|
||||||
*
|
|
||||||
* @param oriTransCode 原始交易代码
|
|
||||||
* @return 中文信息装饰后的交易代码
|
|
||||||
*/
|
|
||||||
public static final String decorationTransCode(String oriTransCode) {
|
|
||||||
TradeEnum anEnum = reverseFind(oriTransCode);
|
|
||||||
return (null == anEnum) ? oriTransCode : anEnum.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TradeEnum{" +
|
|
||||||
"code='" + code + '\'' +
|
|
||||||
", msg='" + msg + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.handler;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.client.ISocketClient;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
|
||||||
import io.netty.handler.timeout.IdleState;
|
|
||||||
import io.netty.handler.timeout.IdleStateEvent;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @describe
|
|
||||||
* @auther beck5293
|
|
||||||
* @create 2018-03-26-15:32
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ClientHandler extends ChannelInboundHandlerAdapter {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ClientHandler.class);
|
|
||||||
|
|
||||||
private ISocketClient client;
|
|
||||||
|
|
||||||
public ClientHandler(ISocketClient client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
|
||||||
SocketMsg respMsg = (SocketMsg) msg;
|
|
||||||
if (0 == respMsg.getLength()) {// 接收到心跳应答,修改标志位
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
client.receiveFromServer(ctx.channel(), respMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
|
|
||||||
throws Exception {
|
|
||||||
if (evt instanceof IdleStateEvent) {
|
|
||||||
IdleStateEvent event = (IdleStateEvent) evt;
|
|
||||||
if (event.state().equals(IdleState.READER_IDLE)) {
|
|
||||||
// 超时关闭channel
|
|
||||||
LOGGER.info("READER_IDLE channel {} close it ", ctx.channel().id().asShortText());
|
|
||||||
ctx.close();
|
|
||||||
} else if (event.state().equals(IdleState.WRITER_IDLE)) {
|
|
||||||
|
|
||||||
// 超时关闭channel
|
|
||||||
LOGGER.info("WRITE_IDLE channel {} close it ", ctx.channel().id().asShortText());
|
|
||||||
ctx.close();
|
|
||||||
|
|
||||||
} else if (event.state().equals(IdleState.ALL_IDLE)) {
|
|
||||||
// 超时关闭channel
|
|
||||||
LOGGER.info("ALL_IDLE channel {} close it ", ctx.channel().id().asShortText());
|
|
||||||
ctx.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.userEventTriggered(ctx, evt);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.handler;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketCode;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解码器
|
|
||||||
*/
|
|
||||||
public class Decoder extends ByteToMessageDecoder {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(Decoder.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
|
||||||
// check package len
|
|
||||||
if (in.readableBytes() < SocketCode.PACKAGE_LEN) {
|
|
||||||
LOGGER.info("----package len not enought");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remote ip:port
|
|
||||||
InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
|
|
||||||
|
|
||||||
in.markReaderIndex();
|
|
||||||
// get package len value
|
|
||||||
byte[] packageLenByte = new byte[SocketCode.PACKAGE_LEN];
|
|
||||||
in.readBytes(packageLenByte);
|
|
||||||
String respString = new String(packageLenByte, StandardCharsets.UTF_8);
|
|
||||||
int packageLen = Integer.parseInt(respString.substring(0, 5));
|
|
||||||
|
|
||||||
SocketMsg socketMsg;
|
|
||||||
if (0 == packageLen) {
|
|
||||||
socketMsg = new SocketMsg.Builder().setLength(0).build();
|
|
||||||
out.add(socketMsg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in.readableBytes() < packageLen) {
|
|
||||||
in.resetReaderIndex();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] packageByte = new byte[packageLen];
|
|
||||||
in.readBytes(packageByte);
|
|
||||||
|
|
||||||
try {
|
|
||||||
LOGGER.info("=====channelId {} netty recieve data UTF-8[{}]", ctx.channel().id(),
|
|
||||||
new String(packageByte, "UTF-8"));
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("=====netty recieve data Hex{}", Hex.encodeHexString(packageByte));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
socketMsg = new SocketMsg.Builder()
|
|
||||||
.setLength(packageLen)
|
|
||||||
.setRemoteip(socketAddress.getAddress().getHostAddress())
|
|
||||||
.setRemoteport(socketAddress.getPort())
|
|
||||||
.setMessageBody(packageByte)
|
|
||||||
.build();
|
|
||||||
out.add(socketMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelActive(final ChannelHandlerContext ctx) { // (1)
|
|
||||||
Channel in = ctx.channel();
|
|
||||||
LOGGER.debug("----server channelActive,syncClient ip=[{}]", in.remoteAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
|
||||||
// Close the connection when an exception is raised.
|
|
||||||
LOGGER.warn("Unexpected exception from downstream.", cause);
|
|
||||||
ctx.close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.handler;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketCode;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.util.ByteTools;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.handler.codec.MessageToByteEncoder;
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编码器
|
|
||||||
*/
|
|
||||||
public class Encoder extends MessageToByteEncoder<SocketMsg> {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(Encoder.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void encode(ChannelHandlerContext ctx, SocketMsg msg, ByteBuf out) throws Exception {
|
|
||||||
byte[] respByte;
|
|
||||||
if (0 == msg.getLength()) {
|
|
||||||
respByte = SocketCode.HEART_BEAT_BYTE;
|
|
||||||
} else {
|
|
||||||
byte[] packageLenByte = String.format("%05d", msg.getLength()).getBytes(StandardCharsets.UTF_8);
|
|
||||||
respByte = ByteTools.combinByteArray(packageLenByte, msg.getMessageBody());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
LOGGER.info("=====channelId {} netty sendMsg UTF-8[{}]", ctx.channel().id(),
|
|
||||||
new String(respByte, "UTF-8"));
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("=====netty sendMsg HEX[{}]", Hex.encodeHexString(respByte));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
out.writeBytes(respByte);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
|
||||||
LOGGER.warn("Unexpected exception from downstream.", cause);
|
|
||||||
ctx.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.server;
|
|
||||||
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author charely
|
|
||||||
*/
|
|
||||||
public interface ISocketServer {
|
|
||||||
void processmessage(ChannelHandlerContext ctx, SocketMsg inmessage) throws Exception;
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.server;
|
|
||||||
|
|
||||||
import com.jiuyv.bomap.common.mapper.BOMAP;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.handler.Decoder;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.handler.Encoder;
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
|
||||||
import io.netty.channel.ChannelInitializer;
|
|
||||||
import io.netty.channel.ChannelOption;
|
|
||||||
import io.netty.channel.EventLoopGroup;
|
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
|
||||||
import io.netty.channel.socket.SocketChannel;
|
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
|
||||||
import io.netty.handler.timeout.IdleStateHandler;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Discards any incoming data.
|
|
||||||
*/
|
|
||||||
public class Server {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(Server.class);
|
|
||||||
EventLoopGroup bossGroup = new NioEventLoopGroup();
|
|
||||||
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
|
||||||
private BOMAP bomap;
|
|
||||||
private ISocketServer socketRoute;
|
|
||||||
private int port;
|
|
||||||
private int idletimeout = 30;
|
|
||||||
public Server(int port, ISocketServer socketRoute, BOMAP bomap) {
|
|
||||||
this.port = port;
|
|
||||||
this.socketRoute = socketRoute;
|
|
||||||
this.bomap = bomap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChannelFuture start() throws InterruptedException {
|
|
||||||
// server
|
|
||||||
ServerBootstrap serverBootstrap = new ServerBootstrap();
|
|
||||||
serverBootstrap.group(bossGroup, workerGroup)
|
|
||||||
.channel(NioServerSocketChannel.class) // (3)
|
|
||||||
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
|
|
||||||
@Override
|
|
||||||
public void initChannel(SocketChannel ch) throws Exception {
|
|
||||||
ch.pipeline()
|
|
||||||
.addLast(new IdleStateHandler(0, 0, idletimeout, TimeUnit.SECONDS))
|
|
||||||
.addLast(new Decoder())
|
|
||||||
.addLast(new Encoder())
|
|
||||||
.addLast(new ServerHandler(socketRoute));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.option(ChannelOption.SO_BACKLOG, 128) // (5)
|
|
||||||
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
|
|
||||||
|
|
||||||
|
|
||||||
// connect
|
|
||||||
ChannelFuture future = serverBootstrap.bind(port).sync(); // (7)
|
|
||||||
return future;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.server;
|
|
||||||
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
|
||||||
import io.netty.handler.timeout.IdleState;
|
|
||||||
import io.netty.handler.timeout.IdleStateEvent;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
|
|
||||||
public class ServerHandler extends ChannelInboundHandlerAdapter {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ServerHandler.class);
|
|
||||||
|
|
||||||
private ISocketServer socketRoute;
|
|
||||||
|
|
||||||
public ServerHandler(ISocketServer socketRoute) {
|
|
||||||
this.socketRoute = socketRoute;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
|
||||||
LOGGER.info("channel {} ----serverHandler readmessage", ctx.channel().id().asShortText());
|
|
||||||
SocketMsg reqMsg = (SocketMsg) msg;
|
|
||||||
|
|
||||||
try {
|
|
||||||
socketRoute.processmessage(ctx, reqMsg);
|
|
||||||
} catch (RejectedExecutionException e) {
|
|
||||||
LOGGER.error("", e);
|
|
||||||
}
|
|
||||||
LOGGER.debug("----serverHandler channelRead end");
|
|
||||||
LOGGER.info("channel {} ----serverHandler read end", ctx.channel().id().asShortText());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
|
||||||
// Close the connection when an exception is raised.
|
|
||||||
LOGGER.warn("Unexpected exception from downstream.", cause);
|
|
||||||
ctx.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
|
|
||||||
throws Exception {
|
|
||||||
if (evt instanceof IdleStateEvent) {
|
|
||||||
IdleStateEvent event = (IdleStateEvent) evt;
|
|
||||||
if (event.state().equals(IdleState.READER_IDLE)) {
|
|
||||||
// 超时关闭channel
|
|
||||||
LOGGER.info("READER_IDLE channel {} close it ", ctx.channel().id().asShortText());
|
|
||||||
ctx.close();
|
|
||||||
} else if (event.state().equals(IdleState.WRITER_IDLE)) {
|
|
||||||
|
|
||||||
// 超时关闭channel
|
|
||||||
LOGGER.info("WRITE_IDLE channel {} close it ", ctx.channel().id().asShortText());
|
|
||||||
ctx.close();
|
|
||||||
|
|
||||||
} else if (event.state().equals(IdleState.ALL_IDLE)) {
|
|
||||||
// 超时关闭channel
|
|
||||||
LOGGER.info("ALL_IDLE channel {} close it ", ctx.channel().id().asShortText());
|
|
||||||
ctx.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.userEventTriggered(ctx, evt);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,148 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.server;
|
|
||||||
|
|
||||||
import com.jiuyv.bomap.common.mapper.BOMAP;
|
|
||||||
import com.jiuyv.bomap.common.util.MessageDigestSHA256;
|
|
||||||
import com.jiuyv.sptcc.carbon.gate.dto.SocketErrorMsgVo;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.database.exception.GateException;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.AppCode;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.SocketMsg;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.netty.entity.TradeEnum;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.common.util.JsonUtil;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.model.gate.vo.MsgBodyVo;
|
|
||||||
import com.jiuyv.sptcc.carbon.userGate.userGate.route.IBusinessService;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* socket server business route
|
|
||||||
*/
|
|
||||||
public class SocketServerRoute implements ISocketServer {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(SocketServerRoute.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private BOMAP bomap;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private Map<String, IBusinessService> socketServiceRouteMap;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
if (null == bomap) {
|
|
||||||
Assert.notNull(bomap, "socketServer bomap 注入异常");
|
|
||||||
}
|
|
||||||
|
|
||||||
socketServiceRouteMap.forEach((s, service) ->
|
|
||||||
LOGGER.info("socket服务端路由配置 交易代码 {} 路由对象 {}", s, service.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// @RequestMapping("/test")
|
|
||||||
// public void test() {
|
|
||||||
// String str = "000000000026547CC7EC0913EDF04B2A7FF26239D1D80F4CC028DDAC69E256FB65E5F37E11DFDE00103{\"transCode\":\"02654\",\"reqOrgCode\":\"123\",\"appId\":\"\",\"appUserId\":\"0000000001\",\"appTime\":\"20191128112529\"}";
|
|
||||||
// SocketMsg socketMsg = new SocketMsg();
|
|
||||||
// socketMsg.setMessageBody(str.getBytes(Charsets.UTF_8));
|
|
||||||
//// processmessage(socketMsg);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param reqMsg 请求数据包
|
|
||||||
* @return respMsg 正常返回 reqMsg错误情况原样返回
|
|
||||||
*/
|
|
||||||
@Async("asyncBusinessExecutor")
|
|
||||||
@Override
|
|
||||||
public void processmessage(ChannelHandlerContext ctx, SocketMsg reqMsg) {
|
|
||||||
MsgBodyVo reqBody = null;
|
|
||||||
SocketErrorMsgVo socketErrorMsgVo = new SocketErrorMsgVo();
|
|
||||||
if (0 == reqMsg.getLength()) {// 心跳回包
|
|
||||||
ctx.writeAndFlush(reqMsg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String packageNum = null;
|
|
||||||
String tranCode = null;
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
reqBody = MsgBodyVo.build("", "");
|
|
||||||
byte[] messageByte = reqMsg.getMessageBody();
|
|
||||||
String msg = new String(messageByte, "utf-8");
|
|
||||||
LOGGER.info("socket receive msg [{}]", msg);
|
|
||||||
|
|
||||||
// convert
|
|
||||||
reqBody = (MsgBodyVo) bomap.bytes2object(SocketMsg.SPTCC_MSG, messageByte);
|
|
||||||
|
|
||||||
byte[] data = bomap.object2bytes(SocketMsg.SPTCC_MSG_BODY, reqBody);
|
|
||||||
// 处理业务
|
|
||||||
tranCode = reqBody.getTranCode();
|
|
||||||
// check digest
|
|
||||||
packageNum = reqBody.getPackageNum();
|
|
||||||
String localDigest = MessageDigestSHA256.digest(data);
|
|
||||||
String remoteDigest = reqBody.getDigest();
|
|
||||||
if (!localDigest.equals(remoteDigest)) {
|
|
||||||
LOGGER.error("SHA-256 digest check fail, local [{}] remote [{}]", localDigest, remoteDigest);
|
|
||||||
throw GateException.build("SHA-256 digest check fail");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
IBusinessService service = socketServiceRouteMap.get(tranCode);
|
|
||||||
TradeEnum tradeEnum = TradeEnum.reverseFind(tranCode);
|
|
||||||
if (null != service && null != tradeEnum) {
|
|
||||||
String json = JsonUtil.convertToJson(service.processbusiness(tradeEnum, reqBody.getJsonData()));
|
|
||||||
reqBody.setJsonData(json);
|
|
||||||
} else {
|
|
||||||
LOGGER.error("socket server 路由未配置,transCode:[{}]", tranCode);
|
|
||||||
throw GateException.build("illegal tranCode");
|
|
||||||
}
|
|
||||||
} catch (GateException e) {
|
|
||||||
throw e;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("socket SwitchController error!", e);
|
|
||||||
throw GateException.build("system error");
|
|
||||||
}
|
|
||||||
} catch (GateException e) {
|
|
||||||
socketErrorMsgVo.setRespMsg(e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 准备返回报文
|
|
||||||
try {
|
|
||||||
// 如果错误信息不为空,返回错误信息
|
|
||||||
if (StringUtils.isNotEmpty(socketErrorMsgVo.getRespMsg())) {
|
|
||||||
socketErrorMsgVo.setRespCode(AppCode.FAIL);
|
|
||||||
String tmp = JsonUtil.convertToJson(socketErrorMsgVo);
|
|
||||||
reqBody.setJsonData(tmp);
|
|
||||||
reqBody.setTranCode(tranCode);
|
|
||||||
reqBody.setPackageNum(packageNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换byte[]
|
|
||||||
byte[] data = bomap.object2bytes(SocketMsg.SPTCC_MSG_BODY, reqBody);
|
|
||||||
reqBody.setDigest(MessageDigestSHA256.digest(data));
|
|
||||||
byte[] allData = bomap.object2bytes(SocketMsg.SPTCC_MSG, reqBody);
|
|
||||||
|
|
||||||
LOGGER.info("socket sendMsg [{}]", new String(allData, "UTF-8"));
|
|
||||||
// 组成响应报文
|
|
||||||
ctx.writeAndFlush(SocketMsg.buildRespMsg(allData));
|
|
||||||
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
|
|
||||||
LOGGER.error("socket resp digest fail", e);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("prepare resp data fail", e);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// @RequestMapping("/test")
|
|
||||||
// public String test() {
|
|
||||||
// String str = "{\"tranCode\":\"02650\",\"businessCode\":\"30\",\"fwdCode\":\"xiaohui\",\"acqCode\":\"xiaohui\",\"reqId\":\"14160\",\"reqTime\":\"20191206162008\",\"txnCommonInfo\":{\"dataCelectionDate\":\"000000000000\",\"checkInTxnSeq\":\"000000\",\"driverCardId\":\"0000000000\",\"driverCardType\":\"00\",\"checkInDate\":\"000000000000\",\"checkOutCount\":\"000000\",\"txnFlag\":\"88\",\"companyNo\":\"88888888888\",\"posId\":\"41530905\",\"posSeqId\":\"000000000001\",\"cityCode\":\"7700\",\"cardId\":\"0000000000\",\"cardType\":\"0F\",\"balBef\":\"00000000\",\"txnAmount\":\"00000100\",\"txnDate\":\"20191206\",\"txnTime\":\"162015\",\"counter\":\"000000\",\"orignalTxnAmount\":\"00000100\",\"cardSpec\":\"00\",\"tac\":\"00000000\",\"recordSpacialFlag\":\"01\",\"dtlRecNum\":\"0001\"},\"itsStationInfo\":{\"lineId\":\"09\"},\"qrCodeTxnInfo\":{\"dtlRecType2060\":\"2060\",\"txnCode\":\"386\",\"txnType\":\"00\",\"scanCodeType\":\"01\",\"termSerialNum\":\"000001\",\"payAccount\":\"0000256884 \",\"cardAccount\":\"3104770005650284200F\",\"acquirerNo\":\"2000 \",\"cardIssuerNo\":\"31047700 \",\"codeIssuerNo\":\"11223344 \",\"mcc\":\"4143\",\"chnType\":\"03\",\"transAmt\":\"000000000100\",\"refNum\":\"000000000001\",\"curCode\":\"156\",\"discountType\":\"0000\",\"recAmt\":\"00000064\",\"algFlag\":\"00\",\"rfu\":\"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\",\"inTerminalID\":\"FFF200041530905\",\"interminalSeq\":\"00000001\",\"txnSummary\":\" \",\"intoTxnDate\":\"20191206162015\",\"outTerminalID\":\"FFFFFFFFFFFFFFF\",\"outTerminalSeq\":\"FFFFFFFF\",\"outTxnDate\":\"20191206162015\",\"outRFU\":\"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\",\"qrCode\":\"gQFJJAEBAAAIEjEEdwASQAAAAQQEACEDkop57fwdTaZf5+1izDtHJffXGPRb40DCCz2KZzidOEswgb6Rn8KTTlD8Ou8YisdHhbrg+ynqYpeAI+/JNpritLuAtKDjAgum5cNrWHe8AS+BdAopT4OC9TiQOpJmx0UNMDAwMDI1Njg4NCAgICAgIDEEdwAFZQKEIA8xBHcAESIzRAAAB9ACXgrXBn/7cgYW1PhL4NPR9SO9wzopp0g2/r1M+hRD3ypd6kduALQAFcA11NAarpEEUEZdTvMtKR1CzPE4VRVCIBQxvSHk3sv04kvhSlZNzPPBbNlWSheBKcmNGLVczVn8Dpaq8gxIyU1d6g8uFRFn1X8aFYhrTXN9T6+Q8rZ4MGhvO9OVj3keO3bG0BmverLpgOT26lPpzbHjekCA+YkzZY58Aey0J8G9lGi7zqx=\"}}";
|
|
||||||
// String tranCode = "02650";
|
|
||||||
// IBusinessService service = socketServiceRouteMap.get(tranCode);
|
|
||||||
// String json = JsonUtil.toJson(service.processbusiness(TradeEnum.INDUSTRY_OFFLINE_UPLOAD, str));
|
|
||||||
// return json;
|
|
||||||
// }
|
|
||||||
}
|
|
@ -1,317 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字节转换工具
|
|
||||||
*/
|
|
||||||
public final class ByteTools {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 0 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_0 = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 1 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_1 = 0x02;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 2 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_2 = 0x04;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 3 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_3 = 0x08;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 4 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_4 = 0x10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 5 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_5 = 0x20;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 6 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_6 = 0x40;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 7 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_7 = 0x80;
|
|
||||||
|
|
||||||
private static final int[] BITS = {BIT_0, BIT_1, BIT_2, BIT_3, BIT_4, BIT_5, BIT_6, BIT_7};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把16进制字符串转换成字节数组
|
|
||||||
*
|
|
||||||
* @param hex
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static byte[] hexStringToByte(String hex) {
|
|
||||||
|
|
||||||
int len = (hex.length() / 2);
|
|
||||||
byte[] result = new byte[len];
|
|
||||||
char[] achar = hex.toUpperCase().toCharArray();
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
int pos = i * 2;
|
|
||||||
result[i] = (byte) (toByte(achar[pos]) << 4 | (toByte(achar[pos + 1]) & 0xff));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte toByte(char c) {
|
|
||||||
return (byte) "0123456789ABCDEF".indexOf(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把字节数组转换成16进制字符串
|
|
||||||
*
|
|
||||||
* @param bArray
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static final String bytesToHexString(byte[] bArray) {
|
|
||||||
StringBuffer sb = new StringBuffer(bArray.length);
|
|
||||||
String sTemp;
|
|
||||||
for (int i = 0; i < bArray.length; i++) {
|
|
||||||
sTemp = Integer.toHexString(0xFF & bArray[i]);
|
|
||||||
if (sTemp.length() < 2) {
|
|
||||||
sb.append(0);
|
|
||||||
}
|
|
||||||
Locale locale = new Locale("US-ASCII");
|
|
||||||
sb.append(sTemp.toUpperCase(locale));
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把字节数组转换为对象
|
|
||||||
*
|
|
||||||
* @param bytes
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
* @throws ClassNotFoundException
|
|
||||||
*/
|
|
||||||
public static final Object bytesToObject(byte[] bytes) throws IOException,
|
|
||||||
ClassNotFoundException {
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
|
|
||||||
ObjectInputStream oi = new ObjectInputStream(in);
|
|
||||||
Object o = oi.readObject();
|
|
||||||
oi.close();
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把可序列化对象转换成字节数组
|
|
||||||
*
|
|
||||||
* @param s
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public static final byte[] objectToBytes(Serializable s) throws IOException {
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
ObjectOutputStream ot = new ObjectOutputStream(out);
|
|
||||||
ot.writeObject(s);
|
|
||||||
ot.flush();
|
|
||||||
ot.close();
|
|
||||||
return out.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 可序列化对象转换成十六进制字符串
|
|
||||||
*
|
|
||||||
* @param s
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public static final String objectToHexString(Serializable s)
|
|
||||||
throws IOException {
|
|
||||||
return bytesToHexString(objectToBytes(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Object hexStringToObject(String hex)
|
|
||||||
throws IOException, ClassNotFoundException {
|
|
||||||
return bytesToObject(hexStringToByte(hex));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @函数功能: 10进制串转为BCD码
|
|
||||||
* @输入参数: 10进制串
|
|
||||||
* @输出结果: BCD码
|
|
||||||
*/
|
|
||||||
public static byte[] str2Bcd(String ascii) {
|
|
||||||
String asc = ascii;
|
|
||||||
int len = asc.length();
|
|
||||||
int mod = len % 2;
|
|
||||||
|
|
||||||
if (mod != 0) {
|
|
||||||
asc = "0" + asc;
|
|
||||||
len = asc.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte abt[] = null;
|
|
||||||
if (len >= 2) {
|
|
||||||
len = len / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte bbt[] = new byte[len];
|
|
||||||
try {
|
|
||||||
abt = asc.getBytes("US-ASCII");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
int j, k;
|
|
||||||
|
|
||||||
for (int p = 0; p < asc.length() / 2; p++) {
|
|
||||||
if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
|
|
||||||
j = abt[2 * p] - '0';
|
|
||||||
} else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
|
|
||||||
j = abt[2 * p] - 'a' + 0x0a;
|
|
||||||
} else {
|
|
||||||
j = abt[2 * p] - 'A' + 0x0a;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
|
|
||||||
k = abt[2 * p + 1] - '0';
|
|
||||||
} else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
|
|
||||||
k = abt[2 * p + 1] - 'a' + 0x0a;
|
|
||||||
} else {
|
|
||||||
k = abt[2 * p + 1] - 'A' + 0x0a;
|
|
||||||
}
|
|
||||||
|
|
||||||
int a = (j << 4) + k;
|
|
||||||
byte b = (byte) a;
|
|
||||||
bbt[p] = b;
|
|
||||||
}
|
|
||||||
return bbt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字节数据转长整型
|
|
||||||
*
|
|
||||||
* @param resource
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static long bytes2int(byte[] resource) {
|
|
||||||
if (resource == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (resource.length >= 4) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int mask = 0xff;
|
|
||||||
int temp = 0;
|
|
||||||
int res = 0;
|
|
||||||
byte[] b = new byte[]{0, 0, 0, 0};
|
|
||||||
System.arraycopy(resource, 0, b, 4 - resource.length, resource.length);
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
res <<= 8;
|
|
||||||
temp = b[i] & mask;
|
|
||||||
res |= temp;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 整型数据转字节码
|
|
||||||
*
|
|
||||||
* @param num
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static byte[] int2bytes(int num) {
|
|
||||||
byte[] b = new byte[4];
|
|
||||||
long value = num;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
b[i] = (byte) ((value >>> (24 - i * 8)) & 0xFF);
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把字节数组转换成ASCII '0''1'表示字符串,不使用apache的codec的原因是它的bincodec是反过来的
|
|
||||||
*
|
|
||||||
* @param raw
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static final char[] bytesToascii(byte[] raw) {
|
|
||||||
if (raw == null || raw.length == 0) {
|
|
||||||
return new char[0];
|
|
||||||
}
|
|
||||||
// get 8 times the bytes with 3 bit shifts to the left of the length
|
|
||||||
char[] lascii = new char[raw.length << 3];
|
|
||||||
/*
|
|
||||||
* We decr index jj by 8 as we go along to not recompute indices using
|
|
||||||
* multiplication every time inside the loop.
|
|
||||||
*/
|
|
||||||
for (int ii = raw.length - 1, jj = lascii.length - 1; ii >= 0; ii--, jj -= 8) {
|
|
||||||
for (int bits = 0; bits < BITS.length; ++bits) {
|
|
||||||
if ((raw[ii] & BITS[bits]) == 0) {
|
|
||||||
lascii[jj - bits] = '0';
|
|
||||||
} else {
|
|
||||||
lascii[jj - bits] = '1';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lascii;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ascii字符数组转 字节码
|
|
||||||
*
|
|
||||||
* @param ascii
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static final byte[] acsiiTobytes(char[] ascii) {
|
|
||||||
if (ascii == null || ascii.length == 0) {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
// get length/8 times bytes with 3 bit shifts to the right of the length
|
|
||||||
byte[] lraw = new byte[ascii.length >> 3];
|
|
||||||
/*
|
|
||||||
* We decr index jj by 8 as we go along to not recompute indices using
|
|
||||||
* multiplication every time inside the loop.
|
|
||||||
*/
|
|
||||||
for (int ii = lraw.length - 1, jj = ascii.length - 1; ii >= 0; ii--, jj -= 8) {
|
|
||||||
for (int bits = 0; bits < BITS.length; ++bits) {
|
|
||||||
if (ascii[jj - bits] == '1') {
|
|
||||||
lraw[ii] |= BITS[bits];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lraw;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 组合字节数组.
|
|
||||||
*
|
|
||||||
* @param bytes the bytes
|
|
||||||
* @return the byte[]
|
|
||||||
* @throws IOException Signals that an I/O exception has occurred.
|
|
||||||
*/
|
|
||||||
public static byte[] combinByteArray(byte[]... bytes) throws IOException {
|
|
||||||
ByteArrayOutputStream bos = null;
|
|
||||||
try {
|
|
||||||
bos = new ByteArrayOutputStream();
|
|
||||||
for (byte[] b : bytes) {
|
|
||||||
bos.write(b);
|
|
||||||
}
|
|
||||||
return bos.toByteArray();
|
|
||||||
} finally {
|
|
||||||
if (bos != null) {
|
|
||||||
bos.close();
|
|
||||||
bos = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,319 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
|
|
||||||
public final class ConvertTools {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Constant LOGGER.
|
|
||||||
*/
|
|
||||||
private static final Logger LOGGER = LoggerFactory
|
|
||||||
.getLogger(ConvertTools.class);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 0 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_0 = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 1 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_1 = 0x02;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 2 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_2 = 0x04;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 3 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_3 = 0x08;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 4 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_4 = 0x10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 5 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_5 = 0x20;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 6 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_6 = 0x40;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask for bit 7 of a byte.
|
|
||||||
*/
|
|
||||||
private static final int BIT_7 = 0x80;
|
|
||||||
|
|
||||||
private static final int[] BITS = {BIT_0, BIT_1, BIT_2, BIT_3, BIT_4,
|
|
||||||
BIT_5, BIT_6, BIT_7};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 基础构造
|
|
||||||
*/
|
|
||||||
private ConvertTools() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 把16进制字符串转换成字节数组 @param hex @return
|
|
||||||
*/
|
|
||||||
public static byte[] hexStringToByte(String hex) {
|
|
||||||
|
|
||||||
int len = (hex.length() / 2);
|
|
||||||
byte[] result = new byte[len];
|
|
||||||
char[] achar = hex.toUpperCase().toCharArray();
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
int pos = i * 2;
|
|
||||||
result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]) & 0xff);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte toByte(char c) {
|
|
||||||
return (byte) "0123456789ABCDEF".indexOf(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把字节数组转换成16进制字符串
|
|
||||||
*
|
|
||||||
* @param bArray
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static final String bytesToHexString(byte[] bArray) {
|
|
||||||
StringBuffer sb = new StringBuffer(bArray.length);
|
|
||||||
String sTemp;
|
|
||||||
for (int i = 0; i < bArray.length; i++) {
|
|
||||||
sTemp = Integer.toHexString(0xFF & bArray[i]);
|
|
||||||
if (sTemp.length() < 2) {
|
|
||||||
sb.append(0);
|
|
||||||
}
|
|
||||||
Locale locale = new Locale("US-ASCII");
|
|
||||||
sb.append(sTemp.toUpperCase(locale));
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把字节数组转换为对象
|
|
||||||
*
|
|
||||||
* @param bytes
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
* @throws ClassNotFoundException
|
|
||||||
*/
|
|
||||||
public static final Object bytesToObject(byte[] bytes) throws IOException,
|
|
||||||
ClassNotFoundException {
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
|
|
||||||
ObjectInputStream oi = new ObjectInputStream(in);
|
|
||||||
Object o = oi.readObject();
|
|
||||||
oi.close();
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把可序列化对象转换成字节数组
|
|
||||||
*
|
|
||||||
* @param s
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public static final byte[] objectToBytes(Serializable s) throws IOException {
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
ObjectOutputStream ot = new ObjectOutputStream(out);
|
|
||||||
ot.writeObject(s);
|
|
||||||
ot.flush();
|
|
||||||
ot.close();
|
|
||||||
return out.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String objectToHexString(Serializable s)
|
|
||||||
throws IOException {
|
|
||||||
return bytesToHexString(objectToBytes(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Object hexStringToObject(String hex)
|
|
||||||
throws IOException, ClassNotFoundException {
|
|
||||||
return bytesToObject(hexStringToByte(hex));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long bytes2int(byte[] resource) {
|
|
||||||
if (resource == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (resource.length >= 4) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int mask = 0xff;
|
|
||||||
int temp = 0;
|
|
||||||
int res = 0;
|
|
||||||
byte[] b = new byte[]{0, 0, 0, 0};
|
|
||||||
System.arraycopy(resource, 0, b, 4 - resource.length, resource.length);
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
res <<= 8;
|
|
||||||
temp = b[i] & mask;
|
|
||||||
res |= temp;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] int2bytes(int num) {
|
|
||||||
byte[] b = new byte[4];
|
|
||||||
long value = num;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
b[i] = (byte) ((value >>> (24 - i * 8)) & 0xFF);
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把字节数组转换成ASCII '0''1'表示字符串,不使用apache的codec的原因是它的bincodec是反过来的
|
|
||||||
*
|
|
||||||
* @param raw
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static final char[] bytesToascii(byte[] raw) {
|
|
||||||
if (raw == null || raw.length == 0) {
|
|
||||||
return new char[0];
|
|
||||||
}
|
|
||||||
// get 8 times the bytes with 3 bit shifts to the left of the length
|
|
||||||
char[] lascii = new char[raw.length << 3];
|
|
||||||
/*
|
|
||||||
* We decr index jj by 8 as we go along to not recompute indices using
|
|
||||||
* multiplication every time inside the loop.
|
|
||||||
*/
|
|
||||||
for (int ii = raw.length - 1, jj = lascii.length - 1; ii >= 0; ii--, jj -= 8) {
|
|
||||||
for (int bits = 0; bits < BITS.length; ++bits) {
|
|
||||||
if ((raw[ii] & BITS[bits]) == 0) {
|
|
||||||
lascii[jj - bits] = '0';
|
|
||||||
} else {
|
|
||||||
lascii[jj - bits] = '1';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lascii;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final byte[] acsiiTobytes(char[] ascii) {
|
|
||||||
if (ascii == null || ascii.length == 0) {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
// get length/8 times bytes with 3 bit shifts to the right of the length
|
|
||||||
byte[] lraw = new byte[ascii.length >> 3];
|
|
||||||
/*
|
|
||||||
* We decr index jj by 8 as we go along to not recompute indices using
|
|
||||||
* multiplication every time inside the loop.
|
|
||||||
*/
|
|
||||||
for (int ii = lraw.length - 1, jj = ascii.length - 1; ii >= 0; ii--, jj -= 8) {
|
|
||||||
for (int bits = 0; bits < BITS.length; ++bits) {
|
|
||||||
if (ascii[jj - bits] == '1') {
|
|
||||||
lraw[ii] |= BITS[bits];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lraw;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 组合字节数组.
|
|
||||||
*
|
|
||||||
* @param bytes the bytes
|
|
||||||
* @return the byte[]
|
|
||||||
* @throws IOException Signals that an I/O exception has occurred.
|
|
||||||
*/
|
|
||||||
public static byte[] combinByteArray(byte[]... bytes) throws IOException {
|
|
||||||
ByteArrayOutputStream bos = null;
|
|
||||||
try {
|
|
||||||
bos = new ByteArrayOutputStream();
|
|
||||||
for (byte[] b : bytes) {
|
|
||||||
bos.write(b);
|
|
||||||
}
|
|
||||||
return bos.toByteArray();
|
|
||||||
} finally {
|
|
||||||
if (bos != null) {
|
|
||||||
bos.close();
|
|
||||||
bos = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将指定字符串转为指定长度
|
|
||||||
* 如果过长则截取前n位
|
|
||||||
* 如果过短则左补指定字符
|
|
||||||
*
|
|
||||||
* @param str
|
|
||||||
* @param s
|
|
||||||
* @param length
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String leftPad(String str, char s, int length) {
|
|
||||||
if (str == null) {
|
|
||||||
str = "";
|
|
||||||
}
|
|
||||||
if (str.length() > length) {
|
|
||||||
return str.substring(0, length);
|
|
||||||
}
|
|
||||||
while (str.length() < length) {
|
|
||||||
str = s + str;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 元转分
|
|
||||||
*
|
|
||||||
* @param amount
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static Long yuan2fen(String amount) {
|
|
||||||
if (StringUtils.isBlank(amount)) {
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
Long fen;
|
|
||||||
try {
|
|
||||||
fen = new BigDecimal(amount).multiply(new BigDecimal(100)).longValue();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("amount error");
|
|
||||||
fen = 0L;
|
|
||||||
}
|
|
||||||
return fen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分转元
|
|
||||||
* 默认回0
|
|
||||||
* 四舍五入两位小数
|
|
||||||
*
|
|
||||||
* @param amount
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String fen2yuan(Long amount) {
|
|
||||||
if (amount == null) {
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
String yuan = "0";
|
|
||||||
try {
|
|
||||||
yuan = new BigDecimal(amount).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).toString();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("amount error");
|
|
||||||
}
|
|
||||||
return yuan;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @describe
|
|
||||||
* @auther chen_yang
|
|
||||||
* @create 2018-04-16-14:02
|
|
||||||
*/
|
|
||||||
public class DTOFactory {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(DTOFactory.class);
|
|
||||||
private static Class[] classes = new Class[]{String.class};
|
|
||||||
private static Object[] respCode = new Object[]{"01"};
|
|
||||||
private static Object[] respMsg = new Object[]{"FAIL"};
|
|
||||||
private static Map<String, Object[]> respCodeObjectsMap = Maps.newHashMap();
|
|
||||||
|
|
||||||
static {
|
|
||||||
respCodeObjectsMap.put("01", new Object[]{"01"});
|
|
||||||
respCodeObjectsMap.put("88", new Object[]{"88"});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T newInstance(Class<T> tClass) {
|
|
||||||
try {
|
|
||||||
return tClass.newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建默认失败应答
|
|
||||||
*
|
|
||||||
* @param tClass 类型参数
|
|
||||||
*/
|
|
||||||
public static <T> T newFailInstance(Class<T> tClass, String respCode, String respMsg) {
|
|
||||||
Object[] codeObj = respCodeObjectsMap.get(respCode);
|
|
||||||
if (null == codeObj) {
|
|
||||||
codeObj = new Object[]{respCode};
|
|
||||||
respCodeObjectsMap.put(respCode, codeObj);
|
|
||||||
}
|
|
||||||
return newFailInstance(tClass, codeObj, new Object[]{respMsg});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T newFailInstance(Class<T> tClass, Object[] respCode, Object[] respMsg) {
|
|
||||||
try {
|
|
||||||
T t = tClass.newInstance();
|
|
||||||
Method[] methods = tClass.getMethods();
|
|
||||||
|
|
||||||
for (Method method : methods) {
|
|
||||||
if (null != respCode && method.getName().contains("setRespCode")) {
|
|
||||||
Method setCodeMethod = tClass.getMethod("setRespCode", classes);
|
|
||||||
setCodeMethod.invoke(t, respCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != respMsg && method.getName().contains("setRespMsg")) {
|
|
||||||
Method setMsgMethod = t.getClass().getMethod("setRespMsg", classes);
|
|
||||||
setMsgMethod.invoke(t, respMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("DTOFactory 构建默认失败应答失败", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建默认错误应答信息
|
|
||||||
*/
|
|
||||||
public static <T> T newFailInstance(Class<T> tClass) {
|
|
||||||
return newFailInstance(tClass, respCode, respMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param tClass 应答参数类型
|
|
||||||
* @param respMsg 错误应答信息
|
|
||||||
*/
|
|
||||||
public static <T> T newFailInstance(Class<T> tClass, String respMsg) {
|
|
||||||
return newFailInstance(tClass, respCode, new Object[]{respMsg});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
||||||
import com.fasterxml.jackson.databind.JavaType;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @auther chen_yang
|
|
||||||
* @create 2018-01-22-16:03
|
|
||||||
*/
|
|
||||||
public class NoProperisObjectMapper extends ObjectMapper {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(NoProperisObjectMapper.class);
|
|
||||||
private static final long serialVersionUID = 1847111343578713457L;
|
|
||||||
|
|
||||||
private static final NoProperisObjectMapper jsonMapper = new NoProperisObjectMapper();
|
|
||||||
/**
|
|
||||||
* javaType 存储
|
|
||||||
*/
|
|
||||||
private Map<String, JavaType> typeMap = Maps.newHashMap();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* json toJsonString filter null value field and sort by first charaster
|
|
||||||
*/
|
|
||||||
public NoProperisObjectMapper() {
|
|
||||||
super.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
|
||||||
super.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NoProperisObjectMapper defaultInstance() {
|
|
||||||
return jsonMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 简单类型反序列
|
|
||||||
*
|
|
||||||
* @param s 待反序列字符串
|
|
||||||
* @param tClass 参数类型
|
|
||||||
*/
|
|
||||||
public <T> T fromJsonString(String s, Class<T> tClass) {
|
|
||||||
try {
|
|
||||||
return jsonMapper.readValue(s, tClass);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOGGER.error("fromJsonString fail,oriString [{}],classType [{}]", s, tClass, e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 泛型反序列
|
|
||||||
*
|
|
||||||
* @param s 待反序列字符串
|
|
||||||
* @param tClass 参数类型
|
|
||||||
* @param parameterClasses 泛型参数
|
|
||||||
*/
|
|
||||||
public <T> T fromJsonString(String s, Class<T> tClass, Class... parameterClasses) {
|
|
||||||
// className join with '_' as key
|
|
||||||
StringBuilder builder = new StringBuilder(tClass.getName());
|
|
||||||
for (Class aClass : parameterClasses) {
|
|
||||||
builder.append("_").append(aClass.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
String key = builder.toString();
|
|
||||||
JavaType type = typeMap.get(key);
|
|
||||||
|
|
||||||
if (null == type) {
|
|
||||||
type = TypeFactory.defaultInstance().constructParametricType(tClass, parameterClasses);
|
|
||||||
typeMap.put(key, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return jsonMapper.readValue(s, type);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOGGER.error("jsonMapper fail,oriStr [{}]", s, e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param obj 待序列化对象
|
|
||||||
*/
|
|
||||||
public String toJsonString(Object obj) {
|
|
||||||
try {
|
|
||||||
return jsonMapper.writeValueAsString(obj);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("jsonMapper fail", e);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 敏感信息遮蔽工具类
|
|
||||||
*
|
|
||||||
* @auther samayou
|
|
||||||
* @create 2018-06-15-10:42
|
|
||||||
*/
|
|
||||||
public class ShadowUtil {
|
|
||||||
|
|
||||||
private static final Pattern pattern = Pattern.compile("[0-9]+");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 遮蔽敏感字段信息,先对原始字符串正则匹配,如果原始串含有数字,认为是证件号/手机,否则当用户名进行遮蔽
|
|
||||||
*
|
|
||||||
* @param oriStr 原始字符串
|
|
||||||
*/
|
|
||||||
public static String shadow(String oriStr) {
|
|
||||||
if (pattern.matcher(oriStr).find()) {// oriStr 包含数字 -> 不为用户名
|
|
||||||
return shadowPhoneOrIdNo(oriStr);
|
|
||||||
} else {
|
|
||||||
return shadowUserName(oriStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 手机号&证件号敏感信息遮蔽,保留前3后4
|
|
||||||
*/
|
|
||||||
public static String shadowPhoneOrIdNo(String oriStr) {
|
|
||||||
if (StringUtils.isEmpty(oriStr) || oriStr.length() <= 7) {// 手机号为空 || 手机长度不满足7位
|
|
||||||
return oriStr;
|
|
||||||
}
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append(oriStr);
|
|
||||||
int len = oriStr.length();
|
|
||||||
return oriStr.substring(0, 3)
|
|
||||||
+ oriStr.substring(3, len - 4).replaceAll("[0-9]", "*")
|
|
||||||
+ oriStr.substring(len - 4, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户名遮蔽,只保留姓
|
|
||||||
*
|
|
||||||
* @param oriUserName 原用户名
|
|
||||||
*/
|
|
||||||
public static String shadowUserName(String oriUserName) {
|
|
||||||
if (StringUtils.isEmpty(oriUserName)) {
|
|
||||||
return oriUserName;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return oriUserName.substring(0, 1) + oriUserName.substring(1, oriUserName.length())
|
|
||||||
.replaceAll("[\\u4e00-\\u9fa5]|(\\w)", "*");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
|
||||||
|
|
||||||
import com.fasterxml.uuid.EthernetAddress;
|
|
||||||
import com.fasterxml.uuid.Generators;
|
|
||||||
import com.fasterxml.uuid.impl.RandomBasedGenerator;
|
|
||||||
import com.fasterxml.uuid.impl.TimeBasedGenerator;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class UUIDUtil {
|
|
||||||
// 修改成constructMulticastAddress ,防止jmv多个实例在一台服务器上
|
|
||||||
private static TimeBasedGenerator uuidGenerator = Generators
|
|
||||||
.timeBasedGenerator(EthernetAddress.constructMulticastAddress());
|
|
||||||
|
|
||||||
public static UUID getRandomBaseUUID() {
|
|
||||||
// or bogus which would be gotten with: EthernetAddress.constructMulticastAddress()
|
|
||||||
RandomBasedGenerator uuidGenerator = Generators.randomBasedGenerator();
|
|
||||||
// also: we don't specify synchronizer, getting an intra-JVM syncer; there is
|
|
||||||
// also external file-locking-based synchronizer if multiple JVMs run JUG
|
|
||||||
return uuidGenerator.generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getRandomBaseUUIDString() {
|
|
||||||
// or bogus which would be gotten with: EthernetAddress.constructMulticastAddress()
|
|
||||||
RandomBasedGenerator uuidGenerator = Generators.randomBasedGenerator();
|
|
||||||
// also: we don't specify synchronizer, getting an intra-JVM syncer; there is
|
|
||||||
// also external file-locking-based synchronizer if multiple JVMs run JUG
|
|
||||||
return uuidGenerator.generate().toString().replaceAll("-", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to pass Ethernet address; can either use real one (shown here)
|
|
||||||
public static UUID getTimebaseUUID() {
|
|
||||||
// or bogus which would be gotten with:
|
|
||||||
// EthernetAddress.constructMulticastAddress()
|
|
||||||
|
|
||||||
// also: we don't specify synchronizer, getting an intra-JVM syncer;
|
|
||||||
// there is
|
|
||||||
// also external file-locking-based synchronizer if multiple JVMs run
|
|
||||||
// JUG
|
|
||||||
return uuidGenerator.generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package com.jiuyv.sptcc.carbon.userGate.userGate.common.util;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.validation.ConstraintViolation;
|
|
||||||
import javax.validation.Validation;
|
|
||||||
import javax.validation.Validator;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ValidateUtils {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ValidateUtils.class);
|
|
||||||
|
|
||||||
private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段合法性校验
|
|
||||||
*
|
|
||||||
* @param r 待校验参数
|
|
||||||
*/
|
|
||||||
public static <R> Optional<String> validate(R r) {
|
|
||||||
Set<ConstraintViolation<R>> checkResult = validator.validate(r);
|
|
||||||
if (checkResult.isEmpty()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
StringBuilder buffer = new StringBuilder();
|
|
||||||
checkResult.stream().forEach(result -> buffer.append(result.getMessage()));
|
|
||||||
return Optional.of(buffer.toString());
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue