丰桥自助打印顺丰面单
第一步:基础准备工作对接的丰桥三方官网地址:http://qiao.sf-express.com/pages/developDoc/index.html?level2=535247服务器需要有java环境:需要1.6或以上版本(目前用的java版本是1.8),具体安装步骤可百度搜索一下,安装完后查看下版本。查看服务器时区,使用命令timedatectl | grep "Time zone" 查看,
第一步:基础准备工作
对接的丰桥三方官网地址:
http://qiao.sf-express.com/pages/developDoc/index.html?level2=535247
服务器需要有java环境:需要1.6或以上版本(目前用的java版本是1.8),具体安装步骤可百度搜索一下,安装完后查看下版本。
查看服务器时区,使用命令timedatectl | grep "Time zone" 查看,查看是否是 echo "Asia/Shanghai" > /etc/timezone如果不是需要时区设置成这样,不然请求面单服务生成面单图片的时候,上面打印时间会与实际生成的时间相差八小时。
服务器还需要有宋体黑体库(simsun.ttf和simhei.ttf),因为生成的面单图片上面字母生成需要服务器有这字体库。使用命令fc-list查看字体库列表有没有这两种字体库。
从顺丰丰桥官网下载面单自助打印SDK,下面这个目录文件是生成面单图片的服务。

上传到服务器上,启动这个服务命令是java -Dfile.encoding=utf-8 -jar csim_waybill_print_service_V1.1.*.jar port
启动端口默认是4040,如果不特别设置的话。
启动端口需要登录服务器云管理平台,在安全组中增加开放端口。
端口设置后,命令执行后,浏览器打开
http://服务所在服务器ip:4040/servertest.html
显示OK代表面单图片服务开启成功。
此处ip建议换成域名,这样安全些。
备注:这个面单服务建议做成长链接编写一个脚本让这个服务器不能停,避免服务停止,服务停止了就无法生成面单图片。
顺丰面单图片打印机型号:汉印(N41BT)
面单图片所用打印纸:热敏打印纸
电脑所需安装驱动下载地址:https://cn.hprt.com/XiaZai.html(搜索N41BT这个打印机对应的驱动)
驱动具体安装步骤丰桥上应该有视频教程,如果没有可以联系丰桥那边技术客服咨询进行安装。
以上基础准备工作完成,接下来进行第二大步,项目里封装面单打印sdk。
第二步:tp5框架里封装面单打印类
(1)对接顺丰接口类
common目录下新增logistics目录,common\logistics目录下新增LogisticsSdk类文件
namespace app\common\logistics;
class LogisticsSdk {
//配置信息
public $SURFACE_SINGLE = array(
'partnerID'=>'',//例如ghdfnf
'checkword'=>'',//例如NZvqbVTXENbFkvhIXliWQRbshjdhjHJSDhjhj
'serviceCode'=>'EXP_RECE_CREATE_ORDER',
'call_url_box'=>'https://sfapi.sf-express.com/std/service',
'monthlyCard'=>'',//例如 0200179234
'cancelOrder'=>'EXP_RECE_UPDATE_ORDER',
'queryOrder'=>'EXP_RECE_SEARCH_ORDER_RESP',
'queryRoutes'=>'EXP_RECE_SEARCH_ROUTES'
);
public function __construct()
{
$this->partnerID =$this->SURFACE_SINGLE['partnerID'];//顾客编码;
$this->checkword =$this->SURFACE_SINGLE['checkword'];//校验码
$this->serviceCode =$this->SURFACE_SINGLE['serviceCode'];//生成面单图片服务接口
$this->call_url_box =$this->SURFACE_SINGLE['call_url_box'];//环境的地址
$this->monthlyCard =$this->SURFACE_SINGLE['monthlyCard'];//月结卡号
$this->queryOrder =$this->SURFACE_SINGLE['queryOrder'];//查询订单服务接口
$this->cancelOrder =$this->SURFACE_SINGLE['cancelOrder'];//取消订单服务接口
$this->queryRoutes =$this->SURFACE_SINGLE['queryRoutes'];//路由查询接口
}
/*顺丰订单取消*/
public function cancelOrder($xiao_order_id){
//发送数据包
$sendData=[
'dealType'=>2,
'language'=>'zh-CN',
'orderId'=>$xiao_order_id,
'totalWeight'=>0,
'waybillNoInfoList'=>[]
];
//发送参数
$post_data = array(
'serviceCode' => $this->cancelOrder,
);
$res=$this->sign_send($sendData,$post_data);
$resu=json_decode($res['apiResultData'],true);
if($resu['success']==1){
return json_encode(['code'=>1,'msg'=>'取消成功','data'=>[]]);
}else{
return json_encode(['code'=>0,'msg'=>$resu['errorMsg'],'data'=>[]]);
}
}
/*顺丰路由查询*/
public function queryRoutes($express_order){
$sendData=[
'trackingType'=>1,
'trackingNumber'=>$express_order,
'language'=>'0',
'methodType'=>1
];
$post_data = array(
'serviceCode' => $this->queryRoutes,
);
$res=$this->sign_send($sendData,$post_data);
$apiResultData=json_decode($res['apiResultData'],true);
if(!empty($apiResultData['msgData'])){
$routeResps=$apiResultData['msgData']['routeResps'];
$routes=$routeResps[0]['routes'];
if(!empty($routes)){
//更新快递状态
$opCode=array_column($routes,'opCode');
return json_encode(['code'=>1,'msg'=>'请求成功','data'=>$opCode]);
}else{
return json_encode(['code'=>0,'msg'=>'没有查询到信息','data'=>[]]);
}
}else{
return json_encode(['code'=>0,'msg'=>'请求失败','data'=>'']);
}
}
//生成签名
public function sign_send($sendData,$post_data){
$msgData=json_encode($sendData);
$timestamp = time();
//通过MD5和BASE64生成数字签名
$msgDigest = base64_encode(md5((urlencode($msgData .$timestamp. $this->checkword)), TRUE));
$post_data['partnerID']=$this->partnerID;
$post_data['requestID']=$this->create_uuid();
$post_data['timestamp']=$timestamp;
$post_data['msgData'] =$msgData;
$post_data['msgDigest']=$msgDigest;
$resultCont = $this->send_post($this->call_url_box, $post_data);
$res=json_decode($resultCont,true);
return $res;
}
//获取UUID
public function create_uuid() {
$chars = md5(uniqid(mt_rand(), true));
$uuid = substr ( $chars, 0, 8 ) . '-'
. substr ( $chars, 8, 4 ) . '-'
. substr ( $chars, 12, 4 ) . '-'
. substr ( $chars, 16, 4 ) . '-'
. substr ( $chars, 20, 12 );
return $uuid ;
}
//发送请求
public function send_post($url,$post_data) {
$postdata = http_build_query($post_data);
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type:application/x-www-form-urlencoded;charset=utf-8',
'content' => $postdata,
'timeout' => 15 * 60 // 超时时间(单位:s)
)
);
ini_set('user_agent','Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727;)');
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
/*顺丰路由查询*/
public function queryRoutesInfo($express_order){
$sendData=[
'trackingType'=>1,
'trackingNumber'=>$express_order,
'language'=>'0',
'methodType'=>1
];
$post_data = array(
'serviceCode' => $this->queryRoutes,
);
$res=$this->sign_send($sendData,$post_data);
$apiResultData=json_decode($res['apiResultData'],true);
if($apiResultData['success']){
if(!empty($apiResultData['msgData'])){
$routeResps=$apiResultData['msgData']['routeResps'];
$routes=$routeResps[0]['routes'];
return json_encode(['code'=>1,'msg'=>'请求成功','data'=>$routes],320);
}else{
return json_encode(['code'=>0,'msg'=>'请求失败','data'=>'']);
}
}else{
return json_encode(['code'=>0,'msg'=>'请求失败','data'=>'']);
}
}
}
(2) 调用顺丰面单服务类WaybillPrinterSdk文件
class WaybillPrinterSdk
{
public $host = 'http://test.logistics.xiaodongai.com';
public function createPhoto($data=[],$drug=[]){
/**
* *******2联150 丰密运单*************
*/
/**
* 调用打印机 不弹出窗口 适用于批量打印【二联单】
*/
// $reqURL = "http://localhost:4040/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=noAlertPrint";
/**
* 调用打印机 弹出窗口 可选择份数 适用于单张打印【二联单】
*/
// $reqURL = "http://localhost:4040:4040/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=print";
/**
* 直接输出图片的BASE64编码字符串 可以使用html标签直接转换成图片【二联单】
*/
$reqURL = "http://面单服务所部署服务器ip:4040/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=image";//ip建议换成域名,这样安全些
// $reqURL = "http://localhost:4040/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=image";
/**
* *******3联210 丰密运单*************
*/
/**
* 调用打印机 不弹出窗口 适用于批量打印【三联单】
*/
$url10 = "http://localhost:4040/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=noAlertPrint";
/**
* 调用打印机 弹出窗口 可选择份数 适用于单张打印【三联单】
*/
// $reqURL = "http://localhost:4040/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=print";
/**
* 直接输出图片的BASE64编码字符串 可以使用html标签直接转换成图片【三联单】
*/
// $reqURL = "http://localhost:4040/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=image";
//1.根据业务需求确定请求地址,并确定是否替换版本
$reqURL = $this->handle_url($reqURL,true);//true 不需要 false 需要
//2.组装参数 丰密参数 true设置 false 不设置
$post_json_data = $this->assembly_param($data,$drug);
//3.发送请求
$result = $this->send_post($reqURL, $post_json_data);
$images_url='';
if(empty($result)){
return $images_url;
}
//如果url是打印图片 则保存图片到本地
if(strpos($reqURL, "image")){
//4.处理结果数据
$imageData = $this->handle_data($result);
//5图片保存到本地
$images_url=$this->save_image($imageData);
}
return $images_url;
}
/**
* 处理url
* @param unknown $reqURL
* @param unknown $notTopLogo true 不需要 false 需要
* @return mixed
*/
function handle_url($reqURL,$notTopLogo){
if ( $notTopLogo && strpos($reqURL, "V2.0"))
{
$reqURL = str_replace("V2.0", "V2.1",$reqURL);;
}
if ($notTopLogo && strpos($reqURL,"V3.0"))
{
$reqURL = str_replace("V3.0", "V3.1",$reqURL);
}
return $reqURL;
}
/**
* 组装参数
* @param unknown $fengmi
* @return string
*/
/**
* 组装参数
* @param unknown $fengmi
* @return string
*/
function assembly_param($fengmi,$drug){
//这个必填
$waybillDtos['appId'] = $fengmi['appId'];//"SLKJ2019"; //对应丰桥平台获取的clientCode
$waybillDtos['appKey'] = $fengmi['appKey'];//"FBIqMkZjzxbsZgo7jTpeq7PD8CVzLT4Q"; //对应丰桥平台获取的checkWord
// $waybillDtos['isPrintLogo'] = "1"; // 1 需要打印logo,0 不需要
$waybillDtos['mailNo'] =$fengmi['mailNo'];
$waybillDtos['electric'] =$fengmi['electric'];
//$waybillDto->mailNo="SF7551234567890,SF2000601520988,SF2000601520997";//子母单方式
//签回单号 签单返回服务POD 会打印两份快单 其中第二份作为返寄的单==如有签回单业务需要传此字段值
$waybillDtos['consignerProvince'] = $fengmi['consignerProvince'];
$waybillDtos['consignerCity'] = $fengmi['consignerCity'];
$waybillDtos['consignerCounty'] =$fengmi['consignerCounty'];
$waybillDtos['consignerAddress'] = $fengmi['consignerAddress']; //详细地址建议最多30个字 字段过长影响打印效果
// $waybillDtos['consignerCompany'] = $fengmi['consignerCompany'];
$waybillDtos['consignerMobile'] = $fengmi['consignerMobile'];
$waybillDtos['consignerName'] = $fengmi['consignerName'];
// $waybillDtos['consignerShipperCode'] =$fengmi['consignerShipperCode'];
// $waybillDtos['consignerTel'] = $fengmi['consignerTel'];
//寄件人信息
$waybillDtos['deliverProvince'] = $fengmi['deliverProvince'];
$waybillDtos['deliverCity'] = $fengmi['deliverCity'];
$waybillDtos['deliverCounty'] = $fengmi['deliverCounty'];
$waybillDtos['deliverCompany'] = $fengmi['deliverCompany'];
$waybillDtos['deliverAddress'] = $fengmi['deliverAddress']; //详细地址建议最多30个字 字段过长影响打印效果
$waybillDtos['deliverName'] = $fengmi['deliverName'];
$waybillDtos['deliverMobile'] = $fengmi['deliverMobile'];
// $waybillDtos['deliverShipperCode'] = $fengmi['deliverShipperCode'];
// $waybillDtos['deliverTel'] = $fengmi['deliverTel'];
// $waybillDtos['destCode'] = $fengmi['destCode']; //目的地代码 参考顺丰地区编号
// $waybillDtos['zipCode'] = $fengmi['zipCode']; //原寄地代码 参考顺丰地区编号
//1 :标准快递 2.顺丰特惠 3: 电商特惠 5:顺丰次晨 6:顺丰即日 7.电商速配 15:生鲜速配
$waybillDtos['expressType'] = $fengmi['expressType'];
///addedService
// COD代收货款价值 单位元 此项和月结卡号绑定的增值服务相关
// $waybillDtos['codValue'] = $fengmi['codValue'];
// $waybillDtos['insureValue'] = $fengmi['insureValue']; //声明保价价值 单位元
$waybillDtos['monthAccount'] = $fengmi['monthAccount']; //月结卡号
$waybillDtos['orderNo'] = "";
$waybillDtos['payMethod'] = $fengmi['payMethod']; // 1寄方付 2收方付 3第三方月结支付
$waybillDtos['childRemark'] = "";//子单号备注
$waybillDtos['mainRemark'] = "";//主运单备注
$waybillDtos['returnTrackingRemark'] = "";//签回单备注
//加密项
$waybillDtos['encryptCustName'] = false;//加密寄件人及收件人名称
$waybillDtos['encryptMobile'] = true;//加密寄件人及收件人联系手机
$waybillDtos['cargoInfoDtoList'] = $drug;
$waybillDtos['returnTrackingNo']='';
if ($fengmi)
{
$rlsMains['abFlag']=$fengmi['abFlag'];
$rlsMains['codingMapping']=$fengmi['codingMapping'];
$rlsMains['codingMappingOut']=$fengmi['codingMappingOut'];
$rlsMains['destRouteLabel']=$fengmi['destRouteLabel'];
$rlsMains['destTeamCode']=$fengmi['destTeamCode'];
$rlsMains['printIcon']=$fengmi['printIcon'];
$rlsMains['proCode']=$fengmi['proCode'];
$rlsMains['qrcode']=$fengmi['qrcode'];
$rlsMains['sourceTransferCode']=$fengmi['sourceTransferCode'];
$rlsMains['waybillNo']=$fengmi['waybillNo'];
$rlsMains['xbFlag']=$fengmi['xbFlag'];
$rlsInfoDtoList=array($rlsMains);
if (null != ($waybillDtos['returnTrackingNo']))
{
$rlsBacks['waybillNo'] = $waybillDtos['returnTrackingNo'];
$rlsBacks['destRouteLabel'] = $fengmi['destRouteLabel'];
$rlsBacks['printIcon'] = $fengmi['printIcon'];
$rlsBacks['proCode'] = $fengmi['proCode'];
$rlsBacks['abFlag'] =$fengmi['xbFlag'];
$rlsBacks['xbFlag'] =$fengmi['xbFlag'];
$rlsBacks['codingMapping'] =$fengmi['codingMapping'];
$rlsBacks['codingMappingOut'] =$fengmi['codingMappingOut'];
$rlsBacks['destTeamCode'] =$fengmi['destTeamCode'];
$rlsBacks['sourceTransferCode'] =$fengmi['sourceTransferCode'];
//对应下订单设置路由标签返回字段twoDimensionCode 该参
$rlsBacks['qrcode'] =$fengmi['qrcode'];
array_push($rlsInfoDtoList,$rlsBacks);
}
$waybillDtos['rlsInfoDtoList'] = $rlsInfoDtoList;
}
$waybillDtoList = array($waybillDtos);
$post_json_data = json_encode($waybillDtoList,JSON_UNESCAPED_UNICODE);
return $post_json_data;
}
/**
* 发送post请求
*
* @param string $url
* 请求地址
* @param array $post_data
* post键值对数据
* @return string
*/
function send_post($reqURL, $post_data)
{
//curl验证成功
$ch = curl_init($reqURL);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS,$post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($post_data)
));
$result = curl_exec($ch);
if (curl_errno($ch)) {
print curl_error($ch);
}
curl_close($ch);
if(strpos($reqURL, "image")=== false){
echo "\n";
echo "返回:".$result;
}
return $result;
}
/**
* 处理数据
* @param unknown $result
*/
function handle_data($result){
$startIndex = strpos($result,"[")+1;
$substrLen = strrpos($result,"]") - $startIndex;
$imageData = substr($result,$startIndex,$substrLen);
/**
* 如果以 \ 开头 ,截取
*/
if(strpos($imageData,"\\")===0){
$imageData = substr($imageData,1);
}
/**
* 如果以 \ 结尾 ,截取
*/
if(substr_compare($imageData, "\\", -strlen("\\")) === 0){
$imageData = substr($imageData,0,(strlen($imageData)-1));
}
//换行符替换为空
str_replace("\\n", "",$imageData);
return $imageData;
}
/**
*保存图片到腾讯云cos
* @param unknown $imageData
*/
function save_image($imageData){
$img_url = base64_decode($imageData);
$path = 'logistics/'.date('Ymd');
//调用上传sdk
$CosSdk = new CosSdk();
$res= $CosSdk->upload($img_url,$path);//此处上传到腾讯云cos,如果要上传到别的地方这块需调整存储位置
$result = json_decode($res,true);
if($result['code']==1){
return $result['data']['url'];
}else{
echo " 图片生成失败\n";
}
}
}
(3) 操作顺丰业务类LogoptSdk
namespace app\common\logistics;
use app\common\logistics\LogisticsSdk;
use app\common\logistics\WaybillPrinterSdk;
class LogoptSdk {
public $Logistics;
public $xiao_order_id;
public function __construct()
{
//实例化对象
$this->Logistics = new LogisticsSdk;
$this->partnerID =$this->Logistics->partnerID;//顾客编码;
$this->checkword =$this->Logistics->checkword;//校验码
$this->serviceCode =$this->Logistics->serviceCode;//生成面单图片服务接口
$this->call_url_box =$this->Logistics->call_url_box;//环境的地址
$this->monthlyCard =$this->Logistics->monthlyCard;//月结卡号
$this->queryOrder =$this->Logistics->queryOrder;//查询订单服务接口
$this->cancelOrder =$this->Logistics->cancelOrder;//取消订单服务接口
$this->queryRoutes =$this->Logistics->queryRoutes;//路由查询接口
}
//生成唯一订单id,此订单号是用于从顺丰下单,自己生成的一个顺丰订单号
public function createOrderid(){
//获取时间戳
$unix=microtime(true);
$orderid=str_replace(".","",substr($unix,-11));
$date=date('Ymd',time());
$this ->xiao_order_id ='XIAO-'.$date.'-'.$orderid;
return $this ->xiao_order_id;
}
/*1.生成运单号*/
public function createOrder($drug_pay,$xiao_order_id){
//发送数据包
$sendData=[
'cargoDetails'=> [
['amount'=>$drug_pay['drug_money'],'count'=>$drug_pay['total'],'name'=>'药品','unit'=>'盒','volume'=>0.0,'weight'=>0.1],
],
'contactInfoList'=>[
['address'=>'广东省广州市天河区渔兴路小马驹创意园xx栋xxx室','city'=>'广州市','contact'=>'寄件人名称','county'=>'天河区','contactType'=>1,'mobile'=>'寄件人手机号','province'=>'广东省'],
['address'=>$drug_pay['detail_address'],'city'=>$drug_pay['city'],'company'=>'','contact'=>$drug_pay['name'],'contactType'=>2,'county'=>$drug_pay['city'].$drug_pay['area'],'mobile'=>$drug_pay['phone'],'province'=>$drug_pay['province']],
],
'customsInfo'=>(object)[],
'expressTypeId'=>202,//下单的时候选的顺丰产品类型,202是顺丰微小件产品类型,具体自己公司需要哪种产品类型结合自己公司需要
'extraInfoList'=>[],
'isOneselfPickup'=>0,
'language'=>'zh-CN',
'monthlyCard'=>$this->monthlyCard,
'orderId'=>$xiao_order_id,
'parcelQty'=>1, //包裹数,一个包裹对应一个运单号;若包裹数大于1,则返回一个母运单号和N-1个子运单号
'payMethod'=>1, //付款方式,支持以下值:1:寄方付 2:收方付 3:第三方付
'totalWeight'=>0,
'is_docall'=>0 //等于0代表不需要通知顺丰小哥上门取件,等于1代表需要下单后自动通知顺丰小哥去寄件地址上门取件
];
//发送参数
$post_data = array(
'serviceCode' => $this->serviceCode,
);
$res=$this->Logistics->sign_send($sendData,$post_data);
return $res;
}
/*2.生成面单图片*/
public function createPhoto($raw,$drug_pay)
{
$data['mailNo'] = $raw['waybillNo'];
//二维码信息
$data['abFlag'] = $raw['abFlag'];
$data['codingMapping']=$raw['codingMapping'];
$data['codingMappingOut']=$raw['codingMappingOut'];
$data['destRouteLabel'] =$raw['destRouteLabel'];
$data['destTeamCode'] =$raw['destTeamCode'];
$data['printIcon'] ='00000000';
$data['proCode'] =$raw['proCode'];
$data['qrcode'] =$raw['qrcode'];
$data['sourceTransferCode']=$raw['sourceTransferCode'];
$data['waybillNo'] =$raw['waybillNo'];
$data['xbFlag'] =$raw['xbFlag'];
//基础信息
$data['appId'] =$this->partnerID;
$data['appKey']=$this->checkword;
$data['electric']='E';
$data['expressType']=2;
$data['monthAccount']=$this->monthlyCard;
$data['payMethod']=1;
//收件人信息
$data['consignerProvince']=$drug_pay['province'];
$data['consignerCity']=$drug_pay['city'];
$data['consignerCounty']=$drug_pay['area'];
$data['consignerAddress']=$drug_pay['detail_address'];
$data['consignerCompany']='';
$data['consignerMobile']=$drug_pay['phone'];
$data['consignerName']=$drug_pay['name'];
//寄件人信息
$data['deliverProvince']='广东省';
$data['deliverCity']='广州市';
$data['deliverCounty']='天河区';
$data['deliverCompany']='xxxx'; //寄件人
$data['deliverAddress']='广东省广州市天河区渔兴路小马驹创意园xxx栋xxx室';
$data['deliverName']=''; //寄件人
$data['deliverMobile']=''; //寄件人手机号
$WaybillPrinter= new WaybillPrinterSdk();
$images_url=$WaybillPrinter->createPhoto($data,[]);
return $images_url;
}
/*3.顺丰订单取消*/
public function cancelOrder($face_order){
$res=$this->Logistics->cancelOrder($face_order);
return $res;
}
/*4.顺丰路由节点操作码查询*/
public function queryRoutes($express_order){
$res=$this->Logistics->queryRoutes($express_order);
return $res;
}
/*5.顺丰路由信息查询*/
public function queryRoutesInfo($express_order){
$res=$this->Logistics->queryRoutesInfo($express_order);
return $res;
}
}
以上三个文件是框架里封装的类。
第三步:控制器中接口调用封装好的面单类库
/*1.顺丰下单接口 和 面单图片生成
1.7version(100*150)
*/
public function alertPrint(){
//订单id
$id=input('post.id');
$ordernumber=input('post.ordernumber');
if(empty($id)&&empty($ordernumber)){
return json(['code'=>201,'msg'=>'不存在该订单信息!','data'=>[]]);
}
if(!empty($ordernumber)){
$where = array('dp.ordernumber'=>$ordernumber);
}else{
$where = array('dp.id'=>$id);
}
//防止重复提交
$key='ordernumber.online.'.$ordernumber;
$redis = new RedisCache();
$key_ordernumber=$redis->get($key);
if($key_ordernumber){
return json(['code'=>201,'msg'=>'同一个订单号一分钟只允许请求一次接口','data'=>[]]);
}else{
$redis->set($key, $ordernumber, 60);//設置有效時間為1分鐘
}
$orderlist=Db::table('wechat_drug_pay')
->alias('dp')
->field('dp.id,op.drug_total as drug_money,op.drug_num,dp.ordernumber,wop.store_id,dp.freight,dp.address,dp.unitid,dp.consultant_unionid,dp.patient_unionid,dp.inquiry_id,dp.prescription,ad.take_over,ad.city,ad.name,ad.area,ad.phone,ad.province,ad.detail_address,um.user_mobile')
->join('wechat_address ad','dp.address = ad.id','LEFT')
->join('wechat_order_price op','dp.ordernumber = op.ordernumber','LEFT')
->join('wechat_pharmacy_order wop','dp.id = wop.order_id','LEFT')
->join('wechat_user_message um','dp.id = um.order_id','LEFT')
->where($where)
->find();
if(empty($orderlist)){
return json(['code'=>201,'msg'=>'不存在该订单信息。','data'=>$orderlist]);
}
$xdOrder=$orderlist['ordernumber'];
//物流信息(重打面单)
$logisticslist=Db::table('wechat_logistics')
->alias('wl')
->where(['wl.ordernumber'=>$xdOrder])
->find();
if(empty($logisticslist)){
$logisticslist= [];
}
//运单号
$express_order=!empty($logisticslist['sf_waybillno'])?$logisticslist['sf_waybillno']:'';
$drug_pay['id']=!empty($orderlist['id'])?$orderlist['id']:$id;//订单ID
$drug_pay['route_label_data'] = !empty($logisticslist['route_label_data'])?$logisticslist['route_label_data']:input('post.route_label_data'); //路由信息
$drug_pay['face_order']=!empty($logisticslist['sf_order'])?$logisticslist['sf_order']:input('post.face_order');//面单订单号
$drug_pay['total']=!empty($orderlist['drug_num'])?$orderlist['drug_num']:input('post.total');//药方药物总数
$drug_pay['drug_money']=!empty($orderlist['drug_money'])?$orderlist['drug_money']:input('post.drug_money');//药品总价
$drug_pay['store_id'] =isset($orderlist['store_id'])?$orderlist['store_id']:input('post.store_id');//药房ID
$drug_pay['ordernumber'] =!empty($orderlist['ordernumber'])?$orderlist['ordernumber']:input('post.ordernumber');//订单号
$drug_pay['express_order']= $express_order;//顺丰运单号
$drug_pay['address_id']=input('post.address_id');//收货地址ID
$drug_pay['freight'] =!empty(input('post.freight'))?input('post.freight'):12;//运费
$drug_pay['take_over']=!empty($orderlist['take_over'])?$orderlist['take_over']:input('post.take_over');//收货地址
$drug_pay['city']=!empty($orderlist['city'])?$orderlist['city']:input('post.city');//市
$drug_pay['name']=!empty($orderlist['name'])?$orderlist['name']:input('post.name');//收货人
$drug_pay['area']=!empty($orderlist['area'])?$orderlist['area']:input('post.area');//区
$drug_pay['phone']=!empty($orderlist['phone'])?$orderlist['phone']:input('post.phone');//收货人联系方式
$drug_pay['province']=!empty($orderlist['province'])?$orderlist['province']:input('post.province');//省
$drug_pay['detail_address']=!empty($orderlist['detail_address'])?$orderlist['detail_address']:input('post.detail_address');//详细地址
$route_label_data=json_decode($drug_pay['route_label_data'],true);
$present_address_id = $orderlist['address'];
$face_order=$drug_pay['face_order'];
//查询收货人信息
$address=DB::table('wechat_address')->field('id,take_over,city,name,area,phone,province,detail_address')->where(['id'=>$present_address_id])->find();
$orderlist['address']=$address;
$LogoptSdk = new LogoptSdk();
$xiao_order_id= $LogoptSdk->createOrderid();
if(empty($express_order)){
//1.首次生成面单打印
$res = $LogoptSdk ->createOrder($drug_pay,$xiao_order_id);
//记录失败记录
if(empty($res['apiResultData'])){
if(!empty($res['apiErrorMsg'])){
$apiErrorMsg=$res['apiErrorMsg'];
}else{
$apiErrorMsg='顺丰下单失败';
}
$this->dingdingSend($xdOrder.$apiErrorMsg);//发送钉钉机器人通知消息
$this->expressFail($xdOrder,$apiErrorMsg);//记录顺丰下单失败记录表
return json(['code'=>201,'msg'=>'顺丰下单失败!','data'=>$res,'drug_pay'=>$drug_pay]);
}
$resu=json_decode($res['apiResultData'],true);
//记录失败记录
$errorCode=$resu['errorCode'];
if($errorCode!=='S0000'){
$this->dingdingSend($xdOrder.$resu['errorMsg']);
$this->expressFail($xdOrder,$resu['errorMsg']);
return json(['code'=>201,'msg'=>$resu['errorMsg'],'data'=>[]]);
}
$routeLabelData = '';
if(!empty($resu['msgData']['routeLabelInfo'][0]['routeLabelData'])){
$routeLabelData=$resu['msgData']['routeLabelInfo'][0]['routeLabelData'];
}else{
$resmsg =!empty($resu['errorMsg'])?$resu['errorMsg']:'下单失败,没有路由信息';
if(!empty($resu['msgData']['remark'])) {
if ($resu['msgData']['remark'] == 1) {
$resmsg = $resu['msgData']['remark'] . '、收方超范围'.$drug_pay['take_over'].$drug_pay['detail_address'];
} else if ($resu['msgData']['remark'] == 2) {
$resmsg = $resu['msgData']['remark'] . '、派方超范围'.$drug_pay['take_over'].$drug_pay['detail_address'];
} else if ($resu['msgData']['remark']) {
$resmsg = $resu['msgData']['remark'] . '、其它原因'.$drug_pay['take_over'].$drug_pay['detail_address'];
}
}
$this->dingdingSend($xdOrder.$resmsg);
$this->expressFail($xdOrder,$resmsg);
return json(['code'=>201,'msg'=>$resmsg,'data'=>[]]);
}
$route_label_data = $routeLabelData;
if(empty($routeLabelData['waybillNo'])){
if(!empty($resu['errorMsg'])){
$errorMsg=$resu['errorMsg'];
}else{
if(!empty($resu['msgData']['remark'])){
$remark=$resu['msgData']['remark'];
if($remark==2){
$errorMsg='配送超范围';
}
}
}
$this->dingdingSend($xdOrder.$errorMsg);
$this->expressFail($xdOrder,$errorMsg);
return json(['code'=>201,'msg'=>'顺丰下单失败,运单号空','data'=>[]]);
}else{
$data['mailNo']=$routeLabelData['waybillNo'];
//写入顺丰单号
$sfOrderArr=explode(',',$routeLabelData['waybillNo']);
$address =$present_address_id;
$addresslist=Db::table('wechat_address') ->where(['id'=>$address])->find();
//发送短信和推送模板消息
$sms_data = array (
'xdOrder' => $xdOrder,
'sfOrder' => $sfOrderArr,
'user_mobile' => $orderlist['user_mobile'],
'id' => $orderlist['id'],
'phone' => $orderlist['phone'],
'address_id' => $orderlist['address'],
'prescription' => $orderlist['prescription'],
'patient_unionid' => $orderlist['patient_unionid'],
'consultant_unionid' => $orderlist['consultant_unionid'],
'unitid' => $orderlist['unitid'],
'inquiry_id' => $orderlist['inquiry_id'],
'address_arr'=> $addresslist
);
$this->expressOrder($sms_data);//给收件人发送顺丰单号短信通知消息
//二维码信息
$data['abFlag']=$routeLabelData['abFlag'];
$data['codingMapping']=$routeLabelData['codingMapping'];
$data['codingMappingOut']=$routeLabelData['codingMappingOut'];
$data['destRouteLabel']=$routeLabelData['destRouteLabel'];
$data['destTeamCode']=$routeLabelData['destTeamCode'];
$data['printIcon']='00000000';
$data['proCode']=$routeLabelData['proCode'];
$data['qrcode']=$routeLabelData['twoDimensionCode'];
$data['sourceTransferCode']=$routeLabelData['sourceTransferCode'];
$data['waybillNo']=$routeLabelData['waybillNo'];
$data['xbFlag']=$routeLabelData['xbFlag'];
$routeLabel=json_encode($routeLabelData);
}
}else{
$xiao_order_id = !empty($logisticslist['sf_order'])?$logisticslist['sf_order']:'';
//2.重复生成面单打印
$data['mailNo']=$express_order;
//二维码信息
$data['abFlag']='';
$data['codingMapping']='';
$data['codingMappingOut']='';
$data['destRouteLabel']=$route_label_data['destRouteLabel'];
$data['destTeamCode']='';
$data['printIcon']='00000000';
$data['proCode']=$route_label_data['proCode'];
$data['qrcode']=$route_label_data['twoDimensionCode'];
$data['sourceTransferCode']='';
$data['waybillNo']=$express_order;
$data['xbFlag']='';
}
$orderlist['face_order'] = $xiao_order_id;
$orderlist['route_label_data'] = $route_label_data;
$images_url=$LogoptSdk->createPhoto($data,$drug_pay);
if(!empty($images_url)){
if(empty($express_order)){
// 启动事务
Db::startTrans();
try {
$list['order_id']=$drug_pay['id'];
$list['ordernumber']=$xdOrder;
$list['sf_order']=$xiao_order_id;
$list['sf_waybillno']=$data['mailNo'];
$list['face_images_url']=$images_url;
$list['route_label_data']=$routeLabel;
$list['status']=0;
$list['Logistics_type']=0;
$list['Merge_order']=0;
$list['Sf_cansol_status']=0;
$list['create_time']=time();
$result = Db::table('wechat_logistics')->insert($list);//加入物流表
if(empty($result)){
return json(['code'=>201,'msg'=>'添加物流信息失败','data'=>[]]);
}
//写入跟进记录信息
$contents = json_encode(array('生成物流面单图片'),320);
//面单图片生成成功后,操作对应的其他需要操作的表逻辑
Db::commit();
return json_encode(['code'=>200,'msg'=>'请求成功,第一次生成面单图片','data'=>['images_url'=>$images_url,'xiao_order_id'=>$xiao_order_id,'sfOrder'=>$data['mailNo'],'order'=>$orderlist]],JSON_UNESCAPED_SLASHES);
} catch (\Exception $e) {
// 日志写入
Log::record(json_encode($e->getMessage()), 'express_error');
// 回滚事务
Db::rollback();
return Error::codeMsg(4002);
}
}else{
return json_encode(['code'=>200,'msg'=>'请求成功,第二次生成面单图片','data'=>['images_url'=>$images_url,'xiao_order_id'=>$face_order,'sfOrder'=>$express_order,'order'=>$orderlist]],JSON_UNESCAPED_SLASHES);
}
}else{
if(empty($express_order)){
$this->dingdingSend($xdOrder.'请求失败,生成面单失败');
$this->expressFail($xdOrder,'请求失败,生成面单失败');
return json(['code'=>201,'msg'=>'请求失败,生成面单失败','data'=>['images_url'=>$images_url,'xiao_order_id'=>$xiao_order_id,'address_dev'=>$address_dev,'order'=>$orderlist]],JSON_UNESCAPED_SLASHES);
}else{
$this->dingdingSend($xdOrder.'已有顺丰单号,不用重新请求,谢谢');
$this->expressFail($xdOrder,'已有顺丰单号,不用重新请求,谢谢');
return json(['code'=>201,'msg'=>'已有顺丰单号,不用重新请求,谢谢','data'=>['images_url'=>$images_url,'xiao_order_id'=>$xiao_order_id,'address_dev'=>$address_dev,'order'=>$orderlist]],JSON_UNESCAPED_SLASHES);
}
}
}
至此从顺丰下单,并生成面单图片已完成。
第四步:编写更新物流状态接口
/*1.更新顺丰的物流状态 update此接口需要用脚本定时请求或通过定时任务,时间间隔可以设置成一分钟或两分钟一次
1.7version(100*150)
*/
public function update()
{
$date = date('Y-m-d H:i:s');
$time = strtotime("$date -10 day");//查询出近10天数据进行更新
$where = "dp.status in (1,4,5,6,7) and dp.create_time >=$time and wl.status in (0,1)";//wl.status等于0的是未揽收的,wl.status等于1的是已揽收的
$limit = 100;
//总的条数
$count = Db::table('wechat_drug_pay')
->alias('dp')
->field('dp.id,dp.ordernumber,wl.sf_waybillno')
->join('wechat_logistics wl', 'dp.ordernumber = wl.ordernumber')
->where($where)
->count();
if (empty($count)) {
return json_encode(['code' => 201, 'msg' => '不存在订单信息', 'data' => []]);
}
//防止重复提交
$pagekey = 'page.online';
$redis = new RedisCache();
$page_val = !empty($redis->get($pagekey)) ? $redis->get($pagekey) : 1;//此处将页码存在redis了
if (!$page_val) {
$page_val = 1;
$redis->set($pagekey, 1);
}
$max_page = ceil($count / $limit);
$max_page = !empty($max_page) ? $max_page : 1;
if ($page_val >= $max_page) {
$page = intval($max_page);
$redis->set($pagekey, 1);
} else {
$page = intval($page_val);
$page_val++;
$redis->set($pagekey, $page_val);
}
$offest = ($page - 1) * $limit;
//运单号
$orderlist = Db::table('wechat_drug_pay')
->alias('dp')
->field('dp.id,dp.ordernumber,wl.sf_waybillno')
->join('wechat_logistics wl', 'dp.ordernumber = wl.ordernumber')
->where($where)
->order(" dp.id", "desc")
->limit($offest, $limit)
->select();
if (empty($orderlist)) {
return json_encode(['code' => 201, 'msg' => '不存在订单信息', 'data' => []]);
}
if (!empty($orderlist)) {
$key = 0; //实际更新条数
foreach ($orderlist as $k => $v) {
$num = $k + 1;
$ordernumber = $v['ordernumber'];
$sf_waybillno = $v['sf_waybillno'];
$res = $this->queryExpressStatus($sf_waybillno, $ordernumber);
if (!empty($res['data'])) {
$status = $res['data']['status'];
$key++;
Db::table('wechat_logistics')->where(array("ordernumber" => $ordernumber))->update(['status' => $status, 'update_time' => time()]);
//向订单跟进记录表中插入一条记录
if ($status == 0) {
$type = 4; //未揽收
$contents = '物流未揽收';
} elseif ($status == 1) {
$LogoptSdk = new LogoptSdk();
$res = $LogoptSdk->queryRoutes($sf_waybillno);
$result = json_decode($res, true);
$opCode = !empty($result['data'][0]['opCode']) ? $result['data'][0]['opCode'] : '';
$time = !empty($result['data'][0]['acceptTime']) ? $result['data'][0]['acceptTime'] : '';
$sf_harvest_time = !empty(strtotime($time)) ? strtotime($time) : '';
$type = 9; //已揽收
if ($opCode == 50 || $opCode == 54) {
$contents = '在' . $time . ' 物流已揽收';
} else {
$contents = '物流已揽收';
}
//更新揽收时间
Db::table('wechat_logistics')->where(array("ordernumber" => $ordernumber))->update(['sf_harvest_time' => $sf_harvest_time, 'update_time' => time()]);
} elseif ($status == 2 || $status == 4 || $status == 5) {
$LogoptSdk = new LogoptSdk();
$res = $LogoptSdk->queryRoutesInfo($sf_waybillno);
$result = json_decode($res, true);
$result_routes=$result['data'];
$brr = array();
foreach ($result_routes as $keyes => $values) {
if(!empty($values['opCode'])){
if ($values['opCode'] == 204) {
$brr['remark'] = $values['remark'];
$brr['acceptTime']=strtotime($values['acceptTime']);
}else{
$brr['acceptTime']=strtotime($values['acceptTime']);
}
}
}
$contents = '';
if (!empty($brr)) {
$remark = trim($brr['remark']);
$name = substr($remark, 4 * 3, (stripos($remark, ',') - 4 * 3));
$phone = substr($remark, stripos($remark, ':') + 3, 11);
$contents = '快递员:' . $name . '电话:' . $phone;
}
if ($status == 2) {
$type = 10; //已签收
$contents = '物流已签收。' . $contents;
} else {
$type = 11; //物流异常
if ($status == 4) {
$contents = '物流已拒收。' . $contents;
} else {
$contents = '物流派件异常。' . $contents;
}
}
}
$result = Db::table('wechat_drug_order_recordlog')->where(array("ordernumber" => $ordernumber, 'type' => $type))->find();
if (empty($result)) {
$content = json_encode(array($contents), 320);
$arr = array();
$arr['user_id'] = '';
$arr['ordernumber'] = $ordernumber;
$arr['type'] = $type;
$arr['contents'] = $content;
$arr['create_time'] = time();
$arr['update_time'] = time();
Db::table('wechat_drug_order_recordlog')->insert($arr);
}
}
if ($num == count($orderlist)) {
return json_encode(['code' => 200, 'msg' => '物流状态修改成功', 'data' => ['num' => '请求接口查询' . $num . '条', 'page' => $page, 'max_page' => $max_page, 'key' => '路由信息更新' . $key . '条']]);
}
}
}
}
/*2.顺丰物流状态查询*/
public function queryExpressStatus($express_order,$ordernumber=''){
if(empty($express_order)){
if(!empty($ordernumber)){
$orderlist=Db::table('wechat_drug_pay')
->alias('dp')
->field('dp.id,wl.sf_waybillno')
->join('wechat_logistics wl','dp.id = wl.order_id','LEFT')
->where(['dp.ordernumber'=>$ordernumber])
->find();
$express_order = !empty($orderlist['sf_waybillno'])?$orderlist['sf_waybillno']:'';
}
}
if(empty($express_order)){
return json(['code'=>201,'msg'=>'参数缺失','data'=>[]]);
}
$LogoptSdk = new LogoptSdk();
$res = $LogoptSdk->queryRoutes($express_order);
$res_data = json_decode($res,true);
if($res_data['code']==1){
$opCode = $res_data['data'];
$str=implode(',',$opCode);
if (strpos($str, '80') === false && (strpos($str, '50') !== false||strpos($str, '54') !== false)) {
return ['code'=>200,'msg'=>'查询成功','data'=>['status'=>1,'info'=>'已揽收']];
}elseif(strpos($str,'80')!==false){
return ['code'=>200,'msg'=>'查询成功','data'=>['status'=>2,'info'=>'已签收']];
}elseif(strpos($str,'33')!==false){
return ['code'=>200,'msg'=>'查询成功','data'=>['status'=>4,'info'=>'已拒收']];
}elseif(strpos($str,'70')!==false){
return ['code'=>200,'msg'=>'查询成功','data'=>['status'=>5,'info'=>'派件异常']];
}elseif(strpos($str,'30')!==false||strpos($str,'31')!==false||strpos($str,'36')!==false||strpos($str,'43')!==false||strpos($str,'44')!==false||strpos($str,'105')!==false||strpos($str,'106')!==false||strpos($str,'204')!==false||strpos($str,'657')!==false||strpos($str,'658')!==false){
return ['code'=>200,'msg'=>'查询成功','data'=>['status'=>6,'info'=>'物流运输中']];
}else{
return ['code'=>201,'msg'=>'查询成功','data'=>['status'=>0,'info'=>'未揽收']];
}
}else{
return ['code'=>201,'msg'=>'暂无信息','data'=>[]];
}
}
更多推荐

所有评论(0)