Nequi
Nesta página
Comece com Nequi#
Esta página fornece um guia completo para integrar com sucesso Nequi com DEUNA em seu checkout.
Nequi é uma carteira digital administrada pelo Bancolombia e amplamente utilizada na Colômbia.
Como funciona#
A integração da DEUNA com o Nequi permite que os usuários paguem por meio de um fluxo de notificação push, totalmente gerenciado dentro do widget de pagamento DEUNA - sem necessidade de redirecionamentos externos.
Processo de pagamento
A lista a seguir descreve um processo de pagamento válido com Nequi:
- O usuário seleciona Nequi dentro do widget de pagamento.
- O usuário insere seu número de telefone real do Nequi.
- Uma notificação push é enviada para o aplicativo móvel Nequi.
- O usuário aprova o pagamento diretamente no app.
- DEUNA recebe o status do pagamento.
- DEUNA aciona o evento de retorno de chamada apropriado no widget:
onSuccesspara pagamentos aprovadosonErrorpara aqueles recusados ou expirados
manipulação de eventos onError
O widget DEUNA aciona o onError retorno de chamada nos seguintes cenários:
- O número de telefone fornecido no formulário de checkout é válido, mas não está associado a uma conta Nequi.
- O usuário rejeita a notificação push do aplicativo Nequi.
Em ambos os casos, DEUNA retorna uma resposta incluindo um código de erro e uma mensagem de erro descrevendo a falha. Você pode lidar com a resposta com base na lógica de negócios e na experiência do usuário desejada.
Requisitos#
O conteúdo a seguir lista todos os requisitos para uma integração bem-sucedida com o Nequi.
Suas credenciais de sandbox e produção Nequi devem ser solicitadas diretamente ao seu gerente de conta Bancolombia ou Nequi.
Ambientes:
- Caixa de areia: https://api.sandbox.deuna.io
- Produção: https://api.deuna.io
Conclua o processo de certificação com Nequi e obtenha as seguintes credenciais fornecidas por Nequi:
-
Merchant ID
-
Senha do comerciante
-
Chave pública.
-
Código de identificação
-
Tempo para expirar (máx. 45min)
Configurar webhooks no Nequi#
Configure webhooks em sua sessão Nequi para cada loja.
Se você não configurar os webhooks do Nequi, as atualizações de status no Nequi demorarão entre dois a cinco minutos.
Certifique-se de que seu endpoint de webhook esteja altamente disponível e escalonável. Opcionalmente, você pode configurar o estorno da transação caso a confirmação do pagamento falhe por indisponibilidade do serviço.
Carga útil do webhook
Nequi enviará a seguinte carga JSON:
{
"commerceCode": "29603",
"value": "1",
"phoneNumber": "3195414070",
"messageId": "60396545535",
"transactionId": "350-12345-34000201-60396545535",
"region": "C001",
"receivedAt": "2023-02-27T15:50:13.527Z",
"paymentStatus": "SUCCESS"
}Campos de carga útil
| Campo | Descrição |
|---|---|
commerceCode | Seu código interno de comerciante Nequi |
value | Valor do pagamento |
phoneNumber | Número de celular do pagador |
messageId | Identificador exclusivo de transação |
transactionId | Identificador de pagamento |
region | Região de pagamento: P001 (Panamá) ou C001 (Colômbia) |
receivedAt | Carimbo de data e hora de pagamento no formato JSON |
paymentStatus | Situação do pagamento: SUCCESS, CANCELED, ou DENIED |
Verificação de solicitação de segurança
Todas as solicitações de webhook do Nequi incluem cabeçalhos de segurança que você deve verificar:
Solicitar cabeçalhos
{
"Content-Type": "application/json",
"Digest": "SHA-256=43GpOk5L54gfpAMBE0xNX1bj2hJA9JJ1RR0dErHfZhI=",
"Signature": "keyId=\"YourClientId\",algorithm=\"hmac-sha384\",headers=\"content-type digest\",signature=\"...\""
}Processo de verificação
Você deve verificar duas coisas para cada solicitação:
1. Verifique a digestão corporal
O Digest header contém um hash SHA-256 do corpo da solicitação:
// Convert body to string
const parsedBody = JSON.stringify(request.body);
// Calculate SHA-256 hash
const calculatedDigest = `SHA-256=${createHash('sha256')
.update(parsedBody)
.digest('base64')}`;
// Verify it matches the header
if (calculatedDigest !== request.headers.Digest) {
return 401; // Invalid Digest
}2. Verifique a assinatura da solicitação
O Signature header garante que a solicitação veio de Nequi:
- Analise o cabeçalho da assinatura.
const parts = request.headers.Signature.split(',');
const signature = {};
for (const part of parts) {
const [key, value] = part.split('=');
signature[key] = value.slice(1, -1); // Remove quotes
}
// Result:
// {
// keyId: "YourClientId",
// algorithm: "hmac-sha384",
// headers: "content-type digest",
// signature: "..."
// }- Construa o texto de assinatura.
const headerNames = signature.headers.split(' '); // ["content-type", "digest"]
const linesForSignature = [];
for (const headerName of headerNames) {
const value = request.headers[headerName.toLowerCase()];
linesForSignature.push(`${headerName}: ${value}`);
}
const textForSignature = linesForSignature.join('\n');
// Result:
// "content-type: application/json
// digest: SHA-256=43GpOk5L54gfpAMBE0xNX1bj2hJA9JJ1RR0dErHfZhI="- Calcule e verifique o HMAC.
const APP_SECRET = 'YourSharedSecret'; // Store securely, never hardcode
// Calculate HMAC-SHA384
const base64hmac = createHmac('sha384', APP_SECRET)
.update(textForSignature)
.digest('base64');
// Convert to base64url format
const calculatedSignature = base64hmac
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
// Verify signature
if (calculatedSignature !== signature.signature) {
return 401; // Invalid Signature
}Exemplo completo de implementação (Node.js)
const { createHash, createHmac } = require('node:crypto');
// Store securely - use environment variables
const APP_SECRET = process.env.NEQUI_WEBHOOK_SECRET;
async function handleNequiWebhook(request, response) {
try {
// 1. Verify Body Digest
const parsedBody = JSON.stringify(request.body);
const calculatedDigest = `SHA-256=${createHash('sha256')
.update(parsedBody)
.digest('base64')}`;
if (calculatedDigest !== request.headers.digest) {
return response.status(401).send('Invalid Digest');
}
// 2. Parse Signature Header
const parts = request.headers.signature.split(',');
const signatureData = {};
for (const part of parts) {
const [key, value] = part.split('=');
signatureData[key] = value.slice(1, -1);
}
// 3. Build Signing Text
const headerNames = signatureData.headers.split(' ');
const linesForSignature = headerNames.map(name =>
`${name}: ${request.headers[name.toLowerCase()]}`
);
const textForSignature = linesForSignature.join('\n');
// 4. Verify Signature
const base64hmac = createHmac('sha384', APP_SECRET)
.update(textForSignature)
.digest('base64');
const calculatedSignature = base64hmac
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
if (calculatedSignature !== signatureData.signature) {
return response.status(401).send('Invalid Signature');
}
// 5. Process the payment notification asynchronously
processPaymentAsync(request.body);
// 6. Respond immediately (within 10 seconds)
return response.status(200).send('OK');
} catch (error) {
console.error('Webhook processing error:', error);
return response.status(500).send('Internal Server Error');
}
}
async function processPaymentAsync(paymentData) {
// Process payment in background
// Update your database, trigger notifications, etc.
const { transactionId, paymentStatus, value, phoneNumber } = paymentData;
if (paymentStatus === 'SUCCESS') {
// Handle successful payment
} else if (paymentStatus === 'CANCELED' || paymentStatus === 'REFUSED') {
// Handle failed payment
}
}Integrar Nequi#
Agora que os requisitos técnicos estão definidos, você pode iniciar a integração passo a passo.
1. Crie um order_token
Para efetuar uma compra, você deve criar um pedido DEUNA.
Faça uma solicitação ao Crie um pedido endpoint.
A API retorna um order_token, que é usado em todo o fluxo.
2. Obtenha o order_token
Faça uma solicitação ao Obter pedido endpoint.
Use este token para as próximas etapas.
3. Renderize o widget de pagamento
Depois de receber o token do pedido, você pode renderizar o Widget DEUNA.
await DeunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
callbacks: ...,
paymentMethods: [
{
paymentMethod: "voucher",
processors: ["nequi_push_voucher"],
},
],
});4. Faça um pagamento com cartão
Faça uma solicitação de pagamento com cartão para o Comprar V2 endpoint e processar o pagamento.
Resposta
{
"order": {
"cash_change": 0,
"currency": "USD",
"discounts": [],
"display_items_total_amount": "",
"display_shipping_amount": "",
"display_sub_total": "",
"display_tax_amount": "",
"display_total_amount": "",
"display_total_discount": "",
"gift_card": [],
"items": [
{
"brand": "",
"category": "",
"color": "",
"description": "Papa Fritas",
"details_url": "",
"discounts": [],
"id": "001",
"image_url": "https://images-staging.getduna.com/95463fb5-6279-4ec3-8ff9-fe07aacd2142/cd928351d12c6b96_domicilio_316_744x744.png?d=600x600",
"isbn": "",
"manufacturer": "",
"name": "Papa Fritas",
"options": "",
"quantity": 1,
"size": "",
"sku": "",
"tax_amount": {
"amount": 44,
"currency": "USD",
"currency_symbol": "$",
"display_amount": ""
},
"taxable": false,
"total_amount": {
"amount": 594,
"currency": "USD",
"currency_symbol": "$",
"display_amount": "",
"display_original_amount": "",
"display_total_discount": "",
"original_amount": 0,
"total_discount": 0
},
"type": "",
"unit_price": {
"amount": 550,
"currency": "USD",
"currency_symbol": "$",
"display_amount": ""
},
"uom": "",
"upc": "",
"weight": {
"unit": "",
"weight": 0
}
},
{
"brand": "",
"category": "",
"color": "",
"description": "Hamburguesa ",
"details_url": "",
"discounts": [],
"id": "002",
"image_url": "https://images-staging.getduna.com/95463fb5-6279-4ec3-8ff9-fe07aacd2142/cd928351d12c6b96_domicilio_51330_744x744_1646338877.png?d=600x600",
"isbn": "",
"manufacturer": "",
"name": "Hamburguesa",
"options": "",
"quantity": 2,
"size": "",
"sku": "",
"tax_amount": {
"amount": 88,
"currency": "USD",
"currency_symbol": "$",
"display_amount": ""
},
"taxable": false,
"total_amount": {
"amount": 3088,
"currency": "USD",
"currency_symbol": "$",
"display_amount": "",
"display_original_amount": "",
"display_total_discount": "",
"original_amount": 0,
"total_discount": 0
},
"type": "",
"unit_price": {
"amount": 1500,
"currency": "USD",
"currency_symbol": "$",
"display_amount": ""
},
"uom": "",
"upc": "",
"weight": {
"unit": "",
"weight": 0
}
}
],
"items_total_amount": 3682,
"metadata": {
"key1": "NO REQUERIDO",
"key2": "NO REQUERIDO"
},
"order_id": "order116",
"payment": {
"data": {
"amount": {
"amount": 3770,
"currency": "USD"
},
"authorization_3ds": {
"html_content": "<div></div>",
"url_challenge": "",
"version": "1.1.1"
},
"authorization_code": "TEST00",
"created_at": "2022-07-22 20:22:48.408419489 +0000 UTC",
"customer": {
"email": "jhondoe@deuna.com",
"id": "xxxxxx-0eb3-450f-8b26-4ff23208470f"
},
"from_card": {
"card_brand": "Visa",
"first_six": "411111",
"last_four": "1111"
},
"id": "order116",
"installments": {
"installment_amount": 5999,
"installment_rate": 0.12,
"installment_type": "MCI",
"installments": 3,
"plan_id": "7471ed27-094d-44c4-a62d-225644b782f7",
"plan_option_id": "87309ea8-3942-4fdf-95ec-ce29a792aff2"
},
"merchant": {
"id": "9a85e296-cc3d-454b-b591-208d6e538126",
"store_code": "all"
},
"metadata": {
"authorization_code": "TEST00"
},
"method_type": "credit_card",
"processor": "paymentez",
"reason": "",
"status": "processed",
"updated_at": "2022-07-22 20:22:48.408809765 +0000 UTC"
}
},
"redirect_url": "",
"scheduled_at": "",
"shipping": null,
"shipping_address": {
"additional_description": "Piso 9",
"address_type": "home",
"address1": "Av. de los Incas 15-33, Ambato 180202, Ecuador",
"address2": "Av. de los Incas 15-33, Ambato 180202, Ecuador",
"city": "Ambato",
"country_code": "EC",
"created_at": "0001-01-01T00:00:00Z",
"first_name": "Jhon",
"id": 0,
"identity_document": "146565656",
"is_default": true,
"last_name": "Doe",
"lat": -1.2480678792202227,
"lng": -78.62532788804577,
"phone": " 946565665",
"state_name": "Tungurahua",
"updated_at": "0001-01-01T00:00:00Z",
"user_id": "xxxxx4e2-xxxx-xxxx-xxxx-xxxxx5b7b2e",
"zipcode": "180202"
},
"shipping_amount": 0,
"shipping_method": null,
"shipping_methods": [],
"shipping_options": {},
"status": "succeeded",
"store_code": "",
"sub_total": 3550,
"tax_amount": 132,
"timezone": "",
"total_amount": 3770,
"total_discount": 0,
"user_instructions": "Piso 9",
"webhook_urls": null
},
"order_token": "0b98dbe8-d265-49bc-b80d-536cea46509c"
}Teste Nequi#
Para testar o Nequi, você precisa solicitar os dados de teste do Nequi. Se necessário, o pagamento pode ser reembolsado através do Painel de Administração DEUNA ou através do API de reembolsos.