Forum Moderators: coopster

Message Too Old, No Replies

SOAP client in PHP

         

optik

5:20 pm on Feb 17, 2009 (gmt 0)

10+ Year Member



Hi

I have installed the PHP 5 SOAP extension and am trying to get a test working.

<?php

$client = new SoapClient("http://www50example.com/vbfacileinpt/np.asmx?wsdl");

$client->__soapCall("GetPrimeNumbers", array("5"));

echo "REQUEST:\n" . $client->__getLastRequest() . "\n";

?>

I have check the sevrice is workign and it is fine but I get the following error:

Fatal error: Uncaught SoapFault exception: [soap:Server] System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.ArgumentOutOfRangeException: Length cannot be less than zero. Parameter name: length at System.String.Substring(Int32 startIndex, Int32 length) at PrimeNumbers.PrimeNumbers.npr(Int64 inf) at PrimeNumbers.PrimeNumbers.GetPrimeNumbers(Int32 max) --- End of inner exception stack trace --- in /home/devsxtr/public_html/d_soap.php:7 Stack trace: #0 /home/devsxtr/public_html/d_soap.php(7): SoapClient->__soapCall('GetPrimeNumbers', Array) #1 {main} thrown in /home/devsxtr/public_html/d_soap.php on line 7

Not really sure what to make of that?

[edited by: eelixduppy at 6:35 pm (utc) on Feb. 17, 2009]
[edit reason] exemplified [/edit]

Little_G

5:58 pm on Feb 17, 2009 (gmt 0)

10+ Year Member



Hi,

Try this:

class GetPrimeNumbers{
public $max = 5;
};
$client = new SoapClient("http://www50.example.com/vbfacileinpt/np.asmx?wsdl");
$response = $client->GetPrimeNumbers(new GetPrimeNumbers());
echo $response->GetPrimeNumbersResult;

I defined a class to recreate the Soap structure, and also used a nice feature of the extension of mapping operations defined in the wsdl to methods of the SoapClient object (so you can call $client->GetPrimeNumbers()).

Andrew

[edited by: eelixduppy at 6:35 pm (utc) on Feb. 17, 2009]
[edit reason] example.com [/edit]

optik

11:09 pm on Feb 17, 2009 (gmt 0)

10+ Year Member



Thanks that worked although it looks like I have asked the wrong question!

This test SOAP request uses a function is that right?

The server I actually want to connect to doesn't seem to require a function

You can see it's format here

[soapclient.com...]

Little_G

2:17 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

You an see the functions that are available from the service by calling __getFunctions(), example

$client = new SoapClient("https://www.example.com/java-bin/services/SECCardService?wsdl");
echo '<pre>';
var_dump($client->__getFunctions());
echo '</pre>';

Andrew

optik

5:59 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Thanks again Andrew that has worked, I also had to install the OpenSSL PHP extension as the connection is over HTTPS.

Going back to your fist example


class GetPrimeNumbers{
public $max = 5;
};
$client = new SoapClient("http://www50.example.com/vbfacileinpt/np.asmx?wsdl");
$response = $client->GetPrimeNumbers(new GetPrimeNumbers());
echo $response->GetPrimeNumbersResult;

I'm not clear where the variable name $max and the function GetPrimeNumbersResult have come from?

When it comes to the service I am accessing I will need to change these but I don't know where to find the right function and variable name, there were no clues from the getFucntions command.

Little_G

7:34 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

Unfortunately the service has defined operations and datatypes with the same or similar names which is a little ambiguous and makes understanding what it wants more difficult.
GetPrimeNumbersResult isn't a method but a property of the return value (which is an object), if you call var_dump on $response you can see it's structure.
If you call the __getTypes() method then you can see the types that the service defines, in this case:

struct GetPrimeNumbers { 
int max;
}
struct GetPrimeNumbersResponse {
string GetPrimeNumbersResult;
}

I created a GetPrimeNumbers class to represent the first structure, the soap extension creates a generic object to represent the second, which, as you can see, has a property called GetPrimeNumbersResult.

Andrew

optik

7:52 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Thanks that has solved that mystery, unfortunately when I run __getTypes on the service I'm trying to access it returns

array(0) {
}

So I suppose I won't be able to make the call using your initial suggestion.

I've gone back to my original method of using __soapCall and this at least connecting now due to openSSL being installed but I'm not getting a response back from the service.

The relevant info I got back from doing __getFunctions() was

array(8) {

[4]=>
string(265) "string validateCardFull(string $mid, string $vpn_pswd, string $trans_id, string $ip, string $name, string $card_number, string $amount, string $expiry_date, string $issue_number, string $start_date, string $order, string $shipping, string $billing, string $options)"

}

I've omitted the arrays that I don't want to use but they are of similar make up.

I've also tried this format to no avail $client->validateCardFull("", "","","","","","","","","","","","",""));

Little_G

8:59 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

The reason __getTypes() returns nothing is because the service doesn't define any complex datatypes, the function you mention for example only uses strings.
You say the function fails, does it return an error?

Andrew

optik

9:19 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



I'm trying

<?php

$client = new SoapClient("https://www.example.com/java-bin/services/SECCardService?wsdl", array('trace' => 1));

$client->validateCardFull("", "","","","","","","","","","","","","");

echo "REQUEST:\n" . $client->__getLastResponse() . "\n";

?>

At the moment and it just returns "REQUEST:"

I've also tried __getLastRequest and the same thing happens.

EDIT: __getLastRequest is working

[edited by: eelixduppy at 10:44 pm (utc) on Feb. 18, 2009]

optik

9:31 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



It seems like I have to include the parameter name as well as the value for each string but I'm unsure how to do this

optik

9:39 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



