# Language


# Overview

1. High Accuracy OCR (Optical Character Recognition) includes English, Latin, Chinese, Korean and Japanese Languages.&#x20;
2. Face Biometrics is used for Matching Both the Source and the Target Image. It Matches the User's Selfie Image with the Image on the Document.&#x20;
3. User Authentication and Liveness Check is used for Customer Verification and Authentication. It Protects You from Identity Theft & Spoofing Attacks Using Active and Passive Selfie Technology for Liveness Check.

<br>

{% content-ref url="/pages/83pZJ041DdrlKb3dK2Ui" %}
[Android](/language/android)
{% endcontent-ref %}

{% content-ref url="/pages/YqaHBwzfwzMjpASo5Rvy" %}
[iOS](/language/ios)
{% endcontent-ref %}

{% content-ref url="/pages/dRICNaBRf6yg3bnw2TYS" %}
[Flutter](/language/flutter)
{% endcontent-ref %}

{% content-ref url="/pages/nOZ63NYZ6yXlxq2955uE" %}
[Cordova](/language/cordova)
{% endcontent-ref %}

{% content-ref url="/pages/g6Asl558KD0ITnNzRaU1" %}
[React-Native](/language/react-native)
{% endcontent-ref %}

{% content-ref url="/pages/OXAlRmDBo50HOshyDPnb" %}
[Xamarin](/language/xamarin)
{% endcontent-ref %}

{% content-ref url="/pages/4XNHhXPcqYDLohG7VXUx" %}
[Docker](/language/docker)
{% endcontent-ref %}

{% content-ref url="/pages/YcaYmEmnQjaZYrj7jfdn" %}
[Web API](/language/web-api)
{% endcontent-ref %}


# Android

Accura Scan’s robust android support. Click below for more details.


# Project Setup

{% embed url="<https://drive.google.com/file/d/1eZ_x5EhO5mPErszt2VnyH4Ostl01j1qr/view?usp=sharing>" %}

{% hint style="info" %}
The Android SDK has been VAPT (Vulnerability Assessment and Penetration Testing) tested .&#x20;

You can find the detailed report in the PDF attached below.
{% endhint %}

{% file src="/files/YG5O7Oj4X9IS0v29CpkU" %}

***

Add Accura SDK's to your App

### **Step 1:** Add the JitPack repository

1. In your **root-level (project-level)** Gradle file (`<project>/build.gradle`)<br>

   ```
   allprojects {
       repositories {
           ...
           maven {
               url 'https://jitpack.io'
               credentials { username authToken }
           }
       }
   }
   ```
2. Add the token to `gradle.properties`

   ```
   authToken=jp_ssguccab6c5ge2l4jitaj92ek2

   ```

### **Step 2: Add dependency**

In your **module (app-level)** Gradle file (usually `<project>/<app-module>/build.gradle`), add the dependencies for the Accura Products.

{% tabs %}
{% tab title="Accura OCR" %}

```
dependencies {
    ...
    implementation 'com.github.accurascan:AccuraOCR:6.2.1'
}
```

{% endtab %}

{% tab title="Accura Face Match" %}

```
dependencies {
    ...
    implementation 'com.github.accurascan:AccuraFaceMatch:3.2.7'
}
```

{% endtab %}

{% tab title="Accura Liveness" %}

```
dependencies {
    ...
    implementation 'com.github.accurascan:Liveness-Android:3.4.7'
}
```

{% endtab %}
{% endtabs %}

### **Step 3: Required Adanced setup as per requirement**

Add some more setup in your **module (app-level)** Gradle file (usually `<project>/<app-module>/build.gradle`), for the Accura Products.

1. Specify CPU architectures as per your Requirement.

   ```
   android {
       defaultConfig {
           ...
           ndk {
               // Specify CPU architecture.
               // 'armeabi-v7a' & 'arm64-v8a' are respectively 32 bit and 64 bit device architecture 
               // 'x86' & 'x86_64' are respectively 32 bit and 64 bit emulator architecture
               abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
           }
       }
   }
   ```
2. Add Packaging option for some `.so` files, for multiple Accura Products

   ```
   android {
       ...
       packagingOptions {
           pickFirst 'lib/arm64-v8a/libcrypto.so'
           pickFirst 'lib/arm64-v8a/libssl.so'

           pickFirst 'lib/armeabi-v7a/libcrypto.so'
           pickFirst 'lib/armeabi-v7a/libssl.so'

           pickFirst 'lib/x86/libcrypto.so'
           pickFirst 'lib/x86/libssl.so'

           pickFirst 'lib/x86_64/libcrypto.so'
           pickFirst 'lib/x86_64/libssl.so'
   	}
   	
   }
   ```

{% hint style="info" %} <mark style="color:blue;">**Note:**</mark> <mark style="color:blue;"></mark><mark style="color:blue;">Add Packaging options are required for multiple Accura Products used in same Project</mark>
{% endhint %}


# Accura OCR

High Accuracy OCR (Optical Character Recognition) Includes English, Latin, Chinese, Korean and Japanese Languages.

{% embed url="<https://drive.google.com/file/d/1v4utpEOGs3bIHpGe5L59VVTdGmE6Hmpv/view?usp=sharing>" %}

## Step 1: Before you begin

1. If you haven't done already then follow [Project Setup](/language/android/project-setup) steps.
2. Please download the Accura Scan license and then add it to your app.
3. To generate your Accura Scan license contact <sales@accurascan.com>
4. Move your **key.license** file into the **module (app-level)** **assets folder** (usually `<project>/<app-module>/src/main/assets`)

> <mark style="color:blue;">**Note:**</mark> Make sure license file name should be **key.license**

1. Permissions required
   1. Camera Permission `android.permission.CAMERA`
   2. Storage Permission required only for print out debug logs.

{% hint style="info" %} <mark style="color:blue;">**Note:**</mark> Enable logging for debugging purposes using the methods provided below. Please remember to disable logging before releasing the app. **(Storage permission is required for logging)**.\
AccuraLog.enableLogs(true);\
AccuraLog.refreshLogfile(activity);\
\
Log file will be stored in **InternalStorage/Downloads/AccuraLog.txt**
{% endhint %}

## Step 2: Initialize SDK when the app starts

1. Initialize SDK with Licensing<br>

   ```
   RecogEngine recogEngine = new RecogEngine();
   RecogEngine.SDKModel sdkModel = recogEngine.initEngine(your activity context);

   // Error Message if license is not valid.
   String licenseErrorMessage = sdkModel.message;

   if (sdkModel.i > 0) { // if license is valid

        if (sdkModel.isMRZEnable) // RecogType.MRZ

        if (sdkModel.isBankCardEnable)  // RecogType.BANKCARD
        
        if (sdkModel.isAllBarcodeEnable) // RecogType.BARCODE

       // sdkModel.isOCREnable is true then get card list which you are selected on creating license
       if (sdkModel.isOCREnable) List<ContryModel> modelList = recogEngine.getCardList(MainActivity.this);
       if (modelList != null) { // if country & card added in license
           ContryModel contryModel = modelList.get(selected country position);
           contryModel.getCountry_id(); // getting country id
           CardModel model = contryModel.getCards().get(0/*selected card position*/); // getting card
           model.getCard_id() // getting card id
           model.getCard_name()  // getting card name

           if (cardModel.getCard_type() == 1) {
               // RecogType.PDF417
           } else if (cardModel.getCard_type() == 2) {
               // RecogType.DL_PLATE
           } else {
               // RecogType.OCR
           }
       }
   }
   ```

   ```
   // Error Message if license is not valid.
   String licenseErrorMessage = sdkModel.message;
   ```
2. After initializing the SDK, proceed to initialize the filters below if the license is valid.

   (sdkModel.i > 0)<br>

   * Set Blur Percentage to allow blur on document<br>

     ```
     //0 for clean document and 100 for Blurry document
     recogEngine.setBlurPercentage(Context context, int /*blurPercentage*/50);
     ```

   * Set Face blur Percentage to allow blur on detected Face<br>

     ```
     // 0 for clean face and 100 for Blurry face
     recogEngine.setFaceBlurPercentage(Context context, int /*faceBlurPercentage*/50);
     ```

   * Set Glare Percentage to detect Glare on document<br>

     ```
     // Set min and max percentage for glare
     recogEngine.setGlarePercentage(Context context, int /*minPercentage*/6, int /*maxPercentage*/98);
     ```

   * Set Hologram detection to verify the hologram on the face<br>

     ```
     // true to check hologram on face
     recogEngine.SetHologramDetection(Context context, boolean /*isDetectHologram*/true);
     ```

   * Set light tolerance to detect light on document<br>

     ```
     // 0 for full dark document and 100 for full bright document
     recogEngine.setLowLightTolerance(Context context, int /*tolerance*/30);
     ```

   * Set motion threshold to detect motion on camera document<br>

     ```
       // 1 - allows 1% motion on document and
       // 100 - it can not detect motion and allow document to scan.
       recogEngine.setMotionThreshold(Context context, int /*motionThreshold*/18);
     ```

## Step 3 : Set CameraView

1. Your activity class should extend `com.accurascan.ocr.mrz.motiondetection.SensorsActivity`.<br>

2. Camera View support both orientations Portarait and Landscape<br>

   > <mark style="color:blue;">**Note:**</mark> Make sure your activity orientation should be finalise before Initialize camera because auto rotate is not support during scanning.

3. Initialize cameraView to your activity class.<br>

   ```
   // defined object of CameraView
   private CameraView cameraView;

   @Override
   public void onCreate(Bundle savedInstanceState) {
       if (isPortrait) {
           setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); // to set portarait mode
       } else {
           setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // to set landscape mode
       }
       super.onCreate(savedInstanceState);
       setTheme(R.style.AppThemeNoActionBar);
       setContentView(R.layout.your layout);

       // Recog type selection base on your license data
       // As like RecogType.OCR, RecogType.MRZ, RecogType.PDF417, RecogType.DL_PLATE, RecogType.BANKCARD
       RecogType recogType = RecogType.OCR;
       cardId = CardModel.getCard_id();
       cardName = CardModel.getCard_name();
       countryId = ContryModel.getCountry_id();

       // initialized camera
       initCamera();
   }

   private void initCamera() {
       //<editor-fold desc="To get status bar height">
       Rect rectangle = new Rect();
       Window window = getWindow();
       window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
       int statusBarTop = rectangle.top;
       int contentViewTop = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
       int statusBarHeight = contentViewTop - statusBarTop;
       //</editor-fold>

       RelativeLayout linearLayout = findViewById(R.id.ocr_root); // layout width and height is match_parent

       cameraView = new CameraView(this);
       if (recogType == RecogType.OCR || recogType == RecogType.DL_PLATE) {
           // must have to set data for RecogType.OCR and RecogType.DL_PLATE
           cameraView.setCountryId(countryId).setCardId(cardId)
           		.setMinFrameForValidate(3/*minFrame*/); // Set min frame for qatar ID card for Most validated data. minFrame supports only odd numbers like 3,5...
       } else if (recogType == RecogType.PDF417) {
           // must have to set data RecogType.PDF417
           cameraView.setCountryId(countryId);
       }
       if (recogType == RecogType.MRZ) {
           // Also set MRZ document type to scan specific MRZ document
           // 1. ALL MRZ document       - MRZDocumentType.NONE        
           // 2. Passport MRZ document  - MRZDocumentType.PASSPORT_MRZ
           // 3. ID card MRZ document   - MRZDocumentType.ID_CARD_MRZ 
           // 4. Visa MRZ document      - MRZDocumentType.VISA_MRZ    
           cameraView.setMRZDocumentType(mrzDocumentType);
           
           // Pass 'all' for accepting MRZs of all countries
           // or you can pass respective country codes of countries whose MRZ you want to accept. Eg:- 'IND', 'USA', 'TUN', etc.
           cameraView.setMRZCountryCodeList("all");
       }
       cameraView.setRecogType(recogType)
               .setView(linearLayout) // To add camera view
               .setCameraFacing(0) // // To set selfie(1) or rear(0) camera.
               .setOcrCallback(this)  // To get feedback and Success Call back
               .setStatusBarHeight(statusBarHeight)  // To remove Height from Camera View if status bar visible
               .setFrontSide() // or cameraView.setBackSide(); to scan card side front or back default it's scan front side first
   //                Option setup
   //                .setEnableMediaPlayer(false) // false to disable default sound and true to enable sound and default it is true
   //                .setCustomMediaPlayer(MediaPlayer.create(this, /*custom sound file*/)) // To add your custom sound and Must have to enable media player
               .init();  // initialized camera
   	// To set barcode formate.
   	cameraView.setBarcodeFormat(int barcodeFormat); // access all type of BarcodeFormate from BarcodeFormat.java class
   }


   ```

   \
   And recommended to override the following methods.

   ```
   /**
    * To handle camera on window focus update
    * @param hasFocus
    */
   @Override
   public void onWindowFocusChanged(boolean hasFocus) {
       if (cameraView != null) {
           cameraView.onWindowFocusUpdate(hasFocus);
       }
   }

   @Override
   protected void onResume() {
       super.onResume();
       cameraView.onResume();
   }

   @Override
   protected void onPause() {
       cameraView.onPause();
       super.onPause();
   }

   @Override
   protected void onDestroy() {
       cameraView.onDestroy();
       super.onDestroy();
   }
   ```

4. Implements **`com.accurascan.ocr.mrz.interfaces.OcrCallback`** to your Activity and Override following methods to receive data during scanning.<br>

   > **Note:** Below Override methods are invoked from background thread. So make sure to use in UI thread

   * When below override method is getting called, you can start scanning and set parameter of center scanning frame.

     <br>

     ```
     /**
      * To update your border frame according to width and height
      * it's different for different card
      * Call {@link CameraView#startOcrScan(boolean isReset)} To start Camera Preview
      * @param width    border layout width
      * @param height   border layout height
      */
     @Override
     public void onUpdateLayout(int width, int height) {
         if (cameraView != null) cameraView.startOcrScan(false);

         //<editor-fold desc="To set camera overlay Frame">
         ViewGroup.LayoutParams layoutParams = borderFrame.getLayoutParams();
         layoutParams.width = width;
         layoutParams.height = height;
         borderFrame.setLayoutParams(layoutParams);

         ViewGroup.LayoutParams lpRight = viewRight.getLayoutParams();
         lpRight.height = height;
         viewRight.setLayoutParams(lpRight);

         ViewGroup.LayoutParams lpLeft = viewLeft.getLayoutParams();
         lpLeft.height = height;
         viewLeft.setLayoutParams(lpLeft);
         //</editor-fold>
     }
     ```

   * You can receive information during scanning in the below override method<br>

     ```
     /**
      * @param titleCode to display scan card message on top of border Frame
      *
      * @param errorMessage To display process message.
      *                null if message is not available
      * @param isFlip  true to set your customize animation for scan back card alert after complete front scan
      *                and also used cameraView.flipImage(ImageView) for default animation
      */
     @Override
     public void onProcessUpdate(int titleCode, String errorMessage, boolean isFlip) {
     // make sure update view on ui thread
         runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 if (getTitleMessage(titleCode) != null) { // check
                     Toast.makeText(context, getTitleMessage(titleCode), Toast.LENGTH_SHORT).show(); // display title
                 }
                 if (errorMessage != null) {
                     Toast.makeText(context, getErrorMessage(errorMessage), Toast.LENGTH_SHORT).show(); // display message
                 }
                 if (isFlip) {
                     // To set default animation or remove this line to set your custom animation after successfully scan front side.
                     cameraView.flipImage(imageFlip);
                 }
             }
         });
     }

     private String getTitleMessage(int titleCode) {
         if (titleCode < 0) return null;
         switch (titleCode){
             case RecogEngine.SCAN_TITLE_OCR_FRONT:// for front side ocr;
                 return String.format("Scan Front Side of %s", cardName);
             case RecogEngine.SCAN_TITLE_OCR_BACK: // for back side ocr
                 return String.format("Scan Back Side of %s", cardName);
             case RecogEngine.SCAN_TITLE_OCR: // only for single side ocr
                 return String.format("Scan %s", cardName);
             case RecogEngine.SCAN_TITLE_MRZ_PDF417_FRONT:// for front side MRZ, PDF417 and BankCard
                 if (recogType == RecogType.BANKCARD) {
                     return "Scan Bank Card";
                 } else if (recogType == RecogType.BARCODE) {
                     return "Scan Barcode";
                 } else
                     return "Scan Front Side of Document";
             case RecogEngine.SCAN_TITLE_MRZ_PDF417_BACK: // for back side MRZ and PDF417
                 return "Now Scan Back Side of Document";
             case RecogEngine.SCAN_TITLE_DLPLATE: // for DL plate
                 return "Scan Number Plate";
             default:return "";
         }
     }

     private String getErrorMessage(String s) {
         switch (s) {
             case RecogEngine.ACCURA_ERROR_CODE_MOTION:
                 return "Keep Document Steady";
             case RecogEngine.ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME:
                 return "Keep document in frame";
             case RecogEngine.ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME:
                 return "Bring card near to frame.";
             case RecogEngine.ACCURA_ERROR_CODE_PROCESSING:
                 return "Processing...";
             case RecogEngine.ACCURA_ERROR_CODE_BLUR_DOCUMENT:
                 return "Blur detect in document";
             case RecogEngine.ACCURA_ERROR_CODE_FACE_BLUR:
                 return "Blur detected over face";
             case RecogEngine.ACCURA_ERROR_CODE_GLARE_DOCUMENT:
                 return "Glare detect in document";
             case RecogEngine.ACCURA_ERROR_CODE_HOLOGRAM:
                 return "Hologram Detected";
             case RecogEngine.ACCURA_ERROR_CODE_DARK_DOCUMENT:
                 return "Low lighting detected";
             case RecogEngine.ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT:
                 return "Can not accept Photo Copy Document";
             case RecogEngine.ACCURA_ERROR_CODE_FACE:
                 return "Face not detected";
             case RecogEngine.ACCURA_ERROR_CODE_MRZ:
                 return "MRZ not detected";
             case RecogEngine.ACCURA_ERROR_CODE_PASSPORT_MRZ:
                 return "Passport MRZ not detected";
             case RecogEngine.ACCURA_ERROR_CODE_ID_MRZ:
                 return "ID card MRZ not detected";
             case RecogEngine.ACCURA_ERROR_CODE_VISA_MRZ:
                 return "Visa MRZ not detected";
             case RecogEngine.ACCURA_ERROR_CODE_WRONG_SIDE:
                 return "Scanning wrong side of document";
             case RecogEngine.ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE:
                 return "Document is upside down. Place it properly";
             default:
                 return s;
         }
     }

     ```

   > Note : **(Optional)** `cameraView.flipImage(imageFlip);`  Use to display default flip card animation. \
   > You can use your custom animation for flip card.

   * You can receive and display the scanned result in the below override method. The method below is invoked twice for *RecogType.PDF417* and *RecogType.OCR*. And for the *RecogType.OCR*, it can be invoked once or twice with respect to a document. You can verify this with `cameraView.isBackSideAvailable()`. It will return <mark style="color:blue;">true</mark> if the back is available, otherwise return <mark style="color:red;">false</mark>.

     <br>

     ```
     /**
      * Override this method after scan complete to get data from document
      *
      * @param result is scanned card data
      *  result instance of {@link OcrData} if recog type is {@link com.docrecog.scan.RecogType#OCR}
      *              or {@link com.docrecog.scan.RecogType#DL_PLATE} or {@link com.docrecog.scan.RecogType#BARCODE}
      *  result instance of {@link RecogResult} if recog type is {@link com.docrecog.scan.RecogType#MRZ}
      *  result instance of {@link CardDetails} if recog type is {@link com.docrecog.scan.RecogType#BANKCARD}
      *  result instance of {@link PDF417Data} if recog type is {@link com.docrecog.scan.RecogType#PDF417}
      *
      */
     @Override
     public void onScannedComplete(Object result) {
         // display data on ui thread
         Log.e("TAG", "onScannedComplete: ");
         if (result != null) {
         	// make sure release camera view before open result screen
             // Do some code for display data

             if (result instanceof OcrData) {
                 if (recogType == RecogType.OCR) {
                     // @recogType is {@see com.docrecog.scan.RecogType#OCR}
                     if (isBack || !cameraView.isBackSideAvailable()) { // To check card has back side or not
                 	    if (cameraView != null) cameraView.release(true);	
                         OcrData.setOcrResult((OcrData) result); // Set data To retrieve it anywhere
                     } else {
                         isBack = true;
                         cameraView.setBackSide(); // To recognize data from back side too.
                         cameraView.flipImage(imageFlip);
                     }
                 } else if (recogType == RecogType.DL_PLATE || recogType == RecogType.BARCODE) {
                     // @recogType is {@link RecogType#DL_PLATE} or recogType == {@link RecogType#BARCODE}
                 	if (cameraView != null) cameraView.release(true);
                     OcrData.setOcrResult((OcrData) result); // Set data To retrieve it anywhere
                 }
             } else if (result instanceof RecogResult) {
                 // @recogType is {@see com.docrecog.scan.RecogType#MRZ}
                 if (cameraView != null) cameraView.release(true);
                 RecogResult.setRecogResult((RecogResult) result); // Set data To retrieve it anywhere
             } else if (result instanceof CardDetails) {
                 //  @recogType is {@see com.docrecog.scan.RecogType#BANKCARD}
                 if (cameraView != null) cameraView.release(true);
                 CardDetails.setCardDetails((CardDetails) result); // Set data To retrieve it anywhere
             } else if (result instanceof PDF417Data) {
                 //  @recogType is {@see com.docrecog.scan.RecogType#PDF417}
                 if (isBack || !cameraView.isBackSideAvailable()) {
                     if (cameraView != null) cameraView.release(true);
                     PDF417Data.setPDF417Result((PDF417Data) result); // Set data To retrieve it anywhere
                 } else {
                     isBack = true;
                     cameraView.setBackSide(); // To recognize data from back side too.
                     cameraView.flipImage(imageFlip);
                 }
             }
         } else Toast.makeText(this, "Failed", Toast.LENGTH_SHORT).show();
     }
     ```

   > <mark style="color:blue;">**Note:**</mark> It is necessary to release the camera view before showing the result on the results screen. Before releasing it, ensure that both sides of the document must be scanned as per your requirements. If you only scan one side and then release it directly, it may not fulfill your requirements.
   >
   > ```
   > if (cameraView != null) cameraView.release(true);
   > ```

   * Receive error messages<br>

     ```
     @Override
     public void onError(String errorMessage) {
         // display data on ui thread
         // stop ocr if failed
         Runnable runnable = () -> Toast.makeText(OcrActivity.this, errorMessage, Toast.LENGTH_LONG).show();
         runOnUiThread(runnable);
     }
     ```

5. **(Optional)**&#x54;o restart the scanning process after obtaining the result, you need to include the following code. This code should be placed within the *override method* of an *Android activity*, which gets called when you open the result activity using the `startActivityForResult(Intent, RESULT_ACTIVITY_CODE)`.

   <br>

   ```
   @Override
   protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
       ...
       if (resultCode == RESULT_OK) {
           if (requestCode == RESULT_ACTIVITY_CODE) {
               //<editor-fold desc="Call CameraView#startOcrScan(true) to scan document again">
               if (cameraView != null) cameraView.startOcrScan(true);
               //</editor-fold>
           }
       }
   }
   ```

   <br>


# Accura Scan -  Face Match / Face Biometrics

Face Biometrics is used for Matching Both the Source and the Target Image. It Matches the User's Selfie Image with the Image on the Document.

{% embed url="<https://drive.google.com/file/d/1MxXqc_FtS8wTI6Qa1aGiIBzAkgJD9uL6/view?usp=sharing>" %}

## Step 1: Before you begin

1. If you haven't done already then follow [Project Setup](/language/android/project-setup) steps.
2. Please download the Accura Scan license and then add it to your app.

   1. To generate your Accura Scan license contact <sales@accurascan.com>

   2. Move your **accuraface.license** file into the **module (app-level)** **assets folder** (usually `<project>/<app-module>/src/main/assets`)

   > <mark style="color:blue;">**Note:**</mark> Make sure license file name should be **accuraface.license**
3. Permissions required:
   1. Camera Permission `android.permission.CAMERA`
   2. Storage Permission required only for print out debug logs.

{% hint style="info" %} <mark style="color:blue;">**Note:**</mark> Enable logging for debugging purposes using the methods provided below. Please remember to disable logging before releasing the app. **(Storage permission is required for logging).**\
AccuraFaceMatchLog.setPrintLogs(true);\
AccuraFaceMatchLog.refreshLogfile(this);\
\
Log file will be stored in **InternalStorage/Downloads/AccuraLog.txt**
{% endhint %}

## Step 2 : Open Auto Capture Camera

* Customize camera screen **(Optional)**<br>

  ```
  FMCameraScreenCustomization cameraScreenCustomization = new FMCameraScreenCustomization();

  cameraScreenCustomization.backGroundColor = getResources().getColor(R.color.fm_camera_Background);
  cameraScreenCustomization.closeIconColor = getResources().getColor(R.color.fm_camera_CloseIcon);
  cameraScreenCustomization.feedbackBackGroundColor = getResources().getColor(R.color.fm_camera_feedbackBg);
  cameraScreenCustomization.feedbackTextColor = getResources().getColor(R.color.fm_camera_feedbackText);
  cameraScreenCustomization.feedbackTextSize = 18;
  cameraScreenCustomization.feedBackframeMessage = "Frame Your Face";
  cameraScreenCustomization.feedBackAwayMessage = "Move Phone Away";
  cameraScreenCustomization.feedBackOpenEyesMessage = "Keep Your Eyes Open";
  cameraScreenCustomization.feedBackCloserMessage = "Move Phone Closer";
  cameraScreenCustomization.feedBackCenterMessage = "Move Phone Center";
  cameraScreenCustomization.feedBackMultipleFaceMessage = "Multiple Face Detected";
  cameraScreenCustomization.feedBackHeadStraightMessage = "Keep Your Head Straight";
  cameraScreenCustomization.feedBackBlurFaceMessage = "Blur Detected Over Face";
  cameraScreenCustomization.feedBackGlareFaceMessage = "Glare Detected";
  cameraScreenCustomization.feedBackLowLightMessage = "Low light detected";
  cameraScreenCustomization.feedbackDialogMessage = "Loading...";
  cameraScreenCustomization.feedBackProcessingMessage = "Processing...";
  cameraScreenCustomization.showlogo = 0; // Set 0 to hide logo from selfie camera screen
  cameraScreenCustomization.logoIcon = R.drawable.your_logo; // To set your custom logo
      
  // FMCameraScreenCustomization.CAMERA_FACING_FRONT to set selfie camera       
  // FMCameraScreenCustomization.CAMERA_FACING_BACK to set rear camera
  cameraScreenCustomization.facing = FMCameraScreenCustomization.CAMERA_FACING_FRONT;

      
  // 0 for full dark face and 100 for full bright face or set it -1 to remove low light filter
  cameraScreenCustomization.setLowLightTolerence(-1/*lowLightTolerence*/);

  // 0 for clean face and 100 for Blurry face or set it -1 to remove blur filter
  cameraScreenCustomization.setBlurPercentage(80/*blurPercentage*/); // To allow blur on face
                                                  
  // Set min and max percentage for glare or set it -1 to remove glare filter
  cameraScreenCustomization.setGlarePercentage(6/*glareMinPercentage*/, 99/*glareMaxPercentage*/);
  ```

* Open Camera screen using android **Intent.**<br>

  ```
  Intent intent = SelfieFMCameraActivity.getCustomIntent(this, cameraScreenCustomization);
  startActivityForResult(intent, ACCURA_FACEMATCH_CAMERA);
  ```

{% hint style="info" %} <mark style="color:blue;">**Note:**</mark> If you want to use default camera screen then create intent with null object.\
Intent intent = SelfieFMCameraActivity.getCustomIntent(this,  null);&#x20;
{% endhint %}

* Receive Capture Image<br>

  ```
  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      if (resultCode == RESULT_OK) {
          if (requestCode == ACCURA_LIVENESS_CAMERA && data != null) {
              AccuraFMCameraModel result = data.getParcelableExtra("Accura.fm");
              if (result == null) {
                  return;
              }
              if (result.getStatus().equals("1")) {
                  // result bitmap
                  Bitmap bitmap = result.getFaceBiometrics();
                  Toast.makeText(this, "Success", Toast.LENGTH_SHORT).show();
              } else {
                  Toast.makeText(this, "Failed" + result.getStatus(), Toast.LENGTH_SHORT).show();
              }
          }
      }
  }
  ```

## **Step 3 : Implement face match**

1. **(Optional)** Required storage permission to read image file from internal storage.

2. Initialize **`com.inet.facelock.callback.FaceHelper`** in onCreate method <br>

   ```
   FaceHelper faceHelper = new FaceHelper(/*your activity context*/);
   faceHelper.setFaceMatchCallBack(this);
   faceHelper.initEngine();
   ```

3. Set src and target image to faceHelper<br>

   > <mark style="color:blue;">**Note:**</mark> Make sure to call **"faceHelper.setInputImage"** first, followed by **"faceHelper.setMatchImage"**.

   \
   Using a **File**

   ```
   faceHelper.setInputImage(srcFile);
   faceHelper.setMatchImage(targetFile);
   ```

   Using a **File URI**

   ```
   faceHelper.setInputImage(srcUri);
   faceHelper.setMatchImage(targetUri);
   ```

   Using **Path**

   ```
   faceHelper.setInputImage(srcPath);
   faceHelper.setMatchImage(targetPath);
   ```

   Using a **Bitmap**

   ```
   faceHelper.setInputImage(srcBitmap);
   faceHelper.setMatchImage(targetBitmap);
   ```

   \
   Using a file **URI** by using one function

   ```
   faceHelper.getFaceMatchScore(srcUri, targetUri);
   ```

   \
   Using a **file** by using one function

   ```
   faceHelper.getFaceMatchScore(srcFile, targetFile);
   ```

