0
votes

When I send the data of the card to make the purchase by means of stripe it shows me the following message:

Successfully charged $50!

tok_1BKYfLDi3J7CIS2eVqZVeZqT

But when you do not receive data when sending the payment data shows these errors

Notice: Undefined index: token in C:\xampp\htdocs\DesignFormStripe\charge.php on line 9 Fatal error: Uncaught Stripe\Error\Card: Cannot charge a customer that has no active card in C:\xampp\htdocs\DesignFormStripe\php\lib\stripe\lib\ApiRequestor.php:128 from API request 'req_W6Qbd7iMVHDsGS' Stack trace: #0 C:\xampp\htdocs\DesignFormStripe\php\lib\stripe\lib\ApiRequestor.php(102): Stripe\ApiRequestor::_specificAPIError('{\n "error": {\n...', 402, Array, Array, Array) #1 C:\xampp\htdocs\DesignFormStripe\php\lib\stripe\lib\ApiRequestor.php(309): Stripe\ApiRequestor->handleErrorResponse('{\n "error": {\n...', 402, Array, Array) #2 C:\xampp\htdocs\DesignFormStripe\php\lib\stripe\lib\ApiRequestor.php(65): Stripe\ApiRequestor->_interpretResponse('{\n "error": {\n...', 402, Array) #3 C:\xampp\htdocs\DesignFormStripe\php\lib\stripe\lib\ApiResource.php(119): Stripe\ApiRequestor->request('post', '/v1/charges', Array, Array) #4 C:\xampp\htdocs\DesignFormStripe\php\lib\stripe\lib\ApiResource.php(158): Stripe\ApiResource::_staticRequest('post', '/v1/charges', Array, NULL) #5 C:\xampp\htdocs\DesignFormStripe\php\lib\str in C:\xampp\htdocs\DesignFormStripe\php\lib\stripe\lib\ApiRequestor.php on line 128

How can I fix those running errors?


Update my question

Fix previous errors with the documentation of Stripe, on handling errors.

The code is almost solved in the following way:

<?php
  require_once('./config.php');

  $token  = $_POST['token']; // retrieve token POST parameter to charge the card (stripeToken)


  $customer = \Stripe\Customer::create(array(
      'email' => '[email protected]',
      //'email' => $_POST['stripeEmail'],
      'card'  => $token
  ));

try {
  // Use Stripe's library to make requests...

  $charge = \Stripe\Charge::create(array(
      'customer' => $customer->id,
      'amount'   => 500,
      'description' => 'Event charge',
      'currency' => 'usd'
  ));

  echo '<h1>Successfully charged $50!</h1>';
  echo "$token";

} 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
}
?>

Now when opening the page without received data it shows the following message:

Status is:402 Type is:card_error Code is:missing Param is:card Message is:Cannot charge a customer that has no active card

Now a new problem :(

But when loading the page again, and confirm form re-submission, it shows the same messages of previous errors.

I imagine that the error is shown because Stripe only accepts the Token generated at the request of the charge only once.

But instead of showing these errors when confirm form re-submission, show an custom error message, for example: The payment request is already in process.

1

1 Answers

0
votes

The issue here is that your code expects the card token tok_XXXX to be present in $_POST['token']. It seems that there are cases where the parameter is not sent by your form when the form is submitted though and you're not catching it.

Because of this, $token is empty and simply not sent to Stripe and the customer is created without a card. The next step is to charge the customer but since it has no card the API returns an error.

You need to change two things in your code to avoid this. First off, you should make sure that you catch all errors that can be returned by Stripe's API as documented here. The idea is that you catch the exception and then you display a user-friendly error message while you log the detailed error on your end to solve this.

Then, you need to add some logic at the beginning of your code that will ensure that $_POST['token'] is set as expected. If not, leave early and return an error to the customer.

Finally, the issue usually comes from a bug client-side where your form can be submitted without the token being created successfully first. Common issues come from not disabling form submission until a token is created or not properly initializing JS code on some browsers.