iOS

Integrated Requirement

Compliance Explanation

Please note that when integrating SDK products provided by the TrustDecision in the APP of your company:

1.1 According to the user's information protection regulations, before your users start the App for the first time and start collecting information, your company should fully inform the user of the purpose, method, and scope of collecting, using, and sharing the user's personal information with a third party through an interactive interface or design (such as a pop-up window of the privacy policy), and obtain the express consent of the end user.

1.2 To provide business security and risk control services to your company, the TrustDecision SDK will collect, process, and use the identification information(IMEI/IDFA), AndroidID, IMSI, MEID, MAC address, SIM card serial number, device type, device model, system type, geographical location, login IP address, application list, running process, sensor information(light sensor, gravity sensor, magnetic field sensor, acceleration sensor, gyroscope sensor) and other device information of the user's device. To ensure compliance with your use of related services, the aforementioned privacy policy should cover the authorization of TrustDecision SDK to provide services and collect, process, and use relevant information. The following terms are for your reference. The specific expression can be determined by your company according to the overall framework and content of your privacy agreement:

TrustDecision SDK: For business security and risk control, our company uses the TrustDecision SDK. The SDK needs to obtain the information of your devices, such as (IMEI/IDFA), AndroidID, IMSI, MAC address, SIM card serial number, device type, device model, system type, geographic location, login IP address, application list, running process, sensor information(light sensor, gravity sensor, magnetic field sensor, acceleration sensor, gyroscope sensor) and other related device information, for fraud risk identification.

Privacy Protocol: https://www.trustdecision.com/legal/privacy-policy

Environment

ItemsDescription
Supported System VersionsiOS9.0+
Supporting architecturearmv7, arm64, x86_64

Integration Steps

There are 3 steps to integrate Liveness Detection SDK:

  1. Use the Retrive license API to get a license within the effective timeframe.
  2. Integrate the SDK for both Android and iOS platforms, initializing liveness detection process with the license generated in Step 1 and get the livenessId from the TDLivenessResultStruct structure.
  3. Use the Retrive result API with the "livenessId" generated in Step 2 to obtain a selfie if the liveness detection is successful, or receive detailed results in case of failure.

1. Retrive license API

Base URL

API

URLRequest MethodsContent TypeOutput FormatCharacter Set
api-base-url?partner_code=xxx&partner_key=xxxPOSTapplication/jsonJSONUTF-8

Authentication

ParameterTypeDescriptionRequired/OptionalNotes
partner_codeStringPartner CodeRequiredAssigned by TD
partner_keyStringPartner KeyRequiredAssigned by TD

Request

ParameterTypeDescriptionRequired/OptionalNotes
session_durationIntegerDuration of the license's effective timeframeOptionalThe default duration is 600 seconds, with a maximum of 86,400 seconds. The unit is seconds.

Response Parameters

ParameterTypeDescriptionNotes
codeIntegerAPI status codePlease refer to below API Code list
messageStringStatus InformationDetailed reasons will be provided about API status
sequence_idStringUnique response codeA unique ID used to track each request
licenseStringLiveness detection initialization licenseThe license is used to initiate the liveness detection process in SDK subsequently.
expiry_timestampIntegerLicense expiration timestampThe timestamp when the license expires, e.g., 1715667188.

Response Example

  • Request
{
    "session_duration": 600  //optional
}
  • Success
{
    "code": 200,
    "message": "success",
    "sequence_id": "17119500882*****29",
    "license": "a41701e49******3",
    "expiry_timestamp": 1715667188
}
  • Failed
{
    "code": 11350,
    "sequence_id": "69b57131b6fb********61ccba118b60",
    "message": "Internal error"
}

2.SDK Integration methods

CocoaPods

  • Added pod 'TrustDecisionPro', '4.2.7.2' in the corresponding target in the Podfile
  • Added pod 'TrustDecisionLiveness', '2.3.3' in the corresponding target in the Podfile
  • Execute the pod install --repo-update command in the folder where the Podfile is located. (M1 series mac computers need to execute arch -x86_64 pod install --repo-update command)

SDK Structure

files in Pods/TrustDecisionPro directory:

  • TDMobRisk.framework(TrustDecision SDK, is a static library type)
  • TDCorePlugin.framework (TrustDecision plugin, is an Embed dynamic library type)

