I'm trying to implement 3D Secure in my web app. It works perfectly well with a SEPA debit and a card debit that doesn't need 3D Secure. However, with a card that requires 3D Secure, the payment remains in the Incomplete
state in Stripe dashboard.
My product is an annual subscription.
First I create a payment intent on the server (https://stripe.com/docs/api/payment_intents/create) and I send the client secret in the HTTP response.
List<Object> paymentMethodTypes = new ArrayList<>();
paymentMethodTypes.add("card");
paymentMethodTypes.add("sepa_debit");
Map<String, Object> params = new HashMap<>();
params.put("amount", 2000);
params.put("currency", "eur");
params.put(
"payment_method_types",
paymentMethodTypes
);
PaymentIntent paymentIntent = PaymentIntent.create(params);
After that, I use stripe.confirmCardSetup
on the frontend with the clientSecret
and with the card
element and I send the payment method to my backend.
const response = await stripe.confirmCardSetup(clientSecret, {
payment_method: {
card: elements.getElement(CardElement)
}
})
await setDefaultPaymentMethod(payload?.setupIntent?.payment_method);
Then I retrieve the payment method and attach it to the customer and I finally create the subscription as shown in Stripe examples (https://stripe.com/docs/billing/subscriptions/examples).
PaymentMethod paymentMethod = PaymentMethod.retrieve(
"pm_***"
);
Map<String, Object> params = new HashMap<>();
params.put(
"customer",
"clg_***"
);
PaymentMethod updatedPaymentMethod = paymentMethod.attach(params);
// Create subscription
It does display the 3D Secure authentication modal on the frontend. However, at the end of the whole process (after creating the subscription on the backend), card payment that requires 3D Secure remains in Incomplete
state. Can anyone point me to the right direction to implement 3D Secure correctly?