stripe / stripe-ios

Stripe iOS SDK
https://stripe.com
MIT License
2.12k stars 982 forks source link

[BUG] Getting 'No such PaymentMethod' error when presenting payment sheet. #4222

Closed HiteshPrajapati95 closed 23 hours ago

HiteshPrajapati95 commented 1 week ago

Summary

I am using same setup as reference link : https://docs.stripe.com/payments/finalize-payments-on-the-server?platform=ios Getting success when making payment with new card (in case no card has saved with customer) but for the second time when trying to present payment sheet, it immediately closes payment sheet automatically with error 'No such PaymentMethod'.

Code to reproduce

func presentPaymentSheet(from vc: UIViewController, amount: Int, currency: String) { STPAPIClient.shared.publishableKey = stripePublishableKey

    let intentConfig = PaymentSheet.IntentConfiguration(
        mode: .payment(amount: amount, currency: currency, captureMethod: .manual)
    ) { [weak self] paymentMethod, shouldSavePaymentMethod, intentCreationCallback in
        self?.handleConfirm(paymentMethod, shouldSavePaymentMethod, intentCreationCallback)
    }

    var configuration = PaymentSheet.Configuration()
    configuration.customer = .init(id: stripeCustomerCode, ephemeralKeySecret: ephemeralKeySecret)
    configuration.returnURL = “AppName://stripe-redirect"
    configuration.merchantDisplayName = AppName
    configuration.applePay = .init(merchantId: appleMerchantID, merchantCountryCode: countryCode)
    configuration.allowsDelayedPaymentMethods = true

    let paymentSheet = PaymentSheet(intentConfiguration: intentConfig, configuration: configuration)

    paymentSheet.present(from: vc) { result in
        switch result {
        case .completed:
            // Payment completed - show a confirmation screen.
        case .failed(let error):
            // PaymentSheet encountered an unrecoverable error. 
            print("paymentSheet result: Error", error)
        case .canceled:
            // Customer canceled payment
        }
    }

}

iOS version

16.7.10

Installation method

Using cocoapods

SDK version

24.0.0

Other information

Related concern is how SDK is trying to use payment method when payment sheet is not being presented and also user has not selected any payment method to start payment process yet.

seanzhang-stripe commented 1 week ago

@HiteshPrajapati95 Can you put some logs in your code to check if stripePublishableKey is changed before your code presents the PaymentSheet at the second time?

HiteshPrajapati95 commented 4 days ago

Hi @seanzhang-stripe, I've checked for the same, and there is no change in stripePublishableKey. It always remains the same.

HiteshPrajapati95 commented 3 days ago

@seanzhang-stripe, The issue is that when SDK fetches payment method from platform, it retrieves the wrong payment method. Somehow SDK gets the payment method from the Connect account, and when it loads the payment sheet UI, it considers it a platform. I think this is why it returns error as No such payment method.

seanzhang-stripe commented 3 days ago

@HiteshPrajapati95 Did you clone the platform payment method to the connected account, and use the cloned payment method to create a Direct Charge? Can you share with me the relevant PaymentIntent ID?

HiteshPrajapati95 commented 3 days ago

@seanzhang-stripe, When users do not have any saved cards, at that time users enter card details, and that card gets cloned in to connect account through backend setup. After that, using the cloned payment method, payment gets success through intent.

Now for the second time, when the user tries to make payment with the saved payment method at that time (when presenting the payment sheet), SDK returns an error by fetching the previously used payment method and closes the payment sheet instantly.

For the second time, the payment method clone steps don't perform because of getting a payment sheet error while presenting the payment sheet.

Here is the request_id for the same case: req_KUbLmRiDahouB9

seanzhang-stripe commented 2 days ago

Thanks for the request ID. The error message from the response already explained the problem:

No such PaymentMethod: 'pm_1QHk0tG8Thp5LtcOe8gic7X7'; It's possible this PaymentMethod exists on one of your connected accounts, in which case you should retry this request on that connected account. Learn more at https://stripe.com/docs/connect/authentication

Since pm_1QHk0tG8Thp5LtcOe8gic7X7 is the cloned payment that exists in your connected account, and you should call STPAPIClient.shared.stripeAccount = {{CONNECTED_ACCOUNT_ID}} in your iOS app before using this payment method for creating a direct charge on that connected account.

HiteshPrajapati95 commented 2 days ago

@seanzhang-stripe Thank you for the guidance. To clarify, in our implementation, we are not retrieving payment methods directly from the connected account. We did not specify the connected account ID when displaying the Payment Sheet UI to list the user’s payment methods.

The connected account ID is only applied when the user selects a payment method from the list to proceed with a payment. However, it seems that the Stripe SDK itself is inadvertently fetching a payment method from the connected account immediately upon invoking the Payment Sheet function to display the user’s payment methods before the user even selects any payment method. This triggers the error immediately.

Additionally, this issue began occurring after we updated the Stripe SDK to version 24.0.0.

seanzhang-stripe commented 1 day ago

Hi @HiteshPrajapati95 Thanks for the additional input. I've escalated this problem to the product team and I'll keep you posted.

wooj-stripe commented 23 hours ago

@HiteshPrajapati95 -thanks so much for taking the time to report this issue. We believe we have identified the root cause of this issue and have applied a fix in our backend. I will be optimistically closing this issue, but feel free to reopen if you continue to have an issue.