0

I am using Stripe elements to make an asychronous paymentRequest to charge customers. The request returns 'success' irrespective of the charge result so what's the best way to return a state so I can handle the charge state client side and report a failed charge? Do I need to use endpoints? Stripe seems to leave us hanging after the charge with no guidance.

Listener:

<script>    
    paymentRequest.on('token', function(ev) {

        fetch('https://example.com/pub/apple.php', {
        method: 'POST',
        body: JSON.stringify({token: ev.token.id , email: ev.token.email}),
        headers: {'content-type': 'application/json'},
    })
      .then(function(response) {
        if (response.ok) {

          // Report to the browser that the payment was successful, prompting
          // it to close the browser payment interface.

          ev.complete('success');

        } else {

          // Report to the browser that the payment failed, prompting it to
          // re-show the payment interface, or show an error message and close
          // the payment interface.

          ev.complete('fail');
        }
  });
});
    </script>

https://example.com/pub/apple.php:

require_once('../_stripe-php-4.9.0/init.php');

// Retrieve the request's body and parse it as JSON
$input = @file_get_contents("php://input");
$json = json_decode($input);

// get the token from the returned object

$token = $json->token;
$email = $json->email;

$skey = 'sk_test_Y********************F';  

\Stripe\Stripe::setApiKey($skey);  

//  create the customer

$customer = \Stripe\Customer::create(array(
          "source" => $token,
           "description" => 'Device',
           "email" => $email)
        );  



    //charge the card    

    $charge = \Stripe\Charge::create(array(
              "amount" => 1000, 
              "currency" => 'GBP',
              "statement_descriptor" => 'MTL',
              "description" => 'Device - '.$customer->id,
              "customer" => $customer->id)
            );
duck
  • 5,240
  • 1
  • 15
  • 15

1 Answers1

0

In order to let the user know that their charge failed, and trigger ev.complete('fail'); in the code above, you'll need response.ok inside your fetch request to return false.

Let's first look at the definition of that response.ok property,

The ok read-only property of the Response interface contains a Boolean stating whether the response was successful (status in the range 200-299) or not.

via https://developer.mozilla.org/en-US/docs/Web/API/Response/ok

So for a successful request you want PHP to return a 2xx status (let's say 200) , and for failure a non-200 HTTP status code (lets say a 402).

In your PHP, you will attempt to make a Charge, then receive a response from Stripe. Based upon this response, you should make PHP return a status to your front-end --- either a 200 OK or a 402 error.

You can do this with the function http_response_code(), e.g. http_response_code(200) or http_response_code(402)

http://php.net/manual/en/function.http-response-code.php

Let's look at a simplified example

try {
  // make a charge
  $charge = \Stripe\Charge::create(array(
    "amount" => 1000, 
    "currency" => 'GBP',
    "source" => $token
  ));

  // send a 200 ok
  http_response_code(200);
  print("Charge successful");

} catch(\Stripe\Error\Card $e) {
  // Since it's a decline, \Stripe\Error\Card will be caught
  $body = $e->getJsonBody();
  $err  = $body['error'];

  // this charge declined, return a 402
  // response.ok should then be false
  http_response_code(402);
  print('Error:' . $err['message']);
}

The Charge call here is wrapped in a try-catch block. If the charge succeeds, a 200 HTTP response code is sent, and response.ok will be true.

If the user provides a card that declines, that error will be caught, and 402 HTTP response code will be returned (along with an error message). In that case response.ok would be false, so ev.complete('fail'); would be called.

There are some other types of Stripe errors you probably want to catch, a full reference is here,

https://stripe.com/docs/api/errors https://stripe.com/docs/api/errors/handling

duck
  • 5,240
  • 1
  • 15
  • 15