4. Implement **`com.inet.facelock.callback.FaceCallback`**&#x74;o your Activity and Override following methods to receive data.

   * Received original image in Bitmap format to display on ui as per your requirement <br>

     ```
     @Override
     public void onSetInputImage(Bitmap src1) {
         // set src image to your view
         image1.setImageBitmap(src1);
     }

     @Override
     public void onSetMatchImage(Bitmap src2) {
         // set target image to your view
         image2.setImageBitmap(src2);
     }
     ```

   * Receive Match score of src and target Image on below override method<br>

     ```
     @Override
     public void onFaceMatch(float score) {
         // get face match score
         System.out.println("Match Score : " + ss + " %");
     }
     ```

   * **(Optional)** Recomanded override methods for SDK<br>

     ```
     @Override
     public void onInitEngine(int ret) {
     }

     @Override
     public void onExtractInit(int ret) {
     }
     ```

   * Receive Detected Face position on your src and Target Images<br>

     ```
     // Src Image result
     @Override
     public void onLeftDetect(FaceDetectionResult faceResult) {
         if (faceResult != null) {
             // do some code
             Bitmap bitmap = faceResult.getFaceImage(bitmap); // get face Image
         }
     }

     // Target Image Result
     @Override
     public void onRightDetect(FaceDetectionResult faceResult) {
         if (faceResult != null) {
             // do some code
             Bitmap bitmap = faceResult.getFaceImage(bitmap); // get face Image
         }
     }
     ```

{% hint style="info" %}
Take a look of [ActivityFaceMatch.java](https://github.com/accurascan/Android-KYC) for full working example.
{% endhint %}


# Accura Liveness

User Authentication and Liveness Check Is Used for Customer Verification and Authentication.

{% embed url="<https://drive.google.com/file/d/1rKAqI_a1zUfDlDtUdB8VI5H0gokUlEYr/view?usp=sharing>" %}

## Step 1: Before you begin

1. If you haven't done already then follow [Project Setup](/language/android/project-setup) steps.
2. Contact AccuraScan at <contact@accurascan.com> for Liveness SDK or API
3. Required below permissions:
   1. Camera Permission `android.permission.CAMERA`
   2. Required Interent Permission
   3. Storage Permission required only for print out debug logs.

{% hint style="info" %} <mark style="color:blue;">**Note:**</mark> Enable logs using below methods for debugging. make sure disable it before release it. **(Required Storage permission for logging).**\
\
AccuraLivenessLog.setDEBUG(true);\
AccuraLivenessLog.refreshLogfile(activity);\
\
Log file will be stored in **InternalStorage/Downloads/AccuraLivenessLog.txt**
{% endhint %}

## Step 2 : Open Liveness camera screen

* Customize camera screen **(Optional)**<br>

  ```
  // To customize your screen theme and feed back messages
  LivenessCustomization livenessCustomization = new LivenessCustomization();

  livenessCustomization.backGroundColor = getResources().getColor(R.color.livenessBackground);
  livenessCustomization.closeIconColor = getResources().getColor(R.color.livenessCloseIcon);
  livenessCustomization.feedbackBackGroundColor = Color.TRANSPARENT;
  livenessCustomization.feedbackTextColor = Color.BLACK;
  livenessCustomization.feedbackTextSize = 18;
  livenessCustomization.feedBackframeMessage = "Frame Your Face";
  livenessCustomization.feedBackAwayMessage = "Move Phone Away";
  livenessCustomization.feedBackOpenEyesMessage = "Keep Your Eyes Open";
  livenessCustomization.feedBackCloserMessage = "Move Phone Closer";
  livenessCustomization.feedBackCenterMessage = "Move Phone Center";
  livenessCustomization.feedBackMultipleFaceMessage = "Multiple Face Detected";
  livenessCustomization.feedBackHeadStraightMessage = "Keep Your Head Straight";
  livenessCustomization.feedBackBlurFaceMessage = "Blur Detected Over Face";
  livenessCustomization.feedBackGlareFaceMessage = "Glare Detected";
  livenessCustomization.feedBackLowLightMessage = "Low light detected";
  livenessCustomization.feedbackDialogMessage = "Loading...";
  livenessCustomization.feedBackProcessingMessage = "Processing...";
  livenessCustomization.showlogo = 0; // Set 0 to hide logo from selfie camera screen
  livenessCustomization.logoIcon = R.drawable.your_logo; // To set your custom logo
      
  // LivenessCustomization.CAMERA_FACING_FRONT to set selfie camera       
  // LivenessCustomization.CAMERA_FACING_BACK to set rear camera
  livenessCustomization.facing = LivenessCustomization.CAMERA_FACING_FRONT;
      
  // 0 for full dark face and 100 for full bright face or set it -1 to remove low light filter
  livenessCustomization.setLowLightTolerence(-1/*lowLightTolerence*/);

  // 0 for clean face and 100 for Blurry face or set it -1 to remove blur filter
  livenessCustomization.setBlurPercentage(80/*blurPercentage*/); // To allow blur on face
                                                  
  // Set min and max percentage for glare or set it -1 to remove glare filter
  livenessCustomization.setGlarePercentage(6/*glareMinPercentage*/, 99/*glareMaxPercentage*/);
  ```

* Open Camera screen using android **Intent.**<br>

  ```
  Intent intent = SelfieCameraActivity.getCustomIntent(this, livenessCustomization, "your_url");
  startActivityForResult(intent, ACCURA_LIVENESS_CAMERA);
  ```

{% hint style="info" %} <mark style="color:blue;">**Note:**</mark> If you want to use default camera screen then create intent with null object.\
Intent intent = SelfieCameraActivity.getCustomIntent(this, null, "your\_url");&#x20;
{% endhint %}

* Receive Capure Image and liveness score<br>

  ```
  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      if (resultCode == RESULT_OK) {
          if (requestCode == ACCURA_LIVENESS_CAMERA && data != null) {
              AccuraVerificationResult result = data.getParcelableExtra("Accura.liveness");
              if (result == null) {
                  return;
              }
              if (result.getStatus().equals("1")) {
                  // get face image
                  Bitmap bitmap = result.getFaceBiometrics();
                  double livenessScore = result.getLivenessResult().getLivenessScore() * 100.0;
                  Toast.makeText(this, "Liveness Score : " + livenessScore, Toast.LENGTH_SHORT).show();
              } else {
                  Toast.makeText(this, result.getStatus() + " " + result.getErrorMessage(), Toast.LENGTH_SHORT).show();
              }
          }
      }
  }
  ```

  <br>


# Finger Biometrics

{% content-ref url="/pages/TiGdNrK5q8KAZhUKJzFf" %}
[Setup Accura Finger](/solutions/finger-biometrics/android/setup-accura-finger)
{% endcontent-ref %}


# iOS

Accura Scan’s robust IOS support. Click below to know more:


# Project Setup

{% embed url="<https://drive.google.com/file/d/1LwGC6oxyXlxhpACkfDQR5rkbPfyF2s-j/view?usp=sharing>" %}

{% hint style="info" %}
The iOS SDK has been VAPT (Vulnerability Assessment and Penetration Testing) tested .&#x20;

You can find the detailed report in the PDF attached below.
{% endhint %}

{% file src="/files/JfEsegNImhkTSAtjgb9d" %}

***

> ### Below are the steps to setup Accura Scan’s SDK in your project.

1. install Git LFS using command `install git-lfs`
2. Add below pod in podfile&#x20;

{% hint style="info" %}
If using `pod 'AccuraKYC'` or `pod 'AccuraKYC_Sim'`, no need to add\
any other pod, as it contains all OCR, Facematch and Liveness.
{% endhint %}

#### Bitcoded and Without Simulator

{% tabs %}
{% tab title="KYC" %}

```
# install the AccuraKYC pod for  AccuraOCR, AccuraFacematch And AccuraLiveness
pod 'AccuraKYC', '4.2.0'
```

{% endtab %}

{% tab title="OCR" %}

```
# install the AccuraOCR pod for AccuraOCR only.
pod 'AccuraOCR', '4.0.7'
```

{% endtab %}

{% tab title="Facematch and Liveness" %}

```
# install the AccuraLiveness_FM pod for AccuraLiveness And AccuraFacematch both.
pod 'AccuraLiveness_FM', '4.3.8'
```

{% endtab %}
{% endtabs %}

#### With Simulator and Not Bitcoded

{% tabs %}
{% tab title="KYC" %}

```
# install the AccuraKYC pod for  AccuraOCR, AccuraFacematch And AccuraLiveness
pod 'AccuraKYC_Sim', '4.2.0'
```

{% endtab %}

{% tab title="OCR" %}

```
# install the AccuraOCR pod for AccuraOCR only.
pod 'AccuraOCR_Sim', '4.0.7'
```

{% endtab %}

{% tab title="Facematch and Liveness" %}

```
# install the AccuraLiveness_FM pod for AccuraLiveness And AccuraFacematch both.
pod 'AccuraLiveness_FM_Sim', '4.3.8'
```

{% endtab %}
{% endtabs %}

3. Run `pod install`

&#x20; Note :- After the pod is installed, ensure to check the pod size as mentioned [here](/language/ios/project-setup/check-pod-size)

4. Solving pod issue (follow this step only if the pod size doesn’t match the size mentioned in point 3)

   \
   i. Clean the pod using `pod clean` command\
   ii. install Git LFS using `install git-lfs` command\
   iii. Run `pod install`


# Check Pod Size

* If you are using `AccuraKYC` pod\
  `your Project's root dicrectory/Pods/AccuraKYC/Framework/AccuraOCR.framework`\
  the `AccuraOCR.framework` size should be around 420 MB
* If you are using `AccuraOCR` pod\
  `your Project's root dicrectory/Pods/AccuraOCR/Framework/AccuraOCR.framework`\
  the `AccuraOCR.framework` size should be around 310 MB
* If you are using `AccuraLiveness_FM` pod\
  `your Project's root dicrectory/Pods/AccuraLiveness_FM/Framework/AccuraLiveness_FM.framework`\
  the `AccuraLiveness_FM.framework` size should be around 160 MB

{% hint style="info" %}
***Note*****:** If using Simulator Pods, the sizes of the pods will be reduce to around half of\
what's given above.
{% endhint %}

> If your pod size does not match given size follow step 4 of the [***Project Setup***](/language/ios/project-setup)


# Accura OCR

{% embed url="<https://drive.google.com/file/d/1TQ7QRyszd__SZhItxKUC9mW41WZ57mZ9/view?usp=sharing>" %}

### High Accuracy OCR (Optical Character Recognition) Includes English, Latin, Chinese, Korean and Japanese Languages.


# Setup Accura License and Configurations

To generate your Accura Scan license contact <sales@accurascan.com>

**Step 1:  Add license file in to your project.**\
Rename your license file to **`key.license`** (case-sensitive) and add it to your Xcode project.

{% hint style="info" %}
Make sure to rename your license with the proper name and format, which is key with the extension license. Eventually, it will look like key.license
{% endhint %}

**Step 2: To initialize sdk on app start:**

```
import AccuraOCR
var accuraCameraWrapper: AccuraCameraWrapper? = nil
var arrCountryList = NSMutableArray()
accuraCameraWrapper = AccuraCameraWrapper.init()
	let sdkModel = accuraCameraWrapper.loadEngine(your PathForDirectories)
	if (sdkModel.i > 0) {
		if(sdkModel!.isBankCardEnable) {
			self.arrCountryList.add("Bank Card")
		}
		if(sdkModel!.isMRZEnable) {
			self.arrCountryList.add("All MRZ")
			// ID MRZ
			// Visa MRZ
			// Passport MRZ
			// All MRZ
		}
		
		// if sdkModel.isOCREnable then get card data

		if (sdkModel.isOCREnable) let countryListStr = self.videoCameraWrapper?.getOCRList();
			if (countryListStr != null) {
				for i in countryListStr!{
					self.arrCountryList.add(i)
				}
			}
		}
		if(sdkModel!.isBarcodeEnable) {
			self.arrCountryList.add("Barcode")
		}
	}
	arrCountryList to get value(forKey: "card_name") //get card Name
	arrCountryList to get value(forKey: "country_id") //get country id
	arrCountryList to get value(forKey: "card_id") //get card id
```

**Step 2.1: Update filters config like below.**

Call this function after initialize sdk if license is valid(sdkModel.i > 0)

* Set Blur Percentage to allow blur on document

```
// 0 for clean document and 100 for Blurry document
self.accuraCameraWrapper?.setBlurPercentage(60/*blurPercentage*/)
```

* Set Blur Face Percentage to allow blur on detected Face

```
// 0 for clean face and 100 for Blurry face
accuraCameraWrapper?.setFaceBlurPercentage(80/*faceBlurPercentage*/)
```

* Set Glare Percentage to detect Glare on document

```
// Set min and max percentage for glare
accuraCameraWrapper?.setGlarePercentage(6/*minPercentage*/, 98/*maxPercentage*/)
```

* Set Photo Copy to allow photocopy document or not

```
// Set allow photocopy document or not
accuraCameraWrapper?.setCheckPhotoCopy(false/*isCheckPhotoCopy*/)
```

* Set Hologram detection to verify the hologram on the face

```
// true to check hologram on face
accuraCameraWrapper?.setHologramDetection(true/*isDetectHologram*/)
```

* Set Low Light Tolerance to allow lighting to detect documant

```
// 0 for full dark document and 100 for full bright document
accuraCameraWrapper?.setLowLightTolerance(10/*lowlighttolerance*/)
```

* Set motion threshold to detect motion on camera document

```
// 1 - allows 1% motion on document and
// 100 - it can not detect motion and allow document to scan.
accuraCameraWrapper?.setMotionThreshold(25/*setMotionThreshold*/)
```

* Sets camera Facing front or back camera

```
accuraCameraWrapper?.setCameraFacing(.CAMERA_FACING_BACK)
```

* Flip camera

```
accuraCameraWrapper?.switchCamera()
```

* Set Front/Back Side Scan

```
accuraCameraWrapper?.cardSide(.FRONT_CARD_SCAN)
```

<br>


# Set Up Camera View

This step-by-step process will help you setup the camera view.

{% hint style="info" %}
**Important:** Grant **Camera** and **Photo Library** permissions in your app.
{% endhint %}

```
import AccuraOCR
import AVFoundation
var accuraCameraWrapper: AccuraCameraWrapper? = nil
override func viewDidLoad() {
	super.viewDidLoad()
    // initialize Camera for OCR,MRZ,DLplate and BankCard
    accuraCameraWrapper = AccuraCameraWrapper.init(delegate: self, andImageView: /*setImageView*/ _imageView, andLabelMsg: */setLable*/ lblOCRMsg, andurl: */your PathForDirectories*/ NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String, cardId: /*setCardId*/ Int32(cardid!), countryID: /*setcountryid*/ Int32(countryid!), isScanOCR:/*Bool*/ isCheckScanOCR, andcardName:/*string*/  docName, andcardType: Int32(cardType/*2 = DLPlate And 3 = bankCard*/), andMRZDocType: /*SetMRZDocumentType*/ Int32(MRZDocType!/*0 = AllMRZ, 1 = PassportMRZ, 2 = IDMRZ, 3 = VisaMRZ*/))
        
    // initialize Camera for Barcode and PDF417 driving license
    accuraCameraWrapper = AccuraCameraWrapper.init(delegate: self, andImageView: imageView, andLabelMsg: lblBottamMsg, andurl: 1, isBarcodeEnable: isBarcodeEnabled/*set true for barcode and false for PDF417 driving license*/, countryID: Int32(self.countryid!), setBarcodeType: .all/*set barcode types*/)
        
	//Set min frame for qatar ID card
	//call this function before start camera
	accuraCameraWrapper?.setMinFrameForValidate(3) // Supports only odd number values
}

override func viewDidAppear(_ animated: Bool) {
	super.viewDidAppear(animated)
	accuraCameraWrapper?.startCamera()
}

override func viewWillDisappear(_ animated: Bool) {
	accuraCameraWrapper?.stopCamera()
	accuraCameraWrapper?.closeOCR()
	accuraCameraWrapper = nil
	super.viewWillDisappear(animated)
}

extension ViewController: VideoCameraWrapperDelegate{
	//it sets ViewLayer border according to card image
	func onUpdateLayout(_ frameSize: CGSize, borderRatio: Float) {
	frameSize:- get layer frame size
	borderRatio:- get layer ratio
	}
    
    func isBothSideAvailable(_ isBothAvailable: Bool) {
        accuraCameraWrapper?.cardSide(.FRONT_CARD_SCAN)
    }
	
	//it calls when scan barcode an PDF417 Driving license
    func recognizeSucceedBarcode(_ message: String!, back BackSideImage: UIImage!, frontImage FrontImage: UIImage!, face FaceImage: UIImage!) {
          //message :- Barcode Data
          //BackSideImage :- back image of Document
          //FrontImage :- front image of Document
          //FaceImage :- Face image of document
          if(isBarcodeEnabled) {
              //display result of barcode
          } else {
               if(BackSideImage == nil) {
                    self.accuraCameraWrapper?.cardSide(.BACK_CARD_SCAN)
                    self.flipAnimation()
              } else if (FrontImage == nil) {
                  self.accuraCameraWrapper?.cardSide(.FRONT_CARD_SCAN)
                  self.flipAnimation()
              }else {
                  //Display Result
              }
         }

	//  it calls continues when detect frame from camera
	func processedImage(_ image: UIImage!) {
		image:- get camara image.
	}

	// it call when license key wrong or didnt get key.license file
	func recognizeFailed(_ message: String!) {
		message:- message is a set alert message.
	}

	// it calls when get MRZ data

	func recognizeSucceed(_ scanedInfo: NSMutableDictionary!, recType: RecType, bRecDone: Bool, bFaceReplace: Bool, bMrzFirst: Bool, photoImage: UIImage, docFrontImage: UIImage!, docbackImage: UIImage!) {
		scanedInfo :- get MRZ data.
		photoImage:- get a document face Image.
		docFrontImage:- get document frontside image.
		docbackImage:- get document backside image.
	}

	// it calls when get front or back side image
	func matchedItem(_ image: UIImage!, isCardSide1 cs: Bool, isBack b: Bool, isFront f: Bool, imagePhoto imgp: UIImage!, imageResult: UIImage!) {
		if f == true to set frontside document Image.
		if f == false to set backside document Image.
	}

	//  it calls when get OCR data
	func resultData(_ resultmodel: ResultModel!) {
        if isbothSideAvailable {
            accuraCameraWrapper?.cardSide(.BACK_CARD_SCAN)
            if(resultmodel.arrayocrBackSideDataKey.count > 0) {
                //Display Result
            }
        } else {
            //Display result
        }
    }

	//  it calls when detect vehicle numberplate
	func dlPlateNumber(_ plateNumber: String!, andImageNumberPlate imageNumberPlate: UIImage!) {
		plateNumber:- get data of numberplate
		imageNumberPlate:- get image of numberplate
	}

	//it calls when get Bank Card data
	func recognizSuccessBankCard(cardDetail: NSMutableDictionary!, andBankCardImage bankCardImage: UIImage!) {
		cardDetail["card_type"] :- get bank card type
		cardDetail["card_number"] :- get bank card number
		cardDetail["expiration_month"] :- get bank card expiry month
		cardDetail["expiration_year"] :- get bank card expiry year
	}

	// it calls when recieve error message
	func reco_msg(_ messageCode: String!) {
		var message = String()
		if messageCode == ACCURA_ERROR_CODE_MOTION {
			message = "Keep Document Steady";
		} else if(messageCode == ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME) {
			message = "Keep document in frame";
		} else if(messageCode == ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME) {
			message = "Bring card near to frame";
		} else if(messageCode == ACCURA_ERROR_CODE_PROCESSING) {
			message = "Processing...";
		} else if(messageCode == ACCURA_ERROR_CODE_BLUR_DOCUMENT) {
			message = "Blur detect in document";
		} else if(messageCode == ACCURA_ERROR_CODE_FACE_BLUR) {
			message = "Blur detected over face";
		} else if(messageCode == ACCURA_ERROR_CODE_GLARE_DOCUMENT) {
			message = "Glare detect in document";
		} else if(messageCode == ACCURA_ERROR_CODE_HOLOGRAM) {
			message = "Hologram Detected";
		} else if(messageCode == ACCURA_ERROR_CODE_DARK_DOCUMENT) {
			message = "Low lighting detected";
		} else if(messageCode == ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT) {
			message = "Can not accept Photo Copy Document";
		} else if(messageCode == ACCURA_ERROR_CODE_FACE) {
			message = "Face not detected";
		} else if(messageCode == ACCURA_ERROR_CODE_MRZ) {
			message = "MRZ not detected";
		} else if(messageCode == ACCURA_ERROR_CODE_PASSPORT_MRZ) {
			message = "Passport MRZ not detected";
		} else if(messageCode == ACCURA_ERROR_CODE_ID_MRZ) {
			message = "ID MRZ not detected"
		} else if(messageCode == ACCURA_ERROR_CODE_VISA_MRZ) {
			message = "Visa MRZ not detected"
		}else if(messageCode == ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE) {
			message = "Document is upside down. Place it properly"
		}else if(messageCode == ACCURA_ERROR_CODE_WRONG_SIDE) {
			message = "Scanning wrong side of Document"
		}else {
			message = message;
		}
		print(message)
	}
}


// it calls when update title messages
func reco_titleMessage(_ messageCode: Int32) {
    var msg: String = ""
    switch messageCode {
        case SCAN_TITLE_OCR_FRONT:
            var frontMsg = "Scan Front side of ";
            frontMsg = frontMsg.appending(docName)
            msg = frontMsg
            break
        case SCAN_TITLE_OCR_BACK:
            var backMsg = "Scan Back side of ";
            backMsg = backMsg.appending(docName)
            msg = backMsg
            break
        case  SCAN_TITLE_OCR:
            var backMsg = "Scan ";
            backMsg = backMsg.appending(docName)
            msg = backMsg
            break
        case SCAN_TITLE_MRZ_PDF417_FRONT:
            msg = "Scan Front Side of Document"
            break
        case SCAN_TITLE_MRZ_PDF417_BACK:
            msg = "Scan Back Side of Document"
            break
        case SCAN_TITLE_DLPLATE:
            msg = "Scan Number plate"
            break
        case SCAN_TITLE_BARCODE:
            msg = "Scan Barcode"
            break
        case SCAN_TITLE_BANKCARD:
            msg = "Scan BankCard"
            break
        default:
            break
    }
    print(msg)
}
```


# Accura Scan - Face Match / Face Biometrics

{% embed url="<https://drive.google.com/file/d/1yVvjT-lPMKgqwoHPVkj2M4je5Ien40NA/view?usp=sharing>" %}

To generate your Accura Scan license contact <sales@accurascan.com>

### *Step 1:* Add Licence File

Add **`accuraface.license`** (case-sensitive) to your Xcode project.

{% hint style="info" %}
Make sure to rename your license with proper name and format which is accuraface with extension license, eventually will look like accuraface.license.
{% endhint %}

### *Step 2:* Add `FaceView.swift` file in your project.

### *Step 3:* Open auto capture camera

* import the module name `import AccuraLiveness_fm` if you are using `AccuraLiveness_FM` pod

```
// To customize your screen theme and feed back messages
var facematch = Facematch()
facematch.setBackGroundColor("#C4C4C5")
facematch.setCloseIconColor("#000000")
facematch.setFeedbackBackGroundColor("#C4C4C5")
facematch.setFeedbackTextColor("#000000")
facematch.setFeedbackTextSize(Float(18.0))
facematch.setFeedBackframeMessage("Frame Your Face")
facematch.setFeedBackAwayMessage("Move Phone Away")
facematch.setFeedBackOpenEyesMessage("Keep Open Your Eyes")
facematch.setFeedBackCloserMessage("Move Phone Closer")
facematch.setFeedBackCenterMessage("Center Your Face")
facematch.setFeedbackMultipleFaceMessage("Multiple face detected")
facematch.setFeedBackFaceSteadymessage("Keep Your Head Straight")
facematch.setFeedBackLowLightMessage("Low light detected")
facematch.setFeedBackBlurFaceMessage("Blur detected over face")
facematch.setFeedBackGlareFaceMessage("Glare detected")

// 0 for clean face and 100 for Blurry face
facematch.setBlurPercentage(80) // set blure percentage -1 to remove this filter

// Set min and max percentage for glare
facematch.setGlarePercentage(6, 99) //set glaremin -1 and glaremax -1 to remove this filter
```

### ***Step 4:*****&#x20;To Start Facematch**

```
facematch.setFacematch(self)
```

### *Step 5:* Detect face image

```
// it calls when Face image
func facematchData(_ FaceImage: UIImage!) {
	setFaceRegion(FaceImage)
}
// it calls when Facematch camera view dissappear
func facematchViewDisappear() {
}
```

### *Step 6:* Implement face match code manually to your activity.

**Important** Grant **Camera** permission in your app.

```
//if you are using Accura kyc pod need to import module 'import AccuraOCR' and if you using FaceMatchSDK pod need to import module 'import FaceMatchSDK'
import AccuraOCR
override func viewDidLoad() {
	super.viewDidLoad()
	/*
	 * FaceMatch SDK method to check if engine is initiated or not
	 * Return: true or false
	 */
	let fmInit = EngineWrapper.isEngineInit()
	if !fmInit{
		/*
		 * FaceMatch SDK method initiate SDK engine
		 */
		EngineWrapper.faceEngineInit()
	}
}

override func viewDidAppear(_ animated: Bool) {
	super.viewDidAppear(animated)
	/*
	 * Facematch SDK method to get SDK engine status after initialization
	 * Return: -20 = Face Match license key not found, -15 = Face Match license is invalid.
	 */
	let fmValue = EngineWrapper.getEngineInitValue() //get engineWrapper load status
	if fmValue == -20{
		// key not found
	}else if fmValue == -15{
		// License Invalid
	}
}

//make sure close FaceEngine when view disappear
override func viewDidDisappear(_ animated: Bool) {
    EngineWrapper.faceEngineClose()
}

/**
 * This method use calculate faceMatch score
 * Parameters to Pass: selected uiimage
 *
 */
func setFaceRegion(_ image: UIImage) {
	var faceRegion : NSFaceRegion?
	/*
	 * Accura Face SDK method to detect user face from document image
	 * Param: Document image
	 * Return: User Face
	 */
	faceRegion = EngineWrapper.detectSourceFaces(image)
	let face1 : NSFaceRegion? = faceView1.getFaceRegion(); // Get image data
	if (face1 == nil) {
		/*
		 * Accura Face SDK method to detect user face from document image
		 * Param: Document image
		 * Return: User Face
		 */
		faceRegion = EngineWrapper.detectSourceFaces(image);
	} else {
		/*
		 * Accura Face SDK method to detect user face from selfie or camera stream
		 * Params: User photo, user face found in document scanning
		 * Return: User face from user photo
		 */
		faceRegion = EngineWrapper.detectTargetFaces(image, feature1: face1?.feature);
	}
	if (selectFirstImage){
		if (faceRegion != nil){
			/*
			 * SDK method call to draw square face around
			 * @Params: BackImage, Front Image faceRegion Data
			 */
			faceView1.setFaceRegion(faceRegion)
		}
		let face2 : NSFaceRegion? = faceView2.getFaceRegion(); // Get image data
		if (face2 != nil) {
			let face1 : NSFaceRegion? = faceView1.getFaceRegion(); // Get image data
			var faceRegion2 : NSFaceRegion?
			if (face1 == nil){
				/*
				 * Accura Face SDK method to detect user face from document image
				 * Param: Document image
				 * Return: User Face
				 */
				faceRegion2 = EngineWrapper.detectSourceFaces(face2?.image)
			}else{
				/*
				 * Accura Face SDK method to detect user face from selfie or camera stream
				 * Params: User photo, user face found in document scanning
				 * Return: User face from user photo
				 */
				faceRegion2 = EngineWrapper.detectTargetFaces(face2?.image, feature1: face2?.feature)  //Identify face in back image which found in front
			}
			if(faceRegion2 != nil){
				/*
			     * SDK method call to draw square face around
				 * @Params: BackImage, Front Image faceRegion Data
				 */
				faceView2.setFaceRegion(faceRegion2)
				/*
				 * SDK method call to draw square face around
				 * @Params: BackImage, Front faceRegion Image
				 */
			}
		}
	} else if(faceRegion != nil){
	/*
	 * SDK method call to draw square face around
	 * @Params: BackImage, Front Image faceRegion Data
	 */
	faceView2.setFaceRegion(faceRegion)
	/*
	 * SDK method call to draw square face around
	 * @Params: BackImage, Front faceRegion Image
	 *
	}
	let face1:NSFaceRegion? = faceView1.getFaceRegion() // Get image data
	let face2:NSFaceRegion? = faceView2.getFaceRegion() // Get image data
	/*
	 * FaceMatch SDK method call to get FaceMatch Score
	 * @Params: FrontImage Face, BackImage Face
	 * @Return: Match Score
	 */
	let fmSore = EngineWrapper.identify(face1?.feature, featurebuff2: face2?.feature)
	let twoDecimalPlaces = String(format: "%.2f", fmSore*100) //Match score Convert Float Value
	print(Match Score :- "\(twoDecimalPlaces) %")
}
```


# Accura Face Liveness

This step-by-step process will help you setup Accura Scan’s Face Liveness solution.

{% embed url="<https://drive.google.com/file/d/155S2EdBxWWUFBwasdJnZzha6Rmg_ZGAi/view?usp=sharing>" %}

{% hint style="info" %}
Contact to <connect@accurascan.com> to get Url for liveness
{% endhint %}

### ***Step 1**:* Open camera for liveness Detectcion.

* import the module name `import AccuraLiveness_fm` if you are using `AccuraLiveness_FM` pod
* Setup auto capture Camera

```
//set liveness url
var liveness = Liveness()
liveness.setLivenessURL("/*Your URL*/")

// To customize your screen theme and feed back messages
liveness.setBackGroundColor("#C4C4C5")
liveness.setCloseIconColor("#000000")
liveness.setFeedbackBackGroundColor("#C4C4C5")
liveness.setFeedbackTextColor("#000000")
liveness.setFeedbackTextSize(Float(18.0))
liveness.setFeedBackframeMessage("Frame Your Face")
liveness.setFeedBackAwayMessage("Move Phone Away")
liveness.setFeedBackOpenEyesMessage("Keep Open Your Eyes")
liveness.setFeedBackCloserMessage("Move Phone Closer")
liveness.setFeedBackCenterMessage("Center Your Face")
liveness.setFeedbackMultipleFaceMessage("Multiple face detected")
liveness.setFeedBackFaceSteadymessage("Keep Your Head Straight")
liveness.setFeedBackLowLightMessage("Low light detected")
liveness.setFeedBackBlurFaceMessage("Blur detected over face")
liveness.setFeedBackGlareFaceMessage("Glare detected")

// 0 for clean face and 100 for Blurry face
liveness.setBlurPercentage(80) // set blure percentage -1 to remove this filter

// Set min and max percentage for glare
liveness.setGlarePercentage(6, 99) //set glaremin -1 and glaremax -1 to remove this filter

// if you want to enable SSL certificate pinning for Liveness API set it true. 
// if 'evaluateServerTrustWIthSSLPinning()' is true must have to add SSL Certificate of Your liveness API Server in Your Proeject's Root directory
liveness.evaluateServerTrustWIthSSLPinning(true)
```

### ***Step 2:*****&#x20;To Start Liveness**

```
liveness.setLiveness(self)
```

### ***Step 3**:* Handle Accura liveness Result

```
// it calls when get liveness result
func livenessData(_ stLivenessValue: String, livenessImage: UIImage, status: Bool){
}

// it calls when liveness camera view dissappear
func livenessViewDisappear() {
}
```


# Finger Biometrics

{% content-ref url="/pages/84SHUAPZItLYJiip0nxj" %}
[Setup Accura Finger](/solutions/finger-biometrics/ios/setup-accura-finger)
{% endcontent-ref %}


# Flutter

Accura Scan’s robust Flutter support. Click below for more details.


# Project Setup

**Add:** `flutter_accurascan_kyc` under dependencies in your pubspec.yaml file. And run \
`flutter pub get`

OR

&#x20;**Install using Terminal**

```
flutter pub add flutter_accurascan_kyc:4.2.0
```


# Android Setup


# Adding Permissions, Packaging options and Auth Token

**Add this permissions into Android’s AndroidManifest.xml file.**

```
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
```

**Add it in your root build.gradle at the end of repositories.**

```
allprojects {
   repositories {
       google()
       mavenCentral()
       maven {
           url 'https://jitpack.io'
           credentials { username 'jp_ssguccab6c5ge2l4jitaj92ek2' }
       }    
    }
}
```

**Add it in your app/build.gradle file.**

```
packagingOptions {
   pickFirst 'lib/arm64-v8a/libcrypto.so'
   pickFirst 'lib/arm64-v8a/libssl.so'
   
   pickFirst 'lib/armeabi-v7a/libcrypto.so'
   pickFirst 'lib/armeabi-v7a/libssl.so'
   
   pickFirst 'lib/x86/libcrypto.so'
   pickFirst 'lib/x86/libssl.so'
   
   pickFirst 'lib/x86_64/libcrypto.so'
   pickFirst 'lib/x86_64/libssl.so'
   
}
```


# Adding License

Accura Scan requires two licenses to enable the full functionality of this library. To generate your Accura Scan license contact <sales@accurascan.com>.

**The first license**, "key.license," is mandatory for the library to function properly. It includes all the necessary setup for the Accura SDK. **The second license**, "accuraface.license," is used to obtain the face match percentages between two face pictures. To set up the licenses, follow these steps:

1. Create an "assets" folder under app/src/main in your project directory.
2. Place the license files in the assets folder:

• key.license (for Accura Scan OCR) • accuraface.license (for Accura Scan Face Match) By following these instructions, you will properly set up the licenses by adding the license files to the designated assets folder.

### Setup License:

Create "assets" folder under app/src/main and Add license file in to assets folder. \
\- key.license // for Accura Scan OCR \
\- accuraface.license // for Accura Scan Face Match&#x20;

**Generate your Accura Scan license from** <https://accurascan.com/developer/dashboard>


# iOS Setup


# Installing pods and Adding Permissions.

**Installing Pods**

Install Git LFS using command `port install git-lfs` or `brew install git-lfs`

And then run `pod install`

{% hint style="info" %}
***Important:*** Please note that in the directory "Pods/AccuraKYC\_Sim/AccuraOCR.framework," the size of the AccuraOCR.framework should be approximately 220 MB. If the size is different, it may indicate that the git-lfs (Git Large File Storage) has not been initialized properly.
{% endhint %}

**Add this permissions into iOS Info.plist file.**

```
<key>NSCameraUsageDescription</key>
<string>App usage camera for scan documents.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App usage photos for get document picture.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>App usage photos for save document picture.</string>
```


# Adding License

Accura Scan requires two licenses to enable the full functionality of this library. To generate your Accura Scan license contact <sales@accurascan.com>

**The first license**, "key.license," is mandatory for the library to work properly. It includes all the necessary setup for the Accura SDK. **The second license**, "accuraface.license," is used for obtaining face match percentages between two face pictures. To set up the licenses, follow these steps:

1. Place both license files (key.license and accuraface.license) in your project's Runner directory.
2. Add the licenses to the target in your project.

By following these instructions, you will properly set up the licenses by placing them in the Runner directory and adding them to the target of your project..

### Setup License:

Place both the license in your project's Runner directory, and add the licenses to the target.

**Generate your Accura Scan license from** <https://accurascan.com/developer/dashboard>


# Functions

{% hint style="info" %}
**Usage:** Import flutter library into file.
{% endhint %}

```
import 'package:flutter_accurascan_kyc/flutter_accurascan_kyc.dart';
```


# Fetching Details From License

Setting up License

### The method used to fetch the details from the license is

```
AccuraOcr.getMetaData()
```

### The example function is shown below

```
  Future<void> getMetaData() async{
    try {
      await AccuraOcr.getMetaData().then((value) =>
          print(value));
    }on PlatformException{}
    if (!mounted) return;
  }
```

### ***Response:***

**On Success:** JSON String Response = { countrie&#x73;**:** Array\[], barcode&#x73;**:** Array\[], isVali&#x64;**:** boolean, isOCREnabl&#x65;**:** boolean, isBarcodeEnabl&#x65;**:** boolean, isBankCardEnable: boolean, isMRZEnable: boolean }

**Error:** String


# Setting Configurations, Error messages, Camera customization

The following methods are commonly used to set up configurations, error messages, scanning title messages, and camera customization

### Methods use to set configs are as follows

```
      AccuraOcr.setFaceBlurPercentage(80);
      AccuraOcr.setHologramDetection(true);
      AccuraOcr.setLowLightTolerance(10);
      AccuraOcr.setMotionThreshold(25);
      AccuraOcr.setMinGlarePercentage(6);
      AccuraOcr.setMaxGlarePercentage(99);
      AccuraOcr.setBlurPercentage(60);
      AccuraOcr.setCameraFacing(0);
```

### Methods use to set Error messages are as follows

```
       AccuraOcr.ACCURA_ERROR_CODE_MOTION("Keep Document Steady");
       AccuraOcr.ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME("Keep document in frame");
       AccuraOcr.ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME("Bring card near to frame");
       AccuraOcr.ACCURA_ERROR_CODE_PROCESSING("Processing");
       AccuraOcr.ACCURA_ERROR_CODE_BLUR_DOCUMENT("Blur detect in document");
       AccuraOcr.ACCURA_ERROR_CODE_FACE_BLUR("Blur detected over face");
       AccuraOcr.ACCURA_ERROR_CODE_GLARE_DOCUMENT("Glare detect in document");
       AccuraOcr.ACCURA_ERROR_CODE_HOLOGRAM("Hologram Detected");
       AccuraOcr.ACCURA_ERROR_CODE_DARK_DOCUMENT("Low lighting detected");
       AccuraOcr.ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT("Can not accept Photo Copy Document");
       AccuraOcr.ACCURA_ERROR_CODE_FACE("Face not detected");
       AccuraOcr.ACCURA_ERROR_CODE_MRZ("MRZ not detected");
       AccuraOcr.ACCURA_ERROR_CODE_PASSPORT_MRZ("Passport MRZ not detected");
       AccuraOcr.ACCURA_ERROR_CODE_ID_MRZ("ID MRZ not detected");
       AccuraOcr.ACCURA_ERROR_CODE_VISA_MRZ("Visa MRZ not detected");
       AccuraOcr.ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE("Document is upside down. Place it properly");
       AccuraOcr.ACCURA_ERROR_CODE_WRONG_SIDE("Scanning wrong side of Document");
       AccuraOcr.Disable_Card_Name(false);
```

### Methods use to set Scaning title messages are as follows

```
       AccuraOcr.SCAN_TITLE_OCR_FRONT("Scan Front side of ");
       AccuraOcr.SCAN_TITLE_OCR_BACK("Scan Back side of ");
       AccuraOcr.SCAN_TITLE_OCR("Scan ");
       AccuraOcr.SCAN_TITLE_MRZ_PDF417_FRONT("Scan Front Side of Document");
       AccuraOcr.SCAN_TITLE_MRZ_PDF417_BACK("Scan Back Side of Document");
       AccuraOcr.SCAN_TITLE_DLPLATE("Scan Number plate");
       AccuraOcr.SCAN_TITLE_BARCODE("Scan Barcode");
       AccuraOcr.SCAN_TITLE_BANKCARD("Scan BankCard");
```

### Methods use to set Camera customization are as follows

<pre><code>       AccuraOcr.isShowLogo(0);
       AccuraOcr.isFlipImg(1);
       AccuraOcr.CameraScreen_Border_Width(10);  // To set the width of the frame
       AccuraOcr.CameraScreen_CornerBorder_Enable(true); //To enable corner Only frame
<strong>       AccuraOcr.CameraScreen_Color("#80000000");   //Pass empty string for clear color else pass the Hex code e.g, #FFFFFF.
</strong>       AccuraOcr.CameraScreen_Back_Button(1); //For iOS disable the back button by Passing 0.
       AccuraOcr.CameraScreen_Change_Button(1); //To disable flip camera button pass 0.
       AccuraOcr.CameraScreen_Frame_Color("#D5323F"); //Pass a Hex Code to change the color of the frame.
       AccuraOcr.CameraScreen_Text_Border_Color("#000000"); //Pass a Hex Code to change the color of the text border pass empty string to disable it.
       AccuraOcr.CameraScreen_Text_Color("#FFFFFF"); //Pass a Hex Code to change the color of the text.
</code></pre>

### Methods use to set all the above configuration is

```
AccuraOcr.setAccuraConfigs();
```

### The example function is shown below

```
 Future<void> setAccuraConfig() async{
    try {

      await AccuraOcr.setFaceBlurPercentage(80);
      await AccuraOcr.setHologramDetection(true);
      await AccuraOcr.setLowLightTolerance(10);
      await AccuraOcr.setMotionThreshold(25);
      await AccuraOcr.setMinGlarePercentage(6);
      await AccuraOcr.setMaxGlarePercentage(99);
      await AccuraOcr.setBlurPercentage(60);
      await AccuraOcr.setCameraFacing(0);

      await AccuraOcr.SCAN_TITLE_OCR_FRONT("Scan Front side of ");
      await AccuraOcr.SCAN_TITLE_OCR_BACK("Scan Back side of ");
      await AccuraOcr.SCAN_TITLE_OCR("Scan ");
      await AccuraOcr.SCAN_TITLE_MRZ_PDF417_FRONT("Scan Front Side of Document");
      await AccuraOcr.SCAN_TITLE_MRZ_PDF417_BACK("Scan Back Side of Document");
      await AccuraOcr.SCAN_TITLE_DLPLATE("Scan Number plate");
      await AccuraOcr.SCAN_TITLE_BARCODE("Scan Barcode");
      await AccuraOcr.SCAN_TITLE_BANKCARD("Scan BankCard");


      await AccuraOcr.ACCURA_ERROR_CODE_MOTION("Keep Document Steady");
      await AccuraOcr.ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME("Keep document in frame");
      await AccuraOcr.ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME("Bring card near to frame");
      await AccuraOcr.ACCURA_ERROR_CODE_PROCESSING("Processing");
      await AccuraOcr.ACCURA_ERROR_CODE_BLUR_DOCUMENT("Blur detect in document");
      await AccuraOcr.ACCURA_ERROR_CODE_FACE_BLUR("Blur detected over face");
      await AccuraOcr.ACCURA_ERROR_CODE_GLARE_DOCUMENT("Glare detect in document");
      await AccuraOcr.ACCURA_ERROR_CODE_HOLOGRAM("Hologram Detected");
      await AccuraOcr.ACCURA_ERROR_CODE_DARK_DOCUMENT("Low lighting detected");
      await AccuraOcr.ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT("Can not accept Photo Copy Document");
      await AccuraOcr.ACCURA_ERROR_CODE_FACE("Face not detected");
      await AccuraOcr.ACCURA_ERROR_CODE_MRZ("MRZ not detected");
      await AccuraOcr.ACCURA_ERROR_CODE_PASSPORT_MRZ("Passport MRZ not detected");
      await AccuraOcr.ACCURA_ERROR_CODE_ID_MRZ("ID MRZ not detected");
      await AccuraOcr.ACCURA_ERROR_CODE_VISA_MRZ("Visa MRZ not detected");
      await AccuraOcr.ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE("Document is upside down. Place it properly");
      await AccuraOcr.ACCURA_ERROR_CODE_WRONG_SIDE("Scanning wrong side of Document");
      await AccuraOcr.isShowLogo(0);
      await AccuraOcr.isFlipImg(1);
      await AccuraOcr.CameraScreen_Border_Width(10);
      await AccuraOcr.CameraScreen_CornerBorder_Enable(true);
      await AccuraOcr.CameraScreen_Color("#80000000");  
      await AccuraOcr.CameraScreen_Back_Button(1); 
      await AccuraOcr.CameraScreen_Change_Button(1); 
      await AccuraOcr.CameraScreen_Frame_Color("#D5323F");
      await AccuraOcr.CameraScreen_Text_Border_Color("#000000"); 
      await AccuraOcr.CameraScreen_Text_Color("#FFFFFF"); 

      AccuraOcr.setAccuraConfigs();

    }on PlatformException{}
  }
```


# OCR

Accura Scan’s OCR scans and extracts data from any government Id globally.

### The method use to Start OCR scanning is

```
AccuraOcr.startOcrWithCard(config)
```

In the above method, the 'config' parameter is an array that consists of the following values, provided in the same format and sequence as shown below: Country ID, Card ID, Card Name, and Card Type. All these values will be provided by the license. Please note that the specific values for Country ID, Card ID, Card Name, and Card Type will vary based on your licensing information.

```
var config = [
  countrySelect['id'],  //Country id(Integer)
  cardSelected['id'],   //Card id(Integer)
  cardSelected['name'], //Card name(String)
  cardSelected['type'], //Card type(Integer)
];
```

### The example function is shown below

<pre><code>Future&#x3C;void> startOCR() async {
try {
var config = [
  countrySelect['id'],
  cardSelected['id'],
  cardSelected['name'],
  cardSelected['type'],
];
await AccuraOcr.startOcrWithCard(config)
    .then((value) =>
{
  setState(() {
    dynamic result = json.decode(value);
        })
      })
    .onError((error, stackTrace) =>{
    });
<strong>  } on PlatformException {}
</strong>}
</code></pre>

### ***Response:***

**On Success:** JSON String Response

**Error:** String


# MRZ

Accura Scan’s MRZ scans and extracts the MRZ data from any government Id globally.

### The method use to Start MRZ scanning is

```
AccuraOcr.startMRZ(config)
```

In the above method, the 'config' parameter is an array that consists of the following values, provided in the same format and sequence as shown below:

```
var config = [
  mrzselected, //pass either of the following passport_mrz, id_mrz, visa_mrz, other_mrz (String)
];
```

### The example function is shown below

```
Future<void> startMRZ() async {
try {
var config = [
  mrzselected,
];
await AccuraOcr.startMRZ(config)
    .then((value) => {
  setState((){
    dynamic result = json.decode(value);
          })
        }).onError((error, stackTrace) => {
      });
    } on PlatformException {}
}
```

### ***Response:***

**On Success:** JSON String Response

**Error:** String


# Barcode and Bankcard

Accura Scan’s solution scans and extracts data from Barcodes as well as Bank cards.

## Barcode

#### Method use to start Barcode scanning is

```
AccuraOcr.startBarcode(config);
```

In the above method, the 'config' parameter is an array that consists of the 'Selected Barcode' value. The specific value for the 'Selected Barcode' will be provided by the license.

```
var config= [barcodeSelected];
```

### The example function is shown below

<pre><code>Future&#x3C;void> startBarcode() async{
var config= barcodeSelected; //Barcode Selected(String)
await AccuraOcr.startBarcode([config]).then((value) => {
setState((){
  dynamic result = json.decode(value);
    })
<strong>  });
</strong>}
</code></pre>

