Search code examples
phpasmxsoap-client

Unable to call .NET ASMX from PHP


I have the following - currently hosted - SOAP service that was created in .NET that I'm trying to call from PHP:

POST /ExampleService/ExampleService.asmx HTTP/1.1
Host: dev.examplesite.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://localhost:51713/ExampleService.asmx/RegisterPerson"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <UserCredentials xmlns="http://localhost:51713/ExampleService.asmx">
      <UserID>string</UserID>
      <AuthKey>string</AuthKey>
    </UserCredentials>
  </soap:Header>
  <soap:Body>
    <RegisterPerson xmlns="http://localhost:51713/ExampleService.asmx">
      <requestItem>
        <RequestResult>string</RequestResult>
        <Firstname>string</Firstname>
        <Lastname>string</Lastname>
      </requestItem>
    </RegisterPerson>
  </soap:Body>
</soap:Envelope>

and I'm trying to call it using the following PHP code:

<?php
    $ns = "http://dev.examplesite.com/ExampleService/ExampleService.asmx";  
    $wsdl_url = "http://dev.examplesite.com/ExampleService/ExampleService.asmx?wsdl";
    $client = new SOAPClient($wsdl_url);

    $header = new SoapHeader(
        $ns, 
        'UserCredentials', 
        array(
            'UserID' => "1", 
            'AuthKey' => "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" 
        )
    );
    $client->__setSoapHeaders($header);

    $params = array( 
        'Firstname'  => 'John', 
        'Lastname' => 'Doe'
    );

    $client->__soapCall('RegisterPerson',$params);
?>

This however results in the following error:

Fatal error: Uncaught SoapFault exception: [soap:MustUnderstand] Missing required header 'UserCredentials'. in /home/devops1/public_html/asmxtest/register.php:43 Stack trace: #0 /home/devops1/public_html/asmxtest/register.php(43): SoapClient->__soapCall('RegisterPerso...', Array) #1 {main} thrown in /home/devops1/public_html/asmxtest/register.php on line 43

I've tried a few other methods but all met with no success. One thing that concerns me is the fact that we are reaching across over the wire to this web service which is already hosted on a testing server, and the localhost:51713 is ringing alarm bells. Should this be changed to a fully qualified domain name such as dev.examplesite.com?


Solution

  • For as easy as the SoapClient is supposed to be, I've never had success w/ it. In just about every case we have rolled our own process, which always seemed to work better.

    Example:

    // set our headers to pass in cURL
    $headers = array(
        'Content-type: text/xml;charset="utf-8"',
        'Accept: text/xml',
        'Cache-Control: no-cache',
        'Pragma: no-cache',
        'SOAPAction: ' . $action,
        'Content-length: '.strlen($soap)
     );
    
     // initiate cURL
     try {
        $_ch = curl_init();
        curl_setopt($_ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($_ch, CURLOPT_URL, WEB_SERVICE_URL);
        curl_setopt($_ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($_ch, USERPWD, USER_ID . ":" . PASSWORD);
        curl_setopt($_ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
        curl_setopt($_ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($_ch, CURLOPT_POST, true);
        curl_setopt($_ch, CURLOPT_POSTFIELDS, $soap);
        curl_setopt($_ch, CURLOPT_HTTPHEADER, $headers);
    
        // process the request and get the result back
        $response = curl_exec($_ch);
        curl_close($_ch);
        return $response;
     } catch (Exception $e) {
        capDebug(__FILE__, __LINE__, "Error calling the web service: " . $e->getMessage(), "/tmp/errors.log");
        return false;
     }
    

    We've had to massage the data afterwards, but it always works!