@qazuor/qzpay-mercadopago
@qazuor/qzpay-mercadopago
Provider View on npm @qazuor/qzpay-mercadopago
MercadoPago integration for Latin American markets.
Installation
pnpm add @qazuor/qzpay-mercadopago mercadopagoSetup
import { createQZPayMercadoPagoAdapter } from '@qazuor/qzpay-mercadopago';
const mpAdapter = createQZPayMercadoPagoAdapter({ accessToken: process.env.MERCADOPAGO_ACCESS_TOKEN!, webhookSecret: process.env.MERCADOPAGO_WEBHOOK_SECRET});
// Or use the class directlyimport { QZPayMercadoPagoAdapter } from '@qazuor/qzpay-mercadopago';
const mpAdapter = new QZPayMercadoPagoAdapter({ accessToken: process.env.MERCADOPAGO_ACCESS_TOKEN!});Configuration Options
| Option | Type | Required | Description |
|---|---|---|---|
accessToken | string | Yes | MercadoPago access token |
webhookSecret | string | No | Webhook secret for verification |
Using with QZPay
import { createQZPayBilling } from '@qazuor/qzpay-core';import { createQZPayMercadoPagoAdapter } from '@qazuor/qzpay-mercadopago';import { createQZPayDrizzleAdapter } from '@qazuor/qzpay-drizzle';
const billing = createQZPayBilling({ storage: createQZPayDrizzleAdapter(db), paymentAdapter: createQZPayMercadoPagoAdapter({ accessToken: process.env.MERCADOPAGO_ACCESS_TOKEN! })});Sub-Adapters
The MercadoPago adapter provides access to specialized sub-adapters:
mpAdapter.customers // QZPayMercadoPagoCustomerAdaptermpAdapter.subscriptions // QZPayMercadoPagoSubscriptionAdaptermpAdapter.payments // QZPayMercadoPagoPaymentAdaptermpAdapter.checkout // QZPayMercadoPagoCheckoutAdaptermpAdapter.prices // QZPayMercadoPagoPriceAdaptermpAdapter.webhooks // QZPayMercadoPagoWebhookAdapterCustomer Adapter
// Create customerconst customerId = await mpAdapter.customers.create({ email: 'user@example.com', name: 'John Doe'});
// Update customerawait mpAdapter.customers.update(customerId, { name: 'Jane Doe'});
// Delete customerawait mpAdapter.customers.delete(customerId);
// Retrieve customer detailsconst customer = await mpAdapter.customers.retrieve(customerId);Payment Adapter
// Create paymentconst payment = await mpAdapter.payments.create(customerId, { amount: 9900, // in cents currency: 'ars', paymentMethodId: 'visa'});
// Capture authorized paymentawait mpAdapter.payments.capture(paymentId);
// Cancel paymentawait mpAdapter.payments.cancel(paymentId);
// Refund paymentconst refund = await mpAdapter.payments.refund({ amount: 5000, reason: 'customer_request'}, paymentId);
// Retrieve paymentconst payment = await mpAdapter.payments.retrieve(paymentId);Subscription Adapter
MercadoPago uses “Preapprovals” for subscriptions:
// Create subscriptionconst subscription = await mpAdapter.subscriptions.create( customerId, { trialPeriodDays: 7 }, 'plan_xxx' // preapproval plan ID);
// Update subscriptionawait mpAdapter.subscriptions.update(subscriptionId, { metadata: { tier: 'pro' }});
// Cancel subscriptionawait mpAdapter.subscriptions.cancel(subscriptionId, false); // immediately
// Pause subscriptionawait mpAdapter.subscriptions.pause(subscriptionId);
// Resume subscriptionawait mpAdapter.subscriptions.resume(subscriptionId);Checkout Adapter (Preferences)
// Create checkout preferenceconst session = await mpAdapter.checkout.create({ mode: 'subscription', successUrl: 'https://example.com/success', cancelUrl: 'https://example.com/cancel'}, ['plan_xxx']);
// session.init_point - URL to redirect user// session.sandbox_init_point - Sandbox URL for testing
// Retrieve preferenceconst preference = await mpAdapter.checkout.retrieve(preferenceId);
// Expire preferenceawait mpAdapter.checkout.expire(preferenceId);Price Adapter (Plans)
// Create a product (returns plan name as ID)const productId = await mpAdapter.prices.createProduct( 'Pro Plan', 'Monthly subscription');
// Create a price/planconst priceId = await mpAdapter.prices.create({ amount: 2900, currency: 'ars', interval: 'month', intervalCount: 1}, productId);
// Archive a priceawait mpAdapter.prices.archive(priceId);Webhook Handling (IPN)
import { extractMPPaymentEventData, extractMPSubscriptionEventData, classifyMPEvent, mpRequiresImmediateAction} from '@qazuor/qzpay-mercadopago';
// Construct and verify webhook eventconst event = mpAdapter.webhooks.constructEvent( rawBody, signature // x-signature header);
// Verify signature only (HMAC-SHA256)const isValid = mpAdapter.webhooks.verifySignature(rawBody, signature);
// Extract event dataconst paymentData = extractMPPaymentEventData(event);const subscriptionData = extractMPSubscriptionEventData(event);
// Classify event typeconst category = classifyMPEvent(event.type);// Returns: 'payment' | 'subscription' | 'chargeback' | 'other'
// Check if requires immediate actionif (mpRequiresImmediateAction(event)) { // Handle urgent events (chargebacks, failed payments)}IPN Handler
For more control over IPN processing:
import { QZPayMercadoPagoIPNHandler } from '@qazuor/qzpay-mercadopago';
const ipnHandler = new QZPayMercadoPagoIPNHandler(mpAdapter);
// Register handlersipnHandler.on('payment', async (notification) => { console.log('Payment notification:', notification.id);});
ipnHandler.on('subscription_preapproval', async (notification) => { console.log('Subscription notification:', notification.id);});
// Process incoming IPNconst result = await ipnHandler.process(notification);3D Secure Support
import { isPaymentEventRequires3DS, extractMP3DSFromPaymentEvent, getMP3DSChallengeUrl} from '@qazuor/qzpay-mercadopago';
// Check if payment requires 3DSif (isPaymentEventRequires3DS(event)) { const threeDSInfo = extractMP3DSFromPaymentEvent(event); const challengeUrl = getMP3DSChallengeUrl(event);
// Redirect user to challenge URL return redirect(challengeUrl);}Status Mapping
Payment Status
| MercadoPago | QZPay |
|---|---|
pending | pending |
approved | succeeded |
authorized | requires_capture |
in_process | processing |
in_mediation | disputed |
rejected | failed |
cancelled | canceled |
refunded | refunded |
charged_back | disputed |
Subscription Status
| MercadoPago | QZPay |
|---|---|
pending | pending |
authorized | active |
paused | paused |
cancelled | canceled |
Constants
import { MERCADOPAGO_SUBSCRIPTION_STATUS, MERCADOPAGO_PAYMENT_STATUS, MERCADOPAGO_WEBHOOK_EVENTS, MERCADOPAGO_BILLING_INTERVAL, MERCADOPAGO_STATUS_DETAIL} from '@qazuor/qzpay-mercadopago';Regional Configuration
MercadoPago operates in multiple countries:
| Country | Currency | Site ID |
|---|---|---|
| Argentina | ARS | MLA |
| Brazil | BRL | MLB |
| Mexico | MXN | MLM |
| Chile | CLP | MLC |
| Colombia | COP | MCO |
| Peru | PEN | MPE |
| Uruguay | UYU | MLU |
Testing
Use sandbox credentials for development:
MERCADOPAGO_ACCESS_TOKEN=TEST-xxxMERCADOPAGO_WEBHOOK_SECRET=xxxThe adapter automatically detects sandbox mode from the access token.
Test Cards
| Card Number | Result |
|---|---|
5031 7557 3453 0604 | Approved (Mastercard) |
4509 9535 6623 3704 | Approved (Visa) |
3711 803032 57522 | Approved (Amex) |
Accessing MercadoPago Client
For advanced use cases:
const client = mpAdapter.getMercadoPagoClient();