Files
App-Estoque-LiberiKids/INTEGRACAO-PIX-GUIDE.md
2025-10-14 14:04:17 -03:00

388 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🏦 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**
1. Acesse: https://www.mercadopago.com.br/developers
2. Crie conta de desenvolvedor
3. Obtenha suas credenciais:
- **Public Key** (pk_test_...)
- **Access Token** (TEST-...)
### **Passo 2: Instalar SDK**
```bash
npm install mercadopago
```
### **Passo 3: Configurar no .env**
```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**
```javascript
// 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**
```javascript
// 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**
```css
/* 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**
```javascript
// 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**
```sql
-- 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**
1. **Nunca exponha** as credenciais no frontend
2. **Use HTTPS** sempre em produção
3. **Valide webhooks** com assinatura
4. **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!**