顺丰开放平台Api PHP SDK demo
引用
对接前期工作
- 注册
- 提交接入申请
- 接口初始化配置,获得 app_id 和app_secret
- 完成测试环境测试
- 进入生产使用
接入注意事项
- 申请令牌 (
/security/access_token/
接口) access_token
有效期为 1 小时,过期需使用refresh_token
刷新令牌(/security/refresh_token/
接口)refresh_token
有效期为当天 24 点,过期需重新申请(/security/access_token/
接口)- 接口均为
https
,数据传输格式为json
Demo
SDK Demo
<?php
/**
* 顺丰 api 接口使用
* Date: 2017/10/19
* Time: 9:36
* @author zlh <root@rooot.me>
*/
class SfApi {
/**
* @var string
*/
protected $app_id;
/**
* @var string
*/
protected $app_key;
/**
* @var string
*/
public $access_token;
/**
* @var string
*/
public $refresh_token;
/**
* @var string
*/
private $uri;
/**
* SfApi constructor.
* @param string $app_id
* @param string $app_key
* @param bool $online
* @return void
*/
public function __construct ($app_id, $app_key, $online = false) {
$this->app_id = $app_id;
$this->app_key = $app_key;
$this->url = $online ? 'https://open-prod.sf-express.com/' : 'https://open-sbox.sf-express.com/';
}
/**
* 快速创建订单
* @param array $req_body
* @return bool|string
*/
public function order ($req_body) {
$req_body = array(
'orderId' => $req_body['orderId'],
'expressType' => $req_body['expressType'],
'payMethod' => $req_body['payMethod'],
'custId' => $req_body['custId'],
'payArea' => isset($req_body['payArea']) ? $req_body['payArea'] : 'SFCM10008035754399',
//'remark' => $req_body['remark'],
'consigneeInfo' => array(
'company' => isset($req_body['consigneeInfo']['company']) ? $req_body['consigneeInfo']['company'] : '个人',
'contact' => $req_body['consigneeInfo']['contact'],
'tel' => $req_body['consigneeInfo']['tel'],
'province' => $req_body['consigneeInfo']['province'],
'city' => $req_body['consigneeInfo']['city'],
'county' => $req_body['consigneeInfo']['county'],
'address' => $req_body['consigneeInfo']['address'],
'mobile' => $req_body['consigneeInfo']['mobile'],
),
'cargoInfo' => array(
'cargo' => $req_body['cargoInfo']['cargo'],
),
'addedServices' => $req_body['addedServices'],
);
$res = $this->send('order', $req_body);
$res_tmp = json_decode($res, true);
if(empty($res_tmp['head']['code'])) {
return '系统错误!';
}elseif(substr($res_tmp['head']['code'], -3) != '200') {
return $res_tmp['head']['message'];
}else{
return true;
}
}
/**
* 订单结果查询
* @param string $order_id
* @return json
*/
public function orderQuery ($order_id) {
$req_body = array(
'orderId' => $order_id
);
return $this->send('order/query', $req_body);
}
/**
* 根据 运单号/订单号 查询物流路由
* @param array $req_body
* @return json
*/
public function routeQuery ($req_body) {
$req_body = array(
'trackingType' => $req_body['trackingType'],
'trackingNumber' => $req_body['trackingNumber'],
'methodType' => $req_body['methodType'],
);
return $this->send('route/query', $req_body);
}
/**
* 电子运单图片下载
* @param string $orderId
* @param bool $isLogo
* @return json (image参数为BASE64编码的字符串)
*/
public function wayBillImage ($orderId, $isLogo = false) {
$req_body = array(
'orderId' => $orderId,
'isLogo' => $isLogo ? 1 : 0
);
return $this->send('waybill/image', $req_body);
}
/**
* 获取顺丰授权
* @return json
*/
public function getToken () {
return $this->send('security/access_token');
}
/**
* 刷新授权令牌
* @param string $access_token
* @param string $refresh_token
* @return json
*/
public function refreshToken ($access_token, $refresh_token) {
$this->access_token = $access_token;
$this->refresh_token = $refresh_token;
return $this->send('security/refresh_token');
}
/**
* 忘记 access_token 查询
* @return json
*/
public function queryToken () {
return $this->send('security/access_token/query');
}
/**
* 根据请求的接口创建相应的 Uri
* @param string $resource 要请求的resource(前后不带'/')
* @return string
*/
protected function buildUri ($resource) {
$query = '/sf_appid/' . $this->app_id . '/sf_appkey/' . $this->app_key;
if ($resource == 'security/refresh_token') {
$query = "/access_token/$this->access_token/refresh_token/$this->refresh_token" . $query;
}elseif (substr($resource, 0, 8) != 'security') {
$query = '/access_token/' . $this->access_token . $query;
}
$uri = $this->url . $this->transType()[$resource]['type'] . '/v1.0/' . $resource . $query;
return $uri;
}
/**
* 向顺丰接口发送请求
* SSL POST JSON
* @param string $resource 要请求的resource(前后不带'/')
* @param array $body 请求报文(参数)
* @return json
*/
protected function send ($resource, $body = array()) {
$this->uri = $this->buildUri($resource);
$req_data = array(
'head' => array(
'transType' => $this->transType()[$resource]['transType'],
'transMessageId' => date('Ymd') . substr_replace(time(), mt_rand(10,99),0,2),
)
);
if(!empty($body)) {
$req_data['body'] = $body;
}
$header = array(
"Content-Type: application/json",
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->uri);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true); // 从证书中检查SSL加密算法是否存在
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($req_data));
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
/**
* 顺丰开放平台各接口对应的资源类型
* @return array
*/
private function transType () {
return array(
'order' => array('transType' => 200, 'type' => 'rest'),
'order/query' => array('transType' => 203, 'type' => 'rest'),
'filter' => array('transType' => 204, 'type' => 'rest'),
'route/query' => array('transType' => 501, 'type' => 'rest'),
'route/inc/query' => array('transType' => 504, 'type' => 'rest'),
'waybill/image' => array('transType' => 205, 'type' => 'rest'),
'product/basic/query' => array('transType' => 250, 'type' => 'rest'),
'product/additional/query' => array('transType' => 251, 'type' => 'rest'),
'security/access_token/query' => array('transType' => 300, 'type' => 'public'),
'security/access_token' => array('transType' => 301, 'type' => 'public'),
'security/refresh_token' => array('transType' => 302, 'type' => 'public'),
);
/**
快速下单 /order/ 200
订单查询 /order/query/ 203
订单筛选 /filter/ 204
路由查询 /route/query/ 501
路由增量查询 /route/inc/query/ 504
电子运单图片下载 /waybill/image/ 205
基础服务查询 /product/basic/query/ 250
附加服务查询 /product/additional/query/ 251
申请访问令牌 /security/access_token/ 301
查询访问令牌 /security/access_token/query/ 300
刷新访问令牌 /security/refresh_token/ 302
*/
}
}
使用
- 引入该类文件
- 并实例化,参数分别为
app_id
,app_secret
,是否用于生产环节 (true|false),默认为 false
。 - 检查
access_token
并设置。 - 调用对应方法即可,详细使用请参考方法注释和顺丰接口文档。
例子
// 实例化对象并传入参数
$sf = new SfApi('your app_id', 'your app_secret', false);
// 获取 access_token
$token_res = $sf->getToken();
var_dump($token_res);
// 为对象设置 access_token 属性
$sf->access_token = json_decode($token_res, true)['body']['accessToken'];
// 下单
$req_body = array(
'orderId' => 'SF201710091507536283',
'expressType' => 1,
'payMethod' => 3,
'custId' => 'your custId',
'payArea' => '010EU',
'remark' => '备注',
'consigneeInfo' => array(
'company' => '个人',
'contact' => '测试对象',
'tel' => '17600000000',
'province' => '北京市',
'city' => '北京市',
'county' => '朝阳区',
'address' => '十里河',
'mobile' => '17600000000',
),
'cargoInfo' => array(
'cargo' => '产品名',
),
// 代收货款需填,标准快递则不需要如下参数
'addedServices' => array(
array(
'name' => 'COD',
'value' => '698',
),
array(
'name' => 'CUSTID',
'value' => 'your custId'
)
)
);
$order_res= $sf->order($req_body);
var_dump($order_res);
// 获取运单图片
$image_res = $sf->wayBillImage('SF201710091507536283');
$image_res = json_decode($image_res, true);
file_put_contents('./SF201710091507536283.jpg', base64_decode($image_res['body']['images'][0]));
echo '<img src="./SF201710091507536283.jpg" />';
运单图片
示例
图中马赛克为手打
运单图片处理
处理图片使用 GD
或 imagemagick
等处理图片的库。
一般来说需要隐藏客户的收件信息,下附上图片处理相关函数。
/** 图片局部打马赛克
* @param String $source 原图
* @param Stirng $dest 生成的图片
* @param int $x1 起点横坐标
* @param int $y1 起点纵坐标
* @param int $x2 终点横坐标
* @param int $y2 终点纵坐标
* @param int $deep 深度,数字越大越模糊
* @param bool $fill 是否只填充白色
* @return boolean
*/
function imageMosaics($source, $dest, $x1, $y1, $x2, $y2, $deep, $fill = false){
// 判断原图是否存在
if(!file_exists($source)){
return false;
}
// 获取原图信息
list($owidth, $oheight, $otype) = getimagesize($source);
// 判断区域是否超出图片
if($x1>$owidth || $x1<0 || $x2>$owidth || $x2<0 || $y1>$oheight || $y1<0 || $y2>$oheight || $y2<0){
return false;
}
switch($otype){
case 1: $source_img = imagecreatefromgif($source); break;
case 2: $source_img = imagecreatefromjpeg($source); break;
case 3: $source_img = imagecreatefrompng($source); break;
default:
return false;
}
// 打马赛克
if($fill === false) {
for($x=$x1; $x<$x2; $x=$x+$deep){
for($y=$y1; $y<$y2; $y=$y+$deep){
$color = imagecolorat($source_img, $x+round($deep/2), $y+round($deep/2));
imagefilledrectangle($source_img, $x, $y, $x+$deep, $y+$deep, $color);
}
}
}else{
$im = imagecreatetruecolor(200, 200);
$fill = imagecolorallocate($im, 255, 255, 255);
imagefilledrectangle($source_img, $x1, $y1, $x2, $y2, $fill);
}
// 生成图片
switch($otype){
case 1: imagegif($source_img, $dest); break;
case 2: imagejpeg($source_img, $dest); break;
case 3: imagepng($source_img, $dest); break;
}
return is_file($dest)? true : false;
}
// 使用
$source = $dest = './201710244108826825.jpg';
// 5,5 1125,100 区域填充白色(应对带有顺丰logo的打印纸)
$flag = imageMosaics($source, $dest, 5, 5, 1125, 100, 4, true);
// (120)215, 250 810,400 区域马赛克
$flag = imageMosaics($source, $dest, 215, 250, 810, 400, 7);
// (110)210,1207 678,1314 区域马赛克
$flag = imageMosaics($source, $dest, 210, 1207, 678, 1314, 7);
echo '<img width="400px" src="'.$source.'">';
该函数为以前网络上找到并改造的,未找到原作者。如有侵权请联系我删除。
处理后示例
图中 logo 处和收件人处为函数生成的马赛克、填充白色,其余区域为手打马赛克。
其他
代码写的比较仓促,不过一般的与顺丰对接也就这些基本功能,还有一些接口本文没有用到的,可以参考上面 SDK 中对应函数的注释和接口文档。
注:转载请注明出处。
本文由 root 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Sep 28, 2018 at 12:10 pm