Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The Cardinal Mobile SDK for iOS makes it easy for you to activate and integrate Cardinal Consumer Authentication (CCA) into your checkout flow. In just a few simple steps, you will be able to create a great user experience for your consumers, while utilizing the benefits of CCA.

Prerequisites

Within the Cardinal Mobile SDK ecosystem, authentication between the Merchant and Cardinal is handled via a JWT (JSON Web Token). To initialize the system for processing, a JWT must be generated server-side and passed into the first call in the chain.

Within the JWT, specify the Org Unit Id, API Key & API Identifier. If you weren't given these values upon registration, please contact your account manager.

For more information on generating a JWT, please see the Generating a Server JWT.

Cardinal’s Mobile SDK requires iOS 9 and XCode 8.

Table of Contents

Flow

image-20240123-153442.pngImage Removed
image-20240123-153609.pngImage Removed

Step 1- Download and Import

Download the CardinalMobile.framework/CardinalMobile.xcframework file using the following cURL:

Download cURL

Code Block
curl -L -u <USER_NAME>
        :<API_KEY> https://cardinalcommerceprod.jfrog.io/artifactory/ios/<VERSION>-<BUILD_NUMBER>/cardinalmobilesdk.zip
        -o <LOCAL_FILE_NAME.EXT>

#Example: 
curl -L -u UserName:ApiKey "https://cardinalcommerceprod.jfrog.io/artifactory/ios/2.2.5-1/cardinalmobilesdk.zip" -o cardinalmobile2.2.5-1.zip

Download .xcframework Using cURL

Code Block
curl -L -u <USER_NAME>
        :<API_KEY> https://cardinalcommerceprod.jfrog.io/artifactory/ios/<VERSION>-<BUILD_NUMBER>/CardinalMobileiOSXC.zip
        -o <LOCAL_FILE_NAME.EXT>

#Example: 
curl -L -u UserName:ApiKey "https://cardinalcommerceprod.jfrog.io/artifactory/ios/2.2.5-1/CardinalMobileiOSXC.zip" -o cardinalmobile2.2.5-1.zip

In your XCode project:

  • Drag the CardinalMobile.framework or CardinalMobile.xcframework file into the Frameworks group in your Xcode Project

    • Create the Frameworks group if it doesn't already exist.

  • In the Import dialog, tick the box to Copy items into destinations group folder (or Destination: Copy items if needed). The iOS SDK files are now available for linking to your project.

image-20240201-162750.png

Step 2- Setting up your Build Environment

  1. Open Xcode and click on your project in the source list to the left of the main editor area.

  2. Select your application under the Targets section and go to the General tab.

  3. Expand the Embedded Binaries section then click the small “+” button at the bottom of the list.

  4. Add the CardinalMobile.framework or CardinalMobile.xcframework file from the list

Step 3- Configure Cardinal Mobile SDK

Upon successfully completing Integration in Step 1 and Step 2, create a new instance of the cardinal object by [CardinalSession new]. SDK offers multiple configuration options for you (if not specified, everything is set to default). For more details: CardinalConfigurationOptions. Use the code snippet below for completing the configuration. 

Expand
titleObjective-C Code Snippet
Code Block
languageobjective-c
#import <CardinalMobile/CardinalMobile.h>

CardinalSession *session;

//Setup can be called in viewDidLoad
- (void)setupCardinalSession {
	session = [CardinalSession new]; 
	CardinalSessionConfiguration *config = [CardinalSessionConfiguration new];
	config.deploymentEnvironment = CardinalSessionEnvironmentProduction;
	config.requestTimeout = CardinalSessionTimeoutStandard;
	config.challengeTimeout = 5;
	config.uiType = CardinalSessionUITypeBoth;

	UiCustomization *yourCustomUi = [[UiCustomization alloc] init];
	//Set various customizations here. See "iOS UI Customization" documentation for detail.
	config.uiCustomization = yourCustomUi;

	UiCustomization *yourDarkModeCustomUi = [[UiCustomization alloc] init];
	config.darkModeUiCustomization = yourDarkModeCustomUi;


	CardinalSessionRenderTypeArray *renderType = [[CardinalSessionRenderTypeArray alloc] initWithObjects:
    	                       	CardinalSessionRenderTypeOTP,
        	                   	CardinalSessionRenderTypeHTML,
								CardinalSessionRenderTypeOOB,
								CardinalSessionRenderTypeSingleSelect,
								CardinalSessionRenderTypeMultiSelect,
            	               nil];
	config.renderType = renderType;

	[session configure:config];
}
Expand
titleSwift Code Snippet
Code Block
languageobjective-c
import CardinalMobile

