作者 朱兆平

add: 非保集拼返回接口

add: 华东对接规则脚本
@@ -96,6 +96,7 @@ wharf.interface.host=http://10.50.3.66:1983/ @@ -96,6 +96,7 @@ wharf.interface.host=http://10.50.3.66:1983/
96 nmms.interface.host=http://10.50.3.82:8081/ 96 nmms.interface.host=http://10.50.3.82:8081/
97 #新舱单网站内网接口,注意尾部带/符号 97 #新舱单网站内网接口,注意尾部带/符号
98 nmms.site.host=http://nmms1.15miaoo.com:17999 98 nmms.site.host=http://nmms1.15miaoo.com:17999
  99 +#nmms.site.host=https://nmms.zzcargo.com:8443
99 custom.receptDirectory= bw/read/ 100 custom.receptDirectory= bw/read/
100 101
101 # 卡口指令通知接口 102 # 卡口指令通知接口
@@ -4,7 +4,7 @@ loginname=KKW1 @@ -4,7 +4,7 @@ loginname=KKW1
4 #\u767B\u5F55\u5BC6\u7801 4 #\u767B\u5F55\u5BC6\u7801
5 loginpass=KKW1 5 loginpass=KKW1
6 #\u53D1\u9001\u62A5\u6587\u76EE\u5F55,\u76F8\u5BF9\u7A0B\u5E8F\u76EE\u5F55 6 #\u53D1\u9001\u62A5\u6587\u76EE\u5F55,\u76F8\u5BF9\u7A0B\u5E8F\u76EE\u5F55
7 -sendDirectory=D:/bw/sendDirectory 7 +sendDirectory=bw/send
8 #\u63A5\u6536\u5B58\u50A8\u62A5\u6587\u76EE\u5F55 8 #\u63A5\u6536\u5B58\u50A8\u62A5\u6587\u76EE\u5F55
9 receiveDirectory=D:/bw/receiveDirectory 9 receiveDirectory=D:/bw/receiveDirectory
10 #\u8F66\u5355\u5173\u7CFB\u62A5\u6587\u76EE\u5F55 10 #\u8F66\u5355\u5173\u7CFB\u62A5\u6587\u76EE\u5F55
1 #log4j=log_api.xml 1 #log4j=log_api.xml
2 2
3 isneedlog=N 3 isneedlog=N
4 -psip=10.50.3.74 4 +#psip=10.50.3.74
  5 +psip=192.168.1.53
