通过API上传文件xml

时间:2016-03-11 15:29:32

标签: php api exact-online

我尝试创建一个php脚本,通过API在线精确发送xml文件。

我的文件位于/tmp/xxx.xml

php代码(精确在线api上的连接):

    <?php



require_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

<?php



require_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

<?php



class 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文件?

全部谢谢

1 个答案:

答案 0 :(得分:0)

真的没那么难。

您应该使用已经执行此操作的库。例如,我使用这个库(非常好):

https://github.com/picqer/exact-php-client

然后我扩展了Connection以添加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>');