var session : CardinalSession!

//Setup can be called in viewDidLoad
func setupCardinalSession{
	session = CardinalSession()
	var config = CardinalSessionConfiguration()
	config.deploymentEnvironment = .production
	config.requestTimeout = 8000
	config.challengeTimeout = 5
	config.uiType = .both

	let yourCustomUi = UiCustomization()
	//Set various customizations here. See "iOS UI Customization" documentation for detail.
	config.uiCustomization = yourCustomUi

	let yourDarkModeCustomUi = UiCustomization()
	config.uiCustomization = yourDarkModeCustomUi

	config.renderType = [CardinalSessionRenderTypeOTP, 
							CardinalSessionRenderTypeHTML,
							CardinalSessionRenderTypeOOB,
							CardinalSessionRenderTypeSingleSelect, 
							CardinalSessionRenderTypeMultiSelect]

	session.configure(config)
}

Step 4 - Setup the Initial Call to Cardinal

Calling cardinal session setup will begin the communication process with Cardinal to ensure your user's experience is seamless, by authenticating your credentials (serverJwt) and completing the data collection process. By the time they are ready to checkout, all necessary pre-processing will be completed.Use the code snippet below for completing the cardinal session setup

Expand
titleObjective-C Code Snippet
Code Block
languageobjective-c
NSString *jwtString = @"INSERT_YOUR_JWT_HERE";
 
[session setupWithJWT:jwtString
          didComplete:^(NSString * _Nonnull consumerSessionId){
    //
    // You may have your Submit button disabled on page load. Once you are setup
    // for CCA, you may then enable it. This will prevent users from submitting
    // their order before CCA is ready.
    //
} didValidate:^(CardinalResponse * _Nonnull validateResponse) {
    // Handle failed setup
    // If there was an error with setup, cardinal will call this function with
    // validate response and empty serverJWT
}];
Expand
titleSwift Code Snippet
Code Block
languageobjective-c
let jwtString = "INSERT_YOUR_JWT_HERE"
 
session.setup(jwtString: jwtString, completed: { (consumerSessionId: String) in
    //
    // You may have your Submit button disabled on page load. Once you are setup
    // for CCA, you may then enable it. This will prevent users from submitting
    // their order before CCA is ready.
    //
}) { (validateResponse: CardinalResponse) in
    // Handle failed setup
    // If there was an error with setup, cardinal will call this function with
    // validate response and empty serverJWT
}
Info

Security Guide

After you configure cardinalSession, call method getWarnings to get the list of all the warnings for the particular device. Take further action based on the warnings found. The list of warnings can be accessed as follows:

NSArray<Warning *> *warnings = [session getWarnings];

See our iOS Security Guidance for detail.

Step 5- Create Lookup Request and Response to Centinel

Create an API call to your backend server in order to send a Lookup Request (cmpi_lookup) to Cardinal's Centinel platform for initiating the Consumer Authentication transaction.  The Centinel platform manages all of the routing and connectivity, as well as the rules engine for all of the various 3-D Secure protocols and versions.  Please follow the Getting Started and Lookup Request/Response sections for completing your backend integration: Cardinal (cmpi) Messages 

Required Field for identifyingnan SDK transaction : 

  • <DeviceChannel>SDK</DeviceChannel>

  • <DFReferenceId>ReferenceId</DFReferenceId>

ReferenceId is consumerSessionId returned on setup completion, if no referenceID is passed in serverJwt. Else you can use that referenceID as DFReferenceId

Step 6 - Validate CMPI Lookup Response to Create an Authentication Session

