Vue Integration

Integrate the VECU IDV Web SDK into your Vue applications with proper lifecycle management.

Vue 3 Composition API

<template>
  <div ref="verificationContainer" :style="{ minHeight: '600px' }"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue';
import { createVecuIDVSDK } from 'vec-idp-web-sdk';

const props = defineProps<{
  customerInfo: {
    firstName: string;
    lastName: string;
    email?: string;
    phone?: string;
  };
}>();

const emit = defineEmits<{
  (e: 'success', result: any): void;
  (e: 'error', error: Error): void;
  (e: 'progress', event: { step: string; percentage: number }): void;
}>();

const verificationContainer = ref<HTMLDivElement | null>(null);
let sdk: any = null;
let cleanup: (() => void) | null = null;

onMounted(async () => {
  sdk = createVecuIDVSDK({
    deploymentStage: 'sandbox',
    bearerToken: import.meta.env.VITE_BEARER_TOKEN,
    debug: import.meta.env.DEV,
    logLevel: 'info',
  });

  if (props.customerInfo && verificationContainer.value) {
    await startVerification();
  }
});

async function startVerification() {
  if (!sdk || !verificationContainer.value) return;

  cleanup = await sdk.startVerificationWithCustomer(
    verificationContainer.value,
    {
      customerInfo: props.customerInfo,
      referenceId: `customer-${Date.now()}`,
      mode: 'embedded',
      onProgress: (event: { step: string; percentage: number }) => {
        console.log(`Progress: ${event.step} (${event.percentage}%)`);
        emit('progress', event);
      },
      onSuccess: (result: any) => {
        console.log('Verification completed!', result);
        emit('success', result);
      },
      onError: (error: Error) => {
        console.error('Verification failed:', error);
        emit('error', error);
      },
      config: {
        qrCode: true,
      },
    }
  );
}

// Watch for customer info changes
watch(
  () => props.customerInfo,
  async newInfo => {
    if (newInfo && verificationContainer.value) {
      cleanup?.();
      await startVerification();
    }
  }
);

onUnmounted(() => {
  cleanup?.();
  sdk?.destroy();
});
</script>

Vue 3 Composable

Create a reusable composable for verification:

// composables/useVerification.ts
import { ref, onUnmounted, type Ref } from 'vue';
import { createVecuIDVSDK } from 'vec-idp-web-sdk';

interface CustomerInfo {
  firstName: string;
  lastName: string;
  email?: string;
  phone?: string;
  address?: {
    line1: string;
    locality: string;
    majorAdminDivision: string;
    country: string;
    postalCode: string;
    type: string;
  };
}

interface UseVerificationOptions {
  onSuccess?: (result: any) => void;
  onError?: (error: Error) => void;
  onProgress?: (event: { step: string; percentage: number }) => void;
}

export function useVerification(options: UseVerificationOptions = {}) {
  const containerRef = ref<HTMLElement | null>(null);
  const isLoading = ref(false);
  const error = ref<Error | null>(null);
  const result = ref<any>(null);

  let sdk: any = null;
  let cleanup: (() => void) | null = null;

  // Initialize SDK
  sdk = createVecuIDVSDK({
    deploymentStage: import.meta.env.PROD ? 'production' : 'sandbox',
    bearerToken: import.meta.env.VITE_BEARER_TOKEN,
    debug: import.meta.env.DEV,
  });

  async function startVerification(customerInfo: CustomerInfo) {
    if (!sdk || !containerRef.value) return;

    isLoading.value = true;
    error.value = null;
    result.value = null;

    try {
      cleanup = await sdk.startVerificationWithCustomer(containerRef.value, {
        customerInfo,
        referenceId: `ref-${Date.now()}`,
        onProgress: (event: { step: string; percentage: number }) => {
          options.onProgress?.(event);
        },
        onSuccess: (res: any) => {
          result.value = res;
          isLoading.value = false;
          options.onSuccess?.(res);
        },
        onError: (err: Error) => {
          error.value = err;
          isLoading.value = false;
          options.onError?.(err);
        },
        config: {
          qrCode: true,
        },
      });
    } catch (err) {
      error.value = err as Error;
      isLoading.value = false;
    }
  }

  function cancelVerification() {
    cleanup?.();
    isLoading.value = false;
  }

  onUnmounted(() => {
    cleanup?.();
    sdk?.destroy();
  });

  return {
    containerRef,
    startVerification,
    cancelVerification,
    isLoading,
    error,
    result,
  };
}

Using the Composable

<template>
  <div>
    <h1>Identity Verification</h1>

    <div v-if="error" class="error">Error: {{ error.message }}</div>

    <div v-if="result" class="success">Verification Complete!</div>

    <div ref="containerRef" style="min-height: 600px;"></div>

    <div class="controls">
      <button @click="handleStart" :disabled="isLoading">
        {{ isLoading ? 'Verifying...' : 'Start Verification' }}
      </button>
      <button v-if="isLoading" @click="cancelVerification">Cancel</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { useVerification } from '@/composables/useVerification';

const {
  containerRef,
  startVerification,
  cancelVerification,
  isLoading,
  error,
  result,
} = useVerification({
  onSuccess: result => {
    console.log('Success!', result);
  },
  onError: error => {
    console.error('Error:', error);
  },
});

function handleStart() {
  startVerification({
    firstName: 'John',
    lastName: 'Doe',
    email: 'john@example.com',
  });
}
</script>

Vue 2 Options API

<template>
  <div ref="verificationContainer" style="min-height: 600px;"></div>
</template>

<script>
import { createVecuIDVSDK } from 'vec-idp-web-sdk';

export default {
  name: 'VerificationComponent',

  props: {
    customerInfo: {
      type: Object,
      required: true,
    },
  },

  data() {
    return {
      sdk: null,
      cleanup: null,
    };
  },

  async mounted() {
    this.sdk = createVecuIDVSDK({
      deploymentStage: 'sandbox',
      bearerToken: process.env.VUE_APP_BEARER_TOKEN,
      debug: process.env.NODE_ENV === 'development',
    });

    await this.startVerification();
  },

  beforeDestroy() {
    this.cleanup?.();
    this.sdk?.destroy();
  },

  watch: {
    customerInfo: {
      handler() {
        this.cleanup?.();
        this.startVerification();
      },
      deep: true,
    },
  },

  methods: {
    async startVerification() {
      if (!this.sdk || !this.$refs.verificationContainer) return;

      this.cleanup = await this.sdk.startVerificationWithCustomer(
        this.$refs.verificationContainer,
        {
          customerInfo: this.customerInfo,
          referenceId: `customer-${Date.now()}`,
          mode: 'embedded',
          onProgress: event => {
            console.log(`Progress: ${event.step} (${event.percentage}%)`);
            this.$emit('progress', event);
          },
          onSuccess: result => {
            console.log('Verification completed!', result);
            this.$emit('success', result);
          },
          onError: error => {
            console.error('Verification failed:', error);
            this.$emit('error', error);
          },
          config: {
            qrCode: true,
          },
        }
      );
    },
  },
};
</script>

Nuxt.js Integration

For Nuxt 3, create a client-only component:

<!-- components/Verification.client.vue -->
<template>
  <div ref="verificationContainer" style="min-height: 600px;"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';

const props = defineProps<{
  customerInfo: {
    firstName: string;
    lastName: string;
    email?: string;
  };
}>();

const emit = defineEmits<{
  (e: 'success', result: any): void;
  (e: 'error', error: Error): void;
}>();

const verificationContainer = ref<HTMLDivElement | null>(null);
let sdk: any = null;
let cleanup: (() => void) | null = null;

onMounted(async () => {
  // Dynamic import for client-side only
  const { createVecuIDVSDK } = await import('vec-idp-web-sdk');

  sdk = createVecuIDVSDK({
    deploymentStage: 'sandbox',
    bearerToken: useRuntimeConfig().public.bearerToken,
    debug: process.dev,
  });

  cleanup = await sdk.startVerificationWithCustomer(
    verificationContainer.value,
    {
      customerInfo: props.customerInfo,
      referenceId: `ref-${Date.now()}`,
      onSuccess: (result: any) => emit('success', result),
      onError: (error: Error) => emit('error', error),
    }
  );
});

onUnmounted(() => {
  cleanup?.();
  sdk?.destroy();
});
</script>

Usage in a page:

<!-- pages/verify.vue -->
<template>
  <div>
    <h1>Identity Verification</h1>
    <ClientOnly>
      <Verification
        :customer-info="customerInfo"
        @success="handleSuccess"
        @error="handleError"
      />
      <template #fallback>
        <div>Loading verification...</div>
      </template>
    </ClientOnly>
  </div>
</template>

<script setup>
const customerInfo = {
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
};

function handleSuccess(result) {
  navigateTo('/success');
}

function handleError(error) {
  console.error(error);
}
</script>

Error Handling

Create an error handling wrapper:

<template>
  <div v-if="hasError" class="error-fallback">
    <h2>Verification Error</h2>
    <p>{{ errorMessage }}</p>
    <button @click="retry">Retry</button>
  </div>
  <slot v-else></slot>
</template>

<script setup lang="ts">
import { ref, onErrorCaptured } from 'vue';

const hasError = ref(false);
const errorMessage = ref('');

onErrorCaptured(error => {
  hasError.value = true;
  errorMessage.value = error.message;
  console.error('Verification error:', error);
  return false; // Prevent propagation
});

function retry() {
  hasError.value = false;
  errorMessage.value = '';
}
</script>

Best Practices

  1. Use refs for container - Always use template refs for the container element
  2. Cleanup on unmount - Always call cleanup and destroy in onUnmounted/beforeDestroy
  3. Watch for changes - Re-initialize if customer info changes
  4. Client-side only - Use dynamic imports or .client.vue suffix in Nuxt
  5. Environment variables - Store tokens in environment variables

Next Steps