打印电子面单,常用两种方案:
- 通过快递100获取快递单号,结合c-lodop热敏纸打印
- 通过菜鸟ISV/自研ERP使用菜鸟电子面单
1.快递100 - 结合热敏纸打印(C-Lodop)
介绍:根据客户提交的快递公司编码获取电子面单页面,调用方获取到电子面单页面后可以通过打印机打印出来使用
地址文档
1.快递100: http://www.kuaidi100.com/openapi/cloudprintele.shtml
2.电子面单:https://poll.kuaidi100.com/manager/page/document/eleapi
3.C-lodop: http://www.lodop.net/
操作代码
<?php
namespace App\Services;
/**
* 快递100 - 获取物流单号
*/
class SendExpressService
{
public function __construct()
{
// 快递100参数
$this->kuaidicom = ""; // 物流编号 - zhongtong
$this->key = ""; // 快递100key
$this->secret = ""; // 快递100secret
$this->partnerId = ""; // 快递100partnerId
$this->partnerKey = ""; // 快递100partnerKey
}
/**
* 生成快递单号
* @Author echo
* @DateTime 2019-03-08
* @param [type] $orderItem [description]
* @return [type] [description]
*/
public function createExpressCode($orderItem, $supplierAddressInfo)
{
// $supplierAddressInfo - 供应商信息
// $orderItem - 订单信息
$postData = [
'recMan' => [
"name"=>$orderItem->receiveName,
"mobile"=>$orderItem->mobile,
"tel"=>"",
"zipCode"=>"",
"province"=>$orderItem->province,
"city"=>$orderItem->city,
"district"=>$orderItem->area,
"addr"=>$orderItem->address,
"company"=>""
],
'sendMan' => [
"name"=>$supplierAddressInfo->contact_person,
"mobile"=>$supplierAddressInfo->mobile,
"tel"=>"",
"zipCode"=>"",
"province"=> $supplierAddressInfo->province,
"city"=> $supplierAddressInfo->city,
"district"=> $supplierAddressInfo->area,
"addr"=> $supplierAddressInfo->address,
"company"=>""
],
"kuaidicom"=> $this->kuaidicom,
"partnerId"=> $this->partnerId,
"partnerKey"=>$this->partnerKey,
"net"=>"",
"kuaidinum"=>"",
"orderId"=>$orderCode,
"payType"=>"",
"expType"=>"标准快递",
"weight"=>"1",
"volumn"=>"0",
"count"=>1,
"remark"=>$note,
"valinsPay"=>"0",
"collection"=>"0",
"needChild"=>"0",
"needBack"=>"0",
"cargo"=>"",
"needTemplate"=>"1"
];
$time = time();
$sign = strtoupper(md5(json_encode($postData).$time.$this->key.$this->secret));
$apiUrl = "http://api.kuaidi100.com/eorderapi.do?method=getElecOrder¶m=".json_encode($postData)."&sign=".$sign."&t=".$time."&key=".$this->key;
return CurlHandler::curl_post_http($apiUrl,[]);
}
}
<script src="/Lodop/js/LodopFuncs.js"></script>
<script type="text/javascript">
var LODOP; //声明为全局变量
// 电子面单 - 预览
function sendPreviewCommand(expressInfo)
{
LODOP=getLodop();
if (!LODOP.CVERSION) {
alert('请安装C-Lodop插件')
return
}
setConent(expressInfo);
LODOP.PREVIEW();
return
}
// 打印电子面单
function sendCommand(expressInfo)
{
LODOP=getLodop();
if (!LODOP.CVERSION) {
alert('请安装C-Lodop插件')
return
}
LODOP.SET_PRINT_MODE("CATCH_PRINT_STATUS",true);
setConent(expressInfo);
LODOP.PRINT();
orderId = $(this).val()
LODOP.On_Return=function(TaskID,Value){
alert('成功')
};
}
</script>
2.菜鸟物流
介绍:ISV/自研ERP使用菜鸟电子面单:需要注册一个ISV账号申请API并发布,然后重新注册一个商家账号对该ISV发布的应用进行授权,方可完成对接。
文档地址:
1.电子面单接入文档(LINK接入)https://open.taobao.com/doc.htm?docId=107052&docType=1
2.物流云平台 https://cloud.cainiao.com/
3.电子面单管理中心 https://dayin.cainiao.com/miandan/subscribe/subscribe.htm
4.错误码 https://global.link.cainiao.com/#/homepage/doc/3?_k=pnfgj0
日常测试环境
地址:https://linkdaily.tbsandbox.com/gateway/link.do
或者 https://linkdaily.tbsandbox.com/gateway/pac_message_receiver.do (测试环境不稳定,时有调整,两个地址都试一下,哪个可以用哪个)
AppKey:766654
SecretKey:F53eqq903jQySV100Z8w06f9g914A13Z
Token:TmpFU1ZOUGoyRnoybDZmT3lyaW9hWGR4VFNad0xNYTBUek9QZk9kamt2Z1hJMytsVkVHK0FjVW55T25wcUR1Qw==
日常测试环境使用以上提供的AppKey、SecretKey、Token,不能使用自己申请的。测试环境不支持配置请求、返回报文格式,默认格式xml格式;不可新增订购关系,只能使用提供的快递公司获取面单号,支持的快递公司通过订购关系查询接口获取。请参照LINK接入白皮书1.10中的代码示例进行联调测试,测试环境只供调通接口,具体数据没有参考意义,数据准确性请到正式环境验证。
注:
1、电子面单测试使用日常测试环境(沙箱环境),不使用彩虹桥环境;
2、不要使用自己申请的**AppKey、SecretKey、Token;**
3、报文格式只能使用XML格式;
4、按以下顺序调试电子面单接口:订购关系查询接口、取号接口、更新接口、取消接口;
5、日常环境不支持测试云打印接口,请到正式环境调试。
操作代码
<?php
namespace App\Services;
/**
* 菜鸟物流获取快递单号
*/
class SendExpressService
{
public function __construct()
{
// 菜鸟参数
$this->cainiaoDomain = ""; // 菜鸟请求域名 - http://link.cainiao.com/gateway/link.do
$this->cainiaoAppSecret = ""; // 菜鸟AppSecret
$this->logisticProviderId = ""; // token(申请成功后菜鸟给的token)
$this->cpCode = ""; // 物流编号 - YTO
$this->senderMobile = ""; // 发货人号码
$this->senderName = ""; // 发货人姓名
$this->template = ""; // 物流默认模板
}
/**
* 获取发货地
* @Author echo
* @DateTime 2019-04-10
* @return [type] [description]
*/
public function getDeliveryAddress()
{
// 请求类型
$type = "TMS_WAYBILL_SUBSCRIPTION_QUERY";
// 请求内容
$requestData= json_encode(['cpCode' => $this->cpCode]);
// 请求链接
$url = $this->cainiaoDomain."?logistic_provider_id=".$this->logisticProviderId."&msg_type=".$type."&logistics_interface=".urlencode($requestData)."&data_digest=".$this->encrypti($requestData,$this->cainiaoAppSecret);
// 返回请求
return get_url($url);
}
/**
* 获取快递单号
* @Author echo
* @DateTime 2019-04-10
* @param array $sender [发货人信息]
* @param array $recipient [收货人信息]
* @param [type] $orderCode [订单号]
* @return [type] [description]
*/
public function getExpressCode($sender = [],$recipient = [],$orderCode = null)
{
/**
* tip
* - orderCode不能重复
* - recipient数据必须与为“TMS_WAYBILL_SUBSCRIPTION_QUERY”获取数据
* - 发货人/收货人,地址/联系人/联系方式不能为空
*/
// 请求方式
$type = "TMS_WAYBILL_GET";
// 请求内容
$requestData ='{
"cpCode":"'.$this->cpCode.'",
"dmsSorting":"false",
"needEncrypt":"false",
"resourceCode":"无",
"sender":{
"address":{
"city":"'.$sender['city'].'",
"detail":"'.$sender['detail'].'",
"district":"'.$sender['district'].'",
"province":"'.$sender['province'].'",
"town":"'.$sender['town'].'"
},
"mobile":"'.$sender['mobile'].'",
"name":"'.$sender['name'].'",
"phone":"'.$sender['phone'].'",
},
"storeCode":"无",
"tradeOrderInfoDtos":[
{
"logisticsServices":"",
"objectId":"1",
"orderInfo":{
"orderChannelsType":"OTHERS",
"tradeOrderList":[
"'.$orderCode.'"
]
},
"packageInfo":{
"id":"'.$orderCode.'",
"items":[
{
"count":1,
"name":"商品"
}
],
"volume":"1",
"weight":"1"
},
"recipient":{
"address":{
"city":"'.$recipient['city'].'",
"detail":"'.$recipient['detail'].'",
"district":"'.$recipient['district'].'",
"province":"'.$recipient['province'].'",
"town":"'.$recipient['town'].'"
},
"mobile":"'.$recipient['mobile'].'",
"name":"'.$recipient['name'].'",
"phone":"'.$recipient['phone'].'",
},
"templateUrl":"'.$this->template.'",
"userId":"1"
}
]
}';
$url = $domain."?logistic_provider_id=".$this->logisticProviderId."&msg_type=".$type."&logistics_interface=".urlencode($requestData)."&data_digest=".$this->encrypti($requestData,$this->cainiaoAppSecret);
return get_url($url);
}
/**
* 电商Sign签名生成
* @param data 内容
* @param appkey Appkey
* @return DataSign签名
*/
public function encrypti($data,$this->cainiaoAppSecret)
{
return urlencode(base64_encode(md5($data.$this->cainiaoAppSecret,true)));
}
// get方式请求
function get_url($httpUrl)
{
$ch = curl_init();
$timeout = 5;
curl_setopt ($ch, CURLOPT_URL, $httpUrl);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
return $file_contents;
}
}
<script type="text/javascript">
var serviceUrl = "ws://localhost:13528"
var socket;
function doConnect(callback)
{
socket = new WebSocket(serviceUrl);
// 监听消息
socket.onmessage = function(event)
{
console.log('Client received a message',event);
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;
}
window.open(url);
}
};
socket.onopen = function(event)
{
if (callback != null) {
callback();
}
}
socket.onerror = function(error)
{
console.log("Failed to connect CN print at " + serviceUrl, error);
alert("打印接连接错误,请启动CAINIAO打印组件")
}
// 监听Socket的关闭
socket.onclose = function(event)
{
console.log('Client notified socket has closed',event);
alert("打印连接关闭,请启动CAINIAO打印组件")
};
}
/**
* 打印命令
* @Author echo
* @DateTime 2019-04-29
* @param {[type]} expressInfo [获取快递单号,返回打印信息]
* @return {[type]} [description]
*/
function sendCommand(expressInfo)
{
if (typeof socket == "undefined" || socket.readyState == WebSocket.CLOSED) {
doConnect(sendCommand);
return;
}
if (socket.readyState != WebSocket.OPEN) {
alert("无效连接: " + socket.readyState);
return;
}
var time = new Date().getTime();
var contents = [];
// 物流基础数据
contents.push(expressInfo)
// 物流自定义数据 (需要自行配置)
diyContent = {"templateURL" : "http://cloudprint.cainiao.com/template/customArea/7737479/2","data" : {"product_detail": "自定义内容"}}
contents.push(diyContent)
msg = {
"cmd": "print",
"requestID": "123458976",
"version": "1.0",
"task": {
"taskID": "7293666",
"preview": false, // 是否预览
"printer": "",
"notifyMode": "allInOne",
"previewType": "html",
"documents": [
{
"documentID": "0123456789",
"contents": contents
}
]
}
}
var obj = msg
if (obj["task"])
{
obj["task"]["taskID"] = time.toString() + "_TASK"
obj["task"]["preview"] = true;
}
var newMsg = JSON.stringify(obj);
socket.send(newMsg);
}
</script>
打印电子面单,常用两种方案:
- 通过快递100获取快递单号,结合c-lodop热敏纸打印
- 通过菜鸟ISV/自研ERP使用菜鸟电子面单
1.快递100 - 结合热敏纸打印(C-Lodop)
介绍:根据客户提交的快递公司编码获取电子面单页面,调用方获取到电子面单页面后可以通过打印机打印出来使用
地址文档
1.快递100: http://www.kuaidi100.com/openapi/cloudprintele.shtml
2.电子面单:https://poll.kuaidi100.com/manager/page/document/eleapi
3.C-lodop: http://www.lodop.net/
操作代码
<?php
namespace App\Services;
/**
* 快递100 - 获取物流单号
*/
class SendExpressService
{
public function __construct()
{
// 快递100参数
$this->kuaidicom = ""; // 物流编号 - zhongtong
$this->key = ""; // 快递100key
$this->secret = ""; // 快递100secret
$this->partnerId = ""; // 快递100partnerId
$this->partnerKey = ""; // 快递100partnerKey
}
/**
* 生成快递单号
* @Author echo
* @DateTime 2019-03-08
* @param [type] $orderItem [description]
* @return [type] [description]
*/
public function createExpressCode($orderItem, $supplierAddressInfo)
{
// $supplierAddressInfo - 供应商信息
// $orderItem - 订单信息
$postData = [
'recMan' => [
"name"=>$orderItem->receiveName,
"mobile"=>$orderItem->mobile,
"tel"=>"",
"zipCode"=>"",
"province"=>$orderItem->province,
"city"=>$orderItem->city,
"district"=>$orderItem->area,
"addr"=>$orderItem->address,
"company"=>""
],
'sendMan' => [
"name"=>$supplierAddressInfo->contact_person,
"mobile"=>$supplierAddressInfo->mobile,
"tel"=>"",
"zipCode"=>"",
"province"=> $supplierAddressInfo->province,
"city"=> $supplierAddressInfo->city,
"district"=> $supplierAddressInfo->area,
"addr"=> $supplierAddressInfo->address,
"company"=>""
],
"kuaidicom"=> $this->kuaidicom,
"partnerId"=> $this->partnerId,
"partnerKey"=>$this->partnerKey,
"net"=>"",
"kuaidinum"=>"",
"orderId"=>$orderCode,
"payType"=>"",
"expType"=>"标准快递",
"weight"=>"1",
"volumn"=>"0",
"count"=>1,
"remark"=>$note,
"valinsPay"=>"0",
"collection"=>"0",
"needChild"=>"0",
"needBack"=>"0",
"cargo"=>"",
"needTemplate"=>"1"
];
$time = time();
$sign = strtoupper(md5(json_encode($postData).$time.$this->key.$this->secret));
$apiUrl = "http://api.kuaidi100.com/eorderapi.do?method=getElecOrder¶m=".json_encode($postData)."&sign=".$sign."&t=".$time."&key=".$this->key;
return CurlHandler::curl_post_http($apiUrl,[]);
}
}
<script src="/Lodop/js/LodopFuncs.js"></script>
<script type="text/javascript">
var LODOP; //声明为全局变量
// 电子面单 - 预览
function sendPreviewCommand(expressInfo)
{
LODOP=getLodop();
if (!LODOP.CVERSION) {
alert('请安装C-Lodop插件')
return
}
setConent(expressInfo);
LODOP.PREVIEW();
return
}
// 打印电子面单
function sendCommand(expressInfo)
{
LODOP=getLodop();
if (!LODOP.CVERSION) {
alert('请安装C-Lodop插件')
return
}
LODOP.SET_PRINT_MODE("CATCH_PRINT_STATUS",true);
setConent(expressInfo);
LODOP.PRINT();
orderId = $(this).val()
LODOP.On_Return=function(TaskID,Value){
alert('成功')
};
}
</script>
2.菜鸟物流
介绍:ISV/自研ERP使用菜鸟电子面单:需要注册一个ISV账号申请API并发布,然后重新注册一个商家账号对该ISV发布的应用进行授权,方可完成对接。
文档地址:
1.电子面单接入文档(LINK接入)https://open.taobao.com/doc.htm?docId=107052&docType=1
2.物流云平台 https://cloud.cainiao.com/
3.电子面单管理中心 https://dayin.cainiao.com/miandan/subscribe/subscribe.htm
4.错误码 https://global.link.cainiao.com/#/homepage/doc/3?_k=pnfgj0
日常测试环境
地址:https://linkdaily.tbsandbox.com/gateway/link.do
或者 https://linkdaily.tbsandbox.com/gateway/pac_message_receiver.do (测试环境不稳定,时有调整,两个地址都试一下,哪个可以用哪个)
AppKey:766654
SecretKey:F53eqq903jQySV100Z8w06f9g914A13Z
Token:TmpFU1ZOUGoyRnoybDZmT3lyaW9hWGR4VFNad0xNYTBUek9QZk9kamt2Z1hJMytsVkVHK0FjVW55T25wcUR1Qw==
日常测试环境使用以上提供的AppKey、SecretKey、Token,不能使用自己申请的。测试环境不支持配置请求、返回报文格式,默认格式xml格式;不可新增订购关系,只能使用提供的快递公司获取面单号,支持的快递公司通过订购关系查询接口获取。请参照LINK接入白皮书1.10中的代码示例进行联调测试,测试环境只供调通接口,具体数据没有参考意义,数据准确性请到正式环境验证。
注:
1、电子面单测试使用日常测试环境(沙箱环境),不使用彩虹桥环境;
2、不要使用自己申请的**AppKey、SecretKey、Token;**
3、报文格式只能使用XML格式;
4、按以下顺序调试电子面单接口:订购关系查询接口、取号接口、更新接口、取消接口;
5、日常环境不支持测试云打印接口,请到正式环境调试。
操作代码
<?php
namespace App\Services;
/**
* 菜鸟物流获取快递单号
*/
class SendExpressService
{
public function __construct()
{
// 菜鸟参数
$this->cainiaoDomain = ""; // 菜鸟请求域名 - http://link.cainiao.com/gateway/link.do
$this->cainiaoAppSecret = ""; // 菜鸟AppSecret
$this->logisticProviderId = ""; // token(申请成功后菜鸟给的token)
$this->cpCode = ""; // 物流编号 - YTO
$this->senderMobile = ""; // 发货人号码
$this->senderName = ""; // 发货人姓名
$this->template = ""; // 物流默认模板
}
/**
* 获取发货地
* @Author echo
* @DateTime 2019-04-10
* @return [type] [description]
*/
public function getDeliveryAddress()
{
// 请求类型
$type = "TMS_WAYBILL_SUBSCRIPTION_QUERY";
// 请求内容
$requestData= json_encode(['cpCode' => $this->cpCode]);
// 请求链接
$url = $this->cainiaoDomain."?logistic_provider_id=".$this->logisticProviderId."&msg_type=".$type."&logistics_interface=".urlencode($requestData)."&data_digest=".$this->encrypti($requestData,$this->cainiaoAppSecret);
// 返回请求
return get_url($url);
}
/**
* 获取快递单号
* @Author echo
* @DateTime 2019-04-10
* @param array $sender [发货人信息]
* @param array $recipient [收货人信息]
* @param [type] $orderCode [订单号]
* @return [type] [description]
*/
public function getExpressCode($sender = [],$recipient = [],$orderCode = null)
{
/**
* tip
* - orderCode不能重复
* - recipient数据必须与为“TMS_WAYBILL_SUBSCRIPTION_QUERY”获取数据
* - 发货人/收货人,地址/联系人/联系方式不能为空
*/
// 请求方式
$type = "TMS_WAYBILL_GET";
// 请求内容
$requestData ='{
"cpCode":"'.$this->cpCode.'",
"dmsSorting":"false",
"needEncrypt":"false",
"resourceCode":"无",
"sender":{
"address":{
"city":"'.$sender['city'].'",
"detail":"'.$sender['detail'].'",
"district":"'.$sender['district'].'",
"province":"'.$sender['province'].'",
"town":"'.$sender['town'].'"
},
"mobile":"'.$sender['mobile'].'",
"name":"'.$sender['name'].'",
"phone":"'.$sender['phone'].'",
},
"storeCode":"无",
"tradeOrderInfoDtos":[
{
"logisticsServices":"",
"objectId":"1",
"orderInfo":{
"orderChannelsType":"OTHERS",
"tradeOrderList":[
"'.$orderCode.'"
]
},
"packageInfo":{
"id":"'.$orderCode.'",
"items":[
{
"count":1,
"name":"商品"
}
],
"volume":"1",
"weight":"1"
},
"recipient":{
"address":{
"city":"'.$recipient['city'].'",
"detail":"'.$recipient['detail'].'",
"district":"'.$recipient['district'].'",
"province":"'.$recipient['province'].'",
"town":"'.$recipient['town'].'"
},
"mobile":"'.$recipient['mobile'].'",
"name":"'.$recipient['name'].'",
"phone":"'.$recipient['phone'].'",
},
"templateUrl":"'.$this->template.'",
"userId":"1"
}
]
}';
$url = $domain."?logistic_provider_id=".$this->logisticProviderId."&msg_type=".$type."&logistics_interface=".urlencode($requestData)."&data_digest=".$this->encrypti($requestData,$this->cainiaoAppSecret);
return get_url($url);
}
/**
* 电商Sign签名生成
* @param data 内容
* @param appkey Appkey
* @return DataSign签名
*/
public function encrypti($data,$this->cainiaoAppSecret)
{
return urlencode(base64_encode(md5($data.$this->cainiaoAppSecret,true)));
}
// get方式请求
function get_url($httpUrl)
{
$ch = curl_init();
$timeout = 5;
curl_setopt ($ch, CURLOPT_URL, $httpUrl);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
return $file_contents;
}
}
<script type="text/javascript">
var serviceUrl = "ws://localhost:13528"
var socket;
function doConnect(callback)
{
socket = new WebSocket(serviceUrl);
// 监听消息
socket.onmessage = function(event)
{
console.log('Client received a message',event);
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;
}
window.open(url);
}
};
socket.onopen = function(event)
{
if (callback != null) {
callback();
}
}
socket.onerror = function(error)
{
console.log("Failed to connect CN print at " + serviceUrl, error);
alert("打印接连接错误,请启动CAINIAO打印组件")
}
// 监听Socket的关闭
socket.onclose = function(event)
{
console.log('Client notified socket has closed',event);
alert("打印连接关闭,请启动CAINIAO打印组件")
};
}
/**
* 打印命令
* @Author echo
* @DateTime 2019-04-29
* @param {[type]} expressInfo [获取快递单号,返回打印信息]
* @return {[type]} [description]
*/
function sendCommand(expressInfo)
{
if (typeof socket == "undefined" || socket.readyState == WebSocket.CLOSED) {
doConnect(sendCommand);
return;
}
if (socket.readyState != WebSocket.OPEN) {
alert("无效连接: " + socket.readyState);
return;
}
var time = new Date().getTime();
var contents = [];
// 物流基础数据
contents.push(expressInfo)
// 物流自定义数据 (需要自行配置)
diyContent = {"templateURL" : "http://cloudprint.cainiao.com/template/customArea/7737479/2","data" : {"product_detail": "自定义内容"}}
contents.push(diyContent)
msg = {
"cmd": "print",
"requestID": "123458976",
"version": "1.0",
"task": {
"taskID": "7293666",
"preview": false, // 是否预览
"printer": "",
"notifyMode": "allInOne",
"previewType": "html",
"documents": [
{
"documentID": "0123456789",
"contents": contents
}
]
}
}
var obj = msg
if (obj["task"])
{
obj["task"]["taskID"] = time.toString() + "_TASK"
obj["task"]["preview"] = true;
}
var newMsg = JSON.stringify(obj);
socket.send(newMsg);
}
</script>