capacitor-microblink 0.0.1 → 0.3.0

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,213 +1,224 @@
1
1
  package com.otto.microblink;
2
2
 
3
+ import android.content.Intent;
4
+ import android.os.Build;
5
+
6
+ import androidx.activity.result.ActivityResult;
7
+
3
8
  import com.getcapacitor.JSObject;
4
9
  import com.getcapacitor.Plugin;
5
10
  import com.getcapacitor.PluginCall;
6
11
  import com.getcapacitor.PluginMethod;
12
+ import com.getcapacitor.annotation.ActivityCallback;
7
13
  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;
14
+ import com.microblink.blinkcard.core.BlinkCardSdkSettings;
15
+ import com.microblink.blinkcard.core.result.CardAccountResult;
16
+ import com.microblink.blinkcard.core.result.DateResult;
17
+ import com.microblink.blinkcard.core.session.BlinkCardScanningResult;
18
+ import com.microblink.blinkcard.core.session.BlinkCardSessionSettings;
19
+ import com.microblink.blinkcard.core.settings.ExtractionSettings;
20
+ import com.microblink.blinkcard.core.settings.ScanningSettings;
21
+ import com.microblink.blinkcard.ux.contract.BlinkCardScanActivityResult;
22
+ import com.microblink.blinkcard.ux.contract.BlinkCardScanActivitySettings;
23
+ import com.microblink.blinkcard.ux.contract.MbBlinkCardScan;
24
+ import com.microblink.blinkcard.ux.contract.ScanActivityResultStatus;
25
+
26
+ import java.util.List;
27
+ import java.util.function.Consumer;
25
28
 
26
29
  @CapacitorPlugin(name = "Microblink")
