Как построить 3-й параметр метода edai.Search в запросе CURL к XPLAN API? - PullRequest
0 голосов
/ 25 июня 2018

Я пытаюсь запустить поиск по API, который требует, чтобы данные моего запроса были стилизованы как XML, вложенный в запрос XML. Я опубликую все свои вызовы классов и методов (которые я отправил в службу технической поддержки iress), чтобы их можно было полностью просмотреть, и, если у кого-то есть доступ к одному и тому же API, они могут немедленно воспроизвести проблему для себя.

<code>class XMLCurler
{
    private $username = '[redacted]';
    private $password = '[redacted]';
    private $url = 'https://[redacted].xplan.iress.com.au/RPC2/';
    public $ch;     // the curl handle
    public $token;  
    public $results;

    public function __construct() {
        if ($this->connect()) {
            if ($this->login()) {
                echo "<div class=\"success\">Successful Connection & Login. Token: {$this->token}</div>";
            }
        }
    }

    public function __destruct() {
        if ($this->ch) {
            $this->disconnect();
        }
    }

    public function connect() {
        if (!$this->ch = curl_init($this->url)) { // generate curl handle
            echo "<div class=\"error\">CURL Error While Connecting (check url)";
            return false;
        }
        return true;
    }

    public function disconnect() {
        curl_close($this->ch);
    }

    public function processResponse($response) {
        if (!$response) {
            echo "<div class=\"error\">CURL Error While Attempting to Login - No XML token string<br><b>" , curl_error($this->ch) , "</b></div>";
            return false;
        }
        $decoded = xmlrpc_decode($response);
        if (is_array($decoded) && xmlrpc_is_fault($decoded)) {
            echo "<div class=\"error\">Error Response: {$decoded['faultString']} ({$decoded['faultCode']})</div>";
            return false;
        }
        return $decoded;    
    }

    public function login() {
        $postfields = xmlrpc_encode_request('edai.Login', array($this->username, $this->password));  // package as xml
        curl_setopt($this->ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $postfields);
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);      // not advised, I need to find out how to avoid this
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);      // not advised, I need to find out how to avoid this

        if (!$token = $this->processResponse(curl_exec($this->ch))) {
            return false;
        }
        if (!preg_match("~^[\w+]{20}$~", $token)) {
            echo "<div class=\"error\">Invalid/Unexpected Token Generated<br><b>$token</b>";
            return false;
        }
        $this->token = $token;  // cache the valid token
        return true;
    }

    public function listChildren($path) {
        $method = "edai.ListChildren";
        $request = xmlrpc_encode_request($method, array($this->token, $path));

        echo "<div class=\"notice\">XMLRPC Encoded Request (for $method): <pre>" , htmlentities($request) , "
"; curl_setopt ($ this-> ch, CURLOPT_POSTFIELDS, $ request); if (! $ results = $ this-> processResponse (curl_exec ($ this-> ch))) { вернуть ложь; } $ this-> results = $ results; // кэшируем действительные результаты вернуть истину; } поиск по публичной функции ($ basepath, $ queryxml) { $ method = "edai.Search"; / ** Отчаянно / Ручная конструкция xml ... * $ xml = new DOMDocument ("1.0", "utf-8"); * $ xml-> appendChild ($ methodCall = $ xml-> createElement ("methodCall")); * $ methodCall-> appendChild ($ methodName = $ xml-> createElement ("methodName")); * $ methodCall-> appendChild ($ params = $ xml-> createElement ("params")); * $ params-> appendChild ($ param1 = $ xml-> createElement ("param")); * $ param1-> appendChild ($ value1 = $ xml-> createElement ("value")); * $ value1-> appendChild ($ string1 = $ xml-> createElement ("string")); * $ params-> appendChild ($ param2 = $ xml-> createElement ("param")); * $ param2-> appendChild ($ value2 = $ xml-> createElement ("value")); * $ value2-> appendChild ($ string2 = $ xml-> createElement ("string")); * $ params-> appendChild ($ param3 = $ xml-> createElement ("param")); * $ param3-> appendChild ($ value3 = $ xml-> createElement ("value")); * $ value3-> appendChild ($ string3 = $ xml-> createElement ("string")); * $ string3-> appendChild ($ EntitySearch = $ xml-> createElement ("EntitySearch")); * $ EntitySearch-> appendChild ($ SearchResult1 = $ xml-> createElement ("SearchResult")); * $ SearchResult1-> setAttribute ("field", "first_name"); * $ EntitySearch-> appendChild ($ SearchResult2 = $ xml-> createElement ("SearchResult")); * $ SearchResult2-> setAttribute ('field', "last_name"); * $ EntitySearch-> appendChild ($ SearchQuick = $ xml-> createElement ("SearchQuick")); * $ SearchQuick-> appendChild ($ s = $ xml-> createElement ("s")); * $ xpath = new DOMXPath ($ xml); * $ result1 = $ xpath-> query ("// methodName"); * $ result1-> item (0) -> nodeValue = $ method; * $ result2 = $ xpath-> query ("// params / param [1] / value / string"); * $ result2-> item (0) -> nodeValue = $ this-> token; * $ result3 = $ xpath-> query ("// params / param [2] / value / string"); * $ result3-> item (0) -> nodeValue = "entitymgr / client"; * $ result4 = $ xpath-> query ("// SearchQuick / s"); * $ result4-> item (0) -> nodeValue = "last_name: Smith"; * $ xml-> formatOutput = true; * $ request = $ xml-> saveXML (); * / / ** отчаянно пытался передать массив ... * $ queryarray = array ( * "EntitySearch" => массив ( * массив ( * "SearchResult" => массив ( * "@attr" => массив ( * "field" => "first_name" *) *) *), * массив ( * "SearchResult" => массив ( * "@attr" => массив ( * "field" => "last_name" *) *) *), * массив ( * "SearchQuick" => массив ( * "s" => "last_name: Smith" *) *) *) *); * / $ request = xmlrpc_encode_request ($ method, array ($ this-> token, $ basepath, $ queryxml)); // это изменяет вложенную строку $ queryxml // Причины:// Ответ об ошибке: UNKNOWN (CORBA.UNKNOWN (omniORB.UNKNOWN_PythonException, CORBA.COMPLETED_MAYBE)) (-32505) // $ request = html_entity_decode ($ request); // восстанавливать закодированные объекты // $ request = preg_replace ('~ (?:> \ K \ s +) | (?: \ s + (? = <)) ~', '', $ request); // удаляем каждый пробел между тегами (хак) // Причины: // Ответ об ошибке: ExpatError (синтаксическая ошибка: строка 1, столбец 0 (байт 0)) (-32505) echo "<div class = \" note \ "> Кодированный запрос XMLRPC (для $ method):
" , htmlentities($request) , "
"; curl_setopt ($ this-> ch, CURLOPT_POSTFIELDS, $ request); if (! $ results = $ this-> processResponse (curl_exec ($ this-> ch))) { вернуть ложь; } $ this-> results = $ results; // кэшируем действительные результаты вернуть истину; } }

Ниже показано, как я звоню. edai.ListChildren работает, потому что мне не нужно отправлять какие-либо данные XML. edai.Search не работает, потому что мне не удается правильно подготовить запрос XML в запросе XML.

<code>$XC = new XMLCurler();

/* edai.ListChildren works as desired/expected */
$path = "/entitymgr/client";
if ($XC->listChildren($path)) {
    echo "<div>List of Children Successful.<pre>";
    var_export($XC->results);
    echo "
"; } / * edai.Search не работает * / $ basepath = "entitymgr / client"; $ queryxml = last_name: Smith XML; if ($ XC-> search ($ basepath, $ queryxml)) { echo "
Поиск успешен.
";
    var_export($XC->results);
    echo "
"; }

Это запрос о попытке и сообщение об ошибке .

Это соответствующая часть руководства, которое мне было предоставлено (XPLAN XML-RPC ВНЕШНИЙ ИНТЕРФЕЙС ДОСТУПА К ДАННЫМ 7 мая 2013 г.) :

Я связался с iress.com пару недель назад, они позвонили мне, чтобы подтвердить, что я авторизован для доступа к API, и сказали, что они будут на связи - что последующего вызова не произошло и я хотел бы вернуться к работе над этим проектом.

Я точно знаю, что для моего запроса существует фамилия Smith.

У меня нет опыта работы с Python, поэтому ответы на ошибки мне не помогут. Я сделал больше попыток град Мэри , чем я написал, но я устал тратить свое время. Я не знаю, должен ли третий параметр быть вложенным в <value>, <param>, <struct>, <string>, <array>, <xml> или что-то еще целиком.

Если у кого-нибудь есть какие-либо предложения относительно того, как подготовить мой XML-запрос к этому запросу, я его выполню и предоставлю отзыв.

Я также рад получить совет о дизайне класса, проблемах безопасности и совершенно разных подходах php для получения edai.Search для возврата некоторых полезных данных.


По запросу @ThW, вот коллекция попыток xml и их соответствующих сообщений об ошибках: https://pastebin.com/dYtwXWxz

Ответы [ 3 ]

0 голосов
/ 05 июля 2018

После личного разговора со службой поддержки IRESS и продолжения расследования, к сожалению (и несмотря на написанное руководство, в котором описывается, как интегрироваться с API), единственное лицензированное использование API - это «загрузка документов со сканером Toshiba».

Чтобы получить доступ, юридические группы IRESS и компании должны будут оформить новые лицензионные документы по указанному выше отредактированному URL. Это вряд ли будет быстрым делом.

0 голосов
/ 24 октября 2018

Оказывается, что ошибка была не в моем php-коде (который я с тех пор разработал для лучшей обработки данных ответа), а скорее в xml-запросе, который я отправлял.

Вместо того, чтобы использовать чтопредлагаемая документация:

<SearchQuick><s>last_name:Smith</s></SearchQuick>

Используйте следующее эквивалентное действительное выражение:

<SearchByField field="last_name" op="equal"><s>Smith</s></SearchByField>
0 голосов
/ 03 июля 2018

Снимок в темноте, поскольку я не могу проверить API напрямую ...

Возможно, вызов xmlrpc_encode_request мог бы быть связан с именованными параметрами:

$params = [
    'context' => $this->token,
    'basepath' => $basepath, // try with a leading slash, too, in spite of the docs listing it w/o one
    'queryxml' => $queryxml,
];
$request = xmlrpc_encode_request($method, $params);  // this mutates the nested $queryxml string

Если это не такt, прекратите возиться с кодом и установите SoapUI или Почтальон или Бессонница или аналогичный, и вручную создайте свои запросы.

Iподозреваю, что у вас будет рабочий запрос в течение получаса, и он может работать в обратном направлении для отладки вашего кода / переписывания кода.Я сделал бы это для вас, если бы у меня был доступ к API.

Что нужно проверить:

  • имеет значение кодировка (если это будет utf8 вместо)?

  • XML-запрос должен рассматриваться как строка, поэтому убедитесь, что он закодирован / обернут в теги CDATA, когда ваш GUI-клиент делает свои запросы.В зависимости от выбранного вами клиента, это может быть сделано за вас, просто убедитесь, что это сделано

...