SwiftID KYC SDK Integration Guide

This guide details the integration process for the SwiftID KYC SDK for developers.

Supported KYC Flows

SwiftID's KYC SDK has the following flows:

Authentication token

Create Wallet

Assign ID (CPF)

Name & ID Number Verification

Identification Document & Selfie Verification

Two-Factor Authentication

Proof of Address

Salary verification (Coming soon)

The following sections detail the usage of each implemented flow.

SDK Initialization

To instantiate SwiftID's SDK the module must be invoked as:

  • Locate the google-services.json file at the root of the SDK.
  • This file contains a BUNDLE_ID entry corresponding to the app identifier using the SDK which will grant you access to our database upload system so that users can upload their documentation. This is necessary for uploading files such as ID images and the Selfie identification image as well as the proof of physical address.
  • Replace the value of this entry with your project's bundle identifier found in the Signing and Capabilities tab of your app target configuration.
  • This identifier is required by SwiftID to grant access to the database upload system for user documentation (ID images, selfie, proof of address). Please provide us with this bundle identifier. This is necessary for uploading files such as ID images and the Selfie identification image as well as the proof of physical address.

Also, you will need to enable data binding in your build.gradle file of your app (if not done already), and add the following dependencies from Firebase

implementation("com.google.firebase:firebase-storage-ktx:20.2.0")
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:28.4.1"))

You should also apply this plugin in your root build.gradle, that will enable Firebase in your project

id 'com.google.gms.google-services' version '4.4.1' apply false
  • Once the BUNDLE_ID is configured, instantiate the SDK the following way:

KYCSdkManager.initSDK(context: Context, email: String, password: String)

Where email is the email you provided, and password is the password we provided to you so you can use the SDK.

Create Wallet

 Manual Flow

This flow generates a non-custodial cmorq EVM address. The network SDK call returns a KyCCreateWalletModel object through a completion closure:

data class CreateWalletModel(
    public var message: String = "",
    public var status: Int = 0,
    public var address: String = "",
    public var mnemonic: String = ""
)

To create a new wallet:

KYCSdkManager.createAddress(
    { response ->
        // Manage CreateWalletResponse on success                           
    }
) { error ->
    // Handle Error Case
}

 Pre-built User Experience (UX) Flow

We also have the option to use a pre done UX flow, which will allow the user to create a wallet by simply calling the following method. This flow requires a FragmentActivity to be passed as a parameter. To instantiate this flow we do:

KYCSdkManager.startCreateAddressFlow(activity: FragmentActivity, callback: CreateWalletListener)

The activity will have to implement the CreateWalletDialogFragment.CreateWalletListener interface, which will return the result of the Create Address flow. This interface has 2 methods:

interface CreateWalletListener {
    fun onWalletCreateSuccess(address: String)
    fun onWalletCreateFailure(message: String)
}

on the success, the address of the wallet will be returned, and on the failure, the message of the error will be returned.

Assign CPF

This flow binds an existing cmorq wallet with a provided CPF (Cadastro de Pessoas Físicas - Brazilian tax ID).

  • Ensure the user enters a valid CPF and the wallet is a valid cmorq wallet. Currently, the SDK performs no validation for either.

 Manual Flow

To bind, we make use of the method updateCPF which takes in a cmorq address and a CPF as parameters to bind them. Then executes a closure returning if it was successful or not. It returns a boolean, the tells the user if the CPF already exists in cmorq database, and a string message with the result.

The call is made in the following way:

KYCSdkManager.updateCPF(cpfValue, address,
    { exists, message ->
        // Manage message on success
    }
) { error ->
    // Handle Error Case   
}

 Pre-built User Experience (UX) Flow

You have also the option to use a pre done UX flow, which will allow the user to update the CPF of a given cmorq wallet by simply calling the following method. This flow requires a FragmentActivity to be passed as a parameter. To instantiate this flow we do:

KYCSdkManager.startUpdateCPFFlow(
    address: String,
    activity: FragmentActivity,
    callback: UpdateCPFListener
)

The activity will have to implement the UpdateCPFDialogFragment.UpdateCPFListenerinterface, which will return the result of the Create Address flow. This interface has 2 methods:

interface UpdateCPFListener {
    fun onUpdateCPFSuccess()
    fun onUpdateCPFFailure(message: String)
}

If the binding is successful, the onUpdateCPFSuccess method will be called, otherwise the onUpdateCPFFailure method will be called.

Get Entry by ID

 Manual flow

This library method allows the user to provide a wallet address and a COF abd retrieve all the available information about that user. The way to use this method is by calling the following:

KYCSdkManager.getEntryById(addressInput, cpf,
{ response ->
     // Handle information
},
{ error ->
   // Handle error
})
              

Where the response is EntryByIdResponse which contains all the existing entries of Entry for the given address.

data class EntryByIdResponse(
    var entries: List<Entry>,
    var message: String,
    var status: Int
)

Then Entry is:

data class Entry(
    val cpfHash: String?,
    val createdAt: String?,
    val dob: String?,
    val fullName: String?,
    val imageBack: String?,
    val imageBackDirect: String?,
    val imageFront: String?,
    val imageFrontDirect: String?,
    val imageSelfie: String?,
    val kycVerified: Boolean?,
    val kycVerifiedAI: Boolean?,
    val taxId: String?,
    val walletAddress: String?
)

While this library API does not have a pre-made UX flow (since this library method can return an entry with many different attributes per address), there is an implementation example printing an entry that can be found in the Demo App shipping alongside this SDK.

Verify Name and ID

