PSR-2, refactoring, tests
This commit is contained in:
parent
31b1d9d0f1
commit
ecb26bc1ff
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
/vendor
|
||||
/bin
|
||||
composer.lock
|
||||
composer.phar
|
||||
phpunit.xml
|
||||
.idea
|
||||
.DS_Store
|
||||
@ -8,4 +9,4 @@ phpunit.xml
|
||||
.buildpath
|
||||
.project
|
||||
.swp
|
||||
/nbproject
|
||||
/nbproject
|
||||
|
50
README.md
50
README.md
@ -1,33 +1,31 @@
|
||||
# PHP-клиент для retailCRM API
|
||||
# retailCRM API PHP client
|
||||
|
||||
PHP-клиент для работы с [retailCRM API](http://www.retailcrm.ru/docs/Developers/ApiVersion3).
|
||||
PHP-client for [retailCRM API](http://www.retailcrm.ru/docs/Developers/ApiVersion3).
|
||||
|
||||
Рекомендуем обращаться к [документации](http://retailcrm.github.io/api-client-php) по библиотеке, в частности по классу [RetailCrm\ApiClient](http://retailcrm.github.io/api-client-php/class-RetailCrm.ApiClient.html).
|
||||
Use [API documentation](http://retailcrm.github.io/api-client-php)
|
||||
|
||||
## Обязательные требования
|
||||
## Requirements
|
||||
|
||||
* PHP версии 5.3 и выше
|
||||
* PHP-расширение cURL
|
||||
* PHP 5.3 and above
|
||||
* PHP's cURL support
|
||||
|
||||
## Установка
|
||||
## Install
|
||||
|
||||
1) Установите [composer](https://getcomposer.org/download/)
|
||||
1) Get [composer](https://getcomposer.org/download/)
|
||||
|
||||
2) Выполните в папке проекта:
|
||||
2) Run into your project directory:
|
||||
```bash
|
||||
composer require retailcrm/api-client-php ~3.0.0
|
||||
```
|
||||
|
||||
В конфиг `composer.json` вашего проекта будет добавлена библиотека `retailcrm/api-client-php`, которая установится в папку `vendor/`. При отсутствии файла конфига или папки с вендорами они будут созданы.
|
||||
|
||||
В случае, если до этого в вашем проекте не использовался `composer`, подключите файл автозагрузки вендоров. Для этого укажите в коде проекта:
|
||||
If you have not used `composer` before, include autoloader into your project.
|
||||
```php
|
||||
require 'path/to/vendor/autoload.php';
|
||||
```
|
||||
|
||||
## Примеры использования
|
||||
## Usage
|
||||
|
||||
### Получение информации о заказе
|
||||
### Get order
|
||||
```php
|
||||
$client = new \RetailCrm\ApiClient(
|
||||
'https://demo.retailcrm.ru',
|
||||
@ -38,30 +36,30 @@ $client = new \RetailCrm\ApiClient(
|
||||
try {
|
||||
$response = $client->ordersGet('M-2342');
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
echo "Сетевые проблемы. Ошибка подключения к retailCRM: " . $e->getMessage();
|
||||
echo "Connection error: " . $e->getMessage();
|
||||
}
|
||||
|
||||
if ($response->isSuccessful()) {
|
||||
echo $response->order['totalSumm'];
|
||||
// или $response['order']['totalSumm'];
|
||||
// или
|
||||
// or $response['order']['totalSumm'];
|
||||
// or
|
||||
// $order = $response->getOrder();
|
||||
// $order['totalSumm'];
|
||||
} else {
|
||||
echo sprintf(
|
||||
"Ошибка получения информации о заказа: [Статус HTTP-ответа %s] %s",
|
||||
"Error: [HTTP-code %s] %s",
|
||||
$response->getStatusCode(),
|
||||
$response->getErrorMsg()
|
||||
);
|
||||
|
||||
// получить детализацию ошибок
|
||||
// error details
|
||||
//if (isset($response['errors'])) {
|
||||
// print_r($response['errors']);
|
||||
//}
|
||||
}
|
||||
```
|
||||
|
||||
### Создание заказа
|
||||
### Create order
|
||||
```php
|
||||
|
||||
$client = new \RetailCrm\ApiClient(
|
||||
@ -82,21 +80,21 @@ try {
|
||||
)
|
||||
));
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
echo "Сетевые проблемы. Ошибка подключения к retailCRM: " . $e->getMessage();
|
||||
echo "Connection error: " . $e->getMessage();
|
||||
}
|
||||
|
||||
if ($response->isSuccessful() && 201 === $response->getStatusCode()) {
|
||||
echo 'Заказ успешно создан. ID заказа в retailCRM = ' . $response->id;
|
||||
// или $response['id'];
|
||||
// или $response->getId();
|
||||
echo 'Order successfully created. Order ID into retailCRM = ' . $response->id;
|
||||
// or $response['id'];
|
||||
// or $response->getId();
|
||||
} else {
|
||||
echo sprintf(
|
||||
"Ошибка создания заказа: [Статус HTTP-ответа %s] %s",
|
||||
"Error: [HTTP-code %s] %s",
|
||||
$response->getStatusCode(),
|
||||
$response->getErrorMsg()
|
||||
);
|
||||
|
||||
// получить детализацию ошибок
|
||||
// error details
|
||||
//if (isset($response['errors'])) {
|
||||
// print_r($response['errors']);
|
||||
//}
|
||||
|
@ -4,6 +4,7 @@
|
||||
"type": "library",
|
||||
"keywords": ["API", "retailCRM", "REST"],
|
||||
"homepage": "http://www.retailcrm.ru/",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "retailCRM",
|
||||
@ -12,15 +13,17 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"ext-curl": "*"
|
||||
"ext-curl": "*",
|
||||
"phpunit/php-code-coverage": "3.3.0",
|
||||
"phpunit/php-invoker": "1.1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "3.7.*",
|
||||
"phpmd/phpmd": "2.1.*",
|
||||
"phpunit/phpunit": "5.2.*",
|
||||
"phpmd/phpmd": "2.4.*",
|
||||
"sebastian/phpcpd": "2.0.*",
|
||||
"sebastian/phpdcd": "1.0.*",
|
||||
"squizlabs/php_codesniffer": "dev-master",
|
||||
"apigen/apigen": "~4.0@dev"
|
||||
"squizlabs/php_codesniffer": "2.5.*",
|
||||
"apigen/apigen": "4.1.*"
|
||||
},
|
||||
"support": {
|
||||
"email": "support@intarocrm.ru"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
||||
namespace RetailCrm\Http;
|
||||
|
||||
use RetailCrm\Exception\CurlException;
|
||||
use RetailCrm\Exception\InvalidJsonException;
|
||||
use RetailCrm\Response\ApiResponse;
|
||||
|
||||
/**
|
||||
@ -30,6 +31,8 @@ class Client
|
||||
*
|
||||
* @param string $url api url
|
||||
* @param array $defaultParameters array of parameters
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct($url, array $defaultParameters = array())
|
||||
{
|
||||
@ -60,24 +63,23 @@ class Client
|
||||
* @param string $path request url
|
||||
* @param string $method (default: 'GET')
|
||||
* @param array $parameters (default: array())
|
||||
* @param int $timeout (default: 30)
|
||||
* @param bool $verify (default: false)
|
||||
* @param bool $debug (default: false)
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws CurlException
|
||||
* @throws InvalidJsonException
|
||||
*
|
||||
* @return ApiResponse
|
||||
*/
|
||||
public function makeRequest(
|
||||
$path,
|
||||
$method,
|
||||
array $parameters = array(),
|
||||
$timeout = 30,
|
||||
$verify = false,
|
||||
$debug = false
|
||||
array $parameters = array()
|
||||
) {
|
||||
$allowedMethods = array(self::METHOD_GET, self::METHOD_POST);
|
||||
if (!in_array($method, $allowedMethods)) {
|
||||
|
||||
if (!in_array($method, $allowedMethods, false)) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'Method "%s" is not valid. Allowed methods are %s',
|
||||
@ -91,53 +93,37 @@ class Client
|
||||
|
||||
$url = $this->url . $path;
|
||||
|
||||
if (self::METHOD_GET === $method && sizeof($parameters)) {
|
||||
if (self::METHOD_GET === $method && count($parameters)) {
|
||||
$url .= '?' . http_build_query($parameters, '', '&');
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $verify);
|
||||
|
||||
if (!$debug) {
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, (int) $timeout);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int) $timeout);
|
||||
} else {
|
||||
curl_setopt(
|
||||
$ch,
|
||||
CURLOPT_TIMEOUT_MS,
|
||||
(int) $timeout + ($this->retry * 2000)
|
||||
);
|
||||
}
|
||||
$curlHandler = curl_init();
|
||||
curl_setopt($curlHandler, CURLOPT_URL, $url);
|
||||
curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curlHandler, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_setopt($curlHandler, CURLOPT_FAILONERROR, false);
|
||||
curl_setopt($curlHandler, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curlHandler, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($curlHandler, CURLOPT_TIMEOUT, 30);
|
||||
curl_setopt($curlHandler, CURLOPT_CONNECTTIMEOUT, 30);
|
||||
|
||||
if (self::METHOD_POST === $method) {
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
|
||||
curl_setopt($curlHandler, CURLOPT_POST, true);
|
||||
curl_setopt($curlHandler, CURLOPT_POSTFIELDS, $parameters);
|
||||
}
|
||||
|
||||
$responseBody = curl_exec($ch);
|
||||
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$errno = curl_errno($ch);
|
||||
$error = curl_error($ch);
|
||||
$responseBody = curl_exec($curlHandler);
|
||||
$statusCode = curl_getinfo($curlHandler, CURLINFO_HTTP_CODE);
|
||||
$errno = curl_errno($curlHandler);
|
||||
$error = curl_error($curlHandler);
|
||||
|
||||
curl_close($ch);
|
||||
curl_close($curlHandler);
|
||||
|
||||
if ($errno && in_array($errno, $this->curlErrors) && $this->retry < 3) {
|
||||
if ($errno && in_array($errno, $this->curlErrors, false) && $this->retry < 3) {
|
||||
$errno = null;
|
||||
$error = null;
|
||||
$this->retry += 1;
|
||||
$this->makeRequest(
|
||||
$path,
|
||||
$method,
|
||||
$parameters,
|
||||
$timeout,
|
||||
$verify,
|
||||
$debug
|
||||
);
|
||||
++$this->retry;
|
||||
$this->makeRequest($path, $method, $parameters);
|
||||
}
|
||||
|
||||
if ($errno) {
|
||||
|
@ -28,6 +28,8 @@ class ApiResponse implements \ArrayAccess
|
||||
*
|
||||
* @param int $statusCode HTTP status code
|
||||
* @param mixed $responseBody HTTP body
|
||||
*
|
||||
* @throws InvalidJsonException
|
||||
*/
|
||||
public function __construct($statusCode, $responseBody = null)
|
||||
{
|
||||
@ -71,6 +73,10 @@ class ApiResponse implements \ArrayAccess
|
||||
* Allow to access for the property throw class method
|
||||
*
|
||||
* @param string $name
|
||||
* @param $arguments
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
@ -89,6 +95,9 @@ class ApiResponse implements \ArrayAccess
|
||||
* Allow to access for the property throw object property
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
@ -103,6 +112,8 @@ class ApiResponse implements \ArrayAccess
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
@ -111,6 +122,8 @@ class ApiResponse implements \ArrayAccess
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
@ -119,6 +132,7 @@ class ApiResponse implements \ArrayAccess
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
@ -128,6 +142,9 @@ class ApiResponse implements \ArrayAccess
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
|
@ -13,6 +13,9 @@
|
||||
<server name="CRM_URL" value="foo" />
|
||||
<server name="CRM_API_KEY" value="bar" />
|
||||
<server name="CRM_SITE" value="zoo" />
|
||||
<server name="CRM_STORE" value="moo" />
|
||||
<server name="CRM_PACK_ITEM" value="boo" />
|
||||
<server name="CRM_PACK_QUANTITY" value="goo" />
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
|
@ -27,15 +27,20 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* Return Client object
|
||||
*
|
||||
* @param string $url (default: null)
|
||||
* @param string $apiKey (default: null)
|
||||
* @param string $url (default: null)
|
||||
* @param array $defaultParameters (default: array())
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
public static function getClient($url = null, $defaultParameters = array())
|
||||
{
|
||||
return new Client(
|
||||
$url ?: $_SERVER['CRM_URL'] . '/api/' . ApiClient::VERSION,
|
||||
array('apiKey' => isset($defaultParameters['apiKey']) ? $defaultParameters['apiKey'] : $_SERVER['CRM_API_KEY'])
|
||||
array(
|
||||
'apiKey' => array_key_exists('apiKey', $defaultParameters)
|
||||
? $defaultParameters['apiKey']
|
||||
: $_SERVER['CRM_API_KEY']
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -26,4 +26,66 @@ class ApiClientPacksTest extends TestCase
|
||||
'API returns generatedAt in orders assembly history'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
public function testOrdersPacksCreate()
|
||||
{
|
||||
$client = static::getApiClient();
|
||||
$pack = array(
|
||||
'itemId' => $_SERVER['CRM_PACK_ITEM'],
|
||||
'quantity' => $_SERVER['CRM_PACK_QUANTITY'],
|
||||
'store' => $_SERVER['CRM_STORE']
|
||||
);
|
||||
|
||||
$response = $client->ordersPacksCreate($pack);
|
||||
$this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response);
|
||||
$this->assertEquals(201, $response->getStatusCode());
|
||||
$this->assertTrue($response->success);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
public function testOrdersPacksCreateFailed()
|
||||
{
|
||||
$client = static::getApiClient();
|
||||
$pack = array(
|
||||
'itemId' => 12,
|
||||
'store' => $_SERVER['CRM_STORE'],
|
||||
'quantity' => 2
|
||||
);
|
||||
|
||||
$response = $client->ordersPacksCreate($pack);
|
||||
$this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response);
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertFalse($response->success);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
public function testOrdersPacksGet()
|
||||
{
|
||||
$client = static::getApiClient();
|
||||
|
||||
$response = $client->ordersPacksGet(1);
|
||||
$this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertTrue($response->success);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
public function testOrdersPacksDelete()
|
||||
{
|
||||
$client = static::getApiClient();
|
||||
|
||||
$response = $client->ordersPacksDelete(1);
|
||||
$this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertTrue($response->success);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,10 @@ namespace RetailCrm\Tests;
|
||||
|
||||
use RetailCrm\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Class ApiClientStoreTest
|
||||
* @package RetailCrm\Tests
|
||||
*/
|
||||
class ApiClientStoreTest extends TestCase
|
||||
{
|
||||
/**
|
||||
@ -30,8 +34,7 @@ class ApiClientStoreTest extends TestCase
|
||||
public function testStoreInventoriesUploadExceptionEmpty()
|
||||
{
|
||||
$client = static::getApiClient();
|
||||
|
||||
$response = $client->storeInventoriesUpload(array());
|
||||
$client->storeInventoriesUpload(array());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,20 +50,27 @@ class ApiClientStoreTest extends TestCase
|
||||
$response = $client->storeInventoriesUpload(array(
|
||||
array(
|
||||
'externalId' => $externalIdA,
|
||||
'available' => 10,
|
||||
'purchasePrice' => 1700
|
||||
'stores' => array(
|
||||
array(
|
||||
'code' => $_SERVER['CRM_STORE'],
|
||||
'available' => 10,
|
||||
'purchasePrice' => 1700
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'externalId' => $externalIdB,
|
||||
'available' => 20,
|
||||
'purchasePrice' => 1500
|
||||
'stores' => array(
|
||||
array(
|
||||
'code' => $_SERVER['CRM_STORE'],
|
||||
'available' => 20,
|
||||
'purchasePrice' => 1500
|
||||
)
|
||||
)
|
||||
),
|
||||
));
|
||||
$this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response);
|
||||
$this->assertTrue(
|
||||
$response->isSuccessful(),
|
||||
'Got offer'
|
||||
);
|
||||
$this->assertTrue($response->isSuccessful());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,14 +58,4 @@ class ClientTest extends TestCase
|
||||
$this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
public function testMakeRequestRepeatOnTimeout()
|
||||
{
|
||||
$client = static::getClient();
|
||||
$response = $client->makeRequest('/orders', Client::METHOD_GET, array(), 1, false, true);
|
||||
$this->assertGreaterThanOrEqual(1, $client->retry);
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class ApiResponseTest extends TestCase
|
||||
|
||||
/**
|
||||
* @group unit
|
||||
* @expectedException RetailCrm\Exception\InvalidJsonException
|
||||
* @expectedException \RetailCrm\Exception\InvalidJsonException
|
||||
*/
|
||||
public function testJsonInvalid()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user