Search code examples
androidandroid-intentstripe-paymentspayment

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

  • 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
                        }
                    });
                }