美文网首页iOS开发
Create a Shopping App with Apple

Create a Shopping App with Apple

作者: _浅墨_ | 来源:发表于2023-11-07 21:57 被阅读0次

    支付逻辑

    
    // Note: The code below was taken from the sample app from https://developer.apple.com/documentation/passkit/apple_pay/offering_apple_pay_in_your_app - shortened and adapted for this application
    
    import Foundation
    import PassKit
    
    // Typealias so we don't always need to rewrite the type (Bool) -> Void
    typealias PaymentCompletionHandler = (Bool) -> Void
    
    class PaymentHandler: NSObject {
        
        var paymentController: PKPaymentAuthorizationController?
        var paymentSummaryItems = [PKPaymentSummaryItem]()
        var paymentStatus = PKPaymentAuthorizationStatus.failure
        var completionHandler: PaymentCompletionHandler?
        
        static let supportedNetworks: [PKPaymentNetwork] = [
            .visa,
            .masterCard,
        ]
        
        // This applePayStatus function is not used in this app. Use it to check for the ability to make payments using canMakePayments(), and check for available payment cards using canMakePayments(usingNetworks:). You can also display a custom PaymentButton according to the result. See https://developer.apple.com/documentation/passkit/apple_pay/offering_apple_pay_in_your_app under "Add the Apple Pay Button" section
        class func applePayStatus() -> (canMakePayments: Bool, canSetupCards: Bool) {
            return (PKPaymentAuthorizationController.canMakePayments(),
                    PKPaymentAuthorizationController.canMakePayments(usingNetworks: supportedNetworks))
        }
        
        // Define the shipping methods (this app only offers delivery) and the delivery dates
        func shippingMethodCalculator() -> [PKShippingMethod] {
            
            let today = Date()
            let calendar = Calendar.current
            
            let shippingStart = calendar.date(byAdding: .day, value: 5, to: today)
            let shippingEnd = calendar.date(byAdding: .day, value: 10, to: today)
            
            if let shippingEnd = shippingEnd, let shippingStart = shippingStart {
                let startComponents = calendar.dateComponents([.calendar, .year, .month, .day], from: shippingStart)
                let endComponents = calendar.dateComponents([.calendar, .year, .month, .day], from: shippingEnd)
                
                let shippingDelivery = PKShippingMethod(label: "Delivery", amount: NSDecimalNumber(string: "0.00"))
                shippingDelivery.dateComponentsRange = PKDateComponentsRange(start: startComponents, end: endComponents)
                shippingDelivery.detail = "Sweaters sent to your address"
                shippingDelivery.identifier = "DELIVERY"
                
                return [shippingDelivery]
            }
            return []
        }
        
        func startPayment(products: [Product], total: Int, completion: @escaping PaymentCompletionHandler) {
            completionHandler = completion
            
            // Iterate over the products array, create a PKPaymentSummaryItem for each and append to the paymentSummaryItems array
            products.forEach { product in
                let item = PKPaymentSummaryItem(label: product.name, amount: NSDecimalNumber(string: "\(product.price).00"), type: .final)
                paymentSummaryItems.append(item)
            }
            
            // Add a PKPaymentSummaryItem for the total to the paymentSummaryItems array
            let total = PKPaymentSummaryItem(label: "Total", amount: NSDecimalNumber(string: "\(total).00"), type: .final)
            paymentSummaryItems.append(total)
            
            // Create a payment request and add all data to it
            let paymentRequest = PKPaymentRequest()
            paymentRequest.paymentSummaryItems = paymentSummaryItems // Set paymentSummaryItems to the paymentRequest
            paymentRequest.merchantIdentifier = "merchant.io.designcode.sweatershopapp"
            paymentRequest.merchantCapabilities = .capability3DS // A security protocol used to authenticate users
            paymentRequest.countryCode = "US"
            paymentRequest.currencyCode = "USD"
            paymentRequest.supportedNetworks = PaymentHandler.supportedNetworks // Types of cards supported
            paymentRequest.shippingType = .delivery
            paymentRequest.shippingMethods = shippingMethodCalculator()
            paymentRequest.requiredShippingContactFields = [.name, .postalAddress]
            
            // Display the payment request in a sheet presentation
            paymentController = PKPaymentAuthorizationController(paymentRequest: paymentRequest)
            paymentController?.delegate = self
            paymentController?.present(completion: { (presented: Bool) in
                if presented {
                    debugPrint("Presented payment controller")
                } else {
                    debugPrint("Failed to present payment controller")
                    if let completionHandler = self.completionHandler {
                        completionHandler(false)
                    }
                }
            })
        }
    }
    
    // Set up PKPaymentAuthorizationControllerDelegate conformance
    extension PaymentHandler: PKPaymentAuthorizationControllerDelegate {
    
        // Handle success and errors related to the payment
        func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) {
    
            let errors = [Error]()
            let status = PKPaymentAuthorizationStatus.success
    
            self.paymentStatus = status
            completion(PKPaymentAuthorizationResult(status: status, errors: errors))
        }
    
        func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) {
            controller.dismiss {
                // The payment sheet doesn't automatically dismiss once it has finished, so dismiss the payment sheet
                DispatchQueue.main.async {
                    if self.paymentStatus == .success {
                        if let completionHandler = self.completionHandler {
                            completionHandler(true)
                        }
                    } else {
                        if let completionHandler = self.completionHandler {
                            completionHandler(false)
                        }
                    }
                }
            }
        }
    }
    
    

    开始付款

    当用户点击“使用Apple Pay结账”按钮时,他们将看到Apple Pay的付款表单。

    首先,让我们处理 CartManager。在 CartManager类的顶部添加以下变量。我们创建了一个 PaymentHandler 实例,以及一个名为 paymentSuccess 的发布变量,它让我们知道付款是否成功。

    // ./CartManager.swift
    
    let paymentHandler = PaymentHandler()
    @Published var paymentSuccess = false
    

    CartManager 类底部,创建 pay 方法。

    // ./CartManager.swift
    
    func pay() {
        paymentHandler.startPayment(products: products, total: total) { success in
            self.paymentSuccess = success
            self.products = []
            self.total = 0
        }
    }
    

    接下来处理UI。

    // ./Views/CartView.swift
    
    PaymentButton(action: cartManager.pay)
    

    CartView 中,如果付款成功,我们将显示一条感谢用户购买的消息。否则,我们将显示检查用户购物车中产品数量。

    // ./Views/CartView.swift
    
    if cartManager.paymentSuccess {
        Text("感谢您的购买!您很快就会在我们的舒适毛衣中感到温暖!您还将很快收到确认邮件。")
            .padding()
    } else {
        // 如果 cartManager.products.count > 0 代码...
    }
    

    重置 CartView

    一旦用户完成购买并返回到 ContentView,我们希望将 CartManager 中的 paymentSuccess 状态重置为 false。

    // ./CartManager.swift
    
    @Published var paymentSuccess = false // 删除 private(set) 部分
    

    CartView 上的 ScrollView 中添加onDisappear 逻辑,以便用户可以进行另一次购买。

    // ./Views/CartView.swift
    
    .onDisappear {
        if cartManager.paymentSuccess {
            cartManager.paymentSuccess = false
        }
    }
    

    测试整个App

    效果图

    您可以单击删除图标来从购物车中删除物品,产品列表和价格会立即更新。

    当单击 “使用Apple Pay结账” 按钮时,我们会看到一个付款表单。一旦输入了所有必要的信息并付款,我们将听到一个“TING”的声音,表示成功支付了。

    然后,Apple Pay表单将被关闭,我们将回到CartView,并收到一条感谢购买的消息。

    当返回到ContentView并再次进入CartView时,将看到完成购买后购物车被清空。接下来,可以进行另一次购买。

    项目源码:https://github.com/MFiOS/SweaterShopApp

    相关文章

      网友评论

        本文标题:Create a Shopping App with Apple

        本文链接:https://www.haomeiwen.com/subject/wlzaidtx.html