I need to implement a gateway in php that receives calls in SOAP.
The WSDL of the web service is not very complicated. Next I expose an extract of the same one.
<portType name="DeliveryNotification">
<operation name="notifyDelivery" parameterOrder="parameters platformHeader">
<input message="tns:notifyDelivery"/>
<output message="tns:notifyDeliveryResponse"/>
</operation>
</portType>
<binding name="DeliveryNotificationPortBinding" type="tns:DeliveryNotification">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="notifyDelivery">
<soap:operation soapAction="notifyDelivery"/>
<input>
<soap:body use="literal" parts="parameters"/>
<soap:header message="tns:notifyDelivery" part="platformHeader" use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="DeliveryNotificationService">
<port name="DeliveryNotificationPortBinding" binding="tns:DeliveryNotificationPortBinding">
<soap:address location="http://localhost:8888/soapTest/outbound-test.php"/>
</port>
</service>
The script that processes the service execution request is very simple. I use a separate class to handle this operation and the following:
$server = new Gateway\Debug\DebugSoapServer(OUTBOUND_API_WSDL, array(
'soap_version' => SOAP_1_2
));
$server->setObject(new Gateway\Handlers\OutboundHandlerDecorator(new Gateway\Handlers\OutboundHandler()));
try {
$server->handle();
} catch (Exception $e) {
$server->fault('Sender', $e->getMessage());
}
OutboundHandlerDecorator would act as a proxy to validate access and then delegate to the final handler to process the response.
next I expose its definition:
class OutboundHandlerDecorator
{
private $decorated = null;
public function __construct(OutboundHandler $decorated)
{
$this->decorated = $decorated;
}
public function __call($method, $params)
{
global $methodCalled;
$methodCalled = $method;
if (method_exists($this->decorated, $method)) {
return call_user_func_array(
array($this->decorated, $method), $params);
} else {
throw new \BadMethodCallException();
}
}
}
My problem is the following:
I created the following SOAP message to simulate the call to the notifyDelivery service, using the SOAPUI tool. Next I expose the result:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://test.com/">
<soapenv:Header>
<ws:platformHeader>
<platformCredentials>
<password>myPassword</password>
<userId>myUser</userId>
</platformCredentials>
<platformFlags>
<retry>1</retry>
</platformFlags>
</ws:platformHeader>
</soapenv:Header>
<soapenv:Body>
<ws:notifyDelivery>
<simId>1234567891234567789</simId>
<simIdType>ICCID</simIdType>
</ws:notifyDelivery>
</soapenv:Body>
</soapenv:Envelope>
As a result I get a failed SOAP message, because the BadMethodCallException exception is thrown. Since first of all it tries to find and execute a method called "platformHeader" and for this there is no function defined in the class "OutboundHandler".
If I do not throw this exception, the notifyDelivery method of the "OutboundHandler" class will be executed correctly.
Therefore, my question is: Why does SoapServer identify the header as an operation? From SOAPUI I am configuring the SOAPAction HTTP header to "notifyDelivery". I do not understand this operation.
How could I access the header data independently? In the variable $ params I only have the data of the body of the message.
Thank you very much in advance.
regards
As you can see in this answer, In the "OutboundHandler" handler in addition to a method for each service defined in the WSDL there should also be a method for each message header and define the access control logic there. You should create a method called "platformHeader" and if the credentials are not correct throw a SoapFault exception. At the moment I will implement it in this way.
class OutboundHandler
{
/**
* Validate User Credentials
* @param $params
*/
public function platformHeader( $params ){
if(!($params->platformCredentials->password == "myPassword" && $params->platformCredentials->userId == "myUser"))
throw new \SoapFault("1", "Incorrect user, request rejected.");
}
public function notifyDelivery($params) {
// do something.
}
}