Handling pure PHP errors in CodeIgniter - php

I have a mobile application with an API developed with CodeIgniter, and this API performs payments by Stripe.
These payments are recursive, so once a month I charge my users. But some users cannot be charged (for an example if an user has insufficient funds on his card), and in this case Stripe throws an exception.
I'd like to be able to perform a try/catch in my controller. For now I have this code :
try {
$charge = \Stripe\Charge::create(array(
"amount" => xxx,
"currency" => "eur",
"customer" => xxx)
);
} catch (Exception $e) {
// If user has insufficient funds, perfom this code
}
I recently saw that the piece of code in the catch was never executed, and I saw that CI had its own error handling system, and I could see in my logs that errors from controllers run by cli were displayed on this view : application/views/errors/cli/error_php.php. So how can I simply detect if my Stripe code returns an exception ?
Thanks in advance for any answer :)

Try using the global namespace for your exception like this:
catch (\Exception $e) //note the backslash

Please refer Stripe's API document carefully.
They have described error handling in a very detailed manner. You can read about it here: https://stripe.com/docs/api/php#error_handling
try {
// Use Stripe's library to make requests...
} catch(\Stripe\Error\Card $e) {
// Since it's a decline, \Stripe\Error\Card will be caught
$body = $e->getJsonBody();
$err = $body['error'];
print('Status is:' . $e->getHttpStatus() . "\n");
print('Type is:' . $err['type'] . "\n");
print('Code is:' . $err['code'] . "\n");
// param is '' in this case
print('Param is:' . $err['param'] . "\n");
print('Message is:' . $err['message'] . "\n");
} catch (\Stripe\Error\RateLimit $e) {
// Too many requests made to the API too quickly
} catch (\Stripe\Error\InvalidRequest $e) {
// Invalid parameters were supplied to Stripe's API
} catch (\Stripe\Error\Authentication $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
} catch (\Stripe\Error\ApiConnection $e) {
// Network communication with Stripe failed
} catch (\Stripe\Error\Base $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
}

Related

How can I prevent duplicate charge using Stripe and PHP?

Recently i got duplicated payments with Stripe.
They told me to use Idempotent Requests.
I made some tests and i see the error message if i tried to refresh the browser for example.
But i don't know how to make the "next step" in case of error.
I mean if my client make a payment and there is a network issue, how to do with Stripe to retry and continu the process or how to display an error message and came back to the payment's page ?
My code for now:
\Stripe\Stripe::setApiKey("xxxxxx");
$charge = \Stripe\Charge::create([
'customer' => $customer->id,
'amount' => $total_payment,
'currency' => $currency,
'description' => $description
], ["idempotency_key" => $idempotency,]);
$chargeJson = $charge->jsonSerialize();
$status = $chargeJson['status'];
if($status=="succeeded") {...
Thank you for your help, if you can just give me some information and then it will help me to improve my code ^^
Here is a functional demo of the try/catch with all the possible errors adding "Idempotent Requests field", just add your own functionality in each catch:
try {
// Use Stripe's library to make requests...
$charge = \Stripe\Charge::create([
'amount' => $amount,
'currency' => "usd",
'description' => $description,
"receipt_email" => $mail,
], [
'idempotency_key' => $uniqueID
]);
} catch(\Stripe\Exception\CardException $e) {
// Since it's a decline, \Stripe\Exception\CardException will be caught
echo 'Status is:' . $e->getHttpStatus() . '\n';
echo 'Type is:' . $e->getError()->type . '\n';
echo 'Code is:' . $e->getError()->code . '\n';
// param is '' in this case
echo 'Param is:' . $e->getError()->param . '\n';
echo 'Message is:' . $e->getError()->message . '\n';
} catch (\Stripe\Exception\RateLimitException $e) {
// Too many requests made to the API too quickly
} catch (\Stripe\Exception\InvalidRequestException $e) {
// Invalid parameters were supplied to Stripe's API
} catch (\Stripe\Exception\AuthenticationException $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
} catch (\Stripe\Exception\ApiConnectionException $e) {
// Network communication with Stripe failed
} catch (\Stripe\Exception\ApiErrorException $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
}

How to catch a Stripe Fatal Error in PHP?

I am spinning up an application using the Stripe.js elements. Using the test card numbers provided by Stripe, I have no issues. All works as expected.
I'm now focusing on error handling. When using the test card 4000 0000 0000 0002 to handle a card that is intentionally declined, I get this error:
Fatal error: Uncaught Stripe\Error\Card: Your card was declined. in
C:\Apache24\htdocs...\vendor\stripe\stripe-php\lib\ApiRequestor.php:128 from API request {token}....
Now I'm assuming this is not a PHP Fatal Error (which can not be handled in a try/catch block), so I searched and found this example and implemented it into my code like this:
\Stripe\Stripe::setApiKey(self::APIKEY);
$charge_arr = array(
"key" => value, etc ... )
try {
$charge = \Stripe\Charge::create($charge_arr);
if($charge->paid == true) {
echo '<br>the card was successfully charged!';
}
} catch (\Stripe\Error\Base $e) {
echo '<br>base';
echo ($e->getMessage());
} catch (\Stripe\Error\Card $e) {
$body = $e->getJsonBody();
$err = $body['error'];
print('Status is:' . $e->getHttpStatus() . "\n");
print('Type is:' . $err['type'] . "\n");
print('Code is:' . $err['code'] . "\n");
echo ($e->getMessage());
} catch (\Stripe\Error\Authentication $e) {
echo '<br>Auth';
// a good one to catch
} catch (\Stripe\Error\InvalidRequest $e) {
echo '<br>Invalid Request';
// and catch this one just in case
} catch (Exception $e) {
//catch any non-stripe exceptions
}
This does not, however, catch the error. The message continues to be displayed as it was before I had the catch block.
Any clues why I'm getting the Fatal Error? I, of course, expected the card to be declined, but I expected the result of the decline to be something I could handle in the try/catch block.
EDITS
I should add that I'm using composer to include the Stripe php libraries.
Further note: It may not be relevant, but the Fatal Error message appears for all test cards that are supposed to be declined. The reason for the decline is stated clearly in the error message for each card like (not verbatim) zip code failed validation, CVC not correct, card expired, etc.
As #Ywain rightfully notes, this actually isn't a try/catch block problem. The Fatal Error is generated by the charge transaction in the first place. In other words the call to \Stripe\Charge should return a JSON array with appropriate flags or field values, not a Fatal Error.
Stripe has many exceptions it can throw in the course of a transaction. Their API has excellent sample code to provide a template of catching the various exceptions Stripe API can throw.
try {
// Use Stripe's library to make requests...
} catch(\Stripe\Error\Card $e) {
// Since it's a decline, \Stripe\Error\Card will be caught
$body = $e->getJsonBody();
$err = $body['error'];
print('Status is:' . $e->getHttpStatus() . "\n");
print('Type is:' . $err['type'] . "\n");
print('Code is:' . $err['code'] . "\n");
// param is '' in this case
print('Param is:' . $err['param'] . "\n");
print('Message is:' . $err['message'] . "\n");
} catch (\Stripe\Error\RateLimit $e) {
// Too many requests made to the API too quickly
} catch (\Stripe\Error\InvalidRequest $e) {
// Invalid parameters were supplied to Stripe's API
} catch (\Stripe\Error\Authentication $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
} catch (\Stripe\Error\ApiConnection $e) {
// Network communication with Stripe failed
} catch (\Stripe\Error\Base $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
}
Also keep in mind that once you catch the exception, unless you do something to specifically end your script or change execution path, that your script will continue to run the rest of the code blissfully unaware there was any exception raised. Consider this overly simple example.
try {
$charge = \Stripe\Charge::create($charge_arr);
} catch (\Stripe\Error\Card $e) {
echo("I had an error!");
}
echo ("I completed Successfully");
The card is declined and the api throws \Stripe\Error\Card. You then receive the following output.
I had an error!I completed successfully
This matters if you have multiple API calls in your execution path. You could very well catch the exception thrown just to have another one thrown by a later call that you were not expecting to run. You should have all calls to the API that could raise an exception wrapped in try/catch. You will also need to pay attention to your execution path if you are expecting errors caught from earlier calls to keep other code from executing. Overly simple example.
try {
$charge = \Stripe\Charge::create($charge_arr);
$declined = false;
} catch (\Stripe\Error\Card $e) {
echo("I had an error!");
$declined = true;
}
if(!$declined) {
echo ("I completed Successfully");
}
I think you need to catch the different types of tossed errors.
\Stripe\Stripe::setApiKey(self::APIKEY);
$charge_arr = array(
"key" => value, etc ... )
try {
$charge = \Stripe\Charge::create($charge_arr);
} catch (\Stripe\Error\Base $e) {
echo ($e->getMessage());
} catch (\Stripe\Error\Card $e) {
echo ($e->getMessage()); // I think this is the missing one
} catch (\Stripe\Error\Authentication $e) {
// a good one to catch
} catch (\Stripe\Error\InvalidRequest $e) {
// and catch this one just in case
} catch (Exception $e) {
//catch any non-stripe exceptions
}

Stripe payment with php

I am developing a website that is front end made with angularjs and backend with laravel.
I want to integrate stripe payment. I am facing difficulty to add a angularjs api to laravel for stripe payment. So, I am trying to solve it with only procedural php. here is my code.
<?php
require_once('/stripe-php/lib/Stripe.php');
require_once('/stripe-php/lib/Charge.php');
Stripe::setApiKey('my-secret-key');
$charge = Charge::create(array('amount' => 2000, 'currency' => 'usd', 'source' => $token ));
if ($charge) {
echo "Payment successcul";
}
else {
echo "Not success";
}
?>
I can get the token. But the payment is not processing and I see a blank page.
Follow this step to stripe payment.
1. download stripe folder from https://stripe.com/docs/libraries#php
2. Include the folder in your www folder in your project.
3. Make new PHP file and put this code into file.
<?php
{
require_once "./Stripe-php/init.php"; //include your stripe folder
function __construct()
{
// put your keys here
\Stripe\Stripe::setApiKey("Secret-Key");
}
//put your code into function.
$token = $_POST['stripeToken']; // Token ID
$charge = \Stripe\Charge::create([
'amount' => $20 * 100,
'currency' => 'usd',
'description' => 'Message',
'source' => $token,
]);
if($charge['status'] == "succeeded"){ // if success
$status=1;
$post['charge_id']=$charge['id'];
$post['amount']=$charge['amount'];
$post['funding']=$charge['source']['funding'];
$post['holder_name']=$charge['source']['name'];
$post['brand']=$charge['source']['brand'];
$Message="Payment Success";
}
else{
$status=2; // failed
$post=null;
$Message="Payment Failed";
}
$data["status"] = ($status > 1) ? FAILED : SUCCESS;
$data["message"]=$Message;
$data["PaymentData"]=$post;
return $data; // JSON Returen
}
?>
Include Stripes error handling in the page itself.
try {
// Use Stripe's library to make requests...
} catch(\Stripe\Error\Card $e) {
// Since it's a decline, \Stripe\Error\Card will be caught
$body = $e->getJsonBody();
$err = $body['error'];
print('Status is:' . $e->getHttpStatus() . "\n");
print('Type is:' . $err['type'] . "\n");
print('Code is:' . $err['code'] . "\n");
// param is '' in this case
print('Param is:' . $err['param'] . "\n");
print('Message is:' . $err['message'] . "\n");
} catch (\Stripe\Error\RateLimit $e) {
// Too many requests made to the API too quickly
} catch (\Stripe\Error\InvalidRequest $e) {
// Invalid parameters were supplied to Stripe's API
} catch (\Stripe\Error\Authentication $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
} catch (\Stripe\Error\ApiConnection $e) {
// Network communication with Stripe failed
} catch (\Stripe\Error\Base $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
}

Charging card with Stripe

Everything is working fine in Stripe - the token is generated, written in the "log" part in my dashboard, etc. However there is no charge done. I got no error from Stripe or my code even if I did all the error handling given by the stripe documentation. How can I correct this?
require_once ("vendor/autoload.php");
if ($_POST) {
echo "catch if";
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
StripeStripe::setApiKey("myApyKey");
// Get the credit card details submitted by the form
$token = $_POST['stripeToken'];
// Create a charge: this will charge the user's card
try {
echo "charging";
$charge = StripeCharge::create(array(
"amount" => 1000, // Amount in cents
"currency" => "eur",
"source" => $token,
"description" => "Example charge"
));
}
catch(StripeErrorCard $e) {
// Since it's a decline, \Stripe\Error\Card will be caught
$body = $e->getJsonBody();
$err = $body['error'];
print ('Status is:' . $e->getHttpStatus() . "\n");
print ('Type is:' . $err['type'] . "\n");
print ('Code is:' . $err['code'] . "\n");
// param is '' in this case
print ('Param is:' . $err['param'] . "\n");
print ('Message is:' . $err['message'] . "\n");
}
catch(StripeErrorRateLimit $e) {
// Too many requests made to the API too quickly
}
catch(StripeErrorInvalidRequest $e) {
// Invalid parameters were supplied to Stripe's API
}
catch(StripeErrorAuthentication $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
}
catch(StripeErrorApiConnection $e) {
// Network communication with Stripe failed
}
catch(StripeErrorBase $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
}
catch(Exception $e) {
// Something else happened, completely unrelated to Stripe
}
You are probably getting an error, and your code is handling that error correctly, but you error handling code doesn't actually do anything for many of the cases.
You should probably add something (such as a print call) in each catch block to see exactly what type of issue is being returned.
Alternatively, your Stripe Dashboard has a way to view your accounts Live Mode and Test Mode logs at https://dashboard.stripe.com/logs which will contain an entry for every request (successful or otherwise) that hit Stripe's servers.
Try to use below code find error issue
try {
echo "charging";
$charge = StripeCharge::create(array(
"amount" => 1000, // Amount in cents
"currency" => "eur",
"source" => $token,
"description" => "Example charge"
));
}
catch(StripeErrorCard $e) {
$error = $e->getJsonBody();
<pre>print_r($error);</pre>
//then you can handle like that
if($error == "Your card was declined."){
echo "Your credit card was declined. Please try again with an alternate card.";
}
}

Stripe how to handle InvalidRequest error

I want to handle this error, however I can't get it to work in my catch. I've tried using multiple error phrases such as Stripe\Error\InvalidRequest and invalid_request_error, but none of them work.
Note: I have only included the necessary code, my payment system works fine.
Here's my code:
try {
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => $amount,
'currency' => strtolower($active_user->currency->currency_id)
));
}
catch (Stripe\Error\InvalidRequest $e) {
$msg = "Sorry, you cannot make the same payment twice.";
}
From the Stripe API Docs section on errors:
catch (\Stripe\Error\InvalidRequest $e) {
// Invalid parameters were supplied to Stripe's API
} catch (\Stripe\Error\Authentication $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
} catch (\Stripe\Error\ApiConnection $e) {
// Network communication with Stripe failed
} catch (\Stripe\Error\Base $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
}
Could be a namespacing issue. Try referencing your exception class with respect to the global scope by using a leading slash:
catch (\Stripe\Error\InvalidRequest $e) {
Failing that, add a catch for the base PHP Exception class, and see what you can find out about what is being thrown.
Example from stripe:
Are your responses set to return json, If so, in your } catch (... $e) {
$body = $e->getJsonBody();
$err = $body['error'];
print('Status is:' . $e->getHttpStatus() . "\n");
print('Type is:' . $err['type'] . "\n");
print('Code is:' . $err['code'] . "\n");
// param is '' in this case
print('Param is:' . $err['param'] . "\n");
print('Message is:' . $err['message'] . "\n");

Categories