Ok... I have customer bob. His user id is 1.
Bob is already a customer in Stripe and he already has a subscription.
I want to cancel his subscription so I do this:
$sub = \Stripe\Subscription::retrieve($subscriptionId);
$sub->cancel();
that works.
now I want to resubscribe him to a plan (doesn't matter which plan, any paid plan)... I put it in a try catch: so I do this:
try {
$subscription = \Stripe\Subscription::create(array(
"customer" => $customerId, // bob's id is 1
"plan" => "premium-plan"
));
} catch (\Stripe\Error\ApiConnection $e) {
} catch (\Stripe\Error\InvalidRequest $e) {
// Error is here
} catch (\Stripe\Error\Api $e) {
} catch (\Stripe\Error\Card $e) {
}
the error I get is here: \Stripe\Error\InvalidRequest $e
what could be wrong?
Related
Has Stripe changed something? I have used this code snippet before and now suddenly there is error (Exception $e)? This error is appearing suddenly have fought with in for an hour now
try {
//Charge the Card
$charge = \Stripe\Charge::create(array(
"customer" => $stripe_account,
"amount" => 450,
"currency" => "eur",
'capture' => true),
);
$chargeID = $charge->id;
} catch (\Stripe\Error\InvalidRequest $e) {
//Send User to Error Page
echo json_encode(array("statusCode"=>205));
exit();
} catch (\Stripe\Error\Base $e) {
//Send User to Error Page
echo json_encode(array("statusCode"=>205));
exit();
} catch(\Stripe\Error\Card $e) {
// Since it's a decline, \Stripe\Error\Card will be caught
echo json_encode(array("statusCode"=>205));
//Send User to Error Page
exit();
} catch (Exception $e) {
//Send User to Error Page
echo json_encode(array("statusCode"=>205));
//Send User to Error Page
exit();
}
This issues was fixed by changing the API key. Which makes no sense i've been in contact with Stripe which is now researching this. But it works now.
I have an ionic app that makes a request to my laravel server to make the payment on the stripe platform.
but causing the error returns the Handler.php error and I cannot access the object.
How do I get the "Your card has insufficient funds." in a json?
to later show it in my app.
I already tried the try and catch and keep sending the error in handle
image
My controller:
try {
//Charge the Card
$charge = $stripe->charges()->create([
'source' => $request->token,
'currency' => $reservation->divisa_code,
'amount' => $reservation->total_price_divisa,
'description' => "App Payment Booking Seadust Cancun",
'receipt_email' => $guest->email
]);
} catch (\Stripe\Error\InvalidRequest $e) {
//Send User to Error Page
return $e;
} catch(\Stripe\Error\Card $e) {
// Since it's a decline, \Stripe\Error\Card will be caught
$body = $e->getJsonBody();
return $body;
} catch (\Stripe\Error\Base $e) {
//Send User to Error Page
return $e;
} catch (Exception $e) {
return $e;
};
I think you are catching the wrong exception (check here), you probably should have something like this:
try {
//Charge the Card
$charge = $stripe->charges()->create([
'source' => $request->token,
'currency' => $reservation->divisa_code,
'amount' => $reservation->total_price_divisa,
'description' => "App Payment Booking Seadust Cancun",
'receipt_email' => $guest->email
]);
} catch (\Stripe\Error\InvalidRequest $e) {
//Send User to Error Page
return $e;
} catch (Cartalyst\Stripe\Exception\CardErrorException $e) {
return $e->getMessage();
// or if you want a "bad response" in case of exception
// abort(404, $e->getMessage());
} catch (Exception $e) {
return $e;
};
I am setting up a small Slim 3 application which will be the middleman for processing Web based Stripe payment form. The Slim application will handle the business logic of reaching out to Stripe and conducting the payment, as well as sending the payment data off to some third-party CRM / Applications.
My issue during testing is that when i make a test payment through the StripeJS payment form the slim application is actually logging 3 duplicate requests 1-second apart. Here's what the logging looks like:
test#gmail.com Attempting to make payment 2020-04-27 05:34:39
test#gmail.com Attempting to make payment 2020-04-27 05:34:40
test#gmail.com Attempting to make payment 2020-04-27 05:34:41
test#gmail.com Payment success 2020-04-27 05:34:44
test#gmail.com Payment success 2020-04-27 05:34:45
test#gmail.com Payment success 2020-04-27 05:34:47
This is all from an individual "payment" using the Stripe Test credentials.
The Slim layout is fairly straightforward in terms of the route passing the request directly to my StripeController class. The StripeController class ( in development ) will take the values of the request and pass it to the Stripe API to conduct the payment.
The route layout:
$this->post('/stripe-payment', 'StripeController:stripePayment');
The controller (stripped to essentials for privacy ):
class StripeController extends Controller
{
private $privateKey;
private $httpClient;
public function __construct() {
$this->privateKey = getenv('STRIPE_KEY');
$this->httpClient = new Client();
\Stripe\Stripe::setApiKey($this->privateKey);
}
//
public function stripePayment($request, $response)
{
// Get the request body
$r = (object)$request->getParsedBody();
// Initial Logging
$log = new LogController($r->email_address, 'Attempting to make payment');
$log->saveLog();
// Attempt to find an existing user
$user = User::where('email', $r->email_address)->first();
if($user !== null) {
// If user exists, use their StripeID
$invoice = $this->stripeInvoice($r, $user->stripe_id);
// Log the transaction
$this->savePayment( $user->id, 'stripe-invoice', $invoice->id, $invoice->amount_paid );
// Third party application push
$this->pushUser($r, $invoice->amount_paid);
// Return with success
return $response->withRedirect('example.com/payment-success/');
} else {
// Same as above, just create a user then push.
}
}
public function stripeInvoice(object $r, string $stripe_id)
{
// Try to create the invoice in stripe
try {
\Stripe\InvoiceItem::create([
'customer' => $stripe_id,
'amount' => (int)$r->product,
'currency' => 'USD',
'description' => $plan_desc
]);
} catch ( Exception $e ) {
error_log('STRIPE_INVOICE_EXCEPTION: '.$e->getMessage());
}
// Try to charge the customer the invoice we just created
try {
$invoice = \Stripe\Invoice::create([
'customer' => $stripe_id
]);
$_get_invoice = \Stripe\Invoice::retrieve($invoice->id);
$_get_invoice->pay();
$success = 1;
// Use Stripe's library to make requests...
} catch(\Stripe\Exception\CardException $e) {
$error = $e->getMessage();
// Since it's a decline, \Stripe\Exception\CardException will be caught
} catch (\Stripe\Exception\RateLimitException $e) {
$error = $e->getMessage();
// Too many requests made to the API too quickly
} catch (\Stripe\Exception\InvalidRequestException $e) {
$error = $e->getMessage();
// Invalid parameters were supplied to Stripe's API
} catch (\Stripe\Exception\AuthenticationException $e) {
$error = $e->getMessage();
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
} catch (\Stripe\Exception\ApiConnectionException $e) {
$error = $e->getMessage();
// Network communication with Stripe failed
} catch (\Stripe\Exception\ApiErrorException $e) {
$error = $e->getMessage();
// Display a very generic error to the user, and maybe send
// yourself an email
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
$error = $e->getMessage();
}
if($success != 1) {
return $response->withRedirect('example.com&error='.$error);
} else {
return $_get_invoice;
}
}
}
Is there anything that Slim is doing in the background, like an origin check, that could be causing the duplication issue ?
In Stripe, the test number 4000 0000 0000 0341 simulates, per the Stripe Testing page, a situation where "Attaching this card to a Customer object succeeds, but attempts to charge the customer fail." In my case, I want to treat this situation like an error and send it to the error handler rather than report to the customer that the charge succeeded.
I'm doing this in PHP, so I'm not getting the JSON object from the API but rather a PHP object for the customer. I'm new to the Stripe API so I don't know what else I should be doing here. I tried searching for info about this situation and couldn't find anything helpful. And it doesn't look like this case was handled by existing SO questions.
The excerpt from the code is below. I need to set $charge_failed to true if the customer was not charged.
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);
// Create a customer.
try {
$customer = \Stripe\Customer::create(array( "source" => $my_token, 'email' => $customers_email, "description" => $my_description ));
$charge_failed = false; //TODO Set this boolean according to whether the charge passed or failed.
if ($charge_failed) {
//TODO Report to the user that the charge failed and they need to resubmit.
die();
}
}
catch(\Stripe\Error\Card $e) {
// Card was declined. Report the card declined to the user.
die();
}
catch (\Stripe\Error\RateLimit $e) {
// Report the error appropriately.
die();
} catch (\Stripe\Error\InvalidRequest $e) {
// Report the error appropriately.
die();
} catch (\Stripe\Error\Authentication $e) {
// Report the error appropriately.
die();
} catch (\Stripe\Error\ApiConnection $e) {
// Report the error appropriately.
die();
} catch (\Stripe\Error\Base $e) {
// Report the error appropriately.
die();
} catch (Exception $e) {
// Report the error appropriately.
die();
}
Before some days I implemented stripe successfully. Check below hope this will help.
if ($params['testmode'] == "on") {
\Stripe\Stripe::setApiKey($params['private_test_key']);
$pubkey = $params['public_test_key'];
} else {
\Stripe\Stripe::setApiKey($params['private_live_key']);
$pubkey = $params['public_live_key'];
}
include_once 'Stripe/init.php';
include_once 'Stripe/lib/Stripe.php';
//Set Stripe keys
$params = array(
"testmode" => "off",
"private_live_key" => "sk_live_",
"public_live_key" => "pk_live_",
"private_test_key" => "sk_test_",
"public_test_key" => "pk_test_"
);
if ($params['testmode'] == "on") {
\Stripe\Stripe::setApiKey($params['private_test_key']);
$pubkey = $params['public_test_key'];
} else {
\Stripe\Stripe::setApiKey($params['private_live_key']);
$pubkey = $params['public_live_key'];
}
if (isset($_POST['stripeToken'])) {
try {
$customer = \Stripe\Customer::create(array(
'email' => $varUserEmail,
'source' => $_POST['stripeToken']
));
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => $price,
'currency' => 'usd',
'description' => $description,
));
$result = "success";
//Save information in the database and send an email with status
//Ends here
} catch (\Stripe\Error\Card $e) {
$error = $e->getMessage();
$result = "declined";
//Save information in the database and send an email with status
}
I could be wrong but I believe that this situation occurs only if you already have an existing customer object and you are attempting to update their payment method. Your token you are using to create a customer will be invalid prior to attempting the customer creation and customer creation will fail. If this is an initial charge, the javascript method will return a failure.
The app is built on the MVC pattern, so my controllers are separate from my models.
I am using two payment gateways, Stripe and PayPal and have moved the API code into a model called Payment_Model.php.
Both functions have huge try/catch blocks that throw all manner of errors when a payment fails which is a good thing for me, not so for a customer...
Here is a try catch block example
try {
Stripe::setApiKey($this->config->item('stripe_secret_key'));
$customer = Customer::create([
'email' => 'customer#example.com',
'source' => $this->input->post('stripe_token'),
]);
$charge = Charge::create([
'customer' => $customer->id,
'amount' => $option->price,
'currency' => 'eur',
"description" => "Demo Transaction", // #TODO
]);
} catch (Exception $e) {
} catch (Stripe_CardError $e) {
throw new Exception($e);
} catch (Stripe_InvalidRequestError $e) {
throw new Exception($e);
} catch (Stripe_AuthenticationError $e) {
throw new Exception($e);
} catch (Stripe_ApiConnectionError $e) {
throw new Exception($e);
} catch (Stripe_Error $e) {
throw new Exception($e);
} catch (Exception $e) {
throw new Exception($e);
}
I don't want to display these errors or exceptions in my production environment... instead I would like to replace throw new Exception($e) with false so that I can call the model function in my controller and if something goes wrong I can redirect the user to a decent error page...
So my question is this:
Can I return a boolean IF something bad is caught so that I can either redirect to a success page or an error page in my controller? Or am I missing the point of using exceptions?