capacitor-microblink 0.2.0 → 0.3.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.
@@ -1,376 +1,293 @@
1
1
  package com.otto.microblink;
2
2
 
3
+ import android.Manifest;
3
4
  import android.content.Intent;
4
-
5
+ import android.util.Log;
5
6
  import androidx.activity.result.ActivityResult;
6
7
 
7
8
  import com.getcapacitor.JSObject;
9
+ import com.getcapacitor.PermissionState;
8
10
  import com.getcapacitor.Plugin;
9
11
  import com.getcapacitor.PluginCall;
10
12
  import com.getcapacitor.PluginMethod;
11
13
  import com.getcapacitor.annotation.ActivityCallback;
12
14
  import com.getcapacitor.annotation.CapacitorPlugin;
13
- import com.microblink.blinkcard.MicroblinkSDK;
14
- import com.microblink.blinkcard.activity.result.ResultStatus;
15
- import com.microblink.blinkcard.activity.result.ScanResult;
16
- import com.microblink.blinkcard.activity.result.contract.MbScan;
17
- import com.microblink.blinkcard.entities.recognizers.Recognizer;
18
- import com.microblink.blinkcard.entities.recognizers.RecognizerBundle;
19
- import com.microblink.blinkcard.entities.recognizers.blinkcard.BlinkCardProcessingStatus;
20
- import com.microblink.blinkcard.entities.recognizers.blinkcard.BlinkCardRecognizer;
21
- import com.microblink.blinkcard.results.date.SimpleDate;
22
- import com.microblink.blinkcard.uisettings.BlinkCardUISettings;
23
- import com.microblink.platform.CardScanResult;
24
- import com.microblink.platform.MicroblinkPlatform;
25
- import com.microblink.platform.MicroblinkPlatformCancelState;
26
- import com.microblink.platform.MicroblinkPlatformCardScanResultListener;
27
- import com.microblink.platform.MicroblinkPlatformConfig;
28
- import com.microblink.platform.MicroblinkPlatformConsent;
29
- import com.microblink.platform.MicroblinkPlatformProxySettings;
30
- import com.microblink.platform.MicroblinkPlatformResult;
31
- import com.microblink.platform.MicroblinkPlatformResultListener;
32
- import com.microblink.platform.MicroblinkPlatformServiceSettings;
33
- import com.microblink.platform.MicroblinkPlatformUiSettings;
34
-
35
- import org.json.JSONException;
36
-
37
- import java.util.HashMap;
38
- import java.util.Iterator;
39
- import java.util.Map;
40
-
41
- @CapacitorPlugin(name = "Microblink")
15
+ import com.getcapacitor.annotation.Permission;
16
+ import com.microblink.blinkcard.core.BlinkCardSdkSettings;
17
+ import com.microblink.blinkcard.core.result.CardAccountResult;
18
+ import com.microblink.blinkcard.core.result.DateResult;
19
+ import com.microblink.blinkcard.core.session.BlinkCardScanningResult;
20
+ import com.microblink.blinkcard.core.session.BlinkCardSessionSettings;
21
+ import com.microblink.blinkcard.core.settings.ExtractionSettings;
22
+ import com.microblink.blinkcard.core.settings.ScanningSettings;
23
+ import com.microblink.blinkcard.ux.contract.BlinkCardScanActivityResult;
24
+ import com.microblink.blinkcard.ux.contract.BlinkCardScanActivitySettings;
25
+ import com.microblink.blinkcard.ux.contract.MbBlinkCardScan;
26
+ import com.microblink.blinkcard.ux.contract.ScanActivityResultStatus;
27
+
28
+ import java.util.List;
29
+ import java.util.function.Consumer;
30
+
31
+ @CapacitorPlugin(
32
+ name = "Microblink",
33
+ permissions = {
34
+ @Permission(alias = "camera", strings = { Manifest.permission.CAMERA })
35
+ }
36
+ )
42
37
  public class MicroblinkPlugin extends Plugin {
38
+ private static final String TAG = "MicroblinkPlugin";
43
39
 
44
- private PluginCall pendingVerificationCall;
45
- private JSObject pendingVerificationCardScanResult;
40
+ private boolean isBlinkCardInitialized;
41
+ private String blinkCardLicenseKey;
42
+ private String blinkCardLicensee;
46
43
 
47
- @PluginMethod
48
- public void startVerification(PluginCall call) {
49
- if (pendingVerificationCall != null) {
50
- call.reject("A verification flow is already running.");
44
+ @Override
45
+ public void load() {
46
+ super.load();
47
+
48
+ String configuredLicenseKey = normalized(getConfig().getString("licenseKey"));
49
+ if (configuredLicenseKey == null) {
51
50
  return;
52
51
  }
53
52
 
54
- String workflowId = call.getString("workflowId");
55
- String url = call.getString("url");
56
- String userId = call.getString("userId");
57
- Boolean isProcessingStoringAllowed = call.getBoolean("isProcessingStoringAllowed");
58
- Boolean isTrainingAllowed = call.getBoolean("isTrainingAllowed");
59
- String note = call.getString("note", "");
60
- Long givenOn = call.getLong("givenOn", System.currentTimeMillis());
53
+ String configuredLicensee = normalized(getConfig().getString("licensee"));
54
+ initializeBlinkCardLicense(configuredLicenseKey, configuredLicensee, errorMessage -> {
55
+ if (errorMessage != null) {
56
+ Log.w(TAG, "Auto initializeBlinkCard on load failed: " + errorMessage);
57
+ } else {
58
+ Log.i(TAG, "BlinkCard auto-initialized from plugin config.");
59
+ }
60
+ });
61
+ }
61
62
 
62
- if (workflowId == null || workflowId.isEmpty()) {
63
- call.reject("Missing required field: workflowId.");
64
- return;
65
- }
66
- if (url == null || url.isEmpty()) {
67
- call.reject("Missing required field: url.");
68
- return;
69
- }
70
- if (userId == null || userId.isEmpty()) {
71
- call.reject("Missing required field: userId.");
63
+ @PluginMethod
64
+ public void scanCard(PluginCall call) {
65
+ if (getPermissionState("camera") != PermissionState.GRANTED) {
66
+ requestPermissionForAlias("camera", call, "cameraPermissionCallback");
72
67
  return;
73
68
  }
74
- if (isProcessingStoringAllowed == null) {
75
- call.reject("Missing required field: isProcessingStoringAllowed.");
69
+
70
+ performScanCard(call);
71
+ }
72
+
73
+ @com.getcapacitor.annotation.PermissionCallback
74
+ private void cameraPermissionCallback(PluginCall call) {
75
+ if (call == null) {
76
76
  return;
77
77
  }
78
- if (isTrainingAllowed == null) {
79
- call.reject("Missing required field: isTrainingAllowed.");
78
+
79
+ if (getPermissionState("camera") != PermissionState.GRANTED) {
80
+ call.reject("Camera permission is required to scan cards.");
80
81
  return;
81
82
  }
82
83
 
83
- MicroblinkPlatformConsent consent = new MicroblinkPlatformConsent(
84
- userId,
85
- isProcessingStoringAllowed,
86
- isTrainingAllowed,
87
- note,
88
- givenOn
89
- );
84
+ performScanCard(call);
85
+ }
86
+
87
+ private void performScanCard(PluginCall call) {
88
+ String providedLicenseKey = normalized(call.getString("licenseKey"));
89
+ String providedLicensee = normalized(call.getString("licensee"));
90
90
 
91
- Map<String, String> additionalHeaders = new HashMap<>();
92
- JSObject headersObject = call.getObject("additionalRequestHeaders");
93
- if (headersObject != null) {
94
- Iterator<String> keys = headersObject.keys();
95
- while (keys.hasNext()) {
96
- String key = keys.next();
97
- try {
98
- Object rawValue = headersObject.get(key);
99
- if (rawValue != null) {
100
- additionalHeaders.put(key, String.valueOf(rawValue));
101
- }
102
- } catch (JSONException ignored) {
103
- // Ignore malformed header value.
91
+ if (providedLicenseKey != null) {
92
+ initializeBlinkCardLicense(providedLicenseKey, providedLicensee, errorMessage -> {
93
+ if (errorMessage != null) {
94
+ call.reject(errorMessage);
95
+ return;
104
96
  }
105
- }
97
+ startBlinkCardScan(call, providedLicenseKey, providedLicensee);
98
+ });
99
+ return;
106
100
  }
107
101
 
108
- String startTransactionPath = call.getString("startTransactionPath", "");
109
- String cancelWorkflowPath = call.getString("cancelWorkflowPath", "");
110
- String workflowInfoPath = call.getString("workflowInfoPath", "");
102
+ if (!isBlinkCardInitialized || blinkCardLicenseKey == null) {
103
+ call.reject("BlinkCard is not initialized. Call initializeBlinkCard first or provide licenseKey in scanCard.");
104
+ return;
105
+ }
111
106
 
112
- MicroblinkPlatformProxySettings proxySettings = new MicroblinkPlatformProxySettings(
113
- url,
114
- startTransactionPath,
115
- cancelWorkflowPath,
116
- workflowInfoPath,
117
- additionalHeaders
118
- );
119
- MicroblinkPlatformServiceSettings serviceSettings = new MicroblinkPlatformServiceSettings(
120
- workflowId,
121
- proxySettings,
122
- consent
123
- );
124
- MicroblinkPlatformUiSettings uiSettings = new MicroblinkPlatformUiSettings();
125
-
126
- MicroblinkPlatformResultListener resultListener = new MicroblinkPlatformResultListener() {
127
- @Override
128
- public void onVerificationFinished(MicroblinkPlatformResult result) {
129
- JSObject payload = new JSObject();
130
- payload.put("canceled", false);
131
- payload.put("transactionId", result.getTransactionId());
132
- payload.put("status", toResultStatus(result.getState()));
133
- if (pendingVerificationCardScanResult != null) {
134
- payload.put("cardScanResult", pendingVerificationCardScanResult);
135
- }
136
- resolvePending(payload);
107
+ initializeBlinkCardLicense(blinkCardLicenseKey, blinkCardLicensee, errorMessage -> {
108
+ if (errorMessage != null) {
109
+ call.reject(errorMessage);
110
+ return;
137
111
  }
112
+ startBlinkCardScan(call, blinkCardLicenseKey, blinkCardLicensee);
113
+ });
114
+ }
138
115
 
139
- @Override
140
- public void onVerificationCanceled(MicroblinkPlatformCancelState cancelState) {
141
- JSObject payload = new JSObject();
142
- payload.put("canceled", true);
143
- payload.put("transactionId", cancelState.getTransactionId());
144
- payload.put("cancelReason", toCancelReason(cancelState.getCancelReason()));
145
- if (pendingVerificationCardScanResult != null) {
146
- payload.put("cardScanResult", pendingVerificationCardScanResult);
147
- }
148
- resolvePending(payload);
149
- }
150
- };
151
-
152
- MicroblinkPlatformCardScanResultListener cardScanResultListener = new MicroblinkPlatformCardScanResultListener() {
153
- @Override
154
- public void onCardScanned(CardScanResult cardResult) {
155
- JSObject cardScan = new JSObject();
156
- cardScan.put("cardNumber", cardResult.getCardNumber());
157
- cardScan.put("expiryDate", formatExpiry(cardResult));
158
- cardScan.put("owner", cardResult.getOwner());
159
- cardScan.put("cvv", cardResult.getCvv());
160
- pendingVerificationCardScanResult = cardScan;
116
+ @PluginMethod
117
+ public void initializeBlinkCard(PluginCall call) {
118
+ String licenseKey = normalized(call.getString("licenseKey"));
119
+ if (licenseKey == null) {
120
+ call.reject("Missing required field: licenseKey.");
121
+ return;
122
+ }
123
+
124
+ String licensee = normalized(call.getString("licensee"));
125
+ initializeBlinkCardLicense(licenseKey, licensee, errorMessage -> {
126
+ if (errorMessage != null) {
127
+ call.reject(errorMessage);
128
+ return;
161
129
  }
162
- };
163
130
 
164
- MicroblinkPlatformConfig config = new MicroblinkPlatformConfig(
165
- resultListener,
166
- serviceSettings,
167
- uiSettings,
168
- cardScanResultListener
169
- );
131
+ JSObject payload = new JSObject();
132
+ payload.put("initialized", true);
133
+ call.resolve(payload);
134
+ });
135
+ }
170
136
 
171
- pendingVerificationCall = call;
172
- pendingVerificationCardScanResult = null;
137
+ @PluginMethod
138
+ public void terminateBlinkCard(PluginCall call) {
139
+ BlinkCardInitBridge.terminate(error -> {
140
+ if (error != null) {
141
+ call.reject("Failed to terminate BlinkCard SDK: " + error.getMessage());
142
+ return null;
143
+ }
173
144
 
174
- if (getActivity() == null) {
175
- clearPendingState();
176
- call.reject("Unable to start verification: Activity is unavailable.");
177
- return;
178
- }
145
+ isBlinkCardInitialized = false;
146
+ blinkCardLicenseKey = null;
147
+ blinkCardLicensee = null;
179
148
 
180
- getActivity().runOnUiThread(() -> MicroblinkPlatform.INSTANCE.startVerification(getActivity(), config));
149
+ JSObject payload = new JSObject();
150
+ payload.put("terminated", true);
151
+ call.resolve(payload);
152
+ return null;
153
+ });
181
154
  }
182
155
 
183
- @PluginMethod
184
- public void scanCard(PluginCall call) {
185
- if (pendingVerificationCall != null) {
186
- call.reject("A verification flow is already running.");
156
+ private void startBlinkCardScan(PluginCall call, String licenseKey, String licensee) {
157
+ if (getContext() == null) {
158
+ call.reject("Unable to start BlinkCard scan: Context is unavailable.");
187
159
  return;
188
160
  }
189
161
 
190
- String licenseKey = call.getString("licenseKey");
191
- if (licenseKey == null || licenseKey.isEmpty()) {
192
- call.reject("Missing required field: licenseKey.");
193
- return;
194
- }
195
- String licensee = call.getString("licensee");
162
+ ExtractionSettings extractionSettings = new ExtractionSettings(
163
+ call.getBoolean("extractIban", true),
164
+ call.getBoolean("extractExpiryDate", true),
165
+ call.getBoolean("extractOwner", true),
166
+ call.getBoolean("extractCvv", true),
167
+ call.getBoolean("allowInvalidCardNumber", false)
168
+ );
196
169
 
197
- try {
198
- if (licensee != null && !licensee.isEmpty()) {
199
- MicroblinkSDK.setLicenseKey(licenseKey, licensee, getContext());
200
- } else {
201
- MicroblinkSDK.setLicenseKey(licenseKey, getContext());
202
- }
203
- } catch (RuntimeException ex) {
204
- call.reject("Failed to initialize BlinkCard license: " + ex.getMessage());
205
- return;
206
- }
170
+ ScanningSettings baseScanningSettings = new ScanningSettings();
171
+ ScanningSettings scanningSettings = baseScanningSettings.copy(
172
+ baseScanningSettings.getSkipImagesWithBlur(),
173
+ baseScanningSettings.getTiltDetectionLevel(),
174
+ baseScanningSettings.getInputImageMargin(),
175
+ extractionSettings,
176
+ baseScanningSettings.getCroppedImageSettings(),
177
+ baseScanningSettings.getLivenessSettings(),
178
+ baseScanningSettings.getAnonymizationSettings()
179
+ );
207
180
 
208
- BlinkCardRecognizer recognizer = new BlinkCardRecognizer();
209
- recognizer.setExtractOwner(call.getBoolean("extractOwner", true));
210
- recognizer.setExtractExpiryDate(call.getBoolean("extractExpiryDate", true));
211
- recognizer.setExtractCvv(call.getBoolean("extractCvv", true));
212
- recognizer.setExtractIban(call.getBoolean("extractIban", true));
213
- recognizer.setAllowInvalidCardNumber(call.getBoolean("allowInvalidCardNumber", false));
181
+ BlinkCardSessionSettings baseSessionSettings = new BlinkCardSessionSettings();
182
+ BlinkCardSessionSettings sessionSettings = baseSessionSettings.copy(
183
+ baseSessionSettings.getInputImageSource(),
184
+ scanningSettings
185
+ );
214
186
 
215
- RecognizerBundle recognizerBundle = new RecognizerBundle(recognizer);
216
- BlinkCardUISettings uiSettings = new BlinkCardUISettings(recognizerBundle);
217
- uiSettings.setEditScreenEnabled(call.getBoolean("enableEditScreen", true));
187
+ BlinkCardSdkSettings sdkSettings = licensee == null
188
+ ? new BlinkCardSdkSettings(licenseKey)
189
+ : new BlinkCardSdkSettings(licenseKey, licensee);
218
190
 
219
- MbScan scanContract = new MbScan();
220
- Intent scanIntent = scanContract.createIntent(getContext(), uiSettings);
191
+ BlinkCardScanActivitySettings activitySettings = new BlinkCardScanActivitySettings(sdkSettings, sessionSettings);
192
+ MbBlinkCardScan scanContract = new MbBlinkCardScan();
193
+ Intent scanIntent = scanContract.createIntent(getContext(), activitySettings);
221
194
  startActivityForResult(call, scanIntent, "handleBlinkCardScanResult");
222
195
  }
223
196
 
224
197
  @ActivityCallback
225
198
  private void handleBlinkCardScanResult(PluginCall call, ActivityResult activityResult) {
226
- MbScan scanContract = new MbScan();
227
- ScanResult scanResult = scanContract.parseResult(activityResult.getResultCode(), activityResult.getData());
228
-
229
- if (scanResult.getResultStatus() == ResultStatus.CANCELLED) {
230
- JSObject payload = new JSObject();
231
- payload.put("canceled", true);
232
- call.resolve(payload);
233
- return;
234
- }
199
+ MbBlinkCardScan scanContract = new MbBlinkCardScan();
200
+ BlinkCardScanActivityResult scanResult = scanContract.parseResult(
201
+ activityResult.getResultCode(),
202
+ activityResult.getData()
203
+ );
235
204
 
236
- if (scanResult.getResultStatus() == ResultStatus.EXCEPTION) {
237
- Throwable exception = scanResult.getException();
238
- String message = exception != null ? exception.getMessage() : "BlinkCard scan failed with unknown exception.";
239
- call.reject(message);
205
+ if (scanResult == null) {
206
+ call.reject("BlinkCard scan did not return any result data.");
240
207
  return;
241
208
  }
242
209
 
243
- Intent resultIntent = scanResult.getResult();
244
- if (resultIntent == null) {
245
- call.reject("BlinkCard scan did not return any result data.");
210
+ ScanActivityResultStatus status = scanResult.getStatus();
211
+ if (status == ScanActivityResultStatus.Canceled) {
212
+ JSObject payload = new JSObject();
213
+ payload.put("canceled", true);
214
+ call.resolve(payload);
246
215
  return;
247
216
  }
248
217
 
249
- RecognizerBundle resultBundle = RecognizerBundle.createFromIntent(resultIntent);
250
- if (resultBundle == null || resultBundle.getRecognizers() == null || resultBundle.getRecognizers().length == 0) {
251
- call.reject("BlinkCard result bundle is empty.");
218
+ if (status == ScanActivityResultStatus.ErrorSdkInit) {
219
+ isBlinkCardInitialized = false;
220
+ call.reject("BlinkCard scan failed because SDK initialization in scan activity failed.");
252
221
  return;
253
222
  }
254
223
 
255
- BlinkCardRecognizer blinkCardRecognizer = null;
256
- for (Recognizer<?> recognizer : resultBundle.getRecognizers()) {
257
- if (recognizer instanceof BlinkCardRecognizer) {
258
- blinkCardRecognizer = (BlinkCardRecognizer) recognizer;
259
- break;
260
- }
261
- }
262
- if (blinkCardRecognizer == null) {
263
- call.reject("BlinkCard recognizer result was not found.");
224
+ BlinkCardScanningResult result = scanResult.getResult();
225
+ if (result == null) {
226
+ call.reject("BlinkCard scan finished without scan result.");
264
227
  return;
265
228
  }
266
229
 
267
- BlinkCardRecognizer.Result result = blinkCardRecognizer.getResult();
268
230
  JSObject payload = new JSObject();
269
231
  payload.put("canceled", false);
270
- payload.put("resultState", toBlinkCardResultState(result.getResultState()));
271
- payload.put("processingStatus", toBlinkCardProcessingStatus(result.getProcessingStatus()));
272
- payload.put("cardNumber", result.getCardNumber());
273
- payload.put("cardNumberValid", result.isCardNumberValid());
274
- payload.put("cardNumberPrefix", result.getCardNumberPrefix());
275
- payload.put("owner", result.getOwner());
276
- payload.put("cvv", result.getCvv());
232
+ payload.put("resultState", "valid");
233
+ payload.put("processingStatus", "success");
234
+ payload.put("owner", result.getCardholderName());
277
235
  payload.put("iban", result.getIban());
278
- payload.put("expiryDate", toBlinkCardDate(result.getExpiryDate() != null ? result.getExpiryDate().getDate() : null));
236
+
237
+ List<CardAccountResult> cardAccounts = result.getCardAccounts();
238
+ if (cardAccounts != null && !cardAccounts.isEmpty()) {
239
+ CardAccountResult primaryAccount = cardAccounts.get(0);
240
+ payload.put("cardNumber", primaryAccount.getCardNumber());
241
+ payload.put("cardNumberValid", primaryAccount.getCardNumberValid());
242
+ payload.put("cardNumberPrefix", primaryAccount.getCardNumberPrefix());
243
+ payload.put("cvv", primaryAccount.getCvv());
244
+ payload.put("expiryDate", toBlinkCardDate(primaryAccount.getExpiryDate()));
245
+ }
246
+
279
247
  call.resolve(payload);
280
248
  }
281
249
 
282
- private JSObject toBlinkCardDate(SimpleDate simpleDate) {
283
- if (simpleDate == null) {
250
+ private JSObject toBlinkCardDate(DateResult<String> dateResult) {
251
+ if (dateResult == null || dateResult.getDay() == null || dateResult.getMonth() == null || dateResult.getYear() == null) {
284
252
  return null;
285
253
  }
254
+
286
255
  JSObject date = new JSObject();
287
- date.put("day", simpleDate.getDay());
288
- date.put("month", simpleDate.getMonth());
289
- date.put("year", simpleDate.getYear());
256
+ date.put("day", dateResult.getDay());
257
+ date.put("month", dateResult.getMonth());
258
+ date.put("year", dateResult.getYear());
290
259
  return date;
291
260
  }
292
261
 
293
- private String toBlinkCardResultState(Recognizer.Result.State state) {
294
- if (state == Recognizer.Result.State.Valid) {
295
- return "valid";
296
- }
297
- if (state == Recognizer.Result.State.Uncertain) {
298
- return "uncertain";
299
- }
300
- if (state == Recognizer.Result.State.StageValid) {
301
- return "stageValid";
302
- }
303
- return "empty";
304
- }
305
-
306
- private String toBlinkCardProcessingStatus(BlinkCardProcessingStatus status) {
307
- if (status == BlinkCardProcessingStatus.Success) {
308
- return "success";
309
- }
310
- if (status == BlinkCardProcessingStatus.DetectionFailed) {
311
- return "detectionFailed";
312
- }
313
- if (status == BlinkCardProcessingStatus.ImagePreprocessingFailed) {
314
- return "imagePreprocessingFailed";
315
- }
316
- if (status == BlinkCardProcessingStatus.StabilityTestFailed) {
317
- return "stabilityTestFailed";
318
- }
319
- if (status == BlinkCardProcessingStatus.ScanningWrongSide) {
320
- return "scanningWrongSide";
321
- }
322
- if (status == BlinkCardProcessingStatus.FieldIdentificationFailed) {
323
- return "fieldIdentificationFailed";
324
- }
325
- if (status == BlinkCardProcessingStatus.ImageReturnFailed) {
326
- return "imageReturnFailed";
262
+ private void initializeBlinkCardLicense(String licenseKey, String licensee, Consumer<String> callback) {
263
+ if (getContext() == null) {
264
+ callback.accept("Unable to initialize BlinkCard SDK: Context is unavailable.");
265
+ return;
327
266
  }
328
- return "unsupportedCard";
329
- }
330
267
 
331
- private String toResultStatus(MicroblinkPlatformResult.FinishedState state) {
332
- if (state == MicroblinkPlatformResult.FinishedState.Accept) {
333
- return "accept";
334
- }
335
- if (state == MicroblinkPlatformResult.FinishedState.Reject) {
336
- return "reject";
337
- }
338
- return "review";
339
- }
268
+ BlinkCardInitBridge.initialize(getContext(), licenseKey, licensee, error -> {
269
+ if (error != null) {
270
+ isBlinkCardInitialized = false;
271
+ callback.accept("Init failed: " + error.getMessage());
272
+ return null;
273
+ }
340
274
 
341
- private String toCancelReason(MicroblinkPlatformCancelState.CancelReason reason) {
342
- if (reason == MicroblinkPlatformCancelState.CancelReason.ConsentDenied) {
343
- return "consentDenied";
344
- }
345
- return "userCanceled";
275
+ isBlinkCardInitialized = true;
276
+ blinkCardLicenseKey = licenseKey;
277
+ blinkCardLicensee = licensee;
278
+ callback.accept(null);
279
+ return null;
280
+ });
346
281
  }
347
282
 
348
- private String formatExpiry(CardScanResult cardResult) {
349
- if (cardResult.getExpiryDate() == null) {
350
- return "";
351
- }
352
- Integer month = cardResult.getExpiryDate().getMonth();
353
- Integer year = cardResult.getExpiryDate().getYear();
354
- if (month == null && year == null) {
355
- return "";
283
+ private String normalized(String value) {
284
+ if (value == null) {
285
+ return null;
356
286
  }
357
- String monthPart = month == null ? "00" : String.format("%02d", month);
358
- String yearPart = year == null ? "0000" : String.valueOf(year);
359
- return monthPart + "/" + yearPart;
360
- }
361
-
362
- private synchronized void resolvePending(JSObject payload) {
363
- if (pendingVerificationCall == null) {
364
- clearPendingState();
365
- return;
287
+ String trimmed = value.trim();
288
+ if (trimmed.isEmpty()) {
289
+ return null;
366
290
  }
367
- PluginCall call = pendingVerificationCall;
368
- clearPendingState();
369
- call.resolve(payload);
370
- }
371
-
372
- private synchronized void clearPendingState() {
373
- pendingVerificationCall = null;
374
- pendingVerificationCardScanResult = null;
291
+ return trimmed;
375
292
  }
376
293
  }