5 psport=7484 6 psport=7484
6 encoding=UTF-8 7 encoding=UTF-8
7 8
@@ -43,13 +43,13 @@ public class IMF_Tesk { @@ -43,13 +43,13 @@ public class IMF_Tesk {
43 /** 43 /**
44 * 往IMF发送报文 44 * 往IMF发送报文
45 */ 45 */
46 - /*if(!KAKO_Sender.isrunning){  
47 - KAKO_Sender kako_sender = new KAKO_Sender(client);  
48 - kako_sender.start();  
49 - logger.info("<<<<<<<<<KAKO发送线程已开启>>>>>>>>>>>>");  
50 - }else {  
51 - logger.info("<<<<<<<<<KAKO发送线程已开启-不再启动线程>>>>>>>>>>>>");  
52 - }*/ 46 +// if(!KAKO_Sender.isrunning){
  47 +// KAKO_Sender kako_sender = new KAKO_Sender(client);
  48 +// kako_sender.start();
  49 +// logger.info("<<<<<<<<<KAKO发送线程已开启>>>>>>>>>>>>");
  50 +// }else {
  51 +// logger.info("<<<<<<<<<KAKO发送线程已开启-不再启动线程>>>>>>>>>>>>");
  52 +// }
53 53
54 } 54 }
55 if (!LOGIN_OK){ 55 if (!LOGIN_OK){
  1 +package com.sy.controller;
  2 +
  3 +public class FBresponse {
  4 + public String success = "true";
  5 + public String code = "200";
  6 + public String message = "验放成功";
  7 + public String info = "非保接口验放成功";
  8 +}
  1 +package com.sy.controller;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.springframework.http.MediaType;
  5 +import org.springframework.web.bind.annotation.PostMapping;
  6 +import org.springframework.web.bind.annotation.RequestBody;
  7 +import org.springframework.web.bind.annotation.RestController;
  8 +
  9 +@RestController
  10 +@Slf4j
  11 +public class ZBQResponseController {
  12 +
  13 + @PostMapping(value = "/xml", consumes = MediaType.APPLICATION_XML_VALUE)
  14 + public FBresponse handleXmlRequest(@RequestBody String xmlModel) {
  15 + log.info(xmlModel);
  16 + // 在这里对接收到的XML数据进行处理
  17 + // 可以将接收到的XML转换为对象,或进行其他操作
  18 + return new FBresponse();
  19 + }
  20 +}
  21 +
  22 +
  23 +
  24 +
  25 +
  1 +package com.sy.groovy
  2 +
  3 +import com.sy.model.GatherInfo
  4 +import com.sy.service.impl.GatherInfoHandle
  5 +import org.basis.enhance.groovy.entity.ExecuteParams
  6 +import org.springframework.context.ApplicationContext
  7 +
  8 +//转人工查验
  9 +class CustomsCheckScript extends Script implements ChannelCheckScript{
  10 +
  11 + Boolean check(ExecuteParams executeParams) {
  12 + String NORECORD = "转人工查验";
  13 + GatherInfo gatherInfo = (GatherInfo) executeParams.get("GatherInfo");
  14 + // 调用方法
  15 + ApplicationContext context = getContext();
  16 + // 获取容器中的bean
  17 + GatherInfoHandle gatherInfoHandle = context.getBean(GatherInfoHandle.class);
  18 +
  19 + gatherInfoHandle.sendBw(gatherInfo,false,NORECORD,null,null);
  20 +
  21 + return false
  22 + }
  23 +
  24 + @Override
  25 + Object run() {
  26 + return null
  27 + }
  28 +
  29 + // 获取spring容器
  30 + ApplicationContext getContext() {
  31 + // 获取spring IOC容器
  32 + ApplicationContext context = applicationContext;
  33 + return context;
  34 + }
  35 +}
  1 +package com.sy.groovy
  2 +
  3 +import com.alibaba.fastjson.JSON
  4 +import com.alibaba.fastjson.JSONArray
  5 +import com.alibaba.fastjson.JSONObject
  6 +import com.sy.model.GatherInfo
  7 +import com.sy.model.LandBusinessTypeList
  8 +import com.sy.model.LandRoadVe
  9 +import com.sy.response.ResultJson
  10 +import com.sy.service.CommandLogService
  11 +import com.sy.service.EnginCheckService
  12 +import com.sy.service.RedisService
  13 +import com.sy.service.feigin.G2X81FeignService
  14 +import com.sy.service.feigin.StationManageFeignService
  15 +import com.sy.socket.CommandClient
  16 +import org.apache.commons.lang.StringUtils
  17 +import org.basis.enhance.groovy.entity.ExecuteParams
  18 +import org.slf4j.Logger
  19 +import org.slf4j.LoggerFactory
  20 +import org.springframework.context.ApplicationContext
  21 +
  22 +import java.nio.charset.Charset
  23 +import java.text.SimpleDateFormat
  24 +
  25 +/**
  26 + * 特殊区域本地调拨分拨验放-综保区西货站
  27 + * 返回true 无后续返回,没有验放指令配合
  28 + * todo:需要改造成验放型.返回true false,某些业务类型需要强制走金二验放,海关智能卡口配置端也是根据通道进行配置的
  29 + */
  30 +class G2X21NoticeWithTrue extends Script implements ChannelCheckScript{
  31 + private final Logger log = LoggerFactory.getLogger(getClass());
  32 +
  33 + private static final String X21Template = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
  34 + "<GATHER_INFO AREA_ID=\"#{area_id}\" CHNL_NO=\"#{chnl_no}\" I_E_TYPE=\"#{ie_flag}\" SEQ_NO=\"#{session_id}\">\n" +
  35 + " <IC>\n" +
  36 + " <DR_IC_NO/>\n" +
  37 + " <IC_DR_CUSTOMS_NO/>\n" +
  38 + " <IC_CO_CUSTOMS_NO/>\n" +
  39 + " <IC_BILL_NO/>\n" +
  40 + " <IC_GROSS_WT/>\n" +
  41 + " <IC_VE_CUSTOMS_NO/>\n" +
  42 + " <IC_VE_NAME/>\n" +
  43 + " <IC_CONTA_ID/>\n" +
  44 + " <IC_ESEAL_ID/>\n" +
  45 + " <IC_EX_DATA/>\n" +
  46 + " </IC>\n" +
  47 + " <WEIGHT>\n" +
  48 + " <GROSS_WT>#{gross_wt}</GROSS_WT>\n" +
  49 + " </WEIGHT>\n" +
  50 + " <CAR>\n" +
  51 + " <VE_NAME>#{ve_license_no}</VE_NAME>\n" +
  52 + " <CAR_EC_NO>#{rfid_id}</CAR_EC_NO>\n" +
  53 + " <CAR_EC_NO2/>\n" +
  54 + " <VE_CUSTOMS_NO/>\n" +
  55 + " <VE_WT/>\n" +
  56 + " </CAR>\n" +
  57 + " <CONTA>\n" +
  58 + " <CONTA_NUM/>\n" +
  59 + " <CONTA_RECO>1</CONTA_RECO>\n" +
  60 + " <CONTA_MODEL_F/>\n" +
  61 + " <CONTA_MODEL_B/>\n" +
  62 + " <CONTA_ID_F/>\n" +
  63 + " <CONTA_ID_B/>\n" +
  64 + " </CONTA>\n" +
  65 + " <SEAL>\n" +
  66 + " <ESEAL_ID/>\n" +
  67 + " </SEAL>\n" +
  68 + " <BAR_CODE>#{bar_code}</BAR_CODE>\n" +
  69 + " </GATHER_INFO>";
  70 +
  71 + /**
  72 + * 海关发送报文封装模板
  73 + */
  74 + public static final String HAIGUAN_MQ_TEMPLATE = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
  75 + "<DxpMsg xmlns=\"http://www.chinaport.gov.cn/dxp\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ver=\"1.0\">\n" +
  76 + " <TransInfo>\n" +
  77 + " <CopMsgId>#{CopMsgId}</CopMsgId>\n" +
  78 + " <SenderId>GDXPKK0000000002</SenderId>\n" +
  79 + " <MsgType>#{MsgType}</MsgType>\n" +
  80 + " <CreatTime>#{CreatTime}</CreatTime>\n" +
  81 + " <ReceiverIds>\n" +
  82 + " <ReceiverId>GJCKK00000000001</ReceiverId>\n" +
  83 + " </ReceiverIds>\n" +
  84 + " </TransInfo>\n" +
  85 + " <Data>#{Data}</Data>\n" +
  86 + "</DxpMsg>";
  87 +
  88 + @Override
  89 + Object run() {
  90 + return null
  91 + }
  92 +
  93 +
  94 + /**
  95 + * 此接口不做抬杆判定,只做报文通知,返回只有false
  96 + */
  97 + Boolean check(ExecuteParams executeParams) {
  98 + try{
  99 + /**
  100 + * X21通道信息与流转信息比对
  101 + * 1. 从缓存获取车辆进出场申请信息,有流转信息再进行通道对碰.
  102 + * 无流转信息则说明缓存失效或者二维码不对.
  103 + */
  104 + GatherInfo info = (GatherInfo) executeParams.get("GatherInfo");
  105 + LandRoadVe ve = (LandRoadVe) executeParams.get("LandRoadVe");
  106 +
  107 + ApplicationContext context = getContext();
  108 + G2X81FeignService g2X81FeignService = context.getBean(G2X81FeignService.class);
  109 +
  110 + EnginCheckService enginCheckService = context.getBean(EnginCheckService.class);
  111 +
  112 + /**
  113 + * 写入本地验放通过信息
  114 + */
  115 + enginCheckService.commandlog(info,true,"双验放:本地验放通过:等待特殊区域验放指令",executeParams);
  116 +
  117 +
  118 +
  119 + if (info!=null){
  120 + //缓存X21 的 seqn 需要作为异步X82回执验放时用到的信息
  121 + cacheWithSeqno(info);
  122 + log.info("[G2-X81-CACHE]-车辆[{}]特殊区域流转已缓存[SEQNO]:{}",info.getVename(),info.getSeqno());
  123 + //将X21报文转换成X81格式
  124 + String xmlStr = x21TransToX81(info,ve);
  125 + //调用本地X81申报接口
  126 + ResultJson g2ResultJson = g2X81FeignService.send(xmlStr);
  127 + log.info("[G2-X81-API-RSP]-特殊区域通知接口返回,code:{},message:{},err:{}",g2ResultJson.getCode(),g2ResultJson.getMsg(),g2ResultJson.getError());
  128 + if ("200".equals(g2ResultJson.getCode())){
  129 + record(info,true,"已转特殊区域验放验放-[SEQN]:"+info.getSeqno(),null);
  130 + log.info("[G2-ROUTER-SUCCESS]-已转特殊区域验放路由成功-规则验放成功,SEQNO:{}",info.getSeqno());
  131 + return true;
  132 + }else{
  133 + record(info,false,"特殊区域接口访问失败",null);
  134 + log.error("[G2-X81-API-ERR]-特殊区域接口访问出错")
  135 + return false;
  136 + }
  137 + }else {
  138 + record(info,false,"特殊区域验放失败,未有相关通道流转申请信息",null);
  139 + CommandClient.Client(info,"特殊区域验放失败,未有相关通道流转申请信息");
  140 + }
  141 +
  142 + }catch (Exception e){
  143 + e.printStackTrace();
  144 + log.error("[G2-ROUTER-ERR]:",e);
  145 + return false;
  146 + }
  147 + return true;
  148 + }
  149 +
  150 + // 获取spring容器
  151 + ApplicationContext getContext() {
  152 + // 获取spring IOC容器
  153 + ApplicationContext context = applicationContext;
  154 + return context;
  155 + }
  156 +
  157 +
  158 +
  159 + void record(GatherInfo info, boolean result, String reason, LandBusinessTypeList landBusinessTypeList){
  160 + ApplicationContext context = getContext();
  161 + CommandLogService commandLogService = context.getBean(CommandLogService.class);
  162 + commandLogService.commandlog(info,result,reason,landBusinessTypeList,null,0.0,0.0,0.0,0.0);
  163 + }
  164 +
  165 +
  166 +
  167 + String x21TransToX81(GatherInfo gatherInfo,LandRoadVe ve){
  168 + log.info("[SEQN]-处理X21报文:{}",gatherInfo.getSeqno());
  169 + //当前时间作为X81申报时间
  170 + final SimpleDateFormat sdf = new SimpleDateFormat(
  171 + "yyyy-MM-dd HH:mm:ss");
  172 + final String startTime = sdf.format(new Date());
  173 +
  174 + //金二场站ID与通道ID替换
  175 + ApplicationContext context = getContext();
  176 + StationManageFeignService stationManageFeignService = context.getBean(StationManageFeignService.class);
  177 + log.info("[LOCAL-CHANNEL-NO]-{}",gatherInfo.getChnlno());
  178 + ResultJson resultJson = stationManageFeignService.getChanels(gatherInfo.getChnlno(),1,1);
  179 + log.info("[SERVICE-API-RES]-{}",JSON.toJSONString(resultJson))
  180 +
  181 + if ("200".equals(resultJson.getCode())){
  182 + JSONObject jsonObject = (JSONObject) resultJson.getData();
  183 + int total = jsonObject.getInteger("total");
  184 + if (total>0){
  185 + JSONArray jsonArray = jsonObject.getJSONArray("list");
  186 + JSONObject chanel = jsonArray.getJSONObject(0);
  187 + String channelG2 = chanel.getString("channelG2");
  188 + log.info("[G2-CHANNEL]-{}",channelG2);
  189 + JSONObject yard = chanel.getJSONObject("yard");
  190 + String stationG2 = yard.getString("stationIdG2");
  191 + log.info("[G2-YARD]-{}",stationG2);
  192 + String rfidNo = ve.getVeCustomsNo();
  193 + if (StringUtils.isEmpty(rfidNo)){
  194 + log.error("[VE-RFID-NO-ERR]:车辆-{}电子车牌信息未备案",gatherInfo.getVename());
  195 + record(gatherInfo,false,"车辆电子车牌信息未备案",null);
  196 + }else {
  197 + //todo: 这里取的是车辆备案电子车牌字段.实际上 IC卡号应该是一个字段
  198 + log.info("[VE-RFID-NO]:车辆电子车牌号:{}",rfidNo);
  199 + }
  200 +
  201 +
  202 + //各脚本维护各脚本的模板吧
  203 + String x21XML= X21Template.replace("#{ie_flag}",gatherInfo.getIetype())
  204 + .replace("#{area_id}",stationG2)
  205 + .replace("#{chnl_no}",channelG2)
  206 + .replace("#{session_id}",gatherInfo.getSeqno())
  207 + .replace("#{ve_license_no}",gatherInfo.getVename())
  208 + .replace("#{gross_wt}",gatherInfo.getGrosswt().toString())
  209 + .replace("#{rfid_id}",rfidNo)
  210 + .replace("#{ve_wt}",ve.getSelfWt())
  211 + .replace("#{bar_code}",gatherInfo.getBarcode());
  212 + log.info("[X21]-{}",x21XML);
  213 + String mqXMLStr = mqXMLMake(x21XML,gatherInfo.getSeqno(),startTime);
  214 + log.info("[X21]-加密后的报文为:{}",mqXMLStr)
  215 + return mqXMLStr;
  216 +
  217 + }else {
  218 + throw new Exception("未获取到通道金二配置信息")
  219 + }
  220 +
  221 + }else {
  222 + log.error("场站管理服务接口访问失败")
  223 + }
  224 +
  225 + return "";
  226 + }
  227 +
  228 + String mqXMLMake(String xmlStr,String copMsgId,String creatTime){
  229 + String base64EncodeToString = Base64.getEncoder().encodeToString(xmlStr.getBytes(Charset.forName("utf-8")));
  230 + log.info("[SEND-BASE64-ENCODE]-{}",base64EncodeToString)
  231 +
  232 + return HAIGUAN_MQ_TEMPLATE.replace("#{CopMsgId}",copMsgId)
  233 + .replace("#{CreatTime}",creatTime)
  234 + .replace("#{MsgType}","QNLZ")
  235 + .replace("#{Data}",base64EncodeToString);
  236 + }
  237 +
  238 + void cacheWithSeqno(GatherInfo info){
  239 + ApplicationContext context = getContext();
  240 + RedisService redisService = context.getBean(RedisService.class);
  241 + if (info!=null && StringUtils.isNotEmpty(info.getSeqno())) {
  242 + redisService.set(info.getSeqno(), JSON.toJSONString(info),60*60*24*3);
  243 + }
  244 + }
  245 +}
@@ -136,6 +136,23 @@ public class EnginCheckServiceImpl implements EnginCheckService { @@ -136,6 +136,23 @@ public class EnginCheckServiceImpl implements EnginCheckService {
136 executeParams.put("selfWt", 0.0); 136 executeParams.put("selfWt", 0.0);
137 executeParams.put("goodsWt", 0.0); 137 executeParams.put("goodsWt", 0.0);
138 138
  139 + //适应高清车牌采集,反向填充二维码 gatherInfo中没有二维码信息的情况
  140 + if (StringUtils.isEmpty(gatherInfo.getBarcode())) {
  141 + //从申请缓存获取二维码信息
  142 + String landBusnessInfoJsonStr = redisService.get(gatherInfo.getVename());
  143 + JSONArray array = JSONArray.parseArray(landBusnessInfoJsonStr);
  144 + String carBarcode = array.getJSONObject(0).getString("barcode");
  145 + if (StringUtils.isEmpty(carBarcode)){
  146 + log.error("[BARCODE-RESET-ERR]-从流转申请信息反向填充车辆{}二维码失败",gatherInfo.getVename());
  147 + }else {
  148 + gatherInfo.setBarcode(carBarcode);
  149 + log.info("[BARCODE-RESET]-车牌{}流转申请二维码重置为{}",gatherInfo.getVename(),carBarcode);
  150 + }
  151 + }
  152 +
  153 +
  154 +
  155 +
139 //车辆备案信息 156 //车辆备案信息
140 LandRoadVe ve = veService.selectByFrameNo(gatherInfo.getVename()); 157 LandRoadVe ve = veService.selectByFrameNo(gatherInfo.getVename());
141 if (ve != null) { 158 if (ve != null) {
@@ -138,7 +138,9 @@ public class LandBusListServiceImpl implements LandBusListService { @@ -138,7 +138,9 @@ public class LandBusListServiceImpl implements LandBusListService {
138 /** 138 /**
139 * 通道对碰有了.二维码不一致怎么办? 139 * 通道对碰有了.二维码不一致怎么办?
140 */ 140 */
141 - if (item.getBarcode().equals(gatherInfo.getBarcode()) && item.getAisle().equals(gatherInfo.getChnlno())){ 141 + if (item.getAisle().equals(gatherInfo.getChnlno())
  142 + && item.getBarcode().equals(gatherInfo.getBarcode())
  143 + ){
142 if (item.getBarcode().equals(gatherInfo.getBarcode())){ 144 if (item.getBarcode().equals(gatherInfo.getBarcode())){
143 log.info("车辆-{}的申请缓存信息核碰成功,通道:{}",gatherInfo.getVename(),gatherInfo.getChnlno()); 145 log.info("车辆-{}的申请缓存信息核碰成功,通道:{}",gatherInfo.getVename(),gatherInfo.getChnlno());
144 return item; 146 return item;