G2X21NoticeWithTrue.groovy 10.7 KB
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.getIcCode();
                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}","QGDB")
        .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);
        }
    }
}