# @yengapay/nodejs-sdk

Official Node.js SDK for YengaPay - Accept mobile money payments and send payouts in West Africa.

## Installation

```bash
npm install @yengapay/nodejs-sdk
# or
yarn add @yengapay/nodejs-sdk
```

## Features

- 💳 **Direct Payment API** - Accept mobile money payments via API
- 💸 **Payout API** - Send money to customers
- 🔄 **Fluent Interface** - Clean and intuitive API design
- 📦 **TypeScript Support** - Full type definitions included
- 🌍 **Multi-Operator** - Support for Orange Money, Moov Money, Coris Money, Sank Money
- 🔐 **Secure** - API key authentication

## Quick Start

```typescript
import { YengaPayClient } from '@yengapay/nodejs-sdk';

// Initialize the client with fluent interface
const client = new YengaPayClient()
  .withEnvironment('production') // or 'staging', 'development'
  .withApiKey('your-api-key')
  .withGroupId('your-group-id')
  .withProjectId('your-project-id');

// Alternative: custom base URL
const clientCustom = new YengaPayClient()
  .withApiBaseURL('https://api.yengapay.com')
  .withApiKey('your-api-key')
  .withGroupId('your-group-id')
  .withProjectId('your-project-id');
```

## Direct Payment

### 1. Initialize Payment

```typescript
// Step 1: Initialize payment and get available operators
const payment = await client.directPayment.init({
  amount: 1000, // Amount in XOF
  reference: 'ORDER-123', // Optional: your order reference
  customerEmailToNotify: 'customer@example.com', // Optional
  articles: [ // Optional: items being paid for
    {
      title: 'Product 1',
      description: 'Description',
      price: 1000,
      pictures: ['https://example.com/image.jpg']
    }
  ],
  metadata: { orderId: '123', customField: 'value' } // Optional
});

console.log('Payment Intent ID:', payment.paymentIntentId);
console.log('Expires at:', payment.expiresAt);
console.log('Available operators:', payment.availableOperators);

// Example operator:
// {
//   code: 'ORANGE',
//   name: 'Orange Money',
//   countryCode: 'BF',
//   countryName: 'Burkina Faso',
//   flow: 'ONE_STEP',
//   amount: 1000,
//   fees: 25,
//   totalAmount: 1025,
//   minAmount: 200,
//   maxAmount: 1000000
// }
```

### 2. Process Payment

#### One-Step Flow (Orange Money)

```typescript
const result = await client.directPayment.pay({
  paymentIntentId: payment.paymentIntentId,
  operatorCode: 'ORANGE',
  countryCode: 'BF',
  customerMSISDN: '+22670123456',
  otp: '123456' // Customer enters OTP from their phone
});

if (result.status === 'DONE') {
  console.log('Payment successful!', result.transactionId);
} else if (result.status === 'PENDING') {
  console.log('Payment pending, wait for webhook');
}
```

#### Two-Step Flow (Coris Money, Sank Money)

```typescript
// Step 2a: Send OTP
const otpResult = await client.directPayment.sendOtp({
  paymentIntentId: payment.paymentIntentId,
  operatorCode: 'CORISM',
  countryCode: 'BF',
  customerMSISDN: '+22670123456'
});

console.log(otpResult.message); // "Coris Money vous a envoyé un code OTP par SMS"

// Step 2b: Complete payment with OTP
const result = await client.directPayment.pay({
  paymentIntentId: payment.paymentIntentId,
  operatorCode: 'CORISM',
  countryCode: 'BF',
  customerMSISDN: '+22670123456',
  otp: '123456' // OTP received by customer
});
```

#### Push Notification Flow (Moov Money)

```typescript
const result = await client.directPayment.pay({
  paymentIntentId: payment.paymentIntentId,
  operatorCode: 'MOOV',
  countryCode: 'BF',
  customerMSISDN: '+22670123456'
  // No OTP needed - customer approves on their phone
});

console.log(result.message); // "Le client doit valider sur son téléphone"
```

### 3. Check Payment Status

```typescript
const status = await client.directPayment.getStatus(payment.paymentIntentId);

console.log('Status:', status.status); // PENDING, DONE, FAILED
if (status.status === 'DONE') {
  console.log('Transaction ID:', status.transactionId);
  console.log('Amount:', status.amount);
  console.log('Fees:', status.fees);
}
```

## Payout

### Single Payout

```typescript
const payout = await client.payout.create({
  amount: 5000, // Amount in XOF
  destNumber: '+22670123456',
  destName: 'John Doe', // Optional
  destEmail: 'john@example.com', // Optional
  paymentMethod: 'ORANGE_MONEY', // ORANGE_MONEY, MOOV_MONEY, TELECEL_MONEY, CORIS_MONEY, SANK_MONEY
  description: 'Payment for services' // Optional
});

console.log('Payout ID:', payout.id);
console.log('Status:', payout.status); // PENDING, PROCESSING, SUCCESS, FAILED
```

### Bulk Payout

```typescript
const bulkPayout = await client.payout.createBulk({
  name: 'Monthly Salaries', // Optional
  payouts: [
    {
      amount: 50000,
      destNumber: '+22670111111',
      destName: 'Employee 1',
      paymentMethod: 'ORANGE_MONEY'
    },
    {
      amount: 45000,
      destNumber: '+22670222222',
      destName: 'Employee 2',
      paymentMethod: 'MOOV_MONEY'
    }
  ]
});

console.log('Bulk Payout ID:', bulkPayout.id);
console.log('Total Count:', bulkPayout.totalCount);
console.log('Success Count:', bulkPayout.successCount);
console.log('Failed Count:', bulkPayout.failedCount);
```

### Check Payout Status

```typescript
// Single payout
const payoutStatus = await client.payout.getStatus('payout-id');
console.log(payoutStatus.status); // PENDING, PROCESSING, SUCCESS, FAILED, CANCELLED

// Bulk payout
const bulkStatus = await client.payout.getBulkStatus('bulk-payout-id');
console.log(`Progress: ${bulkStatus.successCount}/${bulkStatus.totalCount}`);
```

## Error Handling

```typescript
import { YengaPayError, AuthenticationError, ValidationError } from '@yengapay/nodejs-sdk';

try {
  const payment = await client.directPayment.init({ amount: 100 });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key or permissions');
  } else if (error instanceof ValidationError) {
    console.error('Validation error:', error.message);
  } else if (error instanceof YengaPayError) {
    console.error('YengaPay error:', error.message, error.statusCode);
  } else {
    console.error('Unknown error:', error);
  }
}
```

## Supported Operators

| Operator | Code | Countries | Flow Type |
|----------|------|-----------|-----------|
| Orange Money | `ORANGE` | BF, CI, SN, ML, NE | ONE_STEP |
| Moov Money | `MOOV` | BF, CI, TG, BJ | TWO_STEP (Push) |
| Coris Money | `CORISM` | BF | TWO_STEP (OTP) |
| Sank Money | `SANKM` | BF | TWO_STEP (OTP) |
| Telecel Money | `TELECEL` | BF | TWO_STEP |

## TypeScript Support

The SDK is written in TypeScript and includes full type definitions:

```typescript
import type {
  InitDirectPaymentParams,
  ProcessPaymentParams,
  PaymentStatusResponse,
  CreatePayoutParams,
  AvailableOperator
} from '@yengapay/nodejs-sdk';
```

## Development

```bash
# Build the SDK
nx build nodejs-sdk

# Run tests
nx test nodejs-sdk

# Lint
nx lint nodejs-sdk
```

## License

MIT

## Support

For support, email support@yengapay.com or visit https://yengapay.com/docs