To ensure seamless identity verification for our platform, we kindly request that you follow these simple steps with your users:

  1. Instruct your users to initiate a transaction of R0.01 from their account to our designated pix token [email protected].
  2. Emphasize the importance of using an account linked to their CPF for this transaction.

This straightforward process triggers the verification mechanism for their Full Name and CPF within our system. It securely locks and confirms their details, enabling us to validate their identity accurately. By cross-referencing the CPF provided during registration with the one used for the transaction, we ensure a robust verification process that enhances security and trust in our platform. Thank you for your cooperation in maintaining the integrity of our services.

Two-Factor Authentication

This flow allows for two different instantiations, one which is our pre-made UX flow that allows the user to simply instantiate the flow, input their phone number, and verify their phone number through 2FA.

 Pre-built User Experience (UX) Flow

This flow requires a FragmentActivity to be passed as a parameter. To instantiate this flow we do:

KYCSdkManager.startDepositFlow(this@Activity)

The activity will have to implement the VerifyPhoneNumberDialogFragment.VerifyPhoneNumberInterface interface, which will return the result of the 2FA flow. This interface has 2 methods:

fun onVerifyPhoneNumberSuccess()
fun onVerifyPhoneNumberFailure(message: String)

 Manual Flow

Another way of working with this API involves utilizing two methods:

  1. Send the MFA
  2. Verify the sent code.

These methods must be executed sequentially. First, we confirm that the MFA message has been sent, indicating backend confirmation of the OTP message transmission. Subsequently, we initiate the verification process by calling the 'verify' method, passing both the OTP received by the user and the user's phone number.

fun send2FA(
    number: String,
    source: String,
    successCallback: () -> Unit,
    failCallback: (String) -> Unit
)

fun verify2FA(
    address: String,
    number: String,
    code: String,
    successCallback: () -> Unit,
    failCallback: (String) -> Unit
)

If the send2FA returns a success, we then call the verify2FA method, which will return a success or a failure. The response model for the send2FA will also return a success or a failure. If the verification is valid, the flow is concluded.

Proof of Address

Manual flow

This section explains the manual Proof of address method.

The method has the signature:

 fun fullAddressCheck(
    address: String,
    cpf: String,
    documentBase64: String,
    physicalAddress: String,
    successCallback: (String) -> Unit,
    failCallback: (String) -> Unit
 )

this method's arguments are:

  • physicalAddress :(String) the users physical address
  • documentBase64 :(String) The utility bill to verify in Base64 format
  • address: (String) The user's cmorq wallet address.
  • cpf: (String) The user's CPF number.
  • successCallback : (String) -> Unit) If the utility bill is accepted, a message is returned with the result
  • failCallback : (String) -> Unit) If the utility bill is not accepted, or there was an error in the process, a message with the cause is returned

 Pre-built User Experience (UX) Flow

The SDK provides a pre-built UX flow that guides the user through the Address verification process. This flow requires a FragmentActivity to be passed as a parameter. To instantiate this flow we do:

fun startAddressValidateFlow(
        activity: FragmentActivity,
        address: String,
        cpf: String,
        callback: AddAddressListener
)

The activity will have to implement the AddAddressDialogFragment.AddAddressListener interface, which will return the result of the Address verification flow. This interface has 2 methods:

fun onAddAddressSuccess(message: String)
fun onAddAddressFailure(message: String)

ID & Selfie Verification

This section explains the two methods for implementing ID and Selfie verification with the CMORK KYC SDK.

 Pre-built User Experience (UX) Flow

The SDK provides a pre-built UX flow that guides the user through the ID and Selfie verification process. Here's how to use it:

fun startSDK(
    context: Context,
    address: String,
    successKYC: (String, Boolean) -> Unit,
    failureKYC: (String) -> Unit,
    selfieSuccess: (String) -> Unit
)

Using this method, a new Intent is created where you must provide the context, address, and two callbacks: one for success and one for failure. The success callback will return a message and a boolean value. The boolean will be true if the KYC was approved by the AI and false if it was not. The failure callback will return a message in case of failure. The selfieSuccess callback will provide the location of the saved selfie image.

Manual flow

For more control, you can use the submitID method to handle image data and verification logic manually.

val address: String = "<Some user wallet>"
val cpf: String = "<Some user CPF>"
val frontImageUri: Uri = <front image uri>
val backImageUri: Uri = <back image uri>
val selfieImageData: Uri = <selfie image uri>

KYCSdkManager.submitID(addres, cpf, frontImageUri, backImageUri, selfieImageUri, onSuccess = { message, accepted ->
   // Handle success response                                                                                              
},
onError = { message ->
  // Handle error case
})
  • address: (String) The user's CMORQ wallet address.
  • cpf: (String) The user's CPF number.
  • frontImageUri: (Uri) The Uri of the user's ID front side image.
  • backImageUri: (Uri) The Uri of the user's ID back side image.
  • selfieImageUri: (Uri) The Uri of the user's selfie image.
  • onSuccess: (Closure) A closure that receives a HawkInboundModel object containing the verification response.
  • onError: (Closure) A closure that receives a Stromg\ containing the message of why it failed.

Hawk Response Model:

  • HawkInboundModel: This model contains the response from the HAWK verification service.
data classt HawkInboundModel (
  val message: String
  val accepted: Boolean
)
  • message: (String) A message from the backend regarding the verification.
  • accepted: (Bool) A boolean indicating whether the verification was successful.

Once the Hawk Process has ended, the HawkInboundModel will be returned inside the completion closure. If the accepted boolean is true, the Id process has concluded, meaning that the user has been successfully KYC'd. In case of a false result, it means that compliance personnel must manually verify the sent ID, since the Hawk System Verification has failed to validate the user.