files in Pods/TrustDecisionLiveness directory:

  • libTDLiveness.a(Mob-Risk SDK liveness component library, is a static library type)
  • CWResource.bundle (Mob-Risk SDK liveness component Required resource package)

Import Header File

Please import the header file if you want to call SDK API.

#import <TDMobRisk/TDMobRisk.h>
import TDMobRisk

Initialization

Precautions

When the installation starts for the first time, the SDK initialization is performed after the user agrees with the privacy agreement.

Avoid SDK initialization collection without the user agreeing to the privacy agreement, causing compliance risk accidents.

Interface Definition

void (*initWithOptions)(NSDictionary *options);

initWithOptions method Required Configuration

Key Definition Description Scene Sample code
partner Partner code Partner, please contact TrustDecision to obtain All Scenes Objective C
[options setValue:@"[Your partner]" forKey:@"partner"];
Swift
options.updateValue("[Your partner]" as NSObject, forKey: "partner")
appKey App key Appkey, please offer your App bundleId for TrustDecision to obtain.
appkey creation requires the user to provide the application bundleId
All Scenes Objective C
[options setValue:@"[Your appKey]" forKey:@"appKey"];
Swift
options.updateValue("[Your appKey]" as NSObject, forKey: "appKey")
country Country code Country/region parameters, such as cn sg us fra idna Fill in the corresponding parameters according to country and region of business.
cn means China,
sg means Singapore,
us means North America,
fra means Europe,
idna means Indonesia
Objective C
[options setValue:@"[Your country code]" forKey:@"country"];
Swift
options.updateValue("[Your country code]" , forKey: "country")

Sample Code

- (void)initTrustDecisionSDK {
  // Get riskManager
  TDMobRiskManager_t *riskManager = [TDMobRiskManager sharedManager];
  // Initialization Configuration
  NSMutableDictionary *options = [NSMutableDictionary dictionary];

/*************************** Mandatory Parameter ***************************/
  //Partner code, Refer to `Required Configuration`
  [options setValue:@"[Your partner]" forKey:@"partner"];
  //App key, Refer to `Required Configuration`
  [options setValue:@"[Your appKey]" forKey:@"appKey"];
  //Country code, Refer to `Required Configuration`
  [options setValue:@"[Your country code]" forKey:@"country"];

  /*************************** Optional Parameter ***************************/
#ifdef DEBUG
  // !!! If not set this parameter in DEBUG mode, the app will terminate
  [options setValue:@(YES) forKey:@"allowed"];
#endif
  // !!!The callback method has been removed, and now a getBlackBoxAsync method has been added to asynchronously obtain blackbox
  riskManager->initWithOptions(options);
}
func initTrustDecisionSDK() {
  let riskManager = TDMobRiskManager.sharedManager()
  var options = [String : NSObject]()
  /*************************** Mandatory Parameter ***************************/
  // Partner code, Refer to `Required Configuration`
  options.updateValue("[Your partner]" as NSObject, forKey: "partner")
  // App key, Refer to `Required Configuration`
  options.updateValue("[Your appKey]" as NSObject, forKey: "appKey")
  // Country code, Refer to `Required Configuration`
  options.updateValue("[Your country]" as NSObject, forKey: "country")

   /*************************** Optional Parameter ***************************/
#if DEBUG
  // !!! If not set this parameter in DEBUG mode, the app will terminate
  options.updateValue(true, forKey: "allowed")
#endif
  // !!!The callback method has been removed, and now a getBlackBoxAsync method has been added to asynchronously obtain blackbox
 riskManager?.pointee.initWithOptions(options)
}

Get Blackbox

Attention

  • Please getBlackBox after initWithOptions, otherwise SDK exceptions will be caused.
  • We suggest that developers do not cache the results returned by getBlackBox in the app. Please rely on this function to get blackBox.

Asynchronous method getBlackBoxAsync (recommend)

   /* Get blackBox asynchronously
    */
   void (*getBlackBoxAsync)(TDGetBlackBoxAsyncBlock block);

Usage Scenario Description

