Принимайте платежи по всей Латинской Америке
Receive payments on your Medusa commerce application using Mercado Pago.
Medusa Payment Mercadopago Repository | Medusa Website | Medusa Repository
[!WARNING] This plugin is a WIP and has only been tested for Credit / Debit Card methods following Mercado Pago docs for Uruguay. You can sumbit issues through GitHub Issues. Feel free to make contributions by making pull requests and proposing ideas / new flows to implement via Discussions
1. Run the following command in the directory of the Medusa backend using your package manager (for example for npm):
2. Set the following environment variables in :
3. In add the following at the end of the array in your project config object:
4. In add the following to the array in your project config object:
The single entry registers two payment providers that share a common base:
| Provider | Payment provider id | Use case |
|---|---|---|
| Regular payments | One-off card payments | |
| Recurring payments | Mercado Pago subscriptions |
Both become selectable at checkout — enable whichever you need per region/payment configuration. They share the block above.
The provider creates a preapproval (a recurring charge mandate) at checkout, reusing the same Payment Brick card tokenization as one-off payments. Mercado Pago's engine then charges the buyer automatically every cycle — no cron or capture logic needed on your side.
The provider's creates the preapproval with and = payment session id. Re-initiating a session deletes the previous one, which cancels any stale preapproval automatically. 3. The storefront completes the cart as usual ( → ); verifies the preapproval and the Medusa payment is authorized. 4. Mercado Pago creates the first charge asynchronously (it can take minutes to hours). When its webhook reports the charge approved, the Medusa payment flips to captured.
Canceling the Medusa payment cancels the whole subscription at Mercado Pago. See Refunds below.
Recurring charges beyond the first have no Medusa payment session, so while handling webhooks the provider re-emits every subscription notification on Medusa's event bus. Subscribe from your own subscription module — the plugin is intentionally not coupled to any:
| Event | Emitted when | Payload |
|---|---|---|
| Preapproval created / status change (authorized, paused, cancelled) | ||
| A recurring charge (invoice) is created or updated — every cycle, approved or rejected |
is the Medusa payment session id used at checkout — correlate it (or , stored in the payment's ) with your own subscription records. Event names and payload types are exported from the package (, , ).
[!NOTE] Delivery is at-least-once: Mercado Pago re-sends webhooks and Medusa's webhook subscriber retries failed events, so the same notification can produce duplicate events. Deduplicate in your subscriber — e.g. key on + for charges, + for subscription updates.
Example subscriber:
Use Medusa's standard refund (admin UI or the payment module's ) — the provider maps it to refunding the most recent charged cycle at Mercado Pago (partial amounts supported). Only the checkout cycle has a Medusa payment record, so older cycles are refunded directly at Mercado Pago (dashboard or refunds API) using the from the event.
Subscriptions have stricter test-mode requirements than one-off payments:
Deferred for now (contributions welcome): redirect-based authorization via (subscription without card token), preapproval plans ().
1. Run the following command in the directory of the Medusa backend to run the backend:
npm run dev2. Enable Mercadopago in a region in the admin. Alternatively, you can use the Admin APIs.
3. Place an order using a frontend that collects payment data using Mercadopago Payment brick like this. Send a POST to with a body that adheres to validator
npm install @nicogorga/medusa-payment-mercadopago1# Access Token available in your Mercado Pago application Test Credentials section2MERCADOPAGO_ACCESS_TOKEN=3# (Optional) Webhook secret available in your Mercado Pago application Webhooks section4MERCADOPAGO_WEBHOOK_SECRET=1projectConfig: {2 plugins = [3 // ...4 {5 resolve: `@nicogorga/medusa-payment-mercadopago`,6 options: {},7 },8 ];9}1modules: [2 {3 resolve: '@medusajs/medusa/payment',4 options: {5 providers: [6 {7 resolve: '@nicogorga/medusa-payment-mercadopago/providers',8 id: 'mercadopago',9 options: {10 accessToken: process.env.MERCADOPAGO_ACCESS_TOKEN,11 webhookSecret: process.env.MERCADOPAGO_WEBHOOK_SECRET,12 },13 dependencies: [14 ContainerRegistrationKeys.LOGGER,15 Modules.EVENT_BUS16 ]17 }18 ],19 }20 }21 ],1await sdk.store.payment.initiatePaymentSession(cart, {2 provider_id: "pp_mercadopago-subscription_mercadopago",3 data: {4 card_token_id: "<Brick formData.token>",5 payer_email: "buyer@example.com", // optional — falls back to the authenticated customer's email6 reason: "Monthly box", // optional7 auto_recurring: {8 frequency: 1,9 frequency_type: "months", // or "days"; end_date and free_trial also supported10 },11 },12});1// src/subscribers/mp-subscription-charge.ts2import { SubscriberArgs, SubscriberConfig } from "@medusajs/framework";3import { SubscriptionChargeEventPayload } from "@nicogorga/medusa-payment-mercadopago/types";4
5export default async function chargeHandler({6 event: { data },7}: SubscriberArgs<SubscriptionChargeEventPayload>) {8 // e.g. create a new order for this cycle, or flag a failed charge9}10
11export const config: SubscriberConfig = {12 event: "mercadopago.subscription.charge.updated",13};