通过 API 上传文件 XML


upload file xml via API

我尝试创建一个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);
}

精确Api.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);
    }
}

没错.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 文件?

谢谢大家

真的没那么难。

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

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>');