Account Linking

This guide provides a brief overview for how to get started using Account Linking.

Initialize the SDK

import UIKit
import BlinkReceipt
import BlinkEReceipt

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        BRScanManager.shared().licenseKey = "YOUR-LICENSE-KEY"
        BRScanManager.shared().prodIntelKey = "YOUR-PROD-INTEL-KEY"
        BRAccountLinkingManager.shared()
        return true
    }

}

Note

A licenseKey or prodIntelKey can be obtained by emailing blinkreceipt@microblink.com.


Create account connection

Account Linking offers two UI/UX experiences when linking and verifying a merchant’s connection.

1. Host App Authentication

Using this flow, a host app can provide a native prompt for users to populate credentials. All other interactions with the merchant are done with the webview hidden in a background with exception when 2FA, Captcha or other user input is required.

Use collected credentials to create BRAccountLinkingConnection object.

let username = "user@domain.com"
let password = "secure-password"
let connection = BRAccountLinkingConnection(retailer: .walmart, username: username, password: password)
connection.configuration.dayCutoff = 30

2. Retailer Webview Authentication

This flow eliminates the need for a host app to provide any native UX to collect credentials. Instead, the SDK presents a webview with the merchant’s regular authentication protocol. The webview stays populated as the user completes whatever authentication flow is required by the merchant. The webview disappears after a successful authentication is complete.

Create BRAccountLinkingConnection object by only specifying the retailer

let connection = BRAccountLinkingConnection(retailer: .walmart)
connection.configuration.dayCutoff = 30

Already linked connections can be switched back and forth by updating the webviewAuthEnabled value

if let connection = BRAccountLinkingManager.shared().getLinkedRetailerConnection(.walmart) {
  connection.webviewAuthEnabled = true // Enable `Retailer Webview Authentication`
  connection.webviewAuthEnabled = false // Disable `Retailer Webview Authentication`
  BRAccountLinkingManager.shared().update(connection)
}
let error = BRAccountLinkingManager.shared().linkRetailer(with: connection)
if (error == .none) {
  // Success
}


Verifying a connection

let username = "user@domain.com"
let password = "secure-password"
let connection = BRAccountLinkingConnection(retailer: .walmart, username: username, password: password)
connection.configuration.dayCutoff = 30

let taskId = BRAccountLinkingManager.shared().verifyRetailer(with: connection, withCompletion: { error, viewController, sessionId in

  if (error == .verificationNeeded) {
    // Display UIViewController for 2FA verification, CAPTCHA or other user input
  } else if (error == .verificationCompleted) {
    // Dismiss the previously presented UIViewController
  } else {

    if (error == .noCredentials) {
      // Error: Credentials have not been provided
    } else if (error == .internal) {
      // Error: Unexpected error
    } else if (error == .parsingFail) {
      // Error: General error
    } else if (error == .invalidCredentials) {
      // Error: Probable cause of the failure is invalid credentials
    } else if (error == .cancelled) {
      // Operation has been cancelled.
      // Dismiss any previously presented user input UIViewController
    }
    // Verification completed successfully
    // Account can be linked
    BRAccountLinkingManager.shared().linkRetailer(with: connection)
  }

})


Grab New Orders

Once credentials are verified and a retailer is linked, we will search for purchases in a user’s account.

let taskId = BRAccountLinkingManager.shared().grabNewOrders(for: .walmart) { retailer, order, remaining, viewController, errorCode, sessionID in

  if (errorCode == .verificationNeeded) {
    // Display UIViewController for 2FA verification, CAPTCHA or other user input
  } else if errorCode == .verificationCompleted {
    // Dismiss the previously presented UIViewController
  } else if errorCode == .none {
    // Orders will be returned here         
    if (remaining <= 0) {
      // Grab Orders completed successfully
      // No more orders to fetch
    }            
  } else {
    // Grab Orders Failed. Check error for more info
  }
}

Note

The SDK will maintain an internal date of the last successful search for each retailer so that each time you attempt to retrieve new messages, you will only get messages since the last successful check, and subject to the day cutoff that you set (default is 15 days).


Grab New Orders (App In Background)

Account Linking also provides an option for apps to periodically check for new orders while the app is in background. Follow the steps below if you want to enable background fetch in your app.

  • Create task identifier by adding background task support in your app. More info here

  • Enable background fetch by using the task identifier from step 1

    BRAccountLinkingManager.shared().enableBackgroundFetch(withIdentifier: taskIdentifier)
    
  • Implement backgroundFetchCompletion callback so the app can receive messages from the background job

    BRAccountLinkingManager.shared().backgroundFetchCompletion = { retailer, errorCode, sessionId, order in }
    

Example:

import UIKit
import BlinkReceipt
import BlinkEReceipt

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        BRScanManager.shared().licenseKey = "YOUR-LICENSE-KEY"
        BRScanManager.shared().prodIntelKey = "YOUR-PROD-INTEL-KEY"

        // Enable background fetch
        let taskIdentifier = "Host App Background Task Identifier"
        BRAccountLinkingManager.shared().enableBackgroundFetch(withIdentifier: taskIdentifier)

        // Background fetch callback 
        BRAccountLinkingManager.shared().backgroundFetchCompletion = { retailer, errorCode, sessionId, order in
          // Same flow as Grab Orders above
        }
        return true
    }

}

Migration from BRAmazonManager

If you had previously integrated Amazon parsing, you will find that BRAmazonManager is no longer accessible in the BlinkEReceipt SDK. Instead, Amazon has been incorporated into Account Linking.

Here is a table detailing the functionality from the previous Amazon integration and how to achieve the same thing in the new framework:

Old Amazon Integration New Account Linking Integration
BRAmazonManager.amazonDayCutoff BRAccountLinkingConnection.configuration.dayCutoff
[BRAmazonManager storeCredentials:password:] Create a BRAccountLinkingConnection object and link with BRAccountLinkingManager.shared().linkRetailer(with: connection)
[BRAmazonManager clearAmazonCredentials] Call BRAccountLinkingManager.shared().unlinkAccount(for: .amazon, withCompletion: {})
[BRAmazonManager hasCredentials] Call BRAccountLinkingManager.shared().getLinkedRetailers() and iterate over the results looking for BRAccountLinkingRetailerAmazon
[BRAmazonManager resetAmazonOrders] Call BRAccountLinkingManager.shared().resetHistory(for: .amazon)
[BRAmazonManager verifyAmazonAccount:] Call BRAccountLinkingManager.shared().verifyRetailer(with: connection, withCompletion: {}
[BRAmazonManager grabNewAmazonOrders:] Call BRAccountLinkingManager.shared().grabNewOrders(for: .amazonBeta) {}

As noted above, the method for handling 2FA and other user-input scenarios is slightly different now. Whereas previously you would trap the error code BRAmazonErrorVerificationNeeded and then invoke [BRAmazonManager showBrowserFromViewController:withCompletion:], the new paradigm is that verifyRetailer and grabNewOrders will return the error code BRAccountLinkingErrorVerificationNeeded as well as the actual view controller for you to display. Once the user has successfully authenticated, the same callback will be invoked with the code BRAccountLinkingErrorVerificationCompleted which is the trigger for you to dismiss the view controller.