After the completion of the cmpi_lookup request, check the CMPI_Lookup_Response for the following fields:

  • ThreeDSVersion = 2.X ( 2.0, 2.1, etc)

  • Enrolled = Y

  • PAResStatus = C

    • If the PAResStatus is not C then you do not need to create an Authentication Session.

Upon validating the above fields, you will call [session continueWithTransactionId.. ] to hand control to SDK for performing the challenge between the user and the issuing bank. Use the code snippet below for completing the sessions continue

Code Block
breakoutModewide
 [session continueWithTransactionId: @"[TRANSACTION_ID]" payload: @"[PAYLOAD]" didValidateDelegate: self];

In continue for Quick Integration, a class conforming to a protocol CardinalValidationDelegate (and implement a method stepUpDidValidate) should be passed as a parameter. Following is the example of class conforming to CardinalValidationDelegate protocol.

Expand
titleObjective-C Code Snippet
Code Block
languageobjective-c
@interface YourViewController()<CardinalValidationDelegate>{ //Conform your ViewController or any other class to CardinalValidationDelegate protocol
     
}
@end
  
@implementation YourViewController
  
    /**
     * This method is triggered when the transaction has been terminated.This is how SDK hands back
     * control to the merchant's application. This method will
     * include data on how the transaction attempt ended and
     * you should have your logic for reviewing the results of
     * the transaction and making decisions regarding next steps.
     * JWT will be empty if validate was not successful
     *
     * @param session
     * @param validateResponse
     * @param serverJWT
     */
    -(void)cardinalSession:(CardinalSession *)session stepUpDidValidateWithResponse:(CardinalResponse *)validateResponse serverJWT:(NSString *)serverJWT{
         
    }
  
@end

if continue is being called in the same class then the following method is called to start StepUpFlow:

Code Block
[session continueWithTransactionId: @"[TRANSACTION_ID]"
                           payload: @"[PAYLOAD]"
               didValidateDelegate: self];
Expand
titleSwift Code Snippet
Code Block
languageobjective-c
class YourViewController:CardinalValidationDelegate {
  
    /**
     * This method is triggered when the transaction has been terminated.This is how SDK hands back
     * control to the merchant's application. This method will
     * include data on how the transaction attempt ended and
     * you should have your logic for reviewing the results of
     * the transaction and making decisions regarding next steps.
     * JWT will be empty if validate was not successful
     *
     * @param session
     * @param validateResponse
     * @param serverJWT
     */
    func cardinalSession(cardinalSession session: CardinalSession!, stepUpValidated validateResponse: CardinalResponse!, serverJWT: String!) {
        
    }
 
}

If continue is being called in the same class then the following method is called to start StepUpFlow:

Code Block
session.continueWith(transactionId: "[TRANSACTION_ID]", payload: "[PAYLOAD]", validationDelegate: self)

stepUpDidValidate is triggered when the transaction has been terminated. This is how the Cardinal Mobile SDK hands back control to the merchant's application. This event will include data on how the transaction attempt ended and should be where you review the results of the transaction and make decisions regarding the next steps. The field ActionCode should be used to determine the overall state of the transaction. On the first pass, we recommend that on an ActionCode of 'SUCCESS' or 'NOACTION' you send the response JWT to your backend for verification. There is more information on verifying JWT's in the next section.

Expand
titleObjective-C Code Snippet
Code Block
languageobjective-c
-(void)cardinalSession:(CardinalSession *)session stepUpDidValidateWithResponse:(CardinalResponse *)validateResponse serverJWT:(NSString *)serverJWT{
    switch (validateResponse.actionCode) {
        case CardinalResponseActionCodeSuccess:
            // Handle successful transaction, send JWT to backend to verify
            break;
  
        case CardinalResponseActionCodeNoAction:
            // Handle no actionable outcome
            break;
  
        case CardinalResponseActionCodeFailure:
            // Handle failed transaction attempt
            break;
  
        case CardinalResponseActionCodeError:
            // Handle service level error
            break;
 
        case CardinalResponseActionCodeCancel:
            // Handle transaction canceled by user
            break;
 
        case CardinalResponseActionCodeTimeout:
            // Handle transaction timeout.
            break;
    }
}
Expand
titleSwift Code Snippet
Code Block
languageobjective-c
unc cardinalSession(cardinalSession session: CardinalSession!, stepUpValidated validateResponse: CardinalResponse!, serverJWT: String!) {
    switch validateResponse.actionCode {
    case .success:
        // Handle successful transaction, send JWT to backend to verify
        break
         
    case .noAction:
        // Handle no actionable outcome
        break
         
    case .failure:
        // Handle failed transaction attempt
        break
         
    case .error:
        // Handle service level error
        break
 
    case .cancel:
        // Handle transaction canceled by user
        break
 
    case .timeout:
        // Handle transaction timedout
        break
    }
}

