Интеграция Siri для выдачи платежей

В моем приложении я поддерживаю только евро и доллары США. Поэтому, когда пользователь пытается отправить платеж с помощью Siri, например, в фунты стерлингов, я прошу его выбрать между евро и долларами США.

После этого на экране я вижу:

  • 100 $
  • 100 евро

Если я выберу 100 долларов в intent.currencyAmount!.currencyCode, у меня всегда будут фунты стерлингов (но пользователь выбрал доллары). Это очень странно.

Вот мой код:

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]
}

Обновление: как воспроизвести (согласно вопросу Дэвида):

1) создать новое намерение расширения

2) в файле plist оставьте только один тип намерения: http://take.ms/pt16N

3) Ваш класс IntentHandler (будет создан xCode) должен подтвердить протокол INSendPaymentIntentHandling.

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) И вы можете запустить с Siri: вы увидите, что если вы выберете китайскую валюту или любую другую нестандартную валюту, а затем я в коде заставлю вас выбрать между EUR и USD, но после этого в функции RESOLVE (вызываемой, когда siri хочет разрешите валюту на большее время), вы получите китайскую валюту (поэтому вам не нужно добавлять какой-либо код для кнопок, как просил Дэвид, потому что весь интерфейс кнопок будет предоставлен Siri)


person Paul T.    schedule 24.10.2016    source источник
comment
Я не вижу ошибки в этом сокращенном коде. Возможно, вы хотите опубликовать код Button или любого другого элемента, который требует взаимодействия с пользователем.   -  person David Seek    schedule 02.11.2016
comment
нет никакой ошибки. Я думаю, что это может быть ошибка Apple, потому что очень странно, что если я выберу доллары, я сразу же получу валюту GBP от Siri.   -  person Paul T.    schedule 02.11.2016
comment
хорошо, но если вы не хотите публиковать код, предположите, что вы правы, и, кроме того, предположите, что в структуре Apple есть ошибка, чего вы ожидаете от этой темы?   -  person David Seek    schedule 02.11.2016
comment
Обновил инструкцию для вас. Как видите, вам не нужен код для кнопок, потому что весь интерфейс кнопок будет предоставлен Siri. Таким образом, вы можете попытаться воспроизвести ту же проблему, но до того, как вам нужно будет создать расширение намерений. И если в структуре Apple есть ошибка, я думаю, что есть какое-то обходное решение, которое позволит коду работать.   -  person Paul T.    schedule 03.11.2016


Ответы (2)


я создал эту проблему: Siri и неправильная валюта

Все, что вам нужно сделать, это подтвердить валюту, выбранную пользователем. Ваш метод подтверждения реализован неправильно, вы должны подтвердить валюту примерно так:

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)
person user3292998    schedule 03.11.2016
comment
Не могли бы вы добавить полный код с разрешением (если у вас есть), подтверждением, обработкой методов? (поэтому я могу попробовать ваш код, потому что моя проблема возникает до метода подтверждения, это происходит в методе Resolve, поэтому, если мой метод разрешения останется прежним, метод подтверждения никогда не будет вызван). И в вашей проблеме пользователь @Reem говорит, что это решение ему не помогло, поэтому я просто хочу попробовать весь код - person Paul T.; 04.11.2016
comment
Я подумал об этом, я не понимаю: если у меня нет метода разрешения для currencyAmount, я не могу просто подтвердить его валюту, потому что он может выбрать валюту GBP, но приложение ее не поддерживает. Но если у меня есть метод resolveCurrencyAmount, я не понимаю, как определить в этом методе, когда мне нужно вернуть завершение (INCurrencyAmountResolutionResult.success), потому что единственный случай, когда у меня есть проблема, - это когда валюта - GBP, но в этом случае я буду всегда просите пользователя выбрать между возможными валютами, и это будет бесконечно, так что будет очень хорошо, если вы можете предоставить свой почти полный код - person Paul T.; 04.11.2016
comment
добавлен комментарий в коде, где нужно создать INpaymentRecord - person user3292998; 04.11.2016
comment
1) в этом случае это не сработает, потому что, как я уже сказал, функция подтверждения никогда не будет вызываться, потому что пользователь будет бесконечно видеть окно в Siri, чтобы выбрать между EUR и USD (потому что в методе разрешения после того, как пользователь выберет USD, я получит GPB, и поэтому я бесконечно заставляю пользователя выбирать между валютами 2) пожалуйста, опубликуйте свой полный код для sendMoneyIntentHandlingProtocol (вы можете удалить очень личные и не очень важные части кода)) 3) пожалуйста, не вносите правки в мой код ( потому что редакторы stackoverflow не позволяют этого, и ваши правки трудно увидеть - person Paul T.; 05.11.2016

В методе confirmSendPayment создайте экземпляр INSendPaymentIntentResponse и назначьте экземпляр INPaymentRecord свойству paymentRecord. Я сделал для этого вспомогательный метод.

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)
}

Надеюсь это поможет.

person cheeseRoot    schedule 06.02.2017
comment
если пользователь не предоставил сумму, которую вы назначаете 0 с валютой INR, но мне нужно, чтобы пользователь ввел сумму и валюту, поэтому мне нужны функции resolveAmount, но если у меня есть эта функция, функция подтверждения никогда не будет выполнена, если валюта неправильная (но это неправильно) - person Paul T.; 07.02.2017
comment
Я не понял, что вы имели в виду, говоря, что функция подтверждения не будет выполняться, если валюта указана неверно ?? - person cheeseRoot; 07.02.2017
comment
потому что, если валюта неправильная, я попрошу выбрать между евро и долларами США, пользователь выберет, например, евро, но iOS будет думать, что он выбрал фунт стерлингов, и поэтому пользователь увидит бесконечный способ выбора между валютами - person Paul T.; 07.02.2017