1
0
mirror of synced 2024-12-01 09:46:06 +03:00
bitrix-module/intaro.intarocrm/classes/general/RestApi.php
2015-03-03 16:37:34 +03:00

690 lines
21 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace RetailCrm;
use RetailCrm\Response\ApiResponse;
use RetailCrm\Exception\CurlException;
/**
* retailCRM API client class
*/
class RestApi
{
const VERSION = 'v3';
const METHOD_GET = 'GET';
const METHOD_POST = 'POST';
protected $client;
protected $url;
protected $defaultParameters;
protected $generatedAt;
/**
* Site code
*/
protected $siteCode;
/**
* Client creating
*
* @param string $url - url сайта
* @param string $apiKey - ключ API
* @param string $site - символьный код сайта
* @return mixed
*/
public function __construct($url, $apiKey, $site = null)
{
if ('/' != substr($url, strlen($url) - 1, 1)) {
$url .= '/';
}
$url = $url . 'api/' . self::VERSION;
if (false === stripos($url, 'https://')) {
throw new \InvalidArgumentException('API schema requires HTTPS protocol');
}
$this->url = $url;
$this->defaultParameters = array('apiKey' => $apiKey);
$this->siteCode = $site;
}
/* Методы для работы с заказами */
/**
* Получение заказа по id
*
* @param string $id - идентификатор заказа
* @param string $by - поиск заказа по id или externalId
* @param string $site - символьный код сайта
* @return ApiResponse - информация о заказе
*/
public function ordersGet($id, $by = 'externalId', $site = null)
{
$this->checkIdParameter($by);
return $this->makeRequest("/orders/$id", self::METHOD_GET, $this->fillSite($site, array(
'by' => $by
)));
}
/**
* Создание заказа
*
* @param array $order - информация о заказе
* @param string $site - символьный код сайта
* @return ApiResponse
*/
public function ordersCreate($order, $site = null)
{
if (!sizeof($order)) {
throw new \InvalidArgumentException('Parameter `order` must contains a data');
}
return $this->makeRequest("/orders/create", self::METHOD_POST, $this->fillSite($site, array(
'order' => json_encode($order)
)));
}
/**
* Изменение заказа
*
* @param array $order - информация о заказе
* @param string $by - изменение заказа по id или externalId
* @param string $site - символьный код сайта
* @return ApiResponse
*/
public function orderEdit($order, $by = 'externalId', $site = null)
{
if (!sizeof($order)) {
throw new \InvalidArgumentException('Parameter `order` must contains a data');
}
$this->checkIdParameter($by);
if (!isset($order[$by])) {
throw new \InvalidArgumentException(sprintf('Order array must contain the "%s" parameter.', $by));
}
return $this->makeRequest(
"/orders/" . $order[$by] . "/edit",
self::METHOD_POST,
$this->fillSite($site, array(
'order' => json_encode($order),
'by' => $by,
))
);
}
/**
* Пакетная загрузка заказов
*
* @param array $orders - массив заказов
* @param string $site - символьный код сайта
* @return ApiResponse
*/
public function orderUpload($orders, $site = null)
{
if (!sizeof($orders)) {
throw new \InvalidArgumentException('Parameter `orders` must contains array of the orders');
}
return $this->makeRequest("/orders/upload", self::METHOD_POST, $this->fillSite($site, array(
'orders' => json_encode($orders),
)));
}
/**
* Обновление externalId у заказов с переданными id
*
* @param array $order - массив, содержащий id и externalId заказа
* @return ApiResponse
*/
public function orderFixExternalIds($order)
{
if (!sizeof($order)) {
throw new \InvalidArgumentException('Method parameter must contains at least one IDs pair');
}
return $this->makeRequest("/orders/fix-external-ids", self::METHOD_POST, array(
'orders' => json_encode($order),
));
}
/**
* Получение последних измененных заказов
*
* @param \DateTime|string|int $startDate - начальная дата и время выборки (Y-m-d H:i:s)
* @param \DateTime|string|int $endDate - конечная дата и время выборки (Y-m-d H:i:s)
* @param int $limit - ограничение на размер выборки
* @param int $offset - сдвиг
* @param bool $skipMyChanges
* @return ApiResponse
*/
public function orderHistory(
$startDate = null,
$endDate = null,
$limit = 100,
$offset = 0,
$skipMyChanges = true
) {
$parameters = array();
if ($startDate) {
$parameters['startDate'] = $this->ensureDateTime($startDate);
}
if ($endDate) {
$parameters['endDate'] = $this->ensureDateTime($endDate);
}
if ($limit) {
$parameters['limit'] = (int) $limit;
}
if ($offset) {
$parameters['offset'] = (int) $offset;
}
if ($skipMyChanges) {
$parameters['skipMyChanges'] = (bool) $skipMyChanges;
}
return $this->makeRequest('/orders/history', self::METHOD_GET, $parameters);
}
/* Методы для работы с клиентами */
/**
* Получение клиента по id
*
* @param string $id - идентификатор
* @param string $by - поиск заказа по id или externalId
* @param string $site - символьный код сайта
* @return array - информация о клиенте
*/
public function customerGet($id, $by = 'externalId', $site = null)
{
$this->checkIdParameter($by);
return $this->makeRequest("/customers/$id", self::METHOD_GET, $this->fillSite($site, array(
'by' => $by
)));
}
/**
* Получение списка клиентов в соответсвии с запросом
*
* @param array $filter - фильтры
* @param int $page - страница
* @param int $limit - ограничение на размер выборки
* @return ApiResponse
*/
public function customersList(array $filter = array(), $page = null, $limit = null)
{
$parameters = array();
if (sizeof($filter)) {
$parameters['filter'] = $filter;
}
if (null !== $page) {
$parameters['page'] = (int) $page;
}
if (null !== $limit) {
$parameters['limit'] = (int) $limit;
}
return $this->makeRequest('/customers', self::METHOD_GET, $parameters);
}
/**
* Создание клиента
*
* @param array $customer - информация о клиенте
* @param string $site - символьный код сайта
* @return ApiResponse
*/
public function customersCreate(array $customer, $site = null)
{
if (!sizeof($customer)) {
throw new \InvalidArgumentException('Parameter `customer` must contains a data');
}
return $this->makeRequest("/customers/create", self::METHOD_POST, $this->fillSite($site, array(
'customer' => json_encode($customer)
)));
}
/**
* Редактирование клиента
*
* @param array $customer - информация о клиенте
* @param string $by - изменение клиента по id или externalId
* @param string $site - символьный код сайта
* @return ApiResponse
*/
public function customerEdit($customer, $by = 'externalId', $site = null)
{
if (!sizeof($customer)) {
throw new \InvalidArgumentException('Parameter `customer` must contains a data');
}
$this->checkIdParameter($by);
if (!isset($customer[$by])) {
throw new \InvalidArgumentException(sprintf('Customer array must contain the "%s" parameter.', $by));
}
return $this->makeRequest(
"/customers/" . $customer[$by] . "/edit",
self::METHOD_POST,
$this->fillSite($site, array(
'customer' => json_encode($customer),
'by' => $by,
)
));
}
/**
* Пакетная загрузка клиентов
*
* @param array $customers - массив клиентов
* @param string $site - символьный код сайта
* @return ApiResponse
*/
public function customerUpload($customers, $site = null)
{
if (!sizeof($customers)) {
throw new \InvalidArgumentException('Parameter `customers` must contains array of the customers');
}
return $this->makeRequest("/customers/upload", self::METHOD_POST, $this->fillSite($site, array(
'customers' => json_encode($customers),
)));
}
/**
* Обновление externalId у клиентов с переданными id
*
* @param array $customers - массив, содержащий id и externalId заказа
* @return array
*/
public function customerFixExternalIds($customers)
{
if (!sizeof($customers)) {
throw new \InvalidArgumentException('Method parameter must contains at least one IDs pair');
}
return $this->makeRequest("/customers/fix-external-ids", self::METHOD_POST, array(
'customers' => json_encode($customers),
));
}
/* Методы для работы со справочниками */
/**
* Получение списка типов доставки
*
* @return ApiResponse
*/
public function deliveryTypesList()
{
return $this->makeRequest('/reference/delivery-types', self::METHOD_GET);
}
/**
* Редактирование типа доставки
*
* @param array $delivery - информация о типе доставки
* @return ApiResponse
*/
public function deliveryTypeEdit($delivery)
{
if (!isset($delivery['code'])) {
throw new \InvalidArgumentException('Data must contain "code" parameter.');
}
return $this->makeRequest(
'/reference/delivery-types/' . $delivery['code'] . '/edit',
self::METHOD_POST,
array(
'deliveryType' => json_encode($delivery)
)
);
}
/**
* Получение списка служб доставки
*
* @return ApiResponse
*/
public function deliveryServicesList()
{
return $this->makeRequest('/reference/delivery-services', self::METHOD_GET);
}
/**
* Редактирование службы доставки
*
* @param array $delivery - информация о типе доставки
* @return ApiResponse
*/
public function deliveryServiceEdit($delivery)
{
if (!isset($delivery['code'])) {
throw new \InvalidArgumentException('Data must contain "code" parameter.');
}
return $this->makeRequest(
'/reference/delivery-services/' . $delivery['code'] . '/edit',
self::METHOD_POST,
array(
'deliveryService' => json_encode($delivery)
)
);
}
/**
* Получение списка типов оплаты
*
* @return ApiResponse
*/
public function paymentTypesList()
{
return $this->makeRequest('/reference/payment-types', self::METHOD_GET);
}
/**
* Редактирование типа оплаты
*
* @param array $paymentType - информация о типе оплаты
* @return ApiResponse
*/
public function paymentTypesEdit($paymentType)
{
if (!isset($paymentType['code'])) {
throw new \InvalidArgumentException('Data must contain "code" parameter.');
}
return $this->makeRequest(
'/reference/payment-types/' . $paymentType['code'] . '/edit',
self::METHOD_POST,
array(
'paymentType' => json_encode($paymentType)
)
);
}
/**
* Получение списка статусов оплаты
*
* @return ApiResponse
*/
public function paymentStatusesList()
{
return $this->makeRequest('/reference/payment-statuses', self::METHOD_GET);
}
/**
* Редактирование статуса оплаты
*
* @param array $paymentStatus - информация о статусе оплаты
* @return ApiResponse
*/
public function paymentStatusesEdit($paymentStatus)
{
if (!isset($paymentStatus['code'])) {
throw new \InvalidArgumentException('Data must contain "code" parameter.');
}
return $this->makeRequest(
'/reference/payment-statuses/' . $paymentStatus['code'] . '/edit',
self::METHOD_POST,
array(
'paymentStatus' => json_encode($paymentStatus)
)
);
}
/**
* Получение списка типов заказа
*
* @return ApiResponse
*/
public function orderTypesList()
{
return $this->makeRequest('/reference/order-types', self::METHOD_GET);
}
/**
* Редактирование типа заказа
*
* @param array $orderType - информация о типе заказа
* @return ApiResponse
*/
public function orderTypesEdit($orderType)
{
if (!isset($orderType['code'])) {
throw new \InvalidArgumentException('Data must contain "code" parameter.');
}
return $this->makeRequest(
'/reference/order-types/' . $orderType['code'] . '/edit',
self::METHOD_POST,
array(
'orderType' => json_encode($orderType)
)
);
}
/**
* Получение списка способов оформления заказа
*
* @return ApiResponse
*/
public function orderMethodsList()
{
return $this->makeRequest('/reference/order-methods', self::METHOD_GET);
}
/**
* Редактирование способа оформления заказа
*
* @param array $orderMethod - информация о способе оформления заказа
* @return ApiResponse
*/
public function orderMethodsEdit($orderMethod)
{
if (!isset($orderMethod['code'])) {
throw new \InvalidArgumentException('Data must contain "code" parameter.');
}
return $this->makeRequest(
'/reference/order-methods/' . $orderMethod['code'] . '/edit',
self::METHOD_POST,
array(
'orderMethod' => json_encode($orderMethod)
)
);
}
/**
* Получение списка статусов заказа
*
* @return ApiResponse
*/
public function orderStatusesList()
{
return $this->makeRequest('/reference/statuses', self::METHOD_GET);
}
/**
* Получение списка сайтов
*
* @return ApiResponse
*/
public function sitesList()
{
return $this->makeRequest('/reference/sites', self::METHOD_GET);
}
/**
* Редактирование статуса заказа
*
* @param array $status - информация о статусе заказа
* @return ApiResponse
*/
public function orderStatusEdit($status)
{
if (!isset($status['code'])) {
throw new \InvalidArgumentException('Data must contain "code" parameter.');
}
return $this->makeRequest(
'/reference/statuses/' . $status['code'] . '/edit',
self::METHOD_POST,
array(
'status' => json_encode($status)
)
);
}
/**
* Получение списка групп статусов заказа
*
* @return ApiResponse
*/
public function orderStatusGroupsList()
{
return $this->makeRequest('/reference/status-groups', self::METHOD_GET);
}
/**
* Обновление статистики
*
* @return ApiResponse
*/
public function statisticUpdate()
{
return $this->makeRequest('/statistic/update', self::METHOD_GET);
}
/**
* @return \DateTime
*/
public function getGeneratedAt()
{
return $this->generatedAt;
}
protected function ensureDateTime($value)
{
if ($value instanceof \DateTime) {
return $value->format('Y-m-d H:i:s');
} elseif (is_int($value)) {
return date('Y-m-d H:i:s', $value);
}
return $value;
}
/**
* Check ID parameter
*
* @param string $by
* @return bool
*/
protected function checkIdParameter($by)
{
$allowedForBy = array('externalId', 'id');
if (!in_array($by, $allowedForBy)) {
throw new \InvalidArgumentException(sprintf(
'Value "%s" for parameter "by" is not valid. Allowed values are %s.',
$by,
implode(', ', $allowedForBy)
));
}
return true;
}
/**
* Fill params by site value
*
* @param string $site
* @param array $params
* @return array
*/
protected function fillSite($site, array $params)
{
if ($site) {
$params['site'] = $site;
} elseif ($this->siteCode) {
$params['site'] = $this->siteCode;
}
return $params;
}
/**
* Make HTTP request
*
* @param string $path
* @param string $method (default: 'GET')
* @param array $parameters (default: array())
* @param int $timeout
* @return ApiResponse
*/
public function makeRequest($path, $method, $parameters = array(), $timeout = 30)
{
$allowedMethods = array(self::METHOD_GET, self::METHOD_POST);
if (!in_array($method, $allowedMethods)) {
throw new \InvalidArgumentException(sprintf(
'Method "%s" is not valid. Allowed methods are %s',
$method,
implode(', ', $allowedMethods)
));
}
$parameters = array_merge($this->defaultParameters, $parameters);
$path = $this->url . $path;
if (self::METHOD_GET === $method && sizeof($parameters)) {
$path .= '?' . http_build_query($parameters);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $path);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return into a variable
curl_setopt($ch, CURLOPT_TIMEOUT, (int) $timeout); // times out after 30s
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // allow redirects
if (self::METHOD_POST === $method) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
}
$responseBody = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$errno = curl_errno($ch);
$error = curl_error($ch);
curl_close($ch);
if ($errno) {
throw new CurlException($error, $errno);
}
$result = json_decode($responseBody, true);
if (isset($result['generatedAt'])) {
$this->generatedAt = new \DateTime($result['generatedAt']);
unset($result['generatedAt']);
}
return new ApiResponse($statusCode, $responseBody);
}
}