capacitor-microblink 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapacitorMicroblink'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '16.0'
15
+ s.dependency 'Capacitor'
16
+ s.dependency 'MicroblinkPlatform', '1.7.0'
17
+ s.swift_version = '5.9'
18
+ end
package/Package.swift ADDED
@@ -0,0 +1,30 @@
1
+ // swift-tools-version: 5.9
2
+ import PackageDescription
3
+
4
+ let package = Package(
5
+ name: "CapacitorMicroblink",
6
+ platforms: [.iOS(.v16)],
7
+ products: [
8
+ .library(
9
+ name: "CapacitorMicroblink",
10
+ targets: ["MicroblinkPlugin"])
11
+ ],
12
+ dependencies: [
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.1"),
14
+ .package(url: "https://github.com/MicroblinkPlatform/microblink-platform-ios.git", from: "1.7.0")
15
+ ],
16
+ targets: [
17
+ .target(
18
+ name: "MicroblinkPlugin",
19
+ dependencies: [
20
+ .product(name: "Capacitor", package: "capacitor-swift-pm"),
21
+ .product(name: "Cordova", package: "capacitor-swift-pm"),
22
+ .product(name: "MicroblinkPlatform", package: "microblink-platform-ios")
23
+ ],
24
+ path: "ios/Sources/MicroblinkPlugin"),
25
+ .testTarget(
26
+ name: "MicroblinkPluginTests",
27
+ dependencies: ["MicroblinkPlugin"],
28
+ path: "ios/Tests/MicroblinkPluginTests")
29
+ ]
30
+ )
package/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # capacitor-microblink
2
+
3
+ Capacitor plugin for microblink
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install capacitor-microblink
9
+ npx cap sync
10
+ ```
11
+
12
+ ## API
13
+
14
+ <docgen-index>
15
+
16
+ * [`startVerification(...)`](#startverification)
17
+ * [Interfaces](#interfaces)
18
+ * [Type Aliases](#type-aliases)
19
+
20
+ </docgen-index>
21
+
22
+ <docgen-api>
23
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
24
+
25
+ ### startVerification(...)
26
+
27
+ ```typescript
28
+ startVerification(options: StartVerificationOptions) => Promise<StartVerificationResult>
29
+ ```
30
+
31
+ Starts Microblink identity verification flow.
32
+
33
+ | Param | Type |
34
+ | ------------- | ----------------------------------------------------------------------------- |
35
+ | **`options`** | <code><a href="#startverificationoptions">StartVerificationOptions</a></code> |
36
+
37
+ **Returns:** <code>Promise&lt;<a href="#startverificationresult">StartVerificationResult</a>&gt;</code>
38
+
39
+ --------------------
40
+
41
+
42
+ ### Interfaces
43
+
44
+
45
+ #### StartVerificationResult
46
+
47
+ | Prop | Type |
48
+ | -------------------- | --------------------------------------------------------- |
49
+ | **`canceled`** | <code>boolean</code> |
50
+ | **`transactionId`** | <code>string \| null</code> |
51
+ | **`status`** | <code>'accept' \| 'review' \| 'reject'</code> |
52
+ | **`cancelReason`** | <code>'userCanceled' \| 'consentDenied'</code> |
53
+ | **`cardScanResult`** | <code><a href="#cardscanresult">CardScanResult</a></code> |
54
+
55
+
56
+ #### CardScanResult
57
+
58
+ | Prop | Type |
59
+ | ---------------- | ------------------- |
60
+ | **`cardNumber`** | <code>string</code> |
61
+ | **`expiryDate`** | <code>string</code> |
62
+ | **`owner`** | <code>string</code> |
63
+ | **`cvv`** | <code>string</code> |
64
+
65
+
66
+ #### StartVerificationOptions
67
+
68
+ | Prop | Type |
69
+ | -------------------------------- | --------------------------------------------------------------- |
70
+ | **`workflowId`** | <code>string</code> |
71
+ | **`url`** | <code>string</code> |
72
+ | **`userId`** | <code>string</code> |
73
+ | **`isProcessingStoringAllowed`** | <code>boolean</code> |
74
+ | **`isTrainingAllowed`** | <code>boolean</code> |
75
+ | **`note`** | <code>string</code> |
76
+ | **`givenOn`** | <code>number</code> |
77
+ | **`additionalRequestHeaders`** | <code><a href="#record">Record</a>&lt;string, string&gt;</code> |
78
+ | **`startTransactionPath`** | <code>string</code> |
79
+ | **`cancelWorkflowPath`** | <code>string</code> |
80
+ | **`workflowInfoPath`** | <code>string</code> |
81
+
82
+
83
+ ### Type Aliases
84
+
85
+
86
+ #### Record
87
+
88
+ Construct a type with a set of properties K of type T
89
+
90
+ <code>{
91
  [P in K]: T;
1
92
  }</code>
93
+
94
+ </docgen-api>
@@ -0,0 +1,63 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
4
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
5
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
6
+ }
7
+
8
+ buildscript {
9
+ repositories {
10
+ google()
11
+ mavenCentral()
12
+ maven { url "https://maven.microblink.com" }
13
+ }
14
+ dependencies {
15
+ classpath 'com.android.tools.build:gradle:8.13.0'
16
+ }
17
+ }
18
+
19
+ apply plugin: 'com.android.library'
20
+
21
+ android {
22
+ namespace = "com.otto.microblink"
23
+ compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
24
+ defaultConfig {
25
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
26
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
27
+ versionCode 1
28
+ versionName "1.0"
29
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
30
+ consumerProguardFiles "proguard-rules.pro"
31
+ }
32
+ buildTypes {
33
+ release {
34
+ minifyEnabled false
35
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
36
+ }
37
+ }
38
+ lint {
39
+ abortOnError = false
40
+ disable += ["Aligned16KB"]
41
+ }
42
+ compileOptions {
43
+ sourceCompatibility JavaVersion.VERSION_21
44
+ targetCompatibility JavaVersion.VERSION_21
45
+ }
46
+ }
47
+
48
+ repositories {
49
+ google()
50
+ mavenCentral()
51
+ maven { url "https://maven.microblink.com" }
52
+ }
53
+
54
+
55
+ dependencies {
56
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
57
+ implementation project(':capacitor-android')
58
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
59
+ implementation "com.microblink:microblink-platform:1.7.0"
60
+ testImplementation "junit:junit:$junitVersion"
61
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
62
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
63
+ }
@@ -0,0 +1,3 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <uses-permission android:name="android.permission.CAMERA" />
3
+ </manifest>
@@ -0,0 +1,213 @@
1
+ package com.otto.microblink;
2
+
3
+ import com.getcapacitor.JSObject;
4
+ import com.getcapacitor.Plugin;
5
+ import com.getcapacitor.PluginCall;
6
+ import com.getcapacitor.PluginMethod;
7
+ import com.getcapacitor.annotation.CapacitorPlugin;
8
+ import com.microblink.platform.CardScanResult;
9
+ import com.microblink.platform.MicroblinkPlatform;
10
+ import com.microblink.platform.MicroblinkPlatformCancelState;
11
+ import com.microblink.platform.MicroblinkPlatformCardScanResultListener;
12
+ import com.microblink.platform.MicroblinkPlatformConfig;
13
+ import com.microblink.platform.MicroblinkPlatformConsent;
14
+ import com.microblink.platform.MicroblinkPlatformProxySettings;
15
+ import com.microblink.platform.MicroblinkPlatformResult;
16
+ import com.microblink.platform.MicroblinkPlatformResultListener;
17
+ import com.microblink.platform.MicroblinkPlatformServiceSettings;
18
+ import com.microblink.platform.MicroblinkPlatformUiSettings;
19
+
20
+ import org.json.JSONException;
21
+
22
+ import java.util.HashMap;
23
+ import java.util.Iterator;
24
+ import java.util.Map;
25
+
26
+ @CapacitorPlugin(name = "Microblink")
27
+ public class MicroblinkPlugin extends Plugin {
28
+
29
+ private PluginCall pendingCall;
30
+ private JSObject pendingCardScanResult;
31
+
32
+ @PluginMethod
33
+ public void startVerification(PluginCall call) {
34
+ if (pendingCall != null) {
35
+ call.reject("A verification flow is already running.");
36
+ return;
37
+ }
38
+
39
+ String workflowId = call.getString("workflowId");
40
+ String url = call.getString("url");
41
+ String userId = call.getString("userId");
42
+ Boolean isProcessingStoringAllowed = call.getBoolean("isProcessingStoringAllowed");
43
+ Boolean isTrainingAllowed = call.getBoolean("isTrainingAllowed");
44
+ String note = call.getString("note", "");
45
+ Long givenOn = call.getLong("givenOn", System.currentTimeMillis());
46
+
47
+ if (workflowId == null || workflowId.isEmpty()) {
48
+ call.reject("Missing required field: workflowId.");
49
+ return;
50
+ }
51
+ if (url == null || url.isEmpty()) {
52
+ call.reject("Missing required field: url.");
53
+ return;
54
+ }
55
+ if (userId == null || userId.isEmpty()) {
56
+ call.reject("Missing required field: userId.");
57
+ return;
58
+ }
59
+ if (isProcessingStoringAllowed == null) {
60
+ call.reject("Missing required field: isProcessingStoringAllowed.");
61
+ return;
62
+ }
63
+ if (isTrainingAllowed == null) {
64
+ call.reject("Missing required field: isTrainingAllowed.");
65
+ return;
66
+ }
67
+
68
+ MicroblinkPlatformConsent consent = new MicroblinkPlatformConsent(
69
+ userId,
70
+ isProcessingStoringAllowed,
71
+ isTrainingAllowed,
72
+ note,
73
+ givenOn
74
+ );
75
+
76
+ Map<String, String> additionalHeaders = new HashMap<>();
77
+ JSObject headersObject = call.getObject("additionalRequestHeaders");
78
+ if (headersObject != null) {
79
+ Iterator<String> keys = headersObject.keys();
80
+ while (keys.hasNext()) {
81
+ String key = keys.next();
82
+ try {
83
+ Object rawValue = headersObject.get(key);
84
+ if (rawValue != null) {
85
+ additionalHeaders.put(key, String.valueOf(rawValue));
86
+ }
87
+ } catch (JSONException ignored) {
88
+ // Ignore malformed header value.
89
+ }
90
+ }
91
+ }
92
+
93
+ String startTransactionPath = call.getString("startTransactionPath", "");
94
+ String cancelWorkflowPath = call.getString("cancelWorkflowPath", "");
95
+ String workflowInfoPath = call.getString("workflowInfoPath", "");
96
+
97
+ MicroblinkPlatformProxySettings proxySettings = new MicroblinkPlatformProxySettings(
98
+ url,
99
+ startTransactionPath,
100
+ cancelWorkflowPath,
101
+ workflowInfoPath,
102
+ additionalHeaders
103
+ );
104
+ MicroblinkPlatformServiceSettings serviceSettings = new MicroblinkPlatformServiceSettings(
105
+ workflowId,
106
+ proxySettings,
107
+ consent
108
+ );
109
+ MicroblinkPlatformUiSettings uiSettings = new MicroblinkPlatformUiSettings();
110
+
111
+ MicroblinkPlatformResultListener resultListener = new MicroblinkPlatformResultListener() {
112
+ @Override
113
+ public void onVerificationFinished(MicroblinkPlatformResult result) {
114
+ JSObject payload = new JSObject();
115
+ payload.put("canceled", false);
116
+ payload.put("transactionId", result.getTransactionId());
117
+ payload.put("status", toResultStatus(result.getState()));
118
+ if (pendingCardScanResult != null) {
119
+ payload.put("cardScanResult", pendingCardScanResult);
120
+ }
121
+ resolvePending(payload);
122
+ }
123
+
124
+ @Override
125
+ public void onVerificationCanceled(MicroblinkPlatformCancelState cancelState) {
126
+ JSObject payload = new JSObject();
127
+ payload.put("canceled", true);
128
+ payload.put("transactionId", cancelState.getTransactionId());
129
+ payload.put("cancelReason", toCancelReason(cancelState.getCancelReason()));
130
+ if (pendingCardScanResult != null) {
131
+ payload.put("cardScanResult", pendingCardScanResult);
132
+ }
133
+ resolvePending(payload);
134
+ }
135
+ };
136
+
137
+ MicroblinkPlatformCardScanResultListener cardScanResultListener = new MicroblinkPlatformCardScanResultListener() {
138
+ @Override
139
+ public void onCardScanned(CardScanResult cardResult) {
140
+ JSObject cardScan = new JSObject();
141
+ cardScan.put("cardNumber", cardResult.getCardNumber());
142
+ cardScan.put("expiryDate", formatExpiry(cardResult));
143
+ cardScan.put("owner", cardResult.getOwner());
144
+ cardScan.put("cvv", cardResult.getCvv());
145
+ pendingCardScanResult = cardScan;
146
+ }
147
+ };
148
+
149
+ MicroblinkPlatformConfig config = new MicroblinkPlatformConfig(
150
+ resultListener,
151
+ serviceSettings,
152
+ uiSettings,
153
+ cardScanResultListener
154
+ );
155
+
156
+ pendingCall = call;
157
+ pendingCardScanResult = null;
158
+
159
+ if (getActivity() == null) {
160
+ clearPendingState();
161
+ call.reject("Unable to start verification: Activity is unavailable.");
162
+ return;
163
+ }
164
+
165
+ getActivity().runOnUiThread(() -> MicroblinkPlatform.INSTANCE.startVerification(getActivity(), config));
166
+ }
167
+
168
+ private String toResultStatus(MicroblinkPlatformResult.FinishedState state) {
169
+ if (state == MicroblinkPlatformResult.FinishedState.Accept) {
170
+ return "accept";
171
+ }
172
+ if (state == MicroblinkPlatformResult.FinishedState.Reject) {
173
+ return "reject";
174
+ }
175
+ return "review";
176
+ }
177
+
178
+ private String toCancelReason(MicroblinkPlatformCancelState.CancelReason reason) {
179
+ if (reason == MicroblinkPlatformCancelState.CancelReason.ConsentDenied) {
180
+ return "consentDenied";
181
+ }
182
+ return "userCanceled";
183
+ }
184
+
185
+ private String formatExpiry(CardScanResult cardResult) {
186
+ if (cardResult.getExpiryDate() == null) {
187
+ return "";
188
+ }
189
+ Integer month = cardResult.getExpiryDate().getMonth();
190
+ Integer year = cardResult.getExpiryDate().getYear();
191
+ if (month == null && year == null) {
192
+ return "";
193
+ }
194
+ String monthPart = month == null ? "00" : String.format("%02d", month);
195
+ String yearPart = year == null ? "0000" : String.valueOf(year);
196
+ return monthPart + "/" + yearPart;
197
+ }
198
+
199
+ private synchronized void resolvePending(JSObject payload) {
200
+ if (pendingCall == null) {
201
+ clearPendingState();
202
+ return;
203
+ }
204
+ PluginCall call = pendingCall;
205
+ clearPendingState();
206
+ call.resolve(payload);
207
+ }
208
+
209
+ private synchronized void clearPendingState() {
210
+ pendingCall = null;
211
+ pendingCardScanResult = null;
212
+ }
213
+ }
File without changes
package/dist/docs.json ADDED
@@ -0,0 +1,221 @@
1
+ {
2
+ "api": {
3
+ "name": "MicroblinkPlugin",
4
+ "slug": "microblinkplugin",
5
+ "docs": "",
6
+ "tags": [],
7
+ "methods": [
8
+ {
9
+ "name": "startVerification",
10
+ "signature": "(options: StartVerificationOptions) => Promise<StartVerificationResult>",
11
+ "parameters": [
12
+ {
13
+ "name": "options",
14
+ "docs": "",
15
+ "type": "StartVerificationOptions"
16
+ }
17
+ ],
18
+ "returns": "Promise<StartVerificationResult>",
19
+ "tags": [],
20
+ "docs": "Starts Microblink identity verification flow.",
21
+ "complexTypes": [
22
+ "StartVerificationResult",
23
+ "StartVerificationOptions"
24
+ ],
25
+ "slug": "startverification"
26
+ }
27
+ ],
28
+ "properties": []
29
+ },
30
+ "interfaces": [
31
+ {
32
+ "name": "StartVerificationResult",
33
+ "slug": "startverificationresult",
34
+ "docs": "",
35
+ "tags": [],
36
+ "methods": [],
37
+ "properties": [
38
+ {
39
+ "name": "canceled",
40
+ "tags": [],
41
+ "docs": "",
42
+ "complexTypes": [],
43
+ "type": "boolean"
44
+ },
45
+ {
46
+ "name": "transactionId",
47
+ "tags": [],
48
+ "docs": "",
49
+ "complexTypes": [],
50
+ "type": "string | null"
51
+ },
52
+ {
53
+ "name": "status",
54
+ "tags": [],
55
+ "docs": "",
56
+ "complexTypes": [],
57
+ "type": "'accept' | 'review' | 'reject' | undefined"
58
+ },
59
+ {
60
+ "name": "cancelReason",
61
+ "tags": [],
62
+ "docs": "",
63
+ "complexTypes": [],
64
+ "type": "'userCanceled' | 'consentDenied' | undefined"
65
+ },
66
+ {
67
+ "name": "cardScanResult",
68
+ "tags": [],
69
+ "docs": "",
70
+ "complexTypes": [
71
+ "CardScanResult"
72
+ ],
73
+ "type": "CardScanResult"
74
+ }
75
+ ]
76
+ },
77
+ {
78
+ "name": "CardScanResult",
79
+ "slug": "cardscanresult",
80
+ "docs": "",
81
+ "tags": [],
82
+ "methods": [],
83
+ "properties": [
84
+ {
85
+ "name": "cardNumber",
86
+ "tags": [],
87
+ "docs": "",
88
+ "complexTypes": [],
89
+ "type": "string"
90
+ },
91
+ {
92
+ "name": "expiryDate",
93
+ "tags": [],
94
+ "docs": "",
95
+ "complexTypes": [],
96
+ "type": "string"
97
+ },
98
+ {
99
+ "name": "owner",
100
+ "tags": [],
101
+ "docs": "",
102
+ "complexTypes": [],
103
+ "type": "string"
104
+ },
105
+ {
106
+ "name": "cvv",
107
+ "tags": [],
108
+ "docs": "",
109
+ "complexTypes": [],
110
+ "type": "string"
111
+ }
112
+ ]
113
+ },
114
+ {
115
+ "name": "StartVerificationOptions",
116
+ "slug": "startverificationoptions",
117
+ "docs": "",
118
+ "tags": [],
119
+ "methods": [],
120
+ "properties": [
121
+ {
122
+ "name": "workflowId",
123
+ "tags": [],
124
+ "docs": "",
125
+ "complexTypes": [],
126
+ "type": "string"
127
+ },
128
+ {
129
+ "name": "url",
130
+ "tags": [],
131
+ "docs": "",
132
+ "complexTypes": [],
133
+ "type": "string"
134
+ },
135
+ {
136
+ "name": "userId",
137
+ "tags": [],
138
+ "docs": "",
139
+ "complexTypes": [],
140
+ "type": "string"
141
+ },
142
+ {
143
+ "name": "isProcessingStoringAllowed",
144
+ "tags": [],
145
+ "docs": "",
146
+ "complexTypes": [],
147
+ "type": "boolean"
148
+ },
149
+ {
150
+ "name": "isTrainingAllowed",
151
+ "tags": [],
152
+ "docs": "",
153
+ "complexTypes": [],
154
+ "type": "boolean"
155
+ },
156
+ {
157
+ "name": "note",
158
+ "tags": [],
159
+ "docs": "",
160
+ "complexTypes": [],
161
+ "type": "string | undefined"
162
+ },
163
+ {
164
+ "name": "givenOn",
165
+ "tags": [],
166
+ "docs": "",
167
+ "complexTypes": [],
168
+ "type": "number | undefined"
169
+ },
170
+ {
171
+ "name": "additionalRequestHeaders",
172
+ "tags": [],
173
+ "docs": "",
174
+ "complexTypes": [
175
+ "Record"
176
+ ],
177
+ "type": "Record<string, string>"
178
+ },
179
+ {
180
+ "name": "startTransactionPath",
181
+ "tags": [],
182
+ "docs": "",
183
+ "complexTypes": [],
184
+ "type": "string | undefined"
185
+ },
186
+ {
187
+ "name": "cancelWorkflowPath",
188
+ "tags": [],
189
+ "docs": "",
190
+ "complexTypes": [],
191
+ "type": "string | undefined"
192
+ },
193
+ {
194
+ "name": "workflowInfoPath",
195
+ "tags": [],
196
+ "docs": "",
197
+ "complexTypes": [],
198
+ "type": "string | undefined"
199
+ }
200
+ ]
201
+ }
202
+ ],
203
+ "enums": [],
204
+ "typeAliases": [
205
+ {
206
+ "name": "Record",
207
+ "slug": "record",
208
+ "docs": "Construct a type with a set of properties K of type T",
209
+ "types": [
210
+ {
211
+ "text": "{\r\n [P in K]: T;\r\n}",
212
+ "complexTypes": [
213
+ "K",
214
+ "T"
215
+ ]
216
+ }
217
+ ]
218
+ }
219
+ ],
220
+ "pluginConfigs": []
221
+ }
@@ -0,0 +1,32 @@
1
+ export interface StartVerificationOptions {
2
+ workflowId: string;
3
+ url: string;
4
+ userId: string;
5
+ isProcessingStoringAllowed: boolean;
6
+ isTrainingAllowed: boolean;
7
+ note?: string;
8
+ givenOn?: number;
9
+ additionalRequestHeaders?: Record<string, string>;
10
+ startTransactionPath?: string;
11
+ cancelWorkflowPath?: string;
12
+ workflowInfoPath?: string;
13
+ }
14
+ export interface CardScanResult {
15
+ cardNumber: string;
16
+ expiryDate: string;
17
+ owner: string;
18
+ cvv: string;
19
+ }
20
+ export interface StartVerificationResult {
21
+ canceled: boolean;
22
+ transactionId: string | null;
23
+ status?: 'accept' | 'review' | 'reject';
24
+ cancelReason?: 'userCanceled' | 'consentDenied';
25
+ cardScanResult?: CardScanResult;
26
+ }
27
+ export interface MicroblinkPlugin {
28
+ /**
29
+ * Starts Microblink identity verification flow.
30
+ */
31
+ startVerification(options: StartVerificationOptions): Promise<StartVerificationResult>;
32
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=definitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["export interface StartVerificationOptions {\n workflowId: string;\n url: string;\n userId: string;\n isProcessingStoringAllowed: boolean;\n isTrainingAllowed: boolean;\n note?: string;\n givenOn?: number;\n additionalRequestHeaders?: Record<string, string>;\n startTransactionPath?: string;\n cancelWorkflowPath?: string;\n workflowInfoPath?: string;\n}\n\nexport interface CardScanResult {\n cardNumber: string;\n expiryDate: string;\n owner: string;\n cvv: string;\n}\n\nexport interface StartVerificationResult {\n canceled: boolean;\n transactionId: string | null;\n status?: 'accept' | 'review' | 'reject';\n cancelReason?: 'userCanceled' | 'consentDenied';\n cardScanResult?: CardScanResult;\n}\n\nexport interface MicroblinkPlugin {\n /**\n * Starts Microblink identity verification flow.\n */\n startVerification(\n options: StartVerificationOptions,\n ): Promise<StartVerificationResult>;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { MicroblinkPlugin } from './definitions';
2
+ declare const Microblink: MicroblinkPlugin;
3
+ export * from './definitions';
4
+ export { Microblink };
@@ -0,0 +1,7 @@
1
+ import { registerPlugin } from '@capacitor/core';
2
+ const Microblink = registerPlugin('Microblink', {
3
+ web: () => import('./web').then((m) => new m.MicroblinkWeb()),
4
+ });
5
+ export * from './definitions';
6
+ export { Microblink };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,UAAU,GAAG,cAAc,CAAmB,YAAY,EAAE;IAChE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;CAC9D,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { MicroblinkPlugin } from './definitions';\n\nconst Microblink = registerPlugin<MicroblinkPlugin>('Microblink', {\n web: () => import('./web').then((m) => new m.MicroblinkWeb()),\n});\n\nexport * from './definitions';\nexport { Microblink };\n"]}
@@ -0,0 +1,5 @@
1
+ import { WebPlugin } from '@capacitor/core';
2
+ import type { MicroblinkPlugin, StartVerificationOptions, StartVerificationResult } from './definitions';
3
+ export declare class MicroblinkWeb extends WebPlugin implements MicroblinkPlugin {
4
+ startVerification(_options: StartVerificationOptions): Promise<StartVerificationResult>;
5
+ }
@@ -0,0 +1,7 @@
1
+ import { WebPlugin } from '@capacitor/core';
2
+ export class MicroblinkWeb extends WebPlugin {
3
+ async startVerification(_options) {
4
+ throw this.unimplemented('Microblink is only available on Android and iOS.');
5
+ }
6
+ }
7
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,MAAM,OAAO,aAAc,SAAQ,SAAS;IAC1C,KAAK,CAAC,iBAAiB,CACrB,QAAkC;QAElC,MAAM,IAAI,CAAC,aAAa,CAAC,kDAAkD,CAAC,CAAC;IAC/E,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type {\n MicroblinkPlugin,\n StartVerificationOptions,\n StartVerificationResult,\n} from './definitions';\n\nexport class MicroblinkWeb extends WebPlugin implements MicroblinkPlugin {\n async startVerification(\n _options: StartVerificationOptions,\n ): Promise<StartVerificationResult> {\n throw this.unimplemented('Microblink is only available on Android and iOS.');\n }\n}\n"]}
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+
5
+ const Microblink = core.registerPlugin('Microblink', {
6
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.MicroblinkWeb()),
7
+ });
8
+
9
+ class MicroblinkWeb extends core.WebPlugin {
10
+ async startVerification(_options) {
11
+ throw this.unimplemented('Microblink is only available on Android and iOS.');
12
+ }
13
+ }
14
+
15
+ var web = /*#__PURE__*/Object.freeze({
16
+ __proto__: null,
17
+ MicroblinkWeb: MicroblinkWeb
18
+ });
19
+
20
+ exports.Microblink = Microblink;
21
+ //# sourceMappingURL=plugin.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Microblink = registerPlugin('Microblink', {\n web: () => import('./web').then((m) => new m.MicroblinkWeb()),\n});\nexport * from './definitions';\nexport { Microblink };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class MicroblinkWeb extends WebPlugin {\n async startVerification(_options) {\n throw this.unimplemented('Microblink is only available on Android and iOS.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,UAAU,GAAGA,mBAAc,CAAC,YAAY,EAAE;AAChD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;AACjE,CAAC;;ACFM,MAAM,aAAa,SAASC,cAAS,CAAC;AAC7C,IAAI,MAAM,iBAAiB,CAAC,QAAQ,EAAE;AACtC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,kDAAkD,CAAC;AACpF,IAAI;AACJ;;;;;;;;;"}
package/dist/plugin.js ADDED
@@ -0,0 +1,24 @@
1
+ var capacitorMicroblink = (function (exports, core) {
2
+ 'use strict';
3
+
4
+ const Microblink = core.registerPlugin('Microblink', {
5
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.MicroblinkWeb()),
6
+ });
7
+
8
+ class MicroblinkWeb extends core.WebPlugin {
9
+ async startVerification(_options) {
10
+ throw this.unimplemented('Microblink is only available on Android and iOS.');
11
+ }
12
+ }
13
+
14
+ var web = /*#__PURE__*/Object.freeze({
15
+ __proto__: null,
16
+ MicroblinkWeb: MicroblinkWeb
17
+ });
18
+
19
+ exports.Microblink = Microblink;
20
+
21
+ return exports;
22
+
23
+ })({}, capacitorExports);
24
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Microblink = registerPlugin('Microblink', {\n web: () => import('./web').then((m) => new m.MicroblinkWeb()),\n});\nexport * from './definitions';\nexport { Microblink };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class MicroblinkWeb extends WebPlugin {\n async startVerification(_options) {\n throw this.unimplemented('Microblink is only available on Android and iOS.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,UAAU,GAAGA,mBAAc,CAAC,YAAY,EAAE;IAChD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;IACjE,CAAC;;ICFM,MAAM,aAAa,SAASC,cAAS,CAAC;IAC7C,IAAI,MAAM,iBAAiB,CAAC,QAAQ,EAAE;IACtC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,kDAAkD,CAAC;IACpF,IAAI;IACJ;;;;;;;;;;;;;;;"}
@@ -0,0 +1,168 @@
1
+ import Foundation
2
+ import Capacitor
3
+ import MicroblinkPlatform
4
+
5
+ @objc(MicroblinkPlugin)
6
+ public class MicroblinkPlugin: CAPPlugin, CAPBridgedPlugin, MicroblinkPlatformSDKDelegate {
7
+ public let identifier = "MicroblinkPlugin"
8
+ public let jsName = "Microblink"
9
+ public let pluginMethods: [CAPPluginMethod] = [
10
+ CAPPluginMethod(name: "startVerification", returnType: CAPPluginReturnPromise)
11
+ ]
12
+ private var pendingCallId: String?
13
+ private var sdk: MicroblinkPlatformSDK?
14
+ private var pendingCardScanResult: [String: Any]?
15
+
16
+ @objc public func startVerification(_ call: CAPPluginCall) {
17
+ if pendingCallId != nil {
18
+ call.reject("A verification flow is already running.")
19
+ return
20
+ }
21
+ guard let workflowId = call.getString("workflowId"), !workflowId.isEmpty else {
22
+ call.reject("Missing required field: workflowId.")
23
+ return
24
+ }
25
+ guard let url = call.getString("url"), !url.isEmpty else {
26
+ call.reject("Missing required field: url.")
27
+ return
28
+ }
29
+ guard let userId = call.getString("userId"), !userId.isEmpty else {
30
+ call.reject("Missing required field: userId.")
31
+ return
32
+ }
33
+ guard let isProcessingStoringAllowed = call.getBool("isProcessingStoringAllowed") else {
34
+ call.reject("Missing required field: isProcessingStoringAllowed.")
35
+ return
36
+ }
37
+ guard let isTrainingAllowed = call.getBool("isTrainingAllowed") else {
38
+ call.reject("Missing required field: isTrainingAllowed.")
39
+ return
40
+ }
41
+ guard let vc = bridge?.viewController else {
42
+ call.reject("No view controller available")
43
+ return
44
+ }
45
+
46
+ let givenOnMs = call.getDouble("givenOn") ?? Date().timeIntervalSince1970 * 1000
47
+ let givenOn = Date(timeIntervalSince1970: givenOnMs / 1000)
48
+ let consent = MicroblinkPlatformConsent(
49
+ userId: userId,
50
+ isProcessingStoringAllowed: isProcessingStoringAllowed,
51
+ isTrainingAllowed: isTrainingAllowed,
52
+ isGivenOn: givenOn,
53
+ note: call.getString("note")
54
+ )
55
+
56
+ let serviceSettings = MicroblinkPlatformServiceSettings(
57
+ workflowId: workflowId,
58
+ url: url,
59
+ consent: consent,
60
+ additionalRequestHeaders: call.getObject("additionalRequestHeaders") as? [String: String]
61
+ )
62
+ if let startTransaction = call.getString("startTransactionPath"), !startTransaction.isEmpty {
63
+ serviceSettings.startTransaction = startTransaction
64
+ }
65
+ if let cancelWorkflow = call.getString("cancelWorkflowPath"), !cancelWorkflow.isEmpty {
66
+ serviceSettings.cancelWorkflow = cancelWorkflow
67
+ }
68
+ if let workflowInfo = call.getString("workflowInfoPath"), !workflowInfo.isEmpty {
69
+ serviceSettings.getWorkflowInfo = workflowInfo
70
+ }
71
+
72
+ pendingCardScanResult = nil
73
+ bridge?.saveCall(call)
74
+ pendingCallId = call.callbackId
75
+ sdk = MicroblinkPlatformSDK(serviceSettings: serviceSettings, delegate: self)
76
+
77
+ let sdkViewController = sdk?.startSDK()
78
+ guard let sdkViewController else {
79
+ clearPendingState()
80
+ call.reject("Unable to start verification.")
81
+ return
82
+ }
83
+ vc.present(sdkViewController, animated: true)
84
+ }
85
+
86
+ public func microblinkPlatformSDKDidFinish(
87
+ viewController: UIViewController,
88
+ result: MicroblinkPlatformResult
89
+ ) {
90
+ var payload: [String: Any] = [
91
+ "canceled": false,
92
+ "transactionId": result.transactionId,
93
+ "status": mapStatus(result.status)
94
+ ]
95
+ if let pendingCardScanResult {
96
+ payload["cardScanResult"] = pendingCardScanResult
97
+ }
98
+ finalize(viewController: viewController, payload: payload)
99
+ }
100
+
101
+ public func microblinkPlatformSDKDidClose(
102
+ viewController: UIViewController,
103
+ cancelState: MicroblinkPlatformCancelState
104
+ ) {
105
+ var payload: [String: Any] = [
106
+ "canceled": true,
107
+ "transactionId": cancelState.transactionId as Any,
108
+ "cancelReason": mapCancelReason(cancelState.cancelReason)
109
+ ]
110
+ if let pendingCardScanResult {
111
+ payload["cardScanResult"] = pendingCardScanResult
112
+ }
113
+ finalize(viewController: viewController, payload: payload)
114
+ }
115
+
116
+ public func microblinkPlatformSDKDidFinishCardScanStep(
117
+ viewController: UIViewController,
118
+ cardScanResult: MicroblinkPlatformResultCardScanResult
119
+ ) {
120
+ pendingCardScanResult = [
121
+ "cardNumber": cardScanResult.cardNumber,
122
+ "expiryDate": cardScanResult.expiryDate,
123
+ "owner": cardScanResult.owner,
124
+ "cvv": cardScanResult.cvv
125
+ ]
126
+ }
127
+
128
+ private func mapStatus(_ status: MicroblinkPlatformResultStatus) -> String {
129
+ switch status {
130
+ case .accept:
131
+ return "accept"
132
+ case .review:
133
+ return "review"
134
+ case .reject:
135
+ return "reject"
136
+ @unknown default:
137
+ return "review"
138
+ }
139
+ }
140
+
141
+ private func mapCancelReason(_ reason: MicroblinkPlatformCancelReason) -> String {
142
+ switch reason {
143
+ case .userCanceled:
144
+ return "userCanceled"
145
+ case .consentDenied:
146
+ return "consentDenied"
147
+ @unknown default:
148
+ return "userCanceled"
149
+ }
150
+ }
151
+
152
+ private func finalize(viewController: UIViewController, payload: [String: Any]) {
153
+ viewController.dismiss(animated: true)
154
+ guard let pendingCallId, let call = bridge?.savedCall(withID: pendingCallId) else {
155
+ clearPendingState()
156
+ return
157
+ }
158
+ clearPendingState()
159
+ call.resolve(payload)
160
+ bridge?.releaseCall(withID: pendingCallId)
161
+ }
162
+
163
+ private func clearPendingState() {
164
+ pendingCallId = nil
165
+ pendingCardScanResult = nil
166
+ sdk = nil
167
+ }
168
+ }
@@ -0,0 +1,8 @@
1
+ import XCTest
2
+ @testable import MicroblinkPlugin
3
+
4
+ class MicroblinkTests: XCTestCase {
5
+ func testPluginBuilds() {
6
+ XCTAssertTrue(true)
7
+ }
8
+ }
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "capacitor-microblink",
3
+ "version": "0.0.1",
4
+ "description": "Capacitor plugin for microblink",
5
+ "main": "dist/plugin.cjs.js",
6
+ "module": "dist/esm/index.js",
7
+ "types": "dist/esm/index.d.ts",
8
+ "unpkg": "dist/plugin.js",
9
+ "files": [
10
+ "android/src/main/",
11
+ "android/build.gradle",
12
+ "dist/",
13
+ "ios/Sources",
14
+ "ios/Tests",
15
+ "Package.swift",
16
+ "CapacitorMicroblink.podspec"
17
+ ],
18
+ "author": "Otto the agent",
19
+ "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/ottotheagent/microblink-capacitor.git"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/ottotheagent/microblink-capacitor/issues"
26
+ },
27
+ "keywords": [
28
+ "capacitor",
29
+ "plugin",
30
+ "native"
31
+ ],
32
+ "scripts": {
33
+ "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
34
+ "verify:ios": "xcodebuild -scheme CapacitorMicroblink -destination generic/platform=iOS",
35
+ "verify:android": "cd android && ./gradlew clean build test && cd ..",
36
+ "verify:web": "npm run build",
37
+ "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
38
+ "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
39
+ "eslint": "eslint . --ext ts",
40
+ "prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
41
+ "swiftlint": "node-swiftlint",
42
+ "docgen": "docgen --api MicroblinkPlugin --output-readme README.md --output-json dist/docs.json",
43
+ "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
44
+ "clean": "rimraf ./dist",
45
+ "watch": "tsc --watch",
46
+ "prepublishOnly": "npm run build"
47
+ },
48
+ "devDependencies": {
49
+ "@capacitor/android": "^8.0.0",
50
+ "@capacitor/core": "^8.0.0",
51
+ "@capacitor/docgen": "^0.3.1",
52
+ "@capacitor/ios": "^8.0.0",
53
+ "@ionic/eslint-config": "^0.4.0",
54
+ "@ionic/prettier-config": "^4.0.0",
55
+ "@ionic/swiftlint-config": "^2.0.0",
56
+ "eslint": "^8.57.1",
57
+ "prettier": "^3.6.2",
58
+ "prettier-plugin-java": "^2.7.7",
59
+ "rimraf": "^6.1.0",
60
+ "rollup": "^4.53.2",
61
+ "swiftlint": "^2.0.0",
62
+ "typescript": "^5.9.3"
63
+ },
64
+ "peerDependencies": {
65
+ "@capacitor/core": ">=8.0.0"
66
+ },
67
+ "prettier": "@ionic/prettier-config",
68
+ "swiftlint": "@ionic/swiftlint-config",
69
+ "eslintConfig": {
70
+ "extends": "@ionic/eslint-config/recommended"
71
+ },
72
+ "capacitor": {
73
+ "ios": {
74
+ "src": "ios"
75
+ },
76
+ "android": {
77
+ "src": "android"
78
+ }
79
+ }
80
+ }