Mercado Pago Integration
Initial Instructions
How to Create a Development App Using the Checkout API
- Visit the Mercado Pago Developer Portal.
- Create an account or log in if you already have one.
- Navigate to the My Apps section and click Create App.
- Fill in the necessary details such as App Name and Description.
- Make sure to select Checkout API as the integration type.
How to Specify the Callback URL
- Set the Redirect URI as required for OAuth flows.
- For local development, it’s highly recommended to use a tool like ngrok to expose your local server over HTTPS. This is required as Mercado Pago only accepts URLs with HTTPS.
- Example:
https://e4b7-2800-a4-93e-a100-65dd-80de-e655-62c1.ngrok-free.app/mercado-pago/oauth_callback
How to Fill in the Following Data
In your Django settings or environment variables, fill in the following keys:
- MERCADO_PAGO_CLIENT_ID: You can find this in the My Apps section of your Mercado Pago account after creating an app.
- MERCADO_PAGO_CLIENT_SECRET: This is also available in the My Apps section, under the app details.
- MERCADO_PAGO_REDIRECT_URI: This is the URL where Mercado Pago will redirect after the OAuth flow. Use the ngrok URL for local development.
- MERCADO_PAGO_PUBLIC_KEY: Available in the Credentials section of your app in Mercado Pago.
- MERCADO_PAGO_ACCOUNT_ID: This is your Collector ID, which can be found in the Account Settings section of your Mercado Pago account.
MERCADO_PAGO_CLIENT_ID = '4064746753721270'
MERCADO_PAGO_CLIENT_SECRET = 'your_client_secret'
MERCADO_PAGO_REDIRECT_URI = 'https://e4b7-2800-a4-93e-a100-65dd-80de-e655-62c1.ngrok-free.app/mercado-pago/oauth_callback'
MERCADO_PAGO_PUBLIC_KEY = 'your_public_key'
MERCADO_PAGO_ACCOUNT_ID = 'your_collector_id'
Base Helper Class
We have a helper class for integrating with Mercado Pago. Assuming the app is named payment
, add the following class in payments/services/MercadoPago.py
. The class can be placed anywhere; this is just a practice given by our company.
class MercadoPagoBase(ABC):
@abstractmethod
def generate_token(self):
pass
@staticmethod
def register_application_link():
token = self.generate_token()
encoded_redirect_uri = quote(f"{settings.MERCADO_PAGO_REDIRECT_URI}", safe='')
auth_url = (
f"https://auth.mercadopago.com/authorization"
f"?client_id={settings.MERCADO_PAGO_CLIENT_ID}"
f"&response_type=code"
f"&platform_id=mp"
f"&redirect_uri={encoded_redirect_uri}"
f"&state={token}"
)
return auth_url
@staticmethod
def register_application_callback(code):
data = {
'grant_type': 'authorization_code',
'client_id': settings.MERCADO_PAGO_CLIENT_ID,
'client_secret': settings.MERCADO_PAGO_CLIENT_SECRET,
'code': code,
'redirect_uri': settings.MERCADO_PAGO_REDIRECT_URI,
}
response = requests.post('https://api.mercadopago.com/oauth/token', data=data)
if response.status_code == 200:
tokens = response.json()
mp_account, _ = MercadoPagoAccount.objects.get_or_create()
mp_account.mercado_pago_user_id = tokens.get('user_id')
mp_account.access_token = tokens.get('access_token')
mp_account.refresh_token = tokens.get('refresh_token')
mp_account.expires_at = timezone.now() + timedelta(seconds=tokens.get('expires_in', 0))
mp_account.save()
return mp_account
@staticmethod
def create_split_payment(mp_account, amount, payment_method, buyer_email, fee_percentage):
"""Create a new split payment on the specified account with the fee applied to the principal account"""
payment_data = {
"transaction_amount": amount,
"description": "Service Payment",
"payment_method_id": payment_method,
"payer": {
"email": buyer_email
},
"application_fee": amount * fee_percentage,
"collector_id": settings.MERCADO_PAGO_ACCOUNT_ID
}
headers = {
"Authorization": f"Bearer {mp_account.access_token}",
"Content-Type": "application/json",
}
response = requests.post('https://api.mercadopago.com/v1/payments', headers=headers, json=payment_data)
if response.status_code == 201:
return response.json()
@staticmethod
def create_new_payment(amount):
"""Create a new payment for the principal account"""
preference_data = {
"items": [
{
"title": "Monthly Subscription",
"quantity": 1,
"unit_price": amount,
}
],
"auto_return": "approved",
}
headers = {
"Authorization": f"Bearer {settings.MERCADO_PAGO_ACCESS_TOKEN}",
"Content-Type": "application/json",
}
response = requests.post('https://api.mercadopago.com/checkout/preferences', headers=headers,
json=preference_data)
if response.status_code == 201:
return response.json()
Then create a class that inherits from this one and specifies the following method to get the token, for example:
class MercadoPagoService(MercadoPagoBase):
@staticmethod
def generate_token():
user = get_user_model().objects.get(name__icontains='Vendedor')
token = VerificationToken.generate_token_for_user(user, VerificationToken.Type.MERCADO_PAGO)
return token.token
You will also need to add the following model, which you can extend as needed:
class MercadoPagoAccount(models.Model):
mercado_pago_user_id = models.CharField(max_length=255, null=True, blank=True)
access_token = models.CharField(max_length=255, null=True, blank=True)
refresh_token = models.CharField(max_length=255, null=True, blank=True)
expires_at = models.DateTimeField(null=True, blank=True)
Then declare the relationship to this new Mercado Pago account model in the appropriate model.
With this, you are ready to start integrating Mercado Pago using the specified classes.
Integrating Payments
Split Payments Integration
To integrate split payments, refer to the following link from the Mercado Pago documentation: Split Payments Integration
The split payment feature allows you to create payments where part of the payment is sent to another account, and the rest is kept by your collector account.
Step-by-Step Usage Example with Views
Step 1: User Initiates Application Registration
In your web application, provide a button that users can click to register their Mercado Pago account. When they click this button, make a request to the following view:
@action(detail=False, methods=['post'])
def register_application(self, request):
auth_url = MercadoPagoService.register_application_link()
return Response({'auth_url': auth_url})
- User Interaction: The user clicks a button to connect their Mercado Pago account.
- Backend Action: This calls
register_application_link()
, which returns anauth_url
that redirects the user to Mercado Pago for authorization.
Step 2: User Authorizes the Application
The user is redirected to Mercado Pago where they authorize the application to access their data.
- User Interaction: The user approves the requested permissions on the Mercado Pago authorization page.
Step 3: Handling the OAuth Callback
After the user authorizes the application, Mercado Pago redirects them to the callback URL (MERCADO_PAGO_REDIRECT_URI
). You need a view to handle this callback:
@action(detail=False, methods=['get'])
def oauth_callback(self, request):
serializer = CallBackSerializer(data=request.query_params)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
token = data.get('state')
code = data.get('code')
try:
verification_token = VerificationToken.objects.get(token=token,
token_type=VerificationToken.Type.MERCADO_PAGO,
expires_at__gte=timezone.now())
user = verification_token.user
except VerificationToken.DoesNotExist:
return Response({'error': 'Invalid or expired token'}, status=status.HTTP_400_BAD_REQUEST)
account = MercadoPagoService.register_application_callback(code, user)
if isinstance(account, MercadoPagoAccount):
return Response({'message': 'Application registered successfully'})
else:
return Response({'error': account.get('error', 'Failed to obtain access token')}, status=status.HTTP_400_BAD_REQUEST)
- User Interaction: No direct interaction; this happens after the user approves the authorization on Mercado Pago.
- Backend Action: This view handles the callback, validates the
code
andstate
, and saves the tokens toMercadoPagoAccount
for the user.
Step 4: Create a Payment for a Registered Company
Once the user’s Mercado Pago account is registered, they can initiate a payment. Use the following view to create a split payment:
@action(detail=False, methods=['post'])
def create_payment_for_company(self, request):
user = request.user
serializer = SplitPaymentSerializer(data=request.data, context={'user': user})
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
payment_info = MercadoPagoService.create_split_payment(
data.get('company').mercado_pago_account,
data.get('amount'),
data.get('payment_method'),
user.email,
3
)
if 'error' in payment_info:
return Response({'error': payment_info['error']}, status=status.HTTP_400_BAD_REQUEST)
return Response({'payment_info': payment_info})
- User Interaction: The user requests to create a payment.
- Backend Action: This view calls
create_split_payment()
, which handles the logic to split the payment and returns payment details.