Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

After that on the screen I see:

  • 100 $
  • 100 EUR

If I choose 100$ in intent.currencyAmount!.currencyCode I always have GBP (but user chose dollars). 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

2) in plist file leave only one type of intent: http://take.ms/pt16N

3) Your IntentHandler class (will be created by xCode) must confirm to INSendPaymentIntentHandling protocol

4) In IntentHandler class add this:

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)

like image 276
Paul T. Avatar asked Oct 24 '16 09:10

Paul T.


People also ask

How do I integrate with Siri?

The most important part of integrating Siri in your app is implementing the intent handler. To do so, you'll need to add the “Intents Extension” target to your app by selecting “File–>New–>Target” and then selecting “Intents Extension.” After that you'll be asked to enter a name. Let's call it “ SiriIntentExtension .”

Is there a Siri API?

The App Intents API essentially integrates third-party apps into the Siri ecosystem more efficiently. It allows users to run and control third-party apps through Siri as though they were native Apple apps like Mail or Calendar.

What can you do with SiriKit?

SiriKit groups intents into domains based on the type of app that's likely to support them. Manage vehicle door locks and get the vehicle's status. Create and manage notes and to-do list items. Listen and control audio through Siri Intents, or listen and watch media content from your app with shortcuts.


1 Answers

i created this issue: Siri and wrong currency

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)
like image 73
user3292998 Avatar answered Sep 21 '22 02:09

user3292998