Сири-интеграция для платежей

В моем заявлении я поддерживаю только валюту EUR и USD. Например, когда пользователь пытается отправить платеж с Siri в GBP, я прошу его выбрать между EUR и USD.

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

  • 100 $
  • 100 EUR

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

Вот мой код:

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) создать новое намерение extantion

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)

Ответ 1

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

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

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)

Ответ 2

В методе 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)
}

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