|  |  | 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.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 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) | 
|  |  | 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; | 
|  |  | } | 
|  |  |  | 
|  |  | } | 
... | ... |  |