Search code examples
phpweb-servicessoapexchangewebservicesphp-ews

PHP SoapServer formatting


I am new to SOAP and trying to format a SOAP response using PHP's SoapServer class.

It might be useful to know that this is for an EWS Push Subscription callback service and that I am using the php-ews library. I have managed to subscribe to the EWS Push Subscription but am having trouble formatting the reply which EWS is expecting from my callback service.

I need the following SOAP response returned by my PHP SOAP service:

<s:Envelope xmlns:s= "http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <SendNotificationResult xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
            <SubscriptionStatus>OK</SubscriptionStatus>
        </SendNotificationResult>
    </s:Body>
</s:Envelope>

Instead I am getting the following output:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://localhost/ioc/ebooking_v4/services/ews/notification.php" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Body>
        <ns1:SendNotificationResponse>
            <return xsi:type="SOAP-ENC:Struct">
                <SubscriptionStatus xsi:type="xsd:string">OK</SubscriptionStatus>
            </return>
        </ns1:SendNotificationResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

My PHP service code:

class ewsService {
    public function SendNotification( $arg ) {
        $result = new EWSType_SendNotificationResultType();
        $result->SubscriptionStatus = 'OK';
        return $result;
    }
}

$server = new soapServer( null, array(
    'uri' => $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'],
));
$server->setObject( new ewsService() );
$server->handle();

The SOAP call to my service is as follows:

<soap11:Envelope xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
    <soap11:Header>
        <t:RequestServerVersion xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" Version="Exchange2010_SP2" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" />
    </soap11:Header>
    <soap11:Body>
        <m:SendNotification xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
            <m:ResponseMessages>
                <m:SendNotificationResponseMessage ResponseClass="Success">
                    <m:ResponseCode>NoError</m:ResponseCode>
                    <m:Notification>
                        <t:SubscriptionId>GQBjaGNpb2ExODEuY2lvLm9seW1waWMub3JnEAAAAFgvEpJcS3JDkpvHOMgnX60FhmhpPInRCA==</t:SubscriptionId>
                        <t:PreviousWatermark>AQAAAIiCiXu/q1ZPvYPyvRVVh5cajSoKAAAAAAA=</t:PreviousWatermark>
                        <t:MoreEvents>false</t:MoreEvents>
                        <t:StatusEvent>
                            <t:Watermark>AQAAAIiCiXu/q1ZPvYPyvRVVh5cajSoKAAAAAAA=</t:Watermark>
                        </t:StatusEvent>
                    </m:Notification>
                </m:SendNotificationResponseMessage>
            </m:ResponseMessages>
        </m:SendNotification>
    </soap11:Body>
</soap11:Envelope>

So I suppose my question is how do I to change the formatting of the SOAP response, using the PHP SoapServer class? Do I need to add a WSDL or pass a classmap to the SoapServer constructor?

If there is no way to do this using the SoapServer class, is there any other way to do this other than creating a string buffer and passing that back manually?

Any help would be greatly appreciated.


Solution

  • I figured this out and posted the solution on a more generic question of this problem here

    For completeness I have included the answer here as well...

    It would seem that I was close but needed to include the NotificationService.wsdl when instantiating the SoapServer class. The WSDL then allows that SoapServer class to format the response accordingly.

    $server = new SoapServer( PHPEWS_PATH.'/wsdl/NotificationService.wsdl', array(
    

    The WSDL was not included in the php-ews library download, however it is included with the Exchange Server installation. If like me you don't have access to the Exchange Server installation you can find the file here. I also had to add the following to the end of the WSDL because I was storing the WSDLs locally and not using autodiscovery:

    <wsdl:service name="NotificationServices">
        <wsdl:port name="NotificationServicePort" binding="tns:NotificationServiceBinding">
            <soap:address location="" />
        </wsdl:port>
    </wsdl:service>
    

    So the full working PHP code is as follows:

    class ewsService {
        public function SendNotification( $arg ) {
            $result = new EWSType_SendNotificationResultType();
            $result->SubscriptionStatus = 'OK';
            //$result->SubscriptionStatus = 'Unsubscribe';
            return $result;
      }
    }
    
    $server = new SoapServer( PHPEWS_PATH.'/wsdl/NotificationService.wsdl', array(
        'uri' => $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'],
    ));
    $server->setObject( $service = new ewsService() );
    $server->handle();
    

    Which gives the following output:

    <?xml version="1.0" encoding="UTF-8"?>
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.microsoft.com/exchange/services/2006/messages">
        <SOAP-ENV:Body>
            <ns1:SendNotificationResult>
                <ns1:SubscriptionStatus>OK</ns1:SubscriptionStatus>
            </ns1:SendNotificationResult>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    

    Hope that helps someone else because that took me a while to figure out!