CMiTP

CMi TP module is used by TPA to communicate CM (with integrated CMi CM module). CMi SDK for iOS is using URI request for communication with CM and universal links feature of iOS.

Sequence diagram

alt text

Request

To start CMi scenario, application should follow these steps:

  1. create params for particular flow
  2. serialize params to dictionary
  3. combine known recepient URI with serialized params
  4. open URI using call of OS

Params Creation

First of all, TPA need to create instance of class that conforms to CMiParams protocol. Based if chosen scmi scenario, it can be one of CMiOauthParams, CMiOpenIdConnectParams or CMiTransactionParams. For futher details, refer to documentation of params classes.

let baseParams = CMiTP.CMiBaseParams(state: state)
let params = CMiOauthParams(baseParams ...)
let params = CMiOpenIdConnectParams(baseParams ...)
let params = CMiTransactionParams(baseParams ...)

Params Serialization

Created params instance need to be serialized to dictionary. so TPA can use it to create URI. TPA should use protocol method CMiParams.toUrlDataDictionary() to get dictionary.

let dictionary = params.toUrlDataDictionary()

Combining URI & Params

Before using dictionary for URI creation, TPA should put additional values to dictionary

let trackingId = //generate tracking id
dictionary[CMiConstants.flowIdHeaderKey] = trackingId
dictionary[CMiConstants.redirectUriKey] = <tpa_redirect_uri>

where <tpa_redirect_uri> is URI used to deliver response to TPA and <trackingId> is log value used to match all calls amongs components

For combining URI of CM with params, TPA should use CMi-Core module. For futher detail refer to its documentation.

let url: CMiUrl = CMiUrl(version: CMiUrl.Version. <version>, 
                         host: <host>,
                         scenarioPath: <path>,
                         data: dictionary)
let validation = CMiUrlValidation(...)
let parser = CMiUrlParser(validation ...)
let uri = try parser.toUrl(url: url)

<version>, <host>, and <path> should be known to TPA as part of interface of CM.

URI Openning

TPA should use resulting uri to open CM. It can be done by calling system method.

UIApplication.shared.open(uri, options: [:], completionHandler: nil)

After succesfull last step, OS will pass control to CM, which will guide user trough particular flow, create response and send it back to TPA.

Response

OS will return control to TPA using delegate method of AppDelegate. To process response from CMi scenario, application should follow these steps:

  1. implement method of AppDelegate (with check for URI type)
  2. valide, parse & deserialize received URI
  3. create result from data in URI
  4. process result

App Delegate method

iOS will pass URI request to application using particular method in AppDelegate with particular values in parameters.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL else {
        return false
    }
    return handleCmiV4Url(url: url)
}

Validation, Parsing, Deserialization

For validation and parsing URI, TPA should use CMi-Core module. For futher detail refer to its documentation.

let validation = CMiCore.CMiUrlValidation()
let parser = CMiCore.CMiUrlParser(validation...)
let urlIsValid = parser.validate(url: url)
if !urlIsValid {
    showInvalidUriError()
}
let cmiUrl = try parser.parse(url: url)

Result Creation

Data from validated and parsed URI can be used to create CMiResult instance. Particular type is determined by path in URI. The value will correspond to the one used in creation of URI with request (See above, marked as )

var result: CMiResult?
if cmiUrl.scenarioPath == <redirLogin> {
    result = try CMiTP.CMiLoginResult(data: cmiUrl.data)
} else if cmiUrl.scenarioPath == <redirTrx>
    result = try CMiTP.CMiTransactionResult(data: cmiUrl.data)
} else {
    preconditionFailure("Unknown path for CMi TP response")
}

where <redirLogin> is TPA’s path for login scenario response and <redirTrx> is TPA’s transaction scenario response.

Result Processing

When processing the result, TPA should first check result code.

if result.result != CMiResult.success {
    showErrorFromResult(result.result)
}

When scenario is succesful, result may contain additional data in properties of CMiLoginResult or CMiTransactionResult instance