npm package: @one-payments/react
Description: React wrapper for One Payments SDK
Author: One Payments
Latest version: 1.7.5

# @one-payments/react

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

## Features

- Native React component wrapping One Payments web component
- Full TypeScript support with type definitions
- React event handlers instead of DOM events
- Seamless integration with React hooks and lifecycle

## Installation

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

## Usage

### Basic Example

```tsx
import React from 'react';
import { OnePayment } from '@one-payments/react';
import { PaymentConfig } from '@one-payments/core';
import { createWebAdapters } from '@one-payments/adapters-web';
import type { PaymentSucceededPayload, PaymentFailedPayload } from '@one-payments/react';

function CheckoutPage() {
  // 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 adapters = createWebAdapters();

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

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

  return (
    <div className="checkout">
      <h1>Complete Your Payment</h1>
      <OnePayment
        config={config}
        adapters={adapters}
        amount={5000}
        currency="SGD"
        orderId={`order-${Date.now()}`}
        firstName="John"
        lastName="Doe"
        email="john@example.com"
        onPaymentSuccess={handleSuccess}
        onPaymentError={handleError}
      />
    </div>
  );
}

export default CheckoutPage;
```

> **Note**: You can also pass a plain config object instead of using `PaymentConfig`:
> ```tsx
> config={{
>   apiKey: 'your-api-key',
>   secretKey: 'your-secret-key',
>   environment: 'demo'
> }}
> ```
> However, `PaymentConfig` is recommended as it provides validation and better TypeScript support.

### With State Management

```tsx
import React, { useState } from 'react';
import { OnePayment } from '@one-payments/react';
import { createWebAdapters } from '@one-payments/adapters-web';
import type {
  PaymentSucceededPayload,
  PaymentFailedPayload,
  StateChangedPayload
} from '@one-payments/react';

function CheckoutWithState() {
  const [paymentStatus, setPaymentStatus] = useState<'idle' | 'processing' | 'success' | 'error'>('idle');
  const [errorMessage, setErrorMessage] = useState<string>('');

  const adapters = createWebAdapters();

  const handleSuccess = (event: CustomEvent<PaymentSucceededPayload>) => {
    setPaymentStatus('success');
    console.log('Payment Intent ID:', event.detail.paymentIntentId);
  };

  const handleError = (event: CustomEvent<PaymentFailedPayload>) => {
    setPaymentStatus('error');
    setErrorMessage(event.detail.message);
  };

  const handleStateChange = (event: CustomEvent<StateChangedPayload>) => {
    console.log('Payment state:', event.detail.status);
    if (event.detail.status === 'processing') {
      setPaymentStatus('processing');
    }
  };

  if (paymentStatus === 'success') {
    return <div>Payment successful! Thank you for your order.</div>;
  }

  return (
    <div>
      {paymentStatus === 'error' && (
        <div className="error">{errorMessage}</div>
      )}
      {paymentStatus === 'processing' && (
        <div className="processing">Processing your payment...</div>
      )}
      <OnePayment
        config={{
          apiKey: process.env.REACT_APP_ONE_PAYMENTS_API_KEY!,
          secretKey: process.env.REACT_APP_ONE_PAYMENTS_SECRET_KEY!,
          environment: 'prod'
        }}
        adapters={adapters}
        amount={5000}
        currency="SGD"
        orderId={`order-${Date.now()}`}
        metadata={{
          userId: '12345',
          productId: 'product-abc'
        }}
        onPaymentSuccess={handleSuccess}
        onPaymentError={handleError}
        onStateChange={handleStateChange}
      />
    </div>
  );
}
```

### With React Router

```tsx
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { OnePayment } from '@one-payments/react';
import { createWebAdapters } from '@one-payments/adapters-web';

function CheckoutPage() {
  const navigate = useNavigate();
  const adapters = createWebAdapters();

  return (
    <OnePayment
      config={{
        apiKey: process.env.REACT_APP_ONE_PAYMENTS_API_KEY!,
        secretKey: process.env.REACT_APP_ONE_PAYMENTS_SECRET_KEY!,
        environment: 'prod'
      }}
      adapters={adapters}
      amount={5000}
      currency="SGD"
      orderId={`order-${Date.now()}`}
      onPaymentSuccess={(event) => {
        navigate('/success', {
          state: { paymentId: event.detail.paymentIntentId }
        });
      }}
      onPaymentError={(event) => {
        navigate('/error', {
          state: { error: event.detail.message }
        });
      }}
    />
  );
}
```

## 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") |
| `onPaymentSuccess` | `(event: CustomEvent<PaymentSucceededPayload>) => void` | No | Callback when payment succeeds |
| `onPaymentError` | `(event: CustomEvent<PaymentFailedPayload>) => void` | No | Callback when payment fails |
| `onStateChange` | `(event: CustomEvent<StateChangedPayload>) => void` | No | Callback 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;
}
```

## Next.js Integration

Using this package with Next.js requires special handling for Server-Side Rendering (SSR). See our comprehensive [Next.js Integration Guide](../../docs/integration-guides/nextjs.md) for detailed instructions.

### Quick Summary for Next.js

```tsx
// Use dynamic import with ssr: false
import dynamic from 'next/dynamic';

const OnePayment = dynamic(
  () => import('@one-payments/react').then((mod) => mod.OnePayment),
  { ssr: false }
);

// Initialize adapters on client-side only
useEffect(() => {
  import('@one-payments/adapters-web').then(({ createWebAdapters }) => {
    setAdapters(createWebAdapters());
  });
}, []);
```

[→ Full Next.js Integration Guide](../../docs/integration-guides/nextjs.md)

## Requirements

- React >= 16.8.0 (hooks support)
- React 19+ supported
- 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/vue](../vue) - Vue wrapper
- [@one-payments/angular](../angular) - Angular wrapper
- [@one-payments/react-native](../react-native) - React Native implementation

## License

MIT