Siri集成支付问题

12
在我的应用程序中,我只支持欧元和美元货币。因此,当用户尝试使用Siri发送英镑等货币的付款时,我会要求他在欧元和美元之间进行选择。
之后,我在屏幕上看到:
- 100美元 - 100欧元
如果我在`intent.currencyAmount!.currencyCode`中选择了100美元,我总是得到英镑(但用户选择的是美元)。这非常奇怪。
这是我的代码:
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]
}
更新:如何重现(根据David的问题):
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启动:如果你选择了人民币或其他非常规货币,然后在代码中让你选择欧元或美元,但在RESOLVE函数中(当Siri想要解决更多货币时调用),你将得到人民币(因此你不需要添加任何像David所要求的按钮代码,因为所有按钮界面都将由Siri提供)。


1
我在这段简短的代码片段中没有看到错误。也许你想发布Button或其他接收用户交互的元素的代码。 - David Seek
1
我认为这可能是苹果的错误,因为如果我选择美元,Siri 立即给我英镑货币,这非常奇怪。 - Paul T.
1
好的,但如果你不想发布代码,那么假设你是正确的,并且进一步假设苹果框架中存在一个错误,你对这个线程有什么期望? - David Seek
1
我已经为您更新了指令。正如您所见,您不需要任何按钮代码,因为Siri将提供所有按钮接口。因此,您可以尝试复制相同的问题,但在此之前,您需要创建意图扩展。如果在Apple框架中存在错误,我认为可能有任何解决方法,可以让代码正常工作。 - Paul T.
2个回答

3
我创建了这个问题: 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)

你能否附上完整的代码,包括解决(如果有),确认,处理方法?因为我想尝试你的代码,因为我的问题发生在确认方法之前,在解决方法中发生,所以如果我的解决方法保持不变,确认方法将永远不会被调用。而且在你的问题中,@Reem用户说这个解决方案对他没有帮助,所以我想尝试整个代码。 - Paul T.
1
我思考了一下,我不明白:如果我没有currencyAmount的resolve方法,我就不能确认他的货币,因为他可能选择了GBP货币,但应用程序不支持它。但是,如果我有resolveCurrencyAmount方法,我不明白如何在这个方法中确定何时需要返回completion(INCurrencyAmountResolutionResult.success),因为唯一的问题情况是当货币是GBP时,但在这种情况下,我将始终要求用户在可能的货币之间进行选择,并且这将是无休止的。所以,如果您能提供几乎完整的代码,那将非常好。 - Paul T.
1
在代码中添加了注释,指明您应该创建INpaymentRecord。 - user3292998
1
  1. 在这种情况下,这是行不通的,因为正如我之前所说的那样,确认函数永远不会被调用,因为用户将无休止地看到Siri窗口,在其中选择EUR和USD之间(因为在resolve方法中,当用户选择USD时,我将得到GPB,这就是为什么我不断让用户在货币之间进行选择)。
  2. 请发布您的sendMoneyIntentHandlingProtocol的完整代码(您可以删除非常个人化和不太重要的代码部分)。
  3. 请不要编辑我的代码(因为stackoverflow的编辑器不允许这样做,而且很难看到您的编辑)。
- Paul T.

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

希望这能有所帮助。

如果用户没有提供金额,则您可以将其分配为0印度卢比,但我需要用户输入金额和货币,因此我需要resolveAmount函数,但是如果我有这个函数,如果货币错误(但它经常错误),则confirm函数将永远不会被执行。 - Paul T.
我不明白你所说的“如果货币不正确,确认功能将不会被执行”的意思? - sudhanshu-shishodia
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Paul T.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接