轻墨随笔

关于菜鸟的圆通电子面单打印

  1. https://open.taobao.com/docs/doc.htm?spm=a21da.7629140.0.0.97iBG8&docType=1&articleId=107052 电子面单接入文档(LINK接入)
  2. https://dayin.cainiao.com/miandan/subscription/branchRechargeInfo.htm?spm=a2d3a.8498240.0.0.558119b3hxhtix 订购关系查询
  3. https://lcp.cloud.cainiao.com/ 后台地址
  4. http://pac.i56.taobao.com/apiinfo/showDetail.htm?spm=0.0.0.0.3tcf05&apiId=TMS_WAYBILL_SUBSCRIPTION_QUERY&type=merchant_electronic_sheet API地址

前面的地址是需要仔细看的,我做的电子面单打印是依靠菜鸟的打印组件预览出来再手动打印,并不是全部用菜鸟的打印组件打印,下面是正式的介绍情况了.

第一步

申请需要申请的账号,这些你就看文档,我也帮不了你什么,我也是别人先申请我在用的.

第二部

单独创建一个控制器,这是控制器的内容,我并不是靠ajax传递数据到控制器接收的,而是用form表单提交,这里说清楚,接收的数据按照你要传递的情况自己组装

1    //圆通信息
 2                     $a=time()+1;//随机订单号
 3                     $b=time();//随机包裹号      这两个参数不许是变量,不然每次返回的快递单号都是同一个,也就是合单,你也可以在群里问客服
 4 //下面是需要传递到接口的数据
 5                     $eorderi ='{"cpCode":"YTO","dmsSorting":"false","needEncrypt":"false","resourceCode":"无",
 6         "sender":{
 7             "address":{
 8                 "city":"宿迁市",
 9                 "detail":"淮海东路*********",
10                 "district":"泗阳县",
11                 "province":"江苏省",
12                 "town":""
13             },
14             "mobile":"18***742",
15             "name":"曲*",
16             "phone":"1865***42",
17         },//这些是发货地址,和你在订购关系里申请的内容要一样
18         "storeCode":"无",
19         "tradeOrderInfoDtos":[
20             {
21                 "logisticsServices":"",
22                 "objectId":"1",
23                 "orderInfo":{
24                     "orderChannelsType":"OTHERS",
25                     "tradeOrderList":[
26                         "'.$a.'"//订单号
27                     ]
28                 },
29                 "packageInfo":{
30                     "id":"'.$b.'",//包裹号
31                     "items":[
32                         {
33                             "count":"'.$total_number.'",
34                             "name":"衣服"
35                         }
36                     ],
37                     "volume":"1",
38                     "weight":"1"
39                 },
40                 "recipient":{
41                     "address":{
42                         "city":"'.$ship_order_data['city'].'",
43                         "detail":"'.$ship_order_data['address'].'",
44                         "district":"'.$ship_order_data['exparea'].'",
45                         "province":"'.$ship_order_data['province'].'",
46                         "town":""
47                     },
48                     "mobile":"'.$ship_order_data['phone'].'",
49                     "name":"'.$ship_order_data['username'].'",
50                     "phone":"'.$ship_order_data['phone'].'"
51                 },//这些是发货地址
52                 "templateUrl":" http://cloudprint.cainiao.com/template/standard/101/572",//我用的是圆通,所以这是模板的地址,自己在API里面找
53                 "userId":"12"//随便填写
54             }
55         ]
56     }';57     58    $jsonResult = $this->submitEOrderi($eorderi);5960    $str=json_decode($jsonResult);      
      $this->assign('list',$str->waybillCloudPrintResponseList[0]->printData);//只需要打印里面的printData里的数据
      return $this->fetch('ce');//新写一个空白的前端.数据在那边接收

第三部

后端代码

//圆通电子面单接口

    /**
     * Json方式 调用电子面单接口
     */
    public function submitEOrderi($requestData)
    {
        $url='http://link.cainiao.com/gateway/link.do';//正式地址  必须


        $appSecret ='z026yj********83S3B6cv86';必须
//
        $datas = array(
            'msg_type' =>'TMS_WAYBILL_GET',
            'logistic_provider_id' =>'UFI1c3dkR2tNRWpX*********************1zWWZxS2V5Y1FrWi90K21jelhOSTMwQ3pKaA==',必须

            'data_digest'=>$this->encrypti($requestData,$appSecret),//获取签名
            'logistics_interface' =>$requestData,
        );

        $result = $this->sendPosti($url,$datas);提交数据

        return $result;
    }
    /**
     * 电商Sign签名生成
     * @param data 内容
     * @param appkey Appkey
     * @return DataSign签名
     */
    public function encrypti($data,$appSecret)
    {
        return base64_encode(md5($data.$appSecret,true));
    }
    /**
     *  post提交数据
     * @param  string $url 请求Url
     * @param  array $datas 提交的数据
     * @return url响应返回的html
     */

    function sendPosti($url, $datas) {
        $temps = array();
        foreach ($datas as $key => $value) {
            $temps[] = sprintf('%s=%s', $key, $value);
        }
        $post_data = implode('&', $temps);
        $url_info = parse_url($url);
        if(empty($url_info['port']))
        {
            $url_info['port']=80;
        }
        $httpheader = "POST " . $url_info['path'] . " HTTP/1.0\r\n";
        $httpheader.= "Host:" . $url_info['host'] . "\r\n";
        $httpheader.= "Content-Type:application/x-www-form-urlencoded\r\n";
        $httpheader.= "Content-Length:" . strlen($post_data) . "\r\n";
        $httpheader.= "Connection:close\r\n\r\n";
        $httpheader.= $post_data;
        $fd = fsockopen($url_info['host'], $url_info['port']);
        fwrite($fd, $httpheader);
        $gets = "";
        $headerFlag = true;
        while (!feof($fd)) {
            if (($header = @fgets($fd)) && ($header == "\r\n" || $header == "\n")) {
                break;
            }
        }
        while (!feof($fd)) {
            $gets.= fread($fd, 128);
        }
        fclose($fd);

        return $gets;
    }

