G2X21NoticeToSamples.groovy 11.1 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 java.net.Socket;
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.text.SimpleDateFormat

/**
 * 同步采集信息给三宝一份
 * 特殊区域本地调拨分拨验放
 * 必须返回false 为异步验放,
 * 将采集报文回传给三宝指定接口,后续由三宝进行海关端那边的工控机展示以及接收指令抬杆.
 * todo:需要改造成验放型.返回true false,某些业务类型需要强制走金二验放,海关智能卡口配置端也是根据通道进行配置的
 */
class G2X21NoticeToSamples 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>";


    @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();
            EnginCheckService enginCheckService = context.getBean(EnginCheckService.class);

            /**
             * 写入本地验放通过信息
             */
            enginCheckService.commandlog(info,true,"口岸放行,已转至特殊区域验放",executeParams);

            if (info!=null){
                //将X21报文转换成X81格式
                String xmlStr = x21TransToX81(info,ve);

            }else {
                record(info,false,"特殊区域验放失败,未有相关通道流转申请信息",null);
                CommandClient.Client(info,"特殊区域验放失败,未有相关通道流转申请信息");
            }

        }catch (Exception e){
            e.printStackTrace();
            log.error("[G2-ROUTER-ERR]:",e);
        }
        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 IE_TYPE="I";
                if ("I".equals(gatherInfo.getIetype())){
                    IE_TYPE = "E"
                }

                if ("E".equals(gatherInfo.getIetype())){
                    IE_TYPE = "I"
                }



                //各脚本维护各脚本的模板吧
                String x21XML= X21Template.replace("#{ie_flag}",IE_TYPE)
                        .replace("#{area_id}","4612329012")
                        .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);

                sendWithSocket_x21(x21XML,"4612329012",channelG2,IE_TYPE)
                log.info("[X21-同步]-success")
                return x21XML;

            }else {
                throw new Exception("未获取到通道金二配置信息")
            }

        }else {
            log.error("场站管理服务接口访问失败")
        }

        return "";
    }

    void sendWithSocket_x21(String xmlBody,String areaID,String chnlNo,String IEtype){
        Socket socket =null;
        OutputStream op = null;
        try {
            //ip+端口
            socket = new Socket("10.50.28.38", 9072);
            log.info("socket通讯创建连接成功");
            op = socket.getOutputStream();
            //xml字节流
            byte[]xBody =xmlBody.getBytes("GB2312");
            //包头
            byte[] head = new byte[4];
            head[0]=(byte)0xE2;
            head[1]=(byte)0x5C;
            head[2]=(byte)0x4B;
            head[3]=(byte)0x89;
            //消息类型,0x21为gatherInfo 0x22为commandInfo
            byte[] mType = new byte[1];
            mType[0] = (byte)0x21;
            //场站号
            byte[]station =areaID.getBytes("ASCII");
            //通道号
            byte[]aisle =chnlNo.getBytes("ASCII");
            //进出标识
            byte[]eType =IEtype.getBytes("ASCII");
            //标识符
            byte[] bwFlag = new byte[4];
            bwFlag[0]=(byte)0x00;
            bwFlag[1]=(byte)0x00;
            bwFlag[2]=(byte)0x00;
            bwFlag[3]=(byte)0x00;
            //xml字节流长度
            byte[]xmlLength = intToByte4(xBody.length);
            //包尾
            byte[]end = new byte[2];
            end[0]=(byte)0xFF;
            end[1]=(byte)0xFF;
            System.out.println();
            //总长 4为总长的length
            byte [] packge = intToByte4((head.length+xBody.length+mType.length+station.length+aisle.length+eType
                    .length+bwFlag.length+xmlLength.length+end.length+4));
            byte[]allByte = byteMergerAll(head,packge,mType,station,aisle,eType,bwFlag,xmlLength,xBody,end);
            op.write(allByte);
            op.flush();
            op.close();
            log.info("发送完毕");
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            log.info("创建连接失败"+e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
            log.info("文件发送失败"+e.getMessage());
        }
    }

    //int转byte
    byte[] intToByte4(int i) {
        byte[] targets = new byte[4];
        //低位到高位
        targets[0] = (byte) (i & 0xFF);
        targets[1] = (byte) (i >> 8 & 0xFF);
        targets[2] = (byte) (i >> 16 & 0xFF);
        targets[3] = (byte) (i >> 24 & 0xFF);
        return targets;
    }

    //合并byte数据
    private static byte[] byteMergerAll(byte[]... values) {
        int length_byte = 0;
        for (int i = 0; i < values.length; i++) {
            length_byte += values[i].length;
        }
        byte[] all_byte = new byte[length_byte];
        int countLength = 0;
        for (int i = 0; i < values.length; i++) {
            byte[] b = values[i];
            System.arraycopy(b, 0, all_byte, countLength, b.length);
            countLength += b.length;
        }
        return all_byte;
    }

}