9.0 KiB
9.0 KiB
🏦 Integração PIX com QR Code - Liberi Kids
🎯 Opções de Integração PIX
1. Mercado Pago (Recomendado)
- ✅ Gratuito para começar
- ✅ QR Code automático
- ✅ Webhook para confirmação
- ✅ Documentação excelente
2. PagSeguro/PagBank
- ✅ PIX instantâneo
- ✅ Taxas competitivas
3. Asaas
- ✅ Focado em pequenas empresas
- ✅ PIX + Boleto + Cartão
🚀 Implementação Mercado Pago
Passo 1: Criar Conta
- Acesse: https://www.mercadopago.com.br/developers
- Crie conta de desenvolvedor
- Obtenha suas credenciais:
- Public Key (pk_test_...)
- Access Token (TEST-...)
Passo 2: Instalar SDK
npm install mercadopago
Passo 3: Configurar no .env
# Mercado Pago PIX
MERCADOPAGO_ACCESS_TOKEN=TEST-sua_access_token_aqui
MERCADOPAGO_PUBLIC_KEY=pk_test_sua_public_key_aqui
Passo 4: API Backend
// server-supabase.js - Adicionar rota PIX
const mercadopago = require('mercadopago');
// Configurar Mercado Pago
mercadopago.configurations.setAccessToken(process.env.MERCADOPAGO_ACCESS_TOKEN);
// Rota para gerar PIX
app.post('/api/pix/gerar', async (req, res) => {
try {
const { valor, descricao, cliente_email, venda_id } = req.body;
const payment_data = {
transaction_amount: parseFloat(valor),
description: descricao || `Venda #${venda_id} - Liberi Kids`,
payment_method_id: 'pix',
payer: {
email: cliente_email || 'cliente@liberikids.com'
},
external_reference: venda_id.toString(),
notification_url: `${process.env.BASE_URL}/api/pix/webhook`
};
const payment = await mercadopago.payment.create(payment_data);
res.json({
success: true,
payment_id: payment.body.id,
qr_code: payment.body.point_of_interaction.transaction_data.qr_code,
qr_code_base64: payment.body.point_of_interaction.transaction_data.qr_code_base64,
pix_copy_paste: payment.body.point_of_interaction.transaction_data.qr_code,
expiration_date: payment.body.date_of_expiration
});
} catch (error) {
console.error('Erro ao gerar PIX:', error);
res.status(500).json({ success: false, error: error.message });
}
});
// Webhook para receber confirmação de pagamento
app.post('/api/pix/webhook', async (req, res) => {
try {
const { type, data } = req.body;
if (type === 'payment') {
const payment = await mercadopago.payment.get(data.id);
if (payment.body.status === 'approved') {
const venda_id = payment.body.external_reference;
// Atualizar status da venda no banco
const { error } = await supabase
.from('vendas')
.update({
status_pagamento: 'pago',
data_pagamento: new Date(),
pix_payment_id: payment.body.id
})
.eq('id', venda_id);
if (!error) {
console.log(`Pagamento confirmado para venda #${venda_id}`);
}
}
}
res.status(200).send('OK');
} catch (error) {
console.error('Erro no webhook PIX:', error);
res.status(500).send('Error');
}
});
Passo 5: Frontend - Modal PIX
// Adicionar ao Vendas.js
const [showPixModal, setShowPixModal] = useState(false);
const [pixData, setPixData] = useState(null);
const [loadingPix, setLoadingPix] = useState(false);
const gerarPix = async (venda) => {
setLoadingPix(true);
try {
const response = await fetch('/api/pix/gerar', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
valor: venda.valor_total,
descricao: `Venda #${venda.id_venda} - Liberi Kids`,
cliente_email: venda.cliente?.email,
venda_id: venda.id
})
});
const data = await response.json();
if (data.success) {
setPixData(data);
setShowPixModal(true);
} else {
toast.error('Erro ao gerar PIX');
}
} catch (error) {
toast.error('Erro ao gerar PIX');
}
setLoadingPix(false);
};
// Modal PIX
{showPixModal && (
<div className="modal-overlay">
<div className="modal pix-modal">
<div className="modal-header">
<h3>🏦 Pagamento PIX</h3>
<button onClick={() => setShowPixModal(false)}>×</button>
</div>
<div className="modal-body">
<div className="pix-content">
<div className="qr-code-section">
<h4>QR Code PIX</h4>
<img
src={`data:image/png;base64,${pixData.qr_code_base64}`}
alt="QR Code PIX"
className="qr-code-image"
/>
</div>
<div className="pix-copy-section">
<h4>Código PIX (Copiar e Colar)</h4>
<div className="pix-code-container">
<input
type="text"
value={pixData.pix_copy_paste}
readOnly
className="pix-code-input"
/>
<button
onClick={() => {
navigator.clipboard.writeText(pixData.pix_copy_paste);
toast.success('Código PIX copiado!');
}}
className="btn-copy-pix"
>
📋 Copiar
</button>
</div>
</div>
<div className="pix-info">
<p><strong>Valor:</strong> R$ {parseFloat(pixData.transaction_amount).toFixed(2)}</p>
<p><strong>Válido até:</strong> {new Date(pixData.expiration_date).toLocaleString()}</p>
<p className="pix-instructions">
📱 <strong>Como pagar:</strong><br/>
1. Abra o app do seu banco<br/>
2. Escaneie o QR Code ou cole o código PIX<br/>
3. Confirme o pagamento
</p>
</div>
</div>
</div>
</div>
</div>
)}
Passo 6: CSS para Modal PIX
/* styles/pix-integration.css */
.pix-modal {
max-width: 500px;
width: 90vw;
}
.pix-content {
text-align: center;
}
.qr-code-section {
margin-bottom: 20px;
}
.qr-code-image {
max-width: 200px;
height: auto;
border: 2px solid #ddd;
border-radius: 8px;
padding: 10px;
background: white;
}
.pix-copy-section {
margin-bottom: 20px;
}
.pix-code-container {
display: flex;
gap: 10px;
margin-top: 10px;
}
.pix-code-input {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
}
.btn-copy-pix {
background: #00d4aa;
color: white;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
white-space: nowrap;
}
.btn-copy-pix:hover {
background: #00b894;
}
.pix-info {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: left;
}
.pix-instructions {
margin-top: 10px;
font-size: 14px;
color: #666;
}
.btn-pix {
background: #00d4aa;
color: white;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.btn-pix:hover {
background: #00b894;
}
🎯 Integração no Sistema de Vendas
1. Adicionar Botão PIX na Lista de Vendas
// Na tabela de vendas, adicionar botão PIX
<button
onClick={() => gerarPix(venda)}
className="btn-icon btn-pix"
title="Gerar PIX"
disabled={loadingPix}
>
🏦 PIX
</button>
2. Adicionar Campo no Banco de Dados
-- Adicionar colunas para controle de PIX
ALTER TABLE vendas ADD COLUMN IF NOT EXISTS status_pagamento VARCHAR(20) DEFAULT 'pendente';
ALTER TABLE vendas ADD COLUMN IF NOT EXISTS data_pagamento TIMESTAMP;
ALTER TABLE vendas ADD COLUMN IF NOT EXISTS pix_payment_id VARCHAR(100);
3. Dashboard com Status de Pagamentos
- Vendas pendentes de pagamento
- Vendas pagas via PIX
- Relatório de recebimentos
💰 Custos e Taxas
Mercado Pago:
- PIX: 0,99% por transação
- Sem mensalidade
- Recebimento em 1 dia útil
PagSeguro:
- PIX: 0,99% por transação
- Recebimento em 1 dia útil
Asaas:
- PIX: R$ 0,20 por transação
- Melhor para alto volume
🔒 Segurança
- Nunca exponha as credenciais no frontend
- Use HTTPS sempre em produção
- Valide webhooks com assinatura
- Monitore transações suspeitas
📱 Funcionalidades Extras
1. WhatsApp com PIX
- Enviar QR Code via WhatsApp
- Link de pagamento direto
2. Relatórios PIX
- Vendas pagas via PIX
- Tempo médio de pagamento
- Conversão PIX vs outros métodos
3. Notificações
- Email quando PIX for pago
- Notificação no sistema
- Atualização automática do status
🎉 Benefícios da Integração
- ✅ Pagamento instantâneo
- ✅ Sem taxas para o cliente
- ✅ QR Code automático
- ✅ Confirmação automática
- ✅ Integração com WhatsApp
- ✅ Relatórios detalhados
🚀 Com essa integração, seu sistema Liberi Kids terá pagamentos PIX completos com QR Code automático!