diff --git a/.gitignore b/.gitignore index 9c4d513..0a15922 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build +demo/info.txt demo/platforms/ios/DemoApp.xcworkspace/xcuserdata demo/platforms/ios/DemoApp.xcodeproj/xcuserdata demo/platforms/ios/DemoApp.xcodeproj/project.xcworkspace @@ -22,4 +23,4 @@ captures/ .idea/gradle.xml .idea/dictionaries .idea/libraries -*.iml \ No newline at end of file +*.iml diff --git a/README.md b/README.md index 4bf84cc..2d50645 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Official Jumio Mobile SDK plugin for Apache Cordova With this release, we only ensure compatibility with the latest Cordova versions and plugins. At the time of this release, the following minimum versions are supported: * Cordova: 7.1.0 -* Cordova Android: 6.3.0 +* Cordova Android: 6.4.0 * Cordova iOS: 4.5.3 ## Setup @@ -17,14 +17,14 @@ cordova create MyProject com.my.project "MyProject" cd MyProject cordova platform add ios cordova platform add android -cordova plugin add https://github.com/Jumio/mobile-cordova.git#v2.9.0 +cordova plugin add https://github.com/Jumio/mobile-cordova.git#v2.10.0 ``` ## Integration ### iOS -Manual integration or dependency management via cocoapods possible, please see [the official documentation of the Jumio Mobile SDK for iOS](https://github.com/Jumio/mobile-sdk-ios/tree/v2.9.0#basic-setup) +Manual integration or dependency management via cocoapods possible, please see [the official documentation of the Jumio Mobile SDK for iOS](https://github.com/Jumio/mobile-sdk-ios/tree/v2.10.0#basic-setup) ### Android @@ -41,17 +41,17 @@ Add a parameter for your SDK_VERSION into the ext-section: ``` ext { - SDK_VERSION = "2.9.0" + SDK_VERSION = "2.10.0" } ``` -Add required permissions for the products as described in chapter [Permissions](https://github.com/Jumio/mobile-sdk-android/blob/v2.9.0/README.md#permissions) +Add required permissions for the products as described in chapter [Permissions](https://github.com/Jumio/mobile-sdk-android/blob/v2.10.0/README.md#permissions) Open the android project of your cordova project located in */platforms/android* and insert the dependencies from the products you require to your **build.gradle** file. (Module: android) -* [Netverify & Fastfill](https://github.com/Jumio/mobile-sdk-android/blob/v2.9.0/docs/integration_netverify-fastfill.md#dependencies) -* [Document Verification](https://github.com/Jumio/mobile-sdk-android/blob/v2.9.0/docs/integration_document-verification.md#dependencies) -* [BAM Checkout](https://github.com/Jumio/mobile-sdk-android/blob/v2.9.0/docs/integration_bam-checkout.md#dependencies) +* [Netverify & Fastfill](https://github.com/Jumio/mobile-sdk-android/blob/v2.10.0/docs/integration_netverify-fastfill.md#dependencies) +* [Document Verification](https://github.com/Jumio/mobile-sdk-android/blob/v2.10.0/docs/integration_document-verification.md#dependencies) +* [BAM Checkout](https://github.com/Jumio/mobile-sdk-android/blob/v2.10.0/docs/integration_bam-checkout.md#dependencies) __Note:__ If you are using Netverify, make sure to add the Google vision meta-data to you **AndroidManifest.xml** accordingly: @@ -260,7 +260,7 @@ Configure the SDK with the *configuration*-Object. | cardNumberMaskingEnabled | Boolean | | offlineToken | String | In your Jumio merchant backend on the "Settings" page under "API credentials" you can find your Offline token. In case you use your offline token, you must not set the API token and secret| | cameraPosition | String | Which camera is used by default. Can be **FRONT** or **BACK**. | -| cardTypes | String-Array | An array of accepted card types. Available card types: **VISA**, **MASTER_CARD**, **AMERICAN_EXPRESS**, **CHINA_UNIONPAY**, **DINERS_CLUB**, **DISCOVER**, **JCB**, **STARBUCKS** | +| cardTypes | String-Array | An array of accepted card types. Available card types: **VISA**, **MASTER_CARD**, **AMERICAN_EXPRESS**, **CHINA_UNIONPAY**, **DINERS_CLUB**, **DISCOVER**, **JCB** | Initialization example with configuration. @@ -293,7 +293,15 @@ Jumio.startBAM(function(cardInformation) { ## Customization ### Android -The Netverify SDK can be customized to the respective needs by following this [customization chapter](https://github.com/Jumio/mobile-sdk-android/blob/v2.9.0/docs/integration_netverify-fastfill.md#customization). + +#### Netverify +The Netverify SDK can be customized to the respective needs by following this [customization chapter](https://github.com/Jumio/mobile-sdk-android/blob/v2.10.0/docs/integration_netverify-fastfill.md#customization). + +#### BAM Checkout +The Netverify SDK can be customized to the respective needs by following this [customization chapter](https://github.com/Jumio/mobile-sdk-android/blob/v2.10.0/docs/integration_bam-checkout.md#customization). + +#### Document Verification +The Netverify SDK can be customized to the respective needs by following this [customization chapter](https://github.com/Jumio/mobile-sdk-android/blob/v2.10.0/docs/integration_document-verification.md#customization). ### iOS The SDK can be customized to the respective needs. You can pass the following customization options to the initializer: diff --git a/package.json b/package.json index 7b9c7a2..1691659 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-jumio-mobilesdk", - "version": "2.9.0", + "version": "2.10.0", "description": "Jumio Mobile SDK Plugin for Cordova", "cordova": { "id": "cordova-plugin-jumio-mobilesdk", diff --git a/plugin.xml b/plugin.xml index 718496c..1acaaaa 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + JumioMobileSDK @@ -25,7 +25,7 @@ - + diff --git a/src/android/JumioMobileSDK.java b/src/android/JumioMobileSDK.java index d19be68..2b7c6d9 100644 --- a/src/android/JumioMobileSDK.java +++ b/src/android/JumioMobileSDK.java @@ -5,14 +5,6 @@ package com.jumio.mobilesdk; -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.PluginResult; -import org.apache.cordova.PluginResult.Status; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; @@ -21,569 +13,612 @@ import com.jumio.MobileSDK; import com.jumio.bam.*; -import com.jumio.bam.custom.*; import com.jumio.bam.enums.CreditCardType; -import com.jumio.commons.json.JSON; import com.jumio.core.enums.*; import com.jumio.core.exceptions.*; import com.jumio.dv.DocumentVerificationSDK; import com.jumio.nv.*; -import com.jumio.nv.data.document.NVDocumentType; -import com.jumio.nv.data.document.NVDocumentVariant; +import com.jumio.nv.data.document.*; import com.jumio.sdk.SDKExpiredException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import org.apache.cordova.*; +import org.apache.cordova.PluginResult.Status; +import org.json.*; + +import java.util.*; public class JumioMobileSDK extends CordovaPlugin { - - private static String TAG = "JumioMobileSDK"; - private static final int PERMISSION_REQUEST_CODE_BAM = 300; - private static final int PERMISSION_REQUEST_CODE_NETVERIFY = 301; - private static final int PERMISSION_REQUEST_CODE_DOCUMENT_VERIFICATION = 303; - - private static final String ACTION_BAM_INIT = "initBAM"; - private static final String ACTION_BAM_START = "startBAM"; - private static final String ACTION_NV_INIT = "initNetverify"; - private static final String ACTION_NV_START = "startNetverify"; - private static final String ACTION_DV_INIT = "initDocumentVerification"; - private static final String ACTION_DV_START = "startDocumentVerification"; - - private BamSDK bamSDK; - private NetverifySDK netverifySDK; - private DocumentVerificationSDK documentVerificationSDK; - private CallbackContext callbackContext; - private String errorMsg; - - @Override - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - PluginResult result = null; - this.callbackContext = callbackContext; - - if (action.equals(ACTION_BAM_INIT)) { - initBAM(args); - result = new PluginResult(Status.NO_RESULT); - result.setKeepCallback(false); - return true; - } else if (action.equals(ACTION_BAM_START)) { - startBAM(args); - result = new PluginResult(Status.NO_RESULT); - result.setKeepCallback(true); - return true; - } else if (action.equals(ACTION_NV_INIT)) { - initNetverify(args); - result = new PluginResult(Status.NO_RESULT); - result.setKeepCallback(false); - return true; - } else if (action.equals(ACTION_NV_START)) { - startNetverify(args); - result = new PluginResult(Status.NO_RESULT); - result.setKeepCallback(true); - return true; - } else if (action.equals(ACTION_DV_INIT)) { - initDocumentVerification(args); - result = new PluginResult(Status.NO_RESULT); - result.setKeepCallback(false); - return true; - } else if (action.equals(ACTION_DV_START)) { - startDocumentVerification(args); - result = new PluginResult(Status.NO_RESULT); - result.setKeepCallback(true); - return true; - } else { - result = new PluginResult(Status.INVALID_ACTION); - callbackContext.error("Invalid Action"); - return false; - } - } - - // BAM Checkout - - private void initBAM(JSONArray data) { - if (BamSDK.isRooted(cordova.getActivity().getApplicationContext())) { - showErrorMessage("The BAM SDK can't run on a rooted device."); - return; - } - - if (!BamSDK.isSupportedPlatform(cordova.getActivity())) { - showErrorMessage("This platform is not supported."); - return; - } - - try { - JSONObject options = data.getJSONObject(3); - if (options.has("offlineToken")) { - String offlineToken = options.getString("offlineToken"); - bamSDK = BamSDK.create(cordova.getActivity(), offlineToken); - } else { - if (data.isNull(0) || data.isNull(1) || data.isNull(2)) { - showErrorMessage("Missing required parameters apiToken, apiSecret or dataCenter."); - return; - } - - String apiToken = data.getString(0); - String apiSecret = data.getString(1); - JumioDataCenter dataCenter = (data.getString(2).toLowerCase().equals("us")) ? JumioDataCenter.US : JumioDataCenter.EU; - - bamSDK = BamSDK.create(cordova.getActivity(), apiToken, apiSecret, dataCenter); - } - - // Configuration options - if (!data.isNull(3)) { - options = data.getJSONObject(3); - Iterator keys = options.keys(); - while (keys.hasNext()) { - String key = keys.next(); - - if (key.equals("cardHolderNameRequired")) { - bamSDK.setCardHolderNameRequired(options.getBoolean(key)); - } else if (key.equals("sortCodeAndAccountNumberRequired")) { - bamSDK.setSortCodeAndAccountNumberRequired(options.getBoolean(key)); - } else if (key.equals("expiryRequired")) { - bamSDK.setExpiryRequired(options.getBoolean(key)); - } else if (key.equals("cvvRequired")) { - bamSDK.setCvvRequired(options.getBoolean(key)); - } else if (key.equals("expiryEditable")) { - bamSDK.setExpiryEditable(options.getBoolean(key)); - } else if (key.equals("cardHolderNameEditable")) { - bamSDK.setCardHolderNameEditable(options.getBoolean(key)); - } else if (key.equals("merchantReportingCriteria")) { - bamSDK.setMerchantReportingCriteria(options.getString(key)); - } else if (key.equals("vibrationEffectEnabled")) { - bamSDK.setVibrationEffectEnabled(options.getBoolean(key)); - } else if (key.equals("enableFlashOnScanStart")) { - bamSDK.setEnableFlashOnScanStart(options.getBoolean(key)); - } else if (key.equals("cardNumberMaskingEnabled")) { - bamSDK.setCardNumberMaskingEnabled(options.getBoolean(key)); - } else if (key.equals("cameraPosition")) { - JumioCameraPosition cameraPosition = (options.getString(key).toLowerCase().equals("front")) ? JumioCameraPosition.FRONT : JumioCameraPosition.BACK; - bamSDK.setCameraPosition(cameraPosition); - } else if (key.equals("cardTypes")) { - JSONArray jsonTypes = options.getJSONArray(key); - ArrayList types = new ArrayList(); - if (jsonTypes != null) { - int len = jsonTypes.length(); - for (int i=0;i creditCardTypes = new ArrayList(); - for (String type : types) { - if (type.toLowerCase().equals("visa")) { - creditCardTypes.add(CreditCardType.VISA); - } else if (type.toLowerCase().equals("master_card")) { - creditCardTypes.add(CreditCardType.MASTER_CARD); - } else if (type.toLowerCase().equals("american_express")) { - creditCardTypes.add(CreditCardType.AMERICAN_EXPRESS); - } else if (type.toLowerCase().equals("china_unionpay")) { - creditCardTypes.add(CreditCardType.CHINA_UNIONPAY); - } else if (type.toLowerCase().equals("diners_club")) { - creditCardTypes.add(CreditCardType.DINERS_CLUB); - } else if (type.toLowerCase().equals("discover")) { - creditCardTypes.add(CreditCardType.DISCOVER); - } else if (type.toLowerCase().equals("jcb")) { - creditCardTypes.add(CreditCardType.JCB); - } else if (type.toLowerCase().equals("starbucks")) { - creditCardTypes.add(CreditCardType.STARBUCKS); - } - } - - bamSDK.setSupportedCreditCardTypes(creditCardTypes); - } - } - } - } catch (JSONException e) { - showErrorMessage("Invalid parameters: " + e.getLocalizedMessage()); - } catch (PlatformNotSupportedException e) { - showErrorMessage("Error initializing the BAM SDK: " + e.getLocalizedMessage()); - } catch (SDKExpiredException e) { - showErrorMessage("Error initializing the BAM SDK: " + e.getLocalizedMessage()); - } - } - - private void startBAM(JSONArray data) { - if (bamSDK == null) { - showErrorMessage("The BAM SDK is not initialized yet. Call initBAM() first."); - return; - } - - Runnable runnable = new Runnable() { - @Override - public void run() { - try { - checkPermissionsAndStart(bamSDK); - } catch (Exception e) { - showErrorMessage("Error starting the BAM SDK: " + e.getLocalizedMessage()); - } - } - }; - - this.cordova.setActivityResultCallback(this); - this.cordova.getActivity().runOnUiThread(runnable); - } - - // Netverify - - private void initNetverify(JSONArray data) { - if (!NetverifySDK.isSupportedPlatform(cordova.getActivity())) { - showErrorMessage("This platform is not supported."); - return; - } - - try { - if (data.isNull(0) || data.isNull(1) || data.isNull(2)) { - showErrorMessage("Missing required parameters apiToken, apiSecret or dataCenter."); - return; - } - - String apiToken = data.getString(0); - String apiSecret = data.getString(1); - JumioDataCenter dataCenter = (data.getString(2).toLowerCase().equals("us")) ? JumioDataCenter.US : JumioDataCenter.EU; - - netverifySDK = NetverifySDK.create(cordova.getActivity(), apiToken, apiSecret, dataCenter); - - // Configuration options - if (!data.isNull(3)) { - JSONObject options = data.getJSONObject(3); - Iterator keys = options.keys(); - while (keys.hasNext()) { - String key = keys.next(); - - if (key.equals("requireVerification")) { - netverifySDK.setRequireVerification(options.getBoolean(key)); - } else if (key.equals("callbackUrl")) { - netverifySDK.setCallbackUrl(options.getString(key)); - } else if (key.equals("requireFaceMatch")) { - netverifySDK.setRequireFaceMatch(options.getBoolean(key)); - } else if (key.equals("preselectedCountry")) { - netverifySDK.setPreselectedCountry(options.getString(key)); - } else if (key.equals("merchantScanReference")) { - netverifySDK.setMerchantScanReference(options.getString(key)); - } else if (key.equals("merchantReportingCriteria")) { - netverifySDK.setMerchantReportingCriteria(options.getString(key)); - } else if (key.equals("customerID")) { - netverifySDK.setCustomerId(options.getString(key)); - } else if (key.equals("additionalInformation")) { - netverifySDK.setAdditionalInformation(options.getString(key)); - } else if (key.equals("enableEpassport")) { - netverifySDK.setEnableEMRTD(options.getBoolean(key)); - } else if (key.equals("sendDebugInfoToJumio")) { - netverifySDK.sendDebugInfoToJumio(options.getBoolean(key)); - } else if (key.equals("dataExtractionOnMobileOnly")) { - netverifySDK.setDataExtractionOnMobileOnly(options.getBoolean(key)); - } else if (key.equals("cameraPosition")) { - JumioCameraPosition cameraPosition = (options.getString(key).toLowerCase().equals("front")) ? JumioCameraPosition.FRONT : JumioCameraPosition.BACK; - netverifySDK.setCameraPosition(cameraPosition); - } else if (key.equals("preselectedDocumentVariant")) { - NVDocumentVariant variant = (options.getString(key).toLowerCase().equals("paper")) ? NVDocumentVariant.PAPER : NVDocumentVariant.PLASTIC; - netverifySDK.setPreselectedDocumentVariant(variant); - } else if (key.equals("documentTypes")) { - JSONArray jsonTypes = options.getJSONArray(key); - ArrayList types = new ArrayList(); - if (jsonTypes != null) { - int len = jsonTypes.length(); - for (int i=0;i documentTypes = new ArrayList(); - for (String type : types) { - if (type.toLowerCase().equals("passport")) { - documentTypes.add(NVDocumentType.PASSPORT); - } else if (type.toLowerCase().equals("driver_license")) { - documentTypes.add(NVDocumentType.DRIVER_LICENSE); - } else if (type.toLowerCase().equals("identity_card")) { - documentTypes.add(NVDocumentType.IDENTITY_CARD); - } else if (type.toLowerCase().equals("visa")) { - documentTypes.add(NVDocumentType.VISA); - } - } - - netverifySDK.setPreselectedDocumentTypes(documentTypes); - } - } - } - } catch (JSONException e) { - showErrorMessage("Invalid parameters: " + e.getLocalizedMessage()); - } catch (PlatformNotSupportedException e) { - showErrorMessage("Error initializing the Netverify SDK: " + e.getLocalizedMessage()); - } - } - - private void startNetverify(JSONArray data) { - if (netverifySDK == null) { - showErrorMessage("The Netverify SDK is not initialized yet. Call initNetverify() first."); - return; - } - - Runnable runnable = new Runnable() { - @Override - public void run() { - try { - checkPermissionsAndStart(netverifySDK); - } catch (Exception e) { - showErrorMessage("Error starting the Netverify SDK: " + e.getLocalizedMessage()); - } - } - }; - - this.cordova.setActivityResultCallback(this); - this.cordova.getActivity().runOnUiThread(runnable); - } - - // Document Verification - - private void initDocumentVerification(JSONArray data) { - if (!DocumentVerificationSDK.isSupportedPlatform(cordova.getActivity())) { - showErrorMessage("This platform is not supported."); - return; - } - - try { - if (data.isNull(0) || data.isNull(1) || data.isNull(2)) { - showErrorMessage("Missing required parameters apiToken, apiSecret or dataCenter."); - return; - } - - String apiToken = data.getString(0); - String apiSecret = data.getString(1); - JumioDataCenter dataCenter = (data.getString(2).toLowerCase().equals("us")) ? JumioDataCenter.US : JumioDataCenter.EU; - - documentVerificationSDK = DocumentVerificationSDK.create(cordova.getActivity(), apiToken, apiSecret, dataCenter); - - // Configuration options - if (!data.isNull(3)) { - JSONObject options = data.getJSONObject(3); - Iterator keys = options.keys(); - while (keys.hasNext()) { - String key = keys.next(); - - if (key.equals("type")) { - documentVerificationSDK.setType(options.getString(key)); - } else if (key.equals("customDocumentCode")) { - documentVerificationSDK.setCustomDocumentCode(options.getString(key)); - } else if (key.equals("country")) { - documentVerificationSDK.setCountry(options.getString(key)); - } else if (key.equals("merchantReportingCriteria")) { - documentVerificationSDK.setMerchantReportingCriteria(options.getString(key)); - } else if (key.equals("callbackUrl")) { - documentVerificationSDK.setCallbackUrl(options.getString(key)); - } else if (key.equals("additionalInformation")) { - documentVerificationSDK.setAdditionalInformation(options.getString(key)); - } else if (key.equals("merchantScanReference")) { - documentVerificationSDK.setMerchantScanReference(options.getString(key)); - } else if (key.equals("customerId")) { - documentVerificationSDK.setCustomerId(options.getString(key)); - } else if (key.equals("documentName")) { - documentVerificationSDK.setDocumentName(options.getString(key)); - } else if (key.equals("cameraPosition")) { - JumioCameraPosition cameraPosition = (options.getString(key).toLowerCase().equals("front")) ? JumioCameraPosition.FRONT : JumioCameraPosition.BACK; - documentVerificationSDK.setCameraPosition(cameraPosition); - } - } - } - - // Configuration options - if (!data.isNull(3)) { - JSONObject options = data.getJSONObject(3); - Iterator keys = options.keys(); - while (keys.hasNext()) { - String key = keys.next(); - - // ... - } - } - } catch (JSONException e) { - showErrorMessage("Invalid parameters: " + e.getLocalizedMessage()); - } catch (PlatformNotSupportedException e) { - showErrorMessage("Error initializing the Document Verification SDK: " + e.getLocalizedMessage()); - } - } - - private void startDocumentVerification(JSONArray data) { - if (documentVerificationSDK == null) { - showErrorMessage("The Document Verification SDK is not initialized yet. Call initDocumentVerification() first."); - return; - } - - Runnable runnable = new Runnable() { - @Override - public void run() { - try { - checkPermissionsAndStart(documentVerificationSDK); - } catch (Exception e) { - showErrorMessage("Error starting the Document Verification SDK: " + e.getLocalizedMessage()); - } - } - }; - - this.cordova.setActivityResultCallback(this); - this.cordova.getActivity().runOnUiThread(runnable); - } - - - // Permissions - - private void checkPermissionsAndStart(MobileSDK sdk) { - if (!MobileSDK.hasAllRequiredPermissions(cordova.getActivity().getApplicationContext())) { - //Acquire missing permissions. - String[] mp = MobileSDK.getMissingPermissions(cordova.getActivity().getApplicationContext()); - - int code; - if (sdk instanceof BamSDK) - code = PERMISSION_REQUEST_CODE_BAM; - else if (sdk instanceof NetverifySDK) - code = PERMISSION_REQUEST_CODE_NETVERIFY; - else if (sdk instanceof DocumentVerificationSDK) - code = PERMISSION_REQUEST_CODE_DOCUMENT_VERIFICATION; - else { - showErrorMessage("Invalid SDK instance"); - return; - } - - cordova.requestPermissions(this, code, mp); - } else { - this.startSdk(sdk); - } - } - - @Override - public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException { - boolean allGranted = true; - for (int grantResult : grantResults) { - if (grantResult != PackageManager.PERMISSION_GRANTED) { - allGranted = false; - break; - } - } - - if (allGranted) { - if (requestCode == JumioMobileSDK.PERMISSION_REQUEST_CODE_BAM) { - startSdk(this.bamSDK); - } else if (requestCode == JumioMobileSDK.PERMISSION_REQUEST_CODE_NETVERIFY) { - startSdk(this.netverifySDK); - } else if (requestCode == JumioMobileSDK.PERMISSION_REQUEST_CODE_DOCUMENT_VERIFICATION) { - startSdk(this.documentVerificationSDK); - } - } else { - showErrorMessage("You need to grant all required permissions to start the Jumio SDK."); - super.onRequestPermissionResult(requestCode, permissions, grantResults); - } - } - - // SDK Result - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent intent) { - // BAM Checkout Results - if (requestCode == BamSDK.REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - BamCardInformation cardInformation = intent.getParcelableExtra(BamSDK.EXTRA_CARD_INFORMATION); - - JSONObject result = new JSONObject(); - try { - result.put("cardType", cardInformation.getCardType()); - result.put("cardNumber", String.valueOf(cardInformation.getCardNumber())); - result.put("cardNumberGrouped", String.valueOf(cardInformation.getCardNumberGrouped())); - result.put("cardNumberMasked", String.valueOf(cardInformation.getCardNumberMasked())); - result.put("cardExpiryMonth", String.valueOf(cardInformation.getCardExpiryDateMonth())); - result.put("cardExpiryYear", String.valueOf(cardInformation.getCardExpiryDateYear())); - result.put("cardExpiryDate", String.valueOf(cardInformation.getCardExpiryDateYear())); - result.put("cardCVV", String.valueOf(cardInformation.getCardCvvCode())); - result.put("cardHolderName", String.valueOf(cardInformation.getCardHolderName())); - result.put("cardSortCode", String.valueOf(cardInformation.getCardSortCode())); - result.put("cardAccountNumber", String.valueOf(cardInformation.getCardAccountNumber())); - result.put("cardSortCodeValid", cardInformation.isCardSortCodeValid()); - result.put("cardAccountNumberValid", cardInformation.isCardAccountNumberValid()); - - callbackContext.success(result); - cardInformation.clear(); - } catch (JSONException e) { - showErrorMessage("Result could not be sent. Try again."); - } - } else if (resultCode == Activity.RESULT_CANCELED) { - int errorCode = intent.getIntExtra(BamSDK.EXTRA_ERROR_CODE, 0); - String errorMsg = intent.getStringExtra(BamSDK.EXTRA_ERROR_MESSAGE); - showErrorMessage("Cancelled with error code: " + errorCode + ": " + errorMsg); - } - // Netverify Results - } else if (requestCode == NetverifySDK.REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - NetverifyDocumentData documentData = intent.getParcelableExtra(NetverifySDK.EXTRA_SCAN_DATA); - JSONObject result = new JSONObject(); - try { - result.put("selectedCountry", documentData.getSelectedCountry()); - result.put("selectedDocumentType", documentData.getSelectedDocumentType()); - result.put("idNumber", documentData.getIdNumber()); - result.put("personalNumber", documentData.getPersonalNumber()); - result.put("issuingDate", documentData.getIssuingDate()); - result.put("expiryDate", documentData.getExpiryDate()); - result.put("issuingCountry", documentData.getIssuingCountry()); - result.put("lastName", documentData.getLastName()); - result.put("firstName", documentData.getFirstName()); - result.put("middleName", documentData.getMiddleName()); - result.put("dob", documentData.getDob()); - result.put("gender", documentData.getGender()); - result.put("originatingCountry", documentData.getOriginatingCountry()); - result.put("addressLine", documentData.getAddressLine()); - result.put("city", documentData.getCity()); - result.put("subdivision", documentData.getSubdivision()); - result.put("postCode", documentData.getPostCode()); - result.put("optionalData1", documentData.getOptionalData1()); - result.put("optionalData2", documentData.getOptionalData2()); - result.put("placeOfBirth", documentData.getPlaceOfBirth()); - result.put("extractionMethod", documentData.getExtractionMethod()); - - // MRZ data if available - if (documentData.getMrzData() != null) { - JSONObject mrzData = new JSONObject(); - mrzData.put("format", documentData.getMrzData().getFormat()); - mrzData.put("line1", documentData.getMrzData().getMrzLine1()); - mrzData.put("line2", documentData.getMrzData().getMrzLine2()); - mrzData.put("line3", documentData.getMrzData().getMrzLine3()); - mrzData.put("idNumberValid", documentData.getMrzData().idNumberValid()); - mrzData.put("dobValid", documentData.getMrzData().dobValid()); - mrzData.put("expiryDateValid", documentData.getMrzData().expiryDateValid()); - mrzData.put("personalNumberValid", documentData.getMrzData().personalNumberValid()); - mrzData.put("compositeValid", documentData.getMrzData().compositeValid()); - result.put("mrzData", mrzData); - } - - callbackContext.success(result); - } catch (JSONException e) { - showErrorMessage("Result could not be sent: " + e.getLocalizedMessage()); - } - } else if (resultCode == Activity.RESULT_CANCELED) { - int errorCode = intent.getIntExtra(NetverifySDK.EXTRA_ERROR_CODE, 0); - String errorMsg = intent.getStringExtra(NetverifySDK.EXTRA_ERROR_MESSAGE); - showErrorMessage("Cancelled with error code: " + errorCode + ": " + errorMsg); - } - } else if (requestCode == DocumentVerificationSDK.REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - callbackContext.success("Document-Verification finished successfully."); - } else if (resultCode == Activity.RESULT_CANCELED) { - int errorCode = intent.getIntExtra(DocumentVerificationSDK.EXTRA_ERROR_CODE, 0); - String errorMsg = intent.getStringExtra(DocumentVerificationSDK.EXTRA_ERROR_MESSAGE); - showErrorMessage("Cancelled with error code: " + errorCode + ": " + errorMsg); - } - } - } - - // Helper methods - - private void startSdk(MobileSDK sdk) { - try { - sdk.start(); - } catch (MissingPermissionException e) { - Toast.makeText(cordova.getActivity(), e.getMessage(), Toast.LENGTH_LONG).show(); - } - } - - private void showErrorMessage(String msg) { - Log.e(TAG, msg); - callbackContext.error(msg); - } + + private static String TAG = "JumioMobileSDK"; + private static final int PERMISSION_REQUEST_CODE_BAM = 300; + private static final int PERMISSION_REQUEST_CODE_NETVERIFY = 301; + private static final int PERMISSION_REQUEST_CODE_DOCUMENT_VERIFICATION = 303; + + private static final String ACTION_BAM_INIT = "initBAM"; + private static final String ACTION_BAM_START = "startBAM"; + private static final String ACTION_NV_INIT = "initNetverify"; + private static final String ACTION_NV_START = "startNetverify"; + private static final String ACTION_DV_INIT = "initDocumentVerification"; + private static final String ACTION_DV_START = "startDocumentVerification"; + + private BamSDK bamSDK; + private NetverifySDK netverifySDK; + private DocumentVerificationSDK documentVerificationSDK; + private CallbackContext callbackContext; + private String errorMsg; + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + PluginResult result = null; + this.callbackContext = callbackContext; + + if (action.equals(ACTION_BAM_INIT)) { + initBAM(args); + result = new PluginResult(Status.NO_RESULT); + result.setKeepCallback(false); + return true; + } else if (action.equals(ACTION_BAM_START)) { + startBAM(args); + result = new PluginResult(Status.NO_RESULT); + result.setKeepCallback(true); + return true; + } else if (action.equals(ACTION_NV_INIT)) { + initNetverify(args); + result = new PluginResult(Status.NO_RESULT); + result.setKeepCallback(false); + return true; + } else if (action.equals(ACTION_NV_START)) { + startNetverify(args); + result = new PluginResult(Status.NO_RESULT); + result.setKeepCallback(true); + return true; + } else if (action.equals(ACTION_DV_INIT)) { + initDocumentVerification(args); + result = new PluginResult(Status.NO_RESULT); + result.setKeepCallback(false); + return true; + } else if (action.equals(ACTION_DV_START)) { + startDocumentVerification(args); + result = new PluginResult(Status.NO_RESULT); + result.setKeepCallback(true); + return true; + } else { + result = new PluginResult(Status.INVALID_ACTION); + callbackContext.error("Invalid Action"); + return false; + } + } + + // BAM Checkout + + private void initBAM(JSONArray data) { + if (BamSDK.isRooted(cordova.getActivity().getApplicationContext())) { + showErrorMessage("The BAM SDK can't run on a rooted device."); + return; + } + + if (!BamSDK.isSupportedPlatform(cordova.getActivity())) { + showErrorMessage("This platform is not supported."); + return; + } + + try { + JSONObject options = data.getJSONObject(3); + if (options.has("offlineToken")) { + String offlineToken = options.getString("offlineToken"); + bamSDK = BamSDK.create(cordova.getActivity(), offlineToken); + } else { + if (data.isNull(0) || data.isNull(1) || data.isNull(2)) { + showErrorMessage("Missing required parameters apiToken, apiSecret or dataCenter."); + return; + } + + String apiToken = data.getString(0); + String apiSecret = data.getString(1); + JumioDataCenter dataCenter = (data.getString(2).toLowerCase().equalsIgnoreCase("us")) ? JumioDataCenter.US : JumioDataCenter.EU; + + bamSDK = BamSDK.create(cordova.getActivity(), apiToken, apiSecret, dataCenter); + } + + // Configuration options + if (!data.isNull(3)) { + options = data.getJSONObject(3); + Iterator keys = options.keys(); + while (keys.hasNext()) { + String key = keys.next(); + + if (key.equalsIgnoreCase("cardHolderNameRequired")) { + bamSDK.setCardHolderNameRequired(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("sortCodeAndAccountNumberRequired")) { + bamSDK.setSortCodeAndAccountNumberRequired(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("expiryRequired")) { + bamSDK.setExpiryRequired(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("cvvRequired")) { + bamSDK.setCvvRequired(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("expiryEditable")) { + bamSDK.setExpiryEditable(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("cardHolderNameEditable")) { + bamSDK.setCardHolderNameEditable(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("merchantReportingCriteria")) { + bamSDK.setMerchantReportingCriteria(options.getString(key)); + } else if (key.equalsIgnoreCase("vibrationEffectEnabled")) { + bamSDK.setVibrationEffectEnabled(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("enableFlashOnScanStart")) { + bamSDK.setEnableFlashOnScanStart(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("cardNumberMaskingEnabled")) { + bamSDK.setCardNumberMaskingEnabled(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("cameraPosition")) { + JumioCameraPosition cameraPosition = (options.getString(key).toLowerCase().equals("front")) ? JumioCameraPosition.FRONT : JumioCameraPosition.BACK; + bamSDK.setCameraPosition(cameraPosition); + } else if (key.equalsIgnoreCase("cardTypes")) { + JSONArray jsonTypes = options.getJSONArray(key); + ArrayList types = new ArrayList(); + if (jsonTypes != null) { + int len = jsonTypes.length(); + for (int i = 0; i < len; i++) { + types.add(jsonTypes.get(i).toString()); + } + } + + ArrayList creditCardTypes = new ArrayList(); + for (String type : types) { + if (type.toLowerCase().equals("visa")) { + creditCardTypes.add(CreditCardType.VISA); + } else if (type.toLowerCase().equals("master_card")) { + creditCardTypes.add(CreditCardType.MASTER_CARD); + } else if (type.toLowerCase().equals("american_express")) { + creditCardTypes.add(CreditCardType.AMERICAN_EXPRESS); + } else if (type.toLowerCase().equals("china_unionpay")) { + creditCardTypes.add(CreditCardType.CHINA_UNIONPAY); + } else if (type.toLowerCase().equals("diners_club")) { + creditCardTypes.add(CreditCardType.DINERS_CLUB); + } else if (type.toLowerCase().equals("discover")) { + creditCardTypes.add(CreditCardType.DISCOVER); + } else if (type.toLowerCase().equals("jcb")) { + creditCardTypes.add(CreditCardType.JCB); + } + } + + bamSDK.setSupportedCreditCardTypes(creditCardTypes); + } + } + } + } catch (JSONException e) { + showErrorMessage("Invalid parameters: " + e.getLocalizedMessage()); + } catch (PlatformNotSupportedException e) { + showErrorMessage("Error initializing the BAM SDK: " + e.getLocalizedMessage()); + } catch (SDKExpiredException e) { + showErrorMessage("Error initializing the BAM SDK: " + e.getLocalizedMessage()); + } + } + + private void startBAM(JSONArray data) { + if (bamSDK == null) { + showErrorMessage("The BAM SDK is not initialized yet. Call initBAM() first."); + return; + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + try { + checkPermissionsAndStart(bamSDK); + } catch (Exception e) { + showErrorMessage("Error starting the BAM SDK: " + e.getLocalizedMessage()); + } + } + }; + + this.cordova.setActivityResultCallback(this); + this.cordova.getActivity().runOnUiThread(runnable); + } + + // Netverify + + private void initNetverify(JSONArray data) { + if (!NetverifySDK.isSupportedPlatform(cordova.getActivity())) { + showErrorMessage("This platform is not supported."); + return; + } + + try { + if (data.isNull(0) || data.isNull(1) || data.isNull(2)) { + showErrorMessage("Missing required parameters apiToken, apiSecret or dataCenter."); + return; + } + + String apiToken = data.getString(0); + String apiSecret = data.getString(1); + JumioDataCenter dataCenter = (data.getString(2).toLowerCase().equalsIgnoreCase("us")) ? JumioDataCenter.US : JumioDataCenter.EU; + + netverifySDK = NetverifySDK.create(cordova.getActivity(), apiToken, apiSecret, dataCenter); + + // Configuration options + if (!data.isNull(3)) { + JSONObject options = data.getJSONObject(3); + Iterator keys = options.keys(); + while (keys.hasNext()) { + String key = keys.next(); + + if (key.equalsIgnoreCase("requireVerification")) { + netverifySDK.setRequireVerification(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("callbackUrl")) { + netverifySDK.setCallbackUrl(options.getString(key)); + } else if (key.equalsIgnoreCase("requireFaceMatch")) { + netverifySDK.setRequireFaceMatch(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("preselectedCountry")) { + netverifySDK.setPreselectedCountry(options.getString(key)); + } else if (key.equalsIgnoreCase("merchantScanReference")) { + netverifySDK.setMerchantScanReference(options.getString(key)); + } else if (key.equalsIgnoreCase("merchantReportingCriteria")) { + netverifySDK.setMerchantReportingCriteria(options.getString(key)); + } else if (key.equalsIgnoreCase("customerID")) { + netverifySDK.setCustomerId(options.getString(key)); + } else if (key.equalsIgnoreCase("additionalInformation")) { + netverifySDK.setAdditionalInformation(options.getString(key)); + } else if (key.equalsIgnoreCase("enableEpassport")) { + netverifySDK.setEnableEMRTD(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("sendDebugInfoToJumio")) { + netverifySDK.sendDebugInfoToJumio(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("dataExtractionOnMobileOnly")) { + netverifySDK.setDataExtractionOnMobileOnly(options.getBoolean(key)); + } else if (key.equalsIgnoreCase("cameraPosition")) { + JumioCameraPosition cameraPosition = (options.getString(key).toLowerCase().equals("front")) ? JumioCameraPosition.FRONT : JumioCameraPosition.BACK; + netverifySDK.setCameraPosition(cameraPosition); + } else if (key.equalsIgnoreCase("preselectedDocumentVariant")) { + NVDocumentVariant variant = (options.getString(key).toLowerCase().equals("paper")) ? NVDocumentVariant.PAPER : NVDocumentVariant.PLASTIC; + netverifySDK.setPreselectedDocumentVariant(variant); + } else if (key.equalsIgnoreCase("documentTypes")) { + JSONArray jsonTypes = options.getJSONArray(key); + ArrayList types = new ArrayList(); + if (jsonTypes != null) { + int len = jsonTypes.length(); + for (int i = 0; i < len; i++) { + types.add(jsonTypes.get(i).toString()); + } + } + + ArrayList documentTypes = new ArrayList(); + for (String type : types) { + if (type.toLowerCase().equals("passport")) { + documentTypes.add(NVDocumentType.PASSPORT); + } else if (type.toLowerCase().equals("driver_license")) { + documentTypes.add(NVDocumentType.DRIVER_LICENSE); + } else if (type.toLowerCase().equals("identity_card")) { + documentTypes.add(NVDocumentType.IDENTITY_CARD); + } else if (type.toLowerCase().equals("visa")) { + documentTypes.add(NVDocumentType.VISA); + } + } + + netverifySDK.setPreselectedDocumentTypes(documentTypes); + } + } + } + } catch (JSONException e) { + showErrorMessage("Invalid parameters: " + e.getLocalizedMessage()); + } catch (PlatformNotSupportedException e) { + showErrorMessage("Error initializing the Netverify SDK: " + e.getLocalizedMessage()); + } + } + + private void startNetverify(JSONArray data) { + if (netverifySDK == null) { + showErrorMessage("The Netverify SDK is not initialized yet. Call initNetverify() first."); + return; + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + try { + checkPermissionsAndStart(netverifySDK); + } catch (Exception e) { + showErrorMessage("Error starting the Netverify SDK: " + e.getLocalizedMessage()); + } + } + }; + + this.cordova.setActivityResultCallback(this); + this.cordova.getActivity().runOnUiThread(runnable); + } + + // Document Verification + + private void initDocumentVerification(JSONArray data) { + if (!DocumentVerificationSDK.isSupportedPlatform(cordova.getActivity())) { + showErrorMessage("This platform is not supported."); + return; + } + + try { + if (data.isNull(0) || data.isNull(1) || data.isNull(2)) { + showErrorMessage("Missing required parameters apiToken, apiSecret or dataCenter."); + return; + } + + String apiToken = data.getString(0); + String apiSecret = data.getString(1); + JumioDataCenter dataCenter = (data.getString(2).toLowerCase().equalsIgnoreCase("us")) ? JumioDataCenter.US : JumioDataCenter.EU; + + documentVerificationSDK = DocumentVerificationSDK.create(cordova.getActivity(), apiToken, apiSecret, dataCenter); + + // Configuration options + if (!data.isNull(3)) { + JSONObject options = data.getJSONObject(3); + Iterator keys = options.keys(); + while (keys.hasNext()) { + String key = keys.next(); + + if (key.equalsIgnoreCase("type")) { + documentVerificationSDK.setType(options.getString(key)); + } else if (key.equalsIgnoreCase("customDocumentCode")) { + documentVerificationSDK.setCustomDocumentCode(options.getString(key)); + } else if (key.equalsIgnoreCase("country")) { + documentVerificationSDK.setCountry(options.getString(key)); + } else if (key.equalsIgnoreCase("merchantReportingCriteria")) { + documentVerificationSDK.setMerchantReportingCriteria(options.getString(key)); + } else if (key.equalsIgnoreCase("callbackUrl")) { + documentVerificationSDK.setCallbackUrl(options.getString(key)); + } else if (key.equalsIgnoreCase("additionalInformation")) { + documentVerificationSDK.setAdditionalInformation(options.getString(key)); + } else if (key.equalsIgnoreCase("merchantScanReference")) { + documentVerificationSDK.setMerchantScanReference(options.getString(key)); + } else if (key.equalsIgnoreCase("customerId")) { + documentVerificationSDK.setCustomerId(options.getString(key)); + } else if (key.equalsIgnoreCase("documentName")) { + documentVerificationSDK.setDocumentName(options.getString(key)); + } else if (key.equalsIgnoreCase("cameraPosition")) { + JumioCameraPosition cameraPosition = (options.getString(key).toLowerCase().equals("front")) ? JumioCameraPosition.FRONT : JumioCameraPosition.BACK; + documentVerificationSDK.setCameraPosition(cameraPosition); + } + } + } + + // Configuration options + if (!data.isNull(3)) { + JSONObject options = data.getJSONObject(3); + Iterator keys = options.keys(); + while (keys.hasNext()) { + String key = keys.next(); + + // ... + } + } + } catch (JSONException e) { + showErrorMessage("Invalid parameters: " + e.getLocalizedMessage()); + } catch (PlatformNotSupportedException e) { + showErrorMessage("Error initializing the Document Verification SDK: " + e.getLocalizedMessage()); + } + } + + private void startDocumentVerification(JSONArray data) { + if (documentVerificationSDK == null) { + showErrorMessage("The Document Verification SDK is not initialized yet. Call initDocumentVerification() first."); + return; + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + try { + checkPermissionsAndStart(documentVerificationSDK); + } catch (Exception e) { + showErrorMessage("Error starting the Document Verification SDK: " + e.getLocalizedMessage()); + } + } + }; + + this.cordova.setActivityResultCallback(this); + this.cordova.getActivity().runOnUiThread(runnable); + } + + + // Permissions + + private void checkPermissionsAndStart(MobileSDK sdk) { + if (!MobileSDK.hasAllRequiredPermissions(cordova.getActivity().getApplicationContext())) { + //Acquire missing permissions. + String[] mp = MobileSDK.getMissingPermissions(cordova.getActivity().getApplicationContext()); + + int code; + if (sdk instanceof BamSDK) + code = PERMISSION_REQUEST_CODE_BAM; + else if (sdk instanceof NetverifySDK) + code = PERMISSION_REQUEST_CODE_NETVERIFY; + else if (sdk instanceof DocumentVerificationSDK) + code = PERMISSION_REQUEST_CODE_DOCUMENT_VERIFICATION; + else { + showErrorMessage("Invalid SDK instance"); + return; + } + + cordova.requestPermissions(this, code, mp); + } else { + this.startSdk(sdk); + } + } + + @Override + public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException { + boolean allGranted = true; + for (int grantResult : grantResults) { + if (grantResult != PackageManager.PERMISSION_GRANTED) { + allGranted = false; + break; + } + } + + if (allGranted) { + if (requestCode == JumioMobileSDK.PERMISSION_REQUEST_CODE_BAM) { + startSdk(this.bamSDK); + } else if (requestCode == JumioMobileSDK.PERMISSION_REQUEST_CODE_NETVERIFY) { + startSdk(this.netverifySDK); + } else if (requestCode == JumioMobileSDK.PERMISSION_REQUEST_CODE_DOCUMENT_VERIFICATION) { + startSdk(this.documentVerificationSDK); + } + } else { + showErrorMessage("You need to grant all required permissions to start the Jumio SDK."); + super.onRequestPermissionResult(requestCode, permissions, grantResults); + } + } + + // SDK Result + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + // BAM Checkout Results + if (requestCode == BamSDK.REQUEST_CODE) { + if (intent == null) { + return; + } + if (resultCode == Activity.RESULT_OK) { + BamCardInformation cardInformation = intent.getParcelableExtra(BamSDK.EXTRA_CARD_INFORMATION); + + JSONObject result = new JSONObject(); + try { + result.put("cardType", cardInformation.getCardType()); + result.put("cardNumber", String.valueOf(cardInformation.getCardNumber())); + result.put("cardNumberGrouped", String.valueOf(cardInformation.getCardNumberGrouped())); + result.put("cardNumberMasked", String.valueOf(cardInformation.getCardNumberMasked())); + result.put("cardExpiryMonth", String.valueOf(cardInformation.getCardExpiryDateMonth())); + result.put("cardExpiryYear", String.valueOf(cardInformation.getCardExpiryDateYear())); + result.put("cardExpiryDate", String.valueOf(cardInformation.getCardExpiryDateYear())); + result.put("cardCVV", String.valueOf(cardInformation.getCardCvvCode())); + result.put("cardHolderName", String.valueOf(cardInformation.getCardHolderName())); + result.put("cardSortCode", String.valueOf(cardInformation.getCardSortCode())); + result.put("cardAccountNumber", String.valueOf(cardInformation.getCardAccountNumber())); + result.put("cardSortCodeValid", cardInformation.isCardSortCodeValid()); + result.put("cardAccountNumberValid", cardInformation.isCardAccountNumberValid()); + + ArrayList scanReferenceList = intent.getStringArrayListExtra(BamSDK.EXTRA_SCAN_ATTEMPTS); + if (scanReferenceList != null && scanReferenceList.size() > 0) { + for (int i = scanReferenceList.size() - 1; i >= 0; i--) { + result.put(String.format(Locale.getDefault(), "Scan reference %d", i), scanReferenceList.get(i)); + } + } else { + result.put("Scan reference 0", "N/A"); + } + + callbackContext.success(result); + cardInformation.clear(); + } catch (JSONException e) { + showErrorMessage("Result could not be sent. Try again."); + } + } else if (resultCode == Activity.RESULT_CANCELED) { + int errorCode = intent.getIntExtra(BamSDK.EXTRA_ERROR_CODE, 0); + String errorMsg = intent.getStringExtra(BamSDK.EXTRA_ERROR_MESSAGE); + sendErrorObject(errorCode, errorMsg, ""); + } + // Netverify Results + } else if (requestCode == NetverifySDK.REQUEST_CODE) { + if (intent == null) { + return; + } + String scanReference = intent.getStringExtra(NetverifySDK.EXTRA_SCAN_REFERENCE) != null ? intent.getStringExtra(NetverifySDK.EXTRA_SCAN_REFERENCE) : ""; + + if (resultCode == Activity.RESULT_OK) { + NetverifyDocumentData documentData = intent.getParcelableExtra(NetverifySDK.EXTRA_SCAN_DATA); + JSONObject result = new JSONObject(); + try { + result.put("scanReference", scanReference); + result.put("selectedCountry", documentData.getSelectedCountry()); + result.put("selectedDocumentType", documentData.getSelectedDocumentType()); + result.put("idNumber", documentData.getIdNumber()); + result.put("personalNumber", documentData.getPersonalNumber()); + result.put("issuingDate", documentData.getIssuingDate()); + result.put("expiryDate", documentData.getExpiryDate()); + result.put("issuingCountry", documentData.getIssuingCountry()); + result.put("lastName", documentData.getLastName()); + result.put("firstName", documentData.getFirstName()); + result.put("middleName", documentData.getMiddleName()); + result.put("dob", documentData.getDob()); + result.put("gender", documentData.getGender()); + result.put("originatingCountry", documentData.getOriginatingCountry()); + result.put("addressLine", documentData.getAddressLine()); + result.put("city", documentData.getCity()); + result.put("subdivision", documentData.getSubdivision()); + result.put("postCode", documentData.getPostCode()); + result.put("optionalData1", documentData.getOptionalData1()); + result.put("optionalData2", documentData.getOptionalData2()); + result.put("placeOfBirth", documentData.getPlaceOfBirth()); + result.put("extractionMethod", documentData.getExtractionMethod()); + + // MRZ data if available + if (documentData.getMrzData() != null) { + JSONObject mrzData = new JSONObject(); + mrzData.put("format", documentData.getMrzData().getFormat()); + mrzData.put("line1", documentData.getMrzData().getMrzLine1()); + mrzData.put("line2", documentData.getMrzData().getMrzLine2()); + mrzData.put("line3", documentData.getMrzData().getMrzLine3()); + mrzData.put("idNumberValid", documentData.getMrzData().idNumberValid()); + mrzData.put("dobValid", documentData.getMrzData().dobValid()); + mrzData.put("expiryDateValid", documentData.getMrzData().expiryDateValid()); + mrzData.put("personalNumberValid", documentData.getMrzData().personalNumberValid()); + mrzData.put("compositeValid", documentData.getMrzData().compositeValid()); + result.put("mrzData", mrzData); + } + + callbackContext.success(result); + } catch (JSONException e) { + showErrorMessage("Result could not be sent: " + e.getLocalizedMessage()); + } + } else if (resultCode == Activity.RESULT_CANCELED) { + int errorCode = intent.getIntExtra(NetverifySDK.EXTRA_ERROR_CODE, 0); + String errorMsg = intent.getStringExtra(NetverifySDK.EXTRA_ERROR_MESSAGE); + sendErrorObject(errorCode, errorMsg, scanReference); + } + } else if (requestCode == DocumentVerificationSDK.REQUEST_CODE) { + String scanReference = intent.getStringExtra(NetverifySDK.EXTRA_SCAN_REFERENCE) != null ? intent.getStringExtra(NetverifySDK.EXTRA_SCAN_REFERENCE) : ""; + + if (resultCode == Activity.RESULT_OK) { + try { + JSONObject result = new JSONObject(); + result.put("successMessage", "Document-Verification finished successfully."); + result.put("scanReference", scanReference); + callbackContext.success(result); + } catch (JSONException e) { + showErrorMessage("Result could not be sent: " + e.getLocalizedMessage()); + } + } else if (resultCode == Activity.RESULT_CANCELED) { + int errorCode = intent.getIntExtra(DocumentVerificationSDK.EXTRA_ERROR_CODE, 0); + String errorMsg = intent.getStringExtra(DocumentVerificationSDK.EXTRA_ERROR_MESSAGE); + Log.e(TAG, errorMsg); + sendErrorObject(errorCode, errorMsg, scanReference); + } + } + } + + // Helper methods + + private void startSdk(MobileSDK sdk) { + try { + sdk.start(); + } catch (MissingPermissionException e) { + Toast.makeText(cordova.getActivity(), e.getMessage(), Toast.LENGTH_LONG).show(); + } + } + + private void showErrorMessage(String msg) { + Log.e(TAG, msg); + try{ + JSONObject errorResult = new JSONObject(); + errorResult.put("errorMessage", msg != null ? msg : ""); + callbackContext.error(errorResult); + }catch (JSONException e) { + Log.e(TAG, e.getLocalizedMessage()); + } + } + + private void sendErrorObject(int errorCode, String errorMsg, String scanReference) { + try { + JSONObject errorResult = new JSONObject(); + errorResult.put("errorCode", String.valueOf(errorCode)); + errorResult.put("errorMessage", errorMsg != null ? errorMsg : ""); + errorResult.put("scanReference", scanReference != null ? scanReference : ""); + callbackContext.error(errorResult); + } catch (JSONException e) { + showErrorMessage("Result could not be sent: " + e.getLocalizedMessage()); + } + } } diff --git a/src/ios/JumioMobileSDK.m b/src/ios/JumioMobileSDK.m index 6302168..8be49bf 100644 --- a/src/ios/JumioMobileSDK.m +++ b/src/ios/JumioMobileSDK.m @@ -11,9 +11,11 @@ @implementation JumioMobileSDK - (void)initBAM:(CDVInvokedUrlCommand*)command { + self.callbackId = command.callbackId; + NSUInteger argc = [command.arguments count]; if (argc < 3) { - [self showSDKError: @"Missing required parameters apiToken, apiSecret or dataCenter."]; + [self sendErrorMessage: @"Missing required parameters apiToken, apiSecret or dataCenter."]; return; } @@ -131,18 +133,24 @@ - (void)initBAM:(CDVInvokedUrlCommand*)command } } } - - self.bamViewController = [[BAMCheckoutViewController alloc] initWithConfiguration: self.bamConfiguration]; + + @try { + self.bamViewController = [[BAMCheckoutViewController alloc] initWithConfiguration: self.bamConfiguration]; + } @catch (NSException *exception) { + NSString *msg = [NSString stringWithFormat: @"Cancelled with exception %@: %@", exception.name, exception.reason]; + [self sendErrorMessage: msg]; + } } - (void)startBAM:(CDVInvokedUrlCommand*)command { + self.callbackId = command.callbackId; + if (self.bamViewController == nil) { - [self showSDKError: @"The BAM SDK is not initialized yet. Call initBAM() first."]; + [self sendErrorMessage: @"The BAM SDK is not initialized yet. Call initBAM() first."]; return; } - self.callbackId = command.callbackId; [self.viewController presentViewController: self.bamViewController animated: YES completion: nil]; } @@ -150,9 +158,11 @@ - (void)startBAM:(CDVInvokedUrlCommand*)command - (void)initNetverify:(CDVInvokedUrlCommand*)command { + self.callbackId = command.callbackId; + NSUInteger argc = [command.arguments count]; if (argc < 3) { - [self showSDKError: @"Missing required parameters apiToken, apiSecret or dataCenter."]; + [self sendErrorMessage: @"Missing required parameters apiToken, apiSecret or dataCenter."]; return; } @@ -286,18 +296,24 @@ - (void)initNetverify:(CDVInvokedUrlCommand*)command } } } - - self.netverifyViewController = [[NetverifyViewController alloc] initWithConfiguration: self.netverifyConfiguration]; + + @try { + self.netverifyViewController = [[NetverifyViewController alloc] initWithConfiguration: self.netverifyConfiguration]; + } @catch (NSException *exception) { + NSString *msg = [NSString stringWithFormat: @"Cancelled with exception %@: %@", exception.name, exception.reason]; + [self sendErrorMessage: msg]; + } } - (void)startNetverify:(CDVInvokedUrlCommand*)command { + self.callbackId = command.callbackId; + if (self.netverifyViewController == nil) { - [self showSDKError: @"The Netverify SDK is not initialized yet. Call initNetverify() first."]; + [self sendErrorMessage: @"The Netverify SDK is not initialized yet. Call initNetverify() first."]; return; } - self.callbackId = command.callbackId; [self.viewController presentViewController: self.netverifyViewController animated: YES completion: nil]; } @@ -305,9 +321,11 @@ - (void)startNetverify:(CDVInvokedUrlCommand*)command - (void)initDocumentVerification:(CDVInvokedUrlCommand*)command { + self.callbackId = command.callbackId; + NSUInteger argc = [command.arguments count]; if (argc < 3) { - [self showSDKError: @"Missing required parameters apiToken, apiSecret or dataCenter."]; + [self sendErrorMessage: @"Missing required parameters apiToken, apiSecret or dataCenter."]; return; } @@ -390,17 +408,23 @@ - (void)initDocumentVerification:(CDVInvokedUrlCommand*)command } } - self.documentVerificationViewController = [[DocumentVerificationViewController alloc] initWithConfiguration: self.documentVerifcationConfiguration]; + @try { + self.documentVerificationViewController = [[DocumentVerificationViewController alloc] initWithConfiguration: self.documentVerifcationConfiguration]; + } @catch (NSException *exception) { + NSString *msg = [NSString stringWithFormat: @"Cancelled with exception %@: %@", exception.name, exception.reason]; + [self sendErrorMessage: msg]; + } } - (void)startDocumentVerification:(CDVInvokedUrlCommand*)command { + self.callbackId = command.callbackId; + if (self.documentVerificationViewController == nil) { - [self showSDKError: @"The Document-Verification SDK is not initialized yet. Call initDocumentVerification() first."]; + [self sendErrorMessage: @"The Document-Verification SDK is not initialized yet. Call initDocumentVerification() first."]; return; } - self.callbackId = command.callbackId; [self.viewController presentViewController: self.documentVerificationViewController animated: YES completion: nil]; } @@ -440,6 +464,8 @@ - (void) bamCheckoutViewController:(BAMCheckoutViewController *)controller didFi [result setValue: cardInformation.cardAccountNumber forKey: @"cardAccountNumber"]; [result setValue: [NSNumber numberWithBool: cardInformation.cardSortCodeValid] forKey: @"cardSortCodeValid"]; [result setValue: [NSNumber numberWithBool: cardInformation.cardAccountNumberValid] forKey: @"cardAccountNumberValid"]; + + [result setValue: scanReference forKey: @"scanReference"]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: result]; [self.commandDelegate sendPluginResult: pluginResult callbackId: self.callbackId]; @@ -447,8 +473,8 @@ - (void) bamCheckoutViewController:(BAMCheckoutViewController *)controller didFi } - (void) bamCheckoutViewController:(BAMCheckoutViewController *)controller didCancelWithError:(NSError *)error scanReference:(NSString *)scanReference { - NSString *msg = [NSString stringWithFormat: @"Cancelled with error code %ld: %@", (long)error.code, error.localizedDescription]; - [self showSDKError: msg]; + [self sendError: error scanReference: scanReference]; + [self.viewController dismissViewControllerAnimated: YES completion: nil]; } #pragma mark - Netverify Delegates @@ -531,6 +557,7 @@ - (void)netverifyViewController:(NetverifyViewController *)netverifyViewControll [result setValue: mrzData forKey: @"mrzData"]; } + [result setValue: scanReference forKey: @"scanReference"]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: result]; [self.commandDelegate sendPluginResult: pluginResult callbackId: self.callbackId]; @@ -539,37 +566,49 @@ - (void)netverifyViewController:(NetverifyViewController *)netverifyViewControll - (void)netverifyViewController:(NetverifyViewController *)netverifyViewController didFinishInitializingWithError:(NSError *)error { if (error != nil) { - NSString *msg = [NSString stringWithFormat: @"Cancelled with error code %ld: %@", (long)error.code, error.localizedDescription]; - [self showSDKError: msg]; + [self sendError: error scanReference: nil]; } } - (void)netverifyViewController:(NetverifyViewController *)netverifyViewController didCancelWithError:(NSError *)error scanReference:(NSString *)scanReference { - NSString *msg = [NSString stringWithFormat: @"Cancelled with error code %ld: %@", (long)error.code, error.localizedDescription]; - [self showSDKError: msg]; + [self sendError: error scanReference: scanReference]; + [self.viewController dismissViewControllerAnimated: YES completion: nil]; } - + #pragma mark - Document Verification Delegates - (void) documentVerificationViewController:(DocumentVerificationViewController *)documentVerificationViewController didFinishWithScanReference:(NSString *)scanReference { - NSString *msg = @"Document-Verification finished successfully."; - CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: msg]; + NSDictionary *result = [NSDictionary dictionaryWithObject: scanReference forKey: @"scanReference"]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsDictionary: result]; [self.commandDelegate sendPluginResult: pluginResult callbackId: self.callbackId]; [self.viewController dismissViewControllerAnimated: YES completion: nil]; } - (void) documentVerificationViewController:(DocumentVerificationViewController *)documentVerificationViewController didFinishWithError:(NSError *)error { - NSString *msg = [NSString stringWithFormat: @"Cancelled with error code %ld: %@", (long)error.code, error.localizedDescription]; - [self showSDKError: msg]; + [self sendError: error scanReference: nil]; + [self.viewController dismissViewControllerAnimated: YES completion: nil]; } #pragma mark - Helper Methods + + +- (void) sendErrorMessage: (NSString *)errorMessage { + NSDictionary* result = [NSDictionary dictionaryWithObject: errorMessage forKey: @"errorMessage"]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsDictionary: result]; + [self.commandDelegate sendPluginResult: pluginResult callbackId: self.callbackId]; + [self.viewController dismissViewControllerAnimated: YES completion: nil]; +} + +- (void)sendError:(NSError *)error scanReference:(NSString *)scanReference { + NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; + [result setValue: [NSNumber numberWithInteger: error.code] forKey: @"errorCode"]; + [result setValue: error.localizedDescription forKey: @"errorMessage"]; + if (scanReference) { + [result setValue: scanReference forKey: @"scanReference"]; + } -- (void)showSDKError:(NSString *)msg { - NSLog(@"%@", msg); - - CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: msg]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsDictionary: result]; [self.commandDelegate sendPluginResult: pluginResult callbackId: self.callbackId]; [self.viewController dismissViewControllerAnimated: YES completion: nil]; }