### ***Response:***

**On Success:** JSON String Response

**Error:** String

## Bankcard

#### Method use to start Bankcard scanning is

```
AccuraOcr.startBankCard()
```

### The example function is shown below

```
Future<void> startBankCard() async{
try{
await AccuraOcr.startBankCard().then((value) => {
  setState((){
    dynamic result = json.decode(value);
      })
    });
  }on PlatformException{}
}
```

### ***Response:***

**On Success:** JSON String Response

**Error:** String


# Facematch and Liveness

Accura Scan face biometrics solution matches the selfie image with the image on the id card and also confirms if the user was live or not during the process.

## Facematch

### The method use to Start Facematch is

```
AccuraFacematch.startFaceMatch(accuraConfs)
```

In above method accuraConfs is an array consist of Face Uri in String Format, value will be provided by MRZ or OCR response.

```
var accuraConfs = [
{"face_uri":faceMatchURL}
];
```

### Methods use to set Facematch configs are as follows

```
    AccuraFacematch.setFaceMatchFeedbackTextSize(18);
    AccuraFacematch.setFaceMatchFeedBackframeMessage("Frame Your Face");
    AccuraFacematch.setFaceMatchFeedBackAwayMessage("Move Phone Away");
    AccuraFacematch.setFaceMatchFeedBackOpenEyesMessage("Keep Your Eyes Open");
    AccuraFacematch.setFaceMatchFeedBackCloserMessage("Move Phone Closer");
    AccuraFacematch.setFaceMatchFeedBackCenterMessage("Move Phone Center");
    AccuraFacematch.setFaceMatchFeedbackMultipleFaceMessage("Multiple Face Detected");
    AccuraFacematch.setFaceMatchFeedBackFaceSteadymessage("Keep Your Head Straight");
    AccuraFacematch.setFaceMatchFeedBackLowLightMessage("Low light detected");
    AccuraFacematch.setFaceMatchFeedBackBlurFaceMessage("Blur Detected Over Face");
    AccuraFacematch.setFaceMatchFeedBackGlareFaceMessage("Glare Detected");
    AccuraFacematch.setFaceMatchBlurPercentage(80);
    AccuraFacematch.setFaceMatchGlarePercentage_0(-1);
    AccuraFacematch.setFaceMatchGlarePercentage_1(-1);
```

### The example function is shown below

```
Future<void> startFaceMatch() async{
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
try{
var accuraConfs = {
  "face_uri":this.faceMatchURL
};

   await AccuraFacematch.setFaceMatchFeedbackTextSize(18);
   await AccuraFacematch.setFaceMatchFeedBackframeMessage("Frame Your Face");
   await AccuraFacematch.setFaceMatchFeedBackAwayMessage("Move Phone Away");
   await AccuraFacematch.setFaceMatchFeedBackOpenEyesMessage("Keep Your Eyes Open");
   await AccuraFacematch.setFaceMatchFeedBackCloserMessage("Move Phone Closer");
   await AccuraFacematch.setFaceMatchFeedBackCenterMessage("Move Phone Center");
   await AccuraFacematch.setFaceMatchFeedbackMultipleFaceMessage("Multiple Face Detected");
   await AccuraFacematch.setFaceMatchFeedBackFaceSteadymessage("Keep Your Head Straight");
   await AccuraFacematch.setFaceMatchFeedBackLowLightMessage("Low light detected");
   await AccuraFacematch.setFaceMatchFeedBackBlurFaceMessage("Blur Detected Over Face");
   await AccuraFacematch.setFaceMatchFeedBackGlareFaceMessage("Glare Detected");
   await AccuraFacematch.setFaceMatchBlurPercentage(80);
   await AccuraFacematch.setFaceMatchGlarePercentage_0(-1);
   await AccuraFacematch.setFaceMatchGlarePercentage_1(-1);

   await AccuraFacematch.startFaceMatch([accuraConfs])
    .then((value) => {
  setState((){
    dynamic result = json.decode(value);
        })
      }).onError((error, stackTrace) => {
     });
   }on PlatformException{}
}
```

### ***Response:***

**On Success:** JSON Response { detect: (URI), score: (Float) }

**Error:** String

## Liveness

### The method use to Start Liveness is

```
AccuraLiveness.startLiveness(accuraConfs)
```

In above method accuraConfs is an array consist of Face Uri in String Format, value will be provided by MRZ or OCR response.

```
var accuraConfs = [
  {"face_uri":faceMatchURL}
];
```

### Methods use to set Liveness configs are as follows

```
    AccuraLiveness.setLivenessFeedbackTextSize(18);
    AccuraLiveness.setLivenessFeedBackframeMessage("Frame Your Face");
    AccuraLiveness.setLivenessFeedBackAwayMessage("Move Phone Away");
    AccuraLiveness.setLivenessFeedBackOpenEyesMessage("Keep Your Eyes Open");
    AccuraLiveness.setLivenessFeedBackCloserMessage("Move Phone Closer");
    AccuraLiveness.setLivenessFeedBackCenterMessage("Move Phone Closer");
    AccuraLiveness.setLivenessFeedbackMultipleFaceMessage("Multiple Face Detected");
    AccuraLiveness.setLivenessFeedBackFaceSteadymessage("Keep Your Head Straight");
    AccuraLiveness.setLivenessFeedBackBlurFaceMessage("Blur Detected Over Face");
    AccuraLiveness.setLivenessFeedBackGlareFaceMessage("Glare Detected");
    AccuraLiveness.setLivenessBlurPercentage(80);
    AccuraLiveness.setLivenessGlarePercentage_0(-1);
    AccuraLiveness.setLivenessGlarePercentage_1(-1);
    AccuraLiveness.setLivenessFeedBackLowLightMessage("Low light detected");
    AccuraLiveness.setLivenessfeedbackLowLightTolerence(39);
    AccuraLiveness.setLivenessURL("You Liveness Url");
```

### The example function is shown below

<pre><code>Future&#x3C;void> startLiveness() async{
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
try{
var accuraConfs = {
  "face_uri":this.faceMatchURL
};

   await AccuraLiveness.setLivenessFeedbackTextSize(18);
   await AccuraLiveness.setLivenessFeedBackframeMessage("Frame Your Face");
   await AccuraLiveness.setLivenessFeedBackAwayMessage("Move Phone Away");
   await AccuraLiveness.setLivenessFeedBackOpenEyesMessage("Keep Your Eyes Open");
   await AccuraLiveness.setLivenessFeedBackCloserMessage("Move Phone Closer");
   await AccuraLiveness.setLivenessFeedBackCenterMessage("Move Phone Closer");
   await AccuraLiveness.setLivenessFeedbackMultipleFaceMessage("Multiple Face Detected");
   await AccuraLiveness.setLivenessFeedBackFaceSteadymessage("Keep Your Head Straight");
   await AccuraLiveness.setLivenessFeedBackBlurFaceMessage("Blur Detected Over Face");
   await AccuraLiveness.setLivenessFeedBackGlareFaceMessage("Glare Detected");
   await AccuraLiveness.setLivenessBlurPercentage(80);
   await AccuraLiveness.setLivenessGlarePercentage_0(-1);
   await AccuraLiveness.setLivenessGlarePercentage_1(-1);
   await AccuraLiveness.setLivenessFeedBackLowLightMessage("Low light detected");
   await AccuraLiveness.setLivenessfeedbackLowLightTolerence(39);
   await AccuraLiveness.setLivenessURL("You Liveness Url");



   await AccuraLiveness.startLiveness([accuraConfs])
    .then((value) => {
  setState((){
    dynamic result = json.decode(value);
           })
<strong>         }).onError((error, stackTrace) => {
</strong>      });
   }on PlatformException{}
}
</code></pre>

### ***Response:***

**On Success:** JSON Response

**Error:** String


# Cordova

Accura Scan’s robust Cordova support. Click below for more details.


# Project Setup

## Product Installation:

#### Add plugin

$ `cordova plugin add <absolute-path-to-(cordova-accura-kyc-pl)-folder>`

#### Example

```
cordova plugin add I:\accura-cordova\custom-plugins\cordova-accura-kyc-pl
```

### Create Your Own Accura Scan License

Accura Scan requires two licenses to enable the full functionality of this library. To generate your Accura Scan license contact <sales@accurascan.com>

**The first license**, "key.license," is mandatory for the library to function properly. It includes all the necessary setup for the Accura SDK. **The second license**, "accuraface.license," is used to obtain the face match percentages between two face pictures. To set up the licenses, follow these steps:

1. Create an "assets" folder under app/src/main in your project directory.
2. Place the license files in the assets folder:

• key.license (for Accura Scan OCR) • accuraface.license (for Accura Scan Face Match) By following these instructions, you will properly set up the licenses by adding the license files to the designated assets folder.


# Android Setup


# Packaging options and Auth Token

#### Add it in your root build.gradle at the end of repositories.

```
buildscript {
    repositories {
        ...
        jcenter()
    }
}

allprojects {
    repositories {
        ...
        jcenter()
        maven {
            url 'https://jitpack.io'
            credentials { username 'jp_ssguccab6c5ge2l4jitaj92ek2' }
        }
    }
}
```

#### Set Accura SDK as a dependency to our app/build.gradle file.

```
android {
    ...
    
    packagingOptions {
        pickFirst 'lib/arm64-v8a/libcrypto.so'
        pickFirst 'lib/arm64-v8a/libssl.so'

        pickFirst 'lib/armeabi-v7a/libcrypto.so'
        pickFirst 'lib/armeabi-v7a/libssl.so'

        pickFirst 'lib/x86/libcrypto.so'
        pickFirst 'lib/x86/libssl.so'

        pickFirst 'lib/x86_64/libcrypto.so'
        pickFirst 'lib/x86_64/libssl.so'

        pickFirst '**/libjsc.so'
        pickFirst '**/libc++_shared.so'

        pickFirst 'lib/x86/libc++_shared.so'
        pickFirst 'lib/x86_64/libc++_shared.so'
        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
        pickFirst 'lib/arm64-v8a/libc++_shared.so'

        pickFirst 'lib/x86/libopencv_java4.so'
        pickFirst 'lib/armeabi-v7a/libopencv_java4.so'
        pickFirst 'lib/arm64-v8a/libopencv_java4.so'
        pickFirst 'lib/x86_64/libopencv_java4.so'
        pickFirst 'lib/armeabi-v7a/libopencv_java4.so'

        pickFirst 'lib/armeabi-v7a/libaccurasdk.so'
        pickFirst 'lib/arm64-v8a/libaccurasdk.so'
        pickFirst 'lib/armeabi-v7a/libaccuraface.so'
        pickFirst 'lib/arm64-v8a/libaccuraface.so'
        pickFirst 'lib/armeabi-v7a/libaccuraliveness.so'
        pickFirst 'lib/arm64-v8a/libaccuraliveness.so'
    }
}
```


# Adding License

### Setup License:

Create "assets" folder under app/src/main and Add license file in to assets folder. \
\- key.license // for Accura Scan OCR \
\- accuraface.license // for Accura Scan Face Match&#x20;


# iOS Setup


# Installing pods

{% hint style="info" %}

#### *Please make sure to install git-lfs into your Mac.*

{% endhint %}

**Open your mac terminal and fire following command**

```
brew install git-lfs

or

port install git-lfs
```


# Adding License

Open iOS project into Xcode and drag & drop both license into project root directory. Do not forgot to check **"copy if needed"** & **"project name".**


# Functions

{% hint style="info" %}
To initialise the package use below code
{% endhint %}

```
document.addEventListener('deviceready', onDeviceReady, false);

var accura;

function onDeviceReady() {

     // Cordova is now initialized.

     accura = cordova.plugins.ACCURAService;

}
```


# Fetching Details From License

### The method use to fetch the details from the license is

```
accura.getMetadata(function (results), function (error))
```

### ***Response:***

**Success:** JSON Response = {countries: Array\[\<CountryModels>],barcodes: Array\[],\
isValid: boolean, isOCREnable: boolean ,isBarcode: boolean, isBankCard: boolean, isMRZ: boolean}

**Error:** String

#### Example Function:-

```
function getMetadata() {
     accura.getMetadata(function (results) {
         if (results.isValid) {
            //Here you will get json string from SDK with all 
                available functions activated on your license.
         } else {
             alert('Licence is not Loaded');
         }
     }, function (error) {
         alert(error);
     })
}
```


# Setting Title & Error messages

The following methods are commonly used to set up error and scanning title messages.

### Methods use to set all the configuration is

```
accura.setupAccuraConfig( config, function (result), function (error));
```

### *Parameter*:

***config***: JSON Object

### ***Response:***&#x20;

***Success***: JSON Response = {"Messages setup successfully"}\
***Error***: String

#### *Example Function:*

```
function setupAccuraConfig() {

    var config = {
        ACCURA_ERROR_CODE_MOTION:'Keep Document Steady',
        ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME:'Keep document in frame',
        ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME:'Bring card near to frame',
        ACCURA_ERROR_CODE_PROCESSING:'Processing…',
        ACCURA_ERROR_CODE_BLUR_DOCUMENT:'Blur detect in document',
        ACCURA_ERROR_CODE_FACE_BLUR:'Blur detected over face' ,
        ACCURA_ERROR_CODE_GLARE_DOCUMENT:'Glare detect in document' ,
        ACCURA_ERROR_CODE_HOLOGRAM:'Hologram Detected', 
        ACCURA_ERROR_CODE_DARK_DOCUMENT:'Low lighting detected',
        ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT: 'Can not accept Photo Copy Document',
        ACCURA_ERROR_CODE_FACE:'Face not detected',
        ACCURA_ERROR_CODE_MRZ:'MRZ not detected',
        ACCURA_ERROR_CODE_PASSPORT_MRZ:'Passport MRZ not detected',
        ACCURA_ERROR_CODE_ID_MRZ:'ID card MRZ not detected',
        ACCURA_ERROR_CODE_VISA_MRZ:'Visa MRZ not detected',
        ACCURA_ERROR_CODE_WRONG_SIDE:'Scanning wrong side of document',
        ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE:'Document is upside down. Place it properly',
    
        IS_SHOW_LOGO: true,
        SCAN_TITLE_OCR_FRONT: 'Scan Front Side of OCR Document',
        SCAN_TITLE_OCR_BACK: 'Scan Back Side of OCR Document',
        SCAN_TITLE_OCR:'Scan',
        SCAN_TITLE_BANKCARD:'Scan Bank Card',
        SCAN_TITLE_BARCODE:'Scan Barcode',
        SCAN_TITLE_MRZ_PDF417_FRONT:'Scan Front Side of Document',
        SCAN_TITLE_MRZ_PDF417_BACK:'Now Scan Back Side of Document',
        SCAN_TITLE_DLPLATE:'Scan Number Plate'
    };
    
    accura.setupAccuraConfig( config, function (result) {
        console.log("Messgae:- ", result);
    }, function (error) {
        alert(error);
    });
}
```


