0
votes

I have a custom PHP Stripe code for donations.

I am having issues with catching declined cards or a general error (such as when a user tries to load the card-processing PHP page, which should redirect to an error page).

DONATION.PHP

//Create Customer
$customer = \Stripe\Customer::create(array(
    "email" => $email,
    "source"  => $token
));

try {
    //Charge the Card
    $charge = \Stripe\Charge::create(array(
        "customer" => $customer->id,
        "amount" => $totalAmount,
        "currency" => "usd",
        "description" => "Name: $fname $lname For: Donation",
        "statement_descriptor" => "DONATION",
    ));

} catch (\Stripe\Error\InvalidRequest $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

} catch (\Stripe\Error\Base $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

} catch (Exception $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

} catch(\Stripe\Error\Card $e) {
    // Since it's a decline, \Stripe\Error\Card will be caught
    $body = $e->getJsonBody();
    $err  = $body['error'];
    header("Location: https://example.com/declined/");
    exit();
};

//Send User to Thank You Page
header("Location: https://example.com/thank-you/");
exit();

While testing a declined card simply goes to "error" page vs "declined" page. Trying to load the "donation.php" page directly does go to "error".

The above code doesn't actually process the payment either from what I can tell as it never shows up in my stripe payments tab in test mode.

Thank you for the help!

=== updated as requested

try {
    //Charge the Card
    $charge = \Stripe\Charge::create(array(
        "customer" => $customer->id,
        "amount" => $totalAmount,
        "currency" => "usd",
        "description" => "Name: $fname $lname For: Donation",
        "statement_descriptor" => "DONATION",
    ));

} catch (\Stripe\Error\InvalidRequest $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

} catch(\Stripe\Error\Card $e) {
    // Since it's a decline, \Stripe\Error\Card will be caught
    $body = $e->getJsonBody();
    $err  = $body['error'];
    header("Location: https://example.com/declined/");
    exit();

} catch (\Stripe\Error\Base $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

} catch (Exception $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();
};

//Send User to Thank You Page
header("Location: https://example.com/thank-you/");
exit();
1
You need to put the exceptions in order of scope. Exception will catch everything that's not previously specified, so it needs to be placed last. - aynber
Yes I tried and after trying a declined card I get this error: PHP Fatal error: Uncaught Stripe\Error\Card: Your card was declined. in /home/xxx/stripe/lib/ApiRequestor.php:214 from API request 'req_xxxxx - Luis M
Odd. Everything is caught with Exception being the catchall, so it shouldn't be throwing an uncaught error. Can you edit your post with the current code, and a full trace if you have it? - aynber
Ok I edited the post with latest code. I don't have the full trace, thanks - Luis M

1 Answers

4
votes
} catch (Exception $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

}

Will catch any exception that's why it always falls back to this one and doesn't progress to your decline catch block.

Write it as such:

//Create Customer
$customer = \Stripe\Customer::create(array(
    "email" => $email,
    "source"  => $token
));

try {
    //Charge the Card
    $charge = \Stripe\Charge::create(array(
        "customer" => $customer->id,
        "amount" => $totalAmount,
        "currency" => "usd",
        "description" => "Name: $fname $lname For: Donation",
        "statement_descriptor" => "DONATION",
    ));

} catch (\Stripe\Error\InvalidRequest $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

} catch (\Stripe\Error\Base $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

} catch(\Stripe\Error\Card $e) {
    // Since it's a decline, \Stripe\Error\Card will be caught
    $body = $e->getJsonBody();
    $err  = $body['error'];
    header("Location: https://example.com/declined/");
    exit();
} catch (Exception $e) {
    //Send User to Error Page
    header("Location: https://example.com/error/");
    exit();

};

//Send User to Thank You Page
header("Location: https://example.com/thank-you/");
exit();