I am looking for some advices and exmaples. Since now I havent seen trouble consuming SOAP services with PHP.
A third party has developed a service, they provided me a file with the WSDL and all the needed XSD schemas. But since their service URL has this look : https://webservice.com/xml_listen.cgi I am really struggling how to approach it.
I have tried the basic stuff that I have used until this moment about the previous services that I have consumed like:
$client = new SoapClient(array(
'location' => "https://webservice.com/xml_listen.cgi",
'uri' => "https://webservice.com/xml_listen.cgi",
'trace' => 1 ));
$return = $client->__soapCall("SomeFuncion",array());
var_dump($return);
I am hoping to find a way how to consume this kind of non WSDL services.
Thank you in advance!
Related
Our iOS app should receive push notification. Following this tutorial I implemented these methods in application delegate:
didRegisterForRemoteNotificationsWithDeviceToken
and
didFailToRegisterForRemoteNotificationsWithError
which are called by didFinishLaunchingWithOptions and it seems that the device is correctly registered in our MySQL service. Moreover, I have just created a pem sandbox certification that I will use for testing. Now, I need to know what I should do at the backend in PHP. Which code is required? We are using Zend framework so I should implement function preparetosend_apple()in my mapper and sendtoappleAction() in our controller but I don't know where to start from and how to test it. Thank you!
First thing is sending push notification directly from application is not a good idea as this call can be blocking one (means the rest of the codeblock will wait for its completion). So I suggest using background processor/message queuing services (like gearman, zero mq, etc.).
Secondly easiest solution will be using Parse like services. Parse allows registering the app using the certificates you mentioned and has SDK for php (composer based).
In the background service you just call the API from SDK. Like:
use Parse\ParseClient;
use Parse\ParseInstallation;
use Parse\ParsePush;
ParseClient::initialize($appId, $restKey, $masterKey, $curlDebug);
...
...
...
Using channel in parse
$response = ParsePush::send(array(
"channels" => ["channel-$userId"],
"data" => $data,
));
OR using custom query
$query = ParseInstallation::query();
$query->equalTo('userId', "user-$userId");
$response = ParsePush::send(array(
"where" => $query,
"data" => $data,
));
The best part of using parse - I will say using other interesting features like -- broadcast messages, device listings, etc.
Hope this may help you.
I am using the Braintree PHP Client which relies heavily on static methods.
All my endpoints in this project are covered with integration tests
Something like:
Storage::shouldReceive('put')->once()->andReturn(true);
$this->post('/api/payment');
As you can see I'm also using Mockery in order to create mocks. However since the Braintree library is heavily relying on static methods, I'm not able to create methods, thus not able to test these endpoints.
Here's an example of a code written using the Braintree PHP Client:
$result = Braintree\Transaction::sale([
'amount' => '1000.00',
'paymentMethodNonce' => 'nonceFromTheClient',
'options' => [ 'submitForSettlement' => true ]
]);
What options do I have here?
this answer will only work if you got mockery 1.* installed.. earlier versions won't do static method mocking. The below code works:
$brainTreeMock = Mockery::mock('alias:Braintree_Transaction');
$transaction = (object)[ 'id' => str_random(5) ];
$brainTreeMock->shouldReceive('sale')->andReturn((object)[
'success' => true,
'transaction' => $transaction
]
);
Mocking one of the components during integration tests should be done with great care, as it defeats the purpose.
I believe Braintree provides a sanbox for integration testing, so there is no need to mock it.
You can use an alias mock to mock public static method calls. You would use it like this:
$classMock = Mockery::mock('alias:NamespaceToClass\ClassName');
$classMock->shouldReceive('someMethod')->once()->andReturn('Something');
Usually I would advocate mocking the responses from an API instead of making calls to it when running integration tests.
However, I contacted Braintree and they said (at time of writing) that it's ok to run the tests vs the sandbox as long as you don't exceed 25 concurrent requests per second.
Could you tell me if there is a tool to generate a soap client with these requirements:
soap 1.2
the client is based on three different service (so 3 wsdl)
those services have shared types
I found out about:
http://php.net/manual/en/class.soapclient.php
and
http://www.php.net/manual/en/soapclient.soapclient.php
The thing I can't find out searching for it is especially the last two point.
Any help will be appreciated because I can't unserstand how to create it from different sources and how to call a specific service.
I can't test my solution as i don't have 2-3 web services running, but i think this solution will work (if i understood you correctly). Please if you can try it and let me know.
<?php
class wstest {
function __construct($url) {
$this->soapUrl = $url;
try{
$this->client = new SoapClient($this->soapUrl,array('login' => 'wsuser', 'password' => "some_password", "connection_timeout"=>30,'trace'=>true,'keep_alive'=>false,'features' => SOAP_SINGLE_ELEMENT_ARRAYS));
} catch (Exception $e) {
echo $e->getMessage();
}
}
};
$con = new wstest("http://firstwebservice.com/?wsdl");
$con2 = new wstest("http://secondwebservice.com/?wsdl");
$con3 = new wstest("http://thirdwebservice.com/?wsdl");
?>
I'm trying to figure out what you might want to do.
First: One WSDL === one Service === one SoapClient. You cannot mix two WSDL locations on the Soap client level, but depending on your application, might connect each services' results on a higher level.
So if you have three WSDL, then you must instantiate three SoapClient classes to be used. It's not like a single generic HTTP Client which can make requests to any existing webserver.
Second: Unless you provide a classmap to the SoapClient, the return value of any request is only a mixture of stdClass and array. There might be types defined in the WSDL, but PHP does not map them to anything unless you define it.
I would recommend using a classmap with your own defined classes that match the ComplexType definitions in the WSDL. There are some code generators to be googled that might do the job, but the Soap standard is complex, as is the definitionof WSDL, so you might end up doing work by hand.
You can perfectly live without a classmap if the data structures are small.
Third: If the three WSDL share data types, this will not affect PHP in any way. Since without classmap the responses are stdClass and Array, and the Request parameters can be the same, you won't get any benefit from this information.
If on the other hand you go the way of the classmap, I'd expect that the shared types will lead to the same classes generated, so you would also see on the PHP level that a ComplexType from Service A is identical to the ComplexType of Service B.
I received a manual to internal SOAP interface of my partner. It says:
MyPARTNER web services are provided in the form of a SOAP interface. The service is available in this URL: https://justsomeurl.com:435/soap
then some bla bla about authorization etc. and then a part about Accessible Methods:
pull()
The PULL method is used for pulling data from the database. The method
receives a unique data based parameter under an internal name
requestXML. This parameter contains data in a structured XML format.
String pull(String requestXML)
The XML contains data required to make the request, and the response
data is sent back.
then some other methods, error codes, it's not important here...
The problem is that I'm totally unexperienced in SOAP so I don't know how to use this interface via PHP. I've tried to find some examples, tutorials and I am now little bit more informed about SOAP and its functionality but still haven't found any advice about how to use interface like this...
thanx for any help
Php comes with PHP SOAP libraries, that usually are included and enabled after a common php installation.
Yuo are asked to biuld the client part of the webservice pattern. Your partner should provide you the .wsdl of the web service. The wsdl describes the avialble method, the parameters they need and what they return.
Tipically parameters and return values are array structures
This could be a skeleton for your code:
//build a client for the service
$client = new SoapClient("partner.wsdl");
//$client is now a sort of object where you can call functions
//prepare the xml parameter
$requestXML = array("parameter" => "<xml>Hello</xml>");
//call the pull function this is like
$result = $client->__soapCall("pull", $requestXML );
//print the value returned by the web service
print_r($result);
Here follows a non-wsdl example
First the location paramater is the address the SOAP request will be sent to.
The uri parameter is the target namespace of the SOAP service. This is related to xml namespaces.
A sample code for you could be:
//for URI specification you should watch your partners documentation. maybe also a fake uri (like mine) could work
//build a client for the service
$client = new SoapClient(null, array(
'location' =>
"https://justsomeurl.com:435/soap",
'uri' => "urn:WebServices",
'trace' => 1 ));
// Once built a non-wsdl web service works as a wsdl one
//$client is now a sort of object where you can call functions
//prepare the xml parameter
$requestXML = array("parameter" => "<xml>Hello</xml>");
//call the pull function this is like
$result = $client->__soapCall("pull", $requestXML );
//print the value returned by the web service
print_r($result);
Here a useful link: http://www.herongyang.com/PHP/SOAP-Use-SOAP-Extension-in-non-WSDL-Mode.html
I am consuming a third-party webservice and I'm using soapUI to test it. I was advised to load the WSDL, leave it untouchted, then change the endpoint in SOAPUI before executing the calls to the endpoints. This works fine and is behaving as I would expect it to.
I'm now trying to emulate this in PHP but I'm having problems changing the endpoint. I'm loading the WSDL into SOAPCLIENT and then using this command to change the endpoint:
$client->__setLocation($endpointURI);
However this is not acting like I'd expect it to and is giving me a "500:Internal Server Error" response when I the go to make a soap call after modifying the location/endpoint. I'm certain that all other parameters are correct and was wondering if anyone could shed some light on the issue and confirm that doing this 'set location' cmd should be the equivalent of changing the endpoint manually in SOAPUI.
Any ideas/opinions appreciated.
While instantiating SoapClient try to add an array key named 'location' with the new endpoint.
$options = array('login' => 'x', 'password' => 'y', 'location' => $endpointURI);
$client = new SoapClient($address, $options);
Try calling __soapCall with the location override in there:
$result = $this->soap_client->__soapCall('whatever', ['location' => $file_location]);
I'm finding __setLocation is not working while the above workaround does.