Apple 支付账单地址税费计算
Apple pay billing address tax calculation
我正在尝试通过以下流程使用 Stripe 实施 Apple 支付
- select 产品
- tap apple pay(item/s 的摘要显示不含税)
- 根据 selecting/updating 帐单地址,计算税金并
paymentSummaryItems
更新以显示最终金额
- 执行付款
但我找不到在付款授权之前提取账单信息以计算和应用税款的方法。对于送货地址,有一个委托回调
func applePayContext(_ context: STPApplePayContext, didSelectShippingContact contact: PKContact, handler: @escaping (PKPaymentRequestShippingContactUpdate) -> Void) {}
每次更新送货地址时都会调用它,但与结算地址不同。
这是正确的流程还是应该在显示 PKPaymentAuthorizationController
之前计算税金?
在没有送货地址的情况下使用 Apple Pay 时,您应该在显示 Apple Pay 之前收集计算税费所需的信息 sheet 并在要求您的客户付款时包含税务信息(这意味着税费应该是在 Apple Pay sheet).
上显示为不同的行项目
如果您要收集送货地址,您将使用 STPApplePayContextDelegate
根据送货地址计算税费,以更新 Apple Pay sheet 上显示的税费作为客户 selects/changes 他们的送货地址。
出于隐私原因,Apple Pay 在客户确认付款之前不向您提供账单地址,并且在确认付款之前仅提供部分送货地址:
To maintain privacy, the shipping information is anonymized. For example, in the United States it only includes the city, state, and zip code. This provides enough information to calculate shipping costs, without revealing sensitive information until the user actually approves the purchase.
原来账单地址有回调但是在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)
}
}
- 由于我们使用扩展,因此关联对象是存储值的方式
- 我只需要这里的地址(是的,它不完整)所以我只将它传递给存储完成+来自委托的完成
注意:一旦你准备好计算,你必须从委托中调用完成
使用方法:
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")
}
}
- 生成初始汇总项
- 根据地址进行任何计算以获得税金或任何额外费用
- 您必须调用从
PKPaymentAuthorizationControllerDelegate
传递的完成(尚未测试但基于 didAuthorizePayment
您有大约 30 秒的时间来完成)
我正在尝试通过以下流程使用 Stripe 实施 Apple 支付
- select 产品
- tap apple pay(item/s 的摘要显示不含税)
- 根据 selecting/updating 帐单地址,计算税金并
paymentSummaryItems
更新以显示最终金额 - 执行付款
但我找不到在付款授权之前提取账单信息以计算和应用税款的方法。对于送货地址,有一个委托回调
func applePayContext(_ context: STPApplePayContext, didSelectShippingContact contact: PKContact, handler: @escaping (PKPaymentRequestShippingContactUpdate) -> Void) {}
每次更新送货地址时都会调用它,但与结算地址不同。
这是正确的流程还是应该在显示 PKPaymentAuthorizationController
之前计算税金?
在没有送货地址的情况下使用 Apple Pay 时,您应该在显示 Apple Pay 之前收集计算税费所需的信息 sheet 并在要求您的客户付款时包含税务信息(这意味着税费应该是在 Apple Pay sheet).
上显示为不同的行项目如果您要收集送货地址,您将使用 STPApplePayContextDelegate
根据送货地址计算税费,以更新 Apple Pay sheet 上显示的税费作为客户 selects/changes 他们的送货地址。
出于隐私原因,Apple Pay 在客户确认付款之前不向您提供账单地址,并且在确认付款之前仅提供部分送货地址:
To maintain privacy, the shipping information is anonymized. For example, in the United States it only includes the city, state, and zip code. This provides enough information to calculate shipping costs, without revealing sensitive information until the user actually approves the purchase.
原来账单地址有回调但是在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)
}
}
- 由于我们使用扩展,因此关联对象是存储值的方式
- 我只需要这里的地址(是的,它不完整)所以我只将它传递给存储完成+来自委托的完成
注意:一旦你准备好计算,你必须从委托中调用完成
使用方法:
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")
}
}
- 生成初始汇总项
- 根据地址进行任何计算以获得税金或任何额外费用
- 您必须调用从
PKPaymentAuthorizationControllerDelegate
传递的完成(尚未测试但基于didAuthorizePayment
您有大约 30 秒的时间来完成)