npm package: @shipoora/yookassa-sdk
Description: TypeScript SDK for YooKassa REST API v3. Zero dependencies, full types, retries, webhook validation.
Latest version: 0.1.0

# yookassa-sdk

TypeScript SDK for YooKassa REST API v3 with full type safety, automatic retries, and webhook validation.

## Features

- **Zero runtime dependencies** — only Node.js standard library
- **Full type safety** — complete TypeScript definitions for all API entities
- **Automatic retries** — exponential backoff with jitter for transient failures
- **Webhook validation** — secure signature verification with `timingSafeEqual`
- **Tree-shakeable exports** — import only what you need

## Installation

```bash
npm install yookassa-sdk
# or
yarn add yookassa-sdk
# or
pnpm add yookassa-sdk
```

## Quick Start

```typescript
import { YooKassaClient } from 'yookassa-sdk';

const sdk = new YooKassaClient({
    shopId: process.env.YOOKASSA_SHOP_ID,
    secretKey: process.env.YOOKASSA_SECRET_KEY,
});

// Create a payment
const payment = await sdk.payments.create({
    amount: { value: '299.00', currency: 'RUB' },
    capture: true,
    confirmation: { type: 'redirect', return_url: 'https://example.com/return' },
    description: 'Order #123',
});

// Card binding (authorization hold — 1 RUB, never settled)
const binding = await sdk.payments.create({
    amount: { value: '1.00', currency: 'RUB' },
    capture: false,
    save_payment_method: true,
    confirmation: { type: 'redirect', return_url: 'https://example.com/binding-return' },
    description: 'Card verification',
});

// Capture an authorized payment
const captured = await sdk.payments.capture(payment.id, {
    amount: { value: '299.00', currency: 'RUB' },
});

// Get a saved payment method
const method = await sdk.paymentMethods.get(payment.payment_method.id);

// Process a refund
const refund = await sdk.refunds.create({
    payment_id: payment.id,
    amount: { value: '299.00', currency: 'RUB' },
});
```

## Webhook Handling

```typescript
import { validateSignature, parseEvent } from 'yookassa-sdk';

// Validate webhook signature (use timingSafeEqual to prevent timing attacks)
const isValid = validateSignature(rawBody, signature, secretKey);
if (!isValid) {
    throw new Error('Invalid signature');
}

// Parse the event (type-safe)
const event = parseEvent(rawBody);

if (event.type === 'notification') {
    switch (event.event) {
        case 'payment.succeeded':
            console.log('Payment succeeded:', event.object.id);
            break;
        case 'payment.waiting_for_capture':
            console.log('Awaiting capture:', event.object.id);
            break;
        case 'refund.succeeded':
            console.log('Refund succeeded:', event.object.id);
            break;
    }
}
```

Or via the client:

```typescript
const sdk = new YooKassaClient({ shopId, secretKey });
const isValid = sdk.webhooks.validateSignature(rawBody, sig, secret);
const event = sdk.webhooks.parseEvent(rawBody);
```

## Error Handling

```typescript
import { YooKassaClient, YooKassaApiError, YooKassaNetworkError } from 'yookassa-sdk';

try {
    const payment = await sdk.payments.create({ /* ... */ });
} catch (error) {
    if (error instanceof YooKassaApiError) {
        console.log('API Error:', error.code, error.description);
        // Check error type
        if (error.isNotFound) { /* ... */ }
        if (error.isRateLimited) { /* ... */ }
        if (error.isBadRequest) { /* ... */ }
    } else if (error instanceof YooKassaNetworkError) {
        console.log('Network error:', error.message);
    }
}
```

## Configuration

```typescript
const sdk = new YooKassaClient({
    shopId: '123456',
    secretKey: 'live_...',
    
    // Request timeout (default: 30s)
    timeoutMs: 30_000,
    
    // Retry configuration (default: 3 attempts)
    retry: {
        maxAttempts: 3,
        baseDelayMs: 500,
        maxDelayMs: 10_000,
    },
    
    // Hooks for logging/monitoring
    hooks: {
        onRequest: (url) => console.log('-->', url),
        onResponse: (url, res, ms) => console.log('<--', res.status, ms + 'ms'),
    },
});
```

## API Reference

### Payments

| Method | Description |
|--------|-------------|
| `create(data)` | Create a new payment |
| `get(id)` | Get payment by ID |
| `capture(id, data?)` | Capture an authorized payment |
| `cancel(id)` | Cancel an authorized payment |
| `list(params?)` | List payments with filters |

### Refunds

| Method | Description |
|--------|-------------|
| `create(data)` | Create a refund |
| `get(id)` | Get refund by ID |
| `list(params?)` | List refunds with filters |

### Receipts

| Method | Description |
|--------|-------------|
| `create(data)` | Create a fiscal receipt |
| `get(id)` | Get receipt by ID |
| `list(params?)` | List receipts with filters |

### Payment Methods

| Method | Description |
|--------|-------------|
| `get(id)` | Get saved payment method details |
| `delete(id)` | Delete a saved payment method |

## Requirements

- Node.js 18.0.0 or higher

## License

MIT