From 031059ae64ba0e13a76614f4298929215b3528e6 Mon Sep 17 00:00:00 2001 From: Aniket-indulkar Date: Wed, 17 Sep 2025 11:09:04 +0100 Subject: [PATCH] Update ComplyCube integration and settings Upgraded complycube to version 0.0.9 and switched to a local path dependency. Added a comprehensive all-settings.json configuration file. Refactored main.dart to use event streams for status updates and moved verification start to a button. Updated Android build files for Kotlin serialization plugin, minSdkVersion, and packaging options. Changed MainActivity class name in AndroidManifest.xml. --- android/app/build.gradle | 20 +- android/app/src/main/AndroidManifest.xml | 2 +- android/settings.gradle | 1 + lib/all-settings.json | 381 +++++++++++++++++++++++ lib/main.dart | 166 ++++++---- pubspec.lock | 9 +- pubspec.yaml | 2 +- 7 files changed, 512 insertions(+), 69 deletions(-) create mode 100644 lib/all-settings.json diff --git a/android/app/build.gradle b/android/app/build.gradle index 47ddca1..5e9c507 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -2,6 +2,7 @@ plugins { id "com.android.application" id "kotlin-android" id "dev.flutter.flutter-gradle-plugin" + id "org.jetbrains.kotlin.plugin.serialization" } def localProperties = new Properties() @@ -46,7 +47,7 @@ android { applicationId "com.complycube.flutter.complycube_example" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 24 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName @@ -60,15 +61,20 @@ android { } } - packagingOptions { + packaging { resources { excludes += [ - 'META-INF/DEPENDENCIES', - 'META-INF/LICENSE', - 'META-INF/LICENSE.txt', - 'META-INF/NOTICE', - 'META-INF/NOTICE.txt' + "META-INF/DEPENDENCIES", + "META-INF/LICENSE", + "META-INF/LICENSE.txt", + "META-INF/NOTICE", + "META-INF/NOTICE.txt", + "META-INF/INDEX.LIST", + "META-INF/*.SF", + "META-INF/*.DSA", + "META-INF/*.RSA" ] + pickFirsts += ["META-INF/io.netty.versions.properties"] } } } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 6d995d2..67dffee 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,7 +5,7 @@ android:theme="@style/LaunchTheme" android:icon="@mipmap/ic_launcher"> ", + "stages": [ + { + "name": "intro", + "title": "Green Bank ID verification", + "message": "We will now verify your identity so you can start trading." + }, + { + "name": "consent", + "title": "Terms of Service", + "message": "Complete your identity verification to start trading with Green Bank." + }, + { + "name": "documentCapture", + "title": "Document Capture", + "nfcEnabled": false, + "showGuidance": false, + "useLiveCaptureOnly": false, + "useMLAssistance": true, + "retryLimit": 1, + "documentTypes": { + "passport": true, + "driving_license": ["GB", "FR"], + "national_identity_card": ["GB", "FR"], + "residence_permit": ["GB", "FR"] + } + }, + { + "name": "faceCapture", + "mode": "photo", + "showGuidance": false, + "useLiveCaptureOnly": false, + "useMLAssistance": true, + "retryLimit": 1 + }, + { + "name": "faceCapture", + "mode": "video", + "showGuidance": false, + "useLiveCaptureOnly": false, + "useMLAssistance": true, + "retryLimit": 1 + }, + { + "name": "poaCapture", + "documentTypes" : { + "bank_statement": true, + "utility_bill": true + }, + "showGuidance": false, + "useLiveCaptureOnly": false, + "useMLAssistance": true, + "retryLimit": 1, + "isAddressCaptureEnabled": true + }, + { + "name": "addressCapture", + "allowedCountries": ["GB", "FR"], + "useAutoComplete": true + }, + { + "name": "customerInfo", + "title": "CustomerInfo", + "customerInfoFields": [ + { + "metadata": [ + { + "key": "Tax Residence", + "question": "Are you a tax resident outside of Canada?", + "componentType": "SINGLE_CHOICE", + "format": {"type": "NUMBER", "validation": "100"}, + "options": [ + {"label": "No, Just Canada", "value": "Canada"}, + {"label": "Yes, I am", "value": "Outside"} + ], + "required": true, + "description": + "Tax residency is usually based on where you primarily live and spend time." + }, + { + "key": "Jurisdiction Country", + "question": "Tax residences", + "componentType": "MULTI_SELECT_COUNTRY", + "constraint": { + "expression": "metadata.Tax Residence contains Outside" + }, + "required": true, + "description": + "Please select all the countries that you're a tax resident in." + }, + { + "key": "Has SSN", + "question": "Do you have Social Security Number?", + "componentType": "SINGLE_CHOICE", + "format": {"type": "NUMBER", "validation": "100"}, + "options": [ + {"label": "Yes", "value": "yes"}, + {"label": "No", "value": "no"} + ], + "constraint": { + "expression": + "metadata.Jurisdiction Country contains US" + }, + "required": true, + "description": "Your data is processed securely." + }, + { + "key": "SSN Reason", + "question": "Don't have Social Security Number?", + "componentType": "SINGLE_CHOICE", + "format": {"type": "NUMBER", "validation": "500"}, + "options": [ + {"label": "Pending Application", "value": "PA"}, + {"label": "Not Applicable", "value": "NA"}, + {"label": "Other Reason", "value": "Other"} + ], + "constraint": { + "expression": "metadata.Has SSN contains no" + }, + "required": true, + "description": "Let us know why you do not have SSN" + }, + { + "key": "SSN Reason Other", + "question": + "Provide short explanation for not having SSN?", + "componentType": "PARAGRAPH", + "format": {"type": "MAXCHAR", "validation": "500"}, + "constraint": { + "expression": "metadata.SSN Reason contains Other" + }, + "required": true, + "description": + "Let us know why so we can verify your identity another way" + }, + { + "key": "Has SIN", + "question": "Do you have Social Insurance Number?", + "componentType": "SINGLE_CHOICE", + "format": {"type": "NUMBER", "validation": "100"}, + "options": [ + {"label": "Yes", "value": "yes"}, + {"label": "No", "value": "no"} + ], + "constraint": { + "expression": + "metadata.Jurisdiction Country contains CA" + }, + "required": true, + "description": "Your data is processed securely." + }, + { + "key": "SIN Reason", + "question": "Don't have Social Insurance Number?", + "componentType": "SINGLE_CHOICE", + "format": {"type": "NUMBER", "validation": "500"}, + "options": [ + {"label": "Pending Application", "value": "PA"}, + {"label": "Not Applicable", "value": "NA"}, + {"label": "Other Reason", "value": "Other"} + ], + "constraint": { + "expression": "metadata.Has SIN contains no" + }, + "required": true, + "description": + "Let us know why you do not have Social Insurance Number" + }, + { + "key": "SIN Reason Other", + "question": + "Provide short explanation for not having Social Insurance Number", + "componentType": "PARAGRAPH", + "format": {"type": "MAXCHAR", "validation": "500"}, + "constraint": { + "expression": "metadata.SIN Reason contains Other" + }, + "required": true, + "description": + "Let us know why so we can verify your identity another way" + } + ], + "metadataTemplates": [ + { + "templateKey": "TIN_HAS", + "question": + "Do you have a TIN or equivalent for {country}", + "componentType": "SINGLE_CHOICE", + "options": [ + {"label": "Yes", "value": "yes"}, + {"label": "No", "value": "no"} + ], + "description": + "Select Yes if you have a valid Tax Identification Number or similar tax number for {country}" + }, + { + "templateKey": "TIN", + "question": "Tax Identification Number for {country}", + "componentType": "SHORT_ANSWER", + "format": {"type": "MAXCHAR", "validation": "100"}, + "description": + "Enter your Tax Identification Number for {country}" + }, + { + "templateKey": "TIN_REASON", + "question": "Don't have a TIN for {country}?", + "componentType": "SINGLE_CHOICE", + "options": [ + {"label": "Pending Application", "value": "pending"}, + {"label": "Not Applicable", "value": "na"}, + {"label": "Other", "value": "other"} + ], + "description": "Let us know why you do not have a TIN" + }, + { + "templateKey": "TIN_REASON_OTHER", + "question": "Let us know why you do not have a TIN.", + "componentType": "PARAGRAPH", + "format": {"type": "MAXCHAR", "validation": "500"}, + "description": + "Provide short explanation for not having a TIN" + } + ] + }, + { + "details": [ + { + "person": [ + "first_name", + "middle_name", + "last_name", + "gender", + "date_of_birth", + "birth_country", + "nationality", + "tax_identification_number", + "national_id", + { + "name": "ssn", + "constraint": { + "expression": "metadata.Has SSN contains yes" + } + }, + { + "name": "social_insurance_number", + "constraint": { + "expression": "metadata.Has SIN contains yes" + } + } + ], + "company": [ + "name", + "website", + "registration_number", + "incorporation_type", + { + "name": "incorporation_country", + "constraint": { + "expression": "company.registration_number SIN contains yes" + } + } + ] + } + ] + } + ] + } + ], + "lookAndFeel": { + "isDarkMode": false, + "uiInterfaceStyle": "light", + "borderRadius": 8, + "enableAnimations": true, + + "primaryButtonColor": "#000000", + "primaryButtonBgColor": "#000000", + "primaryButtonTextColor": "#FFFFFF", + "primaryButtonBorderColor": "#000000", + + "secondaryButtonColor": "#FFFFFF", + "secondaryButtonBgColor": "#FFFFFF", + "secondaryButtonTextColor": "#000000", + "secondaryButtonBorderColor": "#333333", + + "documentSelectorColor": "#FFFFFF", + "documentSelectorBorderColor": "#E0E0E0", + "documentSelectorIconColor": "#000000", + "documentSelectorTitleTextColor": "#111111", + "documentSelectorDescriptionTextColor": "#555555", + + "documentTypeSelectorBgColor": "#FFFFFF", + "documentTypeSelectorBorderColor": "#DDDDDD", + "documentTypeSelectorIconColor": "#000000", + "documentTypeSelectorTitleTextColor": "#111111", + "documentTypeSelectorDescriptionTextColor": "#555555", + + "infoPopupColor": "#F2F2F2", + "infoPopupIconColor": "#000000", + "infoPopupTitleTextColor": "#111111", + "infoPopupDescriptionTextColor": "#555555", + + "infoPanelColor": "#F2F2F2", + "infoPanelBgColor": "#F2F2F2", + "infoPanelIconColor": "#000000", + "infoPanelTitleTextColor": "#111111", + "infoPanelDescriptionTextColor": "#555555", + + "errorPopupColor": "#F8F8F8", + "errorPopupIconColor": "#333333", + "errorPopupTitleTextColor": "#000000", + "errorPopupDescriptionTextColor": "#666666", + + "errorPanelColor": "#F8F8F8", + "errorPanelBgColor": "#F8F8F8", + "errorPanelIconColor": "#333333", + "errorPanelTitleTextColor": "#000000", + "errorPanelDescriptionTextColor": "#666666", + + "cameraButtonColor": "#000000", + + "bodyTextColor": "#222222", + "headingTextColor": "#000000", + "subheadingTextColor": "#444444", + + "backgroundColor": "#FFFFFF", + "backgroundContentColor": "#000000", + "backgroundContentContrastColor": "#333333", + "backgroundDividerColor": "#E0E0E0", + + "editTextColor": "#111111" + }, + "colorScheme" : { + "primaryButtonBgColor": "#000000", + "primaryButtonTextColor": "#FFFFFF", + "primaryButtonBorderColor": "#000000", + + "secondaryButtonBgColor": "#FFFFFF", + "secondaryButtonTextColor": "#000000", + "secondaryButtonBorderColor": "#333333", + + "documentSelectorColor": "#FFFFFF", + "docTypeBgColor": "#FFFFFF", + "documentSelectorBorderColor": "#E0E0E0", + "docTypeBorderColor": "#E0E0E0", + "documentSelectorIconColor": "#000000", + "documentSelectorTitleTextColor": "#111111", + "documentSelectorDescriptionTextColor": "#555555", + + "infoPopupColor": "#F2F2F2", + "popUpBgColor": "#F2F2F2", + "infoPopupIconColor": "#000000", + "infoPopupTitleTextColor": "#111111", + "popUpTitleColor": "#111111", + "infoPopupDescriptionTextColor": "#555555", + + "errorPopupColor": "#F8F8F8", + "errorPopupIconColor": "#333333", + "errorPopupTitleTextColor": "#000000", + "errorPopupDescriptionTextColor": "#666666", + + "cameraButtonColor": "#000000", + + "bodyTextColor": "#222222", + "textSecondary": "#222222", + "headingTextColor": "#000000", + "headerTitle": "#000000", + "subheadingTextColor": "#444444", + "subheaderTitle": "#444444", + + "backgroundColor": "#FFFFFF", + "backgroundContentColor": "#000000", + "backgroundContentContrastColor": "#333333", + "backgroundDividerColor": "#E0E0E0", + "editTextColor": "#111111" + } + + +} diff --git a/lib/main.dart b/lib/main.dart index 9f4fc98..f6f2294 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,6 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:complycube/complycube.dart'; @@ -13,6 +16,42 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { + StreamSubscription? _sub; + String _status = 'idle'; + + @override + void initState() { + super.initState(); + _sub = ComplyCube.events.listen((evt) { + if (evt is ComplyCubeSuccess) { + setState(() => _status = 'success: ${evt.payload}'); + if (kDebugMode) { + print('success event: ${evt.payload}'); + } + } else if (evt is ComplyCubeError) { + setState(() => _status = 'error ${evt.code}: ${evt.message}'); + if (kDebugMode) { + print('error event: ${evt.message}'); + } + } else if (evt is ComplyCubeCancelled) { + setState(() => _status = 'cancelled'); + if (kDebugMode) { + print('cancelled event: ${evt.reason}'); + } + } else if (evt is ComplyCubeCustom) { + // optional + if (kDebugMode) { + print('custom event: ${evt.event}'); + } + } + }); + } + + @override + void dispose() { + _sub?.cancel(); + super.dispose(); + } @override Widget build(BuildContext context) { @@ -21,64 +60,81 @@ class _MyAppState extends State { appBar: AppBar( title: const Text('Plugin example app'), ), - body: ComplyCubeWidget( - settings:const { - "clientID": "CLIENT_ID", - "clientToken": "CLIENT_TOKEN", - "stages": [ - { - "name": "intro", - "title": "ID verification", - "message": "We will now verify your identity.", - }, - { - "name": 'documentCapture', - }, - 'faceCapture', + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: _start, + child: const Text('Start Verification'), + ), + const SizedBox(height: 16), + Text('Status: $_status'), ], - "lookAndFeel": { - "primaryButtonBgColor": "#000000", - "primaryButtonPressedBgColor": "#000000", - "primaryButtonBorderColor": "#000000", - "primaryButtonTextColor": "#FFFFFF", - - "linkButtonTextColor": "#000000", - "headerTitle": "#000000", - "subheaderTitle": "#000000", - "textSecondary": "#000000", - - "docTypeBgColor": "#000000", - "docTypeTextColor": "#000000", - "docTypeBorderColor": "#000000", - - "textItemType": "#000000", - "blueBigType": "#000000", - "popUpBgColor": "#000000", - "popUpTitleColor": "#000000", - - "backgroundContentColor": "#000000", - "documentSelectorIconColor": "#000000", - "documentSelectorTitleTextColor": "#000000", - - "headingTextColor": "#000000", - "cameraButtonColor": "#000000", - "borderRadius": 16, - } - }, - onError: (errors) { - print("CCube Errors:: ${errors.map((e) => e.toJson())}"); - }, - onSuccess: (result) { - print("CCube Result:: ${result.toJson()}"); - }, - onCancelled: (error) { - print("CCube Errors:: ${error.toJson()}"); - }, - onComplyCubeEvent: (event) { - print("CCube Event:: $event"); - }, + ), ), ), ); } + + Future _start() async { + // pass stages or workflowTemplateId if you pass both workflowTemplateId will be used + //also pass color scheme or look and feel to customize the ui look and feel has priority over color scheme + final settings = { + "clientID": "", + "clientToken": "", + // "workflowTemplateId": "", + "stages": ["welcome","consent","documentCapture","faceCapture","addressCapture","poaCapture"], + "lookAndFeel": { + "borderRadius": 16, + "enableAnimations": false, + "primaryButtonColor": "#000000", + "primaryButtonBgColor": "#000000", + "primaryButtonTextColor": "#FFFFFF", + "primaryButtonBorderColor": "#000000", + "secondaryButtonColor": "#FFFFFF", + "secondaryButtonBgColor": "#FFFFFF", + "secondaryButtonTextColor": "#000000", + "secondaryButtonBorderColor": "#333333", + "documentSelectorColor": "#FFFFFF", + "documentSelectorBorderColor": "#E0E0E0", + "documentSelectorIconColor": "#000000", + "documentSelectorTitleTextColor": "#111111", + "documentSelectorDescriptionTextColor": "#555555", + "documentTypeSelectorBgColor": "#FFFFFF", + "documentTypeSelectorBorderColor": "#DDDDDD", + "documentTypeSelectorIconColor": "#000000", + "documentTypeSelectorTitleTextColor": "#111111", + "documentTypeSelectorDescriptionTextColor": "#555555", + "infoPopupColor": "#F2F2F2", + "infoPopupIconColor": "#000000", + "infoPopupTitleTextColor": "#111111", + "infoPopupDescriptionTextColor": "#555555", + "infoPanelColor": "#F2F2F2", + "infoPanelBgColor": "#F2F2F2", + "infoPanelIconColor": "#000000", + "infoPanelTitleTextColor": "#111111", + "infoPanelDescriptionTextColor": "#555555", + "errorPopupColor": "#F8F8F8", + "errorPopupIconColor": "#333333", + "errorPopupTitleTextColor": "#000000", + "errorPopupDescriptionTextColor": "#666666", + "errorPanelColor": "#F8F8F8", + "errorPanelBgColor": "#F8F8F8", + "errorPanelIconColor": "#333333", + "errorPanelTitleTextColor": "#000000", + "errorPanelDescriptionTextColor": "#666666", + "cameraButtonColor": "#000000", + "bodyTextColor": "#222222", + "headingTextColor": "#000000", + "subheadingTextColor": "#444444", + "backgroundColor": "#FFFFFF", + "backgroundContentColor": "#000000", + "backgroundContentContrastColor": "#333333", + "backgroundDividerColor": "#E0E0E0", + "editTextColor": "#111111" + } + }; + await ComplyCube.start(settings); + } } diff --git a/pubspec.lock b/pubspec.lock index ac8ec1b..e5b7b3b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -44,11 +44,10 @@ packages: complycube: dependency: "direct main" description: - name: complycube - sha256: da13e2321f5e3a9da9031e751099daf04faab7b0e204d3ff26acba958df9bdc5 - url: "https://pub.dev" - source: hosted - version: "0.0.6" + path: "/Users/aniket.indulkar/Documents/GitHub/complycube-sdk-flutter-internal" + relative: false + source: path + version: "0.0.9" cupertino_icons: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d6cae16..1bc5413 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ environment: dependencies: flutter: sdk: flutter - complycube: ^0.0.6 + complycube: ^0.0.9 # When depending on this package from a real application you should use: # complycube: ^x.y.z