@mateosuarezdev/easy-mercadopago
v1.0.9
Published
A comprehensive MercadoPago service for Bun and Node.js with retry logic, webhook verification, and payment status polling
Maintainers
Readme
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
npm install @mateosuarezdev/easy-mercadopago mercadopagoQuick Start
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:
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.comBasic Usage
1. Create a Payment (API Endpoint)
// 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)
// 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)
// 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
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
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: "[email protected]",
},
});Error Handling
The library uses a safe result pattern:
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:
import {
MercadopagoService,
CheckoutData,
PaymentStatus,
} from "@mateosuarezdev/easy-mercadopago";Examples
Check out the examples folder for complete implementations:
Common Patterns
E-commerce API Flow
// 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
// 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
License
MIT License - see LICENSE file.
