time_stamp = date('Y-m-d H:i:s', time());//时间 yyyyMMddhhmmss
// $this->params_base['IMEI'] = '0000';//设备串号(移动终端设备串号,默认0000)
// $this->params_base['apiVersion'] = $this->api_version;//接口版本号(服务端向下版本兼容控制),默认值为1
// $this->params_base['SIGN'] = md5($this->params_base['IMEI']."&".$this->client_id."&".$this->params_base['timeStamp']);
// echo $this->params_base['IMEI']."&".$this->client_id."&".$this->params_base['timeStamp'];
// 设定default时产生
//加载redis
$this->redis = Redis::getInstance()->getConnect();
//从redis中拿参数..这些参数来自于数据库ims_superdesk_jd_vop_configs表..然后设置默认的时候存到了redis zjh 2018年8月17日 14:22:06
$key = 'superdesk_jd_vop_' . 'web_jd_vop_configs_manage' . ':' . 17;
$api_conf = $this->redis->get($key);
if (!empty($api_conf)) {
$api_conf = json_decode($api_conf, true);
$this->client_id = $api_conf['client_id'];
$this->client_secret = $api_conf['client_secret'];
$this->username = $api_conf['username'];
$this->password = $api_conf['password'];
} else {
$api_conf = JdConfig::create()->where('is_default',1)->get()->toArray();
if(!empty($api_conf)){
$this->client_id = $api_conf['client_id'];
$this->client_secret = $api_conf['client_secret'];
$this->username = $api_conf['username'];
$this->password = $api_conf['password'];
} else {
//手动配置 201998
$this->client_id = 'nuAeRH1KFlSeiIrfPYTZ';
$this->client_secret = 'ioyqcauADf0v3ayE73I5';
$this->username = '中航物业员工福利';
$this->password = 'avic-s';
}
}
}
function init_access_token()
{
global $_W;
/******************************************************* redis *********************************************************/
$table__key = 'superdesk_jd_vop_' . 'sdk_access_token' . ':' . 17;
$colunm_key = 'jd_vop_access_token';
//microtime_format('Y-m-d H:i:s.x',microtime())
$result = $this->redis->hget($table__key, $colunm_key);
$result = json_decode($result, true);
// echo json_encode($result,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
if (empty($result) || empty($result['result'])) {
$result = $this->access_token();
$this->redis->hset($table__key, $colunm_key, $result);
$result = json_decode($result, true);
}
if (intval(floatval($result['result']['time']) / 1000) + intval($result['result']['expires_in']) <= time()) {
$result = $this->refresh_token($result['result']['refresh_token']);
$this->redis->hset($table__key, $colunm_key, $result);
// BUG 当要去刷时 $result 变回字符串
$result = json_decode($result, true);
}
$this->access_token = $result['result']['access_token'];
// echo $this->access_token;
// echo "
";
// echo date('Y-m-d H:i:s', floatval($result['result']['time']) / 1000);
// echo "
";
// echo "
";
/******************************************************* redis *********************************************************/
}
/**
* 签名,生成规则如下:
* 1. 按照以下顺序将字符串拼接起来
* client_secret+timestamp+client_id+username+password+grant_type+scope+client_secret
* 其中
* client_secret的值是京东分配的
* username使用原文
* password需要md5加密后的
* 2. 将上述拼接的字符串使用MD5加密,加密后的值再转为大写
*/
function create_sign()
{
$sign_str =
$this->client_secret .
$this->time_stamp . $this->client_id . $this->username . md5($this->password) . $this->grant_type . $this->scope .
$this->client_secret;
$sign_md5 = md5($sign_str);
$sign_result = strtoupper($sign_md5);
return $sign_result;
}
/**
* TODO 已测 1.3 获取Access Token
* HTTPS请求方式:POST
*
* @return string
*/
function access_token_url()
{
return $this->host . $this->edition . "/oauth2/accessToken";
}
function access_token()
{
$params = array();
$params['grant_type'] = $this->grant_type;//该值固定为access_token
$params['client_id'] = $this->client_id;
$params['client_secret'] = $this->client_secret;
$params['timestamp'] = $this->time_stamp;
$params['username'] = $this->username;
$params['password'] = md5($this->password);
$params['scope'] = $this->scope;//非必须 申请权限。(目前推荐为空。为以后扩展用)
$params['sign'] = $this->create_sign();
$response = $this->post($this->access_token_url(), $params, true);
// {
// "success": true,
// "resultMessage": "",
// "resultCode": "0000",
// "result": {
// "uid": "6165718786",
// "refresh_token_expires": 1525071742348,
// "time": 1509346942348,
// "expires_in": 86400,
// "refresh_token": "A23k88ryXJx9QJBay7QEmdPcM0GoJk8uidR2pIjy",
// "access_token": "NIwoLn95BLs0ZdKLyawIiuFPM"
// }
// }
return $response;
}
/**
* TODO 已测 1.4 使用Refresh Token 刷新 Access Token
* HTTPS请求方式:POST
*
* @return string
*/
function refresh_token_url()
{
return $this->host . $this->edition . "/oauth2/refreshToken";
}
function refresh_token($refresh_token)
{
$params = array();
$params['refresh_token'] = $refresh_token;
$params['client_id'] = $this->client_id;
$params['client_secret'] = $this->client_secret;
$response = $this->post($this->refresh_token_url(), $params, true);
// {
// "success": true,
// "resultMessage": "",
// "resultCode": "0000",
// "result": {
// "uid": "6165718786",
// "refresh_token_expires": 1525077000000,
// "time": 1509352200000,
// "expires_in": 86400,
// "refresh_token": "lhC8Btoft3GovRWad71v7b2RZ0ZQ45wQWjNmn46j",
// "access_token": "yEZ3Ut9m1Np4XAGm8Qaq0f9s2"
// }
// }
return $response;
}
//======================Other End========================
/**
* GET wrappwer for oAuthRequest.
*
* @return mixed
*/
function get($url, $parameters = array())
{
$response = $this->oAuthRequest($url, 'GET', $parameters);
if ($this->format === 'json' && $this->decode_json) {
return json_decode($response, true);
}
return $response;
}
/**
* POST wreapper for oAuthRequest.
*
* @return mixed
*/
function post($url, $parameters = array(), $multi = false)
{
$response = $this->oAuthRequest($url, 'POST', $parameters, $multi);
if ($this->format === 'json' && $this->decode_json) {
return json_decode($response, true);
}
return $response;
}
/**
* Format and sign an OAuth / API request
*
* @return string
* @ignore
*/
function oAuthRequest($url, $method, $params, $multi = false)
{
if (strrpos($url, 'http://') !== 0 && strrpos($url, 'https://') !== 0) {
$url = "{$this->host}/{$this->edition}/{$url}";
} else {
$url = $url . '?client_id=' . $this->client_id . '&client_secret=' . $this->client_secret;
}
$parameters = array_merge_recursive($this->params_base, $params);
// TODO jd_vop_api_logs
switch ($method) {
case 'GET' :
$url = $url . http_build_query($parameters);
return $this->http($url, 'GET');
case 'PUT' :
$headers = array();
if (!$multi && (is_array($parameters) || is_object($parameters))) {
if ($this->format === 'json' && $this->decode_json) {
$body = json_encode($parameters);
if ($this->debug) {
echo '============= BODY =============';
echo '
';
echo $body;
echo '
';
echo '============= BODY =============';
echo '
';
}
} else {
$body = http_build_query($parameters);
}
} else {
$body = self::build_http_query_multi($parameters);
$headers [] = "Content-Type: multipart/form-data; boundary=" . self::$boundary;
}
return $this->http($url, 'PUT', $body, $headers);
case 'DELETE' :
if (!empty($parameters)) {
$url = $url . '&' . http_build_query($parameters);
}
return $this->http($url, 'DELETE');
default :
$headers = array();
if (!$multi && (is_array($parameters) || is_object($parameters))) {
if ($this->format === 'json' && $this->decode_json) {
$body = json_encode($parameters);
if ($this->debug) {
echo '============= BODY =============';
echo '
';
echo $body;
echo '
';
echo '============= BODY =============';
echo '
';
}
} else {
$body = http_build_query($parameters);
}
} else {
$body = self::build_http_query_multi($parameters);
$headers [] = "Content-Type: multipart/form-data; boundary=" . self::$boundary;
}
return $this->http($url, $method, $body, $headers);
}
}
/**
* Make an HTTP request
*
* @return string API results
* @ignore
*/
function http($url, $method, $postfields = NULL, $headers = array())
{
$this->http_info = array();
$ci = curl_init();
/* Curl settings */
curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ci, CURLOPT_ENCODING, "");
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
// curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader'));
curl_setopt($ci, CURLOPT_HEADER, FALSE);
switch ($method) {
case 'GET':
curl_setopt($ci, CURLOPT_HTTPGET, TRUE);
if (!empty($postfields)) {
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
$this->postdata = $postfields;
}
break;
case 'POST':
curl_setopt($ci, CURLOPT_POST, TRUE);
if ($this->format === 'json') {
$headers [] = "Content-Type: application/json;";
}
if (!empty($postfields)) {
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
$this->postdata = $postfields;
}
break;
case 'PUT':
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'PUT');
$headers [] = "Content-Type: application/json;";
if (!empty($postfields)) {
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
$this->postdata = $postfields;
}
break;
case 'DELETE':
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
if (!empty($postfields)) {
$url = "{$url}?{$postfields}";
echo $url;
echo '
';
} else {
$url = $url;
}
break;
}
// $headers[] = "API-RemoteIP: " . $_SERVER['REMOTE_ADDR'];
curl_setopt($ci, CURLOPT_URL, $url);
curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ci, CURLINFO_HEADER_OUT, TRUE);
$response = curl_exec($ci);
$this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
$this->http_info = array_merge($this->http_info, curl_getinfo($ci));
$this->url = $url;
if ($this->debug) {
echo "=====post data======\r\n";
echo '
';
var_dump($postfields);
echo '
';
echo '=====info=====' . "\r\n";
echo '
';
print_r(curl_getinfo($ci));
echo '
';
echo '=====$response=====' . "\r\n";
echo '
';
print_r($response);
echo '
';
}
$code = curl_getinfo($ci);
$response = json_decode($response, true);
if (!$response) {// TODO 暂时修正京东返回空的问题
$response = array();
}
$response['code'] = $code['http_code'];
$___url___ = str_replace($this->host . $this->edition, '', $url);
$log_data = array();
$log_data['url'] = $url;
$log_data['api'] = substr($___url___, 0, strpos($___url___, '?'));
$log_data['method'] = $method;
$log_data['post_fields'] = $postfields;
$log_data['curl_info'] = json_encode(curl_getinfo($ci), JSON_UNESCAPED_UNICODE);
$log_data['success'] = isset($response['success']) ? $response['success'] : "exit0";
$log_data['resultMessage'] = isset($response['resultMessage']) ? $response['resultMessage'] : "exit0";
$log_data['resultCode'] = isset($response['resultCode']) ? $response['resultCode'] : "exit0";
$log_data['result'] = isset($response['result']) ? json_encode($response['result'], JSON_UNESCAPED_UNICODE) : "";
/************************** 2019年12月31日 09:42:42 zjh 改数据库为文件 *************************************/
// $this->_logsModel->insert($log_data);// TODO 屏蔽测试
//日志记录
Logger::getInstance()->info('京东请求日志:' . json_encode($log_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
/************************** 2019年12月31日 09:42:42 zjh 改数据库为文件 *************************************/
if (!empty($response['status']) && $response['status'] == 'Unauthorized.') {
/* header("Location:".site_url("Login/logout"));
exit();*/
$response['status'] = 'Unauthorized.';
}
$response = json_encode($response);
curl_close($ci);
return $response;
}
/**
* 处理多媒体数据内容
*
* @ignore
*/
public static function build_http_query_multi($params)
{
if (!$params) return '';
uksort($params, 'strcmp');
$pairs = array();
self::$boundary = $boundary = uniqid('------------------');
$MPboundary = '--' . $boundary;
$endMPboundary = $MPboundary . '--';
$multipartbody = '';
foreach ($params as $parameter => $value) {
if (in_array($parameter, array('pic', 'image', 'Filedata')) && $value{0} == '@') {
$url = ltrim($value, '@');
$content = file_get_contents($url);
$array = explode('?', basename($url));
$filename = $array[0];
$multipartbody .= $MPboundary . "\r\n";
$multipartbody .= 'Content-Disposition: form-data; name="' . $parameter . '"; filename="' . $filename . '"' . "\r\n";
$multipartbody .= "Content-Type: image/unknown\r\n\r\n";
$multipartbody .= $content . "\r\n";
} else {
$multipartbody .= $MPboundary . "\r\n";
$multipartbody .= 'content-disposition: form-data; name="' . $parameter . "\"\r\n\r\n";
$multipartbody .= $value . "\r\n";
}
}
$multipartbody .= $endMPboundary;
return $multipartbody;
}
/***********************************************************************************************************************/
/**************** 以下处理业务逻辑 *******************/
/**
* TODO 已测 3.5 商品上下架状态接口
* HTTPS请求方式:POST
*
* @return string
*/
function api_product_sku_state_url()
{
return $this->host . $this->edition . "/api/product/skuState";
}
function api_product_sku_state($sku)
{
$params = array();
$params['token'] = $this->access_token; //授权时获取的access token
$params['sku'] = $sku;//商品编号,支持批量,以,分隔 (最高支持100个商品)1为上架,0为下架
$response = $this->post($this->api_product_sku_state_url(), $params, true);
// 参见:3.5 获取商品上下架状态接口.json
return $response;
}
/**
* TODO 待测 6.2 批量获取库存接口(建议订单详情页、下单使用)
* HTTPS请求方式:POST
*
* @return string
*/
function api_stock_get_new_stock_by_id_url()
{
return $this->host . $this->edition . "/api/stock/getNewStockById";
}
function api_stock_get_new_stock_by_id($skuNums/*商品和数量 [{skuId: 569172,num:101}]*/, $area/*格式:1_0_0 (分别代表1、2、3级地址)*/)
{
$params = array();
$params['token'] = $this->access_token;
$params['skuNums'] = $skuNums;//商品和数量 [{skuId: 569172,num:101}]
$params['area'] = $area;//格式:1_0_0 (分别代表1、2、3级地址)
$response = $this->post($this->api_stock_get_new_stock_by_id_url(), $params, true);
//参数名称 意义
//areaId 配送地址id
//desc 描述
//skuId 商品编号
//stockStateId 库存状态编号 33,39,40,36,34
//StockStateDesc 库存状态描述
//33 有货 现货-下单立即发货
//39 有货 在途-正在内部配货,预计2~6天到达本仓库
//40 有货 可配货-下单后从有货仓库配货
//36 预订
//34 无货
//remainNum 剩余数量 -1未知;当库存小于5时展示真实库存数量
// 参见:6.2 批量获取库存接口(建议订单详情页、下单使用).json
return $response;
}
/**
* TODO 待测 5.2 批量查询协议价价格
* HTTPS请求方式:POST
*
* @return string
*/
function api_price_get_price_url()
{
return $this->host . $this->edition . "/api/price/getPrice";
}
function api_price_get_price($sku)
{
// $start = microtime(true);
$params = array();
$params['token'] = $this->access_token;//授权时获取的access token
$params['sku'] = $sku;//商品编号,请以,分割。例如:J_129408,J_129409(最高支持100个商品)
$response = $this->post($this->api_price_get_price_url(), $params, true);
// 参见:5.2 批量查询协议价价格.json
// $end = microtime(true);
// echo 'api_price_get_price 耗时'.round($end - $start,4).'秒';
// echo '
';
return $response;
}
}