Advantages: Under normal circumstances, the network returns a non-degraded blackBox, which will reduce the amount of data uploaded by the subsequent query interface, and the data size is about 26 bytes;
Disadvantages: Not returned immediately, according to the network It usually takes about 300ms to return;
Applicable scenario: Need to get the latest and non-degraded blackBox scenario;

Sample Code

     TDMobRiskManager_t *riskManager = [TDMobRiskManager sharedManager];
     riskManager->getBlackBoxAsync(^(NSString* blackBox){
         NSLog(@"blackBox:%@", blackBox);
     });
    let riskManager = TDMobRiskManager.sharedManager()
    riskManager?.pointee.getBlackBoxAsync(){(blackBoxString : String!)->Void in
            print("blackBox:" + blackBoxString)                               
    }

Synchronous method getBlackBox

   /* Get blackBox synchronously
    * @return After the SDK is initialized, the blackBox obtained synchronously
    */
   NSString (*getBlackBox)(void);

Usage Scenario Description

Advantages: The blackBox will be returned immediately, not affected by the network status;
Disadvantages: After the device fingerprint SDK is integrated, if the non-degraded blackBox has not been obtained before, it will return to the degraded blackBox will increase the amount of data uploaded by the subsequent query interface, and the data size is about 5000 bytes;
Applicable scenarios: Scenes where blackBox needs to be obtained immediately;

Sample Code

   TDMobRiskManager_t *riskManager = [TDMobRiskManager sharedManager];
   NSString *blackBox = riskManager->getBlackBox();
  let riskManager = TDMobRiskManager.sharedManager()
  let blackBox = riskManager?.pointee.getBlackBox()

Popup Liveness Window

initWithOptions method Optional Parameter

Key Definition Description Scene Sample code
language language type Liveness detection prompt language
Default: en English Options:
en English
zh-Hans Simplified Chinese
zh-Hant Traditional Chinese
es Spanish
id Indonesian
ar Arabic
fil Filipino
ko Korean
pt Portuguese
ru Russian
th Thai
tr Turkish
vi Vietnamese
You can set the language type according to your needs Objective C
[options setValue:@"en" forKey:@"language"];
Swift
options.updateValue("en", forKey: "language")
playAudio Whether to play audio The default is NO, no audio will be played When turned on, the corresponding prompt audio will be played Objective C
[options setValue:@NO forKey:@"playAudio"];
Swift
options.updateValue(false, forKey: "playAudio")
livenessDetectionThreshold Difficulty threshold for live detection Difficulty threshold for live detection, divided into three levels: high, medium, and low The default is medium Adjust to corresponding difficulty as needed Objective C
[options setValue:@"medium" forKey:@"livenessDetectionThreshold"];
Swift
options.updateValue("medium", forKey: "livenessDetectionThreshold")
livenessHttpTimeOut SDK network timeout configuration (unit: seconds) Default is 15s Customers can set the network timeout according to their needs Objective C
[options setValue:@8 forKey:@"livenessHttpTimeOut"];
Swift
options.updateValue(8, forKey: "livenessHttpTimeOut")
showReadyPage When starting the face, the detection preparation page will pop up Whether to display the preparation page, the default is YES, which means it will be displayed After closing, the preparation page will not be displayed, and the identification process will be shorter Objective C
[options setValue:@YES forKey:@"showReadyPage"];
Swift
options.updateValue(true, forKey: "showReadyPage")
faceMissingInterval Timeout when no face is detected (unit: milliseconds) No face timeout, unit ms, default is 1000ms Set the timeout period when no face is detected as needed Objective C
[options setValue:@(1000) forKey:@"faceMissingInterval"];
Swift
options.updateValue(1000, forKey: "faceMissingInterval")
prepareStageTimeout The starting time when preparing to detect the action (unit: seconds) Preparation phase timeout, in seconds, the default is 0S, that is, it will never time out Set the preparation phase timeout as needed Objective C
[options setValue:@(0) forKey:@"prepareStageTimeout"];
Swift
options.updateValue(0, forKey: "prepareStageTimeout")
actionStageTimeout In the action phase, the maximum verification time (unit: seconds) Action phase timeout, unit second, default is 8S Set the action phase timeout as needed Objective C
[options setValue:@(8) forKey:@"actionStageTimeout"];
Swift
options.updateValue(8, forKey: "actionStageTimeout")