27
30
  public class MicroblinkPlugin extends Plugin {
28
31
 
29
- private PluginCall pendingCall;
30
- private JSObject pendingCardScanResult;
32
+ private boolean isBlinkCardInitialized;
33
+ private String blinkCardLicenseKey;
34
+ private String blinkCardLicensee;
31
35
 
32
36
  @PluginMethod
33
- public void startVerification(PluginCall call) {
34
- if (pendingCall != null) {
35
- call.reject("A verification flow is already running.");
37
+ public void scanCard(PluginCall call) {
38
+ String providedLicenseKey = normalized(call.getString("licenseKey"));
39
+ String providedLicensee = normalized(call.getString("licensee"));
40
+
41
+ if (providedLicenseKey != null) {
42
+ initializeBlinkCardLicense(providedLicenseKey, providedLicensee, errorMessage -> {
43
+ if (errorMessage != null) {
44
+ call.reject(errorMessage);
45
+ return;
46
+ }
47
+ startBlinkCardScan(call, providedLicenseKey, providedLicensee);
48
+ });
36
49
  return;
37
50
  }
38
51
 
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.");
52
+ if (!isBlinkCardInitialized || blinkCardLicenseKey == null) {
53
+ call.reject("BlinkCard is not initialized. Call initializeBlinkCard first or provide licenseKey in scanCard.");
49
54
  return;
50
55
  }
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.");
56
+
57
+ startBlinkCardScan(call, blinkCardLicenseKey, blinkCardLicensee);
58
+ }
59
+
60
+ @PluginMethod
61
+ public void initializeBlinkCard(PluginCall call) {
62
+ String licenseKey = normalized(call.getString("licenseKey"));
63
+ if (licenseKey == null) {
64
+ call.reject("Missing required field: licenseKey.");
65
65
  return;
66
66
  }
67
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
- }
68
+ String licensee = normalized(call.getString("licensee"));
69
+ initializeBlinkCardLicense(licenseKey, licensee, errorMessage -> {
70
+ if (errorMessage != null) {
71
+ call.reject(errorMessage);
72
+ return;
90
73
  }
74
+
75
+ JSObject payload = new JSObject();
76
+ payload.put("initialized", true);
77
+ call.resolve(payload);
78
+ });
79
+ }
80
+
81
+ private void startBlinkCardScan(PluginCall call, String licenseKey, String licensee) {
82
+ if (getContext() == null) {
83
+ call.reject("Unable to start BlinkCard scan: Context is unavailable.");
84
+ return;
91
85
  }
92
86
 
93
- String startTransactionPath = call.getString("startTransactionPath", "");
94
- String cancelWorkflowPath = call.getString("cancelWorkflowPath", "");
95
- String workflowInfoPath = call.getString("workflowInfoPath", "");
87
+ ExtractionSettings extractionSettings = new ExtractionSettings(
88
+ call.getBoolean("extractIban", true),
89
+ call.getBoolean("extractExpiryDate", true),
90
+ call.getBoolean("extractOwner", true),
91
+ call.getBoolean("extractCvv", true),
92
+ call.getBoolean("allowInvalidCardNumber", false)
93
+ );
96
94
 
97
- MicroblinkPlatformProxySettings proxySettings = new MicroblinkPlatformProxySettings(
98
- url,
99
- startTransactionPath,
100
- cancelWorkflowPath,
101
- workflowInfoPath,
102
- additionalHeaders
95
+ ScanningSettings baseScanningSettings = new ScanningSettings();
96
+ ScanningSettings scanningSettings = baseScanningSettings.copy(
97
+ baseScanningSettings.getSkipImagesWithBlur(),
98
+ baseScanningSettings.getTiltDetectionLevel(),
99
+ baseScanningSettings.getInputImageMargin(),
100
+ extractionSettings,
101
+ baseScanningSettings.getCroppedImageSettings(),
102
+ baseScanningSettings.getLivenessSettings(),
103
+ baseScanningSettings.getAnonymizationSettings()
103
104
  );
104
- MicroblinkPlatformServiceSettings serviceSettings = new MicroblinkPlatformServiceSettings(
105
- workflowId,
106
- proxySettings,
107
- consent
105
+
106
+ BlinkCardSessionSettings baseSessionSettings = new BlinkCardSessionSettings();
107
+ BlinkCardSessionSettings sessionSettings = baseSessionSettings.copy(
108
+ baseSessionSettings.getInputImageSource(),
109
+ scanningSettings
108
110
  );
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
111
 
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
- };
112
+ BlinkCardSdkSettings sdkSettings = licensee == null
113
+ ? new BlinkCardSdkSettings(licenseKey)
114
+ : new BlinkCardSdkSettings(licenseKey, licensee);
148
115
 
149
- MicroblinkPlatformConfig config = new MicroblinkPlatformConfig(
150
- resultListener,
151
- serviceSettings,
152
- uiSettings,
153
- cardScanResultListener
154
- );
116
+ BlinkCardScanActivitySettings activitySettings = new BlinkCardScanActivitySettings(sdkSettings, sessionSettings);
117
+ MbBlinkCardScan scanContract = new MbBlinkCardScan();
118
+ Intent scanIntent = scanContract.createIntent(getContext(), activitySettings);
119
+ startActivityForResult(call, scanIntent, "handleBlinkCardScanResult");
120
+ }
155
121
 
156
- pendingCall = call;
157
- pendingCardScanResult = null;
122
+ @ActivityCallback
123
+ private void handleBlinkCardScanResult(PluginCall call, ActivityResult activityResult) {
124
+ MbBlinkCardScan scanContract = new MbBlinkCardScan();
125
+ BlinkCardScanActivityResult scanResult = scanContract.parseResult(
126
+ activityResult.getResultCode(),
127
+ activityResult.getData()
128
+ );
158
129
 
159
- if (getActivity() == null) {
160
- clearPendingState();
161
- call.reject("Unable to start verification: Activity is unavailable.");
130
+ if (scanResult == null) {
131
+ call.reject("BlinkCard scan did not return any result data.");
162
132
  return;
163
133
  }
164
134
 
165
- getActivity().runOnUiThread(() -> MicroblinkPlatform.INSTANCE.startVerification(getActivity(), config));
166
- }
135
+ ScanActivityResultStatus status = scanResult.getStatus();
136
+ if (status == ScanActivityResultStatus.Canceled) {
137
+ JSObject payload = new JSObject();
138
+ payload.put("canceled", true);
139
+ call.resolve(payload);
140
+ return;
141
+ }
167
142
 
168
- private String toResultStatus(MicroblinkPlatformResult.FinishedState state) {
169
- if (state == MicroblinkPlatformResult.FinishedState.Accept) {
170
- return "accept";
143
+ if (status == ScanActivityResultStatus.ErrorSdkInit) {
144
+ call.reject("BlinkCard scan failed because SDK initialization in scan activity failed.");
145
+ return;
171
146
  }
172
- if (state == MicroblinkPlatformResult.FinishedState.Reject) {
173
- return "reject";
147
+
148
+ BlinkCardScanningResult result = scanResult.getResult();
149
+ if (result == null) {
150
+ call.reject("BlinkCard scan finished without scan result.");
151
+ return;
174
152
  }
175
- return "review";
176
- }
177
153
 
178
- private String toCancelReason(MicroblinkPlatformCancelState.CancelReason reason) {
179
- if (reason == MicroblinkPlatformCancelState.CancelReason.ConsentDenied) {
180
- return "consentDenied";
154
+ JSObject payload = new JSObject();
155
+ payload.put("canceled", false);
156
+ payload.put("resultState", "valid");
157
+ payload.put("processingStatus", "success");
158
+ payload.put("owner", result.getCardholderName());
159
+ payload.put("iban", result.getIban());
160
+
161
+ List<CardAccountResult> cardAccounts = result.getCardAccounts();
162
+ if (cardAccounts != null && !cardAccounts.isEmpty()) {
163
+ CardAccountResult primaryAccount = null;
164
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
165
+ primaryAccount = cardAccounts.getFirst();
166
+ payload.put("cardNumber", primaryAccount.getCardNumber());
167
+ payload.put("cardNumberValid", primaryAccount.getCardNumberValid());
168
+ payload.put("cardNumberPrefix", primaryAccount.getCardNumberPrefix());
169
+ payload.put("cvv", primaryAccount.getCvv());
170
+ payload.put("expiryDate", toBlinkCardDate(primaryAccount.getExpiryDate()));
171
+ } else {
172
+ primaryAccount = cardAccounts.get(0);
173
+ payload.put("cardNumber", primaryAccount.getCardNumber());
174
+ payload.put("cardNumberValid", primaryAccount.getCardNumberValid());
175
+ payload.put("cardNumberPrefix", primaryAccount.getCardNumberPrefix());
176
+ payload.put("cvv", primaryAccount.getCvv());
177
+ payload.put("expiryDate", toBlinkCardDate(primaryAccount.getExpiryDate()));
178
+ }
179
+
181
180
  }
182
- return "userCanceled";
181
+
182
+ call.resolve(payload);
183
183
  }
184
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 "";
185
+ private JSObject toBlinkCardDate(DateResult<String> dateResult) {
186
+ if (dateResult == null || dateResult.getDay() == null || dateResult.getMonth() == null || dateResult.getYear() == null) {
187
+ return null;
193
188
  }
194
- String monthPart = month == null ? "00" : String.format("%02d", month);
195
- String yearPart = year == null ? "0000" : String.valueOf(year);
196
- return monthPart + "/" + yearPart;
189
+
190
+ JSObject date = new JSObject();
191
+ date.put("day", dateResult.getDay());
192
+ date.put("month", dateResult.getMonth());
193
+ date.put("year", dateResult.getYear());
194
+ return date;
197
195
  }
198
196
 
199
- private synchronized void resolvePending(JSObject payload) {
200
- if (pendingCall == null) {
201
- clearPendingState();
197
+ private void initializeBlinkCardLicense(String licenseKey, String licensee, Consumer<String> callback) {
198
+ if (getContext() == null) {
199
+ callback.accept("Unable to initialize BlinkCard SDK: Context is unavailable.");
202
200
  return;
203
201
  }
204
- PluginCall call = pendingCall;
205
- clearPendingState();
206
- call.resolve(payload);
202
+
203
+ BlinkCardInitBridge.initialize(getContext(), licenseKey, licensee, error -> {
204
+ if (error != null) {
205
+ isBlinkCardInitialized = false;
206
+ callback.accept("Init failed: " + error.getMessage());
207
+ return null;
208
+ }
209
+
210
+ isBlinkCardInitialized = true;
211
+ blinkCardLicenseKey = licenseKey;
212
+ blinkCardLicensee = licensee;
213
+ callback.accept(null);
214
+ return null;
215
+ });
207
216
  }
208
217
 
209
- private synchronized void clearPendingState() {
210
- pendingCall = null;
211
- pendingCardScanResult = null;
218
+ private String normalized(String value) {
219
+ if (value == null || value.isEmpty()) {
220
+ return null;
221
+ }
222
+ return value;
212
223
  }
213
224
  }