Я пытаюсь создать php-скрипт для отправки xml-файла через API в режиме онлайн.
Мой файл находится в /tmp/xxx.xml
PHP-код (связь по точным онлайн-API):
<?phprequire_once 'ExactApi.php';
// Configuration, change these:
$clientId = '{x}';
$clientSecret = 'x';
$redirectUri = "x";
$division = "x";
try {
// Initialize ExactAPI
$exactApi = new ExactApi('fr', $clientId, $clientSecret, $division);
$exactApi->getOAuthClient()->setRedirectUri($redirectUri);
if (!isset($_GET['code'])) {
// Redirect to Auth-endpoint
$authUrl = $exactApi->getOAuthClient()->getAuthenticationUrl();
header('Location: ' . $authUrl, TRUE, 302);
die('Redirect');
} else {
// Receive data from Token-endpoint
$tokenResult = $exactApi->getOAuthClient()->getAccessToken($_GET['code']);
$exactApi->setRefreshToken($tokenResult['refresh_token']);
// List accounts
$response = $exactApi->sendRequest('crm/Accounts', 'get');
var_dump($response);
// Create account
$response = $exactApi->sendRequest('crm/Accounts', 'post', array(
'Status' => 'C',
'IsSupplier' => True,
'Name' => 'xx',
'AddressLine1' => 'xx',
'Postcode' => 'xx',
'City' => 'xx',
'Country' => 'xx',
'Email' => 'xx',
'Phone' => 'xx',
'Website' => 'xx'
));
var_dump($response);
}
}catch(ErrorException $e){
var_dump($e);
}
ExactApi.php
<?phprequire_once 'ExactOAuth.php';
class ExactApi
{
const METHOD_POST = 'post';
const URL_API = 'https://start.exactonline.%s/api/v1/';
/** @var string */
protected $countryCode;
/** @var string */
protected $clientId;
/** @var string */
protected $clientSecret;
/** @var string */
protected $refreshToken;
/** @var string */
protected $accessToken;
/** @var int */
protected $expiresIn;
/** @var string */
protected $division;
/** @var ExactOAuth */
protected $oAuthClient;/**
* @param string $countryCode
* @param string $clientId
* @param string $clientSecret
* @param string $division
* @param string|NULL $refreshToken
*/
public function __construct($countryCode, $clientId, $clientSecret, $division, $refreshToken = NULL)
{
$this->countryCode = $countryCode;
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
$this->refreshToken = $refreshToken;
$this->division = $division;
}
/**
* @return ExactOAuth
*/
public function getOAuthClient()
{
if (!$this->oAuthClient) {
$this->oAuthClient = new ExactOAuth(
$this->countryCode, $this->clientId, $this->clientSecret
);
}
return $this->oAuthClient;
}
/**
* @param string $token
*/
public function setRefreshToken($token)
{
$this->refreshToken = $token;
}
/**
* @return string|FALSE
* @throws \ErrorException
*/
protected function initAccessToken()
{
if (empty($this->accessToken) || $this->isExpired()) {
if (empty($this->refreshToken)) {
throw new \ErrorException('Refresh token is not specified.');
}
$refreshed = $this->getOAuthClient()->refreshAccessToken($this->refreshToken);
if (!$refreshed) {
return FALSE;
}
$this->setExpiresIn($refreshed['expires_in']);
$this->refreshToken = $refreshed['refresh_token'];
$this->accessToken = $refreshed['access_token'];
}
return $this->accessToken;
}
/**
* @param int $expiresInTime
*/
protected function setExpiresIn($expiresInTime)
{
$this->expiresIn = time() + $expiresInTime;
}
/**
* @return int
*/
protected function isExpired()
{
return $this->expiresIn > time();
}
/**
* @param string $resourceUrl
* @param array|NULL $params
* @return string
*/
protected function getRequestUrl($resourceUrl, $params = NULL)
{
$resourceUrlParts = parse_url($resourceUrl);
$baseUrl = sprintf(self::URL_API, $this->countryCode);
$apiUrl = $baseUrl . $this->division.'/'.$resourceUrlParts['path'];
if (isset($resourceUrlParts['query'])) {
$apiUrl .= '?' . $resourceUrlParts['query'];
} else
if ($params && is_array($params)) {
$apiUrl .= '?' . http_build_query($params, '', '&');
}
return $apiUrl;
}
/**
* @param string $url
* @param string $method
* @param array|NULL $payload
* @return string
*/
public function sendRequest($url, $method, $payload = NULL)
{
if ($payload && !is_array($payload)) {
throw new \ErrorException('Payload is not valid.');
}
if (!$accessToken = $this->initAccessToken()) {
throw new \ErrorException('Access token was not initialized');
}
$requestUrl = $this->getRequestUrl($url, array(
'access_token' => $accessToken
));
// Base cURL option
$curlOpt = array();
$curlOpt[CURLOPT_URL] = $requestUrl;
$curlOpt[CURLOPT_RETURNTRANSFER] = TRUE;
$curlOpt[CURLOPT_SSL_VERIFYPEER] = TRUE;
$curlOpt[CURLOPT_HEADER] = false;
if ($method == self::METHOD_POST) {
$curlOpt[CURLOPT_HTTPHEADER] = array(
'Content-Type:application/json',
'access_token:' . $accessToken,
'Content-length: ' . strlen(json_encode($payload))
);
$curlOpt[CURLOPT_POSTFIELDS] = json_encode($payload);
$curlOpt[CURLOPT_CUSTOMREQUEST] = strtoupper($method);
}
$curlHandle = curl_init();
curl_setopt_array($curlHandle, $curlOpt);
return curl_exec($curlHandle);
}
}
ExactOAuth.php
<?phpclass ExactOAuth
{
const URL_AUTH = 'https://start.exactonline.%s/api/oauth2/auth';
const URL_TOKEN = 'https://start.exactonline.%s/api/oauth2/token';
const GRANT_AUTHORIZATION_CODE = 'authorization_code';
const GRANT_REFRESH_TOKEN = 'refresh_token';
const RESPONSE_TYPE_CODE = 'code';
/** @var string */
public $clientId;
/** @var string */
public $clientSecret;
/** @var string */
public $countryCode;
/** @var string */
public $redirectUri;
/**
* @param string $countryCode
* @param string $clientId
* @param string $clientSecret
*/
public function __construct($countryCode, $clientId, $clientSecret)
{
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
$this->countryCode = $countryCode;
}
/**
* @param string|NULL $redirectUri
* @param string $responseType
* @return string
* @throws \ErrorException
*/
public function getAuthenticationUrl($redirectUri = NULL, $responseType = self::RESPONSE_TYPE_CODE)
{
if (empty($this->redirectUri) && empty($redirectUri)) {
throw new \ErrorException('Redirect Uri is not specified.');
}
$params = array(
'client_id' => $this->clientId,
'redirect_uri' => $redirectUri ? $redirectUri : $this->redirectUri,
'response_type' => $responseType
);
$url = sprintf(self::URL_AUTH, $this->countryCode);
return $url . '?' . http_build_query($params, '', '&');
}
/**
* @param string $code
* @param string|NULL $redirectUri
* @param string $grantType
* @return array {access_token, token_type, expires_in, refresh_token}
* @throws \ErrorException
*/
public function getAccessToken($code, $redirectUri = NULL, $grantType = self::GRANT_AUTHORIZATION_CODE)
{
if (empty($this->redirectUri) && empty($redirectUri)) {
throw new \ErrorException('Redirect Uri is not specified.');
}
$params = array(
'code' => $code,
'client_id' => $this->clientId,
'grant_type' => $grantType,
'client_secret' => $this->clientSecret,
'redirect_uri' => $redirectUri ? $redirectUri : $this->redirectUri,
);
$url = sprintf(self::URL_TOKEN, $this->countryCode);
return $this->getResponse($url, $params);
}
/**
* @param string $refreshToken
* @return array {access_token, expires_in, refresh_token}
*/
public function refreshAccessToken($refreshToken)
{
$params = array(
'refresh_token' => $refreshToken,
'grant_type' => self::GRANT_REFRESH_TOKEN,
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret
);
$url = sprintf(self::URL_TOKEN, $this->countryCode);
return $this->getResponse($url, $params);
}
/**
* @param string $url
* @param array $params
* @return array|NULL
*/
public function getResponse($url, $params)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params, '', '&'));
$result = curl_exec($ch);
$decodedResult = json_decode($result, TRUE);
if (isset($decodedResult['error'])) {
return FALSE;
}
return $decodedResult;
}
/**
* @param string $uri
*/
public function setRedirectUri($uri)
{
$this->redirectUri = $uri;
}
}
Я хотел бы отправить файл XML (xxx.xml)
<?xml version="1.0" encoding="utf-8"?>
<eExact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="eExact-XML.xsd">
<Items><Item code="2M31E93_IM"><IsSalesItem>1</IsSalesItem><Sales><Price><Currency code="EUR" /><Value>80.00</Value><VAT code="VN"></VAT></Price><Unit code="pc"><Description>Piece</Description></Unit></Sales><Costs><Price><Currency code="EUR" /><Value>591.53</Value></Price></Costs><ItemAccounts><ItemAccount><Account code="0000002"></Account><IsPrimary>1</IsPrimary><SupplierItemCode>2M31E93_IM</SupplierItemCode><Purchase><Price><Currency code="EUR" /><Value>50.00</Value><VAT code="AN"></VAT></Price><Unit code="pc"><Description>Piece</Description></Unit></Purchase><CanDropShip>1</CanDropShip></ItemAccount></ItemAccounts></Item></Items>
</eExact>
Что я должен добавить в свой php-файл, чтобы отправить мой xml-файл?
Спасибо всем
На самом деле это не так сложно.
Вы должны использовать библиотеку, которая уже делает это. Например, я использую эту библиотеку (это очень хорошо):
https://github.com/picqer/exact-php-client
Затем я расширил соединение, добавив свойства readXML и writeXML, например:
https://gist.github.com/alexjeen/6211c363c4efd4c3034cb3f81f7520bf
И тогда вы просто вызываете класс RawConnection вместо обычного класса Connection библиотеки:
$connection = new \app\exact\RawConnection();
$connection->setRedirectUrl(Yii::$app->params['exact_redirect_url']);
$connection->setExactClientId(Yii::$app->params['exact_client_id']);
$connection->setExactClientSecret(Yii::$app->params['exact_client_secret']);
А затем используйте его следующим образом:
$simpleXmlElement = $connection->getXml(1337, 'GLTransactions');
Или ПОСТАВЬТЕ XML
$simpleXmlElement = $connection->postXml(1337, 'GLTransactions', '<xmlstringhere>');
Других решений пока нет …