简体   繁体   中英

How to create soap request and send XML to the WSDL then receive back the response in XML?

I'm creating an integration via API. Basically what I have to do is create soap request and send XML to the WSDL then receive back the response also in XML so I can parse it later.

The problem for me is... how to start because I don't know the soap request rules and it's hard to me to find good resource of knowledge which may help in my case. If you have one, please paste me the link so I can read about it (already checked PHP manual SoapClient but it's magic to me right now).

What I have since now is creating an object via SoapClient class parsing URL to the WSDL:

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

I've also used the __getFunctions() method so i can see the functions inside:

print_r($soap->__getFunctions()); 

In the result of above code I got an array with functions, here is how it looks:

(

[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)

)

In this moment it seems that there is a light in the tunnel because there is a function getReport which I should call, but the problem is how? I know that there is a __soapCall (php manual):

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

But i can't figure out what and how i should do the next step.

@edited

I've tried in different way and did:

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

And i received messege below:

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

Soap requests with PHP are actually quite simple if you follow the web standard. The PHP SoapClient class is designed for doing the whole xml stuff for you. If you only work with objects that are derived from the WSDL file, it becomes pretty easy.

You are on the right way. The first step should be that you determine the functions and data types from the WSDL file. You 'Ve done that already with the $client->__getFunctions() and $client->__getTypes() function.

ResponseMessage getReport(RequestMessage $getReportRequest)

This gives the following information. If you want to call the getReport function of the web service, you must use the RequestMessage object in the request and receive the ResponseMessage object as a response. So where do we get this methods? This informations are written in the linked XSD file or you can use the $client->__getTypes() function as well. This will give us the following informations.

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;
}

We can translate a struct into a PHP class. This class is a so-called value object.

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;
    }
}

This is a simple PHP value object with getters and setters for the class properties. The properties are exactly the same as stated out in the struct information. You can do this for all structs the $client->__getTypes() function returns. If all types are mapped to PHP value object classes the soap client will even parse a response in a mapped php class. If there 's no mapping to a response type, the soap client will parse the xml response into a stdClass PHP object.

For the getReport example we need the RequestMessage and the Credentials value object.

The next step is initializing the SoapClient class with the right option parameters. After initialization we need to set the credentials header and after that we set the data for our request.

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__);
}

As you can see, the initialization of the SoapClient class is contained in a try / catch block. This enables you to catch errors. The trace option enables you to get the sent request and the received response xml. The classmap option contains the xsd types that we 've got from the $client->__getTypes() function. The classmap enables the soap client to map the types to your value object classes.

As we know, that the getReport webservice function needs a RequestMessage object as parameter, we use our RequestObject value object class with all the values we want to submit in the request.

The sent xml request looks as follows:

<?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>

This xml was automatically generated by the SoapClient class. Ultimately, this request results in an authentication error because I do not know your credentials. But now you know, how to send and receive data with php native PHP classes without writing any xml.

Hope this helped you a bit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM