Laravel - User registration plus stripe payment in try catch block - php

Im using Laravel Cashier and also the authentication registration in one form and to process it all im using a try catch block.
try {
// Process the credit card through Stripe
// Register the user in the system
} catch (\Exception $e) {
// Throw exception with error message
}
This works fine, but im wondering what would happen if the processing of the card worked, but the registering failed.
They would get charged and have no account.
How do you go about reversing actions taken if something fails?

You should use defferent try/catch for each process:
try {
// Process the credit card through Stripe
} catch (\Exception $e) {
// Throw exception with error message
}
And the second for register:
try {
// Register the user in the system
} catch (\Exception $e) {
// Throw exception with error message
}
This way you know exactly what failed.

You should try first register process because it's in our hand we can revert this if any thing goes wrong
try {
// Register the user in the system
// Process the credit card through Stripe
// If process fails throw custom exception
}catch( CustomException $e) {
//revert the Register process
//Throw exception
} catch (\Exception $e) {
// Throw exception with error message
}

Related

Handling Multiple Exception Types For One Try Block

Is there a cleaner way to handle multiple exception types for a single try block? As you will see below we have specific code that is to be executed for the different catch statements.
This function is one of many which use the repeated try catch logic. Is it possible to eliminate this repeated catch code somehow?
public function add_payment_method(Request $request){
try{
// Try to do some stuff
} catch (\Stripe\Error\RateLimit $e) {
/*
CODE FOR THIS SPECIFIC EXCEPTION
*/
} catch (\Stripe\Error\InvalidRequest $e) {
/*
CODE FOR THIS SPECIFIC EXCEPTION
*/
} catch (\Stripe\Error\Authentication $e) {
/*
CODE FOR THIS SPECIFIC EXCEPTION
*/
} catch (\Stripe\Error\Base $e) {
/*
CODE FOR THIS SPECIFIC EXCEPTION
*/
} catch (\Stripe\Error\ApiConnection $e) {
/*
CODE FOR THIS SPECIFIC EXCEPTION
*/
} catch (\Exception $e) {
/*
CODE FOR GENERIC EXCEPTION
*/
}
}
All of these errors extend Stripe\Error\Base, so catching Stripe\Error\Base should cover the more specific ones.
That said, Stripe provides different exception types because you should be doing different actions in response to the different types. A RateLimit exception is something you should queue and retry later. A Card exception is something you should kick back to the user to fix. An Authentication error might mean your entire app is unable to take credit cards because your API token is missing/wrong and you're losing $$$.
See Catching multiple exception types in one catch block
Apart from a thousand ifelse, one can do
catch (Exception $e) {
switch ($e) {
case $e instanceof Exception1:
...;
break;
case $e instanceof Exception2:
...;
break;
default:
...;
}
}

Stripe caught exception localization

I am using Stripe for a german website, I could translate the JS (stripeResponseHandler) error messages for the form following this post but not the exception of validation ($e->getMessage()).
I get the exception error in english, how can I translate it?
My PHP :
try {
require_once('Stripe/init.php');
\Stripe\Stripe::setApiKey("myKey"); //Secret Key
$token = $_POST['stripeToken'];
$coupon = \Stripe\Coupon::retrieve($_POST['couponId']);
$charge = \Stripe\Charge::create(array(...)
} catch (Exception $e) {
echo $e->getMessage();
}
The error messages returned by the API are in English -- at this time, Stripe does not have support for localized API error messages.
You can do what's described in the SO answer you linked to provide your own translations via error handling. E.g. you could do something like:
try {
$charge = \Stripe\Charge::create(...);
} catch(\Stripe\Error\Card $e) {
$body = $e->getJsonBody();
$err = $body['error'];
switch ($err['code']) {
case 'card_declined':
// use your own "card declined" error message
break;
case 'invalid_number':
// use your own "invalid number" error message
break;
// etc.
}
} catch (\Stripe\Error\Base $e) {
// another Stripe error happened, use a generic "error with our payment processor" message
} catch (Exception $e) {
// something else happened, unrelated to Stripe
}

Recurly PHP client. How to customize error messages?

I'm trying to customize error messages.
For handling errors i used "try/catch" block according to this Recurly documentation, like this for example:
try {
$account = Recurly_Account::get('my_account_id');
$subscription = new Recurly_Subscription();
$subscription->account = $account;
$subscription->plan_code = 'my_plan_code';
$subscription->coupon_code = 'my_coupon_code';
/* .. etc .. */
$subscription->create();
}
catch (Exception $e) {
$errorMsg = $e->getMessage();
print $errorMsg;
}
I wanted use code in catch block like this:
catch (Exception $e) {
$errorCode = $e->getCode();
print $myErrorMsg[$errorCode]; // array of my custom messages.
}
But getCode() method always returns zero for all possible errors.
My question for Recurly Team (or who there in this theme):
How i get error code for errors? Or please explain me how i can resolve this topic. Thanks!
If you look at the PHP Client on Github and you search for "throw new" which is what is done when an exception is thrown you'll see that they don't set the exception error code the second parameter of the exception constructor method.
Recurly PHP Client on Github: https://github.com/recurly/recurly-client-php/search?utf8=%E2%9C%93&q=throw+new
PHP Exception documentation: http://php.net/manual/en/language.exceptions.extending.php
Therefore, you'll either need to catch more exceptions based on their name
i.e.
catch (Recurly_NotFoundError $e) {
print 'Record could not be found';
}
OR
look at the exception message and compare it
catch (Exception $e) {
$errorMessage = $e->getMessage();
if($errorMessage=='Coupon is not redeemable.')
{
$myerrorCode=1;
}
//Add more else if, or case switch statement to handle the various errors you want to handle
print $myErrorMsg[$myerrorCode]; // array of my custom messages.
}

PHP Custom Error Handler: How to determine if exception was generated within try{}catch{} block?

I have a custom error handlers:
set_error_handler('API_Error_Handler');
register_shutdown_function('Fatal_Error_Handler'); // This one calls API_Error_Handler eventually
In the following example, both catch{} section AND API_Error_Handler are executed.
try{
// Exception raised here
} catch(Exception $e){
// No error reporting needed, do something else
}
I want ONLY catch{} to execute. How do I do that? Maybe determine within API_Error_Handler whether exception is already caught by try-catch? Or are there other approaches available?
Example code:
set_error_handler(function() {
echo "Error is handled by custom error handler. <br>";
});
try{
new SoapClient('http://bad.address/wsdl');
} catch(Exception $e){
echo "Error is caught. <br>";
}
I think the best way will be to create an Exception class by your self that extends Exception:
class MyCustomException extends \Exception {}
and throw this where you need it. Then change
} catch (Exception $e)
to
} catch (MyCustomException $e)
and you should only get your custom exception catched

catching mailchimp php api errors

I am trying to create a subscribe method for my laravel app that uses the mailchimp api to subscribe a user to a given list. The method works fine when the email address is not already on the lsit. when it is already subscribed the mailchimp api throws the following error
Mailchimp_List_AlreadySubscribed blah#blah.co is already subscribed to
list Tc App Test List. Click here to update your profile.
with the following code being shown
public function castError($result) {
if($result['status'] !== 'error' || !$result['name']) throw new Mailchimp_Error('We received an unexpected error: ' . json_encode($result));
$class = (isset(self::$error_map[$result['name']])) ? self::$error_map[$result['name']] : 'Mailchimp_Error';
return new $class($result['error'], $result['code']);
}
I have attempted a try catch block to catch the error but it is still being returned to the browser, here is what I tried and were it says MailChimp_Error I tried with Exception as well.
public function subscribe($id, $email, $merge_vars)
{
try {
$this->mailchimp->lists->subscribe($id, $email, $merge_vars);
} catch (MailChimp_Error $e) {
$response = 'an error has occured';
}
return $response;
}
Ultimately I want to be able to run the method and then either return either a success message or a message describing the issue to the user. the 3 possible mailchimp method errors are Email_notexists, list_alreadysubscribed and list does not exist although tihs last one should not occur as I am providing the list in the source code.
edit 1; after being in touch with mailchimp api support they suggested this code but the error still gets returned to the browser in its entirety
try {
$results = $this->mailchimp->lists->subscribe($id, $email, $merge_vars);
} catch (Mailchimp_Error $e) {
if ($e->getMessage()) {
$error = 'Code:'.$e->getCode().': '.$e->getMessage();
}
}
echo $error;
You can do
try
{
$response = $this->mailchimp->lists->addListMember($list_id, [
"email_address" => $email,
"status" => "subscribed",
]);
}
catch (\EXCEPTION $e) {
return $e->getMessage();
}
The \EXCEPTION handles a sort of error for stripe
Subscribe is in a namespace Acme\Emails\Subscribe so catch(Mailchimp_Error $e) looks for Mailchimp_Error in this namespace.
Changing it to catch(\Mailchimp_Error $e) makes it look in the root namespace and then it works as intended

Categories