Reputation: 355
For cards that do not require 3D security, it works flawlessly. But for those that require them, it gets stuck at incomplete
status.
My implementation is very simple. The frontend
collects the card info and makes a request to stripe's API
to get the token
and to create the payment_method
.
async submitForm(e) {
e.preventDefault();
try {
const { token } = await this.stripe.createToken(this.card);
const { paymentMethod } = await this.stripe.createPaymentMethod({
type: 'card',
card: this.card,
});
this.stripeTokenHandler(token.id, paymentMethod.id); // handles submission to backend
} catch (e) {
this.cardErrorsTarget.textContent = e.error.message;
}
}
The backend part is written in rails
.
customer = Stripe::Customer.create(
source: params[:stripe_token],
plan: plan_id,
# address of the customer
)
# Creating the setup intent
intent = Stripe::PaymentIntent.create(
amount: some_amount,
customer: customer.id,
payment_method_types: ["card"],
)
# After that I need to confirm the intent
confirm_intent = Stripe::PaymentIntent.confirm(intent.id, {
payment_method: params[:pm_token],
return_url: app_confirm_subscription_url # After 3D secure, it redirects to this URL
})
After the redirection,
def show
intent = Stripe::PaymentIntent.retrieve(params[:payment_intent]) # stripe adds the payment_intent params
raise intent
end
By raising the intent
, I see that
{
paid: true,
status: "succeeded",
result: "authenticated",
// more data
}
But when I go to Stripe's dashboard, it shows that the subscription is incomplete. These are the events
in descending order.
The payment pi_1I6AVKCYHrwDIsnfiGm7bWUM for $29.00 USD has succeeded
[email protected] was charged $29.00 USD
The payment pi_1I6AVKCYHrwDIsnfiGm7bWUM for $29.00 USD requires you to take action in order to complete the payment
A new payment pi_1I6AVKCYHrwDIsnfiGm7bWUM for $29.00 USD was created
[email protected] attempted to subscribe to price_1I5vshCYHrwDIsnf981UpZEc
[email protected] added a new Visa ending in 3220
A card payment method ending in 3220 was attached to customer cus_IhZezT431x2G7Z
A draft invoice for $29.00 USD to [email protected] was finalized
A draft invoice was created
[email protected] is a new customer
PS: The card that I used is 4000 0000 0000 3220, which requires 3D security. If I use the 4242 4242 4242 4242, it works without any problems.
Is there something that I'm missing?
Upvotes: 2
Views: 6678
Reputation: 1179
Creating a standalone PaymentIntent and using it to drive subscription creation is in this case the wrong integration. If we make reference to the guide for starting a fixed price subscription using Elements [1], the major steps are as follows:
createPaymentMethod
from Stripe.jsThe key difference here is step 4. When you start a subscription, a PaymentIntent is created automatically under the hood and associated with the first invoice of the subscription. This is the PaymentIntent that should be used in conjunction with confirmCardPayment
in the client using Stripe.js and the PaymentIntent's client secret [2]. It can be accessed by checking the latest_invoice.payment_intent.status
of the subscription after it is created i.e. after the first payment attempt.
There are quite a few other steps to handle for example when payment fails but the guide goes into details about the possible flows that you will encounter.
[1] https://stripe.com/docs/billing/subscriptions/fixed-price
[2] https://stripe.com/docs/billing/subscriptions/fixed-price#manage-payment-authentication
Upvotes: 2