I have using a version of GoCardless's API in PHP to process payments on my website. However when their API returns an error I would like to display the user more effective errors.
I have got half way there but I was wondering if there is anyway I could do the following:
If I have the following error:
Array ( [error] => Array ( [0] => The resource has already been confirmed ) )
Is there anyway to extract just the The resource has already been confirmed part with PHP?
My Code:
try{
$confirmed_resource = GoCardless::confirm_resource($confirm_params);
}catch(GoCardless_ApiException $e){
$err = 1;
print '<h2>Payment Error</h2>
<p>Server Returned : <code>' . $e->getMessage() . '</code></p>';
}
Thanks.
UPDATE 1:
Code that triggers the exception:
$http_response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_response_code < 200 || $http_response_code > 300) {
// Create a string
$message = print_r(json_decode($result, true), true);
// Throw an exception with the error message
throw new GoCardless_ApiException($message, $http_response_code);
}
UPDATE 2 :-> print_r($e->getMessage()) Output:
Array ( [error] => Array ( [0] => The resource has already been confirmed ) )
The method $e->getMessage() appears to return an array with an index 'error' wich is an array again that contains the message text. If you ask me this is bad API design
However you can access the message text like this:
try{
$confirmed_resource = GoCardless::confirm_resource($confirm_params);
}catch(GoCardless_ApiException $e){
$err = 1;
$message = $e->getMessage();
$error = $message['error'];
print '<h2>Payment Error</h2>
<p>Server Returned : <code><' . $error[0] . "</code></p>";
}
If you look into the GoCardless_ApiException class code you'll see that there's a getResponse() method that you could use to access the error element of the response array...
$try{
$confirmed_resource = GoCardless::confirm_resource($confirm_params);
}catch(GoCardless_ApiException $e){
$err = 1;
$response = $e->getResponse();
print '<h2>Payment Error</h2>
<p>Server Returned : <code>' . $response['error'][0] . "</code></p>";
}
I discovered the problem, the output from $e->getMessage() was a plain string, NOT an array.
So I edited the Request.php file to the following:
$http_response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_response_code < 200 || $http_response_code > 300) {
// Create a string <<-- THE PROBLEM -->>
// $message = print_r(json_decode($result, true), true);
$message_test = json_decode($result, true);
// Throw an exception with the error message
// OLD - throw new GoCardless_ApiException($message, $http_response_code);
throw new GoCardless_ApiException($message_test[error][0], $http_response_code);
}
and then my php file :
try{
$confirmed_resource = GoCardless::confirm_resource($confirm_params);
}catch(GoCardless_ApiException $e){
$err = 1;
$message = $e->getMessage();
print '<h2>Payment Error</h2>
<p>Server Returned : <code>' . $message . "</code></p>";
}
and the page outputs:
Payment Error
Server Returned : The resource has already been confirmed
Related
I am trying to process a credit card (Bambora/Beanstream), and when there is an error, pick out the response code and message out of the Exception array. Here is my code:
try {
$result = $beanstream->payments()->makeCardPayment($payment_data, TRUE);
} catch (\Beanstream\Exception $e) {
//handle exception
print_r($e);
}
The error exception output ($e) begins with:
Beanstream\ApiException Object ( [_message:protected] => Invalid Card
Number [_code:protected] => 52 [message:protected] => Invalid Card
Number [string:Exception:private] => [code:protected] => 52...
I am simply trying to store "message" and "code" into variables. Thank you.
It looks like an object, not like an array.
Just try to get values from the object:
$message = $e->getMessage();
$code = $e->getCode();
When an error occured, an exception is thrown.
Exception are objects and their structures are explained in php documentation
try {
$result = $beanstream->payments()->makeCardPayment($payment_data, TRUE);
} catch (\Beanstream\Exception $e) {
//handle exception
$message = $e->getMessage();
$code = $e->getCode();
}
I am working on an app that does ETH/BTC arbitrage trading of crypto-currency using ccxt crypto API for PHP, and i keep receiving this Network Error exception thrown from the API call usually while trying to place a limit buy order.
{"status":-124,"error_message":"Enter the size in units of 0.0000001 ETH.","data":null}
This above exception is thrown from Bitflyer exchange.
My code is as follows:
$name = '\\ccxt\\'.$exchangeId;
$exchange = new $name(array (
'apiKey' => $api_key, // ←------------ replace with your keys
'secret' => $secret_key,
'enableRateLimit' => true,
));
try{
$symbol = 'ETH/BTC';
$type = 'limit'; // # or 'market', or 'Stop' or 'StopLimit'
$side = 'buy'; // 'sell' or 'buy'
$amount = $data['trade_base_amount']; //0.0515996
$price = $data['exchange_rate']; // 0.01938
// extra params and overrides
$params = array();
$response = $exchange->create_order($symbol, $type, $side, $amount, $price, $params);
print_r($response);
}catch (\ccxt\NetworkError $e) {
echo $exchange->id . ' fetch_trades failed due to a network error: '.$e->getMessage () . "\n";
}catch (\ccxt\ExchangeError $e) {
echo $exchange->id . ' fetch_trades failed due to exchange error: ' .$e->getMessage () . "\n";
}catch (\Exception $e) {
echo $exchange->id . ' fetch_trades failed with: ' . $e->getMessage () . "\n";
}
Can anyone please explain why am I getting this error?
Thanks in advance.
Try using amountToPrecision for me worked
get the documentation on CCXT
We are attempting to call a function OrderInteractive() defined by a wsdl at https://demo2.mvrs.com/AdrConnect/AdrConnectWebService.svc?singlewsdl. It takes two parameters, a communications block with login info, and an order block with data in it. I know the login info is correct, and we are getting a response from the service, but it gives us the default "unknown error has occurred" message. When checking the result of __getLastRequest(), we get this:
<ns1:OrderInteractive>
<ns1:inCommunications>
<Communications>
<Host>Online</Host>
<Account>xxxxx</Account>
<UserID>01</UserID>
<Password>xxxxxxxxx</Password>
<ReportTypes>
<Type>XML2.02</Type>
</ReportTypes>
</Communications>
</ns1:inCommunications>
<ns1:inOrder/>
</ns1:OrderInteractive>
If you look, the order parameter is just empty. My question is why is SOAP stripping the order block, or why is the order block empty? I also tried 2 other methods of calling the function but both result in this logged in my error log:
"The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation 'OrderInteractive'. End element 'Body' from namespace 'http://schemas.xmlsoap.org/soap/envelope/' expected. Found element 'InOrder' from namespace ''. Line 2, position 185."
My code is below:
$commsBlock = "<Communications>
<Host>Online</Host>
<Account>xxxxx</Account>
<UserID>01</UserID>
<Password>xxxxxxxxx</Password>
<ReportTypes>
<Type>XML2.02</Type>
</ReportTypes>
</Communications>";
$orderBlock = "<Order>
<Handling>OL</Handling>
<Account>xxxxx</Account>
<ProductID>DL</ProductID>
<State>
<Abbrev>" . $order['state'] . "</Abbrev>
<Full></Full>
</State>
<Subtype>3Y</Subtype>
<Purpose>AA</Purpose>
<License>" . $order['dln'] . "</License>
<FirstName>" . $order['firstname'] . "</FirstName>
<MiddleName>" . $order['middlename'] . "</MiddleName>
<LastName>" . $order['lastname'] . "</LastName>
<DOB>
<Year>" . date('Y', $order['dob']) . "</Year>
<Month>" . date('m', $order['dob']) . "</Month>
<Day>" . date( 'd', $order['dob']) . "</Day>
</DOB>
<Misc>TEST ORDER INTERACTIVE</Misc>
</Order>";
$soap_url = 'https://demo2.mvrs.com/AdrConnect/AdrConnectWebService.svc?singlewsdl'; // test system url
$soap_params = array(
'trace' => true,
'exceptions' => true,
'cache_wsdl' => false
);
$_client = new SoapClient($soap_url, $soap_params);
$params = array("inCommunications" => $commsBlock, "inOrder" => $orderBlock);
// TRY TO SEND
try {
$_client->OrderInteractive($params); // works, but sends broken order node
//$_client->__soapCall('OrderInteractive', $params); // breaks, goes to catch
//$_client->OrderInteractive(new SoapParam($commsBlock, 'InCommunications'), new SoapParam($orderBlock, 'InOrder')); // breaks, goes to catch
} catch(SoapFault $e) {
capDebug(__FILE__, __LINE__, "Error: SoapFault:\n" . $e->getMessage(), '/tmp/SOAP_errors.log');
}
class inOrder {
function inOrder($xml) {
$this->OrderXml = $xml;
}
}
$xml_order = '<Order>
<Handling>OL</Handling>
<ProductID>DL</ProductID>
.
.
.
<Misc>TEST ORDER INTERACTIVE</Misc></Order>';
// create our order object that is needed
$order = new inOrder($xml_order);
// create our OrderInteractive parameters
$parameters = array(
"inCommunications" => $xml_communication,
"inOrder" => $order
);
try {
$xml = $_client->OrderInteractive($parameters);
} catch (Exception $e) {
print $e->getMessage() . "\n"; exit();
}
The code above worked. WSDL expecting a string and an object as params. Created a class for the order and used a string for the communications block, and we are receiving data fine.
I have a function to translate the current text string using the Free Bing translator API. I just want to make sure if anything fails or something happens with the Application ID or I go over on requests, I don't want a big error to show.
The code I have right now is:
$translate_feed = file_get_contents('http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=' . BING_APPID . '&text=' . urlencode($text) . '&from=en&to=' . $to_lan . '');
$translate = simplexml_load_string($translate_feed);
return $translate[0];
What I want to happen is if anything fails, so if I add in another character to the URL to make it invalid then I want it to just return $text so at least something shows.
Thanks!
Have you tried failing it on purpose to see what happens?
If it's an exception, just catch it and handle it...
try{
//enter code to catch
}catch(Exception $ex){
//Process the exception
}
If there is an error outputted by the function, just # to hide the error and handle the incorrect output of $translate_feed or $translate manually.
You can try failing it on purpose by simply passing an invalid URI to file_get_contents and then forcefully feed non XML or invalid XML to simplexml_load_string to see what happens.
$translate_feed = file_get_contents('http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=' . BING_APPID . '&text=' . urlencode($text) . '&from=en&to=' . $to_lan . '');
if ( $translate_feed === false )
{
echo "failed";
}
You can do like this
if(#file_get_contents("yourFilePath.txt")){
echo "success";
}
/*
It's a modified file_get_contents()
get_contents(filename, use_include_path, context, offset, maxlen)
*/
function get_contents($url, $u = false, $c = null, $o = null) {
$headers = get_headers($url);
$status = substr($headers[0], 9, 3);
if ($status == '200') {
return file_get_contents($url, $u, $c, $o);
}
return false;
}
echo get_contents('https://example.com/');
there is $http_response_header variable is being created in local scope that we can use it to check headers returned from server. Here is my implementation:
public function getData($url)
{
try {
$response = #file_get_contents($url);
if (isset($http_response_header)) {
if (!in_array('HTTP/1.1 200 OK', $http_response_header) &&
!in_array('HTTP/1.0 200 OK', $http_response_header)) {
throw new \Exception('Server did not return success header!');
}
}
return $response;
} catch (\Exception $ex) {
throw new TransportException($ex->getMessage(), $ex->getCode(), $ex);
}
}
if( !$translate_feed) return "Failed";
$translate_feed = file_get_contents('http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=' . BING_APPID . '&text=' . urlencode($text) . '&from=en&to=' . $to_lan . '');
$result=$text;
if ($translate_feed) {
$translate = simplexml_load_string($translate_feed);
if (is_array($translate)) $result=$translate[0];
}
return $result;
I am going crazy starting off with Web Services. I am trying to call the following WSDL using PHP and keep getting nowhere:
http://webservices.sabre.com/wsdl/sabreXML1.0.00/usg/SessionCreateRQ.wsdl
I found the following piece of code on the net, from someone with similar problems, but I could not get it to work either:
$soap = new SoapClient('http://webservices.sabre.com/wsdl/sabreXML1.0.00/usg/SessionCreateRQ.wsdl',
array(
'trace' => true,
'soap_version' => SOAP_1_2,
"exceptions" => 0));
$eb = new EbXmlMessage();
$sec = new Security();
$scrq = new SessionCreateRQ();
try {
$omg = $soap->SessionCreateRQ($scrq, $sec,$eb);
}
catch (Exception $e)
{
print_r($e);
}
//debug
print "Request: \n".
htmlspecialchars($soap->__getLastRequestHeaders()) ."\n";
print "Request: \n".
htmlspecialchars($soap->__getLastRequest()) ."\n";
print "Response: \n".
$soap->__getLastResponseHeaders()."\n";
print "Response: \n".
$soap->__getLastResponse()."\n";
print_r($omg);
//the first envelope headers
class EbXmlMessage
{
public $From = array('PartyId' => 'mysite.com');
public $To = array('PartyId' => 'myprovider.com');
public $CPAId = 'ZZZZ';
public $ConversationId = 'myconv#id.com';
public $Service = 'Session';// or SessionCreate?
public $Action = 'SessionCreateRQ';
public $MessageData = array(
'MessageId' => 'messageid',
'Timestamp' => '2009-04-18T15:15:00Z');
}
//the security token
class Security {
public $Username = "xxxxx";
public $Password = "yyyyy";
public $Organization = "ZZZZ";
public $Domain = "DEFAULT";
}
//this is suppoused to be the payload, or the xml i need to send at the end
class SessionCreateRQ
{
public $POS = array(
'Source' => array(
'_'=>"",
'PseudoCityCode'=>'ZZZZ'
));
}
I keep getting the following error:
Response:
HTTP/1.1 500 Internal Server Error
SOAPAction: ""
Content-Type: text/xml;charset=utf-8
Date: Sun, 19 Apr 2009 22:21:34 GMT
Connection: close
Server: SWS
Response:
soap-env:Client.InvalidEbXmlMessageUnable to internalize
messagejavax.xml.soap.SOAPException: Unable to internalize message at
com.sun.xml.messaging.saaj.soap.MessageImpl.(MessageImpl.java:135)
at
com.sun.xml.messaging.saaj.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:32)
at
com.sabre.universalservices.gateway.control.SoapProcessor.getRequest(SoapProcessor.java:263)
at
com.sabre.universalservices.gateway.control.WSGateway.handleRequest(WSGateway.java:380)
at
com.sabre.universalservices.gateway.control.WSGateway.doPost(WSGateway.java:306)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710) at
javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
at
org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:852)
at
org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:584)
at
org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1508)
at java.lang.Thread.run(Thread.java:595) Caused by:
javax.xml.soap.SOAPException: Invalid
Content-Type:application/soap+xml at
com.sun.xml.messaging.saaj.soap.MessageImpl.verify(MessageImpl.java:159)
at
com.sun.xml.messaging.saaj.soap.MessageImpl.(MessageImpl.java:91)
... 19 more
SoapFault Object (
[message:protected] => Unable to internalize message
[string:private] => .....
This service should be validating me on the system and returning a security object to be used in later calls - a string(?) which I can then store in a session variable for the following calls.
Any help GREATLY appreciated!!!
One thing I noticed is that there is a faultcode value in the SoapFault Object:
[faultcode] => soap-env:Client.InvalidEbXmlMessage
So that may be a useful avenue to start debugging.
I tried comparing the structure of your EbXmlMessage to the XSD and the schema documentation, but I couldn't see any obvious reason that it was declared invalid.
Have you tried changing the Content-type header to text/xml?
Try using wsdl2php. It makes php classes out of the wsdl file. It uses php's SoapClient to send the data.
Here is a nice post explaining how to do it:
http://itworkarounds.blogspot.com/2011/10/simple-soap-client-with-wsdl2php-using.html
Just use nuSOAP. I don't like PHP native SoapClient. nuSoap generates for you a wsdl so you don't have to worry about how to make one.. Here's nuSOAP and here's a simple example code or you can download whole working code here :
Server :
<?php
// include the SOAP classes
require_once('nuSOAP/lib/nusoap.php');
function HelloWorld(){
return 'HelloWorld'; // Returns HelloWorld string
}
function Hello($name){
return 'Hello '.$name; // Returns Hello with name string parameter
}
// create the server object
$server = new nusoap_server();
// Initialize WSDL support
$server->configureWSDL('webservicenamespace', 'urn:webservicenamespace');
$server->register('HelloWorld', array(), array('result' => 'xsd:string')); //xsd:string; xsd:boolean; xsd:integer and so on..
$server->register('Hello', array('name' => 'xsd:string'), array('result' => 'xsd:string')); // array('parametername' => 'parametertype'),array('result' => 'returntype');
if (isset($error))
{
$fault =
$server->fault('soap:Server','',$error);
}
// send the result as a SOAP response over HTTP $HTTP_RAW_POST_DATA
$post = file_get_contents('php://input');
$server->service($post);
?>
Client :
<?php
// Pull in the NuSOAP code
require_once('nuSOAP/lib/nusoap.php');
// Create the client instance
$client = new nusoap_client('http://pathtourl/sample_webservice.php?wsdl', true);
// Check for an error
$err = $client->getError();
if ($err) {
// Display the error
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
// At this point, you know the call that follows will fail
}
// Call the SOAP method
$result = $client->call('Hello', array('name' => 'Scott')); // Call function name, parameters;
// Check for a fault
if ($client->fault) {
echo '<h2>Fault</h2><pre>';
print_r($result);
echo '</pre>';
} else {
// Check for errors
$err = $client->getError();
if ($err) {
// Display the error
echo '<h2>Error</h2><pre>' . $err . '</pre>';
} else {
// Display the result
echo '<h2>Result</h2><pre>';
print_r($result);
echo '</pre>';
}
}
// Display the request and response
echo '<h2>Request</h2>';
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2>';
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
// Display the debug messages
echo '<h2>Debug</h2>';
echo '<pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
?>
Now when you want to make a client you need your wsdl you can simply get it by adding ?wsdl on your link i.e( webservice.php?wsdl )
Hope this helps :) Good luck with your web service.