-
Notifications
You must be signed in to change notification settings - Fork 680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Payment Intents #636
Comments
Instead of being reliant on webhooks we could maybe use the Manual confirmation? The code doesn't look to hard to write. You would have to have some type of API that handles the different statuses and send back responses to the front-end. Here is the docs: https://stripe.com/docs/payments/payment-intents/quickstart#flow-manual-confirmation |
@MarGul nice. They only recently posted that I believe. Gonna look at this in detail when I get to this issue. |
I too am looking into this, not only as a way to be SCA compliant but also to help prevent bank disputes. It's a pretty critical feature. The flow seems a bit ambiougs to me. If anyone can make sense of it / clarify could you comment? It would also help Cashier implement a flow that works with plans/subscriptions. The Payment Intent Flow (as I understand it) - using stripe js / php and with a subscription / plan
$plan = \Stripe\Plan::retrieve('your-subscription-plan-id', [
'api_key' => config('services.stripe.secret'),
]);
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => $plan->amount,
'currency' => $plan->currency,
'payment_method_types' => ['card'],
], [
'api_key' => config('services.stripe.secret'),
]); You can then pass the payment intent details onto your view / form so that it can be used in js when you eventually make a call to
stripe.handleCardPayment(document.querySelector('input[name="payment_intent_secret"]').value, card).then(function(result) {
if (result.error) {
// Payment failed.
} else {
// Payment successful.
}
});
$paymentIntent = null;
if (session('paymentIntentId')) {
$paymentIntent = \Stripe\PaymentIntent::retrieve(session('paymentIntentId'), [
'api_key' => config('services.stripe.secret'),
]);
}
$expiredPaymentIntent = $paymentIntent && in_array($paymentIntent->status, ['canceled', 'succeeded']);
if (! $paymentIntent || $expiredPaymentIntent) {
// Create new payment intent here, as its either not created or old one has expired.
// ...
// ..
// Remember it in session so we don't create a new payment intent everytime checkout page is reloaded:
session()->put('paymentIntentId', $paymentIntent->id, now()->addDay());
} If anyone can shed light on the flow / clarify how they've got it working in their app that would be much appreciated. |
Hey @garygreen, thanks for helping out! I'll look into your reply as soon as I get to the issue. |
Ok so I spoke with Stripe and they have informed me this is the best place to understand the workflow for payment intents with subscriptions: https://stripe.com/docs/billing/subscriptions/payment (that docmentation only went live on Thursday, so its still a WIP but it's much better place to understand than the other docs because they focus on one-off payments rather than subscriptions) The key factor is a subscription may now enter a new status called var stripe = Stripe('key here');
// This can be found on invoice.payment_intent.client_secret
var paymentIntentSecret = 'pi_91_secret_W9';
stripe.handleCardPayment(
paymentIntentSecret
).then(function (result) {
if (result.error) {
// Display error.message in your UI.
} else {
// The payment has succeeded. Display a success message.
}
}) ... that will then prompt for any 3D secure payments / other things needed to complete the payment. A webhook will then fire to note that the payment went thru Hopefully that helps. The docs explain it better but that's how I've understood it. |
@garygreen that helps! We actually need to revert the behavior I added in #631 because of the |
Bit more info - you can also pass a Example in node, but hopefully get the idea: let subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [
{
plan: "plan_DQYe83yUGgx1LE",
},
],
expand : ["latest_invoice.payment_intent"]
}); |
Also I've had to override the <?php
namespace App\Cashier;
use Laravel\Cashier\SubscriptionBuilder as LaravelSubscriptionBuilder;
class SubscriptionBuilder extends LaravelSubscriptionBuilder
{
/**
* Build the payload for subscription creation.
*
* @return array
*/
protected function buildPayload()
{
return array_merge(parent::buildPayload(), [
'enable_incomplete_payments' => true
]);
}
} I've got payment intents mostly working locally now with current version of Cashier. Still a work in progress (understanding the hooks etc), but it's looking good so far. |
Just wanted to share information about upcoming changes being added to Stripe on Juli 1, 2019 regarding Subscriptions. Further changes needed for subscription in EU
|
@bilfeldt thanks for noting that. I'll create a separate issue for this. We'll release an update for this once the API has been released. |
I've been working on a PR for this and it's coming along nicely. Follow along here: #667 |
These changes bring support for the new payment intents api to charges and subscriptions. As there are quite some breaking changes here let's go over the most prominent ones below: Any payment action will now throw an exception when a payment either fails or when the payment requires a secondary action in order to be completed. This goes for single charges, invoicing customers directly, subscribing to a new plan or swapping plans. Developers can catch these exceptions and decide for themselves how to handle these by either letting Stripe handle everything for them (to be set up in the Stripe dashboard) or use the custom built-in solution which will be added in the next commit. A new status column is introduced for subscriptions as well. Whenever an attempt is made to subscribe to a plan but a secondary payment action is required, the subscription will be put into a state of "incomplete" while payment confirmation is awaited. As soon as payment has been properly processed, a webhook will update the subscription's status to active. After these changes, webhooks will be a fundamental part of how Cashier works and they're now required in order to properly handle any payment confirmations and off-session updates to subscriptions & customers. The charge method now only accepts a payment method instead of a token. Developers will need to update their JS integration to retrieve a payment method id instead of a source token. These changes were done because this is now the recommended way by Stripe to work with payment methods. More info about that can be found here: https://stripe.com/docs/payments/payment-methods#transitioning In an upcoming update all card methods as well as the create method on the subscription builder will be updated as well. Closes #636
These changes bring support for the new payment intents api to charges and subscriptions. As there are quite some breaking changes here let's go over the most prominent ones below: Any payment action will now throw an exception when a payment either fails or when the payment requires a secondary action in order to be completed. This goes for single charges, invoicing customers directly, subscribing to a new plan or swapping plans. Developers can catch these exceptions and decide for themselves how to handle these by either letting Stripe handle everything for them (to be set up in the Stripe dashboard) or use the custom built-in solution which will be added in the next commit. A new status column is introduced for subscriptions as well. Whenever an attempt is made to subscribe to a plan but a secondary payment action is required, the subscription will be put into a state of "incomplete" while payment confirmation is awaited. As soon as payment has been properly processed, a webhook will update the subscription's status to active. After these changes, webhooks will be a fundamental part of how Cashier works and they're now required in order to properly handle any payment confirmations and off-session updates to subscriptions & customers. The charge method now only accepts a payment method instead of a token. Developers will need to update their JS integration to retrieve a payment method id instead of a source token. These changes were done because this is now the recommended way by Stripe to work with payment methods. More info about that can be found here: https://stripe.com/docs/payments/payment-methods#transitioning In an upcoming update all card methods as well as the create method on the subscription builder will be updated as well. Closes #636
The PR was merged 🎉 |
show this error after upgrade cashier 10 from 9 How to solve it? Thanks in advance! |
From the upgrade guide:
💡 I would suggest reading the whole of the upgrade guide as there could be other gotchas. |
for this Url not geeting where and which one file nedd to change. |
may this problem create cashier 10 and spark 7+ |
I've already asked you twice to please ask this on a support channel. Please read the upgrade guide thoroughly. |
The new Payment Intents API is needed to make payments SCA compliant. This will require some significant changes in the public API of Cashier as well as making Cashier relient on webhooks to verify payments.
SCA Info: https://stripe.com/docs/strong-customer-authentication
Payment Intents: https://stripe.com/docs/payments/payment-intents
Billing migration guide: https://stripe.com/docs/billing/migration/strong-customer-authentication
The text was updated successfully, but these errors were encountered: