Cardinal Mobile SDK iOS Integration Documentation V 2.1.4

Overview

Activation Steps

Cardinal wants to get you up and running with CCA as quickly and seamlessly as possible. This section of the document will outline the simple steps that are necessary in order to take advantage of Cardinal Mobile SDK..

Step 1 - Download and Import the Cardinal Mobile SDK

Download the CardinalMobile.framework file using following cURL.

Download cURL
curl -L -u<USER_NAME>
        :<API_KEY> https://cardinalcommerce.bintray.com/ios/<VERSION>-<BUILD_NUMBER>/cardinalmobilesdk.zip
        -o <LOCAL_FILE_NAME.EXT>

#Example: 
curl -L -uUserName:ApiKey "https://cardinalcommerce.bintray.com/ios/2.1.4-2/cardinalmobilesdk.zip" -o cardinalmobile2.1.4-2.zip

In your XCode project, drag CardinalMobile.framework file into the Frameworks group in your Xcode Project (create the 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 in your project.

For Bintray username and API Key please reach out to your client manager.

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 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


 Objective-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.timeout = CardinalSessionTimeoutStandard;
	config.uiType = CardinalSessionUITypeBoth;

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

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

	config.enableQuickAuth = false;
	[session configure:config];
}
 Swift
import CardinalMobile
var session : CardinalSession!

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

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

	config.renderType = [CardinalSessionRenderTypeOTP, CardinalSessionRenderTypeHTML]
	config.enableQuickAuth = true
	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


NOTE: The following function call must be placed in your Checkout ViewController.

 Objective-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
}];
 Swift
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
}
If you already have the credit card number and just need to pass it to Cardinal, you can pass it in cardinal session setup.It is ideal in a flow where the consumer has already entered their payment information.
 Objective-C : Cardinal Set up with Account Number
NSString *accountNumberString = @"1234567890123456";
NSString *jwtString = @"INSERT_YOUR_JWT_HERE";

[session setupWithJWT:jwtString 
		accountNumber:accountNumberString 
		  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        
}];
 Swift : Cardinal Setup with AccountNumber
let accountNumberString = "1234567890123456"
let jwtString = "INSERT_YOUR_JWT_HERE"

session.setup(jwtString: jwtString, 
				account: accountNumberString, 
			  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
}

Step 5 - Create a Lookup Request/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: Link

Required Field for identifying as an 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 - Handle the Centinel Lookup Response and create the 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

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 session's continue

cardinal session continue is updated without the hardcoded directoryServerID.

 [session continueWithTransactionId: @"[TRANSACTION_ID]" payload: @"[PAYLOAD]" directoryServerID: CCADirectoryServerIDVisa 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.


 Objective-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:

[session continueWithTransactionId: @"[TRANSACTION_ID]"
						   payload: @"[PAYLOAD]"
			   didValidateDelegate: self];
 Swift
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:

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

Error rendering macro 'excerpt-include' : User 'null' does not have permission to view the page 'STAG:Handling the onValidated - iOS- V 2.1.3'.

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.

Security Warning

For security reasons, all JWT validation must be done on the server side.


Looking for more information?

For more in-depth information on JWT validation including code samples in a few languages, check out the JWT Validation page.

JWT Validation
Please note that each Claim key is case sensitive.
ClaimDescription
audMerchant 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.
jtiJWT Id - A unique identifier for this response JWT. This value is generated by Cardinal.
iatIssued At Time - This is a timestamp of when the JWT was created.
issIssuer - The request JWT's iss field echoed back.
ConsumerSessionIdThe unique session Id for the current user.
PayloadThe 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.

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:

Raw JWT Sample
{
    "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"
    }
}

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:

Stringified JWT Sample
}
    "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\"}"
}