@veriff/react-native-sdk 6.0.0 → 6.1.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,494 +0,0 @@
1
- package com.veriff.sdk.reactnative;
2
-
3
- import android.app.Activity;
4
- import android.content.Context;
5
- import android.content.Intent;
6
- import android.graphics.Color;
7
- import android.text.TextUtils;
8
- import android.util.Log;
9
-
10
- import com.facebook.react.bridge.ActivityEventListener;
11
- import com.facebook.react.bridge.Arguments;
12
- import com.facebook.react.bridge.BaseActivityEventListener;
13
- import com.facebook.react.bridge.Promise;
14
- import com.facebook.react.bridge.ReactApplicationContext;
15
- import com.facebook.react.bridge.ReactContextBaseJavaModule;
16
- import com.facebook.react.bridge.ReactMethod;
17
- import com.facebook.react.bridge.ReadableMap;
18
- import com.facebook.react.bridge.ReadableType;
19
- import com.facebook.react.bridge.WritableMap;
20
- import com.veriff.Branding;
21
- import com.veriff.Configuration;
22
- import com.veriff.Font;
23
- import com.veriff.Result;
24
- import com.veriff.Result.Status;
25
- import com.veriff.Sdk;
26
-
27
- import java.util.*;
28
-
29
- import com.veriff.GeneralConfig;
30
-
31
- import okhttp3.HttpUrl;
32
-
33
- import static android.app.Activity.RESULT_CANCELED;
34
- import static com.veriff.Result.Status.CANCELED;
35
- import static com.veriff.Result.Status.ERROR;
36
-
37
- import androidx.annotation.NonNull;
38
-
39
- import javax.annotation.Nullable;
40
-
41
- public class VeriffSdkModule extends ReactContextBaseJavaModule {
42
- /**
43
- * Indicates that the parameters passed to {@link #launchVeriff(ReadableMap, Promise)} were invalid.
44
- */
45
- private static final String ERROR_INVALID_ARGS = "E_VERIFF_INVALID_ARGUMENTS";
46
-
47
- /**
48
- * Indicates that the activity is no longer attached when the
49
- * {@link #launchVeriff(ReadableMap, Promise)} method was invoked.
50
- */
51
- private static final String ERROR_ACTIVITY_NOT_ATTACHED = "E_VERIFF_ACTIVITY_NOT_ATTACHED";
52
-
53
- /**
54
- * The user canceled left the flow before completing it.
55
- */
56
- private static final String STATUS_CANCELED = "STATUS_CANCELED";
57
-
58
- /**
59
- * The flow was completed, note that this doesn't mean there's a decision yet.
60
- */
61
- private static final String STATUS_DONE = "STATUS_DONE";
62
-
63
- /**
64
- * The flow did not complete successfully.
65
- */
66
- private static final String STATUS_ERROR = "STATUS_ERROR";
67
-
68
- private static final String DEFAULT_BASE_URL = "https://magic.veriff.me";
69
- public static final String TAG = "@veriff/RN-SDK";
70
- private static final String JS_NAME = "VeriffSdk";
71
-
72
- private static final int VERIFF_REQUEST_CODE = 47239;
73
-
74
- private static final String KEY_TOKEN = "sessionToken";
75
- private static final String KEY_BASE_URL = "baseUrl";
76
- private static final String KEY_SESSION_URL = "sessionUrl";
77
- private static final String KEY_BRANDING = "branding";
78
- private static final String KEY_LOCALE = "locale";
79
- private static final String KEY_STATUS = "status";
80
- private static final String KEY_RESULT_ERROR = "result_error";
81
-
82
- private static final String KEY_LOGO = "logo";
83
- private static final String KEY_BACKGROUND = "background";
84
- private static final String KEY_ON_BACKGROUND = "onBackground";
85
- private static final String KEY_ON_BACKGROUND_SECONDARY = "onBackgroundSecondary";
86
- private static final String KEY_ON_BACKGROUND_TERTIARY = "onBackgroundTertiary";
87
- private static final String KEY_PRIMARY = "primary";
88
- private static final String KEY_ON_PRIMARY = "onPrimary";
89
- private static final String KEY_SECONDARY = "secondary";
90
- private static final String KEY_ON_SECONDARY = "onSecondary";
91
- private static final String KEY_CAMERA_OVERLAY = "cameraOverlay";
92
- private static final String KEY_ON_CAMERA_OVERLAY = "onCameraOverlay";
93
- private static final String KEY_OUTLINE = "outline";
94
- private static final String KEY_SUCCESS = "success";
95
- private static final String KEY_ERROR = "error";
96
-
97
- public static final String KEY_BUTTON_RADIUS = "buttonRadius";
98
- private static final String KEY_CUSTOM_INTRO_SCREEN = "customIntroScreen";
99
- private static final String KEY_RN_IMAGE_URI = "uri";
100
- private static final String KEY_RN_VENDOR_DATA = "vendorData";
101
-
102
- private static final String KEY_FONT = "androidFont";
103
-
104
- private static final String KEY_FONT_REGULAR = "regular";
105
- private static final String KEY_FONT_MEDIUM = "medium";
106
- private static final String KEY_FONT_BOLD = "bold";
107
-
108
- private static final String ERROR_UNABLE_TO_ACCESS_CAMERA = "UNABLE_TO_ACCESS_CAMERA";
109
- private static final String ERROR_UNABLE_TO_RECORD_AUDIO = "UNABLE_TO_RECORD_AUDIO";
110
- private static final String ERROR_UNABLE_TO_START_CAMERA = "UNABLE_TO_START_CAMERA";
111
- private static final String ERROR_NO_IDENTIFICATION_METHODS_AVAILABLE = "NO_IDENTIFICATION_METHODS_AVAILABLE";
112
- private static final String ERROR_UNSUPPORTED_SDK_VERSION = "UNSUPPORTED_SDK_VERSION";
113
- private static final String ERROR_SESSION = "SESSION_ERROR";
114
- private static final String ERROR_SETUP = "SETUP_ERROR";
115
- private static final String ERROR_NETWORK = "NETWORK_ERROR";
116
- private static final String ERROR_UNKNOWN = "UNKNOWN_ERROR";
117
- private static final String ERROR_NFC_DISABLED = "NFC_DISABLED";
118
- private static final String ERROR_DEVICE_HAS_NO_NFC = "DEVICE_HAS_NO_NFC";
119
-
120
- private static final Map<String, Object> EXPORTED_CONSTANTS = new HashMap<>();
121
-
122
- static {
123
- // promise reject errors
124
- EXPORTED_CONSTANTS.put("errorInvalidArgs", ERROR_INVALID_ARGS);
125
- EXPORTED_CONSTANTS.put("errorActivityNotAttached", ERROR_ACTIVITY_NOT_ATTACHED);
126
-
127
- // promise resolve statuses
128
- EXPORTED_CONSTANTS.put("statusCanceled", STATUS_CANCELED);
129
- EXPORTED_CONSTANTS.put("statusDone", STATUS_DONE);
130
- EXPORTED_CONSTANTS.put("statusError", STATUS_ERROR);
131
- }
132
-
133
- private final ReactApplicationContext reactContext;
134
-
135
- @Nullable
136
- private Result lastResult;
137
-
138
- @Nullable
139
- private String sessionToken;
140
-
141
- @Nullable
142
- private String status;
143
-
144
- public VeriffSdkModule(ReactApplicationContext reactContext) {
145
- super(reactContext);
146
- this.reactContext = reactContext;
147
- }
148
-
149
- @ReactMethod
150
- public void recoverLastResult(final Promise promise) {
151
- if (lastResult != null && status != null && sessionToken != null) {
152
- sendResult(lastResult, status, sessionToken, promise);
153
- lastResult = null;
154
- sessionToken = null;
155
- status = null;
156
- }
157
- }
158
-
159
- @Override
160
- public String getName() {
161
- return JS_NAME;
162
- }
163
-
164
- @Override
165
- public Map<String, Object> getConstants() {
166
- return EXPORTED_CONSTANTS;
167
- }
168
-
169
- public String extractToken(String startUrl) {
170
- // this is suboptimal but it is what it is.. the SDK returns us a token in the
171
- // INTENT_EXTRA_SESSION_URL for matching :(
172
- HttpUrl url = HttpUrl.parse(startUrl);
173
- if (url == null) {
174
- return null;
175
- }
176
- if (url.encodedPathSegments().size() < 2) {
177
- return null;
178
- }
179
- return url.encodedPathSegments().get(1);
180
- }
181
-
182
- @ReactMethod
183
- public void launchVeriff(ReadableMap configuration, final Promise promise) {
184
- try {
185
- String sessionToken;
186
- String startUrl;
187
-
188
- if (configuration.hasKey(KEY_SESSION_URL) && !TextUtils.isEmpty(configuration.getString(KEY_SESSION_URL))) {
189
- startUrl = configuration.getString(KEY_SESSION_URL);
190
- sessionToken = extractToken(startUrl);
191
- if (TextUtils.isEmpty(startUrl) || TextUtils.isEmpty(sessionToken)) {
192
- promise.reject(ERROR_INVALID_ARGS, "Invalid session url " + startUrl);
193
- return;
194
- }
195
- } else {
196
- sessionToken = configuration.hasKey(KEY_TOKEN) ? configuration.getString(KEY_TOKEN) : null;
197
- if (TextUtils.isEmpty(sessionToken)) {
198
- promise.reject(ERROR_INVALID_ARGS, "No sessionToken in Veriff SDK configuration");
199
- return;
200
- }
201
-
202
- String baseUrl = null;
203
- if (configuration.hasKey(KEY_BASE_URL)) {
204
- baseUrl = configuration.getString(KEY_BASE_URL);
205
- }
206
- if (TextUtils.isEmpty(baseUrl)) {
207
- baseUrl = DEFAULT_BASE_URL;
208
- }
209
- if (baseUrl.endsWith("/")) {
210
- baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
211
- }
212
- startUrl = baseUrl + "/v/" + sessionToken;
213
- }
214
-
215
- this.sessionToken = sessionToken;
216
- this.lastResult = null;
217
- this.status = null;
218
-
219
- Activity activity = getCurrentActivity();
220
- if (activity == null) {
221
- promise.reject(ERROR_ACTIVITY_NOT_ATTACHED, "No activity attached while launching Veriff");
222
- return;
223
- }
224
-
225
- ActivityEventListener listener = new BaseActivityEventListener() {
226
- @Override
227
- public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
228
- if (requestCode == VERIFF_REQUEST_CODE) {
229
- if (data == null) {
230
- return;
231
- }
232
- String token = data.getStringExtra(GeneralConfig.INSTANCE.getINTENT_EXTRA_SESSION_URL());
233
- if (!sessionToken.equals(token) && !startUrl.equals(token)) {
234
- return;
235
- }
236
-
237
- reactContext.removeActivityEventListener(this);
238
-
239
- Result veriffResult = Result.fromResultIntent(data);
240
- lastResult = veriffResult;
241
- status = statusToString(getVeriffStatus(resultCode, veriffResult));
242
-
243
- sendResult(veriffResult, status, sessionToken, promise);
244
- }
245
- }
246
- };
247
-
248
- reactContext.addActivityEventListener(listener);
249
-
250
- Configuration.Builder configBuilder = new Configuration.Builder();
251
-
252
- if (configuration.hasKey(KEY_CUSTOM_INTRO_SCREEN)) {
253
- configBuilder.customIntroScreen(configuration.getBoolean(KEY_CUSTOM_INTRO_SCREEN));
254
- }
255
-
256
- if (configuration.hasKey(KEY_BRANDING)) {
257
- ReadableMap brandConfig = configuration.getMap(KEY_BRANDING);
258
- if (brandConfig != null) {
259
- Branding.Builder branding = new Branding.Builder();
260
-
261
- if (brandConfig.hasKey(KEY_LOGO)) {
262
- handleLogo(activity, KEY_LOGO, branding, brandConfig);
263
- }
264
-
265
- if (brandConfig.hasKey(KEY_BACKGROUND)) {
266
- branding.background(parseColor(brandConfig.getString(KEY_BACKGROUND)));
267
- }
268
-
269
- if (brandConfig.hasKey(KEY_ON_BACKGROUND)) {
270
- branding.onBackground(parseColor(brandConfig.getString(KEY_ON_BACKGROUND)));
271
- }
272
-
273
- if (brandConfig.hasKey(KEY_ON_BACKGROUND_SECONDARY)) {
274
- branding.onBackgroundSecondary(parseColor(brandConfig.getString(KEY_ON_BACKGROUND_SECONDARY)));
275
- }
276
-
277
- if (brandConfig.hasKey(KEY_ON_BACKGROUND_TERTIARY)) {
278
- branding.onBackgroundTertiary(parseColor(brandConfig.getString(KEY_ON_BACKGROUND_TERTIARY)));
279
- }
280
-
281
- if (brandConfig.hasKey(KEY_PRIMARY)) {
282
- branding.primary(parseColor(brandConfig.getString(KEY_PRIMARY)));
283
- }
284
-
285
- if (brandConfig.hasKey(KEY_ON_PRIMARY)) {
286
- branding.onPrimary(parseColor(brandConfig.getString(KEY_ON_PRIMARY)));
287
- }
288
-
289
- if (brandConfig.hasKey(KEY_SECONDARY)) {
290
- branding.secondary(parseColor(brandConfig.getString(KEY_SECONDARY)));
291
- }
292
-
293
- if (brandConfig.hasKey(KEY_ON_SECONDARY)) {
294
- branding.onSecondary(parseColor(brandConfig.getString(KEY_ON_SECONDARY)));
295
- }
296
-
297
- if (brandConfig.hasKey(KEY_CAMERA_OVERLAY)) {
298
- branding.cameraOverlay(parseColor(brandConfig.getString(KEY_CAMERA_OVERLAY)));
299
- }
300
-
301
- if (brandConfig.hasKey(KEY_ON_CAMERA_OVERLAY)) {
302
- branding.onCameraOverlay(parseColor(brandConfig.getString(KEY_ON_CAMERA_OVERLAY)));
303
- }
304
-
305
- if (brandConfig.hasKey(KEY_OUTLINE)) {
306
- branding.outline(parseColor(brandConfig.getString(KEY_OUTLINE)));
307
- }
308
-
309
- if (brandConfig.hasKey(KEY_SUCCESS)) {
310
- branding.success(parseColor(brandConfig.getString(KEY_SUCCESS)));
311
- }
312
-
313
- if (brandConfig.hasKey(KEY_ERROR)) {
314
- branding.error(parseColor(brandConfig.getString(KEY_ERROR)));
315
- }
316
-
317
- if (brandConfig.hasKey(KEY_BUTTON_RADIUS)) {
318
- branding.buttonRadius((float) brandConfig.getDouble(KEY_BUTTON_RADIUS));
319
- }
320
-
321
- if (brandConfig.hasKey(KEY_FONT)) {
322
- ReadableMap srcFont = brandConfig.getMap(KEY_FONT);
323
- Font font = buildFont(activity, srcFont);
324
- branding.font(font);
325
- }
326
- configBuilder.branding(branding.build());
327
- }
328
- }
329
-
330
- if (configuration.hasKey(KEY_LOCALE)) {
331
- configBuilder.locale(Locale.forLanguageTag(configuration.getString(KEY_LOCALE)));
332
- }
333
-
334
- if (configuration.hasKey(KEY_RN_VENDOR_DATA)) {
335
- configBuilder.vendorData(configuration.getString(KEY_RN_VENDOR_DATA));
336
- }
337
-
338
- Intent intent = Sdk.createLaunchIntent(activity, startUrl, configBuilder.build());
339
- activity.startActivityForResult(intent, VERIFF_REQUEST_CODE);
340
-
341
- } catch (Throwable t) {
342
- Log.e(TAG, "starting verification failed", t);
343
- promise.reject(t);
344
- }
345
- }
346
-
347
- private void sendResult(Result veriffResult, String status, String sessionToken, Promise promise) {
348
- WritableMap result = Arguments.createMap();
349
- result.putString(KEY_TOKEN, sessionToken);
350
- result.putString(KEY_STATUS, status);
351
-
352
- if (veriffResult != null && veriffResult.getError() != null) {
353
- result.putString(KEY_RESULT_ERROR, codeToError(veriffResult.getError()));
354
- }
355
-
356
- promise.resolve(result);
357
- }
358
-
359
- @NonNull
360
- private static Status getVeriffStatus(int resultCode, Result veriffResult) {
361
- Status status;
362
- if (veriffResult != null) {
363
- status = veriffResult.getStatus();
364
- } else {
365
- status = resultCode == RESULT_CANCELED ? CANCELED : ERROR;
366
- }
367
- return status;
368
- }
369
-
370
- private Font buildFont(Context context, ReadableMap src) {
371
- int regularFont = getFontId(context, src.getString(KEY_FONT_REGULAR));
372
- int mediumFont = getFontId(context, src.getString(KEY_FONT_MEDIUM));
373
- int boldFont = getFontId(context, src.getString(KEY_FONT_BOLD));
374
-
375
- Log.v(TAG, String.format("Regular font: [%s], value [%s]",
376
- src.getString(KEY_FONT_REGULAR), regularFont));
377
-
378
- Log.v(TAG, String.format("Medium font: [%s], value [%s]",
379
- src.getString(KEY_FONT_MEDIUM), mediumFont));
380
-
381
- Log.v(TAG, String.format("Bold font: [%s], value [%s]",
382
- src.getString(KEY_FONT_BOLD), boldFont));
383
-
384
- return new Font.Builder()
385
- .setRegular(regularFont)
386
- .setMedium(mediumFont)
387
- .setBold(boldFont)
388
- .build();
389
- }
390
-
391
- private void handleLogo(Context context, String key, Branding.Builder branding, ReadableMap brandConfig) {
392
- ReadableType type = brandConfig.getType(key);
393
- Log.d(TAG, "Logo type" + type);
394
- if (ReadableType.String.equals(type)) {
395
- branding.logo(getDrawableId(context, brandConfig.getString(key)));
396
- } else if (ReadableType.Map.equals(type)) {
397
- // check if it's a native RN image
398
- ReadableMap image = brandConfig.getMap(key);
399
- if (image != null) {
400
- if (image.hasKey(KEY_RN_IMAGE_URI)) {
401
- String url = image.getString(KEY_RN_IMAGE_URI);
402
- if (!TextUtils.isEmpty(url)) {
403
- // check if url has an async scheme
404
- if (isAsyncLogoUrl(url)) {
405
- Log.d(TAG, "Async logo" + url);
406
- branding.logo(new ReactNativeImageProvider(url));
407
- } else {
408
- Log.d(TAG, "Logo from resource" + url);
409
- branding.logo(getDrawableId(context, url));
410
- }
411
- } else {
412
- Log.w(TAG, "Image url is empty: " + url);
413
- }
414
- } else {
415
- for (String imageKey : image.toHashMap().keySet()) {
416
- Log.w(TAG, imageKey);
417
- }
418
- }
419
- } else {
420
- Log.w(TAG, "Provided image is null");
421
- }
422
- } else {
423
- Log.w(TAG, "Unexpected image type: " + type);
424
- }
425
- }
426
-
427
- private boolean isAsyncLogoUrl(String url) {
428
- return url.startsWith("https://") || url.startsWith("http://") || url.startsWith("file://");
429
- }
430
-
431
- private int parseColor(String hexcolor) {
432
- if (hexcolor == null) {
433
- return 0;
434
- }
435
- if (hexcolor.startsWith("#")) {
436
- return parseColor(hexcolor.substring(1));
437
- }
438
- long color = Long.parseLong(hexcolor, 16);
439
- int a = 255;
440
- if (hexcolor.length() > 6) {
441
- a = ((int) color) & 0xff;
442
- color = color >>> 8;
443
- }
444
- int r = ((int) (color >>> 16)) & 0xff;
445
- int g = ((int) (color >>> 8)) & 0xff;
446
- int b = ((int) (color >>> 0)) & 0xff;
447
- return Color.argb(a, r, g, b);
448
- }
449
-
450
- private static int getDrawableId(Context context, String name) {
451
- return context.getResources().getIdentifier(name, "drawable", context.getPackageName());
452
- }
453
-
454
- private static int getFontId(Context context, String name) {
455
- return context.getResources().getIdentifier(name, "font", context.getPackageName());
456
- }
457
-
458
- private static String codeToError(Result.Error error) {
459
- switch (error) {
460
- case UNABLE_TO_ACCESS_CAMERA:
461
- return ERROR_UNABLE_TO_ACCESS_CAMERA;
462
- case UNABLE_TO_RECORD_AUDIO:
463
- return ERROR_UNABLE_TO_RECORD_AUDIO;
464
- case UNABLE_TO_START_CAMERA:
465
- return ERROR_UNABLE_TO_START_CAMERA;
466
- case UNSUPPORTED_SDK_VERSION:
467
- return ERROR_UNSUPPORTED_SDK_VERSION;
468
- case SESSION_ERROR:
469
- return ERROR_SESSION;
470
- case NETWORK_ERROR:
471
- return ERROR_NETWORK;
472
- case SETUP_ERROR:
473
- return ERROR_SETUP;
474
- case NFC_DISABLED:
475
- return ERROR_NFC_DISABLED;
476
- case DEVICE_HAS_NO_NFC:
477
- return ERROR_DEVICE_HAS_NO_NFC;
478
- case UNKNOWN_ERROR:
479
- default:
480
- return ERROR_UNKNOWN;
481
- }
482
- }
483
-
484
- private static String statusToString(Status status) {
485
- switch (status) {
486
- case DONE:
487
- return STATUS_DONE;
488
- case CANCELED:
489
- return STATUS_CANCELED;
490
- default:
491
- return STATUS_ERROR;
492
- }
493
- }
494
- }
@@ -1,23 +0,0 @@
1
- package com.veriff.sdk.reactnative;
2
-
3
- import com.facebook.react.ReactPackage;
4
- import com.facebook.react.bridge.NativeModule;
5
- import com.facebook.react.bridge.ReactApplicationContext;
6
- import com.facebook.react.uimanager.ViewManager;
7
-
8
- import java.util.Arrays;
9
- import java.util.Collections;
10
- import java.util.List;
11
-
12
- @SuppressWarnings("unused")
13
- public class VeriffSdkPackage implements ReactPackage {
14
- @Override
15
- public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
16
- return Arrays.<NativeModule>asList(new VeriffSdkModule(reactContext));
17
- }
18
-
19
- @Override
20
- public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
21
- return Collections.emptyList();
22
- }
23
- }