Como migrar para a nova versão do PSE
O Checkout API conta com uma nova integração PSE, que permite aos compradores utilizar este meio de pagamento de forma mais simplificada.
Caso você já tenha implementado uma integração PSE no Checkout API, é possível atualizar para a nova versão, adicionando campos adicionais no processo de criação do pagamento. Para isso, siga as etapas descritas abaixo.
Adicionar novos campos ao formulário de pagamento
Client-Side
Para iniciar a migração, é necessário incluir novos campos obrigatórios ao formulário de pagamento já integrado ao seu projeto. Esses novos campos estão relacionados ao endereço e telefone do comprador, conforme detalhado na tabela abaixo:
Campo | Descripción |
payer.address.zip_code | Código postal do comprador. |
payer.address.street_name | Nome da rua onde o comprador reside. |
payer.address.street_number | Número da residência do comprador. |
payer.address.neighborhood | Nome do bairro onde o comprador reside. |
payer.address.city | Cidade do comprador. |
payer.phone.area_code | Código de área do telefone do comprador. |
payer.phone.number | Número de telefone do comprador. |
No exemplo abaixo, você encontrará uma nova estrutura de código que inclui todos esses campos obrigatórios e os elementos HTML
necessários nas próximas etapas.
HTML
<form id="form-checkout" action="/process_payment" method="post">
<div>
<div>
<label for="zipCode">Zip Code</label>
<input id="form-checkout__zipCode" name="zipCode" type="text">
</div>
<div>
<label for="streetName">Street Name</label>
<input id="form-checkout__streetName" name="streetName" type="text">
</div>
<div>
<label for="streetNumber">Street Number</label>
<input id="form-checkout__streetNumber" name="streetNumber" type="text">
</div>
<div>
<label for="neighborhood">Neighborhood</label>
<input id="form-checkout__neighborhood" name="neighborhood" type="text">
</div>
<div>
<label for="city">Ciudad</label>
<input id="form-checkout__city" name="city" type="text">
</div>
<div>
<label for="federalUnit">Unidad Federal</label>
<input id="form-checkout__federalUnit" name="federalUnit" type="text">
</div>
<div>
<label for="phoneAreaCode">PhoneAreaCode</label>
<input id="form-checkout__phoneAreaCode" name="phoneAreaCode" type="text">
</div>
<div>
<label for="phoneNumber">PhoneNumber</label>
<input id="form-checkout__phoneNumber" name="phoneNumber" type="text">
</div>
<div>
<label for="email">E-mail</label>
<input id="form-checkout__email" name="email" type="text">
</div>
<div>
<label for="personType">Tipo de persona</label>
<select id="form-checkout__personType" name="personType" type="text">
<option value="natural">Natural</option>
<option value="juridica">Jurídica</option>
</select>
</div>
<div>
<label for="identificationType">Tipo de documento</label>
<select id="form-checkout__identificationType" name="identificationType" type="text"></select>
</div>
<div>
<label for="identificationNumber">Número del documento</label>
<input id="form-checkout__identificationNumber" name="identificationNumber" type="text">
</div>
</div>
<div>
<div>
<label for="banksList">Banco</label>
<div id="banksList"></div>
</div>
</div>
<div>
<div>
<input type="hidden" name="transactionAmount" id="transactionAmount" value="100">
<input type="hidden" name="description" id="description" value="Nome do Produto">
<br>
<button type="submit">Pagar</button>
</div>
</div>
</form>
Obter tipos de documentos
Client-Side
Nesta integração com o PSE, é necessário coletar e enviar somente os documentos que correspondam ao tipo de pessoa - física ou jurídica - selecionada ao adicionar o formulário de pagamento.
Esta é uma mudança em relação à antiga integração, na qual esta diferenciação não era necessária.
Para obter os tipos de documentos automaticamente, utilize a seguinte função:
javascript
document.getElementById('form-checkout__personType').addEventListener('change', e => {
const personTypesElement = document.getElementById('form-checkout__personType');
updateSelectOptions(personTypesElement.value);
});
function updateSelectOptions(selectedValue) {
const naturalDocTypes = [
new Option('C.C', 'CC'),
new Option('C.E.', 'CE'),
new Option('Pasaporte', 'PAS'),
new Option('Tarjeta de Extranjería', 'TE'),
new Option('Tarjeta de Identidad ', 'TI'),
new Option('Registro Civil', 'RC'),
new Option('Documento de Identificación', 'DI')
];
const juridicaDocTypes = [
new Option('NIT', 'NIT')
];
const idDocTypes = document.getElementById('form-checkout__identificationType');
if (selectedValue === 'natural') {
idDocTypes.options.length = 0;
naturalDocTypes.forEach(item => idDocTypes.options.add(item, undefined));
} else {
idDocTypes.options.length = 0;
juridicaDocTypes.forEach(item => idDocTypes.options.add(item, undefined));
}
}
Listar bancos
Client-Side
Ao criar um pagamento com PSE, é necessário enviar o código do banco que será usado para fazer a transferência. Para isso, você deve listar os bancos disponíveis e oferecer as opções ao pagador, para que ele escolha o banco de sua preferência.
Para acessar a lista de bancos disponíveis para PSE, é preciso inicialmente, a partir do backend, obter os meios de pagamento. Isso é feito enviando um GET, junto com seu Access Token, para o endpoint /v1/payment_methods. Alternativamente, pode-se utilizar nossos SDKs para adquirir essas informações e posteriormente encaminhá-las para o frontend.
No exemplo a seguir, mostramos como enviar meios de pagamento através de um endpoint do aplicativo, /payment_methods
. Uma vez chamado esse endpoint pelo frontend, a lista de bancos disponíveis para PSE retorna através do campo financial_institutions
dentro do objeto com id=pse
.
json
[
{
"id": "pse",
"name": "PSE",
"payment_type_id": "bank_transfer",
"status": "active",
"secure_thumbnail": "https://www.mercadopago.com/org-img/MP3/API/logos/pse.gif",
"thumbnail": "https://www.mercadopago.com/org-img/MP3/API/logos/pse.gif",
"deferred_capture": "does_not_apply",
"settings": [],
"additional_info_needed": [
"entity_type"
],
"min_allowed_amount": 1600,
"max_allowed_amount": 340000000,
"accreditation_time": 30,
"financial_institutions": [
{
"id": "1040",
"description": "Banco Agrario"
},
{
"id": "1507",
"description": "NEQUI"
},
{
"id": "1052",
"description": "Banco AV Villas"
},
{
"id": "1032",
"description": "Banco Caja Social"
}
],
"processing_modes": [
"aggregator"
]
}
]
Para exibir a lista de bancos, crie um elemento select
em javascript e enriqueça-o com os dados retornados na chamada da API.
javascript
function setPse() {
fetch('/payment_methods')
.then(async function(response) {
const paymentMethods = await response.json();
const pse = paymentMethods.filter((method) => method.id === 'pse')[0];
const banksList = pse.financial_institutions;
const banksListElement = document.getElementById('banksList');
const selectElement = document.createElement('select');
selectElement.name = 'financialInstitution';
banksList.forEach(bank => {
const option = document.createElement('option');
option.value = bank.id;
option.textContent = bank.description;
selectElement.appendChild(option);
});
banksListElement.appendChild(selectElement);
}).catch(function(reason) {
console.error('Failed to get payment methods', reason);
});
}
Para que os elementos dinâmicos dos exemplos anteriores criados com estes javascript sejam carregados quando a página terminar de renderizar, utilize o seguinte código:
javascript
(function initCheckout() {
try {
const docTypeElement = document.getElementById('form-checkout__identificationType');
setPse();
updateSelectOptions('natural')
}catch(e) {
return console.error('Error getting identificationTypes: ', e);
}
})();
Enviar pagamento
Server-Side
O envio de um pagamento com a nova implementação do PSE envolve apenas algumas alterações.
Para isso, é necessário enviar um POST com os parâmetros essenciais para o endpoint /v1/payments. Na execução da solicitação, deve-se incluir novos campos obrigatórios (address
y phone
).
Veja abaixo um exemplo completo para referência, seguido da descrição de cada campo a ser enviado:
<?php
use MercadoPago\Client\Payment\PaymentClient;
use MercadoPago\MercadoPagoConfig;
MercadoPagoConfig::setAccessToken("YOUR_ACCESS_TOKEN");
$client = new PaymentClient();
$payment = $client->create([
"transaction_amount" => 5000,
"description" => "Product description",
"payment_method_id" => "pse",
"additional_info" => [
"ip_address" => "127.0.0.1"
],
"transaction_details" => [
"financial_institution" => $_POST['financialInstitution']
],
"callback_url" => "http://www.your-site.com",
"email" => $_POST['email'],
"identification" => [
"type" => $_POST['identificationType'],
"number" => $_POST['identificationNumber']
],
"address" => [
"zip_code" => $_POST['zipCode'],
"street_name": $_POST['streetName'],
"street_number": $_POST['streetNumber'],
"neighborhood": $_POST['neighborhood'],
"city": $_POST['city'],
"federal_unit": $_POST['federalUnit']
],
"phone" => [
"area_code" => $_POST['phoneAreaCode'],
"number" => $_POST['phoneNumber']
],
"entity_type" => "individual";
]);
echo implode($payment);
?>
import { Payment, MercadoPagoConfig } from 'mercadopago';
const client = new MercadoPagoConfig({ accessToken: '<ACCESS_TOKEN>' });
const payment = new Payment(client);
payment.create({
body: {
transaction_amount: 5000,
description: 'Product description',
payment_method_id: 'pse',
payer: {
entity_type: 'individual',
email: req.body.email,
identification: {
type: req.body.identificationType,
number: req.body.identificationNumber
}
address: {
zip_code: req.body.zipCode,
street_name: req.body.streetName,
street_number: req.body.streetNumber,
neighborhood: req.body.neighborhood,
city: req.body.city,
Federal_unit: req.body.federalUnit
},
phone: {
area_code: req.body.phoneAreaCode,
number: req.body.phoneNumber
}
},
additional_info: {
ip_address: '127.0.0.1'
},
transaction_details: {
financial_institution: req.body.financialInstitution
},
callback_url: 'http://www.your-site.com'
}
}).then(function(response) {
res.status(response.status).json({
status: response.body.status,
status_detail: response.body.status_detail,
id: response.body.id,
});
})
.catch(function(error) {
res.status(error.status).send(error);
});
MercadoPagoConfig.setAccessToken("YOUR_ACCESS_TOKEN");
PaymentClient client = new PaymentClient();
IdentificationRequest identification =
IdentificationRequest.builder()
.type(request.getIdentificationType())
.number(request.getIdentificationNumber())
.build();
PaymentPayerAddressRequest address =
PaymentPayerAddressRequest.builder()
.zipCode(request.getZipCode())
.streetName(request.getStreetName())
.streetNumber(request.getStretNumber())
.neighborhood(request.getNeighborhood())
.city(request.getCity())
.federalUnit(request.getFederalUnit())
.build();
PaymentPayerPhoneRequest phone =
PaymentPayerPhoneRequest.builder()
.areaCode(request.getPhoneAreaCode())
.number(request.getPhoneNumber())
.build();
PaymentPayerRequest payer =
PaymentPayerRequest.builder()
.email(request.getEmail())
.entityType("individual")
.identification(identification)
.address(address)
.phone(phone)
.build();
PaymentAdditionalInfoRequest additionalInfo =
PaymentAdditionalInfoRequest.builder()
.ipAddress("127.0.0.1")
.build();
PaymentTransactionDetailsRequest transactionDetails = PaymentTransactionDetailsRequest.builder()
.financialInstitution(request.getFinancialInstitution())
.build();
PaymentCreateRequest paymentCreateRequest = PaymentCreateRequest.builder()
.transactionAmount(new BigDecimal(5000))
.description("Product description")
.paymentMethodId("pse")
.additionalInfo(additionalInfo)
.transactionDetails(transactionDetails)
.notificationUrl("https://your-site.com")
.payer(payer)
.build();
client.create(paymentCreateRequest);
require 'mercadopago'
sdk = Mercadopago::SDK.new('ACCESS_TOKEN')
payment_data = {
transaction_amount: 5000,
description: "Product description",
payment_method_id: "pse",
additional_info: {
ip_address: "127.0.0.1"
},
transaction_details: {
financial_institution: params[: financialInstitution]
},
callback_url: "https://your-site.com"
payer: {
email: params[:email],
entity_type: "individual",
identification: {
type: params[: identificationType],
number: params[: identificationNumber]
}
address: {
zip_code: params[: zipCode],
street_name: params[: streetName],
street_number: params[: streetNumber],
neighborhood: params[: neighborhood],
city: params[: city],
federal_unit: params[: federalUnit]
}
phone: {
area_code: params[: phoneAreaCode],
number: params[: phoneNumber]
}
}
}
payment_response = sdk.payment.create(payment_data)
payment = payment_response[: response]
using System;
using MercadoPago.Client.Common;
using MercadoPago.Client.Payment;
using MercadoPago.Config;
using MercadoPago.Resource.Payment;
MercadoPagoConfig.AccessToken = "ACCESS_TOKEN";
var client = new PaymentClient();
var identification = new IdentificationRequest() {
Type = request.IdentificationType,
Number = request.IdentificationNumber
};
var address = new PaymentPayerAddressRequest() {
ZipCode = request.ZipCode,
StreetName = request.StreetName,
StreetNumber = request.StreetNumber,
Neighborhood = request.Neighborhood,
City = request.City,
FederalUnit = request.FederalUnit
};
var phone = new PaymentPayerPhoneRequest() {
AreaCode = request.PhoneAreaCode,
Number = request.PhoneNumber
};
var payer = new PaymentPayerRequest() {
Email = request.Email,
EntityType = "individual",
Identification = identification,
Address = address,
Phone = phone
};
var additionalInfo = new PaymentAdditionalInfoRequest() {
IpAddress = "127.0.0.1"
};
var transactionDetails = new PaymentTransactionDetailsRequest() {
FinancialInstitution = request.FinancialInstitution
};
var paymentCreateRequest = new PaymentCreateRequest() {
TransactionAmount = 5000,
Description = "Product description",
PaymentMethodId = "pse",
AdditionalInfo = additionalInfo,
TransactionDetails = transactionDetails,
CallbackUrl = "https://your-site.com",
Payer = payer
};
var payment = await client.CreateAsync(paymentCreateRequest);
import mercadopago
sdk = mercadopago.SDK("ACCESS_TOKEN")
payment_data = {
"transaction_amount": 5000,
"description": "Product description",
"payment_method_id": "pse",
"additional_info": {
"ip_address": "127.0.0.1"
},
"transaction_details": {
"financial_institution": request.POST.get("financialInstitution")
},
"callback_url": "https://your-site.com"
"payer": {
"email": request.POST.get("email"),
"entity_type": "individual",
"identification": {
"type": request.POST.get("identificationType"),
"number": request.POST.get("identificationNumber")
}
"address": {
"zip_code": request.POST.get("zipCode"),
"street_name": request.POST.get("streetName"),
"street_number": request.POST.get("streetNumber"),
"neighborhood": request.POST.get("neighborhood"),
"city": request.POST.get("city"),
"federal_unit": request.POST.get("federalUnit")
},
"phone": {
"area_code": request.POST.get("phoneAreaCode"),
"number": request.POST.get("phoneNumber")
}
}
}
payment_response = sdk.payment().create(payment_data)
payment = payment_response["response"]
curl --location --request POST 'https://api.mercadopago.com/v1/payments' \
-H 'Authorization: Bearer ENV_ACCESS_TOKEN' \
-H 'X-Idempotency-Key: SOME_UNIQUE_VALUE' \
-H 'Content-Type: application/json' \
--d '{
"transaction_amount": 5000,
"description": "Product description",
"payment_method_id": "pse",
"payer": {
"email": "test_user_19549678@testuser.com",
"entity_type": "individual",
"identification": {
"type": "CC",
"number": "76262349"
},
"address": {
"zip_code": "111",
"street_name": "siempre viva",
"street_number": "111",
"neighborhood": "sarasa",
"city": "salto",
"federal_unit": "1"
},
"phone": {
"area_code": "011",
"number": "2134242412"
}
},
"additional_info": {
"ip_address": "127.0.0.1"
},
"transaction_details": {
"financial_institution": "1009"
},
"callback_url": "http://www.your-site.com"
}'
A tabela a seguir tem a lista completa de campos obrigatórios para sua referência:
Campo | Descrição | Possíveis valores/validações | Chamado para obter os valores |
transaction_amount | Valor do pagamento. | Deve ser maior que 0. | - |
transaction_details.financial_institution | Banco informado no POST para efetuar a transferência eletrônica. A lista de bancos deve ser mostrada ao usuário e permitida a seleção. A lista é atualizada, por isso é recomendável consumir as informações a cada hora. | No debe ser nulo ni vacío y debe corresponder a un banco existente. | https://api.mercadopago.com/v1/payment_methods/search?site_id=MCO&id=pse&public_key=YOUR_PUBLIC_KEY |
payer.entity_type | Tipo de pessoa, física ou jurídica. | individual ou association | - |
payer.identification.type | Tipo de documento do comprador. | Valores aceitos: - RC (Registro Civil de Nacimiento) - TI (Tarjeta de Identidad) - CC (Cedula de Ciudadania) - TE (Tarjeta de Extranjeria) - CE (Cedula de Extranjeria) - PAS (Pasaporte) - NIT - DI (Documento de Identificación) | curl -X GET \ 'https://api.mercadopago.com/v1/identification_types' \ -H 'Authorization: Bearer YOUR_PUBLIC_KEY' |
payer.identification.number | Número do documento do comprador. | String Deve ter de 1 até 15 posições numéricas. Se é do tipo 'passaporte', aceitará valores alfanuméricos. | - |
payer.first_name | Nome do comprador. | Deve ter de 1 até 32 posições. | - |
payer.last_name | Sobrenome do comprador. | Deve ter de 1 até 32 posições. | - |
payer.address.zip_code | Código postal do comprador. | Deve ter exatamente 5 posições. | - |
payer.address.street_name | Nome da rua onde o comprador reside. | Deve ter de 1 até 18 posições. | - |
payer.address.street_number | Núúmero da residência do comprador. | Deve ter de 1 até 5 posições. | - |
payer.address.neighborhood | Nome do bairro onde o comprador reside. | Deve ter de 1 até 18 posições. | - |
payer.address.city | Cidade do comprador. | Deve ter de 1 até 18 posições. | - |
payer.phone.area_code | Código de área do telefone do comprador. | Deve ter 3 posições. | - |
payer.phone.number | Número de telefone do comprador. | String Deve ter de 1 até 5 posições e só aceita caracteres numéricos. | - |
additional_info.ip_address | Endereço do IP do comprador, onde o pagamento é gerado. | - | - |
callback_url | Página onde o comprador é redirecionado por padrão após efetuar o pagamento dentro da página do banco, quando o comprador indica que deseja retornar à loja. Você pode ver sugestões de mensagens para mostrar ao comprador no subtítulo Exemplos de mensagens para callback URL. | Não deve ser nulo ou vazio e deve ter, no máximo, 512 caracteres. | - |
notification_url | URL usada para notificar a aplicação de que a transferência foi concluída. | Não deve ser nulo ou vazio e deve ter, no máximo, 512 caracteres. | - |
A resposta mostrará o status pendente
até que o comprador realize o pagamento. Além disso, na resposta à requisição, o parâmetro external_resource_url
retornará uma URL para a qual você deverá redirecionar o comprador para que ele conclua o fluxo de pagamento.
json
{
"id": 1312147735,
...,
"operation_type": "regular_payment",
"payment_method_id": "pse",
"payment_type_id": "bank_transfer",
"payment_method": {
"id": "pse",
"type": "bank_transfer"
},
"status": "pending",
"status_detail": "pending_waiting_transfer",
...
"description": "Título del producto",
...
"callback_url": "http://www.your-site.com",
"installments": 1,
"transaction_details": {
...
"total_paid_amount": 5000,
...
"external_resource_url": "https://www.mercadopago.com.co/sandbox/payments/1312147735/bank_transfer?caller_id=1148920820&hash=f41dd14f-b3a6-4ac4-9b78-5cfeb5a35e77",
...
"financial_institution": "1009",
...
"bank_transfer_id": 129229,
"transaction_id": "10022214"
},
}
Exemplos de mensagens para o callback URL
Após o comprador realizar o pagamento na plataforma do banco escolhido, haverá um redirecionamento para uma URL de callback. Nesta página, ele receberá informações sobre o status da transação.
Na nova versão, o callback URL é um campo obrigatório, por isso é importanteter em mente que é necessário tratar os diferentes estados da transação.
Abaixo, apresentamos exemplos de mensagens que você pode exibir, alinhadas aos três possíveis status em que o pagamento pode se encontrar.