首页 > 解决方案 > 使用 SwiftUI 进行条带化

问题描述

我正在尝试使用STPApplePayContextDelegate.

我根据此文档创建了一个符合此委托的类,但没有运气。我得到这个错误:// 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 $50")
                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) {
        
    }
}

标签: iosswiftswiftuistripe-payments

解决方案


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

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

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

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

更新:为了响应您对代码的请求,请从这里开始。请注意,并非所有内容都已连接 - 您需要连接 buttonPressed 方法,向按钮添加布局约束等,但它为您提供了一种方法来确定如何获取对 UIViewController 的引用

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()

推荐阅读