Как создать запрос soap и отправить XML в WSDL, а затем получить ответ в XML? - PullRequest
0 голосов
/ 14 января 2020

Я создаю интеграцию через API. По сути, мне нужно создать soap запрос и отправить XML в WSDL, а затем получить ответ также в XML, чтобы я мог разобрать его позже.

Проблема для меня заключается в том, что ... Как начать, потому что я не знаю soap правил запроса, и мне трудно найти хороший источник знаний, который может помочь в моем случае. Если у вас есть, пожалуйста, вставьте мне ссылку, чтобы я мог прочитать о ней (уже проверено PHP, ручной SoapClient, но для меня сейчас это волшебство c).

Теперь у меня есть создание Объект с помощью URL-адреса синтаксического анализа класса SoapClient для WSDL:

$soap = new SoapClient('https://wasstt.infomonitor.pl/bigApi/v1/ReportOrderService/WEB-INF/wsdl/wsBigApi1v1.wsdl');

Я также использовал метод __getFunctions (), чтобы я мог видеть функции внутри:

print_r($soap->__getFunctions()); 

В результате Приведенный выше код Я получил массив с функциями, вот как это выглядит:

(

[0] => ResponseMessage addOrder(RequestMessage $addOrderRequest)
[1] => ResponseMessage getOrderList(RequestMessage $getOrderListRequest)
[2] => ResponseMessage getOrderStatus(RequestMessage $getOrderStatusRequest)
[3] => ResponseMessage getReport(RequestMessage $getReportRequest)
[4] => ResponseMessage getStatistic(RequestMessage $getStatisticRequest)
[5] => ResponseMessage checkAppStatus(RequestMessage $checkAppStatusRequest)
[6] => ResponseMessage updateMonitoring(RequestMessage $updateMonitoringRequest)
[7] => ResponseMessage removeTracedEvents(RequestMessage $removeTracedEventsRequest)
[8] => ResponseMessage getMonitoredEntities(RequestMessage $getMonitoredEntitiesRequest)
[9] => ResponseMessage getTracedEvents(RequestMessage $getTracedEventsRequest)
[10] => ResponseMessage whoMonitorsMe(RequestMessage $whoMonitorsMeRequest)
[11] => ResponseMessage updateEconomicInformation(RequestMessage $updateEconomicInformationRequest)
[12] => ResponseMessage updateLiability(RequestMessage $updateLiabilityRequest)

)

В этот момент кажется, что в tunnel, потому что есть функция getReport, которую я должен вызывать, но проблема в том, как? Я знаю, что есть __soapCall (php manual):

public SoapClient::__soapCall ( string $function_name , array $arguments [, array $options [, mixed $input_headers [, array &$output_headers ]]] ) : mixed

Но я не могу понять, что и как мне делать на следующем шаге.

@ edited

Я пытался по-другому и сделал:

$report = $soap->getReport($xml); //getReport is the valid function

И я получил сообщение ниже:

cvc-complex-type.2.4.a: Invalid content was found starting with element 'testDataMarker'. One of '{requestId}' is expected.

1 Ответ

1 голос
/ 15 января 2020

Soap запросов с PHP на самом деле довольно просты, если вы следуете веб-стандарту. Класс PHP SoapClient предназначен для всего, что вам нужно. Если вы работаете только с объектами, полученными из файла WSDL, это становится довольно просто.

Вы на правильном пути. Первым шагом должно быть определение функций и типов данных из файла WSDL. Вы сделали это уже с помощью функций $client->__getFunctions() и $client->__getTypes().

ResponseMessage getReport(RequestMessage $getReportRequest)

Это дает следующую информацию. Если вы хотите вызвать функцию getReport веб-службы, вы должны использовать в запросе объект RequestMessage и получить объект ResponseMessage в качестве ответа. Так где же взять эти методы? Эта информация записана в связанном XSD-файле , или вы также можете использовать функцию $client->__getTypes(). Это даст нам следующую информацию:

struct ResponseMessage {
    messageId responseId;
    dateTime responseDateTime;
    messageId requestId;
    dateTime requestDateTime;
    string user;
    protocolEnum protocol;
    string customProtocol;
    string data;
}

RequestMessage {
    messageId requestId;
    dateTime requestDateTime;
    protocolEnum protocol;
    string customProtocol;
    boolean testDataMarker;
    string data;
}

Мы можем перевести структуру в класс PHP. Этот класс является так называемым объектом значения.

class RequestMessage
{
    protected $requestId;

    protected $requestDateTime;

    protected $protocol;

    protected $customProtocol;

    protected $testDataMarker;

    protected $data;

    public function getRequestId(): ?string
    {
        return $this->requestId;
    }