I've tried this format and it also doesn't work.

$client->__soapCall("validateCardFull",array('order'=>"",'shipping'=>"",'billing'=>"",'options'=>""...etc ));

Little_G

9:48 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

Try creating an associative array and sending to to the mapped method, it sometimes behaves differently, for example:

$params = array('mid' => '', 'vpn_pswd' => '');
$response = $client->validateCardFull($params);

Andrew

optik

9:56 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Just tried that and no joy, I'm wondering if I need to be sending the request from a secure site, the request is to a secure server.

Little_G

10:04 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

That won't make any difference, is the $response variable simply null after the call?

Andrew

optik

10:11 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



It's returns noting not even null, this is what I'm testing.

<?php

$client = new SoapClient("https://www.example.com/java-bin/services/SECCardService?wsdl");

$params = array('mid'=>"",'vpn_pswd'=>"",'trans_id'=>"",'ip'=>"",'name'=>"",'card_number'=>"", 'amount'=>"",'expiry_date'=>"",'issue_number'=>"",'start_date'=>"",'order'=>"",'shipping'=>"",'billing'=>"",'options'=>"");

$response = $client->validateCardFull($params);

echo $response ;

?>

I've also tried the same with values included.

[edited by: eelixduppy at 10:45 pm (utc) on Feb. 18, 2009]

[edited by: coopster at 7:31 pm (utc) on Feb. 19, 2009]
[edit reason] fixed sidescroll [/edit]

Little_G

10:19 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

When I run that code I get a Notice: Array to string conversion in... message, it looks as if the method is expecting 14 string arguments after all.

Andrew

optik

10:28 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



That's strange I'm not getting the response back..

What response do you get for

<?php

$client = new SoapClient("https://www.example.com/java-bin/services/SECCardService?wsdl");

$params='mid="",vpn_pswd="",trans_id="",ip="",name="",card_number="",amount="",expiry_date="",issue_number="",
start_date="",order="",shipping="",billing="",options=""';

$response = $client->validateCardFull($params);

echo $response ;

?>

[edited by: eelixduppy at 10:45 pm (utc) on Feb. 18, 2009]

[edited by: coopster at 7:32 pm (utc) on Feb. 19, 2009]
[edit reason] fixed sidescroll [/edit]

Little_G

10:35 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

I'm getting null, is it working for you now then?

Andrew

optik

10:39 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



No still not working, it looks like it should be formed like this though

<?php

$client = new SoapClient("https://www.example.com/java-bin/services/SECCardService?wsdl");

$params ='"", "","","","","","","","","","","","",""';

$response = $client->validateCardFull($params);

echo $response ;

?>

Do you get null from that as well?

[edited by: eelixduppy at 10:45 pm (utc) on Feb. 18, 2009]

Little_G

10:59 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

Yes I do, I'm pretty certain the method doesn't want all the arguments as one string but instead as 14 separate ones (not that that works either). Does the service provider provide any documentation/instructions for the service?

Andrew

optik

11:12 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Unfortunately not for PHP

They have this for C# which shows the format should be a lisy of strings..

public class SECPaySoapClient
{

/// <summary>
/// This method will run a test SOAP transaction through
/// the SECPay system using the SECPay test account.
/// </summary>
public static void Main()
{
SECVPNService secVpnService = new SECVPNService();

string response = secVpnService.validateCardFull(
"secpay",
"secpay",
"tran0001",
"127.0.0.1",
"Mr Cardholder",
"4444333322221111",
"50.00",
"0105",
"",
"",
"",
"",
"",
"name=Fred+Bloggs,company=Online+Shop+Ltd,addr_1=Dotcom+House, addr_2=London+Road,city=Townville,state=Countyshire, post_code=AB1+C23,tel=01234+567+890,fax=09876+543+210 ,email=somebody%40example.com,url=http%3A%2F%2Fwww.example.com,test_status=true,dups=false, card_type=Visa");

Console.Out.WriteLine("Soap Returned: " + response);

}
}

[edited by: eelixduppy at 12:13 am (utc) on Feb. 19, 2009]

Little_G

11:14 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Hi,

OK, I found the documentation, and by looking at their Java example I tried this:

$client = new SoapClient("https://www.example.com/java-bin/services/SECCardService?wsdl");
$response = $client->validateCardFull("secpay",
"secpay",
"TRAN0001",
"127.0.0.1",
"Mr Cardholder",
"4444333322221111",
"50.00",
"0105",
"",
"",
"",
"",
"name=Fred+Bloggs,company=Online+Shop+Ltd,addr_1=Dotcom+House,addr_2=London+Road,[/pre][pre]city=Townville,state=Countyshire,post_code=AB1+C23,tel=01234+567+890,fax=09876+543+210,[/pre][pre]email=somebody%40example.com,url=http%3A%2F%2Fwww.example.com",
"test_status=true,dups=false,card_type=Visa"
);
var_dump($response);

and it worked!

Andrew

[edited by: Little_G at 11:18 pm (utc) on Feb. 18, 2009]

optik

11:47 pm on Feb 18, 2009 (gmt 0)

10+ Year Member



Great stuff! That worked, thanks so much for your thorough help, it seems var_dump($response); is allowing to see the response unlike __getLastResponse
which is a bit odd but I don't really care now, thanks again.

optik

12:03 am on Feb 19, 2009 (gmt 0)

10+ Year Member



__getLastResponse is actually working for me with array('trace' => 1));
on the end of $client = new SoapClient("https://www.example.com/java-bin/services/SECCardService?wsdl");

I had tried this but probably in combination with the array structure.

Little_G

12:17 am on Feb 19, 2009 (gmt 0)

10+ Year Member



Glad it worked in the end!

Andrew