# OCR

Accura Scan’s OCR scans and extracts data from any government Id globally.

### The method use to Start OCR scanning is

```
accura.startOcrWithCard(accuraConfs, countryID, cardID, cardName, cardType, function (results), function (error));
```

### *Parameter:*

**accuraConfs**: {'enableLogs':false} , **countryID**: Integer, **cardID**: Integer, **cardName**: String, **cardType**: Integer

### ***Response:***

**Success:** JSON String Response

**Error:** String

#### Example function:

```
function startOcrWithCard() {

     var accuraConfs = {};
     var cardSlected = cards[cardSelected.split('_')[0]];
     accura.startOcrWithCard(
         accuraConfs,
         countrySelectedForCard.split('_')[1],
         cardSlected.id,
         cardSlected.name,
         cardSlected.type,
         function (results) {
             //The response from the sdk
         }, function (error) {
             alert(error);
         })
}
```


# MRZ

Accura Scan’s MRZ scans and extracts the MRZ data from any government Id globally.

### The method use to Start MRZ scanning is

<pre><code><strong>accura.startMRZ(accuraConfigs, mrzType, function (result), function (error));
</strong></code></pre>

### *Parameters*

**accuraConfs**: {'enableLogs':false}, **mrzType**: String(e.g. other\_mrz, passport\_mrz, id\_mrz, visa\_mrz)&#x20;

### ***Response:***

**Success:** JSON String Response

**Error:** String

#### Example function:

```
function startMRZ() {

     var accuraConfigs = {};
     accura.startMRZ(accuraConfigs, mrzSelected, function (result) {
          //Result from the SDK
     }, function (error) {
         alert(error)
     })
}
```


# Barcode & Bankcard

Accura Scan’s solution scans and extracts data from Barcodes as well as Bank cards.

## Barcode

### The method use to Start Barcode scanning is

```
accura.startBarcode(accuraConfs, barcodeType, function (results), function (error));
```

### *Parameters:*

**accuraConfs**: {'enableLogs':false}, **barcodeType**: String(Available from the license)

### ***Response:***

**Success:** JSON String Response

**Error:** String

### The example function is shown below

```
function startBarcode() {

   var accuraConfs = {};
   accura.startBarcode(accuraConfs, barcodeSelected, function (results) {
      //Result from the SDK
   }, function (error){
       alert(error);
   })
}
```

## Bankcard

### The method use to Start Bankcard scanning is

```
accura.startBankCard(accuraConfs, function (results), function (error));
```

### *Parameters:*

**accuraConfs**: {'enableLogs':false}

### ***Response:***

**On Success:** JSON String Response

**Error:** String

#### Example function:

```
function startBankCard() {

     var accuraConfs = {};
     accura.startBankCard(accuraConfs, function (results) {
        //Result from the SDK
     }, function (error) {
         alert(error);
     });
}
```


# Facematch & Liveness

Accura Scan face biometrics solution matches the selfie image with the image on the id card and also confirms if the user was live or not during the process.

## Facematch

### The method use to Start Facematch is

```
accura.startFaceMatch(accuraConfs, config, function (result), function (error));
```

### *Parameters:*

**accuraConfs**: JSON Object

* enableLogs: Boolean
* with\_face: Boolean
* face\_uri: URI

**config**: JSON Object

* feedbackTextSize: integer
* feedBackframeMessage: String
* feedBackAwayMessage: String
* feedBackOpenEyesMessage: String
* feedBackCloserMessage: String
* feedBackCenterMessage: String
* feedBackMultipleFaceMessage: String
* feedBackHeadStraightMessage: String
* feedBackBlurFaceMessage: String
* feedBackGlareFaceMessage: String
* setBlurPercentage: integer
* setGlarePercentage\_0: integer
* setGlarePercentage\_1: integer

### Response:

**Success**: JSON Response {with\_face: Boolean,status: Boolean,detect: URI? (when with\_face = true),img\_1: URI? (when with\_face = false),img\_2: URI? (when with\_face = false),score: Float}\
**Error**: String

#### Example function:

<pre><code>function startFaceMatch() {

     var accuraConfs = {with_face: true, face_uri: facematchURI};
     var config = {
         feedbackTextSize: 18,
         feedBackframeMessage: 'Frame Your Face',
         feedBackAwayMessage: 'Move Phone Away',
         feedBackOpenEyesMessage: 'Keep Your Eyes Open',
         feedBackCloserMessage: 'Move Phone Closer',
         feedBackCenterMessage: 'Move Phone Center',
         feedBackMultipleFaceMessage: 'Multiple Face Detected',
         feedBackHeadStraightMessage: 'Keep Your Head Straight',
         feedBackBlurFaceMessage: 'Blur Detected Over Face',
         feedBackGlareFaceMessage: 'Glare Detected',
         // &#x3C;!--// 0 for clean face and 100 for Blurry face or set it -1 to remove blur filter-->
         setBlurPercentage: 80,
         // &#x3C;!--// Set min percentage for glare or set it -1 to remove glare filter-->
         setGlarePercentage_0: -1,
         setGlarePercentage_1: -1,
     };
     accura.startFaceMatch(accuraConfs, config, function (result) {
           //Result from the SDK
<strong>     }, function (error) {
</strong>          alert(error);
     });
}
</code></pre>

## Liveness

### The method use to Start Liveness is

```
accura.startLiveness(accuraConfs, config, function (result), function (error));
```

### *Parameters:*

**accuraConfs**: JSON Object

* enableLogs: Boolean
* with\_face: Boolean
* face\_uri: 'uri of face'

**config**: JSON Object

* feedbackTextSize: integer
* feedBackframeMessage: String
* feedBackAwayMessage: String
* feedBackOpenEyesMessage: String
* feedBackCloserMessage: String
* feedBackCenterMessage: String
* feedBackMultipleFaceMessage: String
* feedBackHeadStraightMessage: String
* feedBackBlurFaceMessage: String
* feedBackGlareFaceMessage: String
* setBlurPercentage: integer
* setGlarePercentage\_0: integer
* setGlarePercentage\_1: integer
* isSaveImage: Boolean
* liveness\_url: URL **(Require)**
* contentType: String
* feedBackLowLightMessage: String
* feedbackLowLightTolerence: integer,
* feedBackStartMessage: String
* feedBackLookLeftMessage: String
* feedBackLookRightMessage: String
* feedBackOralInfoMessage: String
* enableOralVerification: Boolean,
* codeTextColor: String

### Response:

**Success**: JSON Response {with\_face: Boolean, status: Boolean, detect: URI?, image\_uri: URI?, fm\_score: Float?, score: Float}\
**Error**: String

#### Example function:

```
function startLiveness() {
     var accuraConfs = {with_face: true, face_uri: facematchURI};
     var config = {
         feedbackTextSize: 18,
         feedBackframeMessage: 'Frame Your Face',
         feedBackAwayMessage: 'Move Phone Away',
         feedBackOpenEyesMessage: 'Keep Your Eyes Open',
         feedBackCloserMessage: 'Move Phone Closer',
         feedBackCenterMessage: 'Move Phone Center',
         feedBackMultipleFaceMessage: 'Multiple Face Detected',
         feedBackHeadStraightMessage: 'Keep Your Head Straight',
         feedBackBlurFaceMessage: 'Blur Detected Over Face',
         feedBackGlareFaceMessage: 'Glare Detected',
         // <!--// 0 for clean face and 100 for Blurry face or set it -1 to remove blur filter-->
         setBlurPercentage: 80,
         // <!--// Set min percentage for glare or set it -1 to remove glare filter-->
         setGlarePercentage_0: -1,
         // <!--// Set max percentage for glare or set it -1 to remove glare filter-->
         setGlarePercentage_1: -1,
         liveness_url: '<your liveness url>',
         contentType: 'form_data',
         feedBackLowLightMessage: 'Low light detected',
     };
     accura.startLiveness(accuraConfs, config, function (result) {
           //Result from the SDK
     }, function (error) {
          alert(error);
     });
}
```


# React-Native

Accura Scan’s robust React-Native support. Click below for more details.


# Project Setup

**Installation using NPM**

```
npm install accurascan_kyc@1.4.3
```

**Installation using Yarn**

```
yarn add accurascan_kyc@1.4.3
```

### Create Your Own Accura Scan License

Accura Scan has two license require for use full functionality of this library. To generate your Accura Scan license contact <sales@accurascan.com>

**The first license**, "key.license," is mandatory for the library to function properly. It includes all the necessary setup for the Accura SDK. **The second license**, "accuraface.license," is used to obtain the face match percentages between two face pictures. To set up the licenses, follow these steps:

1. Create an "assets" folder under app/src/main in your project directory.
2. Place the license files in the assets folder:

• key.license (for Accura Scan OCR) • accuraface.license (for Accura Scan Face Match) By following these instructions, you will properly set up the licenses by adding the license files to the designated assets folder.


# Android Setup


# Adding Permissions, Packaging options and Auth Token

#### Add this permissions into Android AndroidManifest.xml file.

```
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
```

#### Add it in your root build.gradle at the end of repositories.

<pre><code>buildscript {
    repositories {
        ...
        mavenCentral()
    }
}

<strong>allprojects {
</strong>    repositories {
        ...
        mavenCentral()
        maven {
            url 'https://jitpack.io'
            credentials { username 'jp_ssguccab6c5ge2l4jitaj92ek2' }
        }
    }
}
</code></pre>

#### Set Accura SDK as a dependency to our app/build.gradle file.

```
android {
...

packagingOptions {
   pickFirst 'lib/arm64-v8a/libcrypto.so'
   pickFirst 'lib/arm64-v8a/libssl.so'

   pickFirst 'lib/armeabi-v7a/libcrypto.so'
   pickFirst 'lib/armeabi-v7a/libssl.so'

   pickFirst 'lib/x86/libcrypto.so'
   pickFirst 'lib/x86/libssl.so'

   pickFirst 'lib/x86_64/libcrypto.so'
   pickFirst 'lib/x86_64/libssl.so'

}
splits {
  abi {
    ...
    enable true
    include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
  }
 }
}
```


# Adding License

### Setup License:

Create "assets" folder under app/src/main and Add license file in to assets folder. \
\- key.license // for Accura Scan OCR \
\- accuraface.license // for Accura Scan Face Match&#x20;


# iOS Setup


# Adding Permissions.

{% hint style="info" %}

#### *Please make sure to install git-lfs into your Mac.*

{% endhint %}

**Open your mac terminal and run the following command**

```
brew install git-lfs

or

port install git-lfs
```

#### Add this permissions into iOS Info.plist file.

```
<key>NSCameraUsageDescription</key>
<string>App usage camera for scan documents.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>App usage photos for save document picture.</string>
```


# Adding License

Open iOS project into Xcode and drag & drop both license into project root directory. Do not forgot to check "**copy if needed**" & "**project name**".


# Functions

{% hint style="info" %}
***Import react native library into file.***
{% endhint %}

```
import AccurascanKyc from 'accurascan_kyc'
```


# Fetching License Details

### The method use to fetch the details from the license is

```
AccurascanKyc.getMetaData(function (error, success));
```

### ***Response:***

**Success:** JSON Response = {countries: Array\[\<CountryModels>],barcodes: Array\[],\
isValid: boolean, isOCREnable: boolean ,isBarcode: boolean, isBankCard: boolean, isMRZ: boolean, sdk\_version: String}

**Error:** String

#### Example Function:

```
AccurascanKyc.getMetaData((error, success) => {
    if (error != null) {
        //if SDK returns error in this method.
    } else {
        //Here you will get json string from SDK with all available functions activated on your license.
    }
})
```


# Setting Configurations, Error messages, Camera customization

The following methods are commonly used to set up configurations, error messages, scanning title messages, and camera customization

### The method use to set Configs Message

```
AccurascanKyc.setupAccuraConfig( [config, accuraConfigs, accuraTitleMsg], function (error, success));
```

### *Parameter*:

***config***: JSON Object

### ***Response:***&#x20;

***Success***: JSON Response = {"Messages setup successfully"}\
***Error***: String

#### Example Function:

```
 setUpCustomMessages = () => {
  var config = {
    setFaceBlurPercentage: 80,   // 0 for clean face and 100 for Blurry face
    setHologramDetection: true,  // true to check hologram on face
    setLowLightTolerance: 10,    // 0 for full dark document and 100 for full bright document
    setMotionThreshold: 25,      // 1 - allows 1% motion on document and 100 - it can not detect motion and allow document to scan.
    setMinGlarePercentage: 6,    // Set min percentage for glare
    setMaxGlarePercentage: 99,   // Set max percentage for glare
    setBlurPercentage: 60,       //0 for clean document and 100 for Blurry document
  };

  var accuraConfigs = {
    isShowLogo: 1,     //To hide Logo pass 0
    isFlipImg: 1,      //To hide flip animation pass 0
    CameraScreen_Frame_Color: '#D5323F',  //Pass a Hex Code to change frame color
    CameraScreen_Text_Color: '#FFFFFF',   //Pass a Hex Code to change text color
    CameraScreen_Text_Border_Color: '#000000', //Pass a Hex Code to change text border color
    CameraScreen_Color: '#80000000', //Pass a Hex Code to change Camera Screen Background color
    CameraScreen_Back_Button: 1, //Pass 0 to hide back button in iOS
    CameraScreen_Change_Button: 1, //Pass 0 to hide flip camera button
    CameraScreen_CornerBorder_Enable: false, //To enable corner border frame pass true
    Disable_Card_Name: false, //To disable taking card name automatically pass true
    CameraScreen_Border_Width: 10,
    Disable_Card_Name: false,
    ACCURA_ERROR_CODE_MOTION: 'Keep Document Steady',
    ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME: 'Keep document in frame',
    ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME: 'Bring card near to frame',
    ACCURA_ERROR_CODE_PROCESSING: 'Processing...',
    ACCURA_ERROR_CODE_BLUR_DOCUMENT: 'Blur detect in document',
    ACCURA_ERROR_CODE_FACE_BLUR: 'Blur detected over face',
    ACCURA_ERROR_CODE_GLARE_DOCUMENT: 'Glare detect in document',
    ACCURA_ERROR_CODE_HOLOGRAM: 'Hologram Detected',
    ACCURA_ERROR_CODE_DARK_DOCUMENT: 'Low lighting detected',
    ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT:
      'Can not accept Photo Copy Document',
    ACCURA_ERROR_CODE_FACE: 'Face not detected',
    ACCURA_ERROR_CODE_MRZ: 'MRZ not detected',
    ACCURA_ERROR_CODE_PASSPORT_MRZ: 'Passport MRZ not detected',
    ACCURA_ERROR_CODE_ID_MRZ: 'ID MRZ not detected',
    ACCURA_ERROR_CODE_VISA_MRZ: 'Visa MRZ not detected',
    ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE:
      'Document is upside down. Place it properly',
    ACCURA_ERROR_CODE_WRONG_SIDE: 'Scanning wrong side of Document',
  };

  var accuraTitleMsg = {
    SCAN_TITLE_OCR_FRONT: 'Scan Front side of ',
    SCAN_TITLE_OCR_BACK: 'Scan Back side of ',
    SCAN_TITLE_OCR: 'Scan ',
    SCAN_TITLE_MRZ_PDF417_FRONT: 'Scan Front Side of Document',
    SCAN_TITLE_MRZ_PDF417_BACK: 'Scan Back Side of Document',
    SCAN_TITLE_DLPLATE: 'Scan Number plate',
    SCAN_TITLE_BARCODE: 'Scan Barcode',
    SCAN_TITLE_BANKCARD: 'Scan BankCard',
  };

  //Method for setup config into native OS.
  AccurascanKyc.setupAccuraConfig(
    [config, accuraConfigs, accuraTitleMsg],
    (error, response) => {
      if (error != null) {
        console.log(error);
      } else {
        console.log('Message:- ', response);
      }
    }
  );
};
```


# OCR

Accura Scan’s OCR scans and extracts data from any government Id globally.

### The method use to Scan OCR

```
AccurascanKyc.startOcrWithCard(passArgs, function (error, success));
```

### *Parameter*:

***config***: \[CountryId, CardId, CardName, CardType]

* *CountryId*: integer
* *CardId*: integer
* *CardName*: String
* *CardType*: integer

In the above method, the 'config' parameter is an array that consists of the following values, provided in the same format and sequence as shown below: Country ID, Card ID, Card Name, and Card Type. All these values will be provided by the license. Please note that the specific values for Country ID, Card ID, Card Name, and Card Type will vary based on your licensing information.

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
onPressOCR = () => {
   let passArgs = [
     // all the values will be provided by the license
     this.countrySelected.id,  //integer
     this.cardSelected.id,     //integer
     this.cardSelected.name,   //String
     this.cardSelected.type,   //integer
   ];
   //Method for start OCR scaning from native OS.
   AccurascanKyc.startOcrWithCard(passArgs, (error, response) => {
     if (error != null) {
       console.log(error);
     } else {
       console.log('Success!', response);
     }
   });
};
```


# MRZ

Accura Scan’s MRZ scans and extracts the MRZ data from any government Id globally.

### The method use to Scan MRZ

```
AccurascanKyc.startMRZ(passArgs, function (error, success));
```

### *Parameter*:

***config***: \[MRZType]

* MRZType: String(e.g. other\_mrz, passport\_mrz, id\_mrz, visa\_card)

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
onPressMRZ = () => {
   let passArgs = [this.mrzSelected];  //pass other_mrz or passport_mrz or id_mrz or visa_card as String
   //Method for start MRZ scaning from native OS.
   AccurascanKyc.startMRZ(passArgs, (error, response) => {
     if (error != null) {
       console.log(error);
     } else {
       console.log('Success!', response);
     }
   });
};
```


# Barcode & Bankcard

Accura Scan’s solution scans and extracts data from Barcodes as well as Bank cards.

## Barcode

### The method use to Scan Barcode

```
AccurascanKyc.startBarcode(passArgs, function (error, success));
```

### *Parameter*:&#x20;

In the above method, the 'passArgs' parameter is an array that consists of the 'Selected Barcode' value. The specific value for the 'Selected Barcode' will be provided by the license.

***passArgs***: \[BarcodeType]

* BarcodeType: String&#x20;

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
onPressBarcode = () => {
   let passArgs = [this.barcodeSelected];
   AccurascanKyc.startBarcode(passArgs, (error, response) => {
     if (error != null) {
       console.log(error);
     } else {
       console.log('Success!', response);
     }
   });
};
```

## Bankcard

### The method use to Scan Bankcard

```
AccurascanKyc.startBankCard(function (error, success));
```

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
onPressBankcard = () => {
 AccurascanKyc.startBankCard((error, response) => {
   if (error != null) {
     console.log(error);
   } else {
      console.log('Success!', response);
   }
 });
};
```


# Facematch & Liveness

Accura Scan face biometrics solution matches the selfie image with the image on the id card and also confirms if the user was live or not during the process.

## Facematch

### The method use for Facematch

```
AccurascanKyc.startFaceMatch(passArgs, function (error, success));
```

### *Parameter*:

***passArgs***: \[accuraConfs, config]

* **accuraConfs**: JSON Object
  * face\_uri: URI
* **config**: JSON Object
  * backGroundColor: Hex code&#x20;
  * closeIconColor: Hex code
  * feedbackBackGroundColor: Hex code
  * feedbackTextColor: Hex code
  * setFeedbackTextSize: Integer
  * setFeedBackframeMessage: String
  * setFeedBackAwayMessage: String
  * setFeedBackOpenEyesMessage: String
  * setFeedBackCloserMessage: String
  * setFeedBackCenterMessage: String
  * setFeedbackMultipleFaceMessage: String
  * setFeedBackFaceSteadymessage: String
  * setFeedBackLowLightMessage: String
  * setFeedBackBlurFaceMessage: String
  * setFeedBackGlareFaceMessage: String
  * setBlurPercentage: Integer
  * setGlarePercentage\_0: Integer
  * setGlarePercentage\_1: Integer
  * feedbackDialogMessage: String
  * feedBackProcessingMessage: String
  * isShowLogo: Integer(0 or 1)

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
onPressFaceMatch = () => {
 var accuraConfs = {
   face_uri: this.facematchURI,
 };
 var fconfig = {
   backGroundColor: '#FFC4C4C5',
   closeIconColor: '#FF000000',
   feedbackBackGroundColor: '#FFC4C4C5',
   feedbackTextColor: '#FF000000',
   setFeedbackTextSize: 18,
   setFeedBackframeMessage: 'Frame Your Face',
   setFeedBackAwayMessage: 'Move Phone Away',
   setFeedBackOpenEyesMessage: 'Keep Your Eyes Open',
   setFeedBackCloserMessage: 'Move Phone Closer',
   setFeedBackCenterMessage: 'Move Phone Center',
   setFeedbackMultipleFaceMessage: 'Multiple Face Detected',
   setFeedBackFaceSteadymessage: 'Keep Your Head Straight',
   setFeedBackLowLightMessage: 'Low light detected',
   setFeedBackBlurFaceMessage: 'Blur Detected Over Face',
   setFeedBackGlareFaceMessage: 'Glare Detected',
   setBlurPercentage: 80,
   setGlarePercentage_0: -1,
   setGlarePercentage_1: -1,
   feedbackDialogMessage: 'Loading...',
   feedBackProcessingMessage: 'Processing...',
   isShowLogo: 1,
 };
 let passArgs = [accuraConfs, fconfig];

 AccurascanKyc.startFaceMatch(passArgs, (error, response) => {
   if (error != null) {
     console.log(error);
   } else {
     console.log('Success!', response);
   }
 });
};
```

## Liveness

### The method use for Liveness

```
AccurascanKyc.startLiveness(passArgs, function (error, success));
```

### Parameters:

***passArgs***: \[accuraConfs, config]

* **accuraConfs**: JSON Object
  * face\_uri: 'uri of face'
* **config**: JSON Object
  * backGroundColor: Hex code
  * closeIconColor: Hex code
  * feedbackBackGroundColor: Hex code
  * feedbackTextColor: Hex code
  * setFeedbackTextSize: Integer
  * setFeedBackframeMessage: String
  * setFeedBackAwayMessage: String
  * setFeedBackOpenEyesMessage: String
  * setFeedBackCloserMessage: String
  * setFeedBackCenterMessage: String
  * setFeedbackMultipleFaceMessage: String
  * setFeedBackFaceSteadymessage: String
  * setFeedBackBlurFaceMessage: String
  * setFeedBackGlareFaceMessage: String
  * setBlurPercentage: Integer
  * setGlarePercentage\_0: Integer
  * setGlarePercentage\_1: Integer
  * setLivenessURL: 'Your URL',&#x20;
  * setFeedBackLowLightMessage: String
  * feedbackLowLightTolerence: Integer
  * feedbackDialogMessage: String
  * feedBackProcessingMessage: String
  * isShowLogo: Integer(0 or 1),

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
onPressStartLiveness = () => {
 var accuraConfs = {
   face_uri: this.facematchURI,
 };

 var lconfig = {
   backGroundColor: '#FFC4C4C5',
   closeIconColor: '#FF000000',
   feedbackBackGroundColor: '#FFC4C4C5',
   feedbackTextColor: '#FF000000',
   setFeedbackTextSize: 18,
   setFeedBackframeMessage: 'Frame Your Face',
   setFeedBackAwayMessage: 'Move Phone Away',
   setFeedBackOpenEyesMessage: 'Keep Your Eyes Open',
   setFeedBackCloserMessage: 'Move Phone Closer',
   setFeedBackCenterMessage: 'Move Phone Center',
   setFeedbackMultipleFaceMessage: 'Multiple Face Detected',
   setFeedBackFaceSteadymessage: 'Keep Your Head Straight',
   setFeedBackBlurFaceMessage: 'Blur Detected Over Face',
   setFeedBackGlareFaceMessage: 'Glare Detected',
   setBlurPercentage: 80,
   setGlarePercentage_0: -1,
   setGlarePercentage_1: -1,
   setLivenessURL: 'Your URL',
   setFeedBackLowLightMessage: 'Low light detected',
   feedbackLowLightTolerence: 39,
   feedbackDialogMessage: 'Loading...',
   feedBackProcessingMessage: 'Processing...',
   isShowLogo: 1,
 };

 let passArgs = [accuraConfs, lconfig];

 AccurascanKyc.startLiveness(passArgs, (error, response) => {
   if (error != null) {
     console.log(error);
   } else {
     console.log('Success!', response);
   }
 });
};
```


# Xamarin

Accura Scan’s robust Xamarin support. Click below for more details.


# Project Setup

**Installation of package into project**

1. #### Xamarin forms project
   * Step: 1
     * Add accura service file into your main project directory. Right click on forms project -> Add -> Existing file -> Choose bellow file.
     * IAccuraScanService.cs
   * Step: 2
     * Add following NewGet packages into xamarin project.
     * Newtonsoft.Json
     * Xamarin.Essentials

### Create Your Own Accura Scan License

Accura Scan has three license require for use full functionality of this library. To generate your Accura Scan license contact <sales@accurascan.com>

**key.license**: This license is compulsory for the library to work and provides all the necessary setup for the Accura SDK.

**accuraface.license**: This license is used to obtain face match percentages between two face pictures.

**accuraactiveliveness.license**: This license is used to check active liveness between a face picture and a selfie camera.


# Android Setup

* Step: 1
  * Add below two projects into app. -> Right click on main app -> Add -> Existing project.
  * AccuraAndroidBinding.csproj
  * AccuraAndroidFinalBinding.csproj
* Step: 2
  * Add both projects into your project.Android as reference project.
  * Go to project.Android -> References -> right click -> Add reference -> select both projects -> tap on Add button.
* Step: 3
  * Add accura service file into your project.Android directory. Right click on project.Android -> Add -> Existing file -> Choose bellow file.
  * AccuraScanService.cs


# Adding Permission & Packages

#### Add this below permissions into your Xamarin android project.

* Right click on project.Android -> Options -> Android Application -> Required permissions -> choose below permissions into that list.
  1. Camera
  2. ReadExternalStorage
  3. WriteExternalStorage
  4. RecordAudio

#### Add following NewGet packages into project.Android app.

* Go to project.Android -> Packages -> right click on packages -> Manage NewGet packages.
  1. GoogleGson
  2. Karamunting.AndroidX.BumpTech.Glide
  3. Microsoft.ML.Vision
  4. Square.OkHttp3
  5. Xamarin.Android.Support.Constraint.Layout
  6. Xamarin.AndroidX.AppCompat
  7. Xamarin.AndroidX.ConstraintLayout
  8. Xamarin.AndroidX.ConstraintLayout.Solver
  9. Xamarin.AndroidX.Core
  10. Xamarin.AndroidX.Lifecycle.LiveData
  11. Xamarin.GooglePlayServices.MLKit.FaceDetection
  12. Xamarin.GooglePlayServices.MLKit.Text.Recognition
  13. Xamarin.GooglePlayServices.Vision
  14. Xamarin.GooglePlayServices.Vision.Common
  15. Xamarin.RootBeer
  16. Xamarin.AndroidX.ConstraintLayout.Solver


# Adding License

Go to project.Android -> Assets -> right click on it -> Add -> Existing files -> choose .license files and add it into project.


# iOS Setup

* Step: 1
  * Add below project into app. -> Right click on main app -> Add -> Existing project.
  * AccuraiOSBinding.csproj
* Step: 2
  * Add projects into your project.iOS as reference project.
  * Go to project.iOS -> References -> right click -> Add reference -> select project -> tap on Add button.
* Step: 3
  * Add accura service file into your project.iOS directory. Right click on project.iOS -> Add -> Existing file -> Choose bellow file.
  * AccuraScanService.cs
