【问题标题】:Stripe with SwiftUI使用 SwiftUI 进行条带化
【发布时间】:2021-04-15 16:59:39
【问题描述】:

我正在尝试使用 STPApplePayContextDelegate 在我的 SwiftUI 应用中实现 Stripe。

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

【问题讨论】:

    标签: ios swift swiftui stripe-payments


    【解决方案1】:

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

    您将面临的挑战是将UIViewController 上下文传递给它,因为在纯 SwiftUI 中您不会有任何对 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()
    

    【讨论】:

    • 我选择了选项,尽管我觉得自己快要结束了,但我仍然没有完全弄清楚。我确实创建了一个符合UIViewControllerRepresentable 的类,我试图将它作为参数传递,但我得到:Type of expression is ambiguous without more context。我更新了我的答案.. @jn_pdx
    • 我明白你做了什么,但你需要将 UIViewControllerRepresentable 嵌入到你的视图层次结构中——而不仅仅是在你的 ObservableObject 中创建它。很难给你一个例子,因为你没有显示任何实际的视图代码(即你如何开始支付),但你可以使用类似这个答案的东西作为灵感:stackoverflow.com/questions/62638416/…
    • 我在回答中添加了如何显示“付款”按钮。我确实设法显示了评论中链接中显示的屏幕,但问题是我无法使用它,因为我没有从 Apple 获得任何成功或错误消息,仅来自 Stripe
    • 这可能是最简单的,是的。
    • 谢谢你,我喜欢 SwiftUI,但是没有人有关于如何使用他们的库的文档,他们都只是假设你在使用 Storyboards,非常令人沮丧!
    猜你喜欢
    • 2018-11-25
    • 2016-07-31
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 2011-04-15
    • 2019-10-29
    相关资源
    最近更新 更多