Сири-интеграция для платежей
В моем заявлении я поддерживаю только валюту EUR и USD. Например, когда пользователь пытается отправить платеж с Siri в GBP, я прошу его выбрать между EUR и USD.
После этого на экране я вижу:
Если я выбираю 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)
}
Надеюсь, что это поможет.