* Step: 4
  * Download required framework [AccuraKYC.framework.zip](https://github.com/accurascan/iOS-KYC/releases/download/3.1.1/AccuraKYC.framework.zip) from here then export it and add it as Native Reference into "AccuraiOSBinding.csproj".
  * Go to "AccuraiOSBinding.csproj" -> Native References -> right click -> Add -> choose AccuraKYC.framework


# Adding Permissions

#### Add this permissions into project.iOS Info.plist file.

```
<key>NSCameraUsageDescription</key>
<string>App usage camera for scan documents.</string>
<key>NSMicrophoneUsageDescription</key>
<string>App usage microphone for oral verification.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>App usage speech recognition for oral verification.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>App usage photos for save document picture.</string>
```


# Adding License

Go to project.iOS -> Resources -> right click on it -> Add -> Existing files -> choose all three .license files & gifs and add it into project.


# Functions

{% hint style="info" %}
Import Accura service into using xaml.cs file.
{% endhint %}

```
IAccuraScanService accuraService = DependencyService.Get<IAccuraScanService>();
```


# Fetching License details

### The method use to Fetch License details

```
accuraService.InitSDK(new AccuraScanResultCallBack());
```

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        accuraService.InitSDK(new AccuraScanResultCallBack());
    }
}
public class AccuraScanResultCallBack : AccuraServiceCallBack {
    public void InvokeResult(string error, string result) {
        if (error != null) {
            // Error block.
        }
        else {
            //Result from the SDK
        }
    }
}
```


# Setup custom messages

### The method use to Setup custom messages

```
accuraService.SetupAccuraConfig(configObj, new AccuraScanResultCallBack());
```

### *Parameters:*

**configObj**: JSON Object

* ACCURA\_ERROR\_CODE\_MOTION: String
* ACCURA\_ERROR\_CODE\_DOCUMENT\_IN\_FRAME: String
* ACCURA\_ERROR\_CODE\_BRING\_DOCUMENT\_IN\_FRAME: String
* ACCURA\_ERROR\_CODE\_PROCESSING: String
* ACCURA\_ERROR\_CODE\_BLUR\_DOCUMENT: String
* ACCURA\_ERROR\_CODE\_FACE\_BLUR: String
* ACCURA\_ERROR\_CODE\_GLARE\_DOCUMENT: String
* ACCURA\_ERROR\_CODE\_HOLOGRAM: String
* ACCURA\_ERROR\_CODE\_DARK\_DOCUMENT: String
* ACCURA\_ERROR\_CODE\_PHOTO\_COPY\_DOCUMENT: String
* ACCURA\_ERROR\_CODE\_FACE: String
* ACCURA\_ERROR\_CODE\_MRZ: String
* ACCURA\_ERROR\_CODE\_PASSPORT\_MRZ: String
* ACCURA\_ERROR\_CODE\_ID\_MRZ: String
* ACCURA\_ERROR\_CODE\_VISA\_MRZ: String
* ACCURA\_ERROR\_CODE\_WRONG\_SIDE: String
* ACCURA\_ERROR\_CODE\_UPSIDE\_DOWN\_SIDE: String
* IS\_SHOW\_LOGO: Boolean
* SCAN\_TITLE\_OCR\_FRONT: String
* SCAN\_TITLE\_OCR\_BACK: String
* SCAN\_TITLE\_OCR: String
* SCAN\_TITLE\_BANKCARD: String
* SCAN\_TITLE\_BARCODE: String
* SCAN\_TITLE\_MRZ\_PDF417\_FRONT: String
* SCAN\_TITLE\_MRZ\_PDF417\_BACK: String
* SCAN\_TITLE\_DLPLATE: String

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Functions:

```
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        JObject configObj = JObject.Parse(@"{
            'ACCURA_ERROR_CODE_MOTION':'Keep Document Steady',
            'ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME' : 'Keep document in frame',
            'ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME' : 'Bring card near to frame',
            'ACCURA_ERROR_CODE_PROCESSING' : 'Processing...',
            'ACCURA_ERROR_CODE_BLUR_DOCUMENT' : 'Blur detect in document',
            'ACCURA_ERROR_CODE_FACE_BLUR' : 'Blur detected over face',
            'ACCURA_ERROR_CODE_GLARE_DOCUMENT' : 'Glare detect in document',
            'ACCURA_ERROR_CODE_HOLOGRAM' : 'Hologram Detected',
            'ACCURA_ERROR_CODE_DARK_DOCUMENT' : 'Low lighting detected',
            'ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT' : 'Can not accept Photo Copy Document',
            'ACCURA_ERROR_CODE_FACE' : 'Face not detected',
            'ACCURA_ERROR_CODE_MRZ' : 'MRZ not detected',
            'ACCURA_ERROR_CODE_PASSPORT_MRZ' : 'Passport MRZ not detected',
            'ACCURA_ERROR_CODE_ID_MRZ' : 'ID card MRZ not detected',
            'ACCURA_ERROR_CODE_VISA_MRZ' : 'Visa MRZ not detected',
            'ACCURA_ERROR_CODE_WRONG_SIDE' : 'Scanning wrong side of document',
            'ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE' : 'Document is upside down. Place it properly',
            'IS_SHOW_LOGO' : true,
            'SCAN_TITLE_OCR_FRONT' : 'Scan Front Side of',
            'SCAN_TITLE_OCR_BACK' : 'Scan Back Side of',
            'SCAN_TITLE_OCR' : 'Scan',
            'SCAN_TITLE_BANKCARD' : 'Scan Bank Card',
            'SCAN_TITLE_BARCODE' : 'Scan Barcode',
            'SCAN_TITLE_MRZ_PDF417_FRONT' : 'Scan Front Side of Document',
            'SCAN_TITLE_MRZ_PDF417_BACK' : 'Now Scan Back Side of Document',
            'SCAN_TITLE_DLPLATE' : 'Scan Number Plate',
        }");
        //Setup scanning messages & logo for OCR, MRZ, Barcode & Bankcard.
        accuraService.SetupAccuraConfig(configObj.ToString(), new AccuraScanResultCallBack());
    }
}
public class AccuraScanResultCallBack : AccuraServiceCallBack {
    public void InvokeResult(string error, string result) {
        if (error != null) {
            // Error block.
        }
        else {
            // Result from the SDK
        }
    }
}
```

* **Success**: JSON Response { String }
* **Error**: String


# OCR

Accura Scan’s OCR scans and extracts data from any government Id globally.

### The method use to Scan OCR

```
accuraService.StartOCR(configObj, CountryId, CardId, CardName, CardType, appOriantation, new AccuraScanResultCallBack());
```

### *Parameter*:

* configObj: { enableLogs: false }
* *CountryId*: integer
* *CardId*: integer
* *CardName*: String
* *CardType*: integer
* *Orientation*: String (Default portrait)

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Functions:

```
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        JObject configObj = JObject.Parse(@"{
            'enableLogs' : false
        }");
        //Start OCR scanning.
        accuraService.StartOCR(configObj.ToString(), (string)selected_country["id"], (string)selected_card["id"], (string)selected_card["name"], (string)selected_card["type"], appOriantation, new AccuraScanResultCallBack());
    }
}
public class AccuraScanResultCallBack : AccuraServiceCallBack {
    public void InvokeResult(string error, string result) {
        if (error != null) {
            // Error block.
        }
        else {
            // Result from the SDK
        }
    }
}
```


# MRZ

Accura Scan’s MRZ scans and extracts the MRZ data from any government Id globally.

### The method use to Scan MRZ

```
accuraService.StartMRZ(configObj, MRZType, CountryList, appOriantation, new AccuraScanResultCallBack());
```

### *Parameter*:

* configObj: { enableLogs: false }
* MRZType: String(e.g. 'other\_mrz' or 'passport\_mrz' or 'id\_mrz' or 'visa\_mrz')
* CountryList: String (Default 'all')
* *Orientation*: String (Default portrait)

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Functions:

```
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        JObject configObj = JObject.Parse(@"{
            'enableLogs' : false
        }");
        String mrz_type = "passport_mrz";
        accuraService.StartMRZ(configObj.ToString(), mrz_type, "all", appOriantation, new AccuraScanResultCallBack());
    }
}
public class AccuraScanResultCallBack : AccuraServiceCallBack {
    public void InvokeResult(string error, string result) {
        if (error != null) {
            // Error block.
        }
        else {
            // Result from the SDK
        }
    }
}
```


# Barcode & Bankcard

Accura Scan’s solution scans and extracts data from Barcodes as well as Bank cards.

## Barcode

### The method use to Scan Barcode

```
accuraService.StartBarcode(configObj, BarcodeType, appOriantation, new AccuraScanResultCallBack());
```

### *Parameter*:

* configObj: { enableLogs: false }
* BarcodeType: String
* *Orientation*: String (Default portrait)

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Functions:

```
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        JObject configObj = JObject.Parse(@"{
            'enableLogs' : false
        }");
        accuraService.StartBarcode(configObj.ToString(), barcode_type, appOriantation, new AccuraScanResultCallBack());
    }
}
public class AccuraScanResultCallBack : AccuraServiceCallBack {
    public void InvokeResult(string error, string result) {
        if (error != null) {
            // Error block.
        }
        else {
            // Result from the SDK
        }
    }
}
```

## Bankcard

### The method use to Scan Bankcard

```
accuraService.StartBankCard(configObj, appOriantation, new AccuraScanResultCallBack());
```

### *Parameter*:

* configObj: { enableLogs: false }
* *Orientation*: String (Default portrait)

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        JObject configObj = JObject.Parse(@"{
            'enableLogs' : false
        }");
        accuraService.StartBankCard(configObj.ToString(), appOriantation, new AccuraScanResultCallBack());
    }
}
public class AccuraScanResultCallBack : AccuraServiceCallBack {
    public void InvokeResult(string error, string result) {
        if (error != null) {
            // Error block.
        }
        else {
            // Result from the SDK
        }
    }
}
```


# Facematch & Liveness

Accura Scan face biometrics solution matches the selfie image with the image on the id card and also confirms if the user was live or not during the process.

## Facematch

### The method use to start Facematch

```
accuraService.StartFaceMatch(accuraConfs, config, appOriantation, new AccuraScanResultCallBack());
```

### *Parameter:*

* *accuraConfs*: JSON Object
  * enableLogs: Boolean
  * with\_face: Boolean
  * face\_uri: URI
* *config*: JSON Object
  * feedbackTextSize: integer
  * feedBackframeMessage: String
  * feedBackAwayMessage: String
  * feedBackOpenEyesMessage: String
  * feedBackCloserMessage: String
  * feedBackCenterMessage: String
  * feedBackMultipleFaceMessage: String
  * feedBackHeadStraightMessage: String
  * feedBackBlurFaceMessage: String
  * feedBackGlareFaceMessage: String
  * setBlurPercentage: integer
  * setGlarePercentage\_0: integer
  * setGlarePercentage\_1: integer
* *Orientation*: String (Default portrait)

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        JObject accuraConfigObj = JObject.Parse(@"{
            'enableLogs' : false,
            'with_face' : true,
            'face_uri' : 'your face uri'
        }");
        JObject configObj = JObject.Parse(@"{
            'feedbackTextSize' : 18,
            'feedBackframeMessage' : 'Frame Your Face',
            'feedBackLowLightMessage' : 'Low light detected',
            'feedBackStartMessage' : 'Put your face inside the oval',
            'feedBackAwayMessage' : 'Move Phone Away',
            'feedBackOpenEyesMessage' : 'Keep Your Eyes Open',
            'feedBackCloserMessage' : 'Move Phone Closer',
            'feedBackCenterMessage' : 'Move Phone Center',
            'feedBackMultipleFaceMessage' : 'Multiple Face Detected',
            'feedBackHeadStraightMessage' : 'Keep Your Head Straight',
            'feedBackBlurFaceMessage' : 'Blur Detected Over Face',
            'feedBackGlareFaceMessage' : 'Glare Detected',
            'feedBackProcessingMessage' : 'Processing...',
            'setBlurPercentage' : 99,
            'setGlarePercentage_0' : -1,
            'setGlarePercentage_1' : -1,
            'isShowLogo' : true
        }");
        accuraService.StartFaceMatch(accuraConfigObj.ToString(), configObj.ToString(), appOriantation, new AccuraScanResultCallBack());
    }
}
public class AccuraScanResultCallBack : AccuraServiceCallBack {
    public void InvokeResult(string error, string result) {
        if (error != null) {
            // Error block.
        }
        else {
            // Result from the SDK
        }
    }
}
```

## Liveness

### The method use to start Liveness

```
accuraService.StartLiveness(accuraConfs, config, appOriantation, new AccuraScanResultCallBack());
```

### *Parameter:*

* *accuraConfs*: JSON Object
  * enableLogs: Boolean
  * with\_face: Boolean
  * face\_uri: URI
* *config*: JSON Object
  * feedbackTextSize: integer
  * feedBackframeMessage: String
  * feedBackAwayMessage: String
  * feedBackOpenEyesMessage: String
  * feedBackCloserMessage: String
  * feedBackCenterMessage: String
  * feedBackMultipleFaceMessage: String
  * feedBackHeadStraightMessage: String
  * feedBackBlurFaceMessage: String
  * feedBackGlareFaceMessage: String
  * setBlurPercentage: integer
  * setGlarePercentage\_0: integer
  * setGlarePercentage\_1: integer
  * isSaveImage: Boolean
  * liveness\_url: URL **(Require)**
  * contentType: String
  * feedBackLowLightMessage: String
  * feedbackLowLightTolerence: integer,
  * feedBackStartMessage: String
  * feedBackLookLeftMessage: String
  * feedBackLookRightMessage: String
  * feedBackOralInfoMessage: String
  * enableOralVerification: Boolean,
  * codeTextColor: String
* *Orientation*: String (Default portrait)

### ***Response:***&#x20;

***Success***: JSON Response\
***Error***: String

#### Example Function:

```
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        JObject accuraConfigObj = JObject.Parse(@"{
            'enableLogs' : false,
            'with_face' : false,
            'face_uri' : 'your face uri'}");
        JObject configObj = JObject.Parse(@"{
            'feedbackTextSize' : 18,
            'feedBackframeMessage' : 'Frame Your Face',
            'feedBackAwayMessage' : 'Move Phone Away',
            'feedBackOpenEyesMessage' : 'Keep Your Eyes Open',
            'feedBackCloserMessage' : 'Move Phone Closer',
            'feedBackCenterMessage' : 'Move Phone Center',
            'feedBackMultipleFaceMessage' : 'Multiple Face Detected',
            'feedBackHeadStraightMessage' : 'Keep Your Head Straight',
            'feedBackBlurFaceMessage' : 'Blur Detected Over Face',
            'feedBackGlareFaceMessage' : 'Glare Detected',
            'setBlurPercentage' : 99,
            'setGlarePercentage_0' : -1,
            'setGlarePercentage_1' : -1,
            'isSaveImage' : true,
            'liveness_url' : 'your liveness url',
            'contentType' : 'form_data',
            'feedBackLowLightMessage' : 'Low light detected',
            'feedbackLowLightTolerence' : 39,
            'feedBackStartMessage' : 'Put your face inside the oval',
            'feedBackLookLeftMessage' : 'Look over your left shoulder',
            'feedBackLookRightMessage' : 'Look over your right shoulder',
            'feedBackOralInfoMessage' : 'Say each digits out loud',
            'feedBackProcessingMessage' : 'Processing...',
            'enableOralVerification' : false,
            'codeTextColor' : 'white',
            'isShowLogo' : true
        }");
        accuraService.StartLiveness(accuraConfigObj.ToString(), configObj.ToString(), appOriantation, new AccuraScanResultCallBack());
    }
}
public class AccuraScanResultCallBack : AccuraServiceCallBack {
    public void InvokeResult(string error, string result) {
        if (error != null) {
            // Error block.
        }
        else {
            // Result from the SDK.
        }
    }
}
```


# Docker

Accura Scan's Docker images are designed to work on-premise, specifically on your servers and allows easy deployment of applications

### Install docker on your system from <https://docs.docker.com/get-docker/>

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>MRZ</td><td><a href="/pages/E760kjvA5ZvTLMQ2BwrJ">/pages/E760kjvA5ZvTLMQ2BwrJ</a></td></tr><tr><td>FaceMatch</td><td><a href="/pages/2pb7ArCDbiX8v4zZ2B6G">/pages/2pb7ArCDbiX8v4zZ2B6G</a></td></tr><tr><td>Liveness</td><td><a href="/pages/tQpIG1cf661MTiBt8KOK">/pages/tQpIG1cf661MTiBt8KOK</a></td></tr><tr><td>Voice</td><td><a href="/pages/rWvpBvnk1CZ8ZLb3fajk">/pages/rWvpBvnk1CZ8ZLb3fajk</a></td></tr><tr><td>ID Liveness</td><td><a href="/pages/UXkWTwd7WenysNqz42QZ">/pages/UXkWTwd7WenysNqz42QZ</a></td></tr><tr><td>OCR</td><td><a href="/pages/OXbZlEjFZZV4BKlTSEf8">/pages/OXbZlEjFZZV4BKlTSEf8</a></td></tr></tbody></table>


# MRZ

Accura Scan’s MRZ scans and extracts the MRZ data from any government Id globally.

{% embed url="<https://drive.google.com/file/d/1WLu3nQFrChCH44w5Pjl6Xjmo9-EdkXRA/view?usp=sharing>" %}

### Steps to Install and Run the MRZ Docker

#### Step 1:

Pull AccuraMRZ Docker image (latest tag) using the command `docker pull accurascan/mrz:<latest tag>`

{% hint style="info" %}
Visit <https://hub.docker.com/r/accurascan/mrz> to check the latest available version of AccuraMRZ
{% endhint %}

<pre data-title="Example:" data-full-width="false"><code><strong>docker pull accurascan/mrz:36.0.0
</strong></code></pre>

#### Step 2:

Run the docker by using the command: `sudo docker run -d -it -p port-you-want-accuramrz-to-run-on:80 --restart=always accurascan/mrz:<latest tag>`

{% code title="Example" overflow="wrap" %}

```
sudo docker run -d -it -p 3001:80 --restart=always accurascan/mrz:36.0.0
```

{% endcode %}

#### Step 3:

{% hint style="info" %}
To generate your Accura Scan license contact <sales@accurascan.com>
{% endhint %}

Upload your license accessing "<mark style="color:blue;">https\://\<yourdomain:port></mark>" using a browser, Example is shown in the image below.

<figure><img src="/files/HBfccDzDHAGge7NwgU2F" alt=""><figcaption></figcaption></figure>

#### Step 4:

Use “<mark style="color:blue;">[https://yourdomain:port/api.php](https://docs.accurascan.com/language/docker/https:/yourdomain:port/api.php)</mark>” (POST request) to access the API, an example post request is shown below.

<mark style="color:green;">`POST`</mark> `https://yourdomain:port/api.php`

#### Request Body

> You can either pass image file or an image base64.

| Name                                   | Type           | Description                  |
| -------------------------------------- | -------------- | ---------------------------- |
| file<mark style="color:red;">\*</mark> | file           | Upload your image file       |
| filebase64                             | text or string | paste your image base64 here |

{% tabs %}
{% tab title="200: OK An example response is shown in the image below" %}

{% endtab %}
{% endtabs %}

<figure><img src="/files/SSzaOAorR1cqtoS2CVlV" alt=""><figcaption></figcaption></figure>


# Accura Scan - Face Match / Face Biometrics

Accura Scan face biometrics solution matches the selfie image with the image on the id card

{% embed url="<https://drive.google.com/file/d/1t9vDwGtrfo5vsFQsIo-7403gZM7Hjn_g/view?usp=sharing>" %}

### Steps to Install and Run the FaceMatch Docker

#### Step 1:

Pull AccuraFacematch Docker image using the command `docker pull accurascan/facematch:<latest  tag>`

{% hint style="info" %}
Visit <https://hub.docker.com/r/accurascan/facematch> to check the latest available version of AccuraFaceMatch
{% endhint %}

{% code title="Example:" fullWidth="false" %}

```
docker pull accurascan/facematch:36.0.0
```

{% endcode %}

#### Step 2:

Run the docker by using the command: `sudo docker run -d -it -p port-you-want-accurafacematch-to-run-on:80 --restart=always accurascan/facematch:<latest tag>`

{% code title="Example" overflow="wrap" %}

```
sudo docker run -d -it -p 3001:80 --restart=always accurascan/facematch:36.0.0
```

{% endcode %}

#### Step 3:

{% hint style="info" %}
To generate your Accura Scan license contact <sales@accurascan.com>
{% endhint %}

Upload your license accessing "<mark style="color:blue;">https\://\<yourdomain:port></mark>" using a browser, Example is shown in the image below.

<figure><img src="/files/kFDZn9KeJDnt1Sa0fZXB" alt=""><figcaption></figcaption></figure>

#### Step 4:

