• 海关 实时数据 企业联调接口 开发步骤与概要


    写这个文章前, 先呐喊几声, 一吐心中不快, 诺大的中国海关, 连个指导都没有, 写的文档与demo, 100个人有99.9个人不懂, 还有0.1个人一次能懂的都算是神童, 

    首先, 中国海关数据中心, 经过这个接口的实现, 我感觉到政府的技术落后,不要说芯片, 就连最简单的1+1=2的程序在政府部门都写复杂又困难, 主要还没写一个全面完善使用的文档, 实在是可悲。

    如果能骂人的, 我接着写, 不过还是提倡文明, 就不吐了。

    正题啦:

    第一步:

    看二个公告

    http://www.customs.gov.cn/customs/302249/302266/302267/2134975/index.html 165号

    http://www.customs.gov.cn/customs/302249/302266/302267/2155884/index.html 179号

    第二步:

    下载179号公告文档, 文档包括下面

    第三步:

    打开“海关跨境电商进口版统一信息化系统平台数据实时获取接口(试行)”, 请看1.6.1.1 这里得知, 需要写一个接口, 让海关请求带三个参数OrderNo, sessionID,serviceTime,  把这三个参数存放起来,  可以是消息队列, 可以是数据库, 总之你能再次找得到就行。

    第四步: 

    既然在第三步接收到海关请求的内容也存放起来了, 总得处理并把他们想要的数据返回给海关, 这里就介绍怎得到需要返回的数据, 最关键的一步, 请看1.6.2.2, 订单,商品,支付这些数据, 可能通过OrderNo在你们电商平台得到, 最麻烦的就是CertNo, signValue这二个参数,

    官方文档把最难得到的参数用123来代替, 我感觉到无奈。

    4.1 得去公司找到一个海关登录的IC卡,有一个读卡器, 一般有二个卡(法人卡,操作员卡),记得把操作员卡接到读卡器里, 不能是法人卡,这个十分注意。

    4.2 下载海关控件安装包, 打开这个网址 http://ceb1.chinaport.gov.cn/  , 点 跨境电商进口版, 认真查找“首次登录 需要下载控件”, 点击下载 EportClientSetup_V1.5.5.exe, 请看清楚下载的文件名是不是这个, 这也是十分重要, 如果你千百次对比没错后, 请安装它, 安装完成电脑屏幕右下角会有一个控件启动提醒, 桌面也有一个快捷方式“中国电子口岸客户端控件 重新启动”。 

    4.3 把4.1步里面找到的读卡器接上电脑, 记得这个电脑要安装了海关控件的, 千万不要搞成, A电脑装了控件, 把这读卡器接B电脑上。 如果读卡器出现绿灯, 说明读卡器与卡都没问题, 如果是灯不亮或红灯, 不好意思, 你的卡与读卡器可能有问题了,得找另一个卡与读卡器再试。

    4.4 当环境设置好了, 就需要取CertNo, 证书这些, 下载这个读取编号与证书的工具: https://pan.baidu.com/s/1xo0AcZZ4QZDeAu2DHOEQjg   提取码: cfpp , 解压打开SignTool.exe

    点击步骤:打开卡, 如果出现打开卡成功, 恭喜你, 又前进一步,在验证口令后面的文本框输入设置的密码, 这个密码得问一下你们公司掌管卡的人,如果录入后点击 验证口令 提示 验证口令成功, 又恭喜你前进一步, 点击“获取证书”, 成功的会得到后面文本框里的一串文字, 注意这个文字好长好长, 得小心从文本框里最上方拉到最下方, 很多人没拉到底, 造成证书错误, 当你选择全部后复制出来, 用记事本原封不动的保存, 改后缀名为.cer, 这样就成他们口中所说的证书了, 再点击证书序列号,会得到一个证书编号。

    发给海关的丁鑫, 并登记企业名称, 企业联系人等信息, 总之找他就行了, 怎找呢, 看文章最后一个图。

    到这里, 只差一个signValue这个千奇百怪的东西了。

    第五步:

    誓取signValue这个海关奇怪设计失败货, 一千种方法都可以简单得到, 他们设计出一个最麻烦最不稳定的取得方法, 真的拿他们没办法, 满脸的无奈。

    5.1 首先你要看那个"海关跨境电商进口版统一信息化系统平台数据实时获取接口(试行)"文档, 通过OrderNo把你订单信息,商品信息,支付信息拼成这样的Json, 你也可以用这个来测试, 测试通了, 再取订单来拼接, 如果后面发送得到数据格式有误, 你就得一个字符一个字符的去对, 是否一模一样。

    "sessionID":"fe2374-8fnejf97-55616242"||"payExchangeInfoHead":"{"guid":"9D55BA71-55DE-41F4-8B50-C36C83B3B419","initalRequest":"https://openapi.alipay.com/gateway.do?timestamp=2013-01-0108:08:08&method=alipay.trade.pay&app_id=13580&sign_type=RSA2&sign=ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE&version=1.0&charset=GBK","initalResponse":"ok","ebpCode":"3301963K69","payCode":"312226T001","payTransactionId":"2018121222001354081010726129","totalAmount":100,"currency":"142","verDept":"3","payType":"1","tradingTime":"20181212041803","note":"批量订单,测试订单优化,生成多个so订单"}"||"payExchangeInfoLists":"[{"orderNo":"SO1710301150602574003","goodsInfo":[{"gname":"lhy-gnsku3","itemLink":"http://m.yunjiweidian.com/yunjibuyer/static/vue-buyer/idc/index.html#/detail?itemId=999761&shopId=453"},{"gname":"lhy-gnsku2","itemLink":"http://m.yunjiweidian.com/yunjibuyer/static/vue-buyer/idc/index.html#/detail?itemId=999760&shopId=453"}],"recpAccount":"OSA571908863132601","recpCode":"","recpName":"YUNJIHONGKONGLIMITED"}]"||"serviceTime":"1544519952469"

    得到了这段拼接字符, 就是为了得到signValue, 所以一个字符也不能出错, 不然取不到正确的加签返回值。

    5.2 这里最主要的就是通过websocket取得加签结果

    我这里写的是C#版的, Java版的我是向一位善心的张工程师那得到的,在这里十分感谢张工, 并感谢他的大无畏精神,

    Java 张工版下载地址: https://pan.baidu.com/s/1beifsbtA7fXmi4vJ3c2Kjw 提取码: jdev  

    记得一个前提, websocket的地址就是你装有控件,插有卡的那个电脑的IP地址, 例如:ws://127.0.0.1:61232, 这是我在开发时, 在我自己的电脑上装有控件插有卡, 得来的websocket地址。

    C# 版, 现在大家多用win7, win7不支持ClientWebSocket, 所以我使用了第三方包,WebSocket4Net, 在VS2015 NuGet上面直接安装, 最终写出最简单的明了取得加签返回值

    注意: 看代码里面查找到  "passwd":"66666666"              66666666要改为你公司IC卡的密码, 这个是我随机设置的

    using System;
    using System.Text;
    using WebSocket4Net;
    using SuperSocket.ClientEngine;
    
    namespace ConsoleApp
    {
        public class Program
        {
            static WebSocket websocket = new WebSocket("ws://127.0.0.1:61232");
    
            public static void Main(string[] args)
            {
                try
                {                
                    websocket.Opened += new EventHandler(websocket_Opened);
                    websocket.Error += new EventHandler<ErrorEventArgs>(websocket_Error);
                    websocket.Closed += new EventHandler(websocket_Closed);
                    websocket.MessageReceived += new EventHandler<MessageReceivedEventArgs>(websocket_MessageReceived);
                    websocket.Open();                
    
                    Console.WriteLine("");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                Console.ReadLine();
            }
    
            private static void websocket_Opened(object sender, EventArgs e)
            {
                Console.WriteLine("websocket opened!" + DateTime.Now.ToString());
            }
    
            private static void websocket_Error(object sender, ErrorEventArgs e)
            {
                Console.WriteLine("websocket error!");
                Console.WriteLine("Error:" + e.Exception.Message.ToString());
            }
    
            private static void websocket_Closed(object sender, EventArgs e)
            {
                Console.WriteLine("websocket closed!" + DateTime.Now.ToString());
            }
    
            private static void websocket_MessageReceived(object sender, MessageReceivedEventArgs e)
            {
                Console.WriteLine("websocket message received!");
                string strMessaged = e.Message.ToString().Trim();
                if (strMessaged.Contains("握手成功"))
                {
                    StringBuilder PostJson = new StringBuilder();
                    PostJson.Append(""sessionID":"fe2374-8fnejf97-55616242"||"payExchangeInfoHead":"{"guid":"9D55BA71-55DE-41F4-8B50-C36C83B3B419","initalRequest":"https://openapi.alipay.com/gateway.do?timestamp=2013-01-0108:08:08&method=alipay.trade.pay&app_id=13580&sign_type=RSA2&sign=ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE&version=1.0&charset=GBK","initalResponse":"ok","ebpCode":"3301963K69","payCode":"312226T001","payTransactionId":"2018121222001354081010726129","totalAmount":100,"currency":"142","verDept":"3","payType":"1","tradingTime":"20181212041803","note":"批量订单,测试订单优化,生成多个so订单"}"||"payExchangeInfoLists":"[{"orderNo":"SO1710301150602574003","goodsInfo":[{"gname":"lhy-gnsku3","itemLink":"http://m.yunjiweidian.com/yunjibuyer/static/vue-buyer/idc/index.html#/detail?itemId=999761&shopId=453"},{"gname":"lhy-gnsku2","itemLink":"http://m.yunjiweidian.com/yunjibuyer/static/vue-buyer/idc/index.html#/detail?itemId=999760&shopId=453"}],"recpAccount":"OSA571908863132601","recpCode":"","recpName":"YUNJIHONGKONGLIMITED"}]"||"serviceTime":"1544519952469"");
    
                    string strJson = PostJson.ToString();
    
                    string strSendData0 = "{"_method":"cus-sec_SpcSignDataAsPEM","_id":1,"args":{"inData":"" + strJson.Replace(""","\"") + "","passwd":"66666666"}}";
                    //string strSendData1 = "{"_method":"cus-sec_SpcSignDataAsPEM","_id":1,"args":{"inData":"\"sessionID\":\"1dd44ea3-202a-43e7-87a5-6d82ca3fce4f\"||\"payExchangeInfoHead\":\"{\"guid\":\"9D55BA71-55DE-41F4-8B50-C36C83B3B419\",\"initalRequest\":\"https://openapi.alipay.com/gateway.do?timestamp=2013-01-0108:08:08&method=alipay.trade.pay&app_id=13580&sign_type=RSA2&sign=ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE&version=1.0&charset=GBK\",\"initalResponse\":\"ok\",\"ebpCode\":\"xxxxxxxx\",\"payCode\":\"312226T001\",\"payTransactionId\":\"2018121222001354081010726129\",\"totalAmount\":100,\"currency\":\"142\",\"verDept\":\"3\",\"payType\":\"1\",\"tradingTime\":\"20181212041803\",\"note\":\"批量订单,测试订单优化,生成多个so订单\"}\"||\"payExchangeInfoLists\":\"[{\"orderNo\":\"SO1710301150602574003\",\"goodsInfo\":[{\"gname\":\"lhy-gnsku3\",\"itemLink\":\"http://m.yunjiweidian.com/yunjibuyer/static/vue-buyer/idc/index.html#/detail?itemId=999761&shopId=453\"},{\"gname\":\"lhy-gnsku2\",\"itemLink\":\"http://m.yunjiweidian.com/yunjibuyer/static/vue-buyer/idc/index.html#/detail?itemId=999760&shopId=453\"}],\"recpAccount\":\"OSA571908863132601\",\"recpCode\":\"\",\"recpName\":\"YUNJIHONGKONGLIMITED\"}]\"||\"serviceTime\":\"1544519952469\"","passwd":"66666666"}}";
                    //string strSendData2 = "";
                    
                    //Console.WriteLine(strSendData0);
                    //Console.WriteLine("------------------------------------------");
                    //Console.WriteLine(strSendData1);
                    websocket.Send(strSendData0);
                }
                else
                {
                    Console.WriteLine(strMessaged);
                }
                websocket.Close();
            }
        }
    }
    View Code

    得到的返回值是如图,data就是加签的signValue, 起快把奇怪货关起来, 我在海关微信群里面, 无数工程师为了得到这个, 花上好几天还没有头绪。 

    用其它语言来写也行的, 只是要把websocket send的内容改为json,  但发送的内容得一模一样, 这段是张工发给我的发送给websocket加签的内容。 看清楚必须格式一模一样, 提示\sessionID\, 看清楚这个。

    "{"_method":"cus-sec_SpcSignDataAsPEM","_id":1,"args":{"inData":"\"sessionID\":\"1dd44ea3-202a-43e7-87a5-6d82ca3fce4f\"||\"payExchangeInfoHead\":\"{\"guid\":\"9D55BA71-55DE-41F4-8B50-C36C83B3B419\",\"initalRequest\":\"https://openapi.alipay.com/gateway.do?timestamp=2013-01-0108:08:08&method=alipay.trade.pay&app_id=13580&sign_type=RSA2&sign=ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE&version=1.0&charset=GBK\",\"initalResponse\":\"ok\",\"ebpCode\":\"xxxxxxxx\",\"payCode\":\"312226T001\",\"payTransactionId\":\"2018121222001354081010726129\",\"totalAmount\":100,\"currency\":\"142\",\"verDept\":\"3\",\"payType\":\"1\",\"tradingTime\":\"20181212041803\",\"note\":\"批量订单,测试订单优化,生成多个so订单\"}\"||\"payExchangeInfoLists\":\"[{\"orderNo\":\"SO1710301150602574003\",\"goodsInfo\":[{\"gname\":\"lhy-gnsku3\",\"itemLink\":\"http://m.yunjiweidian.com/yunjibuyer/static/vue-buyer/idc/index.html#/detail?itemId=999761&shopId=453\"},{\"gname\":\"lhy-gnsku2\",\"itemLink\":\"http://m.yunjiweidian.com/yunjibuyer/static/vue-buyer/idc/index.html#/detail?itemId=999760&shopId=453\"}],\"recpAccount\":\"OSA571908863132601\",\"recpCode\":\"\",\"recpName\":\"YUNJIHONGKONGLIMITED\"}]\"||\"serviceTime\":\"1544519952469\"","passwd":"11111111"}}"

    这里取得了加签的内容, 就可以拼凑成返回海关的报文。 记得这里只是拼接报文成功, 你还得联系海关二位员工, 张丁二将, 把上面4.4得到的证书与编号发给他们, 然后请他们帮助你设置海关测试环境。 

    最后说一下, 本人十几年开发工作也经过N次千万级的系统开发与构架, 每秒都是几百几千请求,  面对这小小的不成文不成档的奇怪接口, 也曾发火几次, 写这个文章主要是给后人能简单些, 减少折腾, 希望这文章对大家有用! 

    同时也建议, 各位开发工程师, 如果自己有接口对外的, 希望能认真写写详细的文档, 因为自己做的东西可以感觉很简单, 外人看来还是有复杂度的, 像这个接口, 明明涉及硬件软件, 他文档里一句不提, 最重要的signvalue得来, 居然没详细的方法, 直接用123来代替,浪费开发者的时间, 万望各位开发工程师引以为介, 从大家做起, 不要让简单的事复杂起来。 

  • 相关阅读:
    获取图片的大小(宽高):BytesIO
    python中url解析 or url的base64编码
    [extjs5学习笔记]第三十七节 Extjs6预览版都有神马新东西
    【翻译】Ext JS 6早期访问版本发布
    【翻译】Ext JS 6有什么新东西?
    【Java二十周年】Delphi转行java的一些小感触
    Cursor类取出数据
    通过服务修改widgetUI
    安卓笔记--Style的继承
    [ExtJS5学习笔记]第三十六节 报表组件mzPivotGrid
  • 原文地址:https://www.cnblogs.com/whtydn/p/10220209.html
Copyright © 2020-2023  润新知