2
// Based on http://stackoverflow.com/questions/3934639/soap-authentication-with-php
include 'auth.php';
$soapURL = "http://traindata.njtransit.com:8090/NJTTrainData.asmx?WSDL" ;
$soapParameters = array('UserCredentials'=>array('userName' => $username, 'password' => $password));

$soapFunction = "getTrainScheduleJSON" ;
$soapFunctionParameters = Array('station' => "NY") ;

$soapClient = new SoapClient($soapURL, $soapParameters);

$soapResult = $soapClient->__soapCall($soapFunction, $soapFunctionParameters);

Here is the output (below). It complains about Missing required header 'UserCredentials', but I have UserCredentials included. Or am I missing something? Thanks!

PHP Fatal error:  Uncaught SoapFault exception: [soap:MustUnderstand] System.Web.Services.Protocols.SoapHeaderException: Missing required header 'UserCredentials'.
   at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
   at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest() in /home/www/html/njtransit/wed.php:13
Stack trace:
#0 /home/www/html/njtransit/wed.php(13): SoapClient->__soapCall('getTrainSchedul...', Array)
#1 {main}
  thrown in /home/www/html/njtransit/wed.php on line 13

Here is another attempt adding SoapHeader before the __setSoapHeaders. I also added namespace ($ns):

include 'auth.php';
$soapURL = "http://traindata.njtransit.com:8090/NJTTrainData.asmx?WSDL" ;
$ns = 'http://microsoft.com/webservices/'; //Namespace of the WS.
$soapParameters = array('UserCredentials'=>array('userName' => $username, 'password' => $password));

$soapFunction = "getTrainScheduleJSON" ;
$soapFunctionParameters = Array('station' => "NY") ;

// $soapClient = new SoapClient($soapURL, $soapParameters);
$soapClient = new SoapClient($soapURL);

$header = new SoapHeader($ns,'UserCredentials',$soapParameters,false);

$soapClient->__setSoapHeaders($header);
var_dump($soapClient);
$soapResult = $soapClient->__soapCall($soapFunction, $soapFunctionParameters);

Here is the output and the new error message is, "Object reference not set to an instance of an object."

object(SoapClient)#1 (3) {
  ["_soap_version"]=>
  int(1)
  ["sdl"]=>
  resource(5) of type (Unknown)
  ["__default_headers"]=>
  array(1) {
    [0]=>
    object(SoapHeader)#2 (4) {
      ["namespace"]=>
      string(33) "http://microsoft.com/webservices/"
      ["name"]=>
      string(15) "UserCredentials"
      ["data"]=>
      array(1) {
        ["UserCredentials"]=>
        array(2) {
          ["userName"]=>
          string(10) "myusername"
          ["password"]=>
          string(17) "mypassword"
        }
      }
      ["mustUnderstand"]=>
      bool(false)
    }
  }
}
PHP Fatal error:  Uncaught SoapFault exception: [soap:Server] System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at DepartureVisionServiceXMLExternal.ServiceExternal.Login(String username, String password) in C:\Users\vcaicxz\Desktop\CRYSTAL\PentaDepartureVisionServiceXMLExternaL\NJTTrainData.asmx.cs:line 55
   at DepartureVisionServiceXMLExternal.ServiceExternal.getTrainScheduleJSON(String station) in C:\Users\vcaicxz\Desktop\CRYSTAL\PentaDepartureVisionServiceXMLExternaL\NJTTrainData.asmx.cs:line 141
   --- End of inner exception stack trace --- in /home/www/html/njtransit/wed2.php:19
Stack trace:
#0 /home/www/html/njtransit/wed2.php(19): SoapClient->__soapCall('getTrainSchedul...', Array)
#1 {main}
  thrown in /home/www/html/njtransit/wed2.php on line 19
Edward
  • 9,430
  • 19
  • 48
  • 71
  • The 2nd argument of `SoapClient` concerns options, not soapheaders. [look into __setSoapHeaders()](http://www.php.net/manual/en/soapclient.setsoapheaders.php) – Wrikken Jun 12 '13 at 13:42
  • @Wrikken So I need to make more than one call? – Edward Jun 12 '13 at 21:30
  • No, you need more then 1 function/method. It's just 1 soapcall.... – Wrikken Jun 12 '13 at 21:52
  • @Wrikken Forgive me, I'm still new to SOAP with PHP. Can you provide a PHP code example of what you are referring too? You could answer the question with a PHP code example. – Edward Jun 12 '13 at 21:55
  • 1
    I would think there are examples on that page in the manual? Pastebin your best effort with that __setSoapHeaders() call & I'll see what's wrong with it tomorrow. – Wrikken Jun 12 '13 at 22:12

1 Answers1

3

You are nearly there, this line:

$header = new SoapHeader($ns,'UserCredentials',$soapParameters,false);

Already creates the UserCredentials node, so this line:

$soapParameters = array('UserCredentials'=>array('userName' => $username, 'password' => $password));

Can/Should be:

$soapParameters = array('userName' => $username, 'password' => $password);

Which gives you an empty response, because of the way you call the function, you have two possible ways:

//1. add an extra array around params
$soapClient->__soapCall($soapFunction, array($soapFunctionParameters));
//2. or call like this:
$soapClient->$soapFunction($soapFunctionParameters);

(Which still gives me an empty response, but I would think that's because I have no valid credentials, which is a thing to look out for: I would expect a soaperror/soapfault, but apparently this service does not generate them on bad credentials).

Wrikken
  • 69,272
  • 8
  • 97
  • 136
  • I tried this and it worked!!! It was the additional UserCredentials in soapParameters that was the main problem preventing it from allowing a correct login. This seems so odd to me, because I'm sure I saw numerous examples of SOAP login's being done this way. Thanks again for taking the time to look this over and offer a workable solution and returning the next day to solve this as you promised. – Edward Jun 13 '13 at 19:44
  • Also: $data_ny = $soapClient->getTrainScheduleJSON(array('station' => $station)); did the trick. But I like the way you did $soapClient->$soapFunction($soapFunctionParameters); and will change it to that. – Edward Jun 13 '13 at 19:48