| name | mercadopago-integration |
| description | Integrate MercadoPago OAuth payments into web applications. Use when adding MercadoPago payment processing, OAuth account connection, or checkout functionality. Covers Supabase Edge Functions, React/frontend setup, and database schema for multi-tenant SaaS platforms. |
MercadoPago Integration
Enable MercadoPago OAuth payments in web applications with proper security and multi-tenant support.
When to Use
- Adding MercadoPago payments to an app
- Setting up OAuth connection for marketplace/platform payments
- Troubleshooting MercadoPago integration issues
- Implementing checkout with MercadoPago
Preflight Checklist
Before starting, gather these values:
From Supabase Dashboard
URLs You'll Configure
Environment Variables Summary
| Location | Variable | Example |
|---|
| Frontend .env | VITE_MP_CLIENT_ID | 1234567890 |
| Frontend .env | VITE_MP_REDIRECT_URI | https://xyz.supabase.co/functions/v1/mercadopago-auth |
| Edge Function Secrets | MP_CLIENT_ID | 1234567890 |
| Edge Function Secrets | MP_CLIENT_SECRET | abcdef123456... |
| Edge Function Secrets | FRONTEND_URL | https://myapp.vercel.app |
| Edge Function Secrets | SUPABASE_SERVICE_ROLE_KEY | (from Supabase dashboard) |
Architecture
Frontend (Dashboard) -> MercadoPago Authorization -> Supabase Edge Function -> Database
^ |
+-------------- redirect with tokens ----------------+
Quick Start Checklist
- MercadoPago Dashboard: Create app, add redirect URI, get Client ID/Secret
- Frontend .env: Set
VITE_MP_CLIENT_ID and VITE_MP_REDIRECT_URI
- Edge Function Secrets: Set
MP_CLIENT_ID, MP_CLIENT_SECRET, FRONTEND_URL, SUPABASE_SERVICE_ROLE_KEY
- Database: Add mercadopago columns to tenants/users table
- Deploy:
supabase functions deploy mercadopago-auth
Implementation
Frontend - Initiate OAuth
const MP_CLIENT_ID = import.meta.env.VITE_MP_CLIENT_ID;
const MP_REDIRECT_URI = import.meta.env.VITE_MP_REDIRECT_URI;
const authUrl = `https://auth.mercadopago.com.ar/authorization-` +
`client_id=${MP_CLIENT_ID}&response_type=code&platform_id=mp&` +
`redirect_uri=${encodeURIComponent(MP_REDIRECT_URI)}&state=${tenantId}`;
window.location.href = authUrl;
Frontend - Handle Callback
useEffect(() => {
const mpSuccess = searchParams.get('mp_success');
if (mpSuccess === 'true') {
refreshTenant();
toast({ title: 'MercadoPago conectado' });
searchParams.delete('mp_success');
setSearchParams(searchParams, { replace: true });
}
}, [searchParams]);
Edge Function - Token Exchange
See assets/supabase-edge-function.ts for complete implementation.
Key points:
- Use
SUPABASE_SERVICE_ROLE_KEY to bypass RLS when saving tokens
redirect_uri in token exchange MUST match exactly what's in MP dashboard
- Return redirect to
FRONTEND_URL with success/error params
Database Schema
ALTER TABLE public.tenants
ADD COLUMN IF NOT EXISTS mercadopago_access_token TEXT,
ADD COLUMN IF NOT EXISTS mercadopago_refresh_token TEXT,
ADD COLUMN IF NOT EXISTS mercadopago_user_id TEXT,
ADD COLUMN IF NOT EXISTS mercadopago_public_key TEXT,
ADD COLUMN IF NOT EXISTS mercadopago_connected_at TIMESTAMPTZ;
Common Errors
| Error | Cause | Fix |
|---|
token_exchange_failed | redirect_uri mismatch | Ensure EXACT match in MP dashboard, frontend, and edge function |
missing_params | No code/state in callback | Check OAuth URL includes state parameter |
| Redirect to localhost | FRONTEND_URL not set | Set in edge function secrets |
| Tokens not saved | DB permissions | Use service role key |
| "App can't connect" | MP app misconfiguration | Check MP dashboard settings |
Webhook Setup
Webhooks notify your app when payment status changes (e.g., payment approved).
1. Create Webhook Edge Function
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
serve(async (req) => {
if (req.method !== "POST") {
return new Response("Method not allowed", { status: 405 });
}
const body = await req.json();
if (body.action === "payment.updated" || body.action === "payment.created") {
const paymentId = body.data-.id;
const paymentResponse = await fetch(
`https://api.mercadopago.com/v1/payments/${paymentId}`,
{
headers: {
Authorization: `Bearer ${Deno.env.get("MP_ACCESS_TOKEN")}`,
},
}
);
const payment = await paymentResponse.json();
const supabase = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
);
const orderId = payment.external_reference;
if (payment.status === "approved") {
await supabase
.from("orders")
.update({ payment_status: "paid" })
.eq("id", orderId);
} else if (payment.status === "rejected") {
await supabase
.from("orders")
.update({ payment_status: "failed" })
.eq("id", orderId);
}
}
return new Response("OK", { status: 200 });
});
2. Configure Webhook in MercadoPago Dashboard
- Go to MercadoPago Developers
- Select your application
- Go to Webhooks or IPN/Notifications
- Add webhook URL:
https://<project-ref>.supabase.co/functions/v1/mercadopago-webhook
- Select events:
payment (payment status changes)
merchant_order (optional)
3. Test Webhook
supabase functions deploy mercadopago-webhook
curl -X POST https://<project>.supabase.co/functions/v1/mercadopago-webhook \
-H "Content-Type: application/json" \
-d '{"action":"payment.updated","data":{"id":"test123"}}'
Resources
- assets/supabase-edge-function.ts: Complete OAuth edge function template
- assets/use-mercadopago.tsx: React hook for OAuth flow
- assets/migration.sql: Database migration template
- references/troubleshooting.md: Detailed debugging guide