showLiveness method

The showLiveness method is used to display the Liveness vc, and its interface is defined as follows

/**
 * Display Liveness window, will use [targetVC.navigationController pushViewController:lvctl animated:YES]; to show
 * @usage: manager->showLivenessWithShowStyle(self,TDLivenessShowStylePresent,^(TDLivenessResultStruct resultStruct) {
 * });
 * @param targetVC The parent view where the popup is displayed, UIViewController type
 * @param block result callback block
*/
void (*showLiveness)(id targetVC,TDShowLivenessBlock block);

/**
* Display Liveness window
* @usage: manager->showLivenessWithShowStyle(self,nil,TDLivenessShowStylePresent,^(TDLivenessResultStruct resultStruct) {
* });
* @param targetVC The parent view where the popup is displayed, UIViewController type
* @param license auth license,can be nil
* @param showStyle TDLivenessShowStylePush or TDLivenessShowStylePresent
* @param block result callback block
*/
void (*showLivenessWithShowStyle)(id targetVC,NSString* _Nullable license,TDLivenessShowStyle showStyle,TDShowLivenessBlock block);

TDLivenessResultStruct

We use the TDLivenessResultStruct structure to store the result of the callback;

typedef enum {
    
    // The Liveness is verified successfully;
    TDLivenessResultTypeSuccess,
    // If the Liveness fails, you can get the error code errorCode and errorMsg, and check the cause according to the `Error code` in the document;
    TDLivenessResultTypeFailed,
    // The Liveness window pop-up is successful, waiting to be verified;
    TDLivenessResultTypeReady,
    
} TDLivenessResultType;

typedef struct _TDLivenessResultStruct{
    // return result type
    const TDLivenessResultType resultType;
    // the seqId of the Liveness returned
    char* const seqId;
    // After the return fails, the returned error code can be checked according to the document
    const NSInteger errorCode;
    // Return error message after failure
    char* const errorMsg;
    // liveness score when success
    double score;
    // best image string
    char* const bestImageString;
    // liveness detection ID
    char* const livenessId;

}TDLivenessResultStruct;

Example Code

- (void)showLiveness {
    [TDMobRiskManager sharedManager]->showLivenessWithShowStyle(self,@"Input_your_license",TDLivenessShowStylePush,^(TDLivenessResultStruct resultStruct) {
         if(resultStruct.resultType == TDLivenessResultTypeSuccess){
             // If there is a best photo
             if(resultStruct.bestImageString.length > 0){
                 NSData* data = [[NSData alloc]initWithBase64EncodedString:resultStruct.bestImageString options:NSDataBase64DecodingIgnoreUnknownCharacters];
                 UIImage * image = [UIImage imageWithData:data];
                 UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
             }
            
             NSString*successMsg = [NSString stringWithUTF8String:resultStruct.errorMsg];
             NSLog(@"successMsg-::%@,score:%f,livenessId:%s",successMsg,resultStruct.score,resultStruct.livenessId);
         }else{
             NSString*errorMsg = [NSString stringWithUTF8String:resultStruct.errorMsg];
             NSString*errorMsgInfo = [NSString stringWithFormat:@"Face detection failed, error code: %ld, error message: %@", resultStruct.errorCode,errorMsg];
             NSLog(@"errorMsgInfo-::%@",errorMsgInfo);
         }
     });
}

     func showLiveness() {
         let targetVC = self
         let riskManager = TDMobRiskManager.sharedManager()
        riskManager?.pointee.showLivenessWithShowStyle(self,"Input_your_license",TDLivenessShowStyle(rawValue: TDLivenessShowStylePush.rawValue)){ (resultStruct : TDLivenessResultStruct!)->Void  in
             switch resultStruct.resultType {
             case TDLivenessResultTypeSuccess:
                 let bestImageString : String? = String(utf8String: resultStruct.bestImageString)
                 if(bestImageString != nil && bestImageString!.count > 0){
                     let data : Data? = Data(base64Encoded: bestImageString!)
                     if(data != nil){
                         let image : UIImage? = UIImage(data: data!)
                         if(image != nil){
                             UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil);
                         }
                     }
                 }
                 let successMsg = String(cString:resultStruct.errorMsg)
                 let seqId = String(cString:resultStruct.seqId)
                 print("Liveness successful!!!,seqId:\(seqId),successMsg:\(successMsg),score:\(resultStruct.score),livenessId:\(resultStruct.livenessId)")
             case TDLivenessResultTypeFailed:
                 let errorMsg = String(cString:resultStruct.errorMsg)
                 print("Liveness failed, errorCode:\(resultStruct.errorCode), errorMsg:\(errorMsg)")
             default:
                 break
             }
         }
     }

