【问题标题】:Apple pay billing address tax calculation苹果支付账单地址税计算
【发布时间】:2021-10-24 17:48:17
【问题描述】:

我正在尝试通过以下流程使用 Stripe 实施 Apple pay

  • 选择产品
  • 点击apple pay(显示的商品摘要不含税)
  • 在选择/更新帐单地址后,将计算税金并更新 paymentSummaryItems 以显示最终金额
  • 付款

但我找不到在付款授权之前提取帐单信息以计算和应用税款的方法。对于送货地址,有一个委托回调

func applePayContext(_ context: STPApplePayContext, didSelectShippingContact contact: PKContact, handler: @escaping (PKPaymentRequestShippingContactUpdate) -> Void) {}

每次更新送货地址时都会调用它,但账单地址不一样。

这是正确的流程还是应该在显示PKPaymentAuthorizationController之前计算税金?

【问题讨论】:

    标签: ios swift stripe-payments applepay


    【解决方案1】:

    结果证明帐单地址有回调,但它在PKPaymentAuthorizationControllerDelegate

        // update the summary items in response to the card type changing (for example, applying credit card surcharges)
        //
        // The delegate will receive no further callbacks except paymentAuthorizationControllerDidFinish:
        // until it has invoked the completion block.
        
        @available(iOS 11.0, *)
        optional func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void)
    

    问题是 Stripe 的 STPApplePayContext 没有实现它,因此没有将它传递给它自己的代表 STPApplePayContextDelegate,就像它对送货地址所做的那样。

    快速的解决方案是自己实现:

    struct AssociatedKeys {
        static var postalCodeCompletion: String = "postalCodeCompletionKey"
    }
    
    extension STPApplePayContext {
        // 1
        var didUpdatePostalCodeCompletion: ((CNPostalAddress, (PKPaymentRequestPaymentMethodUpdate) -> Void) -> ())? {
            get {
                guard let value = objc_getAssociatedObject(self, &AssociatedKeys.postalCodeCompletion) as? (CNPostalAddress, (PKPaymentRequestPaymentMethodUpdate) -> Void) -> () else {
                    return nil
                }
                return value
            }
            set(newValue) {
                objc_setAssociatedObject(self, &AssociatedKeys.postalCodeCompletion, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
        
        @objc
        public func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController,
                                                   didSelectPaymentMethod paymentMethod: PKPaymentMethod,
                                                   handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) {
            // 2
            guard let address = paymentMethod.billingAddress?.postalAddresses.first?.value else {
                let error = PKPaymentError(.billingContactInvalidError)
                let paymenMethodUpdate = PKPaymentRequestPaymentMethodUpdate(errors: [error], paymentSummaryItems: [])
                completion(paymenMethodUpdate)
                
                return
            }
            
            didUpdatePostalCodeCompletion?(address, completion)
        }
    }
    
    1. 由于我们使用扩展,关联对象是存储值的方式
    2. 我只需要这里的地址(是的,它不完整)所以我只将它传递给存储的完成 + 来自委托的完成

    注意:您必须在准备好计算后立即从委托中调用完成

    使用方法:

            let merchantIdentifier = "your merch ID"
            let paymentRequest = StripeAPI.paymentRequest(withMerchantIdentifier: merchantIdentifier, country: "US", currency: "USD")
    
            // 1
            paymentRequest.paymentSummaryItems = []
    
            // Initialize an STPApplePayContext instance
            if let applePayContext = STPApplePayContext(paymentRequest: paymentRequest, delegate: self) {
                // Present Apple Pay payment sheet
                
                applePayContext.didUpdatePostalCodeCompletion = { address, completion in
                    
                    // 2
                    let newSummaryItems = [
                        PKPaymentSummaryItem(label: "my new fancy hat", amount: 1),
                        PKPaymentSummaryItem(label: "Tax", amount: 1),
                        PKPaymentSummaryItem(label: "Total", amount: 2)
                    ]
                    
                    let pkpaymentrequest = PKPaymentRequestPaymentMethodUpdate(errors: nil, paymentSummaryItems: newSummaryItems)
                    // 3
                    completion(pkpaymentrequest)
                }
                applePayContext.presentApplePay(completion: nil)
    
            } else {
                print("There is a problem with your Apple Pay configuration")
            }
        }
    
    1. 生成初始汇总项
    2. 根据地址进行任何计算以获取税款或任何额外费用
    3. 您必须调用从 PKPaymentAuthorizationControllerDelegate 传递的完成(尚未测试,但基于 didAuthorizePayment,您有大约 30 秒的时间来完成)

    【讨论】:

    • 嗨,@wootage 感谢您的回答。但是 applePayContext.didUpdatePostalCodeCompletion 没有执行。
    • 哦,它只进入“paymentSummeryitem”,而不是 requiredShippingContactFields。是否可以在 requiredShippingContactFields 上添加这个?
    • didSelectShippingContact 在条带框架中实现,并有自己的委托STPApplePayContextDelegate.applePayContext(_:didSelectShippingContact:handler:))。您可以在课堂上实现它并处理运输部分
    【解决方案2】:

    在没有送货地址的情况下使用 Apple Pay 时,您应在显示 Apple Pay 表之前收集计算税款所需的信息,并在要求您的客户付款时包括税款信息(这意味着税款应作为一个单独的项目显示Apple Pay 表上)。

    如果您要收集送货地址,您将使用STPApplePayContextDelegate 根据送货地址计算税费,以便在客户选择/更改送货地址时更新 Apple Pay 表上显示的税费。

    出于隐私原因,Apple Pay 不会在客户确认付款之前向您提供账单地址,并且在确认付款之前仅提供部分送货地址:

    为了保护隐私,发货信息是匿名的。例如,在美国,它只包括城市、州和邮政编码。这提供了足够的信息来计算运费,而在用户实际批准购买之前不会泄露敏感信息。

    【讨论】:

      猜你喜欢
      • 2016-03-23
      • 2019-05-17
      • 1970-01-01
      • 2014-12-15
      • 2012-05-05
      • 1970-01-01
      • 2017-04-22
      • 2021-08-01
      • 2018-01-30
      相关资源
      最近更新 更多