    public function setRequestId(?string $requestId): self
    {
        $this->requestId = $requestId;
        return $this;
    }

    public function getRequestDateTime(): ?string
    {
        return $this->requestDateTime;
    }

    public function setRequestDateTime(?string $requestDateTime): self
    {
        $this->requestDateTime = $requestDateTime;
        return $this;
    }

    public function getProtocol(): ?string
    {
        return $this->protocol;
    }

    public function setProtocol(?string $protocol): self
    {
        $this->protocol = $protocol;
        return $this;
    }

    public function getCustomProtocol(): ?string
    {  
        return $this->customProtocol;
    }

    public function setCustomProtocol(?string $customProtocol): self
    {
        $this->customProtocol = $customProtocol;
        return $this;
    }

    public function getTestDataMarker(): ?bool
    {
        return $this->testDataMarker;
    }

    public function setTestDataMarker(?bool $testDataMarker): self
    {
        $this->testDataMarker = $testDataMarker;
        return $this;
    }

    public function getData(): ?string
    {
        return $this->data;
    }

    public function setData(?string $data): self
    {
        $this->data = $data;
        return $this;
    }
}

class Credentials 
{
    protected $user;

    protected $password;

    public function getUser(): ?string
    {
        return $this->user;
    }

    public function setUser(?string $user): self
    {
        $this->user = $user;
        return $this;
    }

    public function getPassword(): ?string
    {
        return $this->password;
    }

    public function setPassword(?string $password): self
    {
        $this->password = $password;
        return $this;
    }
}

Это простой объект значения PHP с методами получения и установки для свойств класса. Свойства точно такие же, как указано в информации о структуре. Вы можете сделать это для всех структур, которые возвращает функция $client->__getTypes(). Если все типы сопоставлены с классами объектов значения PHP, клиент soap даже проанализирует ответ в сопоставленном классе php. Если сопоставление с типом ответа отсутствует, клиент soap будет анализировать ответ xml в объект stdClass PHP.

Для примера getReport нам потребуется RequestMessage и объект значения Credentials.

Следующим шагом является инициализация класса SoapClient с правильными параметрами. После инициализации нам нужно установить заголовок учетных данных, и после этого мы устанавливаем данные для нашего запроса.

try {
    $client = new SoapClient(
        'https://wasstt.infomonitor.pl/bigApi/v1/ReportOrderService/WEB-INF/wsdl/wsBigApi1v1.wsdl',
        [
            'trace' => true,
            'exception' => true,
            'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
            'soap_version' => SOAP_1_1,
            'classmap' => [
                'Credentials' => Credentials::class,
                'RequestMessage' => RequestMessage::class,
            ],
        ]
    );

    // set the credentials header
    $credentials = (new Credentials())
        ->setUser('user')
        ->setPassword('password');

    $header = new SoapHeader('http://api.big.pl/bigApi/v1/types', 'credentials', $credentials, false);
    $client->__setSoapHeaders([ $header ]);

    // set the request data
    $requestMessage = (new RequestMessage())
        ->setRequestId(1)
        ->setRequestDateTime('2020-01-15T15:00:00')
        ->setProtocol('bimo v1')
        ->setTestDataMarker(true)
        ->setData('test');

    $result = $client->getReport($requestMessage);
    var_dump($result);
} catch (SoapFault $fault) {
    var_dump($fault, $client->__getLastRequest(), __LINE__);
}

Как видите, инициализация класса SoapClient содержится в блоке try / catch. Это позволяет вам ловить ошибки. Опция трассировки позволяет получить отправленный запрос и полученный ответ xml. Опция classmap содержит типы xsd, которые мы получили от функции $client->__getTypes(). Карта классов позволяет клиенту soap сопоставлять типы с классами объектов-значений.

Как известно, для функции веб-службы getReport в качестве параметра требуется объект RequestMessage, мы используем наш RequestObject Класс объекта значения со всеми значениями, которые мы хотим передать в запросе.

Отправленный запрос xml выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ns1="http://api.big.pl/bigApi/v1/types">
    <SOAP-ENV:Header>
        <ns1:credentials>
            <user>user</user>
            <password>password</password>
        </ns1:credentials>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ns1:getReportRequest>
            <requestId>1</requestId>
            <requestDateTime>2020-01-15T15:00:00</requestDateTime>
            <protocol>bimo v1</protocol>
            <testDataMarker>true</testDataMarker>
            <data>test</data>
        </ns1:getReportRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Этот xml был автоматически сгенерирован SoapClient класс. В конечном итоге этот запрос приводит к ошибке аутентификации, поскольку я не знаю ваших учетных данных. Но теперь вы знаете, как отправлять и получать данные с php нативными PHP классами без записи xml.

Надеюсь, это вам немного помогло.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...