Error Code

CodeMessage
200success (live person)
20700No face detected
20702Person change detected
20703Detection timeout
20705Screen lock or background exit during detection
20710No camera permission
20711User actively cancels detection on the preparation page
20712User actively cancels detection on the detection page
20749Inconsistent action, tilt head down
60001Network issue, failed to retrieve session
60002Network issue, failed to call anti-hack
11350Internal error

3. Retrive result API

Base URL

API

URLRequest MethodsContent TypeOutput FormatCharacter Set
api-base-url?partner_code=xxx&partner_key=xxxPOSTapplication/jsonJSONUTF-8

Authentication

ParameterTypeDescriptionRequired/OptionalNotes
partner_codeStringPartner CodeRequiredAssigned by TD
partner_keyStringPartner KeyRequiredAssigned by TD

Request

ParameterTypeDescriptionRequired/OptionalNotes
liveness_idStringLiveness detection IDRequiredLiveness detection ID generated in the above SDK output of Step 2, representing unique liveness detection process

Response Parameters

ParameterTypeDescriptionNotes
codeIntegerAPI status codePlease refer to below API Code list
messageStringStatus InformationDetailed reasons will be provided about API status
sequence_idStringUnique response codeA unique ID used to track each request,iOS get the livenessId in the TDLivenessResultStruct structure as the value of liveness_id
imageStringLiveness detection face picturesThe best face picture captured during the liveness detection process, in base64 format
scoreDoubleLiveness detection confidence scoreReserved field. Currently, only the code=200 indicates that the liveness test has been passed.

Response Example

  • Request
{
  "liveness_id": 1234567
}
  • Success
{
  "code": "200",
  "message": "success",
  "sequence_id": "1679299854228726325924",
  "image": "\/9j\/4AAQSkZJRgABAQAAAQABAAD\/2wBDAAMCA",
  "score": 0.98958
}
  • Failed
{
    "code": 11350,
    "sequence_id": "69b57131b6fb********61ccba118b60",
    "message": "Internal error"
}

API Code

CodeMessageCharged
200success (live person)YES
12202Identified as a blink attackYES
12203Identified as a mouth movement attackYES
12204Identified as a partial face attackYES
12205Identified as a video replay attackYES
12206Identified as a black and white imageYES
12207Identified as a paper-based attackYES
12208Identified as a frame (including paper or phone frame)YES
12209Identified as a moire pattern attackYES
12210Identified as a face superiority attackYES
12211Identified as a paper-based attack (optical flow)YES
12212Identified as a mask attackYES
12213Identified as an ID card attackYES
12214Identified as a 3D mask attackYES
12215Identified as a synthetic image attackYES
12216Identified as a black-market software attackYES
12217Identified as a T-type mask attackYES
12218Identified as a blurry imageYES
12219Suspected deepfake image attackYES
12220Suspected high-resolution screen attackYES
12222Injection attackYES
12250Verification errorYES
11350Internal errorNO

Get SDK Version

Sample Code

// Get SDK Version
TDMobRiskManager_t *riskManager = [TDMobRiskManager sharedManager];
NSString *sdkVersion = riskManager->getSDKVersion();
// Get SDK Version
let riskManager = TDMobRiskManager.sharedManager()
let sdkVersion = riskManager?.pointee.getSDKVersion()

FAQ

Q1: After integrated the TrustDecision SDK, the project can no longer be debugged in Xcode. How to solve it?

A1: Please refer to Initialization when initializing TrustDecision SDK, add the following parameters

[options setValue:@(YES) forKey:@"allowed"];
options.updateValue(true, forKey: "allowed")