Use the face from eKYC onboarding to register for face authentication.
key | type | required | description | max length |
---|---|---|---|---|
cus_user_id | string | yes | user id of customer | 256 |
faces | []image | no | selfie image from eKYC onboarding | 50 |
face_in_id_card | image | no | image of the face in id_card | |
face_type | string | no | type of face input (selfie , id_card ) | |
selfie_type | string | no | flash_16 : Android use SDK TS, flash_8 : iOS use SDK TS, vendor_a : use SDK other vendor | 64 |
param | Android | iOS | other_vendor |
---|---|---|---|
selfie_type | flash_16 | flash_8 | vendor_a |
Use API directly: Face registration
Use Java SDK: Java API librarary
{
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"faces": [
{
"id": "a4facba3-334b-41fb-97e3-4766cb70ae29"
}
],
"face_in_id_card": {
"id": "d8c330d4-5c7a-4f8e-a0f0-44efffb0cfc6"
},
"face_type": "selfie",
"selfie_type": "flash_16"
}
All APIs were called from the Bank's backend. No API calls at SDK.
Reference Scenario
flow_id
to use for your business: eg. face_auth
or reset_password
Use API directly: Get client settings
Use Java SDK: Java API librarary
// Get client settings
String flowID = "face_auth"
TVResponseData<TVClientSettings> response = TVApi.getInstance().getClientSettings(flowID);
if (response.hasErrors()) {
List<TVApiError> errors = response.getErrors();
System.out.println("Get client settings error:" + errors.get(0).getMessage());
} else {
System.out.println("Get client settings successful");
}
System.out.println(response.getRawJSON());
Pass settings string from step 1 to parameter jsonConfigurationByServer
Android: Init SDK
iOS: Init SDK
val config = TVInitializeConfiguration(
jsonConfigurationByServer = jsonConfigurationByServer,
languageCode = languageCode,
theme = theme
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
TrustVisionSDK.init(context, config, object : TVInitializeListener {
override fun onInitSuccess(result: TVInitResult) {
// Start Face Authen
// eg. startFaceAuthentication(....)
}
override fun onInitError(error: TVDetectionError) {
// Handle errors
}
})
}
Android: Start Face Authentication
iOS: Start Face Authentication
param | Android | iOS |
---|---|---|
authMode | authMode = TVAuthMode.flash16(selfieConfiguration) | method: TVFaceAuthenMethod.flash8 |
val selfieConfiguration = TVSelfieConfiguration(
cameraOption = TVCameraOption.FRONT,
enableSound = true,
isEnableVerticalChecking = false,
isEnableUploadFrames = false,
isEnableUploadImages = false,
isEnableSanityCheck = false,
isEnableVerifyLiveness = false
)
val configuration = TVFaceAuthenticationConfiguration(
cusUserId = "", // leave empty to omit
authType = AuthType.AUTH,
authMode = TVAuthMode.flash16(selfieConfiguration),
isEnableFaceAuthentication = false,
isEnableFaceRegistration = false
)
TrustVisionSDK.startFaceAuthentication(activity, configuration, object : TVCapturingCallBack() {
override fun onNewFrameBatch(frameBatch: FrameBatch) {
}
override fun onError(error: TVDetectionError) {
}
override fun onSuccess(result: TVDetectionResult) {
}
override fun onCanceled() {
}
})
Android: Handle results from SDK
iOS: Handle results from SDK
Note: frames video were batched and sent to host app via method onNewFrameBatch
to upload async.
val selfieFrameBatchIdsDictionary: MutableMap<String, String> = mutableMapOf()
TrustVisionSDK.startFaceAuthentication(activity, configuration, object : TVCapturingCallBack() {
// If frameBatch is uploaded to server by the SDK, the host app does not need to override this method
override fun onNewFrameBatch(frameBatch: FrameBatch) {
val gson = Gson()
val framesStr = gson.toJson(frameBatch.frames)
val params: MutableMap<String, Any> = HashMap()
params["frames"] = framesStr
params["metadata"] = frameBatch.metadata
params["label"] = "video"
val jsonToBeUploaded = gson.toJson(params)
// upload frame batch to server using this api:
// https://ekyc.trustingsocial.com/api-reference/customer-api/#upload-videoaudioframes
val uploadingResult: YourResponseObject = yourMethodToUploadFrameBatch(jsonToBeUploaded)
// Keep the id that generated by the SDK corresponding with the one responded from server
selfieFrameBatchIdsDictionary[frameBatch.id] = uploadingResult.fileId
}
override fun onError(error: TVDetectionError) {
}
override fun onSuccess(result: TVDetectionResult) {
val faceIds: List<TVImageClass> = result.faces?.map {
TVSyncFile.createById(it.imageId)
} ?: emptyList()
val gestureFaces: List<TVGestureFace> = result.gestureFaces?.map {
val gesture = it.gesture
val ids = it.images.map { img -> TVSyncFile.createById(img.imageId) }
TVGestureImage(gesture, ids)
} ?: emptyList()
// If frameBatch is uploaded to server by the SDK
val videoIds = result.livenessFrameBatchIds?.map {
TVVideoFile.createById(it)
}
// If frameBatch is uploaded to server by the host app
val videoIds = selfieFrameBatchIdsDictionary.values.map {
TVVideoFile.createById(it)
}
val cusUserId = "1"
val selfieType = "selfie"
val authType = "transfer"
// SDK uploads images to the server and returns the image IDs to the host app
// call api to verify face authentication
// https://ekyc.trustingsocial.com/api-reference/customer-api#request-face-authentication
yourMethodToCallFaceAuthenticationAPI(
cusUserId,
faceIds,
gestureFaces,
videoIds,
selfieType,
authType
)
}
override fun onCanceled() {
}
})
Use API directly: Request face authentication
Use Java SDK: Face Auth
param | Android | iOS | other_vendor |
---|---|---|---|
auth_type | transfer | transfer | transfer |
selfie_type | flash_16 | flash_8 | vendor_a |
client_transaction_id
is your transaction ID to identify for reconciling or tracing between 2 systems
String cusUserID = "c1b3b3b3-1b3b-4b3b-8b3b-3b3b3b3b3b3b"; // Required
String authType = TVFaceAuthAuthTypeConstant.TRANSFER;
String selfieType ="flash_16";// "flash_16" for android, "flash_8" for iOS, the value should get from SDK.
String clientTransactionID = "a9c9a80a-8ae8-4de9-8dab-d85a85d1882e"; // your transaction ID to identify for reconciling or tracing between 2 systems
List<TVSyncImage> imagesFaceAuth = Arrays.asList(
TVSyncImage.createById("3e2693e7-1e8f-40f0-be68-2cf73b09c61b"),
TVSyncImage.createById("36dc7bd6-ed04-4bd3-bd32-61cb9ac4837c"),
TVSyncImage.createById("15b0db75-d238-4a4b-bea9-4897c7af0a08"),
TVSyncImage.createById("d8c330d4-5c7a-4f8e-a0f0-44efffb0cfc6"));
List<TVGestureImages> gestureImagesFaceAuth = Arrays.asList(
new TVGestureImages("right", Arrays.asList(TVSyncImage.createById("99bbe3b5-23e8-41d6-a496-956d7e5c3ed5"))),
new TVGestureImages("down", Arrays.asList(TVSyncImage.createById("fe140383-81ff-47e3-930f-154272e7da6c"))),
new TVGestureImages("left", Arrays.asList(TVSyncImage.createById("dd553b55-5b02-48e3-b2bf-ecfa45c9119b")))
);
List<TVSyncVideo> videos = Arrays.asList(
TVSyncVideo.createById("dfb4a246-09df-42fc-be41-0faafc8dc5bc")
);
TVResponseData<TVFaceAuthenResponse> faceAuthResponse = TVApi.getInstance().faceAuthen(faceAuthRequest,"", headers);
if (faceAuthResponse.hasErrors()) {
List<TVApiError> errors = faceAuthResponse.getErrors();
System.out.println("Face Auth error:" + errors.get(0).getMessage());
} else {
System.out.println("Face Auth successful");
}
There are some APIs called from SDK. There are some APIs called from the client's backend.
Reference Scenario
Use API directly: Create temporary credential
Use Java SDK: Create temporary credentials
// Create temporary credentials
int durationInSeconds = 900;
String transactionID = "";
String xRequestID = "";
String xRequestID2 = "";
Map<String, String> headers = new HashMap<String, String>();
headers.put("X-Request-Id", xRequestID);
headers.put("X-Request-Id2", xRequestID2);
TVTemporaryCredentialRequest request = new TVTemporaryCredentialRequest(durationInSeconds);
TVResponseData<TVTemporaryCredentialResponse> response = TVApi.getInstance().createTemporaryCredential(request, transactionID, headers);
System.out.println("TVTemporaryCredentialResponse: " + GsonUtils.toJson(response));
if (response.hasErrors()) {
List<TVApiError> errors = response.getErrors();
System.out.println("Create temporary credentials error:" + errors.get(0).getMessage());
} else {
System.out.println("Create temporary credentials successful");
}
Use Java SDK: Reference
props | description |
---|---|
x-request-id | API reconciliation. Reference |
x-request-id2 | Hash(x-request-id2) . Reference |
access_key | the value from API temporary credentials. Reference |
secret_key | the value from API temporary credentials. Reference |
face_auth_endpoint | the value from TS's administrator |
Android: Init SDK
iOS: Init SDK
flowId
parameter is defined for each use-case differentlyflowId | description |
---|---|
face_authen | Authenticate with face for all flows |
reset_password | Authenticate to reset password flow |
login | Use face to replace text password |
payment | Authenticate payment |
transfer | Authenticate transfer |
transfer_type_A | Authenticate transfer type A |
transfer_type_B | Authenticate transfer type B |
transfer_type_C | Authenticate transfer type C |
transfer_type_D | Authenticate transfer type D |
... | You can define any authentication type based on your business |
parameter | description |
---|---|
endpoint | From step 1. eg. https://tv-staging.trustingsocial.com/api |
accessKeyId | From step 1 |
accessKeySecret | From step 1 |
xRequestId | From step 1 |
xRequestId2 | From step 1 |
val config = TVInitializeConfiguration(
endpoint = endpoint,
accessKeyId = accessKeyId,
accessKeySecret = accessKeySecret,
xRequestId = xRequestId,
xRequestId2 = xRequestId2_of_backend at step1,
flowId = flowId,
languageCode = languageCode,
theme = theme
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
TrustVisionSDK.init(context, config, object : TVInitializeListener {
override fun onInitSuccess(result: TVInitResult) {
// Start Face Authen
// eg. startFaceAuthentication(....)
}
override fun onInitError(error: TVDetectionError) {
// Handle errors
}
})
}
Android: Start Face Authentication
iOS: Start Face Authentication
param | Android | iOS |
---|---|---|
authMode | authMode = TVAuthMode.flash16(selfieConfiguration) | method: TVFaceAuthenMethod.flash8 |
val selfieConfiguration = TVSelfieConfiguration(
cameraOption = TVCameraOption.FRONT,
enableSound = true,
isEnableVerticalChecking = false,
isEnableUploadFrames = true,
isEnableUploadImages = true,
isEnableSanityCheck = false,
isEnableVerifyLiveness = false
)
val configuration = TVFaceAuthenticationConfiguration(
cusUserId = "", // leave empty to omit
authType = AuthType.AUTH,
authMode = TVAuthMode.flash16(selfieConfiguration),
isEnableFaceAuthentication = false,
isEnableFaceRegistration = false
)
TrustVisionSDK.startFaceAuthentication(activity, configuration, object : TVCapturingCallBack() {
override fun onNewFrameBatch(frameBatch: FrameBatch) {
}
override fun onError(error: TVDetectionError) {
}
override fun onSuccess(result: TVDetectionResult) {
}
override fun onCanceled() {
}
})
Android: Handle results from SDK
iOS: Handle results from SDK
TrustVisionSDK.startFaceAuthentication(activity, configuration, object : TVCapturingCallBack() {
override fun onError(error: TVDetectionError) {
}
override fun onSuccess(result: TVDetectionResult) {
val faceIds: List<TVImageClass> = result.faces?.map {
TVSyncFile.createById(it.imageId)
} ?: emptyList()
val gestureFaces: List<TVGestureFace> = result.gestureFaces?.map {
val gesture = it.gesture
val ids = it.images.map { img -> TVSyncFile.createById(img.imageId) }
TVGestureImage(gesture, ids)
} ?: emptyList()
val videoIds = result.livenessFrameBatchIds?.map {
TVVideoFile.createById(it)
}
val cusUserId = "1"
val selfieType = "selfie"
val authType = "transfer"
// SDK uploads images to the server and returns the image IDs to the host app
// call api to verify face authentication
// https://ekyc.trustingsocial.com/api-reference/customer-api#request-face-authentication
yourMethodToCallFaceAuthenticationAPI(
cusUserId,
faceIds,
gestureFaces,
videoIds,
selfieType,
authType
)
}
override fun onCanceled() {
}
})
Use API directly: Request face authentication
Use Java SDK: Face Auth
param | Android | iOS | other_vendor |
---|---|---|---|
auth_type | transfer | transfer | transfer |
selfie_type | flash_16 | flash_8 | vendor_a |
client_transaction_id
is your transaction ID to identify for reconciling or tracing between 2 systems
String cusUserID = "c1b3b3b3-1b3b-4b3b-8b3b-3b3b3b3b3b3b"; // Required
String authType = TVFaceAuthAuthTypeConstant.TRANSFER;
String selfieType ="flash_16";// "flash_16" for android, "flash_8" for iOS, the value should get from SDK.
String clientTransactionID = "a9c9a80a-8ae8-4de9-8dab-d85a85d1882e"; // your transaction ID to identify for reconciling or tracing between 2 systems
List<TVSyncImage> imagesFaceAuth = Arrays.asList(
TVSyncImage.createById("3e2693e7-1e8f-40f0-be68-2cf73b09c61b"),
TVSyncImage.createById("36dc7bd6-ed04-4bd3-bd32-61cb9ac4837c"),
TVSyncImage.createById("15b0db75-d238-4a4b-bea9-4897c7af0a08"),
TVSyncImage.createById("d8c330d4-5c7a-4f8e-a0f0-44efffb0cfc6"));
List<TVGestureImages> gestureImagesFaceAuth = Arrays.asList(
new TVGestureImages("right", Arrays.asList(TVSyncImage.createById("99bbe3b5-23e8-41d6-a496-956d7e5c3ed5"))),
new TVGestureImages("down", Arrays.asList(TVSyncImage.createById("fe140383-81ff-47e3-930f-154272e7da6c"))),
new TVGestureImages("left", Arrays.asList(TVSyncImage.createById("dd553b55-5b02-48e3-b2bf-ecfa45c9119b")))
);
List<TVSyncVideo> videos = Arrays.asList(
TVSyncVideo.createById("dfb4a246-09df-42fc-be41-0faafc8dc5bc")
);
TVResponseData<TVFaceAuthenResponse> faceAuthResponse = TVApi.getInstance().faceAuthen(faceAuthRequest,"", headers);
if (faceAuthResponse.hasErrors()) {
List<TVApiError> errors = faceAuthResponse.getErrors();
System.out.println("Face Auth error:" + errors.get(0).getMessage());
} else {
System.out.println("Face Auth successful");
}
Use API directly: Get result of the request
curl -X GET \
https://tv-staging.trustingsocial.com/api/v1/requests_by_req_id/a4facba3-334b-41fb-97e3-4766cb70ae29 \
-H 'Authorization: TV <YOUR ACCESS KEY>:<CREATED SIGNATURE>' \
-H 'X-TV-Timestamp: 2019-04-21T18:00:15+07:00' \
-H 'Content-Type: application/json'
{
"data": {
"status": "success",
"auth_check": {
"score": 0.9999999862517992,
"result": "matched"
},
"request_id": "cfc7b8d5-f2e2-437b-80e5-d600dfad26e2",
"user_metadata": {
"key1": "value1",
"key2": 2
},
"validate_faces_result": {
"sanity_verdict": "good",
"is_live": true,
"sanity_check": {
"portrait_sanity": {
"score": 1,
"verdict": "good"
},
"request_id": "9f89377f-4bb4-4ecb-884c-f46f1d7d6099",
"status": "success"
},
"liveness_check": {
"images": null,
"is_live": true,
"request_id": "baee3d03-8af4-421b-8968-a0f6172b4df8",
"score": 1,
"status": "success"
}
},
"auth_id": "d4f99f9b-4862-437f-a9c9-608e050d06c6",
"histories": [
{
"id": "f1ca6795-cbd4-4eec-821f-b4ac646db627",
"client_id": "0ef0f7e9-7f2f-4767-84b8-f76da7701c46",
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"face_auth_id": "887249dc-681c-4231-aff9-67734833aca7",
"id_card_face_id": "4f959f4a-f5de-4b50-8724-224e709d06c2",
"live_face_id": "009161c9-9c89-4573-8119-8f513de4449c",
"created_at": "2023-12-27T03:33:06.307977Z",
"auth_action": "login",
"status": "success",
"result": "",
"face_type": "selfie"
},
{
"id": "8c23af95-aaa0-4448-bfba-68acce31236e",
"client_id": "0ef0f7e9-7f2f-4767-84b8-f76da7701c46",
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"face_auth_id": "",
"id_card_face_id": "4f959f4a-f5de-4b50-8724-224e709d06c2",
"live_face_id": "009161c9-9c89-4573-8119-8f513de4449c",
"created_at": "2023-12-21T07:24:19.829484Z",
"auth_action": "login",
"status": "failure",
"result": "image is not liveness",
"face_type": "id_card"
}
]
}
}