'When confirming payment intent with Stripe the funds are being hold but the API returns as failed

I am trying to hold funds on the customer card until the trip has been completed.

On the server:

> const capture = await stripe.paymentIntents.create({
>             customer: stripeId,
>             amount: amount,
>             currency: "gbp",
>             payment_method: paymentId,
>             receipt_email: email,
>             confirm: true,
>             capture_method: "manual",
>             setup_future_usage: "off_session",
>             use_stripe_sdk: true,
>         });

Payment intent comes back with status "requires_action" so i try to confirm the hold of funds in the app:

>  final PaymentConfiguration paymentConfiguration =
> PaymentConfiguration.getInstance(requireContext());
>             PaymentLauncher paymentLauncher = PaymentLauncher.Companion.create(this,
> paymentConfiguration.getPublishableKey(),
> paymentConfiguration.getStripeAccountId(), this);
> 
> final ConfirmPaymentIntentParams confirmParams = ConfirmPaymentIntentParams.createWithPaymentMethodId(paymentMethodId,
> clientSecret);
>             paymentLauncher.confirm(confirmParams);

Funds are being confirmed and the payment intent updates status to "requires_capture", but the payment result callback returns as failed. This card does not really need 3DS but it does return "requires_action" so i need to confirm it. On another card that does require 3DS this method works.

@Override
>     public void onPaymentResult(@NonNull PaymentResult paymentResult) {
>         if (paymentResult instanceof PaymentResult.Completed) {
>         } else if (paymentResult instanceof PaymentResult.Canceled) {
>         } else if (paymentResult instanceof PaymentResult.Failed) {
>             Throwable error = ((PaymentResult.Failed) paymentResult).getThrowable();error.getMessage());
>         }
>     }


Solution 1:[1]

I ended up using stripe API:

Check status of the returned payment intent and if it requires_action or requires_confirmation use this:

Stripe stripe = new Stripe(this, publishable key);
ConfirmPaymentIntentParams confirmPaymentIntentParams = ConfirmPaymentIntentParams.create(response.getString("secret"));
stripe.confirmPayment(this, confirmPaymentIntentParams);
    
@Override
public void onActivityResult(int requestCode, int resultCode, @org.jetbrains.annotations.Nullable Intent data) {
                super.onActivityResult(requestCode, resultCode, data);
                stripe.onPaymentResult(requestCode, data, new ApiResultCallback<PaymentIntentResult>() {
                    @Override
                    public void onSuccess(@NonNull PaymentIntentResult paymentIntentResult) {
                        StripeIntent.Status status = paymentIntentResult.getIntent().getStatus();
                        if (status != null) {
                            switch (status) {
                                case Succeeded:
                                case RequiresCapture:
                                    //all good
                                    break;
                                case RequiresAction:
                                case RequiresConfirmation:
                                    //error i guess
                                    break;
                                case RequiresPaymentMethod:
                                    //no funds
                                    break;
                                case Canceled:
                                    checkPayment();
                                    break;
                            }
                        } else {
                            checkPayment();
                        }
                    }
        
                    @Override
                    public void onError(@NonNull Exception e) {
                        //show error
                    }
                });
            }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1