简体   繁体   English

Siri Integration for payment issue

[英]Siri Integration for payments issue

In my application I support only EUR and USD currency. 在我的申请中,我只支持欧元和美元货币。 So when user tries to send payment with Siri to GBP, for example, I ask him to choose between EUR and USD. 因此,当用户尝试使用Siri向GBP发送付款时,我要求他在EUR和USD之间进行选择。

After that on the screen I see: 之后在屏幕上我看到:

  • 100 $ 100美元
  • 100 EUR 100欧元

If I choose 100$ in intent.currencyAmount!.currencyCode I always have GBP (but user chose dollars). 如果我在intent.currencyAmount!.currencyCode选择100 $ intent.currencyAmount!.currencyCode我总是有GBP(但是用户选择了美元)。 It's very strange. 这很奇怪。

Here is my code: 这是我的代码:

func resolveCurrencyAmount(forSendPayment intent: INSendPaymentIntent, with completion: @escaping (INCurrencyAmountResolutionResult) -> Void) {
        if let currencyAmount = intent.currencyAmount { // need to check if we have proper value
            if let amount = currencyAmount.amount {

                if amount.doubleValue == 0 { // wrong amount
                    completion(INCurrencyAmountResolutionResult.unsupported())
                    return
                }

                if let currencyCode = currencyAmount.currencyCode {
                    if let _ = EnumCurrency(rawValue: currencyCode) { // we found currency code that we know
                        completion(INCurrencyAmountResolutionResult.success(with: INCurrencyAmount(amount: NSDecimalNumber(value: abs(amount.doubleValue)), currencyCode: currencyCode)))
                        return
                    }
                }


                // if we are here so we don't have proper currency, try to offer user to choose the same amount but with all possible currencies
                let disambiguationArray: [INCurrencyAmount] = EnumCurrency.allValues.map({ (currency) -> INCurrencyAmount in
                    return INCurrencyAmount(amount: NSDecimalNumber(value: abs(amount.doubleValue)), currencyCode: currency.rawValue)
                })
                completion(INCurrencyAmountResolutionResult.disambiguation(with: disambiguationArray))
            }
        }
        else { // we don't have value
            completion(INCurrencyAmountResolutionResult.needsValue())
        }
    }

enum EnumCurrency : String {
    case EUR = "EUR"
    case USD = "USD"

    static let allValues = [EUR, USD]
}

Update: how to reproduce (according to David question): 更新:如何重现 (根据大卫的问题):

1) create a new intent extantion 1)创建一个新的意图extantion

2) in plist file leave only one type of intent: http://take.ms/pt16N 2)在plist文件中只留下一种意图: http//take.ms/pt16N

3) Your IntentHandler class (will be created by xCode) must confirm to INSendPaymentIntentHandling protocol 3)您的IntentHandler类(将由xCode创建)必须确认INSendPaymentIntentHandling协议

4) In IntentHandler class add this: 4)在IntentHandler类中添加:

func resolveCurrencyAmount(forSendPayment intent: INSendPaymentIntent, with completion: @escaping (INCurrencyAmountResolutionResult) -> Void) {
            if let currencyAmount = intent.currencyAmount { // need to check if we have proper value
                if let amount = currencyAmount.amount {

                    if amount.doubleValue == 0 { // wrong amount


                 completion(INCurrencyAmountResolutionResult.unsupported())
                    return
                }

                if let currencyCode = currencyAmount.currencyCode {
                    if let _ = EnumCurrency(rawValue: currencyCode) { // we found currency code that we know
                        completion(INCurrencyAmountResolutionResult.success(with: INCurrencyAmount(amount: NSDecimalNumber(value: abs(amount.doubleValue)), currencyCode: currencyCode)))
                        return
                    }
                }


                // if we are here so we don't have proper currency, try to offer user to choose the same amount but with all possible currencies
                let disambiguationArray: [INCurrencyAmount] = EnumCurrency.allValues.map({ (currency) -> INCurrencyAmount in
                    return INCurrencyAmount(amount: NSDecimalNumber(value: abs(amount.doubleValue)), currencyCode: currency.rawValue)
                })
                completion(INCurrencyAmountResolutionResult.disambiguation(with: disambiguationArray))
            }
        }
        else { // we don't have value
            completion(INCurrencyAmountResolutionResult.needsValue())
        }
    }

enum EnumCurrency : String {
    case EUR = "EUR"
    case USD = "USD"

    static let allValues = [EUR, USD]
}

// MARK: - Confirm

    func confirm(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) {
// success
        completion(INSendPaymentIntentResponse(code: INSendPaymentIntentResponseCode.success, userActivity: nil))

}

// MARK: - Handle

    func handle(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) {

// just for test
completion(INSendPaymentIntentResponse(code: .failureRequiringAppLaunch, userActivity: userActivity))
}

5) And you can launch with Siri: you will see that if you choose Chinese currency or any other not regular currency and then I in code make you to choose between EUR and USD, but after that in RESOLVE function (called when siri want to resolve currency on more time) you will get Chinese currency (so you don't need to add any code for buttons like David asked, because all the button interface will be provided by Siri) 5)你可以用Siri推出:你会看到如果你选择中国货币或任何其他非常规货币然后我在代码中让你在EUR和USD之间做出选择,但之后在RESOLVE功能中(当siri想要时调用)你可以获得中国货币(因此你不需要像大卫那样为按钮添加任何代码,因为所有按钮界面都将由Siri提供)

i created this issue: Siri and wrong currency 我创造了这个问题: Siri和错误的货币

All you need to do is confirm currency picked by user. 您需要做的就是确认用户选择的货币。 Your confirm method is wrongly implemented, you should confirm currency with something like this: 您的确认方法执行错误,您应该使用以下内容确认货币:

let response = INSendPaymentIntentResponse(code: .ready, userActivity: nil)
response.paymentRecord = INPaymentRecord(
    payee: intent.payee, 
    payer: nil, 
    currencyAmount: intent.currencyAmount, 
    paymentMethod: nil, 
    note: nil, 
    status: .pending, 
    feeAmount: nil)
completion(response)

In confirmSendPayment method, create INSendPaymentIntentResponse instance and assign a INPaymentRecord instance to paymentRecord property. 在confirmSendPayment方法中,创建INSendPaymentIntentResponse实例并将一个INPaymentRecord实例分配给paymentRecord属性。 I made a helper method to do this thing. 我做了一个辅助方法来做这件事。

func confirm(sendPayment intent: INSendPaymentIntent, completion: (INSendPaymentIntentResponse) -> Void) {
    let response = INSendPaymentIntentResponse(code: .Ready, userActivity: nil)
    response.paymentRecord = getPaymentRecord(fromIntent: intent)
    completion(response)
}

private func getPaymentRecord(fromIntent intent: INSendPaymentIntent) -> INPaymentRecord? {
    let currencyAmount = INCurrencyAmount(amount: intent.currencyAmount?.amount ?? 0.0, currencyCode: "INR")
    return INPaymentRecord(payee: intent.payee, payer: nil, currencyAmount: currencyAmount, paymentMethod: nil, note: nil, status: .Pending)
}

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM