1
0
Fork 0
mirror of synced 2025-04-10 04:21:01 +00:00
This commit is contained in:
Alex Lushpai 2019-04-01 02:15:27 +03:00
parent 8001ab64e2
commit a8065558f8
12 changed files with 746 additions and 2 deletions

2
.gitignore vendored
View file

@ -196,4 +196,4 @@ build/*
test-report.xml
# GraphViz Dot
dot/*
dot/*

View file

@ -14,4 +14,4 @@ before_script:
- flags="-o"
- composer install $flags
script: make travis
script: make travis

32
apigen.neon Normal file
View file

@ -0,0 +1,32 @@
extensions:
- php
source:
- src
exclude:
- tests/
- vendor/
- bin/
- docs/
charset:
- auto
- UTF-8
- Windows-1251
title: retailCRM PHP MG Bot API client
templateTheme: bootstrap
groups: auto
accessLevels:
- public
- protected
internal: true
php: false
tree: true
deprecated: true
todo: true
destination: ../mg-bot-api-client-php.pages/
download: false

View file

@ -0,0 +1,123 @@
<?php
/**
* PHP version 7.0
*
* Client
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
namespace RetailCrm\Bot;
use RetailCrm\Bot\Exception\CurlException;
use RetailCrm\Bot\Exception\InvalidJsonException;
use Exception;
use InvalidArgumentException;
/**
* PHP version 7.0
*
* Client class
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
class Client
{
const VERSION = 'v1';
protected $client;
/**
* Init
*
* @param string $url api url
* @param string $token api key
* @param bool $debug debug flag
*/
public function __construct($url, $token, $debug = false)
{
if ('/' !== $url[strlen($url) - 1]) {
$url .= '/';
}
$url = $url . 'api/bot/' . self::VERSION;
$this->client = new Request($url, $token, $debug);
}
/**
* Returns filtered bots list
*
* @param array $parameters (default: array())
*
* @throws InvalidArgumentException
* @throws CurlException
* @throws InvalidJsonException
* @throws Exception
*
* @return Response
*/
public function bots(array $parameters = [])
{
return $this->client->makeRequest('/bots', 'GET', $parameters);
}
/**
* Returns filtered channels list
*
* @param array $parameters (default: array())
*
* @throws InvalidArgumentException
* @throws CurlException
* @throws InvalidJsonException
* @throws Exception
*
* @return Response
*/
public function channels(array $parameters = [])
{
return $this->client->makeRequest('/channels', 'GET', $parameters);
}
/**
* Returns filtered chats list
*
* @param array $parameters (default: array())
*
* @throws InvalidArgumentException
* @throws CurlException
* @throws InvalidJsonException
* @throws Exception
*
* @return Response
*/
public function chats(array $parameters = [])
{
return $this->client->makeRequest('/chats', 'GET', $parameters);
}
/**
* Returns filtered customers list
*
* @param array $parameters (default: array())
*
* @throws InvalidArgumentException
* @throws CurlException
* @throws InvalidJsonException
* @throws Exception
*
* @return Response
*/
public function customers(array $parameters = [])
{
return $this->client->makeRequest('/customers', 'GET', $parameters);
}
}

View file

