450 lines
11 KiB
PHP
450 lines
11 KiB
PHP
<?php
|
||
namespace app\models\common;
|
||
use Yii;
|
||
use yii\base\Model;
|
||
use yii\db\ActiveRecord;
|
||
/*
|
||
* Copyright (c) 2012—2018 成都零点信息技术有限公司 All
|
||
*/
|
||
|
||
/**
|
||
* 2018 年快跑者正式版开放接口 SDK
|
||
*
|
||
* @author xuhaha sxuhaha@gmail.com
|
||
*/
|
||
class KeloopSdk
|
||
{
|
||
const BASE_URL = 'https://open.keloop.cn';
|
||
const VERSION = 1;
|
||
|
||
private $_team_token = ''; // 团队 Token
|
||
private $_dev_key = ''; // 开发者 key
|
||
private $_dev_secret = ''; // 开发者 密钥
|
||
|
||
/**
|
||
* KeloopSdk constructor.
|
||
* @param $config
|
||
* @throws Exception
|
||
*/
|
||
public function __construct($config)
|
||
{
|
||
$this->_dev_key = $config['dev_key'];
|
||
$this->_dev_secret = $config['dev_secret'];
|
||
$this->_team_token = $config['team_token'];
|
||
|
||
if (empty($this->_dev_key) || empty($this->_dev_secret)) {
|
||
throw new Exception('dev_key 或 dev_secret 异常');
|
||
}
|
||
if (empty($this->_team_token)) {
|
||
throw new Exception('team_token 异常');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* generate ticket
|
||
* @return string
|
||
*/
|
||
private function _genTicket()
|
||
{
|
||
if (function_exists('com_create_guid')) {
|
||
$uuid = trim(com_create_guid(), '{}');
|
||
} else {
|
||
mt_srand((double)microtime() * 10000);
|
||
$charid = strtoupper(md5(uniqid(rand(), true)));
|
||
$hyphen = chr(45);
|
||
$uuid = substr($charid, 0, 8) . $hyphen
|
||
. substr($charid, 8, 4) . $hyphen
|
||
. substr($charid, 12, 4) . $hyphen
|
||
. substr($charid, 16, 4) . $hyphen
|
||
. substr($charid, 20, 12);
|
||
}
|
||
return strtoupper($uuid);
|
||
}
|
||
|
||
/**
|
||
* 封装参数
|
||
* @param array $paramm
|
||
* @return array
|
||
*/
|
||
private function _genParam($paramm = [])
|
||
{
|
||
$data = [
|
||
'version' => self::VERSION,
|
||
'timestamp' => time(),
|
||
'ticket' => $this->_genTicket(),
|
||
'team_token' => $this->_team_token,
|
||
'dev_key' => $this->_dev_key,
|
||
'body' => json_encode($paramm)
|
||
];
|
||
$sign = Md5Sign::getSign($data, $this->_dev_secret);
|
||
$data['sign'] = $sign;
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* @param $path
|
||
* @param array $param
|
||
* @return mixed|null
|
||
*/
|
||
public function getUrl($path, $param = [])
|
||
{
|
||
$data = $this->_genParam($param);
|
||
$url = self::BASE_URL . $path;
|
||
$result = HTTPRequest::getUrl($url, $data);
|
||
if (!empty($result)) {
|
||
return json_decode($result, true);
|
||
} else {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param $path
|
||
* @param array $param
|
||
* @return mixed|null
|
||
*/
|
||
public function postUrl($path, $param = [])
|
||
{
|
||
$data = $this->_genParam($param);
|
||
$url = self::BASE_URL . $path;
|
||
$result = HTTPRequest::postUrl($url, $data);
|
||
if (!empty($result)) {
|
||
return json_decode($result, true);
|
||
} else {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检测 sign 是否正确
|
||
* @param $paramm
|
||
* @return bool
|
||
*/
|
||
public function checkSign($paramm)
|
||
{
|
||
if (!isset($paramm['sign'])) {
|
||
return false;
|
||
}
|
||
return Md5Sign::isSignCorrect($paramm, $this->_dev_secret, $paramm['sign']);
|
||
}
|
||
|
||
// ********************** 订单相关接口 ********************** //
|
||
|
||
/**
|
||
* 向绑定的配送站发送订单
|
||
* @param $param
|
||
* @return mixed|null
|
||
*/
|
||
public function createOrder($param)
|
||
{
|
||
$path = '/open/order/createOrder';
|
||
return $this->postUrl($path, $param);
|
||
}
|
||
|
||
/**
|
||
* 获取订单信息
|
||
* @param $param
|
||
* @return mixed|null
|
||
*/
|
||
public function getOrderInfo($param)
|
||
{
|
||
$path = '/open/order/getOrderInfo';
|
||
return $this->getUrl($path, $param);
|
||
}
|
||
|
||
/**
|
||
* 获取订单进程
|
||
* @param $param
|
||
* @return mixed|null
|
||
*/
|
||
public function getOrderLog($param)
|
||
{
|
||
$path = '/open/order/getOrderLog';
|
||
return $this->getUrl($path, $param);
|
||
}
|
||
|
||
/**
|
||
* 计算快跑者商户配送费
|
||
* @param $param
|
||
* @return mixed|null
|
||
*/
|
||
public function getFee($param)
|
||
{
|
||
$path = '/open/order/getFee';
|
||
return $this->getUrl($path, $param);
|
||
}
|
||
|
||
/**
|
||
* 获取配送员最新坐标
|
||
* @param $param
|
||
* @return mixed|null
|
||
*/
|
||
public function getCourierTag($param)
|
||
{
|
||
$path = '/open/order/getCourierTag';
|
||
return $this->getUrl($path, $param);
|
||
}
|
||
|
||
/**
|
||
* 取消订单
|
||
* @param $param
|
||
* @return mixed|null
|
||
*/
|
||
public function cancelOrder($param)
|
||
{
|
||
$path = '/open/order/cancelOrder';
|
||
return $this->postUrl($path, $param);
|
||
}
|
||
|
||
/**
|
||
* 评论订单
|
||
* @param $param
|
||
* @return mixed|null
|
||
*/
|
||
public function commentOrder($param)
|
||
{
|
||
$path = '/open/order/commentOrder';
|
||
return $this->postUrl($path, $param);
|
||
}
|
||
|
||
/**
|
||
* 获取商户计价明细
|
||
* @param $param
|
||
* @return mixed|null
|
||
*/
|
||
public function getMerchantCalc($param)
|
||
{
|
||
$path = '/open/order/getFee';
|
||
return $this->postUrl($path, $param);
|
||
}
|
||
|
||
// ********************** 团队相关接口 ********************** //
|
||
|
||
/**
|
||
* 获取团队信息
|
||
* @return mixed|null
|
||
*/
|
||
public function getTeamInfo()
|
||
{
|
||
$path = '/open/team/getTeamInfo';
|
||
return $this->getUrl($path);
|
||
}
|
||
|
||
// ********************** 商户相关接口 ********************** //
|
||
|
||
/**
|
||
* 获取团队所有合作商户信息
|
||
* @return mixed|null
|
||
*/
|
||
public function getMerchants()
|
||
{
|
||
$path = '/open/merchant/getMerchants';
|
||
return $this->getUrl($path);
|
||
}
|
||
|
||
// ********************** 配送员相关接口 ********************** //
|
||
|
||
/**
|
||
* 获取团队合作的所有配送员信息
|
||
* @return mixed|null
|
||
*/
|
||
public function getCouriers()
|
||
{
|
||
$path = '/open/courier/getCouriers';
|
||
return $this->getUrl($path);
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* 签名类
|
||
* Class Md5Sign
|
||
*/
|
||
class Md5Sign
|
||
{
|
||
|
||
/**
|
||
* 获取签名
|
||
* @param array $param 密的参数数组
|
||
* @param string $accessSec 加密的key
|
||
* @return bool|string 生产的签名
|
||
*/
|
||
public static function getSign($param, $accessSec)
|
||
{
|
||
if (empty($param) || empty($accessSec)) {
|
||
return false;
|
||
}
|
||
|
||
// 除去待签名参数数组中的空值和签名参数
|
||
$param = self::paraFilter($param);
|
||
$param = self::argSort($param);
|
||
$str = self::createLinkstring($param);
|
||
$sign = self::md5Verify($str, $accessSec);
|
||
return $sign;
|
||
}
|
||
|
||
/**
|
||
* 判断签名是否正确
|
||
* @param $paramm
|
||
* @param $encKey
|
||
* @param $sign
|
||
* @return bool
|
||
*/
|
||
public static function isSignCorrect($paramm, $encKey, $sign)
|
||
{
|
||
if (empty($sign)) {
|
||
return false;
|
||
} else {
|
||
$prestr = self::getSign($paramm, $encKey);
|
||
return $prestr === $sign ? true : false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 除去数组中的空值和签名参数
|
||
* @param array $param 签名参数组
|
||
* @return array 获取去掉空值与签名参数后的新签名参数组
|
||
*/
|
||
private static function paraFilter($param)
|
||
{
|
||
$param_filter = array();
|
||
while (list ($key, $val) = each($param)) {
|
||
//去掉 '',null,保留数字0
|
||
if ($key == 'sign' || $key == 'sign_type' || $key == 'key' || (empty($val) && !is_numeric($val))) {
|
||
continue;
|
||
} else {
|
||
$param_filter[$key] = $param[$key];
|
||
}
|
||
}
|
||
return $param_filter;
|
||
}
|
||
|
||
/**
|
||
* 对数组排序
|
||
* @param array $param 排序前的数组
|
||
* @return mixed 排序后的数组
|
||
*/
|
||
private static function argSort($param)
|
||
{
|
||
ksort($param);
|
||
reset($param);
|
||
return $param;
|
||
}
|
||
|
||
/**
|
||
* 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
|
||
* @param array $param 需要拼接的数组
|
||
* @return string 拼接完成以后的字符串
|
||
*/
|
||
private static function createLinkstring($param)
|
||
{
|
||
$arg = '';
|
||
while (list ($key, $val) = each($param)) {
|
||
$arg .= $key . '=' . $val . '&';
|
||
}
|
||
//去掉最后一个&字符
|
||
$arg = trim($arg, '&');
|
||
//如果存在转义字符,那么去掉转义
|
||
if (get_magic_quotes_gpc()) {
|
||
$arg = stripslashes($arg);
|
||
}
|
||
return $arg;
|
||
}
|
||
|
||
/**
|
||
* 生成签名
|
||
* @param string $prestr 需要签名的字符串
|
||
* @param string $sec 身份认证密钥(access_sec)
|
||
* @return string 签名结果
|
||
*/
|
||
private static function md5Verify($prestr, $sec)
|
||
{
|
||
return md5($prestr . $sec);
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* HTTP 请求类
|
||
* Class HTTPRequest
|
||
*/
|
||
class HTTPRequest
|
||
{
|
||
|
||
/**
|
||
* Http post request
|
||
* @param $url
|
||
* @param array $paramms
|
||
* @param int $timeout
|
||
* @return bool|mixed
|
||
*/
|
||
public static function postUrl($url, $paramms = array(), $timeout = 3)
|
||
{
|
||
//编码特殊字符
|
||
$p = http_build_query($paramms);
|
||
$curl = curl_init();
|
||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
|
||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 检查SSL加密算法是否存在
|
||
curl_setopt($curl, CURLOPT_URL, $url);
|
||
// 设置header
|
||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||
curl_setopt($curl, CURLOPT_POST, 1);
|
||
curl_setopt($curl, CURLOPT_POSTFIELDS, $p);
|
||
// 设置cURL 参数,要求结果保存到字符串中还是输出到屏幕上。
|
||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||
// 运行cURL,请求网页
|
||
$data = curl_exec($curl);
|
||
curl_close($curl);
|
||
if ($data === false) {
|
||
return false;
|
||
} else {
|
||
return $data;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Http get request
|
||
* @param $url
|
||
* @param array $paramm
|
||
* @return mixed
|
||
*/
|
||
public static function getUrl($url, $paramm = array())
|
||
{
|
||
$url = self::buildUrl($url, $paramm);
|
||
return self::get($url);
|
||
}
|
||
|
||
/**
|
||
* Http get request
|
||
* @param $url
|
||
* @param int $timeout
|
||
* @return mixed
|
||
*/
|
||
public static function get($url, $timeout = 3)
|
||
{
|
||
$ch = curl_init($url);
|
||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||
$resposne = curl_exec($ch);
|
||
return $resposne;
|
||
}
|
||
|
||
/**
|
||
* Build request url
|
||
* @param $url
|
||
* @param $paramm
|
||
* @return string
|
||
*/
|
||
private static function buildUrl($url, $paramm)
|
||
{
|
||
$url = rtrim(trim($url), '?');
|
||
$url = $url . '?';
|
||
$query = '';
|
||
if (!empty($paramm)) {
|
||
$query = http_build_query($paramm);
|
||
}
|
||
return $url . $query;
|
||
}
|
||
|
||
} |