npm package: @one-payments/vue
Description: Vue wrapper for One Payments SDK
Author: One Payments
Latest version: 1.4.1

# @one-payments/vue

Vue 3 wrapper component for One Payments SDK. Use this package to integrate One Payments into your Vue applications with a native Vue component API.

## Features

- Native Vue 3 component wrapping One Payments web component
- Full TypeScript support with type definitions
- Vue event emitters instead of DOM events
- Reactive props with Vue's reactivity system
- Composition API compatible

## Installation

```bash
npm install @one-payments/vue @one-payments/adapters-web
# or
yarn add @one-payments/vue @one-payments/adapters-web
# or
pnpm add @one-payments/vue @one-payments/adapters-web
```

## Usage

### Basic Example

```vue
<template>
  <div class="checkout">
    <h1>Complete Your Payment</h1>
    <OnePayment
      :config="config"
      :adapters="adapters"
      :amount="5000"
      currency="SGD"
      :orderId="orderId"
      firstName="John"
      lastName="Doe"
      email="john@example.com"
      @payment-success="handleSuccess"
      @payment-error="handleError"
    />
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { OnePayment } from '@one-payments/vue';
import { PaymentConfig } from '@one-payments/core';
import { createWebAdapters } from '@one-payments/adapters-web';
import type {
  PaymentSucceededPayload,
  PaymentFailedPayload
} from '@one-payments/vue';

const adapters = createWebAdapters();
const orderId = computed(() => `order-${Date.now()}`);

// Create config using PaymentConfig class (recommended for type safety and validation)
const config = new PaymentConfig({
  apiKey: 'your-api-key',
  secretKey: 'your-secret-key',
  environment: 'demo'
});

const handleSuccess = (payload: PaymentSucceededPayload) => {
  console.log('Payment successful!', payload);
  // Navigate to success page or show confirmation
};

const handleError = (payload: PaymentFailedPayload) => {
  console.error('Payment failed:', payload);
  // Show error message to user
};
</script>
```

> **Note**: You can also pass a plain config object instead of using `PaymentConfig`, but `PaymentConfig` is recommended as it provides validation and better TypeScript support.

### With State Management

```vue
<template>
  <div class="checkout">
    <div v-if="paymentStatus === 'success'" class="success">
      Payment successful! Thank you for your order.
    </div>

    <div v-else>
      <div v-if="paymentStatus === 'error'" class="error">
        {{ errorMessage }}
      </div>

      <div v-if="paymentStatus === 'processing'" class="processing">
        Processing your payment...
      </div>

      <OnePayment
        :config="config"
        :adapters="adapters"
        :amount="amount"
        :currency="currency"
        :orderId="orderId"
        :metadata="metadata"
        @payment-success="handleSuccess"
        @payment-error="handleError"
        @state-change="handleStateChange"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import { OnePayment } from '@one-payments/vue';
import { createWebAdapters } from '@one-payments/adapters-web';
import type {
  PaymentSucceededPayload,
  PaymentFailedPayload,
  StateChangedPayload
} from '@one-payments/vue';

const paymentStatus = ref<'idle' | 'processing' | 'success' | 'error'>('idle');
const errorMessage = ref('');
const adapters = createWebAdapters();

const config = {
  apiKey: import.meta.env.VITE_ONE_PAYMENTS_API_KEY,
  secretKey: import.meta.env.VITE_ONE_PAYMENTS_SECRET_KEY,
  environment: 'prod' as const
};

const amount = ref(5000);
const currency = ref('SGD');
const orderId = computed(() => `order-${Date.now()}`);
const metadata = ref({
  userId: '12345',
  productId: 'product-abc'
});

const handleSuccess = (payload: PaymentSucceededPayload) => {
  paymentStatus.value = 'success';
  console.log('Payment Intent ID:', payload.paymentIntentId);
};

const handleError = (payload: PaymentFailedPayload) => {
  paymentStatus.value = 'error';
  errorMessage.value = payload.message;
};

const handleStateChange = (payload: StateChangedPayload) => {
  console.log('Payment state:', payload.status);
  if (payload.status === 'processing') {
    paymentStatus.value = 'processing';
  }
};
</script>

<style scoped>
.error {
  padding: 16px;
  background-color: #fee;
  border: 1px solid #fcc;
  border-radius: 4px;
  color: #c00;
  margin-bottom: 16px;
}

.processing {
  padding: 16px;
  background-color: #fef3cd;
  border: 1px solid #ffeaa7;
  border-radius: 4px;
  color: #856404;
  margin-bottom: 16px;
}

.success {
  padding: 16px;
  background-color: #d4edda;
  border: 1px solid #c3e6cb;
  border-radius: 4px;
  color: #155724;
}
</style>
```

### With Vue Router

```vue
<template>
  <OnePayment
    :config="config"
    :adapters="adapters"
    :amount="5000"
    currency="SGD"
    :orderId="orderId"
    @payment-success="handleSuccess"
    @payment-error="handleError"
  />
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import { OnePayment } from '@one-payments/vue';
import { createWebAdapters } from '@one-payments/adapters-web';
import type {
  PaymentSucceededPayload,
  PaymentFailedPayload
} from '@one-payments/vue';

const router = useRouter();
const adapters = createWebAdapters();
const orderId = computed(() => `order-${Date.now()}`);

const config = {
  apiKey: import.meta.env.VITE_ONE_PAYMENTS_API_KEY,
  secretKey: import.meta.env.VITE_ONE_PAYMENTS_SECRET_KEY,
  environment: 'prod' as const
};

const handleSuccess = (payload: PaymentSucceededPayload) => {
  router.push({
    name: 'success',
    params: { paymentId: payload.paymentIntentId }
  });
};

const handleError = (payload: PaymentFailedPayload) => {
  router.push({
    name: 'error',
    query: { error: payload.message }
  });
};
</script>
```

### Options API

```vue
<template>
  <OnePayment
    :config="config"
    :adapters="adapters"
    :amount="amount"
    :currency="currency"
    :orderId="orderId"
    @payment-success="handleSuccess"
    @payment-error="handleError"
  />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { OnePayment } from '@one-payments/vue';
import { createWebAdapters } from '@one-payments/adapters-web';

export default defineComponent({
  name: 'CheckoutPage',
  components: {
    OnePayment
  },
  data() {
    return {
      adapters: createWebAdapters(),
      config: {
        apiKey: process.env.VUE_APP_ONE_PAYMENTS_API_KEY,
        secretKey: process.env.VUE_APP_ONE_PAYMENTS_SECRET_KEY,
        environment: 'prod' as const
      },
      amount: 5000,
      currency: 'SGD'
    };
  },
  computed: {
    orderId() {
      return `order-${Date.now()}`;
    }
  },
  methods: {
    handleSuccess(payload) {
      console.log('Payment successful!', payload);
    },
    handleError(payload) {
      console.error('Payment failed:', payload);
    }
  }
});
</script>
```

## API Reference

### OnePayment Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `config` | `SDKConfig \| PaymentConfig` | Yes | SDK configuration - use `new PaymentConfig({...})` (recommended) or plain object |
| `adapters` | `Adapters` | Yes | Platform adapters (use `createWebAdapters()` for web) |
| `amount` | `number` | Yes | Payment amount in smallest currency unit (e.g., cents for USD, SGD) |
| `currency` | `string` | Yes | ISO 4217 currency code (e.g., "USD", "EUR", "SGD") |
| `orderId` | `string` | Yes | Unique order identifier from your system |
| `firstName` | `string` | **Yes** | Customer's first name (required for all payments) |
| `lastName` | `string` | **Yes** | Customer's last name (required for all payments) |
| `email` | `string` | **Yes** | Customer's email address (required for all payments) |
| `excludePaymentMethods` | `PaymentMethodId[]` | No | Array of payment method IDs to exclude from display |
| `width` | `string` | No | Custom width (e.g., "100%", "500px") |
| `maxWidth` | `string` | No | Maximum width constraint (e.g., "600px") |

### Events

| Event | Payload | Description |
|-------|---------|-------------|
| `payment-success` | `PaymentSucceededPayload` | Emitted when payment succeeds |
| `payment-error` | `PaymentFailedPayload` | Emitted when payment fails |
| `state-change` | `StateChangedPayload` | Emitted when payment state changes |

### Types

```typescript
interface SDKConfig {
  apiKey: string;
  secretKey: string;
  environment: 'dev' | 'staging' | 'prod';
}

interface PaymentSucceededPayload {
  paymentIntentId: string;
  amount: number;
  currency: string;
  status: 'succeeded';
  metadata?: Record<string, unknown>;
}

interface PaymentFailedPayload {
  code: string;
  message: string;
  details?: Record<string, unknown>;
}

interface StateChangedPayload {
  status: 'idle' | 'initializing' | 'ready' | 'processing' | 'requires_action' | 'succeeded' | 'failed';
  [key: string]: unknown;
}
```

## Requirements

- Vue >= 3.0.0
- TypeScript >= 5.0.0 (for TypeScript projects)

## Related Packages

- [@one-payments/core](../core) - Core SDK types and interfaces
- [@one-payments/web-components](../web-components) - Underlying web component
- [@one-payments/adapters-web](../adapters-web) - Web platform adapters
- [@one-payments/react](../react) - React wrapper
- [@one-payments/angular](../angular) - Angular wrapper
- [@one-payments/react-native](../react-native) - React Native implementation

## License

MIT