@ -0,0 +1,32 @@
<?php
/**
* PHP version 7.0
*
* CurlException
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
namespace RetailCrm\Bot\Exception;
use RuntimeException;
/**
* PHP version 7.0
*
* Class CurlException
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
class CurlException extends RuntimeException
{
}

View file

@ -0,0 +1,32 @@
<?php
/**
* PHP version 7.0
*
* CurlException
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
namespace RetailCrm\Bot\Exception;
use DomainException;
/**
* PHP version 7.0
*
* Class InvalidJsonException
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
class InvalidJsonException extends DomainException
{
}

View file

@ -0,0 +1,32 @@
<?php
/**
* PHP version 7.0
*
* CurlException
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
namespace RetailCrm\Bot\Exception;
use DomainException;
/**
* PHP version 7.0
*
* Class CurlException
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
class LimitException extends DomainException
{
}

View file

@ -0,0 +1,151 @@
<?php
/**
* PHP version 7.0
*
* Request
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
namespace RetailCrm\Bot;
use RetailCrm\Bot\Exception\CurlException;
use RetailCrm\Bot\Exception\InvalidJsonException;
use RetailCrm\Bot\Exception\LimitException;
use Exception;
use InvalidArgumentException;
/**
* PHP version 7.0
*
* Request class
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
class Request
{
const METHOD_GET = 'GET';
const METHOD_POST = 'POST';
const METHOD_PUT = 'PUT';
const METHOD_DELETE = 'DELETE';
protected $url;
protected $token;
private $debug;
/**
* Client constructor.
*
* @param string $url api url
* @param string $token api token
* @param bool $debug make request verbose
*/
public function __construct($url, $token, $debug)
{
if (false === stripos($url, 'https://')) {
throw new InvalidArgumentException('API schema requires HTTPS protocol');
}
$this->url = $url;
$this->token = $token;
$this->debug = $debug;
}
/**
* Make HTTP request
*
* @param string $path request url
* @param string $method (default: 'GET')
* @param array $parameters (default: array())
*
* @throws \InvalidArgumentException
* @throws \Exception
* @throws CurlException
* @throws InvalidJsonException
*
* @return Response
*/
public function makeRequest(
$path,
$method,
array $parameters = []
) {
$allowedMethods = [self::METHOD_GET, self::METHOD_POST, self::METHOD_PUT, self::METHOD_DELETE];
if (!in_array($method, $allowedMethods, false)) {
throw new InvalidArgumentException(
sprintf(
'Method "%s" is not valid. Allowed methods are %s',
$method,
implode(', ', $allowedMethods)
)
);
}
$url = $this->url . $path;
if (self::METHOD_GET === $method && count($parameters)) {
$url .= '?' . http_build_query($parameters, '', '&');
}
$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, 60);
curl_setopt($curlHandler, CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($curlHandler, CURLOPT_VERBOSE, (int)$this->debug);
curl_setopt($curlHandler, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
sprintf("X-Bot-Token: %s", $this->token)
]);
if (in_array($method, [self::METHOD_POST, self::METHOD_PUT, self::METHOD_DELETE])) {
curl_setopt($curlHandler, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($curlHandler, CURLOPT_POSTFIELDS, json_encode($parameters));
}
$responseBody = curl_exec($curlHandler);
$statusCode = curl_getinfo($curlHandler, CURLINFO_HTTP_CODE);
$response = Response::parseJSON($responseBody);
$errorMessage = !empty($response['errorMsg']) ? $response['errorMsg'] : '';
/**
* responses with 400 & 460 http codes contains extended error data
* therefore they are not handled as exceptions
*/
if (in_array($statusCode, [403, 404, 500])) {
throw new Exception($errorMessage);
}
if ($statusCode == 503) {
throw new LimitException($errorMessage);
}
$errno = curl_errno($curlHandler);
$error = curl_error($curlHandler);
curl_close($curlHandler);
if ($errno) {
throw new CurlException($error, $errno);
}
return new Response($statusCode, $responseBody);
}
}

View file

