Reputation: 5038
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:
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)
Upvotes: 12
Views: 1157
Reputation: 1108
In confirmSendPayment method, create INSendPaymentIntentResponse instance and assign a INPaymentRecord instance to paymentRecord property. 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.
Upvotes: 0
Reputation: 209
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)
Upvotes: 3