1
votes

I'm using stripe in React and processing the charge through an AJAX call. I've tried to strip down the Stripe.card.createToken function to the bare essentials for this question.

The if else statement checks if the response has any errors.

I use the 4100000000000019 card number to ensure a card declined error but the else statement(the successful charge) fires regardless which card number is entered.

Entering the 4100000000000019 card number results in a blocked charge in the Stripe dashboard. An error definitely gets generated:

{
  "error": {
    "message": "Your card was declined.",
    "type": "card_error",
    "code": "card_declined",
    "decline_code": "generic_decline",
    "charge": "ch_19gMBaIWHxnqld7LCdbCtdNz"
  }
} 

But the if(response.error) is ignored and runs the else statement.

    Stripe.card.createToken({
    number: $('.card-number').val(),
    cvc: $('.card-cvc').val(),
    exp_month: $('.card-expiry-month').val(),
    exp_year: $('.card-expiry-year').val(),
    name: $('.first-name').val()
}, function(status, response){
    if (response.error) {
        this.reportError(response.error.message);
    } else { // No errors, submit the form.
      var token = response.id;
        $.ajax({
           type: 'POST',
           url: 'components/charge.php',
           data : {
             stripeToken: token
           },
           success: function(data,response) {
             paymentSuccessful();
           },
           error: function(data,textStatus) {
             console.log("Ajax Error!");
           }
         });//$.ajax
    }//else
});//Stripe.card.createToken

Any help is much appreciated.

Moe

UPDATE: Thanks to this awesome tutorial by Larry Ullman and it's section on stripe error handling, I came up with a fairly good solution. http://www.larryullman.com/2013/01/30/handling-stripe-errors/

So I added the if else statment inside the AJAX success function.

success: function(data,response) {
                 if(data == "success"){
                   $('#payment-error-copy').text("Your payment was successful. Thank you for ordering!");
                   paymentSuccessful();
                 } else {
                   $('#payment-error-copy').text(data);
                 }
    };//success function

Inside the charge we can return the error response and the precise reason for the error.

my charge.php file

<?php
require_once('vendor/autoload.php');

// Get the payment token submitted by the form:
$token = $_POST['stripeToken'];
try{
  \Stripe\Stripe::setApiKey("<secret_KEY>");

  $customer = \Stripe\Customer::create(array(
    "source" => $token,
    "email" => $email
    )
  );
  // Charge the Customer instead of the card
  \Stripe\Charge::create(array(
      "amount" => $price, // amount in cents, again
      "currency" => "aud",
      "description" => $email." ".$first_name,
      "customer" => $customer->id
    )
  );
  echo "success";
} catch (\Stripe\Error\ApiConnection $e) {
    // Network problem, perhaps try again.
    $e_json = $e->getJsonBody();
    $error = $e_json['error'];
    echo "Sorry, your charge couldn't be processed. Reason: ".$error['message'];
} catch (\Stripe\Error\InvalidRequest $e) {
    // You screwed up in your programming. Shouldn't happen!
    $e_json = $e->getJsonBody();
    $error = $e_json['error'];
    echo "Sorry, your charge couldn't be processed. Reason: ".$error['message'];
} catch (\Stripe\Error\Api $e) {
    // Stripe's servers are down!
    $e_json = $e->getJsonBody();
    $error = $e_json['error'];
    echo "Sorry, your charge couldn't be processed. Reason: ".$error['message'];
} catch (\Stripe\Error\Card $e) {
  // Card was declined.
  $e_json = $e->getJsonBody();
  $error = $e_json['error'];
  echo "Sorry, your charge couldn't be processed. Reason: ".$error['message'];
}

?>

The try catch statement returns a precise message about the charge error and returns it to our success function, so if the charge is anything other than success it runs the error function.

Although my question remains unanswered, the build works as expected and still remains safe for the user to enter their billing info.

Thanks to the other SO users for their input, it is really appreciated.

1

1 Answers

0
votes

I think this particular card number only gives an error when Stripe actually tries to use it.

Just built a change-card-function for my SaaS and noticed that when I update my StripeCustomer default source with the token received, it fails.