stripe / stripe-ios

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

apple pay failed #1807

Closed xujiali08 closed 2 years ago

xujiali08 commented 3 years ago

Summary

I followed the steps in the documentation (https://stripe.com/docs/apple-pay) to access Apple Pay and have been using it for some time, but now after updating from version 20.1.1 to 21.5.1, Apple Pay is no longer available: after the Apple Pay payment pop-up box appears, enter your password, processing payment -> payment not I'd like to know if there is something new, but the iOS side has upgraded the SDK and the backend has not been upgraded, does this have an impact? From the documentation it looks like it has no effect.

Code to reproduce

let config = STPPaymentConfiguration.shared

    func updateKey(isProduction: Bool) {
        if isProduction {
            STPAPIClient.shared.publishableKey = StripeKey.production.rawValue
        } else {
            STPAPIClient.shared.publishableKey = StripeKey.debug.rawValue
        }
        config.appleMerchantIdentifier = appleMerchantKey
        config.companyName = companyName
        config.applePayEnabled = true
    }

func paymentWithApplePay() {
        let paymentRequest  = StripeAPI.paymentRequest(withMerchantIdentifier: StripeManager.shared.appleMerchantKey, country: "US", currency: "USD")
        paymentRequest.paymentSummaryItems = [PKPaymentSummaryItem(label: "********", amount: FinanceService.handerDecimalNumber(int: paymentAmountInCent))]
        if let vc = self.superVc, let applePayContext = STPApplePayContext(paymentRequest: paymentRequest, delegate: vc) {
            applePayContext.presentApplePay {
            }
        } else {
            debugPrint("There is a problem with your Apple Pay configuration")
        }
    }
extension CheckoutViewController: STPApplePayContextDelegate {

    func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: STPPaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
        guard let clientSecret = viewModel.applePaySec else { return }
        completion(clientSecret, nil)
    }

    func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?) {
        viewModel.ApplePayCallbackSuccess = true
        switch status {
        case .success:
            break
        case .error:
            break
        case .userCancellation:
            break
        default:
            fatalError()
        }
    }
}

iOS version

iOS 14.3

Installation method

cocoapods: pod 'Stripe', '21.5.1'

SDK version

21.5.1

Xcode version

12.0.1

Other information

When testing with the simulator, I can get the didCreatePaymentMethod and didCompleteWith status callbacks, but the backend does not receive the callbacks for successful payment, and when testing with the real machine, the sandbox account, it shows that the payment is unsuccessful and does not get the didCreatePaymentMethod and didCompleteWith status callbacks.

4211621331479_ pic

4221621331518_ pic

yuki-stripe commented 3 years ago

Hi @xujiali08, can you show the error you're seeing from this method: func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?)

xujiali08 commented 3 years ago

Hi @xujiali08, can you show the error you're seeing from this method: func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?)

As I said in Other information. When testing with the simulator, I can get the didCreatePaymentMethod and didCompleteWith status callbacks, this method: func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?) callback success, but the backend does not receive the callbacks for successful payment. And when testing with the iphone 11, the sandbox account, it shows that the payment is unsuccessful and does not get the didCreatePaymentMethod and didCompleteWith status callbacks.

yuki-stripe commented 3 years ago

@xujiali08 Ah I see, apologies for missing that. Some questions for you:

  1. How does your backend receive callbacks for successful payment? Webhooks?
  2. Do you see the payments in your dashboard?
2blane commented 3 years ago

I've had this same issue, what is weird is that the first time I try to checkout with Apple Pay the dialog pops up on the screen, but applePayContextDidCreatePaymentMethod is never called so a payment intent is never retrieved from my server, Apple Pay spins for a minute, and then fails. If I then tap out to cancel, and try again, the server is called to get a payment intent, and the checkout works like expected.

It seems as though there is some issue where the first time you try to checkout with Apple Pay the method applePayContextDidCreatePaymentMethod is not called, but if you cancel and then try again the method is called as expected and everything works.

2blane commented 3 years ago

Also of note, the first time I try to checkout with Apple Pay the method below isn't called either so there is no way for me to report the error. It is almost like the delegate isn't getting registered properly on the first go around. Then, the second time I try to checkout the delegate is stored from the first call so it can be used. Might be a 'race condition' where applePayContextDidCreatePaymentMethod is called before the delegate is stored properly? func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?)

2blane commented 3 years ago

Turned out for me to be an issue with App Clips and SwiftUI. The instance of the delegate for me was getting released from memory so the callbacks were not getting registered. To fix I made a static instance of the delegate that was used throughout the app.