Step 7- JWT Validation

Once the response JWT arrives in the onValidated, you will need to send the response JWT to your backend for verification and consumption. We recommend that any values sent to 3rd parties are sourced from the response JWT after it has been properly validated.

Note

Security Warning

All JWT validation must be done on the server side.

For more information on JWT validation go to JWT Validation

JWT Validation

This table includes cases sensitive claim keys and descriptions.

Claim

Description

aud

Merchant jti Id - This is the 'jti' field from your request JWT echoed back. This field allows you to match up your request JWT with Cardinals response JWT.

jti

JWT Id - A unique identifier for this response JWT. This value is generated by Cardinal.

iat

Issued At Time - This is a timestamp of when the JWT was created.

iss

Issuer - The request JWT's iss field echoed back.

ConsumerSessionId

The unique session Id for the current user.

Payload

The response object for your request. This field will contain any actual state information on the transaction. This is the decoded data object that is passed into the payments.validated event as the first argument.

Info

Each claim key is case sensitive.

JWT Payload Example

Below is an example of the JSON content of a basic response JWT Payload where we are passing an object within the Payload claim:

Code Block
{
    "iss": "56560a358b946e0c8452365ds",
    "iat": 1471014492,
    "exp": 1471021692,
    "jti": "8af34811-f97d-495a-ad19-ec2f68004f28",
    "ConsumerSessionId": "0e1ae450-df2b-4872-94f7-f129a2ddab18",
    "Payload": {
        "Validated": true,
        "Payment": {
            "Type": "CCA",
            "ExtendedData": {
                "CAVV": "AAABAWFlmQAAAABjRWWZEEFgFz+=",
                "ECIFlag": "05",
                "PAResStatus": "Y",
                "SignatureVerification": "Y",
                "XID": "MHEyQjFRQkttemdpaFlRdHowWTA=",
                "Enrolled": "Y"
            }
        },
        "ActionCode": "SUCCESS",
        "ErrorNumber": 0,
        "ErrorDescription": "Success"
    }
}

String JWT Example

Below is an example of the JSON content of a basic response JWT Payload where we are passing a string within the Payload claim. This would occur when the request JWT included a ObjectifyPayload flag set to false:

Code Block
}
    "iss": "56560a358b946e0c8452365ds",
    "iat": 1471015342,
    "exp": 1471022542,
    "jti": "55ebfa2a-665f-4d6b-81ea-37d1d4d12d9e",
    "ConsumerSessionId": "fb3a97a3-0344-4d3d-93ea-6482d866ec97",
    "Payload": "{\"Validated\":true,\"Payment\":{\"Type\":\"CCA\",\"ExtendedData\":{\"CAVV\":\"AAABAWFlmQAAAABjRWWZEEFgFz+\\u003d\",\"ECIFlag\":\"05\",\"PAResStatus\":\"Y\",\"SignatureVerification\":\"Y\",\"XID\":\"MFpjUVpwb0FXcHdwMWJBdldwNDA\\u003d\",\"Enrolled\":\"Y\"}},\"ActionCode\":\"SUCCESS\",\"ErrorNumber\":0,\"ErrorDescription\":\"Success\"}"
}

Step 8 - Cleanup

The cleanup method is called after the transaction has completed. This clears Cardinal.java’s current instance so when Cardinal.getInstance() is called again, a new instance is created. This can be called from any location within your application.

Code Block
Cardinal.getInstance().cleanup();