海关179号文件对接

海关179号文件对接

May 08, 2022 · 3 mins read

折腾了几天终于将对接179号文件弄好了。网上各种资料还是挺多的,但是感觉又说的不够完整。

为什么要对接179号文件

海关相关文件

很多人疑惑我已经支付报关了,为什么还要做这个么玩意呢?其实这个179号文件是给个接口给海关来抽查需要清关的订单跟支付相关的信息。

前置条件

  1. 企业已经在海关备案成功,获得海关备案编码,并且拿到加签用的ukey。

业务流程:

  1. 电商系统提供一个公开的接口(查询接口A)给海关,该接口地址需要在中国电子口岸官网进行配置;
  2. 海关通过接口A发送请求,电商系统收到请求后, 封装查询订单数据,并对的数据加签;
  3. 企业将加签的后的数据按照指定的格式发送给海关

179-flow

第二步加签是需要在一个插着海关加签ukey的windows系统上(ukey的驱动只有windows的)。一般的做法就是找一个windows系统的电脑即可。并且将加签的逻辑做成一个本地执行的包通过webwocket 或者轮询亦或者是MQ的方式来监听电商系统中需要加签的数据。

获取证书号certNo与证书

参考的相关文件和源码

工具链接:

https://pan.baidu.com/s/1BWiudH00qngdB8rmlqDMrw 提取码:ln17

1132920-20190517113902092-758512868.png

在windowns电脑上 插上ukey 打开 3-debug_海关证书信息获取插件.rar 可以用这个工具获取证书编号跟证书内容, 将证书内容拷贝出来,修改文件后缀名为 .cer 即可。

然后登陆 中国电子口岸官网 将刚获取的证书编号跟证书上传。 证书编号中的字母一定要小写

1132920-20190517110525140-1674644836.png

查询接口A 开发

@PostMapping(value = "/platDataOpen", headers = "content-type=application/x-www-form-urlencoded")
    public JSONObject platDataOpen(@RequestParam String openReq) {
        // 1. 解析获取数据
        openReq = StringUtils.replace(openReq, """, "\"");
        JSONObject json = JSONObject.parseObject(openReq);
        String orderNo = json.getString("orderNo");
        String sessionID = json.getString("sessionID");
        String serviceTime = json.getString("serviceTime");

        log.info("====orderNo: {}, sesssionId: {}, serviceTime: {}", orderNo, sessionID, serviceTime);

        Customs entity = customsService.buildCustom(orderNo, sessionID);

        StringBuffer sb = new StringBuffer();
        sb.append("\"sessionID\":\"").append(entity.getSessionID()).append("\"").append("||");
        String headerString = JSON.toJSONString(entity.getPayExchangeInfoHead(), SerializerFeature.SortField);
        sb.append("\"payExchangeInfoHead\":\"").append(headerString).append("\"").append("||");
        String listString = JSON.toJSONString(entity.getPayExchangeInfoLists(), SerializerFeature.SortField);
        sb.append("\"payExchangeInfoLists\":\"").append(listString).append("\"").append("||");
        sb.append("\"serviceTime\":\"").append(entity.getServiceTime()).append("\"");
        String signValue = sb.toString();

        log.info("====signValue: {}", signValue);

        //组装加签数据
        JSONObject exchangeData = new JSONObject();
        exchangeData.put("inData", signValue);
        exchangeData.put("sessionId", sessionID);
        exchangeData.put("orderNo", orderNo);

        // 2. 将数据放入redis
        bladeRedis.hSet(DECLARE_DATA_KEY, sessionID, exchangeData.toJSONString());
        bladeRedis.set(CUSTOM_DATA_PREFIX.concat(orderNo), entity);

        // 3. 返回数据
        JSONObject result = new JSONObject();
        result.put("code", "10000");
        result.put("message", "");
        result.put("serviceTime", System.currentTimeMillis());
        return result;
    }