前端页面的代码

<include file="public@header"/>
<head>
    <title>Print Test</title>

    <style type="text/css">

        /*div#ctlDiv {height:750px;width:50%;float:left;border-style:solid;border-color:red;border-width:0px;}*/
        div#pdfDiv {height:750px;width:49%;border-style:solid;border-color:red;border-width:0px;}
    </style>
    <script type="text/javascript">

        var socket;

        window.onload = function load()
        {

            document.getElementById("pdfDiv").style.visibility="hidden";
        }

        function setStatusLabel(msg)
        {
            var eStatus = document.getElementById("connectionStatus");
            eStatus.innerHTML = msg;
        }

        function doConnect(callback)
        {
            var serviceUrl = document.getElementById("serviceUrl").value;

            socket = new WebSocket(serviceUrl);

            // 监听消息
            socket.onmessage = function(event)
            {
                console.log('Client received a message',event);
                document.getElementById("pdfDiv").style.visibility="hidden";
                // parse json
                var obj = eval('('+event.data+')');

                if (obj && (obj.previewURL || obj.previewImage))
                {
                    var url;
                    if (obj && obj.previewURL) {
                        url = obj.previewURL;
                    } else if (obj && obj.previewImage) {
                        url = obj.previewImage;
                    }
                    var pdf = document.getElementById('pdf');
                    if (pdf) {
                        pdf.setAttribute('src', url);
                        document.getElementById("pdfDiv").style.visibility="visible";
                    }
                }
                var resultElement = document.getElementById("resultMessage");
                resultElement.value = resultElement.value + event.data + "\n";
                resultElement.scrollTop = resultElement.scrollHeight;
            };

            socket.onopen = function(event)
            {
                if (callback != null) {
                    callback();
                }
                setStatusLabel("已连接");
            }

            socket.onerror = function(error)
            {
                console.log("Failed to connect CN print at " + serviceUrl, error);
                setStatusLabel("连接错误");
            }

            // 监听Socket的关闭
            socket.onclose = function(event)
            {
                console.log('Client notified socket has closed',event);
                setStatusLabel("连接关闭");
            };
        }

        function sendCommand()
        {
            if (typeof socket == "undefined" || socket.readyState == WebSocket.CLOSED) {
                doConnect(sendCommand);
                return;
            }

            if (socket.readyState != WebSocket.OPEN) {
                alert("无效连接: " + socket.readyState);
                return;
            }

            var msg = document.getElementById('printmessage').value;
            var repeatCount = document.getElementById('repeatCount').value;
            var isPreview = document.getElementById('isPreview').checked;
            var time = new Date().getTime();

            for (var index = 0; index < repeatCount; index++) {
                var obj = JSON.parse(msg);

                if (obj["task"])
                {
                    // taskID
                    obj["task"]["taskID"] = time.toString() + "_TASK_" + index;

                    // preview
                    obj["task"]["preview"] = isPreview;
                }

                var newMsg = JSON.stringify(obj);
                socket.send(newMsg);
            }
        }

        function clearResult()
        {
            var resultElement = document.getElementById("resultMessage");
            resultElement.value = "";
        }
    </script>


</head>
<body>

<div id="ctlDiv">

    <form name="formname" action="javascript:sendCommand()">
        <p hidden>重复发送请求:<input id="repeatCount" type="number" min="1" max="1000" step="1" value="1">   
            <input hidden id="isPreview" type="checkbox" checked="true">预览模式
        </p>
        <p>    <input hidden type="text" id="serviceUrl" name="serviceUrl" value="ws://localhost:13528" />
            <label hidden id="connectionStatus">未知</label>
            <input hidden id="dianji" type="submit" value="发送请求"/>
        </p>
        <textarea  hidden cols="80" rows="20" id="printmessage" name="printmessage">{
    "cmd": "print",
    "requestID": "123458976",
    "version": "1.0",
    "task": {
        "taskID": "7293666",
        "preview": false,
        "printer": "",
        "notifyMode": "allInOne",
        "previewType": "html",
        "documents": [
            {
                "documentID": "0123456789",
                "contents": [
                    {$list}//数据是在这里哦接收的,你不需要改什么,如果你觉得这不是你想要的,你也可以借鉴一下方法
                ]
            }
        ]
    }
}
    </textarea>
        <br/><br/>
        <textarea hidden cols="80" rows="20" id="resultMessage" name="resultMessage" readonly="readonly"></textarea>
        <br/>
        <input hidden type="button" value="清除返回消息" onclick="clearResult()"/>
    </form>
</div>

<div style="margin: 0 auto" id="pdfDiv" align="middle">
    <iframe id="pdf" src="" width="100%" height="100%">
    </iframe>
</div>

</body>
</html>

<script>
    $('#dianji').click();


</script>

最后放一张预览成功的图片(注:必须安装菜鸟打印组件菜鸟预览)

这个需要右键打印,或点击打印的图标才能打印,打印情况就说到这里了

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »