npm package: @mateosuarezdev/easy-mercadopago
Description: A comprehensive MercadoPago service for Bun and Node.js with retry logic, webhook verification, and payment status polling
Author: Mateo Suárez
Latest version: 1.0.9

# Easy MercadoPago

A simple, TypeScript-first MercadoPago integration for Node.js and Bun. Handle payments, webhooks, and more with just a few lines of code.

## Features

✅ **Simple Setup** - Works out of the box  
✅ **TypeScript Support** - Full type safety  
✅ **Automatic Retries** - Built-in error handling  
✅ **Webhook Verification** - Secure webhook processing  
✅ **Payment Polling** - Real-time status updates  
✅ **Dual Package** - Works with both CommonJS and ESM

## Installation

```bash
npm install @mateosuarezdev/easy-mercadopago mercadopago
```

## Quick Start

```typescript
import { MercadopagoService } from "@mateosuarezdev/easy-mercadopago";

const mp = new MercadopagoService({
  mode: "test", // or "production"
  testAccessToken: "YOUR_TEST_TOKEN",
  testWebhookSecret: "YOUR_WEBHOOK_SECRET",
  baseUrl: "https://yoursite.com",
  backPaths: {
    success: "/success",
    failure: "/failure",
    pending: "/pending",
  },
});

// Create a payment
const { error, data } = await mp.createPreference({
  external_reference: mp.createExternalReference("order", "123"),
  items: [
    {
      id: "item1",
      title: "Cool Product",
      quantity: 1,
      unit_price: 100,
      currency_id: "USD",
    },
  ],
});

if (data) {
  // Return payment URL to your frontend
  return { paymentUrl: data.initPoint };
}
```

## Environment Setup

Create a `.env` file:

```env
MERCADOPAGO_TEST_ACCESS_TOKEN=your_test_token_here
MERCADOPAGO_TEST_WEBHOOK_SECRET=your_webhook_secret_here
MERCADOPAGO_PROD_ACCESS_TOKEN=your_prod_token_here
MERCADOPAGO_PROD_WEBHOOK_SECRET=your_prod_webhook_secret_here
BASE_URL=https://yoursite.com
```

## Basic Usage

### 1. Create a Payment (API Endpoint)

```typescript
// In your Express.js route
app.post("/api/create-payment", async (req, res) => {
  const { orderId, items } = req.body;

  const { error, data } = await mp.createPreference({
    external_reference: mp.createExternalReference("order", orderId),
    items: items.map((item) => ({
      id: item.id,
      title: item.name,
      quantity: item.quantity,
      unit_price: item.price,
      currency_id: "USD",
    })),
  });

  if (error) {
    return res.status(400).json({ error: error.message });
  }

  // Send payment URL to frontend
  res.json({
    paymentUrl: data.initPoint,
    preferenceId: data.id,
  });
});
```

### 2. Handle Webhooks (API Endpoint)

```typescript
// Webhook endpoint to receive payment notifications
app.post("/api/webhooks/mercadopago", async (req, res) => {
  const signature = req.headers["x-signature"];
  const requestId = req.headers["x-request-id"];
  const paymentId = req.query["data.id"];

  // Verify webhook security
  if (!mp.verifyWebhookSignature(paymentId, signature, requestId)) {
    return res.status(401).send("Invalid signature");
  }

  // Get payment data from MercadoPago
  const { data: payment } = await mp.getPaymentData(paymentId);

  if (payment.status === "approved") {
    // Update your database
    const parsed = mp.parseExternalReference(payment.external_reference);
    if (parsed?.type === "order") {
      await updateOrderStatus(parsed.id, "paid");
      await sendConfirmationEmail(parsed.id);
    }
  }

  res.status(200).json({ ok: true });
});
```

### 3. Check Payment Status (API Endpoint)

```typescript
// API endpoint to check payment status
app.get("/api/payment-status/:paymentId", async (req, res) => {
  const { paymentId } = req.params;

  // Get current payment status
  const { error, data: payment } = await mp.getPaymentData(paymentId);

  if (error) {
    return res.status(404).json({ error: "Payment not found" });
  }

  res.json({
    status: payment.status,
    amount: payment.transaction_amount,
    externalRef: payment.external_reference,
  });
});

// Or poll until payment is complete (for background jobs)
const { data: payment } = await mp.pollPaymentStatus(paymentId, {
  interval: 2000, // Check every 2 seconds
  maxAttempts: 30, // For 1 minute total
});
```

## Configuration Options

```typescript
new MercadopagoService({
  mode: "test" | "production",
  testAccessToken: string,
  prodAccessToken: string,
  testWebhookSecret: string,
  prodWebhookSecret: string,
  baseUrl: string, // Your site URL
  backPaths: {
    // Where to redirect after payment
    success: "/success",
    failure: "/failure",
    pending: "/pending",
  },
  timeout: number, // Default: 5000ms
  debug: boolean, // Default: true
  maxRetries: number, // Default: 3
  retryDelay: number, // Default: 1000ms
});
```

## Payment with Customer Info

```typescript
const { data } = await mp.createPreference({
  external_reference: mp.createExternalReference("order", "123"),
  items: [
    {
      id: "item1",
      title: "Product",
      quantity: 1,
      unit_price: 100,
      currency_id: "USD",
    },
  ],
  payer: {
    name: "John",
    surname: "Doe",
    email: "john@example.com",
  },
});
```

## Error Handling

The library uses a safe result pattern:

```typescript
const { error, data } = await mp.createPreference(/* ... */);

if (error) {
  console.log("Something went wrong:", error.message);
  return;
}

// Use data safely
console.log("Payment URL:", data.initPoint);
```

## TypeScript Support

Full TypeScript support included:

```typescript
import {
  MercadopagoService,
  CheckoutData,
  PaymentStatus,
} from "@mateosuarezdev/easy-mercadopago";
```

## Examples

Check out the [examples folder](examples/) for complete implementations:

- [Basic E-commerce](examples/basic-ecommerce.ts)
- [Express.js Integration](examples/express-webhook.ts)
- [Next.js API Routes](examples/nextjs-api.ts)

## Common Patterns

### E-commerce API Flow

```typescript
// 1. Create payment endpoint
app.post("/api/checkout", async (req, res) => {
  const { userId, cartItems } = req.body;

  // Create order in your database
  const order = await db.orders.create({ userId, items: cartItems });

  // Create MercadoPago payment
  const { error, data } = await mp.createPreference({
    external_reference: mp.createExternalReference("order", order.id),
    items: cartItems.map((item) => ({
      id: item.productId,
      title: item.name,
      quantity: item.quantity,
      unit_price: item.price,
      currency_id: "USD",
    })),
    notification_url: "https://yourapi.com/api/webhooks/mercadopago",
  });

  if (error) {
    return res.status(400).json({ error: error.message });
  }

  // Return payment URL to frontend
  res.json({
    paymentUrl: data.initPoint,
    orderId: order.id,
  });
});
```

### Webhook Processing

```typescript
// In your webhook handler
app.post("/api/webhooks/mercadopago", async (req, res) => {
  // ... verification code ...

  const { data: payment } = await mp.getPaymentData(paymentId);
  const parsed = mp.parseExternalReference(payment.external_reference);

  if (parsed?.type === "order") {
    // Update order status in database
    await db.orders.update(parsed.id, {
      status: payment.status === "approved" ? "paid" : "failed",
      paymentId: payment.id,
      paidAt: payment.status === "approved" ? new Date() : null,
    });

    // Send notification email
    if (payment.status === "approved") {
      await emailService.sendOrderConfirmation(parsed.id);
    }
  }

  res.status(200).json({ ok: true });
});
```

## Requirements

- Node.js 18+ or Bun 1.0+
- MercadoPago account (test or production)

## Support

- 📖 [Full Documentation](docs/)
- 🐛 [Report Issues](https://github.com/mateosuarezdev/easy-mercadopago/issues)
- 💬 [Discussions](https://github.com/mateosuarezdev/easy-mercadopago/discussions)

## License

MIT License - see [LICENSE](LICENSE) file.