作者 朱兆平

add: 非保集拼返回接口

add: 华东对接规则脚本
... ... @@ -96,6 +96,7 @@ wharf.interface.host=http://10.50.3.66:1983/
nmms.interface.host=http://10.50.3.82:8081/
#新舱单网站内网接口,注意尾部带/符号
nmms.site.host=http://nmms1.15miaoo.com:17999
#nmms.site.host=https://nmms.zzcargo.com:8443
custom.receptDirectory= bw/read/
# 卡口指令通知接口
... ...
... ... @@ -4,7 +4,7 @@ loginname=KKW1
#\u767B\u5F55\u5BC6\u7801
loginpass=KKW1
#\u53D1\u9001\u62A5\u6587\u76EE\u5F55,\u76F8\u5BF9\u7A0B\u5E8F\u76EE\u5F55
sendDirectory=D:/bw/sendDirectory
sendDirectory=bw/send
#\u63A5\u6536\u5B58\u50A8\u62A5\u6587\u76EE\u5F55
receiveDirectory=D:/bw/receiveDirectory
#\u8F66\u5355\u5173\u7CFB\u62A5\u6587\u76EE\u5F55
... ...
#log4j=log_api.xml
isneedlog=N
psip=10.50.3.74
#psip=10.50.3.74
psip=192.168.1.53
psport=7484
encoding=UTF-8
... ...
... ... @@ -43,13 +43,13 @@ public class IMF_Tesk {
/**
* 往IMF发送报文
*/
/*if(!KAKO_Sender.isrunning){
KAKO_Sender kako_sender = new KAKO_Sender(client);
kako_sender.start();
logger.info("<<<<<<<<<KAKO发送线程已开启>>>>>>>>>>>>");
}else {
logger.info("<<<<<<<<<KAKO发送线程已开启-不再启动线程>>>>>>>>>>>>");
}*/
// if(!KAKO_Sender.isrunning){
// KAKO_Sender kako_sender = new KAKO_Sender(client);
// kako_sender.start();
// logger.info("<<<<<<<<<KAKO发送线程已开启>>>>>>>>>>>>");
// }else {
// logger.info("<<<<<<<<<KAKO发送线程已开启-不再启动线程>>>>>>>>>>>>");
// }
}
if (!LOGIN_OK){
... ...
package com.sy.controller;
public class FBresponse {
public String success = "true";
public String code = "200";
public String message = "验放成功";
public String info = "非保接口验放成功";
}
... ...
package com.sy.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class ZBQResponseController {
@PostMapping(value = "/xml", consumes = MediaType.APPLICATION_XML_VALUE)
public FBresponse handleXmlRequest(@RequestBody String xmlModel) {
log.info(xmlModel);
// 在这里对接收到的XML数据进行处理
// 可以将接收到的XML转换为对象,或进行其他操作
return new FBresponse();
}
}
... ...
package com.sy.groovy
import com.sy.model.GatherInfo
import com.sy.service.impl.GatherInfoHandle
import org.basis.enhance.groovy.entity.ExecuteParams
import org.springframework.context.ApplicationContext
//转人工查验
class CustomsCheckScript extends Script implements ChannelCheckScript{
Boolean check(ExecuteParams executeParams) {
String NORECORD = "转人工查验";
GatherInfo gatherInfo = (GatherInfo) executeParams.get("GatherInfo");
// 调用方法
ApplicationContext context = getContext();
// 获取容器中的bean
GatherInfoHandle gatherInfoHandle = context.getBean(GatherInfoHandle.class);
gatherInfoHandle.sendBw(gatherInfo,false,NORECORD,null,null);
return false
}
@Override
Object run() {
return null
}
// 获取spring容器
ApplicationContext getContext() {
// 获取spring IOC容器
ApplicationContext context = applicationContext;
return context;
}
}
... ...
package com.sy.groovy
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject
import com.sy.model.GatherInfo
import com.sy.model.LandBusinessTypeList
import com.sy.model.LandRoadVe
import com.sy.response.ResultJson
import com.sy.service.CommandLogService
import com.sy.service.EnginCheckService
import com.sy.service.RedisService
import com.sy.service.feigin.G2X81FeignService
import com.sy.service.feigin.StationManageFeignService
import com.sy.socket.CommandClient
import org.apache.commons.lang.StringUtils
import org.basis.enhance.groovy.entity.ExecuteParams
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationContext
import java.nio.charset.Charset
import java.text.SimpleDateFormat
/**
* 特殊区域本地调拨分拨验放-综保区西货站
* 返回true 无后续返回,没有验放指令配合
* todo:需要改造成验放型.返回true false,某些业务类型需要强制走金二验放,海关智能卡口配置端也是根据通道进行配置的
*/
class G2X21NoticeWithTrue extends Script implements ChannelCheckScript{
private final Logger log = LoggerFactory.getLogger(getClass());
private static final String X21Template = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<GATHER_INFO AREA_ID=\"#{area_id}\" CHNL_NO=\"#{chnl_no}\" I_E_TYPE=\"#{ie_flag}\" SEQ_NO=\"#{session_id}\">\n" +
" <IC>\n" +
" <DR_IC_NO/>\n" +
" <IC_DR_CUSTOMS_NO/>\n" +
" <IC_CO_CUSTOMS_NO/>\n" +
" <IC_BILL_NO/>\n" +
" <IC_GROSS_WT/>\n" +
" <IC_VE_CUSTOMS_NO/>\n" +
" <IC_VE_NAME/>\n" +
" <IC_CONTA_ID/>\n" +
" <IC_ESEAL_ID/>\n" +
" <IC_EX_DATA/>\n" +
" </IC>\n" +
" <WEIGHT>\n" +
" <GROSS_WT>#{gross_wt}</GROSS_WT>\n" +
" </WEIGHT>\n" +
" <CAR>\n" +
" <VE_NAME>#{ve_license_no}</VE_NAME>\n" +
" <CAR_EC_NO>#{rfid_id}</CAR_EC_NO>\n" +
" <CAR_EC_NO2/>\n" +
" <VE_CUSTOMS_NO/>\n" +
" <VE_WT/>\n" +
" </CAR>\n" +
" <CONTA>\n" +
" <CONTA_NUM/>\n" +
" <CONTA_RECO>1</CONTA_RECO>\n" +
" <CONTA_MODEL_F/>\n" +
" <CONTA_MODEL_B/>\n" +
" <CONTA_ID_F/>\n" +
" <CONTA_ID_B/>\n" +
" </CONTA>\n" +
" <SEAL>\n" +
" <ESEAL_ID/>\n" +
" </SEAL>\n" +
" <BAR_CODE>#{bar_code}</BAR_CODE>\n" +
" </GATHER_INFO>";
/**
* 海关发送报文封装模板
*/
public static final String HAIGUAN_MQ_TEMPLATE = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<DxpMsg xmlns=\"http://www.chinaport.gov.cn/dxp\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ver=\"1.0\">\n" +
" <TransInfo>\n" +
" <CopMsgId>#{CopMsgId}</CopMsgId>\n" +
" <SenderId>GDXPKK0000000002</SenderId>\n" +
" <MsgType>#{MsgType}</MsgType>\n" +
" <CreatTime>#{CreatTime}</CreatTime>\n" +
" <ReceiverIds>\n" +
" <ReceiverId>GJCKK00000000001</ReceiverId>\n" +
" </ReceiverIds>\n" +
" </TransInfo>\n" +
" <Data>#{Data}</Data>\n" +
"</DxpMsg>";
@Override
Object run() {
return null
}
/**
* 此接口不做抬杆判定,只做报文通知,返回只有false
*/
Boolean check(ExecuteParams executeParams) {
try{
/**
* X21通道信息与流转信息比对
* 1. 从缓存获取车辆进出场申请信息,有流转信息再进行通道对碰.
* 无流转信息则说明缓存失效或者二维码不对.
*/
GatherInfo info = (GatherInfo) executeParams.get("GatherInfo");
LandRoadVe ve = (LandRoadVe) executeParams.get("LandRoadVe");
ApplicationContext context = getContext();
G2X81FeignService g2X81FeignService = context.getBean(G2X81FeignService.class);
EnginCheckService enginCheckService = context.getBean(EnginCheckService.class);
/**
* 写入本地验放通过信息
*/
enginCheckService.commandlog(info,true,"双验放:本地验放通过:等待特殊区域验放指令",executeParams);
if (info!=null){
//缓存X21 的 seqn 需要作为异步X82回执验放时用到的信息
cacheWithSeqno(info);
log.info("[G2-X81-CACHE]-车辆[{}]特殊区域流转已缓存[SEQNO]:{}",info.getVename(),info.getSeqno());
//将X21报文转换成X81格式
String xmlStr = x21TransToX81(info,ve);
//调用本地X81申报接口
ResultJson g2ResultJson = g2X81FeignService.send(xmlStr);
log.info("[G2-X81-API-RSP]-特殊区域通知接口返回,code:{},message:{},err:{}",g2ResultJson.getCode(),g2ResultJson.getMsg(),g2ResultJson.getError());
if ("200".equals(g2ResultJson.getCode())){
record(info,true,"已转特殊区域验放验放-[SEQN]:"+info.getSeqno(),null);
log.info("[G2-ROUTER-SUCCESS]-已转特殊区域验放路由成功-规则验放成功,SEQNO:{}",info.getSeqno());
return true;
}else{
record(info,false,"特殊区域接口访问失败",null);
log.error("[G2-X81-API-ERR]-特殊区域接口访问出错")
return false;
}
}else {
record(info,false,"特殊区域验放失败,未有相关通道流转申请信息",null);
CommandClient.Client(info,"特殊区域验放失败,未有相关通道流转申请信息");
}
}catch (Exception e){
e.printStackTrace();
log.error("[G2-ROUTER-ERR]:",e);
return false;
}
return true;
}
// 获取spring容器
ApplicationContext getContext() {
// 获取spring IOC容器
ApplicationContext context = applicationContext;
return context;
}
void record(GatherInfo info, boolean result, String reason, LandBusinessTypeList landBusinessTypeList){
ApplicationContext context = getContext();
CommandLogService commandLogService = context.getBean(CommandLogService.class);
commandLogService.commandlog(info,result,reason,landBusinessTypeList,null,0.0,0.0,0.0,0.0);
}
String x21TransToX81(GatherInfo gatherInfo,LandRoadVe ve){
log.info("[SEQN]-处理X21报文:{}",gatherInfo.getSeqno());
//当前时间作为X81申报时间
final SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
final String startTime = sdf.format(new Date());
//金二场站ID与通道ID替换
ApplicationContext context = getContext();
StationManageFeignService stationManageFeignService = context.getBean(StationManageFeignService.class);
log.info("[LOCAL-CHANNEL-NO]-{}",gatherInfo.getChnlno());
ResultJson resultJson = stationManageFeignService.getChanels(gatherInfo.getChnlno(),1,1);
log.info("[SERVICE-API-RES]-{}",JSON.toJSONString(resultJson))
if ("200".equals(resultJson.getCode())){
JSONObject jsonObject = (JSONObject) resultJson.getData();
int total = jsonObject.getInteger("total");
if (total>0){
JSONArray jsonArray = jsonObject.getJSONArray("list");
JSONObject chanel = jsonArray.getJSONObject(0);
String channelG2 = chanel.getString("channelG2");
log.info("[G2-CHANNEL]-{}",channelG2);
JSONObject yard = chanel.getJSONObject("yard");
String stationG2 = yard.getString("stationIdG2");
log.info("[G2-YARD]-{}",stationG2);
String rfidNo = ve.getVeCustomsNo();
if (StringUtils.isEmpty(rfidNo)){
log.error("[VE-RFID-NO-ERR]:车辆-{}电子车牌信息未备案",gatherInfo.getVename());
record(gatherInfo,false,"车辆电子车牌信息未备案",null);
}else {
//todo: 这里取的是车辆备案电子车牌字段.实际上 IC卡号应该是一个字段
log.info("[VE-RFID-NO]:车辆电子车牌号:{}",rfidNo);
}
//各脚本维护各脚本的模板吧
String x21XML= X21Template.replace("#{ie_flag}",gatherInfo.getIetype())
.replace("#{area_id}",stationG2)
.replace("#{chnl_no}",channelG2)
.replace("#{session_id}",gatherInfo.getSeqno())
.replace("#{ve_license_no}",gatherInfo.getVename())
.replace("#{gross_wt}",gatherInfo.getGrosswt().toString())
.replace("#{rfid_id}",rfidNo)
.replace("#{ve_wt}",ve.getSelfWt())
.replace("#{bar_code}",gatherInfo.getBarcode());
log.info("[X21]-{}",x21XML);
String mqXMLStr = mqXMLMake(x21XML,gatherInfo.getSeqno(),startTime);
log.info("[X21]-加密后的报文为:{}",mqXMLStr)
return mqXMLStr;
}else {
throw new Exception("未获取到通道金二配置信息")
}
}else {
log.error("场站管理服务接口访问失败")
}
return "";
}
String mqXMLMake(String xmlStr,String copMsgId,String creatTime){
String base64EncodeToString = Base64.getEncoder().encodeToString(xmlStr.getBytes(Charset.forName("utf-8")));
log.info("[SEND-BASE64-ENCODE]-{}",base64EncodeToString)
return HAIGUAN_MQ_TEMPLATE.replace("#{CopMsgId}",copMsgId)
.replace("#{CreatTime}",creatTime)
.replace("#{MsgType}","QNLZ")
.replace("#{Data}",base64EncodeToString);
}
void cacheWithSeqno(GatherInfo info){
ApplicationContext context = getContext();
RedisService redisService = context.getBean(RedisService.class);
if (info!=null && StringUtils.isNotEmpty(info.getSeqno())) {
redisService.set(info.getSeqno(), JSON.toJSONString(info),60*60*24*3);
}
}
}
... ...
... ... @@ -136,6 +136,23 @@ public class EnginCheckServiceImpl implements EnginCheckService {
executeParams.put("selfWt", 0.0);
executeParams.put("goodsWt", 0.0);
//适应高清车牌采集,反向填充二维码 gatherInfo中没有二维码信息的情况
if (StringUtils.isEmpty(gatherInfo.getBarcode())) {
//从申请缓存获取二维码信息
String landBusnessInfoJsonStr = redisService.get(gatherInfo.getVename());
JSONArray array = JSONArray.parseArray(landBusnessInfoJsonStr);
String carBarcode = array.getJSONObject(0).getString("barcode");
if (StringUtils.isEmpty(carBarcode)){
log.error("[BARCODE-RESET-ERR]-从流转申请信息反向填充车辆{}二维码失败",gatherInfo.getVename());
}else {
gatherInfo.setBarcode(carBarcode);
log.info("[BARCODE-RESET]-车牌{}流转申请二维码重置为{}",gatherInfo.getVename(),carBarcode);
}
}
//车辆备案信息
LandRoadVe ve = veService.selectByFrameNo(gatherInfo.getVename());
if (ve != null) {
... ...
... ... @@ -138,7 +138,9 @@ public class LandBusListServiceImpl implements LandBusListService {
/**
* 通道对碰有了.二维码不一致怎么办?
*/
if (item.getBarcode().equals(gatherInfo.getBarcode()) && item.getAisle().equals(gatherInfo.getChnlno())){
if (item.getAisle().equals(gatherInfo.getChnlno())
&& item.getBarcode().equals(gatherInfo.getBarcode())
){
if (item.getBarcode().equals(gatherInfo.getBarcode())){
log.info("车辆-{}的申请缓存信息核碰成功,通道:{}",gatherInfo.getVename(),gatherInfo.getChnlno());
return item;
... ...