Projects/Payments/PaymentsIntentsExtension/SendPaymentIntentHandler.swift
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
A class that implements `INSendPaymentIntentHandling` to handle `INSendPaymentIntent`s |
*/ |
import Intents |
import PaymentsFramework |
class SendPaymentIntentHandler: NSObject, INSendPaymentIntentHandling { |
// MARK: Properties |
private let paymentProvider: PaymentProvider |
private let contactLookup: ContactLookup |
// MARK: Initialization |
init(paymentProvider: PaymentProvider, contactLookup: ContactLookup) { |
self.paymentProvider = paymentProvider |
self.contactLookup = contactLookup |
} |
// MARK: INSendPaymentIntentHandling parameter resolution |
func resolvePayee(forSendPayment intent: INSendPaymentIntent, with completion: @escaping (INPersonResolutionResult) -> Void) { |
if let payee = intent.payee { |
// Lookup contacts that match the payee. |
contactLookup.lookup(displayName: payee.displayName) { contacts in |
// Build the `INIntentResolutionResult` to pass to the `completion` closure. |
let result: INPersonResolutionResult |
if let contact = contacts.first, contacts.count == 1 { |
// A single match was found, the payee was successfully resolved. |
let resolvedPayee = INPerson(contact: contact) |
result = INPersonResolutionResult.success(with: resolvedPayee) |
} |
else if contacts.isEmpty { |
// No matches were found. |
result = INPersonResolutionResult.unsupported() |
} |
else { |
/* |
More than one match was made, the user needs to clarify which |
contact they intended. |
*/ |
let people: [INPerson] = contacts.map { contact in |
return INPerson(contact: contact) |
} |
result = INPersonResolutionResult.disambiguation(with: people) |
} |
completion(result) |
} |
} |
else if let mostRecentPayee = paymentProvider.mostRecentPayment?.contact { |
// No payee has been provided, suggest the last payee. |
let result = INPersonResolutionResult.confirmationRequired(with: INPerson(contact: mostRecentPayee)) |
completion(result) |
} |
else { |
// No payee has been provided and there was no previous payee. |
let result = INPersonResolutionResult.needsValue() |
completion(result) |
} |
} |
func resolveCurrencyAmount(forSendPayment intent: INSendPaymentIntent, with completion: @escaping (INCurrencyAmountResolutionResult) -> Void) { |
let result: INCurrencyAmountResolutionResult |
// Resolve the currency amount. |
if let currencyAmount = intent.currencyAmount, let amount = currencyAmount.amount, let currencyCode = currencyAmount.currencyCode { |
if amount.intValue <= 0 { |
// The amount needs to be a positive value. |
result = INCurrencyAmountResolutionResult.unsupported() |
} |
else if let currencyCode = paymentProvider.validate(currencyCode) { |
// Make a new `INCurrencyAmount` with the resolved currency code. |
let resolvedAmount = INCurrencyAmount(amount: amount, currencyCode: currencyCode) |
result = INCurrencyAmountResolutionResult.success(with: resolvedAmount) |
} |
else { |
// The currency is unsupported. |
result = INCurrencyAmountResolutionResult.unsupported() |
} |
} |
else if let mostRecentPayment = paymentProvider.mostRecentPayment { |
// No amount has been provided, suggest the last amount sent. |
let suggestedAmount = INCurrencyAmount(amount: mostRecentPayment.amount, currencyCode: mostRecentPayment.currencyCode) |
result = INCurrencyAmountResolutionResult.confirmationRequired(with: suggestedAmount) |
} |
else { |
// No amount has been provided and there was no previous payment. |
result = INCurrencyAmountResolutionResult.needsValue() |
} |
completion(result) |
} |
// MARK: INSendPaymentIntentHandling intent confirmation |
func confirm(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) { |
guard let payee = intent.payee, |
let payeeHandle = payee.personHandle, |
let currencyAmount = intent.currencyAmount, |
let amount = currencyAmount.amount, |
let currencyCode = currencyAmount.currencyCode |
else { |
completion(INSendPaymentIntentResponse(code: .failure, userActivity: nil)) |
return |
} |
contactLookup.lookup(emailAddress: payeeHandle.value) { contact in |
guard let contact = contact else { |
completion(INSendPaymentIntentResponse(code: .failure, userActivity: nil)) |
return |
} |
let payment = Payment(contact: contact, amount: amount, currencyCode: currencyCode) |
self.paymentProvider.canSend(payment) { success, error in |
guard success else { |
completion(INSendPaymentIntentResponse(code: .failure, userActivity: nil)) |
return |
} |
let response = INSendPaymentIntentResponse(code: .success, userActivity: nil) |
response.paymentRecord = self.makePaymentRecord(for: intent) |
completion(response) |
} |
} |
} |
// MARK: INSendPaymentIntentHandling intent handling |
func handle(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) { |
guard let payee = intent.payee, |
let payeeHandle = payee.personHandle, |
let currencyAmount = intent.currencyAmount, |
let amount = currencyAmount.amount, |
let currencyCode = currencyAmount.currencyCode |
else { |
completion(INSendPaymentIntentResponse(code: .failure, userActivity: nil)) |
return |
} |
contactLookup.lookup(emailAddress: payeeHandle.value) { contact in |
guard let contact = contact else { |
completion(INSendPaymentIntentResponse(code: .failure, userActivity: nil)) |
return |
} |
let payment = Payment(contact: contact, amount: amount, currencyCode: currencyCode) |
self.paymentProvider.send(payment) { success, _, _ in |
guard success else { |
completion(INSendPaymentIntentResponse(code: .failure, userActivity: nil)) |
return |
} |
let response = INSendPaymentIntentResponse(code: .success, userActivity: nil) |
response.paymentRecord = self.makePaymentRecord(for: intent) |
completion(response) |
} |
} |
} |
// MARK: Convenience |
func makePaymentRecord(for intent: INSendPaymentIntent, status: INPaymentStatus = .completed) -> INPaymentRecord? { |
let paymentMethod = INPaymentMethod(type: .unknown, name: "Payments Sample", identificationHint: nil, icon: nil) |
return INPaymentRecord( |
payee: intent.payee, |
payer: nil, |
currencyAmount: intent.currencyAmount, |
paymentMethod: paymentMethod, |
note: intent.note, |
status: status |
) |
} |
} |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-09-13