@ -0,0 +1,230 @@
<?php
/**
* PHP version 7.0
*
* Request
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
namespace RetailCrm\Bot;
use BadMethodCallException;
use InvalidArgumentException;
use RetailCrm\Bot\Exception\InvalidJsonException;
/**
* PHP version 7.0
*
* Request class
*
* @category RetailCrm
* @package Bot
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
class Response implements \ArrayAccess
{
// HTTP response status code
protected $statusCode;
// response assoc array
protected $response;
// response body
protected $raw;
/**
* ApiResponse constructor.
*
* @param int $statusCode HTTP status code
* @param mixed $responseBody HTTP body
*
* @throws InvalidJsonException
*/
public function __construct($statusCode, $responseBody = null)
{
$this->statusCode = (int) $statusCode;
$this->raw = $responseBody;
$this->response = self::parseJSON($responseBody);
}
/**
* Return raw HTTP response
*
* @return string|null
*/
public function getRawResponse()
{
return $this->raw;
}
/**
* Return HTTP response
*
* @return array
*/
public function getResponse()
{
return $this->response;
}
/**
* Return HTTP response status code
*
* @return int
*/
public function getStatusCode()
{
return $this->statusCode;
}
/**
* HTTP request was successful
*
* @return bool
*/
public function isSuccessful()
{
return $this->statusCode < 400;
}
/**
* Allow to access for the property throw class method
*
* @param string $name method name
* @param mixed $arguments method parameters
*
* @throws \InvalidArgumentException
*
* @return mixed
*/
public function __call($name, $arguments)
{
// convert getSomeProperty to someProperty
$propertyName = strtolower(substr($name, 3, 1)) . substr($name, 4);
if (!isset($this->response[$propertyName])) {
throw new InvalidArgumentException("Method \"$name\" not found");
}
return $this->response[$propertyName];
}
/**
* Allow to access for the property throw object property
*
* @param string $name property name
*
* @throws \InvalidArgumentException
*
* @return mixed
*/
public function __get($name)
{
if (!isset($this->response[$name])) {
throw new InvalidArgumentException("Property \"$name\" not found");
}
return $this->response[$name];
}
/**
* Allow to check if the property exists through object property
*
* @param string $name property name
*
* @return bool
*/
public function __isset($name)
{
return isset($this->response[$name]);
}
/**
* Offset set
*
* @param mixed $offset offset
* @param mixed $value value
*
* @throws BadMethodCallException
* @return void
*/
public function offsetSet($offset, $value)
{
$message = sprintf("This call not allowed. Offset given: %s. Value given: %s", $offset, $value);
throw new BadMethodCallException($message);
}
/**
* Offset unset
*
* @param mixed $offset offset
*
* @throws BadMethodCallException
* @return void
*/
public function offsetUnset($offset)
{
$message = sprintf("This call not allowed. Offset given: %s", $offset);
throw new BadMethodCallException($message);
}
/**
* Check offset
*
* @param mixed $offset offset
*
* @return bool
*/
public function offsetExists($offset)
{
return isset($this->response[$offset]);
}
/**
* Get offset
*
* @param mixed $offset offset
*
* @throws \InvalidArgumentException
*
* @return mixed
*/
public function offsetGet($offset)
{
if (!isset($this->response[$offset])) {
throw new InvalidArgumentException("Property \"$offset\" not found");
}
return $this->response[$offset];
}
/**
* @param string $responseBody
*
* @return array
*/
public static function parseJSON($responseBody): array
{
$result = [];
if (!empty($responseBody)) {
$response = json_decode($responseBody, true);
if (!$response && JSON_ERROR_NONE !== ($error = json_last_error())) {
throw new InvalidJsonException("Invalid JSON in the API response body. Error code #$error", $error);
}
$result = $response;
}
return $result;
}
}

View file

@ -0,0 +1,57 @@
<?php
/**
* PHP version 7.0
*
* RequestHelper
*
* @category RetailCrm
* @package Helper
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
namespace RetailCrm\Helper;
/**
* PHP version 7.0
*
* RequestHelper class
*
* @category RetailCrm
* @package Helper
* @author retailCRM <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://help.retailcrm.pro/docs/Developers
*/
class RequestHelper
{
/**
* Prepare module data
*
* @param array $config
* @param string $clientId
*
* @return array
*/
public static function moduleRequest(array $config, string $clientId): array
{
$config['host'] = str_replace("https://", '', $config['host']);
$moduleConfiguration = [
'code' => $config['code'],
'integrationCode' => $config['code'],
'active' => true,
'name' => $config['name'],
'clientId' => $clientId,
'logo' => sprintf("https://%s%s", $config['host'], $config['logo']),
'baseUrl' => sprintf("https://%s", $config['host']),
'accountURL' => sprintf("https://%s/settings/%s", $config['host'], $clientId),
'actions' => ['activity' => '/actions/activity'],
'integrations' => ['mgBot' => []]
];
return $moduleConfiguration;
}
}

View file

@ -0,0 +1,55 @@
<?php
/**
* PHP version 5.4
*
* Test case class
*
* @category RetailCrm
* @package Test
* @author RetailCrm <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://www.retailcrm.ru/docs/Developers/ApiVersion5
*/
namespace RetailCrm\Test;
use PHPUnit\Framework\TestCase as BaseCase;
use RetailCrm\Bot\Client;
/**
* Class TestCase
*
* @category RetailCrm
* @package Test
* @author RetailCrm <integration@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://www.retailcrm.ru/docs/Developers/ApiVersion5
*/
class TestCase extends BaseCase
{
/**
* Return ApiClient object
*
* @param string $url (default: null)
* @param string $key (default: null)
* @param bool $debug (default: false)
*
* @return Client
*/
public static function getApiClient(
$url = null,
$key = null,
$debug = false
) {
$configUrl = getenv('MG_BOT_URL') ?: $_SERVER['MG_BOT_URL'];
$configKey = getenv('MG_BOT_KEY') ?: $_SERVER['MG_BOT_KEY'];
$configDbg = getenv('MG_BOT_DBG') ?: $_SERVER['MG_BOT_DBG'];
return new Client(
$url ?: $configUrl,
$key ?: $configKey,
$debug ?: $configDbg
);
}
}

View file