This section describes how the Netcetera iOS 3DS SDK should be configured.
When a transaction is initiated, the SDK gets the information about the Directory Server that will participate in the message flow trough the passed DS ID. From this ID value the SDK determinate which DS public key to use for the data encryption, the root certificate used for ACS signed content validation and which DS logo to be shown when processing the transaction. They should be configured in the SDK. There are two ways to configure these values.
When configuring with property list configuration file it should be named DSsConfiguration.plist.
In the DSsConfiguration.plist keys that need to be defined are:
To define a scheme DS, simply create a dictionary from the root of the DSsConfiguration.plist where the name of the scheme is the dictionary key. Each scheme DS dictionary contains the following:
Please note that the key names shall be set exactly as stated above for the configuration to be valid.
To define the DS IDs that belong to a certain scheme DS, create a new array named IDs containing string values of the DS IDs. Repeat for each scheme DS.
DS IDs | |
---|---|
parent | Scheme Dictionary |
key | IDs. |
value | ID of the scheme, each in a new row. |
The 3DS Requestor App uses the Cardholder Account Number and optionally other cardholder information to identify the DS ID. A DS ID is the Scheme’s Card RID (Registered application provider identifier). The identifier, usually 5 bytes in length, is issued by the ISO/IEC 7816-5 registration authority and is used to address an application in the card. For example, an RID could be: A000000003. Please refer to the configuration file for more RID values.
To define the public key that will be used for encryption of Device Info, create a new element in the selected scheme name. The key should be dsPublicKey while the value can be the filename of the DS certificate, a PEM string of the certificate or a PEM string of the key.
DS Public Key | |
---|---|
parent | Scheme Dictionary |
key | dsPublicKey |
value | Filename, certificate or public key PEM string. |
Note: If public keys are provided, the keys can be either EC or RSA in PEM format and in ASN1 notation. If certificates are provided, they need to be in the X.509 standard in either PEM or DER format. In case a Certificate chain is provided, the leaf certificate will be used. Make sure that the certificate is part of the application bundle.
To define the root certificate that will be used for a certain scheme DS, create a new element in the selected scheme name. The key should be dsRootCertificate while the value should be the filename of the DS Root certificate or a PEM string of the certificate.
DS Root Certificate | |
---|---|
parent | Scheme Dictionary |
key | dsRootCertificate |
value | Filename of certificate or PEM string. |
Note: The certificate file needs to be in the X.509 standard in either PEM or DER format. Make sure that the certificate is part of the application bundle.
To define the logo that will be used for a certain scheme DS, create a new element in the scheme DS dictionary. The key should be logoImageName, while the value should be the name of the logo image for the scheme DS. Make sure that the logo image is in the application bundle. Repeat the process for each scheme DS.
DS Logo image | |
---|---|
parent | Scheme Dictionary |
key | logoImageName |
value | Name of image filename. |
DSsConfiguration.plist example file can be downloaded from here.
The SDK can also be configured dynamically in code using the ConfigurationBuilder class. This is done by creating Scheme objects and adding them to a ConfigurationBuilder object. The Scheme object holds all the values that need to be configured for a scheme.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | let configurationBuilder = ConfigurationBuilder() let scheme = Scheme(name: "scheme_name") scheme.ids = ["V000000005","V000000006"] scheme.logoImageName = "scheme_logo" // Encryption key configuration with certificate filename. scheme.encryptionKeyValue = "scheme_encryption.cer" // Encryption key configuration with PEM string of key. scheme.encryptionKeyValue = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2APFhfYu2cBvPYpLFiDL8uSzalvoCxHi/1uWDg6k40mRzLq3e9TxiqQ9dhFTfxSOmyztE/k+zb5k9ux4iLaU9nrO1qwqAyP79xmUIDgGEeVOy3JFjkRc3SzU4fMpWKhxkOEBPJ/iwKQYSBvQDz0X7ndbovxo222oHvcMIxy2leFdEQ9cp0A3oT6ozjz1YD6hASI6K4sqSN76M6lcW0dM+ZiE2rTFIB/4tdgTSbjHElDh9VsE9m0JOVvBKp+sI07atca0Mx2aBicjTLKp8BLET2LpNCTNrOL+oRL3H+j1/V7HCD33RVjPWZ5/GWKPuCj5VNpPo/jduD9m3Z8jMsmhwIDAQAB" // Encryption key configuration with PEM string of certificate. scheme.encryptionKeyValue = "MIIFWjCCA0ICCQCo3RgSPCQlaTANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJDSDELMAkGA1UECAwCQ0gxCzAJBgNVBAcMAkNIMQwwCgYDVQQKDANOQ0ExDDAKBgNVBAsMA05DQTERMA8GA1UEAwwIaG9zdEBOQ0ExFzAVBgkqhkiG9w0BCQEWCHVzZXJAbmNhMB4XDTIwMDYxMjEzNTI1M1oXDTIxMDYxMjEzNTI1M1owbzELMAkGA1UEBhMCQ0gxCzAJBgNVBAgMAkNIMQswCQYDVQQHDAJDSDEMMAoGA1UECgwDTkNBMQwwCgYDVQQLDANOQ0ExETAPBgNVBAMMCGhvc3RATkNBMRcwFQYJKoZIhvcNAQkBFgh1c2VyQG5jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJh6hca6jQTSLuD0vKGC1H1YtxoENxPI08DxW+ip4wIy/xbGaC/BWLualVXlqxzNQ7AWPZqnL2enFqg/FPoa4yxZRiJDv6nM/uv/wkxbeV24eGFL/XFyDUgwL+bNEkx02TMyPJGTsy9MSs9Ho8Og8dKTCn8469JPfVkm5nEA2B1DK9ijgtsF8WwkuY8KLt13GATqou46n9kVBUGWGcUcj3LdCeh3JjmNwk3eUcWL4Qkm7nzmPmu9JbAFAUuMj00IZFMPJWzMi+r3EG6RXOGprwbxXEYacACp1gbqWxzaa6azlP1THE9GenJg1Hzc5NjE5UW8ciodnD185PKhVV4tICtSuMxLWv0fB/Lk8RonD2w/fyqnmGY3HaFjgc2zwacIk0WYl4EKxmKyCnSLqQPXLzslxbnnM56HFS9f70O2ZF441QWD8O5n17w2fSTwbGuUM0zkNvhcWZ54oZB6iPnFeU9IvuUGZnucFYjDsHu8YOuFPXNjStDCjNDaXfeQ7t9KfCfQdFRawXKDoAzkTDFxDKH/wPcwsc6MrnC/IaqRQxKqg/rxbyHynZdrwo1gAY+UEl4KjiUah2lR49kFA+ArzNCL+89sdlYQyYLjQAnAC0u5k1L8eKp7QuAgjvT9QGFajCdOGkTaZGGq6+vC9USyTLK1vduLeDW7Z8kMbxAMJg6jAgMBAAEwDQYJKoZIhvcNAQELBQADggIBADK8gNZ3K5uV1UlYMraisebXDlgkbUqIL3H/einNphhPj6qkNkhGvG3o0h/0FhpLH7gXOp58n5XyNvVHb/cEtxdzpMSeoSi5+wQFmsss4Hz0TAeSGH8r+hDJ8ZmbFGOb9T+NETBSRGPOtGusEmjKg2s5yr7PPqLVw8vsJmfvgxfl2wPjFvVOaU0poJjrbcyAaIDW+TCIxllMlt1LkbTfh2xqFK6Be06VYhGRq9e1HzHi5kJnODlm5bEzDtx8Krb6LeWWS+6RKDy+7Us7JEyTR/+K3GeDbdH8OK8g9dv0byRpU5D+sBqwCwm+pDABbuQuAfDIoAk5h4DUMxMJVcKL8iIduoG33ql/kbLaEpzw/DqI0esVbu1RNQA0563Rw40R+oitQmUT0SLWskORZDyJ/u2f/ziPJ7Gy0ycx/6p6aWLHuLsCGKv2hHG1QoXmSZv+JPcKuGjipnGETjww8NIVbD9p641ojeR5z3TTOpl+sMF8cg/WFNURZ/Pv46t9hg9rPTNtSzEyvqaxkYUZKM8q9CVjnGFiIY+y5jPm6IA32XdCavCIIl5/5H8BFxDo3k7QXMHHdMVgJR0c1LGAME5ESG6Bcyaype2DRjfFyx/F7tDqqk0ENZU6fJ2Bfpn9G0CvCrOMdAaRXTdaNwedRnUzGGAczR+epLYyAfk5hw99vpkK" // Root Certificate configuration with certificate filename. scheme.rootCertificateValue = "root_certificate.cer" // Root certificate configuration with PEM string of certificate. scheme.rootCertificateValue = "MIIDUjCCAjoCCQCJdBdaEqB1GzANBgkqhkiG9w0BAQsFADBrMQswCQYDVQQGEwJDSDELMAkGA1UECAwCQ0gxCzAJBgNVBAcMAkNIMQwwCgYDVQQKDANOQ0ExDDAKBgNVBAsMA05DQTENMAsGA1UEAwwESG9zdDEXMBUGCSqGSIb3DQEJARYIdXNlckBuY2EwHhcNMjAwNjEyMTM1NDI2WhcNMjEwNjEyMTM1NDI2WjBrMQswCQYDVQQGEwJDSDELMAkGA1UECAwCQ0gxCzAJBgNVBAcMAkNIMQwwCgYDVQQKDANOQ0ExDDAKBgNVBAsMA05DQTENMAsGA1UEAwwESG9zdDEXMBUGCSqGSIb3DQEJARYIdXNlckBuY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo8nsyE84M23iacFpUC6SyVbyG+9hQWco7yILf2pSPnnEGS8Ng6zL57GVs87Q/kMRCQvndM0ROTZIMb2OQdcita0B8c2eMonDbEqji1ny448gH8P2f1JsgZlaFqZFa1SDqgwiIOyN9IZocdNPYQtavss5Zj73+7EeKiS0nrssCyULz2diH/kju9NUsJelb3ILz3sDXG+lDm0ISk84PYn+pWWp68nFu/2Nk52kGf304WvJGncMLxVHkJ/o/P2oy7G0YD8g1GZbNwZspXS+iUlGOxcXqW4d4w5UgbMiijXmz3eJHOsIza2yACON8nLsoMh1jr2v76TAaXkjqKr0QQ6FTAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHuu3Mxki8dQjBg/EI2Vkq+sdnzCclQiGdPh4uBOa+EGmh4e33uGQ5rOHT2DSFHPGQjmNth5r1B/VgJKVRNPdk9nN5+mZv4zpm18G2fGSywTFNvwJVZzavF/sluVtVgmtr+nvLgQAnOl08vlNPd3LecQ1ks/wxh6hV+bSyl6Z4rxDltcp62TgcQHoOURhHlVjrVIdTwqysW5VEPc80LbMrb/zLBVulHlV2Md6UkaPYDfo53G14Vrs2Qu7A3GQP88TGuk6QOynrmnsYEeF/lWSVfTZ50U2ubvpxJvd+ny46orFvdP11p+oDXiO3SrvRyE9Gq+Dz2RQfeK5iATrSK1xOo=" try configurationBuilder.add(scheme) let configParameters = configurationBuilder.configParameters() |
Predefined configurated values can be overridden. To load a Scheme object for a concrete scheme, call the static functions from the Scheme class with the scheme name.
1 2 3 4 5 6 7 8 | let configurationBuilder = ConfigurationBuilder() let scheme = Scheme.diners() scheme.logoImageName = "diners_scheme_logo" try configurationBuilder.add(scheme) let configParameters = configurationBuilder.configParameters() |
If the SDK is configured with both a property list and the ConfigurationBuilder, the later one will have priority. Moreover, if part of the parameters for a Scheme, or the same parameters are configured in both places, the values from the ConfigurationBuilder will take priority and will override the values from the property list.
Note: If both configurations are used for a given scheme, make sure the same name is used in both places.
The Netcetera iOS 3DS SDK comes bundled with configuration for the following directory servers, listed in the table below.
Scheme | RIDs | DS Public Key | DS Root Public Key | DS Logo |
---|---|---|---|---|
Mastercard | |
3ds2.directory.mastercard.com Expiry: 20.11.2021 |
PRD MasterCard Identity Check Root CA Expiry: 15.07.2030 |
mastercard.png |
Visa | |
3ds2.rsa.encryption.visa.com Expiry: 03.11.2020 |
Visa eCommerce Root Expiry: 24.07.2022 |
visa.png |
Amex | |
sdk.safekey.encryptkey.com Expiry: 03.12.2021 |
American Express Private Certification Authority Expiry: 11.08.2029 |
amex.png |
Diners | |
Discover SDK Key |
ProtectBuy Root Expiry: 03.02.2027 |
diners.png |
JCB | |
|
|
jcb.gif |
MIR | |
|
|
mir.png |
Union | |
银联国际有限公司 Expiry: 02.08.2022 |
CFCA ACS CA Expiry: 28.09.2035 |
union.png |
The binding between the configuration and the pre-configured values is done with the RID value of the Directory Server.
The configuration has precedence over pre-configured values and overwrites them i.e. if a configuration is provided for a parameter, that one will be used, instead of the pre-configured one.
Note: The pre-configured DS Public Key and DS Root Public Key serve for convenience, while the integrators have to verify their compatibility to the Directory Server. The integrators are encouraged to complete the configuration.
To define which device info parameters shall be considered as restricted and thus not collected, use the ConfigParameters.addParam(...) with the following arguments:
Argument | Value |
---|---|
group | nil |
paramName | "restricted-device-info-parameters" |
paramValue | Comma separated values of IDs of the device info parameters. |
List of device info parameters and their corresponding IDs can be found at EMVCo 3DS SDK Device Info. If a entry in the restricted device info parameters configuration has value that doesn’t correspond to any predefined device info parameter ID, an InvalidInput error is thrown.
Example:
1 2 3 4 5 6 7 8 9 | let configParameters = ConfigParameters() do { try configParameters.addParam(group: nil, paramName: "restricted-device-info-parameters", paramValue:"C001,C002,C003,I001,I002") } catch let error as NSError { errorHandler(error.localizedDescription) } |
The ConfigurationBuilder can be used to configure the restricted parameters. A list of restricted parameters should be passed to the restrictedParameters([String]) function of the ConfigurationBuilder object.
When all values are set in the ConfigurationBulder, the configParameters() functions will generate ConfigParameters object that can be used when calling the initialize method of ThreeDS2Service class.
1 2 3 4 5 6 7 | let configurationBuilder = ConfigurationBuilder() let restrictedParametersList = ["I001", "I003"] try configurationBuilder.restrictedParameters(restrictedParametersList) let configParameters = configurationBuilder.configParameters() |
There are 4 log levels defined in the SDK: - debug - info - error (default log level) - noLog
You can change the log level of the SDK by setting the parameter in ConfigurationBuilder.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 | let configBuilder = ConfigurationBuilder() // No SDK logs will be shown try configBuilder.log(to: LogLevel.noLog) // Only error SDK logs will be shown try configBuilder.log(to: LogLevel.error) // Both info and error SDK logs will be shown try configBuilder.log(to: LogLevel.info) // All SDK logs will be shown try configBuilder.log(to: LogLevel.debug) |
The Netcetera iOS 3DS SDK supports customization of the UI elements that are being shown by the SDK itself. For this purpose UiCustomization is used.
For detailed information about the UiCustomization API and how to use it, please refer to section 4.5 in the EMVCo 3DS SDK Specification.
Integrators supporting iOS 13 and above, can take advantage of Dark Mode support. If no UI customization colors are provided, then Dark Mode is supported by default. However, if different UI customizations are specified, remember to provide dark mode alternatives for the colors. Netcetera iOS 3DS SDK has an extended API for dark mode colors to be configured. Every method for setting a color in the classes for UI customization has additional dark mode color setter. Note: If only a light color is set, the same will be used in dark mode.
Example:
1 2 3 4 5 6 7 | let buttonCustomization = ButtonCustomization() // Setting light mode background color. try buttonCustomization.setBackgroundColor(hexColorCode: "#000000") // Setting dark mode background color. try buttonCustomization.setDarkBackgroundColor(hexColorCode: "#FFFFFF") |