Link Transactions to Receipts
Introduction
We provide the ability to submit a bank account transaction identifier when capturing a paper receipt.
This provides facilitates creating link between a particular receipt and a bank transaction.
This is helpful if an integrating app requires the ability to display a receipt associated with a particular bank account transaction, or display all receipts associated with a particular bank account.
Attaching a Transaction Id to the Receipt Capture Flow
- Initialize Transaction
(SBLTransaction
in Objective-C) with
externalAccountTransactionID. - Initialize CaptureFlowCoordinator
with the host
UIViewControllerthat will be presenting the transaction linking flow. - Set
delegateof above created instance to the hostUIViewController. - Start transaction linking flow by passing
Transactionobject created inStep 1usingstart(transaction:)method on instance ofCaptureFlowCoordinatorcreated inStep 2 - Retain instance of coordinator.
- Optionally (recommended) register a transaction observer with SBDataEvent
, so you can provide custom handling of various receipt uploading states for a provided
Transaction.
Note:
- The
Transactionobject represents a Sensibill receipt uploading transaction. - The bank account transaction identifier (called
externalAccountTransactionIDbelow) is a free-form string that supports various transaction identifiers. It can be provided by the integrator via theprivateMetaData.accountTransactionIDproperty of theTransactionobject. - Itβs important to differentiate the bank account transaction identifier from the Sensibill transaction identifier (a read-only property called
remoteID, not mentioned in example below).
Example
import Sensibill
class ViewController: UIViewController {
// MARK: - Private Properties
private var captureFlowCoordinator: CaptureFlowCoordinator?
// MARK: - Private Methods
private func presentReceiptCapture(externalAccountTransactionID: String) {
// Step 1
let sensibillTransaction = Transaction(externalAccountTransactionID: externalAccountTransactionID)
// Step 2
let coordinator = CaptureFlowCoordinator(host: self)
// Step 3
coordinator.delegate = self
// Step 4
coordinator.start(transaction: sensibillTransaction)
// Step 5
self.captureFlowCoordinator = coordinator
// Optional Step 6: uncomment the following line to enable (function is shown in section below)
// registerTransactionObserver(externalAccountTransactionID: externalAccountTransactionID)
}
}
// MARK: - CaptureFlowCoordinatorDelegate
extension ViewController: CaptureFlowCoordinatorDelegate {
public func coordinatorDidFinishCapture(_ coordinator: CaptureFlowCoordinator, transactions: [Transaction]) {
self.captureFlowCoordinator = nil
}
public func coordinatorDidCancelCapture(_ coordinator: CaptureFlowCoordinator) {
self.captureFlowCoordinator = nil
}
}When launching the Receipt Capture Flow , a transaction id can be provided. If a transaction id is provided, the transaction id will be attached as metadata to any receipt object that is created as a result of the capture flow.
For reference, the following snippets would be inserted in place of the code in step 3 of the Use Receipt Capture guide .
Kotlin
val myTransaction: MyTransactionModel // Your transaction model
captureFlow.launchCaptureFlow(
captureFlowListener,
externalAccountTransactionId = myTransaction.id
)Java
final MyTransactionModel myTransaction; // Your transaction model
captureFlow.launchCaptureFlow(
captureFlowListener,
CaptureFlowCoordinator.Companion.getDEFAULT_CONFIG()
externalAccountTransactionId = myTransaction.getId()
);Web SDK does not support Transaction Linking
Monitoring uploads
The following example demonstrates receiving and handling status updates related to uploading a Sensibill transaction with a provided externalAccountTransactionID.
This function can be called right before presenting capture (as shown above in presentReceiptCapture example), or earlier.
func registerTransactionObserver(externalAccountTransactionID: String) {
SBDataEvent.sharedManager().addTransactionObserver(self) { (type, transaction) in
guard type == .statusUpdate else {
// Different notification type is received (not in scope for this example)
return
}
guard let transaction = transaction else {
// Failed to unwrap transaction object (normally shouldn't happen)
return
}
guard transaction.privateMetaData?.externalAccountTransactionID == externalAccountTransactionID else {
// Notification is for a different transaction, and can be ignored
return
}
switch transaction.status {
case .uploading:
// Receipt image was locally validated and is uploading to the server
break
case .processing:
// Receipt image was accepted by the Sensibill API server for processing
break
case .failed:
// Receipt processing failed
// Note: this state is set for failure on any stage
// Optional step: check transaction.error for possible cause
break
case .completed:
// Receipt was processed successfully
// It must now have transaction.receiptID
guard let receiptID = transaction.receiptID else {
// Error: receipt ID is not set for complete transaction
return
}
break
case .unknown:
// Initial transaction status
// (no notification is sent for this status)
break
@unknown default:
// SDK introduced a new status, please review Migration Guide.
break
}
}
}Unlink linked external account transaction associated with receipt.
The following example demonstrates how to unlink external account transaction associated with specific receipt by submitting edit receipt request to Sensibill API using associated receiptID.
func unlinkAccountTransaction(forReceiptID receiptID: String) {
let editRequestMethod = "PUT"
let ediReceiptRequestEndPoint = URLConstant.editReceiptRequestEndPoint(receiptID: receiptID)
let editReceiptRequestParameters = ["edit": ["accountTransactionData": ["id": ""]]]
let request = Request(authenticationType: .token,
method: editRequestMethod,
endPoint: ediReceiptRequestEndPoint,
parameters: editReceiptRequestParameters,
data: nil)
request.start { [weak self] (response, error, code) in
if let _ = response, code == 200 {
// Unlink successful.
return
}
// Unlink failed.
}
}