使用 SwiftUI 条纹

Stripe with SwiftUI

我正在尝试使用 STPApplePayContextDelegate.

在我的 SwiftUI 应用程序中实现 Stripe

我根据这个 documentation 创建了一个符合这个委托的 class 但没有成功。我收到此错误:// Type of expression is ambiguous without more context 在这一行 let applePayContext = STPApplePayContext(paymentRequest: paymentRequest, delegate: self)

我做错了什么?

struct PaymentButtonController : UIViewControllerRepresentable {
    
    class Coordinator : NSObject, STPApplePayContextDelegate {
        var vc : UIViewController?
        
        @objc func buttonPressed() {
            let merchantIdentifier = "merchant.com.your_app_name"
            let paymentRequest = StripeAPI.paymentRequest(withMerchantIdentifier: merchantIdentifier, country: "US", currency: "USD")

            // Configure the line items on the payment request
            paymentRequest.paymentSummaryItems = [
                // The final line should represent your company;
                // it'll be prepended with the word "Pay" (i.e. "Pay iHats, Inc ")
                PKPaymentSummaryItem(label: "iHats, Inc", amount: 50.00),
            ]
            
            // Initialize an STPApplePayContext instance
                if let applePayContext = STPApplePayContext(paymentRequest: paymentRequest, delegate: self) {
                    // Present Apple Pay payment sheet
                    if let vc = vc {
                        applePayContext.presentApplePay(on: vc)
                    }
                    
                } else {
                    // There is a problem with your Apple Pay configuration
                }
        }
        
        func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: STPPaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
            let clientSecret = "..."
            print("ENDLICH")
            // Retrieve the PaymentIntent client secret from your backend (see Server-side step above)
            // Call the completion block with the client secret or an error
            completion(clientSecret, nil);
        }
        
        func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?) {
            print("ENDLICH")
            switch status {
            case .success:
                // Payment succeeded, show a receipt view
                break
            case .error:
                // Payment failed, show the error
                break
            case .userCancellation:
                // User cancelled the payment
                break
            @unknown default:
                fatalError()
            }
        }
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator()
    }
    
    func makeUIViewController(context: Context) -> UIViewController {
        let button = PKPaymentButton(paymentButtonType: .plain, paymentButtonStyle: .automatic)
        button.addTarget(context.coordinator, action: #selector(context.coordinator.buttonPressed), for: .touchUpInside)
        let vc = UIViewController()
        context.coordinator.vc = vc
        vc.view.addSubview(button)
        return vc
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
}

您正在调用的函数 (presentApplePay) 需要 UIViewController 作为其输入,但您传递的是 self,这是您定义的 ApplePayContext以上为 NSObject, ObservableObject, STPApplePayContextDelegate.

您将面临的挑战是获取要传递给它的 UIViewController 上下文,因为在纯 SwiftUI 中您不会有任何对 UIViewController 的引用。

您有几个可能的解决方案:

  1. 在您的 SceneDelegate 中,将 UIHostingController 的引用传递给您的视图,然后将其用作 presentApplePay
  2. 的参数
  3. 使用 UIViewControllerRepresentable 获取一个 UIViewController,您可以将其嵌入到 SwiftUI 视图中并作为参数传递 (https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable)
  4. 使用 SwiftUI-Introspect 之类的库将底层 UIViewController 获取到您当前的 SwiftUI 视图 (https://github.com/siteline/SwiftUI-Introspect)

更新: 为了响应您对代码的请求,这里有一些东西可以开始。请注意,并非所有内容都已连接——您需要连接 buttonPressed 方法,向按钮添加布局约束等,但它为您提供了一种方法来弄清楚如何获取对 UIViewController[=23= 的引用]

struct PaymentButtonController : UIViewControllerRepresentable {
    
    class Coordinator : NSObject {
        var vc : UIViewController?
        
        @objc func buttonPressed() {
            print("Button with VC: \(vc)")
        }
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator()
    }
    
    func makeUIViewController(context: Context) -> UIViewController {
        let button = PKPaymentButton()
        button.addTarget(context.coordinator, action: #selector(context.coordinator.buttonPressed), for: .touchUpInside)
        let vc = UIViewController()
        context.coordinator.vc = vc
        vc.view.addSubview(button)
        return vc
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
}

通过在您的 SwiftUI 代码中使用它来嵌入您的视图:

PaymentButtonController()