|
|
<?php
|
|
|
|
|
|
/**
|
|
|
* 有货相关接口类
|
|
|
*
|
|
|
* @name Yohobuy
|
|
|
* @package library/Api
|
|
|
* @copyright yoho.inc
|
|
|
* @version 1.0 (2015-9-30 16:42:51)
|
|
|
* @author fei.hong <fei.hong@yoho.cn>
|
|
|
*/
|
|
|
|
|
|
namespace Api;
|
|
|
|
|
|
use Plugin\Cache;
|
|
|
|
|
|
class Yohobuy
|
|
|
{
|
|
|
/* 正式环境 */
|
|
|
|
|
|
// const API_URL = 'http://api2.open.yohobuy.com/';
|
|
|
// const API_URL2 = 'http://api.open.yohobuy.com/';
|
|
|
// const SERVICE_URL = 'http://service.api.yohobuy.com/';
|
|
|
// const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
|
|
|
// const API_URL = 'http://apih5.yoho.cn/';
|
|
|
// const API_URL2 = 'http://apih5.yoho.cn/';
|
|
|
// const SERVICE_URL = 'http://serviceh5.yoho.cn/';
|
|
|
// const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
// const API_OLD = 'http://api2.open.yohobuy.com/';
|
|
|
|
|
|
// /* 测试环境 */
|
|
|
// const API_URL = 'http://testapi.yoho.cn:28078/';
|
|
|
// const SERVICE_URL = 'http://testservice.yoho.cn:28077/';
|
|
|
// const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
// const API_OLD = 'http://test2.open.yohobuy.com/';
|
|
|
|
|
|
/* 预览环境 */
|
|
|
const API_URL = 'http://preapi.yoho.cn/';
|
|
|
const API_URL2 = 'http://preapi.yoho.cn/';
|
|
|
const SERVICE_URL = 'http://serviceh5.yoho.cn/';
|
|
|
const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
const API_OLD = 'http://api2.open.yohobuy.com/';
|
|
|
|
|
|
/**
|
|
|
* 私钥列表
|
|
|
*
|
|
|
* @var array
|
|
|
*/
|
|
|
public static $privateKeyList = array(
|
|
|
'android' => 'fd4ad5fcfa0de589ef238c0e7331b585',
|
|
|
'iphone' => 'a85bb0674e08986c6b115d5e3a4884fa',
|
|
|
'ipad' => 'ad9fcda2e679cf9229e37feae2cdcf80',
|
|
|
'web' => '0ed29744ed318fd28d2c07985d3ba633',
|
|
|
);
|
|
|
|
|
|
/**
|
|
|
* 取得当前的客户端类型
|
|
|
*/
|
|
|
public static function clientType()
|
|
|
{
|
|
|
// 苹果设备
|
|
|
if (strstr($_SERVER['HTTP_USER_AGENT'], 'iPhone')) {
|
|
|
return 'iphone';
|
|
|
}
|
|
|
// 苹果IPAD
|
|
|
elseif (strstr($_SERVER['HTTP_USER_AGENT'], 'iPad')) {
|
|
|
return 'ipad';
|
|
|
}
|
|
|
elseif (stristr($_SERVER['HTTP_USER_AGENT'], 'android')) {
|
|
|
return 'android';
|
|
|
}
|
|
|
// 其它
|
|
|
else {
|
|
|
return 'web';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 取得当前的IP地址
|
|
|
*
|
|
|
* @param bool $int 返回int类型的ip地址,默认是
|
|
|
* @return mixed 当前的IP地址
|
|
|
*/
|
|
|
public static function ip($int = true)
|
|
|
{
|
|
|
if (isset($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP']) {
|
|
|
$onlineip = $_SERVER['HTTP_CLIENT_IP'];
|
|
|
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) {
|
|
|
$onlineip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
|
|
} else {
|
|
|
$onlineip = $_SERVER['REMOTE_ADDR'];
|
|
|
}
|
|
|
|
|
|
return $int ? ip2long($onlineip) : $onlineip;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 取得公共的参数
|
|
|
*
|
|
|
* @return array
|
|
|
*/
|
|
|
public static function param()
|
|
|
{
|
|
|
$clientType = self::clientType();
|
|
|
$param = array(
|
|
|
'app_version' => '3.8.2',
|
|
|
'client_type' => $clientType,
|
|
|
'os_version' => 'yohobuy:h5',
|
|
|
'private_key' => self::$privateKeyList[$clientType],
|
|
|
'screen_size' => '720x1280',
|
|
|
'v' => '7',
|
|
|
);
|
|
|
return $param;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 构建URL
|
|
|
*
|
|
|
* @param string $url
|
|
|
* @param array $data
|
|
|
* @return string
|
|
|
*/
|
|
|
public static function httpBuildQuery($url, $data)
|
|
|
{
|
|
|
// 销毁私钥参数
|
|
|
if (isset($data['private_key'])) {
|
|
|
unset($data['private_key']);
|
|
|
}
|
|
|
if (strstr($url, '?') !== false) {
|
|
|
$url .= '&' . http_build_query($data, null, '&');
|
|
|
} else {
|
|
|
$url .= '?' . http_build_query($data, null, '&');
|
|
|
}
|
|
|
return $url;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* get方式调用接口
|
|
|
*
|
|
|
* @param string $url 接口URL
|
|
|
* @param array $data 参数列表
|
|
|
* @parma mixed $cache 控制是否启用接口数据的缓存(时间单位为秒). 如3600表示缓存1小时, false表示不缓存
|
|
|
* @param bool $returnJson 控制是否返回json格式数据
|
|
|
* @param int $timeout 超时时间
|
|
|
* @return mixed
|
|
|
*/
|
|
|
public static function get($url, $data = array(), $cache = false, $returnJson = false, $timeout = 5)
|
|
|
{
|
|
|
// 销毁私钥参数
|
|
|
if (isset($data['private_key'])) {
|
|
|
unset($data['private_key']);
|
|
|
}
|
|
|
if (!empty($data)) {
|
|
|
$url = self::httpBuildQuery($url, $data);
|
|
|
}
|
|
|
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
// 先尝试获取一级缓存(master), 有数据则直接返回.
|
|
|
$result = Cache::get($url, 'master');
|
|
|
if (!empty($result)) {
|
|
|
return $result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$ch = curl_init($url);
|
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
$result = curl_exec($ch);
|
|
|
if (!$returnJson && !empty($result)) {
|
|
|
$result = json_decode($result, true);
|
|
|
}
|
|
|
|
|
|
curl_close($ch);
|
|
|
$data = array();
|
|
|
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
// 接口调用异常时, 不害怕,从我们的二级缓存(slave)里再取数据.
|
|
|
if (empty($result)) {
|
|
|
$result = Cache::get($url, 'slave');
|
|
|
}
|
|
|
// 接口调用成功时,这里会设置一级(master)和二级(slave)的缓存数据.
|
|
|
else {
|
|
|
Cache::set($url, $result, $cache);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* post提交数据
|
|
|
*
|
|
|
* @param string $url 接口URL
|
|
|
* @param array $data 参数列表
|
|
|
* @param bool $returnJson 控制是否返回json格式数据
|
|
|
* @param int $timeout 超时时间
|
|
|
* @param array $header
|
|
|
* @param array $cookie
|
|
|
* @return mixed
|
|
|
*/
|
|
|
public static function post($url, $data = array(), $returnJson = false, $timeout = 10, $header = array(), $cookie = array())
|
|
|
{
|
|
|
$ch = curl_init($url);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
|
|
if (!empty($header)) {
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
|
|
} else {
|
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|
|
}
|
|
|
|
|
|
if (!empty($cookie)) {
|
|
|
$cookie_str = array();
|
|
|
foreach ($cookie as $key => $val) {
|
|
|
$cookie_str[] = urlencode($key) . '=' . urlencode($val);
|
|
|
}
|
|
|
curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookie_str));
|
|
|
}
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
|
// 销毁私钥参数
|
|
|
if (isset($data['private_key'])) {
|
|
|
unset($data['private_key']);
|
|
|
}
|
|
|
if (!empty($data)) {
|
|
|
$str = http_build_query($data, null, '&');
|
|
|
// 新加支持application/x-www-form-urlencoded调用方式
|
|
|
//curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $str);
|
|
|
}
|
|
|
$result = curl_exec($ch);
|
|
|
if (!$returnJson && !empty($result)) {
|
|
|
$result = json_decode($result, true);
|
|
|
}
|
|
|
curl_close($ch);
|
|
|
$data = array();
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 批量调用接口
|
|
|
*
|
|
|
* @param array $urlList 接口列表
|
|
|
* @param array $options CURL设置项
|
|
|
* @parma mixed $cache 控制是否启用接口数据的缓存(时间单位为秒). 如3600表示缓存1小时, false表示不缓存
|
|
|
* @param int $timeout 超时时间,单位是秒
|
|
|
* @return array
|
|
|
*/
|
|
|
public static function getMulti($urlList = array(), $options = array(), $cache = false, $timeout = 5)
|
|
|
{
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
$key = md5(implode(',', array_values($urlList)));
|
|
|
// 先尝试获取一级缓存(master), 有数据则直接返回.
|
|
|
$result = Cache::get($key, 'master');
|
|
|
if (!empty($result)) {
|
|
|
return $result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$result = array();
|
|
|
$response = array();
|
|
|
$running = 0;
|
|
|
$data = '';
|
|
|
$error = '';
|
|
|
$defaultOptions = array(
|
|
|
CURLOPT_HEADER => 0,
|
|
|
CURLOPT_RETURNTRANSFER => 1,
|
|
|
CURLOPT_CONNECTTIMEOUT => $timeout,
|
|
|
CURLOPT_TIMEOUT => $timeout,
|
|
|
CURLOPT_NOSIGNAL => 1, //忽略所有的curl传递给php的信号,减少并发crash
|
|
|
);
|
|
|
$mh = curl_multi_init();
|
|
|
$ch = array();
|
|
|
|
|
|
// 应用CURL配置
|
|
|
if (empty($options)) {
|
|
|
$options = $defaultOptions;
|
|
|
} else {
|
|
|
$options = array_merge($defaultOptions, $options);
|
|
|
}
|
|
|
|
|
|
// 添加子链接句柄
|
|
|
foreach ($urlList as $name => $api) {
|
|
|
$ch[$name] = curl_init($api);
|
|
|
curl_setopt_array($ch[$name], $options);
|
|
|
curl_multi_add_handle($mh, $ch[$name]);
|
|
|
$result[$name] = array();
|
|
|
}
|
|
|
|
|
|
// 调用API接口
|
|
|
do {
|
|
|
do {
|
|
|
$status = curl_multi_exec($mh, $running);
|
|
|
} while ($status == CURLM_CALL_MULTI_PERFORM);
|
|
|
|
|
|
if ($status != CURLM_OK) {
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if ($running > 0) {
|
|
|
curl_multi_select($mh, 0.5);
|
|
|
}
|
|
|
} while ($running);
|
|
|
|
|
|
// 获取API接口响应的结果
|
|
|
foreach ($urlList as $name => $api) {
|
|
|
$error = curl_error($ch[$name]);
|
|
|
if ($error != '') {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
$data = curl_multi_getcontent($ch[$name]);
|
|
|
if (!$data) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
$response = json_decode($data, true);
|
|
|
if (empty($response['data'])) {
|
|
|
continue;
|
|
|
}
|
|
|
$result[$name] = $response['data'];
|
|
|
|
|
|
curl_multi_remove_handle($mh, $ch[$name]);
|
|
|
curl_close($ch[$name]);
|
|
|
}
|
|
|
curl_multi_close($mh);
|
|
|
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
// 接口调用异常时, 不害怕,从我们的二级缓存(slave)里再取数据.
|
|
|
if (empty($result[$name])) {
|
|
|
$result = Cache::get($key, 'slave');
|
|
|
}
|
|
|
// 接口调用成功时,这里会设置一级(master)和二级(slave)的缓存数据.
|
|
|
else {
|
|
|
Cache::set($key, $result, $cache);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* rpc调用远程服务(YAR)
|
|
|
*
|
|
|
* @see http://php.net/manual/zh/yar-client.setopt.php
|
|
|
* @param string $uri
|
|
|
* @param string $method
|
|
|
* @param array $parameters
|
|
|
* @param mixed $cache 控制是否启用接口数据的缓存(时间单位为秒). 如3600表示缓存1小时, false表示不缓存
|
|
|
* @param int $timeout
|
|
|
* @return array
|
|
|
*/
|
|
|
public static function yarClient($uri, $method, $parameters = array(), $cache = false, $timeout = 3000)
|
|
|
{
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
$key = self::httpBuildQuery($uri . $method, $parameters);
|
|
|
// 先尝试获取一级缓存(master), 有数据则直接返回.
|
|
|
$result = Cache::get($key, 'master');
|
|
|
if (!empty($result)) {
|
|
|
return $result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$client = new \Yar_Client($uri);
|
|
|
$client->SetOpt(YAR_OPT_PACKAGER, 'php');
|
|
|
$client->SetOpt(YAR_OPT_TIMEOUT, $timeout);
|
|
|
$client->SetOpt(YAR_OPT_CONNECT_TIMEOUT, $timeout);
|
|
|
|
|
|
try {
|
|
|
$result = call_user_func_array(array($client, $method), $parameters);
|
|
|
} catch (\Exception $e) {
|
|
|
$result = array();
|
|
|
}
|
|
|
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
// 接口调用异常时, 不害怕,从我们的二级缓存(slave)里再取数据.
|
|
|
if (empty($result)) {
|
|
|
$result = Cache::get($key, 'slave');
|
|
|
}
|
|
|
// 接口调用成功时,这里会设置一级(master)和二级(slave)的缓存数据.
|
|
|
else {
|
|
|
Cache::set($key, $result, $cache);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 并行(异步)调用远程服务
|
|
|
*
|
|
|
* @see http://php.net/manual/zh/class.yar-concurrent-client.php
|
|
|
* @param string $uri
|
|
|
* @param string $method
|
|
|
* @param array $parameter
|
|
|
* @param callable $callback
|
|
|
* @param int $timeout
|
|
|
* @return void
|
|
|
*/
|
|
|
public static function yarConcurrentCall($uri, $method, $parameters, $callback, $timeout = 3000)
|
|
|
{
|
|
|
\Yar_Concurrent_Client::call($uri, $method, $parameters, $callback, null, array(
|
|
|
YAR_OPT_PACKAGER => 'php',
|
|
|
YAR_OPT_TIMEOUT => $timeout,
|
|
|
YAR_OPT_CONNECT_TIMEOUT => $timeout
|
|
|
));
|
|
|
}
|
|
|
|
|
|
public static function yarConcurrentLoop($callback = null)
|
|
|
{
|
|
|
\Yar_Concurrent_Client::loop($callback);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 提交json格式数据请求java有关接口
|
|
|
*
|
|
|
* @param string $url 接口URL
|
|
|
* @param array $data 参数列表
|
|
|
* @param bool $returnJson 控制是否返回json格式数据
|
|
|
* @param int $timeout 超时时间
|
|
|
* @param array $cookie
|
|
|
* @return mixed
|
|
|
*/
|
|
|
public static function jsonPost($url, $data = array(), $returnJson = false, $timeout = 10, $cookie = array())
|
|
|
{
|
|
|
$ch = curl_init($url);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
|
|
|
|
|
|
if (!empty($cookie)) {
|
|
|
$cookie_str = array();
|
|
|
foreach ($cookie as $key => $val) {
|
|
|
$cookie_str[] = urlencode($key) . '=' . urlencode($val);
|
|
|
}
|
|
|
curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookie_str));
|
|
|
}
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
|
if (!empty($data)) {
|
|
|
$data_string = json_encode($data);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
|
|
|
// 设置json的Header
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
|
|
'Content-Type: application/json',
|
|
|
'Content-Length: ' . strlen($data_string)
|
|
|
));
|
|
|
}
|
|
|
$result = curl_exec($ch);
|
|
|
if (!$returnJson && !empty($result)) {
|
|
|
$result = json_decode($result, true);
|
|
|
}
|
|
|
curl_close($ch);
|
|
|
$data = array();
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
} |
|
|
<?php
|
|
|
|
|
|
/**
|
|
|
* 有货相关接口类
|
|
|
*
|
|
|
* @name Yohobuy
|
|
|
* @package library/Api
|
|
|
* @copyright yoho.inc
|
|
|
* @version 1.0 (2015-9-30 16:42:51)
|
|
|
* @author fei.hong <fei.hong@yoho.cn>
|
|
|
*/
|
|
|
|
|
|
namespace Api;
|
|
|
|
|
|
use Plugin\Cache;
|
|
|
|
|
|
class Yohobuy
|
|
|
{
|
|
|
/* 正式环境 */
|
|
|
|
|
|
// const API_URL = 'http://api2.open.yohobuy.com/';
|
|
|
// const API_URL2 = 'http://api.open.yohobuy.com/';
|
|
|
// const SERVICE_URL = 'http://service.api.yohobuy.com/';
|
|
|
// const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
|
|
|
// const API_URL = 'http://apih5.yoho.cn/';
|
|
|
// const API_URL2 = 'http://apih5.yoho.cn/';
|
|
|
// const SERVICE_URL = 'http://serviceh5.yoho.cn/';
|
|
|
// const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
// const API_OLD = 'http://api2.open.yohobuy.com/';
|
|
|
|
|
|
// /* 测试环境 */
|
|
|
// const API_URL = 'http://testapi.yoho.cn:28078/';
|
|
|
// const SERVICE_URL = 'http://testservice.yoho.cn:28077/';
|
|
|
// const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
// const API_OLD = 'http://test2.open.yohobuy.com/';
|
|
|
|
|
|
/* 预览环境 */
|
|
|
const API_URL = 'http://preapi.yoho.cn/';
|
|
|
const API_URL2 = 'http://preapi.yoho.cn/';
|
|
|
const SERVICE_URL = 'http://serviceh5.yoho.cn/';
|
|
|
const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
const API_OLD = 'http://api2.open.yohobuy.com/';
|
|
|
|
|
|
/*PC重构地址*/
|
|
|
// const API_URL = 'http://test2.open.yohobuy.com/';
|
|
|
// const SERVICE_URL = 'http://test.service.api.yohobuy.com/';
|
|
|
// const YOHOBUY_URL = 'http://www.yohobuy.com/';
|
|
|
|
|
|
/**
|
|
|
* 私钥列表
|
|
|
*
|
|
|
* @var array
|
|
|
*/
|
|
|
public static $privateKeyList = array(
|
|
|
'android' => 'fd4ad5fcfa0de589ef238c0e7331b585',
|
|
|
'iphone' => 'a85bb0674e08986c6b115d5e3a4884fa',
|
|
|
'ipad' => 'ad9fcda2e679cf9229e37feae2cdcf80',
|
|
|
'web' => '0ed29744ed318fd28d2c07985d3ba633',
|
|
|
);
|
|
|
|
|
|
/**
|
|
|
* 取得当前的客户端类型
|
|
|
*/
|
|
|
public static function clientType()
|
|
|
{
|
|
|
// 苹果设备
|
|
|
if (strstr($_SERVER['HTTP_USER_AGENT'], 'iPhone')) {
|
|
|
return 'iphone';
|
|
|
}
|
|
|
// 苹果IPAD
|
|
|
elseif (strstr($_SERVER['HTTP_USER_AGENT'], 'iPad')) {
|
|
|
return 'ipad';
|
|
|
}
|
|
|
elseif (stristr($_SERVER['HTTP_USER_AGENT'], 'android')) {
|
|
|
return 'android';
|
|
|
}
|
|
|
// 其它
|
|
|
else {
|
|
|
return 'web';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 取得当前的IP地址
|
|
|
*
|
|
|
* @param bool $int 返回int类型的ip地址,默认是
|
|
|
* @return mixed 当前的IP地址
|
|
|
*/
|
|
|
public static function ip($int = true)
|
|
|
{
|
|
|
if (isset($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP']) {
|
|
|
$onlineip = $_SERVER['HTTP_CLIENT_IP'];
|
|
|
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) {
|
|
|
$onlineip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
|
|
} else {
|
|
|
$onlineip = $_SERVER['REMOTE_ADDR'];
|
|
|
}
|
|
|
|
|
|
return $int ? ip2long($onlineip) : $onlineip;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 取得公共的参数
|
|
|
*
|
|
|
* @return array
|
|
|
*/
|
|
|
public static function param()
|
|
|
{
|
|
|
$clientType = self::clientType();
|
|
|
$param = array(
|
|
|
'app_version' => '3.8.2',
|
|
|
'client_type' => $clientType,
|
|
|
'os_version' => 'yohobuy:h5',
|
|
|
'private_key' => self::$privateKeyList[$clientType],
|
|
|
'screen_size' => '720x1280',
|
|
|
'v' => '7',
|
|
|
);
|
|
|
return $param;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 构建URL
|
|
|
*
|
|
|
* @param string $url
|
|
|
* @param array $data
|
|
|
* @return string
|
|
|
*/
|
|
|
public static function httpBuildQuery($url, $data)
|
|
|
{
|
|
|
// 销毁私钥参数
|
|
|
if (isset($data['private_key'])) {
|
|
|
unset($data['private_key']);
|
|
|
}
|
|
|
if (strstr($url, '?') !== false) {
|
|
|
$url .= '&' . http_build_query($data, null, '&');
|
|
|
} else {
|
|
|
$url .= '?' . http_build_query($data, null, '&');
|
|
|
}
|
|
|
return $url;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* get方式调用接口
|
|
|
*
|
|
|
* @param string $url 接口URL
|
|
|
* @param array $data 参数列表
|
|
|
* @parma mixed $cache 控制是否启用接口数据的缓存(时间单位为秒). 如3600表示缓存1小时, false表示不缓存
|
|
|
* @param bool $returnJson 控制是否返回json格式数据
|
|
|
* @param int $timeout 超时时间
|
|
|
* @return mixed
|
|
|
*/
|
|
|
public static function get($url, $data = array(), $cache = false, $returnJson = false, $timeout = 5)
|
|
|
{
|
|
|
// 销毁私钥参数
|
|
|
if (isset($data['private_key'])) {
|
|
|
unset($data['private_key']);
|
|
|
}
|
|
|
if (!empty($data)) {
|
|
|
$url = self::httpBuildQuery($url, $data);
|
|
|
}
|
|
|
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
// 先尝试获取一级缓存(master), 有数据则直接返回.
|
|
|
$result = Cache::get($url, 'master');
|
|
|
if (!empty($result)) {
|
|
|
return $result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$ch = curl_init($url);
|
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
$result = curl_exec($ch);
|
|
|
if (!$returnJson && !empty($result)) {
|
|
|
$result = json_decode($result, true);
|
|
|
}
|
|
|
|
|
|
curl_close($ch);
|
|
|
$data = array();
|
|
|
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
// 接口调用异常时, 不害怕,从我们的二级缓存(slave)里再取数据.
|
|
|
if (empty($result)) {
|
|
|
$result = Cache::get($url, 'slave');
|
|
|
}
|
|
|
// 接口调用成功时,这里会设置一级(master)和二级(slave)的缓存数据.
|
|
|
else {
|
|
|
Cache::set($url, $result, $cache);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* post提交数据
|
|
|
*
|
|
|
* @param string $url 接口URL
|
|
|
* @param array $data 参数列表
|
|
|
* @param bool $returnJson 控制是否返回json格式数据
|
|
|
* @param int $timeout 超时时间
|
|
|
* @param array $header
|
|
|
* @param array $cookie
|
|
|
* @return mixed
|
|
|
*/
|
|
|
public static function post($url, $data = array(), $returnJson = false, $timeout = 10, $header = array(), $cookie = array())
|
|
|
{
|
|
|
$ch = curl_init($url);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
|
|
if (!empty($header)) {
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
|
|
} else {
|
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|
|
}
|
|
|
|
|
|
if (!empty($cookie)) {
|
|
|
$cookie_str = array();
|
|
|
foreach ($cookie as $key => $val) {
|
|
|
$cookie_str[] = urlencode($key) . '=' . urlencode($val);
|
|
|
}
|
|
|
curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookie_str));
|
|
|
}
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
|
// 销毁私钥参数
|
|
|
if (isset($data['private_key'])) {
|
|
|
unset($data['private_key']);
|
|
|
}
|
|
|
if (!empty($data)) {
|
|
|
$str = http_build_query($data, null, '&');
|
|
|
// 新加支持application/x-www-form-urlencoded调用方式
|
|
|
//curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $str);
|
|
|
}
|
|
|
$result = curl_exec($ch);
|
|
|
if (!$returnJson && !empty($result)) {
|
|
|
$result = json_decode($result, true);
|
|
|
}
|
|
|
curl_close($ch);
|
|
|
$data = array();
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 批量调用接口
|
|
|
*
|
|
|
* @param array $urlList 接口列表
|
|
|
* @param array $options CURL设置项
|
|
|
* @parma mixed $cache 控制是否启用接口数据的缓存(时间单位为秒). 如3600表示缓存1小时, false表示不缓存
|
|
|
* @param int $timeout 超时时间,单位是秒
|
|
|
* @return array
|
|
|
*/
|
|
|
public static function getMulti($urlList = array(), $options = array(), $cache = false, $timeout = 5)
|
|
|
{
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
$key = md5(implode(',', array_values($urlList)));
|
|
|
// 先尝试获取一级缓存(master), 有数据则直接返回.
|
|
|
$result = Cache::get($key, 'master');
|
|
|
if (!empty($result)) {
|
|
|
return $result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$result = array();
|
|
|
$response = array();
|
|
|
$running = 0;
|
|
|
$data = '';
|
|
|
$error = '';
|
|
|
$defaultOptions = array(
|
|
|
CURLOPT_HEADER => 0,
|
|
|
CURLOPT_RETURNTRANSFER => 1,
|
|
|
CURLOPT_CONNECTTIMEOUT => $timeout,
|
|
|
CURLOPT_TIMEOUT => $timeout,
|
|
|
CURLOPT_NOSIGNAL => 1, //忽略所有的curl传递给php的信号,减少并发crash
|
|
|
);
|
|
|
$mh = curl_multi_init();
|
|
|
$ch = array();
|
|
|
|
|
|
// 应用CURL配置
|
|
|
if (empty($options)) {
|
|
|
$options = $defaultOptions;
|
|
|
} else {
|
|
|
$options = array_merge($defaultOptions, $options);
|
|
|
}
|
|
|
|
|
|
// 添加子链接句柄
|
|
|
foreach ($urlList as $name => $api) {
|
|
|
$ch[$name] = curl_init($api);
|
|
|
curl_setopt_array($ch[$name], $options);
|
|
|
curl_multi_add_handle($mh, $ch[$name]);
|
|
|
$result[$name] = array();
|
|
|
}
|
|
|
|
|
|
// 调用API接口
|
|
|
do {
|
|
|
do {
|
|
|
$status = curl_multi_exec($mh, $running);
|
|
|
} while ($status == CURLM_CALL_MULTI_PERFORM);
|
|
|
|
|
|
if ($status != CURLM_OK) {
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if ($running > 0) {
|
|
|
curl_multi_select($mh, 0.5);
|
|
|
}
|
|
|
} while ($running);
|
|
|
|
|
|
// 获取API接口响应的结果
|
|
|
foreach ($urlList as $name => $api) {
|
|
|
$error = curl_error($ch[$name]);
|
|
|
if ($error != '') {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
$data = curl_multi_getcontent($ch[$name]);
|
|
|
if (!$data) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
$response = json_decode($data, true);
|
|
|
if (empty($response['data'])) {
|
|
|
continue;
|
|
|
}
|
|
|
$result[$name] = $response['data'];
|
|
|
|
|
|
curl_multi_remove_handle($mh, $ch[$name]);
|
|
|
curl_close($ch[$name]);
|
|
|
}
|
|
|
curl_multi_close($mh);
|
|
|
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
// 接口调用异常时, 不害怕,从我们的二级缓存(slave)里再取数据.
|
|
|
if (empty($result[$name])) {
|
|
|
$result = Cache::get($key, 'slave');
|
|
|
}
|
|
|
// 接口调用成功时,这里会设置一级(master)和二级(slave)的缓存数据.
|
|
|
else {
|
|
|
Cache::set($key, $result, $cache);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* rpc调用远程服务(YAR)
|
|
|
*
|
|
|
* @see http://php.net/manual/zh/yar-client.setopt.php
|
|
|
* @param string $uri
|
|
|
* @param string $method
|
|
|
* @param array $parameters
|
|
|
* @param mixed $cache 控制是否启用接口数据的缓存(时间单位为秒). 如3600表示缓存1小时, false表示不缓存
|
|
|
* @param int $timeout
|
|
|
* @return array
|
|
|
*/
|
|
|
public static function yarClient($uri, $method, $parameters = array(), $cache = false, $timeout = 3000)
|
|
|
{
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
$key = self::httpBuildQuery($uri . $method, $parameters);
|
|
|
// 先尝试获取一级缓存(master), 有数据则直接返回.
|
|
|
$result = Cache::get($key, 'master');
|
|
|
if (!empty($result)) {
|
|
|
return $result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$client = new \Yar_Client($uri);
|
|
|
$client->SetOpt(YAR_OPT_PACKAGER, 'php');
|
|
|
$client->SetOpt(YAR_OPT_TIMEOUT, $timeout);
|
|
|
$client->SetOpt(YAR_OPT_CONNECT_TIMEOUT, $timeout);
|
|
|
|
|
|
try {
|
|
|
$result = call_user_func_array(array($client, $method), $parameters);
|
|
|
} catch (\Exception $e) {
|
|
|
$result = array();
|
|
|
}
|
|
|
|
|
|
/* 开启缓存的情况 */
|
|
|
if ($cache && USE_CACHE) {
|
|
|
// 接口调用异常时, 不害怕,从我们的二级缓存(slave)里再取数据.
|
|
|
if (empty($result)) {
|
|
|
$result = Cache::get($key, 'slave');
|
|
|
}
|
|
|
// 接口调用成功时,这里会设置一级(master)和二级(slave)的缓存数据.
|
|
|
else {
|
|
|
Cache::set($key, $result, $cache);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 并行(异步)调用远程服务
|
|
|
*
|
|
|
* @see http://php.net/manual/zh/class.yar-concurrent-client.php
|
|
|
* @param string $uri
|
|
|
* @param string $method
|
|
|
* @param array $parameter
|
|
|
* @param callable $callback
|
|
|
* @param int $timeout
|
|
|
* @return void
|
|
|
*/
|
|
|
public static function yarConcurrentCall($uri, $method, $parameters, $callback, $timeout = 3000)
|
|
|
{
|
|
|
\Yar_Concurrent_Client::call($uri, $method, $parameters, $callback, null, array(
|
|
|
YAR_OPT_PACKAGER => 'php',
|
|
|
YAR_OPT_TIMEOUT => $timeout,
|
|
|
YAR_OPT_CONNECT_TIMEOUT => $timeout
|
|
|
));
|
|
|
}
|
|
|
|
|
|
public static function yarConcurrentLoop($callback = null)
|
|
|
{
|
|
|
\Yar_Concurrent_Client::loop($callback);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 提交json格式数据请求java有关接口
|
|
|
*
|
|
|
* @param string $url 接口URL
|
|
|
* @param array $data 参数列表
|
|
|
* @param bool $returnJson 控制是否返回json格式数据
|
|
|
* @param int $timeout 超时时间
|
|
|
* @param array $cookie
|
|
|
* @return mixed
|
|
|
*/
|
|
|
public static function jsonPost($url, $data = array(), $returnJson = false, $timeout = 10, $cookie = array())
|
|
|
{
|
|
|
$ch = curl_init($url);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
|
|
|
|
|
|
if (!empty($cookie)) {
|
|
|
$cookie_str = array();
|
|
|
foreach ($cookie as $key => $val) {
|
|
|
$cookie_str[] = urlencode($key) . '=' . urlencode($val);
|
|
|
}
|
|
|
curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookie_str));
|
|
|
}
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
|
if (!empty($data)) {
|
|
|
$data_string = json_encode($data);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
|
|
|
// 设置json的Header
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
|
|
'Content-Type: application/json',
|
|
|
'Content-Length: ' . strlen($data_string)
|
|
|
));
|
|
|
}
|
|
|
$result = curl_exec($ch);
|
|
|
if (!$returnJson && !empty($result)) {
|
|
|
$result = json_decode($result, true);
|
|
|
}
|
|
|
curl_close($ch);
|
|
|
$data = array();
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
} |
...
|
...
|
|