Use “<mark style="color:blue;">[https://yourdomain:port/api.php](https://docs.accurascan.com/language/docker/https:/yourdomain:port/api.php)</mark>” (POST request) to access the API, an example post request is shown below.

<mark style="color:green;">`POST`</mark> `https://yourdomain:port/api.php`

#### Request Body

> You can either pass image file or an image base64.

| Name                                     | Type           | Description                  |
| ---------------------------------------- | -------------- | ---------------------------- |
| image1<mark style="color:red;">\*</mark> | file           | Upload your image file       |
| image2<mark style="color:red;">\*</mark> | file           | Upload your image file       |
| image1base64                             | text or string | paste your image base64 here |
| image2base64                             | text or string | paste your image base64 here |

{% tabs %}
{% tab title="200: OK An example response is shown in the image below" %}

{% endtab %}
{% endtabs %}

<figure><img src="/files/Fx5yHUKCo5E5JAZv3jsP" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The preferred threshold is **55%**, meaning that if an image achieves a score above this threshold, the Face Match is considered ***Successful***; otherwise, the Face Match is deemed to have ***Failed***.
{% endhint %}


# Face Liveness

Face Liveness Check is used for Customer Verification and Authentication. It Protects You from Identity Theft & Spoofing Attacks Using Active and Passive Selfie Technology for Liveness Check.

{% embed url="<https://drive.google.com/file/d/1lL0Hl49D7yQsN4VIaZ2CwI_g9M4u-ajr/view?usp=sharing>" %}

### Steps to Install and Run the Liveness Docker

#### Step 1:

Pull AccuraLiveness Docker image using the command `docker pull accurascan/faceliveness:<latest  tag>`

{% hint style="info" %}
Visit <https://hub.docker.com/r/accurascan/faceliveness> to check the latest version available
{% endhint %}

{% code title="Example:" fullWidth="false" %}

```
docker pull accurascan/faceliveness:36.0.0
```

{% endcode %}

#### Step 2:

Run the docker by using the command: `sudo docker run -dp port-you-want-accuraliveness-to-run-on:443 -- restart=always accurascan/faceliveness:<latest tag>`

{% code title="Example" overflow="wrap" %}

```
docker run -dp 8448:443 --restart=always accurascan/faceliveness:36.0.0
```

{% endcode %}

#### Step 3:

{% hint style="info" %}
To generate your Accura Scan license contact <sales@accurascan.com>
{% endhint %}

Upload your license accessing "<mark style="color:blue;">https\://\<yourdomain:port></mark>" using a browser, Example is shown in the image below.

<figure><img src="/files/BrjZX9xwwUQSb0uRR4oS" alt=""><figcaption></figcaption></figure>

#### Step 4:

Use <mark style="color:blue;">[https://your-domain-or-ip.com:port/upload.php](https://docs.accurascan.com/language/docker/https:/your-domain-or-ip.com:port/upload.php)</mark> (POST request) to access the API, an example post request as shown below.

<mark style="color:green;">`POST`</mark> `https://yourdomain:port/upload.php`

#### Request Body

> You can either pass image file or an image base64.

| Name                                    | Type           | Description                   |
| --------------------------------------- | -------------- | ----------------------------- |
| image<mark style="color:red;">\*</mark> | file           | Upload your image file        |
| imagebase64                             | text or string | paste your image base 64 here |

{% tabs %}
{% tab title="200: OK An example response is shown in the image below" %}

{% endtab %}
{% endtabs %}

<figure><img src="/files/ySdIGfLTb4YMiFdFdPv3" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The preferred threshold is **55%**, meaning that if an image achieves a score above this threshold, the face shown is considered ***Live***; otherwise, it is identified as a ***Spoof***.
{% endhint %}


# Doc Liveness and ID Forgery

Document Liveness & ID Forgery Protection ensures secure verification, blocking deepfakes, spoofing, and camera manipulation with AI-driven detection and motion analysis.

{% embed url="<https://drive.google.com/file/d/1I_Is6k-MYLtdNYJZjVvj-rM5iUBZ4jdu/view?usp=sharing>" %}

### Steps to Install and Run the ID Liveness Docker

#### Step 1:

Pull Accura ID Liveness Docker image using the command `docker pull accurascan/docliveness:<latest tag>`

{% hint style="info" %}
Visit <https://hub.docker.com/r/accurascan/docliveness> to check the latest version available
{% endhint %}

{% code title="Example:" fullWidth="false" %}

```
docker pull accurascan/docliveness:37.0.0
```

{% endcode %}

#### Step 2:

Run the docker by using the command: `sudo docker run -dp port-you-want-accuraliveness-to-run-on:443 -- restart=always accurascan/docliveness:<latest tag>`

{% code title="Example" overflow="wrap" %}

```
docker run -dp 8043:443 --restart=always accurascan/docliveness:37.0.0
```

{% endcode %}

#### Step 3:

{% hint style="info" %}
To generate your Accura Scan license contact <sales@accurascan.com>
{% endhint %}

Upload your license accessing "<mark style="color:blue;">http\://\<yourdomain:port></mark>" using a browser, Example is shown in the image below.

<figure><img src="/files/Sh2CAl9t6vYqoMkMcgJ1" alt=""><figcaption></figcaption></figure>

#### Step 4:

Use <mark style="color:blue;">[https://your-domain-or-ip.com:port/doc\\\_liveness.php](https://docs.accurascan.com/language/docker/https:/your-domain-or-ip.com:port/doc\\_liveness.php)</mark> (POST request) to access the API, an example post request as shown below.

<mark style="color:green;">`POST`</mark> `https://yourdomain:port/doc_liveness.php`

{% hint style="info" %}
To view country\_code and card\_code for any card visit <https://accurascan.com/documents-supported-api>
{% endhint %}

#### Request Body

> You can either pass image file or an image base64.

<table><thead><tr><th>Name</th><th>Type</th><th>Description</th><th data-hidden></th></tr></thead><tbody><tr><td>image<mark style="color:red;">*</mark></td><td>file</td><td>Upload your image file</td><td></td></tr><tr><td>image_base64</td><td>text or string</td><td>paste your image base64 here</td><td></td></tr><tr><td>isface<mark style="color:red;">*</mark></td><td>front/back</td><td>put card side either the card image is front or back</td><td></td></tr><tr><td>country_code<mark style="color:red;">*</mark></td><td>COL</td><td>put country_code of the card image</td><td></td></tr><tr><td>card_code<mark style="color:red;">*</mark></td><td>CLMID</td><td>put card_code of the card image </td><td></td></tr><tr><td>passport<mark style="color:red;">*</mark></td><td>true/false</td><td>if image is a passport put true else put false</td><td></td></tr><tr><td>webcam<mark style="color:red;">*</mark></td><td>true/false</td><td>if image is captured from a webcam put true else if image is captured from a mobile put  false</td><td></td></tr></tbody></table>

{% tabs %}
{% tab title="200: OK An example response is shown in the image below" %}

{% endtab %}
{% endtabs %}

<figure><img src="/files/po0XRpU6tAgm8vwFqatV" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The preferred threshold is **55%**, meaning that if an image achieves a score above this threshold, the ID shown is considered ***Live***; otherwise, it is identified as a ***Spoof***.
{% endhint %}


# Accura Scan Voice Biometrics

Accura Scan Voice Biometrics solution matches the source voice .wav file with the target voice .wav file.

### Steps to Install and Run the Voice Docker

#### Step 1:

Pull AccuraVoice Docker image using the command `docker pull accurascan/voice:<latest tag>`

{% hint style="info" %}
Visit <https://hub.docker.com/r/accurascan/voice> to check the latest available version of AccuraVoice
{% endhint %}

```
Example:
docker pull accurascan/voice:1.0.0
```

#### Step 2:

Run the docker by using the command: `sudo docker run -dp port-you-want-accuravoice-to-run-on:80 --restart=always accurascan/voice:<latest tag>`

```
Example
sudo docker run -dp 8010:80 --restart=always accurascan/voice:1.0.0
```

#### Step 3:

{% hint style="info" %}
To generate your Accura Scan license contact <sales@accurascan.com>
{% endhint %}

Upload your license accessing "<mark style="color:blue;">https\://\<yourdomain:port></mark>" using a browser, Example is shown in the image below.

<figure><img src="/files/fYMNSLZSe5ASsnvgmG5P" alt=""><figcaption></figcaption></figure>

#### Step 4:

Use “<mark style="color:blue;">[https://yourdomain:port/voice\\\_liveness.php](https://docs.accurascan.com/language/docker/https:/yourdomain:port/voice\\_liveness.php)</mark>” (POST request) to access the API, an example post request is shown below.

<mark style="color:green;">`POST`</mark> `https://yourdomain:port/voice_liveness.php`

**Request Body**

| Name     | Type | Description                       |
| -------- | ---- | --------------------------------- |
| source\* | file | Upload your .wav voice image file |
| target\* | file | Upload your .wav voice image file |

{% tabs %}
{% tab title="200: OK An example response is shown in the image below ​" %}

{% endtab %}
{% endtabs %}

<figure><img src="/files/nBr6UPqkvioIUiX9lyoz" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The Preferred Score describes the matching percentage between the source and target voice files.
{% endhint %}


# ID Scan & OCR (Multi Language Support)

OCR (Optical Character Recognition) solution extracts the user fields from the image provided and Authenticates the user.

{% embed url="<https://drive.google.com/file/d/1vMO7PSQDOfrEWh7RCfysGtHfyOmivE0z/view?usp=sharing>" %}

### Steps to Install and Run the OCR Docker

#### Step 1:

Pull AccuraOcr Docker image using the command `docker pull accurascan/ocr:<latest  tag>`

Visit <https://hub.docker.com/r/accurascan/ocr> to check the latest version available<br>

```
docker pull accurascan/ocr:36.0.0
```

#### Step 2:

Run the docker by using the command: `sudo docker run -dp port-you-want-accuraocr-to-run-on:443 -- restart=always accurascan/ocr:<latest tag>`

```
docker run -dp 8448:443 --restart=always
accurascan/ocr:36.0.0
```

{% hint style="info" %}
To generate your Accura Scan license contact <sales@accurascan.com>
{% endhint %}

Upload both Ocr and Mrz license accessing "<mark style="color:blue;">https\://\<yourdomain:port></mark>" using a browser, Example is shown in the image below.

<figure><img src="/files/MrTZ3l1MXya3TurXHOJO" alt=""><figcaption></figcaption></figure>

#### Step 4:

Use <mark style="color:blue;">[https://your-domain-or-ip.com:port/ocr.php](https://docs.accurascan.com/language/docker/https:/your-domain-or-ip.com:port/ocr.php)</mark> (POST request) to access the API, an example post request as shown below.

<mark style="color:green;">`POST`</mark> `https://yourdomain:port/ocr.php`

{% hint style="info" %}
To view country\_code and card\_code for any card visit <https://accurascan.com/documents-supported-api>
{% endhint %}

**Request Body**

> You can either pass image file or an image base64.

| Name                                            | Type           | Description                         |
| ----------------------------------------------- | -------------- | ----------------------------------- |
| country\_code<mark style="color:red;">\*</mark> | COL            | put country\_code of the card image |
| card\_code<mark style="color:red;">\*</mark>    | CLMID          | put card\_code of the card image    |
| scan\_image<mark style="color:red;">\*</mark>   | file           | Upload your image file              |
| image\_base64                                   | text or string | paste your image base 64 here       |

> 200: OK An example response is shown in the image below

<figure><img src="/files/kOgYXMisdaq2cErCiqVT" alt=""><figcaption></figcaption></figure>


# Web Plugin

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Face Plugin</td><td><a href="/pages/GJX64USCzq1y1PZ9AQ96">/pages/GJX64USCzq1y1PZ9AQ96</a></td></tr><tr><td>ID Plugin</td><td><a href="/pages/3CGfXTInMEPAunbEK5ds">/pages/3CGfXTInMEPAunbEK5ds</a></td></tr></tbody></table>


# Face Plugin


# HTML - Vanilla JS

## Accura Face Plugin — Vanilla HTML Integration Guide

This guide walks you through integrating the **Accura Face Plugin** into a standard HTML project using native ES Modules.

***

### Prerequisites

Before proceeding, ensure the following requirement is met:

* **`accura.xml`** — Place your `accura.xml` file in the **same directory** as your `index.html`. This file is required by the plugin to initialize the face detection engine. You can download it from here.

{% file src="/files/MRwhxxZYFOdyrVqnkT4A" %}

***

### Step 1: Implementation

Create an `index.html` file in your project directory and add the following **import and initialization code** inside a `<script type="module">` block.

```html
<script type="module">
  // Import the FacePlugin class directly from the Accura CDN.
  import FacePlugin from "https://unpkg.com/accurafaceplugin/dist/accuramain.js";

  // Declare a variable to hold the active plugin instance.
  // This allows us to safely call destroy() before re-initializing.
  let currentPlugin = null;

  // Destroy any previously active instance before creating a new one.
  // This prevents duplicate camera sessions or memory leaks.
  if (currentPlugin) currentPlugin.destroy();

  // Instantiate the FacePlugin with three required arguments:
  //   1. Path to the accura.xml file (relative to the HTML file)
  //   2. The callback function that receives the captured face image as base64
  //   3. A configuration object to customize UI appearance and detection threshold
  currentPlugin = new FacePlugin(
    "./accura.xml",   // Relative path to the XML license file
    base64Handler,    // Callback invoked upon successful face capture
    {
      threshold: 3,       // Face detection threshold (1–100; higher = stricter)
      textSize: "",       // Overlay instruction text size (leave empty for default)
      textColor: "",      // Overlay instruction text color (leave empty for default)
      textWeight: "",     // Overlay instruction text font weight (leave empty for default)
      textBgColor: "",    // Background color of the text overlay (leave empty for default)
      BodyBgColor: "",    // Background color of the camera viewport (leave empty for default)
    }
  );

  // Start the plugin engine. This opens the camera and begins face detection.
  // The call is wrapped in try/catch to handle permission denials or initialization errors.
  try {
    await currentPlugin.start();
  } catch (error) {
    console.error("Failed to start plugin:", error);
  }
</script>
```

***

### Step 2: Response Handling

When the plugin successfully captures a face, it invokes the **callback function** you provided during instantiation. The callback receives a single object containing a `base64` property — a Data URL string representing the captured facial image encoded in Base64 format.

**What is Base64?** Base64 is a binary-to-text encoding scheme that represents raw image data as an ASCII string. The string is prefixed with a MIME type header (e.g., `data:image/jpeg;base64,...`) followed by the encoded image payload. This format is suitable for direct transmission over HTTP in form fields or JSON bodies.

The following handler demonstrates how to extract that value and forward it to your server-side verification endpoint:

```js
        // This function is invoked automatically by the plugin once a valid face is captured.
        // It receives a destructured object: { base64 } — the raw base64-encoded image string.
        const base64Handler = async ({ base64 }) => {
          console.log("Base64 received:", base64);

          try {
            // Construct a multipart form payload to transmit the image to the server.
            const formData = new FormData();

            // Append the base64 string under the key expected by your backend endpoint.
            formData.append("imagebase64", base64);

            // Dispatch the HTTP POST request to your verification server.
            // Replace "https://ip:port/upload.php" with your actual endpoint URL.
            const response = await fetch("https://ip:port/upload.php", {
              method: "POST",
              body: formData,
            });

            // Parse the JSON response returned by the server.
            const data = await response.json();
            console.log("API Response:", data);

            // Access the liveness/match score from the response payload.
            // The `score` field indicates confidence level of the face verification result.
            if (data && data.score !== undefined) {
              console.log(`Score: ${data.score}`);
            }
          } catch (error) {
            console.error("Error sending to API:", error);
          }
        };
```

***

### Step 3: Demo Implementation

The following is a complete, ready-to-use `index.html` file. Copy and paste it as-is into your project.

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Accura Face Plugin - HTML Demo</title>
    <style></style>
  </head>
  <body>
    <script type="module">
        // Import the FacePlugin class directly from the Accura CDN.
        import FacePlugin from "https://unpkg.com/accurafaceplugin/dist/accuramain.js";

        // Declare a variable to hold the active plugin instance.
        // This allows us to safely call destroy() before re-initializing.
        let currentPlugin = null;

        // This function is invoked automatically by the plugin once a valid face is captured.
        // It receives a destructured object: { base64 } — the raw base64-encoded image string.
        const base64Handler = async ({ base64 }) => {
          console.log("Base64 received:", base64);

          try {
            // Construct a multipart form payload to transmit the image to the server.
            const formData = new FormData();

            // Append the base64 string under the key expected by your backend endpoint.
            formData.append("imagebase64", base64);

            // Dispatch the HTTP POST request to your verification server.
            // Replace "https://ip:port/upload.php" with your actual endpoint URL.
            const response = await fetch("https://ip:port/upload.php", {
              method: "POST",
              body: formData,
            });

            // Parse the JSON response returned by the server.
            const data = await response.json();
            console.log("API Response:", data);

            // Access the liveness/match score from the response payload.
            // The `score` field indicates confidence level of the face verification result.
            if (data && data.score !== undefined) {
              console.log(`Score: ${data.score}`);
            }
          } catch (error) {
            console.error("Error sending to API:", error);
          }
        };

      // Destroy any previously active instance before creating a new one.
      // This prevents duplicate camera sessions or memory leaks.
      if (currentPlugin) currentPlugin.destroy();

      // Instantiate the FacePlugin with three required arguments:
      //   1. Path to the accura.xml file (relative to the HTML file)
      //   2. The callback function that receives the captured face image as base64
      //   3. A configuration object to customize UI appearance and detection threshold
      currentPlugin = new FacePlugin(
        "./accura.xml",   // Relative path to the XML license file
        base64Handler,    // Callback invoked upon successful face capture
        {
          threshold: 3,       // Face detection threshold (1–100; higher = stricter)
          textSize: "",       // Overlay instruction text size (leave empty for default)
          textColor: "",      // Overlay instruction text color (leave empty for default)
          textWeight: "",     // Overlay instruction text font weight (leave empty for default)
          textBgColor: "",    // Background color of the text overlay (leave empty for default)
          BodyBgColor: "",    // Background color of the camera viewport (leave empty for default)
        }
      );

      // Start the plugin engine. This opens the camera and begins face detection.
      // The call is wrapped in try/catch to handle permission denials or initialization errors.
      try {
        await currentPlugin.start();
      } catch (error) {
        console.error("Failed to start plugin:", error);
      }
    </script>
  </body>
</html>
```

> **Note:** Since this uses ESM imports, you must serve the file via a local server (e.g., using Live Server in VS Code or `npx serve .`). Opening the file directly via `file://` may cause CORS or module issues.


# React

## Accura Face Plugin — React Integration Guide

This guide walks you through integrating the **Accura Face Plugin** into a React project built with Vite.

***

### Prerequisites

Before proceeding, ensure the following requirement is met:

* **`accura.xml`** — Place your `accura.xml` file in the **`public/`** folder of your project as `public/accura.xml`. This file is required by the plugin to initialize the face detection engine. You can download it from here.

{% file src="/files/UYRDaSONHcarfdtCAsOg" %}

> The `public/` directory is served as static assets in Vite-based projects, making the file accessible at runtime via the path `/accura.xml`.

***

### Step 1: Initialize Project

If you do not have an existing React project, scaffold one using Vite:

```bash
npm create vite@latest my-face-app -- --template react
cd my-face-app
npm install
```

***

### Step 2: Install Plugin

Install the Accura Face Plugin package from the npm registry:

```bash
npm install accurafaceplugin
```

***

### Step 3: TypeScript Support *(Recommended)*

If your project uses TypeScript, create a type declaration file at `src/types.d.ts` to suppress module resolution warnings and enable IDE intellisense:

```typescript
declare module 'accurafaceplugin' {
  export default class FacePlugin {
    constructor(
      xmlPath: string,
      callback: (data: { base64: string }) => void,
      config: Record<string, string | number>
    );
    start(): Promise<void>;
    destroy(): void;
  }
}
```

Ensure this file is included in your `tsconfig.app.json`'s `include` array:

```json
"include": ["src"]
```

***

### Step 4: Implementation

Create a dedicated component file at `src/FaceScanner.jsx` (or `.tsx` for TypeScript). The following snippet shows only the **plugin import and initialization** logic:

```jsx
import { useEffect, useRef } from 'react';

const FaceScanner = () => {
    const pluginRef = useRef(null);    // Holds the active plugin instance across renders
    const initialized = useRef(false); // Guards against double-initialization in Strict Mode

    useEffect(() => {
        // Prevent re-initialization caused by React Strict Mode's double-invocation behavior
        if (initialized.current) return;
        initialized.current = true;

        const initPlugin = async () => {
            // Dynamically import the plugin to ensure it runs only in the browser context.
            // This prevents errors in SSR environments and improves initial bundle performance.
            const { default: FacePlugin } = await import('accurafaceplugin');

            // Instantiate FacePlugin with the license path, capture callback, and config options.
            pluginRef.current = new FacePlugin(
                "/accura.xml",   // Publicly accessible path to the license file (from public/)
                base64Handler,   // Callback function invoked on successful face capture
                {
                    threshold: 3,       // Detection threshold (1–100; higher = stricter)
                    textSize: "",       // Instruction overlay text size (default if empty)
                    textColor: "",      // Instruction overlay text color (default if empty)
                    textWeight: "",     // Instruction overlay font weight (default if empty)
                    textBgColor: "",    // Instruction overlay background color (default if empty)
                    BodyBgColor: "",    // Camera viewport background color (default if empty)
                }
            );

            // Initialize the camera and begin the face detection lifecycle.
            await pluginRef.current.start();
        };

        initPlugin().catch(console.error);

        // Cleanup: destroy the plugin instance when the component unmounts
        // to release camera resources and prevent memory leaks.
        return () => {
            if (pluginRef.current) {
                pluginRef.current.destroy();
            }
        };
    }, []);

    return <></>;
};
```

***

### Step 5: Response Handling

When the plugin successfully detects and captures a face, it fires the **`base64Handler`** callback. This callback receives a single argument — an object containing a `base64` property. The value is a Data URL string encoding the captured face image in Base64 format (e.g., `data:image/jpeg;base64,/9j/...`).

**What is Base64?** Base64 is a binary-to-text encoding mechanism that expresses raw binary image data as a printable ASCII string. The prefix (e.g., `data:image/jpeg;base64,`) identifies the MIME type of the image. The remainder is the encoded pixel data, which can be directly transmitted over HTTP without binary transfer protocols.

The following handler demonstrates extracting the value and forwarding it to a remote verification endpoint:

```jsx
// Called automatically by the plugin upon successful face capture.
// Receives: { base64 } — a complete Data URL string of the captured face image.
const base64Handler = async ({ base64 }) => {
    console.log("Base64 received:", base64);

    try {
        // Build a multipart form payload for HTTP transmission.
        const formData = new FormData();

        // Attach the base64-encoded image string under the key your backend expects.
        formData.append("imagebase64", base64);

        // Submit the payload to your server-side verification endpoint via POST.
        // Replace the URL with your actual backend address.
        const response = await fetch("https://ip:port/upload.php", {
            method: "POST",
            body: formData,
        });

        // Deserialize the JSON response from the verification server.
        const data = await response.json();
        console.log("API Response:", data);

        // Read the liveness/match confidence score from the response.
        if (data && data.score !== undefined) {
            console.log(`Score: ${data.score}`);
        }
    } catch (error) {
        console.error("Error sending to API:", error);
    }
};
```

***

### Step 6: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `src/FaceScanner.jsx`. The original logic is preserved exactly as-is.

```jsx
import React, { useEffect, useRef, useState } from 'react';
import type FacePlugin from "accurafaceplugin";

const FaceScanner = () => {
    const [isReady, setIsReady] = useState(false);
    const pluginRef = useRef<FacePlugin | null>(null);

    useEffect(() => {
        const initPlugin = async () => {
            try {
                // Load plugin dynamically for SSR safety and clean bundling
                const { default: FacePlugin } = await import('accurafaceplugin');

                const base64Handler = async ({ base64 }: { base64: string }) => {
                    console.log("Base64 received:", base64);

                    try {
                        const formData = new FormData();
                        formData.append("imagebase64", base64);
                        // formData.append("image2base64", base64);

                        const response = await fetch(
                            "https://ip:port/upload.php",
                            {
                                method: "POST",
                                body: formData,
                            },
                        );

                        const data = await response.json();
                        console.log("API Response:", data);

                        // Display the score on UI
                        if (data && data.score !== undefined) {
                            console.log(`Score: ${data.score}`);
                        }
                    } catch (error) {
                        console.error("Error sending to API:", error);
                    }
                };

                pluginRef.current = new FacePlugin(
                    "/accura.xml", // Path to license in public folder
                    base64Handler,
                    {
                        threshold: 3,
                        textSize: "",
                        textColor: "",
                        textWeight: "",
                        textBgColor: "",
                        BodyBgColor: "",
                    }
                );

                await pluginRef.current.start();
                setIsReady(true);
            } catch (error) {
                console.error("Plugin initialization failed:", error);
            }
        };

        initPlugin();

        // Cleanup on unmount
        return () => {
            if (pluginRef.current) {
                pluginRef.current.destroy();
            }
        };
    }, []);

    return (
        <></>
    );
};

export default FaceScanner;
```

***

### Step 7: Usage

Import and render the `FaceScanner` component in your `App.jsx`:

```jsx
import FaceScanner from './FaceScanner';

export default function App() {
  return (
    <div className="App">
      <FaceScanner />
    </div>
  );
}
```

> **Note:** Remove the `<StrictMode>` wrapper from `main.jsx` or `main.tsx` if present, as React Strict Mode invokes lifecycle hooks twice in development, which can cause duplicate plugin initialization.

***

### Step 8: Running the Project

```bash
npm run dev
```


# Nextjs

## Accura Face Plugin — Next.js Integration Guide

This guide walks you through integrating the **Accura Face Plugin** into a Next.js project using the App Router.

***

### Prerequisites

Before proceeding, ensure the following requirement is met:

* **`accura.xml`** — Place your `accura.xml` file in the **`public/`** folder of your project as `public/accura.xml`. This file is required by the plugin to initialize the face detection engine. You can download it from here.&#x20;

{% file src="/files/AZ59uaCj1J7ouL8F2RM6" %}

### Step 1: Initialize Project

If you do not have an existing Next.js project, create one using the official CLI:

```bash
npx create-next-app@latest my-face-app
cd my-face-app
```

***

### Step 2: Install Plugin

Install the Accura Face Plugin package from the npm registry:

```bash
npm install accurafaceplugin
```

***

### Step 3: TypeScript Support

Since the `accurafaceplugin` package does not ship with TypeScript declarations, create a type definition file at the project root to resolve module errors and enable type checking:

```typescript
// types.d.ts (place in the project root)
declare module 'accurafaceplugin' {
  export default class FacePlugin {
    constructor(
      xmlPath: string,
      callback: (data: { base64: string }) => void,
      config: Record<string, string | number>
    );
    start(): Promise<void>;
    destroy(): void;
  }
}
```

Ensure this file is referenced in your `tsconfig.json`'s `include` array:

```json
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types.d.ts"]
```

***

### Step 4: Implementation

Create `components/FaceScanner.tsx`. The snippet below demonstrates only the **plugin import and instantiation** — the minimal code required to activate the face detection engine in a Next.js client component:

```tsx
"use client"; // Required: marks this as a Client Component for browser-only execution

import { useEffect, useRef } from "react";
import type FacePlugin from "accurafaceplugin";

export default function FaceScanner() {
  const pluginRef = useRef<FacePlugin | null>(null); // Persists the plugin instance across renders
  const initialized = useRef<boolean>(false);         // Prevents double-init from React Strict Mode

  useEffect(() => {
    // Exit early if the plugin has already been initialized
    if (initialized.current) return;
    initialized.current = true;

    // Dynamically import the plugin at runtime to avoid SSR-related errors.
    // Next.js renders components on the server by default; browser APIs
    // (camera, DOM) are unavailable there. Dynamic import defers execution
    // to the client side only.
    import("accurafaceplugin").then((Module) => {
      const FacePlugin = Module.default;

      // Instantiate the plugin with the license path, capture callback, and UI configuration.
      pluginRef.current = new FacePlugin(
        "/accura.xml",   // Resolves to public/accura.xml at runtime
        base64Handler,   // Invoked automatically when a valid face is captured
        {
          threshold: 3,       // Detection strictness level (1–100)
          textSize: "",       // Overlay text size (uses default when empty)
          textColor: "",      // Overlay text color (uses default when empty)
          textWeight: "",     // Overlay text font weight (uses default when empty)
          textBgColor: "",    // Overlay text background (uses default when empty)
          BodyBgColor: "",    // Viewport background color (uses default when empty)
        }
      );

      // Launch the camera interface and begin the face detection session.
      pluginRef.current.start().then(() => {
        console.log("Accura Plugin Ready");
      });
    }).catch(err => {
      console.error("Failed to load FacePlugin:", err);
    });

    // Cleanup: invoked when the component unmounts (e.g., page navigation).
    // Ensures the camera stream is released and all plugin resources are freed.
    return () => {
      if (pluginRef.current) {
        pluginRef.current.destroy();
      }
    };
  }, []);

  return <></>;
}
```

***

### Step 5: Response Handling

Upon a successful face capture, the plugin invokes the `base64Handler` callback asynchronously. The callback receives a single argument — an object with a `base64` property containing the captured image encoded as a Base64 Data URL string (e.g., `data:image/jpeg;base64,/9j/...`).

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. The prefix segment (e.g., `data:image/jpeg;base64,`) conveys the MIME type, while the remainder is the encoded image payload. This format enables safe and seamless transmission of binary content over text-based protocols such as HTTP multipart form submissions.

The following handler demonstrates forwarding the captured image to a remote verification endpoint:

```tsx
// Invoked by the plugin upon each successful face capture event.
// Receives: { base64 } — a complete Data URL of the captured face image.
const base64Handler = async ({ base64 }: { base64: string }) => {
  console.log("Base64 received:", base64);

  try {
    // Compose a multipart form body to carry the base64-encoded image.
    const formData = new FormData();

    // Attach the image string under the field name expected by your backend.
    formData.append("imagebase64", base64);

    // Send the payload to your server-side face verification endpoint.
    // Replace with your actual backend host and path.
    const response = await fetch("https://ip:port/upload.php", {
      method: "POST",
      body: formData,
    });

    // Parse the JSON body of the server response.
    const data = await response.json();
    console.log("API Response:", data);

    // Inspect the liveness/match score returned by the verification service.
    if (data?.score !== undefined) {
      console.log(`Score: ${data.score}`);
    }
  } catch (error) {
    console.error("Error sending to API:", error);
  }
};
```

***

### Step 6: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `components/FaceScanner.tsx`. The original logic is preserved exactly as-is.

```tsx

"use client";

import { useEffect, useRef } from "react";
import type FacePlugin from "accurafaceplugin"; 

export default function FaceScanner() {
  const pluginRef = useRef<FacePlugin | null>(null);
  const initialized = useRef<boolean>(false);


  const base64Handler = async ({ base64 }: { base64: string }) => {
    console.log("Base64 received:", base64);

    try {
      const formData = new FormData();
      formData.append("imagebase64", base64);

      const response = await fetch("https://ip:port/upload.php", {
        method: "POST",
        body: formData,
      });

      const data = await response.json();
      console.log("API Response:", data);

      if (data?.score !== undefined) {
        console.log(`Score: ${data.score}`);
      }
    } catch (error) {
      console.error("Error sending to API:", error);
    }
  };

  useEffect(() => {
    if (initialized.current) return;
    initialized.current = true;

    import("accurafaceplugin").then((Module) => {
      const FacePlugin = Module.default;


      pluginRef.current = new FacePlugin(
        "/accura.xml",
        base64Handler,
        {
          threshold: 3,
          textSize: "",
          textColor: "",
          textWeight: "",
          textBgColor: "",
          BodyBgColor: "",
        }
      );


      pluginRef.current.start().then(() => {
        console.log("Accura Plugin Ready");
      });
    }).catch(err => {
      console.error("Failed to load FacePlugin:", err);
    });


    return () => {
      if (pluginRef.current) {
        pluginRef.current.destroy();
      }
    };
  }, []);

  return (
    <></>
  );
}
```

***

### Step 7: Usage

Import and render the component in your `app/page.tsx`:

```tsx
import FaceScanner from "./components/FaceScanner";

export default function Home() {
  return (
    <main>
      <FaceScanner />
    </main>
  );
}
```

***

### Step 8: Running the Project

```bash
npm run dev
```


# Angular

## Accura Face Plugin — Angular Integration Guide

This guide walks you through integrating the **Accura Face Plugin** into an Angular project (v17+) using standalone components.

***

### Prerequisites

Before proceeding, ensure the following requirement is met:

* **`accura.xml`** — Place your `accura.xml` license file in the **`public/`** folder of your project as `public/accura.xml`. This file is required by the plugin to initialize the face detection engine. You can download it from here.&#x20;

{% file src="/files/o2j8mdwAz97PfiXxilS5" %}

***

### Step 1: Initialize Project

Create a new Angular project with standalone component architecture. When prompted, select **No** for Server-Side Rendering (SSR):

```bash
npx ng new my-face-app --standalone
cd my-face-app
npm install
```

After scaffolding, open `angular.json` and ensure SSR and prerendering are explicitly disabled:

```json
"options": {
  "prerender": false,
  "ssr": false
}
```

***

### Step 2: Install Plugin

Install the Accura Face Plugin package from the npm registry:

```bash
npm install accurafaceplugin
```

***

### Step 3: TypeScript Support

Angular enforces strict TypeScript compilation. Create a type declaration file at `src/types.d.ts` to declare the module and suppress resolution errors:

```typescript
declare module 'accurafaceplugin';
```

Ensure this file is included in your `tsconfig.app.json`'s `include` array:

```json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": [
      "node"
    ]
  },
  "files": [
    "src/main.ts",
    "src/main.server.ts",
    "server.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}
```

***

### Step 4: Implementation

Generate the scanner component or create it manually at `src/app/face-scanner/face-scanner.component.ts`. The following snippet shows only the **plugin import and initialization** logic:

```typescript
import { Component, OnInit, OnDestroy } from '@angular/core';

export class FaceScannerComponent implements OnInit, OnDestroy {
  plugin: any = null;

  async ngOnInit() {
    // Dynamically import the plugin inside ngOnInit to ensure execution occurs
    // only in the browser context. Angular may run component lifecycle hooks
    // during server-side rendering; dynamic import defers plugin loading safely.
    const { default: FacePlugin } = await import('accurafaceplugin');

    // Instantiate the plugin with:
    //   1. The license file path (served from public/)
    //   2. The capture callback invoked upon face detection
    //   3. A configuration object for UI and detection sensitivity
    this.plugin = new FacePlugin(
      '/accura.xml',   // Resolves to public/accura.xml at runtime
      base64Handler,   // Fired automatically when a valid face is captured
      {
        threshold: 3,       // Detection sensitivity (1–100; higher = stricter)
        textSize: '',       // Overlay text size (default if empty)
        textColor: '',      // Overlay text color (default if empty)
        textWeight: '',     // Overlay font weight (default if empty)
        textBgColor: '',    // Overlay background color (default if empty)
        BodyBgColor: '',    // Viewport background color (default if empty)
      }
    );

    // Launch the camera and commence the face detection session.
    await this.plugin.start();
  }

  // Angular's destruction lifecycle hook — destroy the plugin instance
  // to free camera resources when the component is removed from the DOM.
  ngOnDestroy() {
    if (this.plugin) {
      this.plugin.destroy();
    }
  }
}
```

***

### Step 5: Response Handling

When the plugin captures a valid face image, it invokes the **`base64Handler`** callback with an object containing a `base64` property — a Data URL string representing the face image encoded in Base64 format (e.g., `data:image/jpeg;base64,/9j/...`).

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. The prefix segment (e.g., `data:image/jpeg;base64,`) conveys the MIME type, while the remainder is the encoded image payload. This format enables seamless transmission of binary content over text-based HTTP protocols without requiring binary transport mechanisms.

The following handler demonstrates forwarding the captured image to a remote verification endpoint:

```typescript
// Invoked automatically by the plugin upon each successful face capture.
// Receives: { base64 } — a complete Data URL of the captured face image.
const base64Handler = async ({ base64 }: { base64: string }) => {
  console.log('Base64 received:', base64);

  try {
    // Compose a multipart form body to transmit the base64-encoded image.
    const formData = new FormData();

    // Attach the image string under the field name your backend expects.
    formData.append('imagebase64', base64);

    // Post the payload to your server-side verification endpoint.
    // Replace the URL with your actual backend host and path.
    const response = await fetch('https://ip:port/upload.php', {
      method: 'POST',
      body: formData,
    });

    // Deserialize the JSON-encoded response from the verification server.
    const data = await response.json();
    console.log('API Response:', data);

    // Extract the liveness/match confidence score from the response.
    if (data && data.score !== undefined) {
      console.log(`Score: ${data.score}`);
    }
  } catch (error) {
    console.error('Error sending to API:', error);
  }
};
```

***

### Step 6: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `src/app/face-scanner/face-scanner.component.ts`. The original logic is preserved exactly as-is.

```typescript
import {
  Component,
  OnInit,
  OnDestroy,
} from '@angular/core';
import { CommonModule, isPlatformBrowser } from '@angular/common';

@Component({
  selector: 'app-face-scanner',
  standalone: true,
  imports: [CommonModule],
  template: ``,
  styles: [``],
})
export class FaceScannerComponent implements OnInit, OnDestroy {
  ready = false;
  plugin: any = null;

  async ngOnInit() {
    try {
      const { default: FacePlugin } = await import('accurafaceplugin');

      const base64Handler = async ({ base64 }: { base64: string }) => {
        console.log('Base64 received:', base64);

        try {
          const formData = new FormData();
          formData.append('imagebase64', base64);

          const response = await fetch('https://ip:port/upload.php', {
            method: 'POST',
            body: formData,
          });

          const data = await response.json();
          console.log('API Response:', data);

          // Display the score on UI
          if (data && data.score !== undefined) {
            console.log(`Score: ${data.score}`);
          }
        } catch (error) {
          console.error('Error sending to API:', error);
        }
      };

      this.plugin = new FacePlugin('/accura.xml', base64Handler, {
        threshold: 3,
        textSize: '',
        textColor: '',
        textWeight: '',
        textBgColor: '',
        BodyBgColor: '',
      });

      await this.plugin.start();
      this.ready = true;
    } catch (error) {
      console.error('Angular Initialization Error:', error);
    }
  }

  ngOnDestroy() {
    if (this.plugin) {
      this.plugin.destroy();
    }
  }
}
```

***

### Step 7: Usage

Register and render the scanner component in `app.component.ts`:

```typescript
import { Component } from '@angular/core';
import { FaceScannerComponent } from './face-scanner/face-scanner.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [FaceScannerComponent],
  template: `<app-face-scanner></app-face-scanner>`
})
export class AppComponent {
  title = 'angular-face';
}
```

***

### Step 8: Running the Project

```bash
npm start
```


# Vue

## Accura Face Plugin — Vue 3 Integration Guide

This guide walks you through integrating the **Accura Face Plugin** into a Vue 3 project built with Vite.

***

### Prerequisites

Before proceeding, ensure the following requirement is met:

* **`accura.xml`** — Place your `accura.xml` license file in the **`public/`** folder of your project as `public/accura.xml`. This file is required by the plugin to initialize the face detection engine. You can download it from here.

{% file src="/files/bOBUket0GHd3RpNHJvnv" %}

***

### Step 1: Initialize Project

If you do not have an existing Vue 3 project, scaffold one using Vite:

```bash
npm create vite@latest my-face-app -- --template vue
cd my-face-app
npm install
```

***

### Step 2: Install Plugin

Install the Accura Face Plugin package from the npm registry:

```bash
npm install accurafaceplugin
```

***

### Step 3: Implementation

Create a dedicated scanner component at `components/FaceScanner.vue`. The following snippet shows only the **plugin import and initialization** logic:

```vue
<script setup>
import { onMounted, onUnmounted } from 'vue';

let plugin = null; // Holds the active plugin instance for lifecycle management

onMounted(async () => {
  // Dynamically import the plugin inside onMounted to guarantee browser-only execution.
  // Vue's onMounted lifecycle hook runs exclusively on the client side,
  // making it safe to access browser APIs such as the camera.
  const { default: FacePlugin } = await import('accurafaceplugin');

  // Instantiate the plugin with:
  //   1. The file path (served from public/)
  //   2. The capture callback invoked on successful face detection
  //   3. A configuration object for UI and detection tuning
  plugin = new FacePlugin(
    "/accura.xml",   // Resolves to public/accura.xml at runtime
    base64Handler,   // Fired automatically when the plugin captures a face
    {
      threshold: 3,       // Detection sensitivity (1–100; higher = stricter)
      textSize: "",       // Overlay text size (default if empty)
      textColor: "",      // Overlay text color (default if empty)
      textWeight: "",     // Overlay font weight (default if empty)
      textBgColor: "",    // Overlay background color (default if empty)
      BodyBgColor: "",    // Viewport background color (default if empty)
    }
  );

  // Activate the camera and begin the face detection session.
  await plugin.start();
});

// Release camera resources and destroy the plugin instance when the component unmounts.
onUnmounted(() => {
  if (plugin) {
    plugin.destroy();
  }
});
</script>
```

***

### Step 4: Response Handling

When the plugin captures a valid face, it invokes the **`base64Handler`** callback with an object containing a `base64` property — a Data URL string representing the captured face image encoded in Base64 format (e.g., `data:image/jpeg;base64,/9j/...`).

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. The prefix segment (e.g., `data:image/jpeg;base64,`) conveys the MIME type, while the remainder is the encoded image payload. This format enables safe and seamless transmission over text-based HTTP protocols without requiring binary transfer mechanisms.

The following handler demonstrates forwarding the image to a remote verification endpoint:

```js
// Automatically invoked by the plugin upon a successful face capture event.
// Receives: { base64 } — a complete Data URL of the captured face image.
const base64Handler = async ({ base64 }) => {
    console.log("Base64 received:", base64);

    try {
        // Construct a multipart form payload for HTTP transmission.
        const formData = new FormData();

        // Attach the base64 string under the field key expected by your backend.
        formData.append("imagebase64", base64);

        // Dispatch the verification request to your server endpoint.
        // Replace the URL with your actual backend host and path.
        const response = await fetch("https://ip:port/upload.php", {
            method: "POST",
            body: formData,
        });

        // Parse the JSON response returned by the verification server.
        const data = await response.json();
        console.log("API Response:", data);

        // Read the liveness/match confidence score from the response payload.
        if (data && data.score !== undefined) {
            console.log(`Score: ${data.score}`);
        }
    } catch (error) {
        console.error("Error sending to API:", error);
    }
};
```

***

### Step 5: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `components/FaceScanner.vue`. The original logic is preserved exactly as-is.

```vue
<template>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from 'vue';

const isReady = ref(false);
let plugin = null;

onMounted(async () => {
  try {
    const { default: FacePlugin } = await import('accurafaceplugin');

    const base64Handler = async ({ base64 }) => {
        console.log("Base64 received:", base64);

        try {
            const formData = new FormData();
            formData.append("imagebase64", base64);

            const response = await fetch(
                "https://ip:port/upload.php",
                {
                    method: "POST",
                    body: formData,
                },
            );

            const data = await response.json();
            console.log("API Response:", data);

            // Display the score on UI
            if (data && data.score !== undefined) {
                console.log(`Score: ${data.score}`);
            }
        } catch (error) {
            console.error("Error sending to API:", error);
        }
    };
    
    plugin = new FacePlugin(
      "/accura.xml",
      base64Handler,
      {
        threshold: 3,
        textSize: "",
        textColor: "",
        textWeight: "",
        textBgColor: "",
        BodyBgColor: "",
      }
    );
    
    await plugin.start();
    isReady.value = true;
  } catch (error) {
    console.error("Plugin failed to start:", error);
  }
});

onUnmounted(() => {
  if (plugin) {
    plugin.destroy();
  }
});
</script>

<style scoped>

</style>
```

***

### Step 6: Usage

Import and use the component in `App.vue`:

```vue
<script setup>
import FaceScanner from './components/FaceScanner.vue';
</script>

<template>
  <FaceScanner />
</template>
```

***

### Step 7: Running the Project

```bash
npm run dev
```


# Svelte

## Accura Face Plugin — Svelte Integration Guide

This guide walks you through integrating the **Accura Face Plugin** into a Svelte project built with Vite.

***

### Prerequisites

Before proceeding, ensure the following requirement is met:

* **`accura.xml`** — Place your `accura.xml` license file in the **`public/`** folder (Vite) or **`static/`** folder (SvelteKit) as `public/accura.xml` or `static/accura.xml` respectively. This file is required by the plugin to initialize the face detection engine. You can download it from here.

{% file src="/files/C1HSWtEDLSipZdnOKbNP" %}

***

### Step 1: Initialize Project

If you do not have an existing Svelte project, scaffold one using Vite:

```bash
npm create vite@latest my-face-app -- --template svelte
cd my-face-app
npm install
```

***

### Step 2: Install Plugin

Install the Accura Face Plugin package from the npm registry:

```bash
npm install accurafaceplugin
```

***

### Step 3: Implementation

Create a dedicated scanner component at `src/lib/FaceScanner.svelte`. The following snippet shows only the **plugin import and initialization** logic:

```svelte
<script>
  import { onMount, onDestroy } from 'svelte';

  let plugin = null; // Holds the active plugin instance for lifecycle management

  onMount(async () => {
    // Dynamically import the plugin inside onMount to guarantee browser-only execution.
    // Svelte's onMount lifecycle hook runs exclusively on the client side,
    // making it safe to access browser APIs such as the camera.
    const { default: FacePlugin } = await import('accurafaceplugin');

    // Instantiate the plugin with:
    //   1. The license file path (served from public/ or static/)
    //   2. The capture callback invoked on successful face detection
    //   3. A configuration object for UI and detection tuning
    plugin = new FacePlugin(
      "/accura.xml",   // Resolves to public/accura.xml (Vite) or static/accura.xml (SvelteKit)
      base64Handler,   // Fired automatically when the plugin captures a valid face
      {
        threshold: 3,       // Detection sensitivity (1–100; higher = stricter)
        textSize: "",       // Overlay text size (default if empty)
        textColor: "",      // Overlay text color (default if empty)
        textWeight: "",     // Overlay font weight (default if empty)
        textBgColor: "",    // Overlay background color (default if empty)
        BodyBgColor: "",    // Viewport background color (default if empty)
      }
    );

    // Activate the camera and begin the face detection session.
    await plugin.start();
  });

  // Release camera resources and destroy the plugin when the component is removed from the DOM.
  onDestroy(() => {
    if (plugin) {
      plugin.destroy();
    }
  });
</script>
```

***

### Step 4: Response Handling

When the plugin captures a valid face, it invokes the **`base64Handler`** callback with an object containing a `base64` property — a Data URL string representing the captured face image encoded in Base64 format (e.g., `data:image/jpeg;base64,/9j/...`).

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. The prefix segment (e.g., `data:image/jpeg;base64,`) conveys the MIME type, while the remainder is the encoded image payload. This format enables seamless transmission of binary content over text-based HTTP protocols without requiring binary transport mechanisms.

The following handler demonstrates forwarding the captured image to a remote verification endpoint:

```js
// Invoked automatically by the plugin upon each successful face capture event.
// Receives: { base64 } — a complete Data URL of the captured face image.
const base64Handler = async ({ base64 }) => {
    console.log("Base64 received:", base64);

    try {
        // Construct a multipart form payload for HTTP transmission.
        const formData = new FormData();

        // Attach the base64 string under the field key expected by your backend.
        formData.append("imagebase64", base64);

        // Dispatch the verification request to your server endpoint.
        // Replace the URL with your actual backend host and path.
        const response = await fetch("https://ip:port/upload.php", {
            method: "POST",
            body: formData,
        });

        // Parse the JSON response returned by the verification server.
        const data = await response.json();
        console.log("API Response:", data);

        // Read the liveness/match confidence score from the response payload.
        if (data && data.score !== undefined) {
            console.log(`Score: ${data.score}`);
        }
    } catch (error) {
        console.error("Error sending to API:", error);
    }
};
```

***

### Step 5: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `src/lib/FaceScanner.svelte`. The original logic is preserved exactly as-is.

```svelte
<script>
  import { onMount, onDestroy } from 'svelte';
  
  let container;
  let plugin = null;
  let isReady = false;

  onMount(async () => {
    try {
      // Dynamic import for client-side only execution
      const { default: FacePlugin } = await import('accurafaceplugin');

      const base64Handler = async ({ base64 }) => {
        console.log("Base64 received:", base64);

        try {
            const formData = new FormData();
            formData.append("imagebase64", base64);

            const response = await fetch(
                "https://ip:port/upload.php",
                {
                    method: "POST",
                    body: formData,
                },
            );

            const data = await response.json();
            console.log("API Response:", data);

            // Display the score on UI
            if (data && data.score !== undefined) {
                console.log(`Score: ${data.score}`);
            }
        } catch (error) {
            console.error("Error sending to API:", error);
        }
    };
      
      plugin = new FacePlugin(
        "/accura.xml",
        base64Handler,
        {
        threshold: 3,
        textSize: "",
        textColor: "",
        textWeight: "",
        textBgColor: "",
        BodyBgColor: "",
      }
      );
      
      await plugin.start();
      isReady = true;
    } catch (error) {
      console.error("Svelte Plugin Error:", error);
    }
  });

  onDestroy(() => {
    if (plugin) {
      plugin.destroy();
    }
  });
</script>
```

***

### Step 6: Usage

Import and render the component in `App.svelte`:

```svelte
<script>
  import FaceScanner from './lib/FaceScanner.svelte';
</script>

<FaceScanner />
```

***

### Step 7: Running the Project

```bash
npm run dev
```


# ID Plugin


# HTML - Vanilla JS

## Accura IDScan Plugin — Vanilla HTML Integration Guide

This guide walks you through integrating the **Accura IDScan Plugin** into a standard HTML project using native ES Modules.

### Step 1: Implementation

Create an `index.html` file in your project directory and add the following **import and initialization code** inside a `<script type="module">` block.

```html
<script type="module">
  // Import the IDCardPlugin class directly from the Accura CDN using ESM syntax.
  // No npm install is required for plain HTML projects.
  import IDCardPlugin from "https://unpkg.com/accuraidscanplugin/dist/accuramain.js";

  // Declare a variable to hold the active plugin instance.
  // This allows us to safely call destroy() before re-initializing.
  let currentPlugin = null;

  // Destroy any previously active instance before creating a new one.
  // This prevents duplicate camera sessions or memory leaks.
  if (currentPlugin) currentPlugin.destroy();

  // Instantiate the IDCardPlugin with two required arguments:
  //   1. The callback function that receives captured card images as base64 Data URLs
  //   2. A configuration object specifying the target card and UI appearance
  currentPlugin = new IDCardPlugin(
    handleCapture,   // Callback invoked upon successful ID card scan completion
    {
      countryCode: "UGA",    // country code of the card being scanned
      cardCode: "UGNIDF",    // card code for the front side of the ID
      topTextSize: "",       // Size of the top instruction overlay text (default if empty)
      topTextColor: "",      // Color of the top instruction overlay text (default if empty)
      topTextWeight: "",     // Font weight of the top instruction text (default if empty)
      bottomTextSize: "",    // Size of the bottom instruction overlay text (default if empty)
      bottomTextColor: "",   // Color of the bottom instruction overlay text (default if empty)
      bottomTextWeight: "",  // Font weight of the bottom instruction text (default if empty)
    }
  );

  // Start the plugin engine. This opens the camera and begins card detection.
  try {
    await currentPlugin.start();
  } catch (error) {
    console.error("Failed to start plugin:", error);
  }
</script>
```

***

### Step 2: Response Handling

When the plugin completes an ID card scan, it invokes the **`handleCapture`** callback with a single payload object. This object may contain one or both of the following properties:

| Property | Type     | Description                                                     |
| -------- | -------- | --------------------------------------------------------------- |
| `front`  | `string` | Base64 Data URL of the front side of the ID card                |
| `back`   | `string` | Base64 Data URL of the back side of the ID card (if applicable) |

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. Each captured card image is delivered as a Data URL string (e.g., `data:image/jpeg;base64,/9j/...`), which combines the MIME type prefix with the encoded image payload. Before transmitting to a server, this string must be decoded back into binary form (a `Blob`) to construct a valid multipart HTTP request.

```js
const base64ToBlob = (base64DataURL) => {
          // Split the Data URL at the comma to separate the metadata header from the payload.
          // meta  = "data:image/jpeg;base64"
          // content = "/9j/4AAQSkZJRgAB..."
          const [meta, content] = base64DataURL.split(",");

          // Extract the MIME type from the header segment (e.g., "image/jpeg").
          const mimeMatch = meta.match(/:(.*?);/);
          const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";

          // Decode the Base64-encoded string into raw binary data using atob().
          const binary = atob(content);

          // Allocate a typed binary array of the same length as the decoded data.
          const array = new Uint8Array(binary.length);

          // Populate the array by converting each character to its Unicode code point —
          // effectively reconstructing the original binary image bytes.
          for (let i = 0; i < binary.length; i++) {
              array[i] = binary.charCodeAt(i);
          }

          // Return a Blob with the correct MIME type for proper server-side handling.
          return new Blob([array], { type: mime });
      };

      // Dispatches a scanned card image (as a Blob) to the server-side verification endpoint.
      const sendToAPI = async (blob, isface, card_code, filename) => {
          const formData = new FormData();
          formData.append("scan_image", blob, filename);  // The binary image file
          formData.append("isface", isface);              // "front" or "back" — identifies card side
          formData.append("country_code", "UGA");         // Country code of the ID Card
          formData.append("card_code", card_code);        // Card code of ID Card
          formData.append("passport", "false");           // Set "true" if the document is a passport
          formData.append("webcam", "false");             // Set "true" if captured via webcam

          try {
              const response = await fetch("https://ip:port/doc_liveness.php", {
                  method: "POST",
                  body: formData,
              });

              const data = await response.json();
              console.log(`API Response (${isface}):`, data);

              // Inspect the liveness/authenticity score returned by the verification service.
              if (data && data.score !== undefined) {
                  console.log(`Score (${isface}): ${data.score}`);
              }
          } catch (error) {
              console.error(`Error sending ${isface} to API:`, error);
          }
      };

      // Primary capture callback — invoked by the plugin when scanning is complete.
      // Receives: base64 — an object containing front and/or back card image Data URLs.
      const handleCapture = async (base64) => {
          // Process the front side of the card if present in the payload.
          if (base64.front) {
              const frontBlob = base64ToBlob(base64.front); // Convert to binary Blob
              await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
          }

          // Process the back side of the card if present in the payload.
          if (base64.back) {
              const backBlob = base64ToBlob(base64.back);   // Convert to binary Blob
              await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
          }
      };
```

***

### Step 3: Demo Implementation

The following is a complete, ready-to-use `index.html` file. Copy and paste it as-is into your project. **No modifications have been made to the original logic.**

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Accura IDScan Plugin - HTML Demo</title>
    <style></style>
  </head>
  <body>
    <script type="module">
      // Import the IDCardPlugin class directly from the Accura CDN using ESM syntax.
      // No npm install is required for plain HTML projects.
      import IDCardPlugin from "https://unpkg.com/accuraidscanplugin/dist/accuramain.js";

      // Declare a variable to hold the active plugin instance.
      // This allows us to safely call destroy() before re-initializing.
      let currentPlugin = null;

      // The following handler demonstrates the **base64-to-Blob conversion** and subsequent API submission:

      // Utility function: converts a base64 Data URL string into a binary Blob object.
      // This is necessary because multipart form uploads expect raw binary data,
      // not the text-encoded base64 representation.
      const base64ToBlob = (base64DataURL) => {
          // Split the Data URL at the comma to separate the metadata header from the payload.
          // meta  = "data:image/jpeg;base64"
          // content = "/9j/4AAQSkZJRgAB..."
          const [meta, content] = base64DataURL.split(",");

          // Extract the MIME type from the header segment (e.g., "image/jpeg").
          const mimeMatch = meta.match(/:(.*?);/);
          const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";

          // Decode the Base64-encoded string into raw binary data using atob().
          const binary = atob(content);

          // Allocate a typed binary array of the same length as the decoded data.
          const array = new Uint8Array(binary.length);

          // Populate the array by converting each character to its Unicode code point —
          // effectively reconstructing the original binary image bytes.
          for (let i = 0; i < binary.length; i++) {
              array[i] = binary.charCodeAt(i);
          }

          // Return a Blob with the correct MIME type for proper server-side handling.
          return new Blob([array], { type: mime });
      };

      // Dispatches a scanned card image (as a Blob) to the server-side verification endpoint.
      const sendToAPI = async (blob, isface, card_code, filename) => {
          const formData = new FormData();
          formData.append("scan_image", blob, filename);  // The binary image file
          formData.append("isface", isface);              // "front" or "back" — identifies card side
          formData.append("country_code", "UGA");         // Country code of the ID Card
          formData.append("card_code", card_code);        // Card code of ID Card
          formData.append("passport", "false");           // Set "true" if the document is a passport
          formData.append("webcam", "false");             // Set "true" if captured via webcam

          try {
              const response = await fetch("https://ip:port/doc_liveness.php", {
                  method: "POST",
                  body: formData,
              });

              const data = await response.json();
              console.log(`API Response (${isface}):`, data);

              // Inspect the liveness/authenticity score returned by the verification service.
              if (data && data.score !== undefined) {
                  console.log(`Score (${isface}): ${data.score}`);
              }
          } catch (error) {
              console.error(`Error sending ${isface} to API:`, error);
          }
      };

      // Primary capture callback — invoked by the plugin when scanning is complete.
      // Receives: base64 — an object containing front and/or back card image Data URLs.
      const handleCapture = async (base64) => {
          // Process the front side of the card if present in the payload.
          if (base64.front) {
              const frontBlob = base64ToBlob(base64.front); // Convert to binary Blob
              await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
          }

          // Process the back side of the card if present in the payload.
          if (base64.back) {
              const backBlob = base64ToBlob(base64.back);   // Convert to binary Blob
              await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
          }
      };

      // Destroy any previously active instance before creating a new one.
      // This prevents duplicate camera sessions or memory leaks.
      if (currentPlugin) currentPlugin.destroy();

      // Instantiate the IDCardPlugin with two required arguments:
      //   1. The callback function that receives captured card images as base64 Data URLs
      //   2. A configuration object specifying the target card and UI appearance
      currentPlugin = new IDCardPlugin(
        handleCapture,   // Callback invoked upon successful ID card scan completion
        {
          countryCode: "UGA",    // country code of the card being scanned
          cardCode: "UGNIDF",    // card code for the front side of the ID
          topTextSize: "",       // Size of the top instruction overlay text (default if empty)
          topTextColor: "",      // Color of the top instruction overlay text (default if empty)
          topTextWeight: "",     // Font weight of the top instruction text (default if empty)
          bottomTextSize: "",    // Size of the bottom instruction overlay text (default if empty)
          bottomTextColor: "",   // Color of the bottom instruction overlay text (default if empty)
          bottomTextWeight: "",  // Font weight of the bottom instruction text (default if empty)
        }
      );

      // Start the plugin engine. This opens the camera and begins card detection.
      try {
        await currentPlugin.start();
      } catch (error) {
        console.error("Failed to start plugin:", error);
      }
    </script>
  </body>
</html>
```

***

> **Note:** Since this uses ESM imports, you must serve the file via a local server (e.g., using Live Server in VS Code or `npx serve .`). Opening the file directly via `file://` may cause CORS or module issues.


# React

## Accura IDScan Plugin — React Integration Guide

This guide walks you through integrating the **Accura IDScan Plugin** into a React project built with Vite.

### Step 1: Initialize Project

If you do not have an existing React project, scaffold one using Vite:

```bash
npm create vite@latest my-id-app -- --template react
cd my-id-app
npm install
```

***

### Step 2: Install Plugin

Install the Accura IDScan Plugin package from the npm registry:

```bash
npm install accuraidscanplugin
```

***

### Step 3: TypeScript Support *(Recommended)*

If your project uses TypeScript, create a type declaration file at `src/types.d.ts` to suppress module resolution warnings:

```typescript
declare module 'accuraidscanplugin';
```

***

### Step 4: Implementation

Create a dedicated component file `src/IDScanner.jsx` (or `.tsx`). The following snippet shows only the **plugin import and instantiation** logic:

```jsx
import { useEffect, useRef } from 'react';

const IDScanner = () => {
    const pluginRef = useRef(null);       // Holds the active plugin instance across renders
    const initialized = useRef(false);   // Guards against double-initialization in Strict Mode

    useEffect(() => {
        // Prevent re-initialization caused by React Strict Mode's double-invocation behavior
        if (initialized.current) return;
        initialized.current = true;

        // Dynamically import the plugin to ensure it runs only in the browser context.
        // This prevents errors in SSR environments and improves initial bundle performance.
        import("accuraidscanplugin").then((Module) => {
            const IDCardPlugin = Module.default;

            // Instantiate the IDCardPlugin with:
            //   1. The capture callback invoked on successful ID scan completion
            //   2. A configuration object specifying the target card and UI appearance
            pluginRef.current = new IDCardPlugin(
                handleCapture,   // Fired automatically when the scan is complete
                {
                    countryCode: "UGA",    // country code of the card
                    cardCode: "UGNIDF",    // Card code for the front-side ID
                    topTextSize: "",       // Top overlay text size (default if empty)
                    topTextColor: "",      // Top overlay text color (default if empty)
                    topTextWeight: "",     // Top overlay font weight (default if empty)
                    bottomTextSize: "",    // Bottom overlay text size (default if empty)
                    bottomTextColor: "",   // Bottom overlay text color (default if empty)
                    bottomTextWeight: "",  // Bottom overlay font weight (default if empty)
                }
            );

            // Initialize the camera and begin the ID card detection session.
            pluginRef.current.start().then(() => {
                console.log("ID Scanner Engine Ready");
            });
        });

        // Cleanup: destroy the plugin instance when the component unmounts
        return () => {
            if (pluginRef.current) {
                pluginRef.current.destroy();
                pluginRef.current = null;
            }
        };
    }, []);

    return <></>;
};
```

***

### Step 5: Response Handling

When the plugin completes an ID card scan, it invokes the **`handleCapture`** callback with a payload object that may contain one or both of the following properties:

| Property | Type     | Description                                                     |
| -------- | -------- | --------------------------------------------------------------- |
| `front`  | `string` | Base64 Data URL of the front side of the ID card                |
| `back`   | `string` | Base64 Data URL of the back side of the ID card (if applicable) |

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. Each scanned card image is delivered as a Data URL string (e.g., `data:image/jpeg;base64,/9j/...`), combining a MIME type prefix with the encoded image payload. Before transmitting to a server, this string must be decoded back into binary form (a `Blob`) to construct a valid multipart HTTP request.

The following demonstrates the **base64-to-Blob conversion** and API submission:

```jsx
// Utility: converts a base64 Data URL string into a binary Blob.
// MultiPart form uploads require raw binary data rather than base64-encoded text.
const base64ToBlob = (base64DataURL) => {
    // Split at the comma: left = MIME header, right = encoded payload
    const [meta, content] = base64DataURL.split(",");

    // Extract the MIME type (e.g., "image/jpeg") from the header
    const mimeMatch = meta.match(/:(.*?);/);
    const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";

    // Decode the base64 payload back into raw binary characters
    const binary = atob(content);

    // Re-construct binary data as a typed array of unsigned 8-bit integers
    const array = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
        array[i] = binary.charCodeAt(i); // Convert each character to its byte value
    }

    // Wrap the binary array in a Blob with the correct MIME type
    return new Blob([array], { type: mime });
};

// Sends a card image Blob to the server-side verification endpoint.
const sendToAPI = async (blob, isface, card_code, filename) => {
    const formData = new FormData();
    formData.append("scan_image", blob, filename);  // The binary image file
    formData.append("isface", isface);              // "front" or "back"
    formData.append("country_code", "UGA");         // ISO country code
    formData.append("card_code", card_code);        // Card template identifier
    formData.append("passport", "false");           // "true" for passport documents
    formData.append("webcam", "false");             // "true" if captured via webcam

    try {
        const response = await fetch("http://ip:port/doc_liveness.php", {
            method: "POST",
            body: formData,
        });
        const data = await response.json();
        console.log(`API Response (${isface}):`, data);

        if (data && data.score !== undefined) {
            console.log(`Score (${isface}): ${data.score}`);
        }
    } catch (error) {
        console.error(`Error sending ${isface} to API:`, error);
    }
};

// Primary capture callback — invoked by the plugin when scanning is complete.
const handleCapture = async (base64) => {
    if (base64.front) {
        const frontBlob = base64ToBlob(base64.front);
        await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
    }
    if (base64.back) {
        const backBlob = base64ToBlob(base64.back);
        await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
    }
};
```

***

### Step 6: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `src/IDScanner.jsx`. The original logic is preserved exactly as-is.

```jsx
import React, { useEffect, useRef, useState } from 'react';

const IDScanner = () => {
    const pluginRef = useRef<any>(null);
    const [ready, setReady] = useState(false);
    const initialized = useRef(false);

    const base64ToBlob = (base64DataURL: string) => {
        const [meta, content] = base64DataURL.split(",");
        const mimeMatch = meta.match(/:(.*?);/);
        const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";
        const binary = atob(content);
        const array = new Uint8Array(binary.length);
        for (let i = 0; i < binary.length; i++) {
            array[i] = binary.charCodeAt(i);
        }
        return new Blob([array], { type: mime });
    };

    const sendToAPI = async (blob: Blob, isface: string, card_code: string, filename: string) => {
        const formData = new FormData();
        formData.append("scan_image", blob, filename);
        formData.append("isface", isface);
        formData.append("country_code", "UGA");
        formData.append("card_code", card_code);
        formData.append("passport", "false");
        formData.append("webcam", "false");

        try {
            console.log(`Sending ${isface} (${card_code}) to API...`);
            const response = await fetch("http://ip:port/doc_liveness.php", {
                method: "POST",
                body: formData,
            });

            const data = await response.json();
            console.log(`API Response (${isface}):`, data);

            if (data && data.score !== undefined) {
                console.log(`Score (${isface}): ${data.score}`);
            }
        } catch (error) {
            console.error(`Error sending ${isface} to API:`, error);
        }
    };


    const handleCapture = async (base64: any) => {
        console.log("Capture result received:", Object.keys(base64));

        if (base64.front) {
            console.log("Processing front side...");
            const frontBlob = base64ToBlob(base64.front);
            await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
        }
        if (base64.back) {
            console.log("Processing back side...");
            const backBlob = base64ToBlob(base64.back);
            await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
        }
    };

    useEffect(() => {
        if (initialized.current) return;
        initialized.current = true;

        console.log("Initializing ID Scanner plugin...");

        import("accuraidscanplugin").then((Module) => {
            const IDCardPlugin = Module.default;
            console.log("Plugin Module loaded");

            pluginRef.current = new IDCardPlugin(handleCapture, {
                countryCode: "UGA",
                cardCode: "UGNIDF",
                topTextSize: "",
                topTextColor: "",
                topTextWeight: "",
                bottomTextSize: "",
                bottomTextColor: "",
                bottomTextWeight: "",
            } as any);

            console.log("Starting plugin engine...");
            pluginRef.current.start().then(() => {
                console.log("ID Scanner Engine Ready and Camera should be open");
                setReady(true);
            }).catch((err: any) => {
                console.error("Engine failed to start:", err);
            });
        }).catch(err => console.error("Plugin dynamic import failed:", err));

        return () => {
            if (pluginRef.current) {
                console.log("Destroying ID Scanner plugin...");
                pluginRef.current.destroy();
                pluginRef.current = null;
            }
        };
    }, []);


    return (
        <></>
    );
};

export default IDScanner;
```

***

### Step 7: Usage

Import and render the component in `App.jsx`:

```jsx
import IDScanner from './IDScanner';

export default function App() {
  return <IDScanner />;
}
```

> **Note:** Remove the `<StrictMode>` wrapper from `main.jsx` or `main.tsx` if present, as React Strict Mode invokes lifecycle hooks twice in development, which can cause duplicate plugin initialization.

***

### Step 8: Running the Project

```bash
npm run dev
```


# Nextjs

## Accura IDScan Plugin — Next.js Integration Guide

This guide walks you through integrating the **Accura IDScan Plugin** into a Next.js project using the App Router.

### Step 1: Initialize Project

If you do not have an existing Next.js project, create one using the official CLI:

```bash
npx create-next-app@latest my-id-app
cd my-id-app
```

***

### Step 2: Install Plugin

Install the Accura IDScan Plugin package from the npm registry:

```bash
npm install accuraidscanplugin
```

***

### Step 3: TypeScript Support

Since the `accuraidscanplugin` package does not ship with TypeScript declarations, create a type definition file at the project root to resolve module errors:

```typescript
// types.d.ts (place in the project root)
declare module 'accuraidscanplugin';
```

Ensure this file is referenced in your `tsconfig.json`'s `include` array:

```json
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types.d.ts"]
```

***

### Step 4: Implementation

Create `components/IDScanner.tsx`. The snippet below demonstrates only the **plugin import and instantiation** — the minimal code required to activate the ID scan engine in a Next.js client component:

```tsx
"use client"; // Required: marks this as a Client Component for browser-only execution

import { useEffect, useRef } from "react";

export default function IDScanner() {
    const pluginRef = useRef(null);        // Persists the plugin instance across renders
    const initialized = useRef(false);    // Prevents double-init from React Strict Mode

    useEffect(() => {
        // Exit early if the plugin has already been initialized
        if (initialized.current) return;
        initialized.current = true;

        // Dynamically import the plugin at runtime to avoid SSR-related errors.
        // Next.js renders components on the server by default; browser-dependent APIs
        // (camera, DOM manipulation) are unavailable in that environment.
        // Dynamic import defers execution to the client side exclusively.
        import("accuraidscanplugin").then((Module) => {
            const IDCardPlugin = Module.default;

            // Instantiate the plugin with:
            //   1. The capture callback: invoked when scan is complete
            //   2. Configuration: specifies the target country, card template, and UI styling
            pluginRef.current = new IDCardPlugin(
                handleCapture,   // Called automatically upon successful ID card scan
                {
                    countryCode: "UGA",    // country code of the card
                    cardCode: "UGNIDF",    // Card code of the card
                    topTextSize: "",       // Top instruction overlay text size (default if empty)
                    topTextColor: "",      // Top instruction overlay text color (default if empty)
                    topTextWeight: "",     // Top instruction overlay font weight (default if empty)
                    bottomTextSize: "",    // Bottom instruction overlay text size (default if empty)
                    bottomTextColor: "",   // Bottom instruction overlay text color (default if empty)
                    bottomTextWeight: "",  // Bottom instruction overlay font weight (default if empty)
                }
            );

            // Launch the camera interface and begin the ID card detection session.
            pluginRef.current.start().then(() => {
                console.log("ID Scanner Ready");
            });
        }).catch(err => console.error("Plugin failed to load:", err));

        // Cleanup: invoked when the component unmounts (e.g., page navigation).
        // Ensures the camera stream is released and all plugin resources are freed.
        return () => {
            if (pluginRef.current) {
                pluginRef.current.destroy();
            }
        };
    }, []);

    return <></>;
}
```

***

### Step 5: Response Handling

When the plugin completes an ID card scan, it invokes the **`handleCapture`** callback with a payload object. This object may contain one or both of the following properties:

| Property | Type     | Description                                                     |
| -------- | -------- | --------------------------------------------------------------- |
| `front`  | `string` | Base64 Data URL of the front side of the ID card                |
| `back`   | `string` | Base64 Data URL of the back side of the ID card (if applicable) |

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. Each scanned card image is delivered as a Data URL string (e.g., `data:image/jpeg;base64,/9j/...`), combining a MIME type prefix with the encoded image payload. Before transmitting to a server, this string must be decoded back into binary form (a `Blob`) to construct a valid multipart HTTP request.

The following demonstrates the **base64-to-Blob conversion** and API submission:

```tsx
// Utility: converts a base64 Data URL string into a binary Blob.
// Multipart form uploads require raw binary data rather than text-encoded base64.
const base64ToBlob = (base64DataURL: string) => {
    // Separate the MIME type header from the encoded payload at the comma boundary.
    // meta    = "data:image/jpeg;base64"
    // content = "/9j/4AAQSkZJRgAB..."
    const [meta, content] = base64DataURL.split(",");

    // Parse the MIME type from the header (e.g., "image/jpeg").
    const mimeMatch = meta.match(/:(.*?);/);
    const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";

    // Decode the base64 payload into raw ASCII binary characters using atob().
    const binary = atob(content);

    // Allocate a typed byte array of the same length as the decoded binary content.
    const array = new Uint8Array(binary.length);

    // Reconstruct the original binary bytes by mapping each character to its code point.
    for (let i = 0; i < binary.length; i++) {
        array[i] = binary.charCodeAt(i);
    }

    // Wrap the binary array in a Blob with the correct content type for server handling.
    return new Blob([array], { type: mime });
};

// Sends a card image Blob to the server-side verification endpoint via multipart POST.
const sendToAPI = async (blob: Blob, isface: string, card_code: string, filename: string) => {
    const formData = new FormData();
    formData.append("scan_image", blob, filename); // The binary image file
    formData.append("isface", isface);             // "front" or "back" — card side identifier
    formData.append("country_code", "UGA");        // ISO country code of the scanned ID
    formData.append("card_code", card_code);       // Card template identifier
    formData.append("passport", "false");          // Set "true" if the document is a passport
    formData.append("webcam", "false");            // Set "true" if the image was captured via webcam

    try {
        const response = await fetch("http://ip:port/doc_liveness.php", {
            method: "POST",
            body: formData,
        });

        const data = await response.json();
        console.log(`API Response (${isface}):`, data);

        // Inspect the document authenticity/liveness score from the response.
        if (data && data.score !== undefined) {
            console.log(`Score (${isface}): ${data.score}`);
        }
    } catch (error) {
        console.error(`Error sending ${isface} to API:`, error);
    }
};

// Primary capture callback — invoked automatically when the plugin completes a scan.
// Receives: base64 — payload object with front and/or back card image Data URLs.
const handleCapture = async (base64: any) => {
    console.log("Capture result:", base64);

    // Convert and dispatch the front card image if present in the payload.
    if (base64.front) {
        const frontBlob = base64ToBlob(base64.front);
        await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
    }

    // Convert and dispatch the back card image if present in the payload.
    if (base64.back) {
        const backBlob = base64ToBlob(base64.back);
        await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
    }
};
```

***

### Step 6: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `components/IDScanner.tsx`. The original logic is preserved exactly as-is.

```tsx
"use client";

import { useEffect, useRef, useState } from "react";

export default function IDScanner() {
    const pluginRef = useRef(null);
    const [ready, setReady] = useState(false);
    const initialized = useRef(false);

    const base64ToBlob = (base64DataURL: string) => {
        const [meta, content] = base64DataURL.split(",");
        const mimeMatch = meta.match(/:(.*?);/);
        const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";
        const binary = atob(content);
        const array = new Uint8Array(binary.length);
        for (let i = 0; i < binary.length; i++) {
            array[i] = binary.charCodeAt(i);
        }
        return new Blob([array], { type: mime });
    };

    const sendToAPI = async (blob: Blob, isface: string, card_code: string, filename: string) => {
        const formData = new FormData();
        formData.append("scan_image", blob, filename); //Upload your image file
        formData.append("isface", isface); //put card side either the card image is front or back
        formData.append("country_code", "UGA"); //put country_code of the card image
        formData.append("card_code", card_code); //put card_code of the card image
        formData.append("passport", "false"); //if image is a passport put true else put false
        formData.append("webcam", "false"); //if image is captured from a webcam put true else if image is captured from a mobile put  false

        try {
            const response = await fetch("http://ip:port/doc_liveness.php", {
                method: "POST",
                body: formData,
            });

            const data = await response.json();
            console.log(`API Response (${isface}):`, data);

            if (data && data.score !== undefined) {
                console.log(`Score (${isface}): ${data.score}`);
            }
        } catch (error) {
            console.error(`Error sending ${isface} to API:`, error);
        }
    };


    const handleCapture = async (base64: any) => {
        console.log("Capture result:", base64);

        if (base64.front) {
            const frontBlob = base64ToBlob(base64.front);
            await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
        }
        if (base64.back) {
            const backBlob = base64ToBlob(base64.back);
            await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
        }
    };

    useEffect(() => {
        if (initialized.current) return;
        initialized.current = true;

        import("accuraidscanplugin").then((Module) => {
            const IDCardPlugin = Module.default;

            pluginRef.current = new IDCardPlugin(handleCapture, {
                countryCode: "UGA",
                cardCode: "UGNIDF",
                topTextSize: "",
                topTextColor: "",
                topTextWeight: "",
                bottomTextSize: "",
                bottomTextColor: "",
                bottomTextWeight: "",
            });

            pluginRef.current.start().then(() => {
                console.log("ID Scanner Ready");
                setReady(true);
            });
        }).catch(err => console.error("Plugin failed to load:", err));

        return () => {
            if (pluginRef.current) {
                pluginRef.current.destroy();
            }
        };
    }, []);

    return (
        <></>
    );
}
```

***

### Step 7: Usage

Import and render the component in `app/page.tsx`:

```tsx
import IDScanner from "./components/IDScanner";

export default function Home() {
  return (
    <main>
      <IDScanner />
    </main>
  );
}
```

***

### Step 8: Running the Project

```bash
npm run dev
```


# Angular

## Accura IDScan Plugin — Angular Integration Guide

This guide walks you through integrating the **Accura IDScan Plugin** into an Angular project using standalone components.

### Step 1: Initialize Project

Create a new Angular project with standalone component architecture. When prompted, select **No** for Server-Side Rendering (SSR):

```bash
npx ng new my-id-app --standalone
cd my-id-app
npm install
```

After scaffolding, open `angular.json` and ensure SSR and prerendering are explicitly disabled:

```json
"options": {
  "prerender": false,
  "ssr": false
}
```

***

### Step 2: Install Plugin

Install the Accura IDScan Plugin package from the npm registry:

```bash
npm install accuraidscanplugin
```

***

### Step 3: TypeScript Support

Angular enforces strict TypeScript compilation. Create a type declaration file at `src/types.d.ts` to declare the module and suppress resolution errors:

```typescript
declare module 'accuraidscanplugin';
```

Ensure this file is included in your `tsconfig.app.json`'s `include` array:

```json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": [
      "node"
    ]
  },
  "files": [
    "src/main.ts",
    "src/main.server.ts",
    "server.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}
```

***

### Step 4: Implementation

Generate the scanner component or create it manually at `src/app/id-scanner/id-scanner.component.ts`. The snippet below shows only the **plugin import and instantiation** logic:

```typescript
import { Component, OnInit, OnDestroy } from '@angular/core';

export class IDScannerComponent implements OnInit, OnDestroy {
  plugin: any = null;

  async ngOnInit() {
    // Dynamically import the plugin inside ngOnInit to ensure browser-only execution.
    // Angular may invoke lifecycle hooks during SSR; dynamic import defers plugin
    // loading to runtime, preventing access to unavailable browser APIs on the server.
    const { default: IDCardPlugin } = await import('accuraidscanplugin');

    // Instantiate the plugin with:
    //   1. The capture callback: invoked when the scan session is complete
    //   2. Configuration: specifies the target card, country, and UI styling options
    this.plugin = new IDCardPlugin(
      handleCapture,   // Fired automatically upon successful ID card scan completion
      {
        countryCode: 'UGA',    // Country code of the ID Card
        cardCode: 'UGNIDF',    // Card code of front ID Card
        topTextSize: '',       // Top overlay text size (default if empty)
        topTextColor: '',      // Top overlay text color (default if empty)
        topTextWeight: '',     // Top overlay font weight (default if empty)
        bottomTextSize: '',    // Bottom overlay text size (default if empty)
        bottomTextColor: '',   // Bottom overlay text color (default if empty)
        bottomTextWeight: '',  // Bottom overlay font weight (default if empty)
      }
    );

    // Activate the camera and commence the ID card detection session.
    await this.plugin.start();
  }

  // Angular destruction hook — destroy the plugin to free camera resources on unmount.
  ngOnDestroy() {
    if (this.plugin) {
      this.plugin.destroy();
    }
  }
}
```

***

### Step 5: Response Handling

When the plugin completes an ID card scan, it invokes the **`handleCapture`** callback with a typed payload object. This object may contain one or both of the following properties:

| Property | Type     | Description                                                     |
| -------- | -------- | --------------------------------------------------------------- |
| `front`  | `string` | Base64 Data URL of the front side of the ID card                |
| `back`   | `string` | Base64 Data URL of the back side of the ID card (if applicable) |

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. Each scanned card image is delivered as a Data URL string (e.g., `data:image/jpeg;base64,/9j/...`), combining a MIME type prefix with the encoded image payload. Before transmitting to a server, this string must be decoded back into binary form (a `Blob`) to construct a valid multipart HTTP request.

The following demonstrates the **base64-to-Blob conversion** and API submission:

```typescript
// Utility: converts a base64 Data URL string into a binary Blob.
// Multipart form uploads require raw binary data, not text-encoded Base64 strings.
const base64ToBlob = (base64DataURL: string) => {
  // Split at comma: 'data:image/jpeg;base64' | '/9j/4AAQSkZJRg...'
  const [meta, content] = base64DataURL.split(',');

  // Extract the MIME type from the header segment.
  const match = meta.match(/:(.*?);/);
  const mime = match ? match[1] : 'image/jpeg';

  // Decode the base64-encoded payload into raw binary characters.
  const binary = atob(content);

  // Reconstruct original binary bytes as a typed Uint8Array.
  const array = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) {
    array[i] = binary.charCodeAt(i); // Map each character to its corresponding byte value
  }

  // Wrap the binary data in a Blob for server-compatible multipart submission.
  return new Blob([array], { type: mime });
};

// Sends a scanned card image Blob to the server-side verification endpoint.
const sendToAPI = async (
  blob: Blob,
  isface: 'front' | 'back',
  card_code: string,
  filename: string,
) => {
  const formData = new FormData();
  formData.append('scan_image', blob, filename); // Binary image file
  formData.append('isface', isface);             // "front" or "back" — card side identifier
  formData.append('country_code', 'UGA');        // ISO country code of the scanned ID
  formData.append('card_code', card_code);       // Card template identifier
  formData.append('passport', 'false');          // Set "true" if the document is a passport
  formData.append('webcam', 'false');            // Set "true" if captured via a webcam

  try {
    const response = await fetch('https://ip:port/doc_liveness.php', {
      method: 'POST',
      body: formData,
    });

    const data = await response.json();
    console.log(`API Response (${isface}):`, data);

    // Read the document authenticity/liveness score from the server response.
    if (data && data.score !== undefined) {
      console.log(`Score (${isface}): ${data.score}`);
    }
  } catch (error) {
    console.error(`Error sending ${isface} to API:`, error);
  }
};

// Primary capture callback — invoked when plugin completes scan.
// Receives: base64 — object with optional front/back card image Data URLs.
const handleCapture = async (base64: { front?: string; back?: string }) => {
  console.log('Capture result:', base64);

  if (base64.front) {
    const frontBlob = base64ToBlob(base64.front);
    await sendToAPI(frontBlob, 'front', 'UGNIDF', 'front.jpg');
  }

  if (base64.back) {
    const backBlob = base64ToBlob(base64.back);
    await sendToAPI(backBlob, 'back', 'UGNIDB', 'back.jpg');
  }
};
```

***

### Step 6: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `src/app/id-scanner/id-scanner.component.ts`. The original logic is preserved exactly as-is.

```typescript
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-id-scanner',
  standalone: true,
  imports: [CommonModule],
  template: ``,
  styles: [``],
})
export class IDScannerComponent implements OnInit, OnDestroy {
  ready = false;
  plugin: any = null;

  async ngOnInit() {
    try {
      const { default: IDCardPlugin } = await import('accuraidscanplugin');

      interface CapturePayload {
        front?: string;
        back?: string;
      }

      const base64ToBlob = (base64DataURL: string) => {
        const [meta, content] = base64DataURL.split(',');
        const match = meta.match(/:(.*?);/);
        const mime = match ? match[1] : 'image/jpeg';
        const binary = atob(content);
        const array = new Uint8Array(binary.length);
        for (let i = 0; i < binary.length; i++) {
          array[i] = binary.charCodeAt(i);
        }
        return new Blob([array], { type: mime });
      };

      // Function to send image to API and log score
      const sendToAPI = async (
        blob: Blob,
        isface: 'front' | 'back',
        card_code: string,
        filename: string,
      ) => {
        const formData = new FormData();
        formData.append('scan_image', blob, filename); //Upload your image file
        formData.append('isface', isface); //put card side either the card image is front or back
        formData.append('country_code', 'UGA'); //put country_code of the card image
        formData.append('card_code', card_code); //put card_code of the card image
        formData.append('passport', 'false'); //if image is a passport put true else put false
        formData.append('webcam', 'false'); //if image is captured from a webcam put true else if image is captured from a mobile put  false

        try {
          const response = await fetch(
            'https://ip:port/doc_liveness.php',
            {
              method: 'POST',
              body: formData,
            },
          );

          const data = await response.json();
          console.log(`API Response (${isface}):`, data);

          if (data && data.score !== undefined) {
            console.log(`Score (${isface}): ${data.score}`);
          }
        } catch (error) {
          console.error(`Error sending ${isface} to API:`, error);
        }
      };

      // Callback receives captured images with metadata
      const handleCapture = async (base64: CapturePayload) => {
        console.log('Capture result:', base64);

        // Send front image
        if (base64.front) {
          const frontBlob = base64ToBlob(base64.front);
          await sendToAPI(frontBlob, 'front', 'UGNIDF', 'front.jpg');
        }

        // Send back image if present
        if (base64.back) {
          const backBlob = base64ToBlob(base64.back);
          await sendToAPI(backBlob, 'back', 'UGNIDB', 'back.jpg');
        }
      };

      this.plugin = new IDCardPlugin(handleCapture, {
        countryCode: 'UGA',
        cardCode: 'UGNIDF',
        topTextSize: '',
        topTextColor: '',
        topTextWeight: '',
        bottomTextSize: '',
        bottomTextColor: '',
        bottomTextWeight: '',
      });

      await this.plugin.start();
      this.ready = true;
    } catch (err) {
      console.error('Angular IDScan Init Error:', err);
    }
  }

  ngOnDestroy() {
    if (this.plugin) {
      this.plugin.destroy();
    }
  }
}
```

***

### Step 7: Usage

Register and render the component in `app.component.ts`:

```typescript
import { Component } from '@angular/core';
import { IDScannerComponent } from './id-scanner/id-scanner.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [IDScannerComponent],
  template: `<app-id-scanner></app-id-scanner>`
})
export class AppComponent {
  title = 'angular-id';
}
```

***

### Step 8: Running the Project

```bash
npm start
```


# Vue

## Accura IDScan Plugin — Vue 3 Integration Guide

This guide walks you through integrating the **Accura IDScan Plugin** into a Vue 3 project built with Vite.

### Step 1: Initialize Project

If you do not have an existing Vue 3 project, scaffold one using Vite:

```bash
npm create vite@latest my-id-app -- --template vue
cd my-id-app
npm install
```

***

### Step 2: Install Plugin

Install the Accura IDScan Plugin package from the npm registry:

```bash
npm install accuraidscanplugin
```

***

### Step 3: Implementation

Create a dedicated scanner component at `components/IDScanner.vue`. The following snippet shows only the **plugin import and initialization** logic:

```vue
<script setup>
import { onMounted, onUnmounted } from 'vue';

let plugin = null; // Holds the active plugin instance for lifecycle management

onMounted(async () => {
  // Dynamically import the plugin inside onMounted to guarantee browser-only execution.
  // Vue's onMounted lifecycle hook runs exclusively on the client side,
  // making it safe to access browser APIs such as the camera.
  const { default: IDCardPlugin } = await import('accuraidscanplugin');

  // Instantiate the plugin with:
  //   1. The capture callback invoked when the scan is complete
  //   2. A configuration object specifying card target and UI appearance
  plugin = new IDCardPlugin(
    handleCapture,   // Fired automatically upon successful ID card scan
    {
      countryCode: "UGA",    // Country code of the ID card
      cardCode: "UGNIDF",    // Card code ID front Card
      topTextSize: "",       // Top overlay text size (default if empty)
      topTextColor: "",      // Top overlay text color (default if empty)
      topTextWeight: "",     // Top overlay font weight (default if empty)
      bottomTextSize: "",    // Bottom overlay text size (default if empty)
      bottomTextColor: "",   // Bottom overlay text color (default if empty)
      bottomTextWeight: "",  // Bottom overlay font weight (default if empty)
    }
  );

  // Activate the camera and begin the ID card detection session.
  await plugin.start();
});

// Release camera resources and destroy the plugin when the component unmounts.
onUnmounted(() => {
  if (plugin) {
    plugin.destroy();
  }
});
</script>
```

***

### Step 4: Response Handling

When the plugin completes an ID card scan, it invokes the **`handleCapture`** callback with a payload object that may contain one or both of the following properties:

| Property | Type     | Description                                                     |
| -------- | -------- | --------------------------------------------------------------- |
| `front`  | `string` | Base64 Data URL of the front side of the ID card                |
| `back`   | `string` | Base64 Data URL of the back side of the ID card (if applicable) |

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. Each scanned card image is delivered as a Data URL string (e.g., `data:image/jpeg;base64,/9j/...`), combining a MIME type prefix with the encoded image payload. Before transmitting to a server, this string must be decoded back into binary form (a `Blob`) to construct a valid multipart HTTP request.

The following demonstrates the **base64-to-Blob conversion** and API submission:

```js
// Utility: converts a base64 Data URL string into a binary Blob.
// Multipart form uploads require raw binary data rather than text-encoded base64.
const base64ToBlob = (base64DataURL) => {
    // Separate the MIME type header from the encoded payload at the comma boundary.
    const [meta, content] = base64DataURL.split(",");

    // Extract the MIME type (e.g., "image/jpeg") from the header segment.
    const mimeMatch = meta.match(/:(.*?);/);
    const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";

    // Decode the base64-encoded payload back into raw binary characters.
    const binary = atob(content);

    // Reconstruct the binary bytes as a typed Uint8Array.
    const array = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
        array[i] = binary.charCodeAt(i); // Map each character to its byte code
    }

    // Return a Blob with the appropriate MIME type for correct server handling.
    return new Blob([array], { type: mime });
};

// Submits a card image Blob to the server-side verification endpoint.
const sendToAPI = async (blob, isface, card_code, filename) => {
    const formData = new FormData();
    formData.append("scan_image", blob, filename);  // Binary image file
    formData.append("isface", isface);              // "front" or "back"
    formData.append("country_code", "UGA");         // ISO country code
    formData.append("card_code", card_code);        // Card template identifier
    formData.append("passport", "false");           // "true" for passport documents
    formData.append("webcam", "false");             // "true" if captured via webcam

    try {
        const response = await fetch("http://ip:port/doc_liveness.php", {
            method: "POST",
            body: formData,
        });
        const data = await response.json();
        console.log(`API Response (${isface}):`, data);

        if (data && data.score !== undefined) {
            console.log(`Score (${isface}): ${data.score}`);
        }
    } catch (error) {
        console.error(`Error sending ${isface} to API:`, error);
    }
};

// Primary capture callback — invoked by the plugin when scanning is complete.
const handleCapture = async (base64) => {
    if (base64.front) {
        const frontBlob = base64ToBlob(base64.front);
        await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
    }
    if (base64.back) {
        const backBlob = base64ToBlob(base64.back);
        await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
    }
};
```

***

### Step 5: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `components/IDScanner.vue`. The original logic is preserved exactly as-is.

```vue
<template>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from 'vue';

const isReady = ref(false);
let plugin = null;

onMounted(async () => {
  try {
    const { default: IDCardPlugin } = await import('accuraidscanplugin');

    const base64ToBlob = (base64DataURL) => {
        const [meta, content] = base64DataURL.split(",");
        const mimeMatch = meta.match(/:(.*?);/);
        const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";
        const binary = atob(content);
        const array = new Uint8Array(binary.length);
        for (let i = 0; i < binary.length; i++) {
            array[i] = binary.charCodeAt(i);
        }
        return new Blob([array], { type: mime });
    };

    const sendToAPI = async (blob, isface, card_code, filename) => {
        const formData = new FormData();
        formData.append("scan_image", blob, filename);
        formData.append("isface", isface);
        formData.append("country_code", "UGA");
        formData.append("card_code", card_code);
        formData.append("passport", "false");
        formData.append("webcam", "false");

        try {
            console.log(`Sending ${isface} (${card_code}) to API...`);
            const response = await fetch("http://ip:port/doc_liveness.php", {
                method: "POST",
                body: formData,
            });

            const data = await response.json();
            console.log(`API Response (${isface}):`, data);

            if (data && data.score !== undefined) {
                console.log(`Score (${isface}): ${data.score}`);
            }
        } catch (error) {
            console.error(`Error sending ${isface} to API:`, error);
        }
    };


    const handleCapture = async (base64) => {
        console.log("Capture result received:", Object.keys(base64));

        if (base64.front) {
            console.log("Processing front side...");
            const frontBlob = base64ToBlob(base64.front);
            await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
        }
        if (base64.back) {
            console.log("Processing back side...");
            const backBlob = base64ToBlob(base64.back);
            await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
        }
    };
    
    plugin = new IDCardPlugin(
      handleCapture,
      {
        countryCode: "UGA",
        cardCode: "UGNIDF",
        topTextSize: "",
        topTextColor: "",
        topTextWeight: "",
        bottomTextSize: "",
        bottomTextColor: "",
        bottomTextWeight: "",
      }
    );
    
    await plugin.start();
    isReady.value = true;
  } catch (error) {
    console.error("Vue plugin error:", error);
  }
});

onUnmounted(() => {
  if (plugin) {
    plugin.destroy();
  }
});
</script>

<style scoped>
</style>
```

***

### Step 6: Usage

Import and render the component in `App.vue`:

```vue
<script setup>
import IDScanner from './components/IDScanner.vue';
</script>

<template>
  <IDScanner />
</template>
```

***

### Step 7: Running the Project

```bash
npm run dev
```


# Svelte

## Accura IDScan Plugin — Svelte Integration Guide

This guide walks you through integrating the **Accura IDScan Plugin** into a Svelte project built with Vite.

### Step 1: Initialize Project

If you do not have an existing Svelte project, scaffold one using Vite:

```bash
npm create vite@latest my-id-app -- --template svelte
cd my-id-app
npm install
```

***

### Step 2: Install Plugin

Install the Accura IDScan Plugin package from the npm registry:

```bash
npm install accuraidscanplugin
```

***

### Step 3: Implementation

Create a dedicated scanner component at `src/lib/IDScanner.svelte`. The following snippet shows only the **plugin import and initialization** logic:

```svelte
<script>
  import { onMount, onDestroy } from 'svelte';

  let plugin = null; // Holds the active plugin instance for lifecycle management

  onMount(async () => {
    // Dynamically import the plugin inside onMount to guarantee browser-only execution.
    // Svelte's onMount lifecycle hook runs exclusively on the client side,
    // making it safe to access browser APIs such as the camera.
    const { default: IDCardPlugin } = await import('accuraidscanplugin');

    // Instantiate the plugin with:
    //   1. The capture callback invoked when the scan session is complete
    //   2. A configuration object specifying the target card and UI appearance
    plugin = new IDCardPlugin(
      handleCapture,   // Fired automatically upon successful ID card scan
      {
        countryCode: "UGA",    // Country code of the ID Card
        cardCode: "UGNIDF",    // Card code of front ID Card
        topTextSize: "",       // Top overlay text size (default if empty)
        topTextColor: "",      // Top overlay text color (default if empty)
        topTextWeight: "",     // Top overlay font weight (default if empty)
        bottomTextSize: "",    // Bottom overlay text size (default if empty)
        bottomTextColor: "",   // Bottom overlay text color (default if empty)
        bottomTextWeight: "",  // Bottom overlay font weight (default if empty)
      }
    );

    // Activate the camera and begin the ID card detection session.
    await plugin.start();
  });

  // Release camera resources and destroy the plugin when the component is removed from the DOM.
  onDestroy(() => {
    if (plugin) {
      plugin.destroy();
    }
  });
</script>
```

***

### Step 4: Response Handling

When the plugin completes an ID card scan, it invokes the **`handleCapture`** callback with a payload object. This object may contain one or both of the following properties:

| Property | Type     | Description                                                     |
| -------- | -------- | --------------------------------------------------------------- |
| `front`  | `string` | Base64 Data URL of the front side of the ID card                |
| `back`   | `string` | Base64 Data URL of the back side of the ID card (if applicable) |

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. Each scanned card image is delivered as a Data URL string (e.g., `data:image/jpeg;base64,/9j/...`), combining a MIME type prefix with the encoded image payload. Before transmitting to a server, this string must be decoded back into binary form (a `Blob`) to construct a valid multipart HTTP request.

The following demonstrates the **base64-to-Blob conversion** and API submission:

```js
// Utility: converts a base64 Data URL string into a binary Blob.
// Multipart form uploads require raw binary data, not text-encoded Base64 strings.
const base64ToBlob = (base64DataURL) => {
    // Split at the comma: left side = MIME header, right side = encoded image data.
    const [meta, content] = base64DataURL.split(",");

    // Extract the MIME type (e.g., "image/jpeg") from the header segment.
    const mimeMatch = meta.match(/:(.*?);/);
    const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";

    // Decode the base64-encoded payload back into raw binary characters using atob().
    const binary = atob(content);

    // Allocate a typed Uint8Array to hold the reconstructed binary bytes.
    const array = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
        array[i] = binary.charCodeAt(i); // Map each character to its corresponding byte value
    }

    // Wrap the reconstructed binary data in a Blob with the correct MIME type.
    return new Blob([array], { type: mime });
};

// Submits a card image Blob to the server-side verification endpoint.
const sendToAPI = async (blob, isface, card_code, filename) => {
    const formData = new FormData();
    formData.append("scan_image", blob, filename);  // Binary image file
    formData.append("isface", isface);              // "front" or "back"
    formData.append("country_code", "UGA");         // ISO country code
    formData.append("card_code", card_code);        // Card template identifier
    formData.append("passport", "false");           // "true" for passport documents
    formData.append("webcam", "false");             // "true" if captured via webcam

    try {
        const response = await fetch("http://ip:port/doc_liveness.php", {
            method: "POST",
            body: formData,
        });
        const data = await response.json();
        console.log(`API Response (${isface}):`, data);

        if (data && data.score !== undefined) {
            console.log(`Score (${isface}): ${data.score}`);
        }
    } catch (error) {
        console.error(`Error sending ${isface} to API:`, error);
    }
};

// Primary capture callback — invoked by the plugin when scanning is complete.
const handleCapture = async (base64) => {
    if (base64.front) {
        const frontBlob = base64ToBlob(base64.front);
        await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
    }
    if (base64.back) {
        const backBlob = base64ToBlob(base64.back);
        await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
    }
};
```

***

### Step 5: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `src/lib/IDScanner.svelte`. The original logic is preserved exactly as-is.

```svelte
<script>
  import { onMount, onDestroy } from 'svelte';
  
  let isReady = false;
  let plugin = null;

  onMount(async () => {
    try {
      const { default: IDCardPlugin } = await import('accuraidscanplugin');

      const base64ToBlob = (base64DataURL) => {
        const [meta, content] = base64DataURL.split(",");
        const mimeMatch = meta.match(/:(.*?);/);
        const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";
        const binary = atob(content);
        const array = new Uint8Array(binary.length);
        for (let i = 0; i < binary.length; i++) {
            array[i] = binary.charCodeAt(i);
        }
        return new Blob([array], { type: mime });
    };

    const sendToAPI = async (blob, isface, card_code, filename) => {
        const formData = new FormData();
        formData.append("scan_image", blob, filename);
        formData.append("isface", isface);
        formData.append("country_code", "UGA");
        formData.append("card_code", card_code);
        formData.append("passport", "false");
        formData.append("webcam", "false");

        try {
            console.log(`Sending ${isface} (${card_code}) to API...`);
            const response = await fetch("http://ip:port/doc_liveness.php", {
                method: "POST",
                body: formData,
            });

            const data = await response.json();
            console.log(`API Response (${isface}):`, data);

            if (data && data.score !== undefined) {
                console.log(`Score (${isface}): ${data.score}`);
            }
        } catch (error) {
            console.error(`Error sending ${isface} to API:`, error);
        }
    };


    const handleCapture = async (base64) => {
        console.log("Capture result received:", Object.keys(base64));

        if (base64.front) {
            console.log("Processing front side...");
            const frontBlob = base64ToBlob(base64.front);
            await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
        }
        if (base64.back) {
            console.log("Processing back side...");
            const backBlob = base64ToBlob(base64.back);
            await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
        }
    };
      
      plugin = new IDCardPlugin(
        handleCapture,
        {
        countryCode: "UGA",
        cardCode: "UGNIDF",
        topTextSize: "",
        topTextColor: "",
        topTextWeight: "",
        bottomTextSize: "",
        bottomTextColor: "",
        bottomTextWeight: "",
      }
      );
      
      await plugin.start();
      isReady = true;
    } catch (e) {
      console.error("Svelte IDScan Error:", e);
    }
  });

  onDestroy(() => {
    if (plugin) {
      plugin.destroy();
    }
  });
</script>
```

***

### Step 6: Usage

Import and render the component in `App.svelte`:

```svelte
<script>
  import IDScanner from './lib/IDScanner.svelte';
</script>

<IDScanner />
```

***

### Step 7: Running the Project

```bash
npm run dev
```


# Web API




---

[Next Page](/llms-full.txt/1)

