Primeiro commit
This commit is contained in:
337
implementar-pix.sh
Executable file
337
implementar-pix.sh
Executable file
@@ -0,0 +1,337 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 🏦 Script para Implementar PIX no Liberi Kids
|
||||
# Execute: ./implementar-pix.sh
|
||||
|
||||
echo "🏦 Implementando PIX no Liberi Kids"
|
||||
echo "=================================="
|
||||
|
||||
# Cores para output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
info() {
|
||||
echo -e "${BLUE}[PIX]${NC} $1"
|
||||
}
|
||||
|
||||
# Instalar dependência do Mercado Pago
|
||||
log "Instalando SDK do Mercado Pago..."
|
||||
npm install mercadopago
|
||||
|
||||
# Criar arquivo de configuração PIX
|
||||
log "Criando configuração PIX..."
|
||||
cat > config/mercadopago.js << 'EOF'
|
||||
const mercadopago = require('mercadopago');
|
||||
|
||||
class MercadoPagoService {
|
||||
constructor() {
|
||||
if (process.env.MERCADOPAGO_ACCESS_TOKEN) {
|
||||
mercadopago.configurations.setAccessToken(process.env.MERCADOPAGO_ACCESS_TOKEN);
|
||||
}
|
||||
}
|
||||
|
||||
async gerarPix(dados) {
|
||||
try {
|
||||
const payment_data = {
|
||||
transaction_amount: parseFloat(dados.valor),
|
||||
description: dados.descricao || `Venda #${dados.venda_id} - Liberi Kids`,
|
||||
payment_method_id: 'pix',
|
||||
payer: {
|
||||
email: dados.cliente_email || 'cliente@liberikids.com',
|
||||
first_name: dados.cliente_nome || 'Cliente',
|
||||
identification: {
|
||||
type: 'CPF',
|
||||
number: dados.cliente_cpf || '00000000000'
|
||||
}
|
||||
},
|
||||
external_reference: dados.venda_id.toString(),
|
||||
notification_url: `${process.env.BASE_URL || 'http://localhost:5000'}/api/pix/webhook`,
|
||||
date_of_expiration: new Date(Date.now() + 30 * 60 * 1000).toISOString() // 30 minutos
|
||||
};
|
||||
|
||||
const payment = await mercadopago.payment.create(payment_data);
|
||||
|
||||
return {
|
||||
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,
|
||||
transaction_amount: payment.body.transaction_amount,
|
||||
status: payment.body.status
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('Erro ao gerar PIX:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async consultarPagamento(payment_id) {
|
||||
try {
|
||||
const payment = await mercadopago.payment.get(payment_id);
|
||||
return {
|
||||
success: true,
|
||||
status: payment.body.status,
|
||||
status_detail: payment.body.status_detail,
|
||||
transaction_amount: payment.body.transaction_amount,
|
||||
date_approved: payment.body.date_approved,
|
||||
external_reference: payment.body.external_reference
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Erro ao consultar pagamento:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new MercadoPagoService();
|
||||
EOF
|
||||
|
||||
# Criar CSS para PIX
|
||||
log "Criando estilos PIX..."
|
||||
cat > client/src/styles/pix-integration.css << 'EOF'
|
||||
/* PIX Integration Styles */
|
||||
|
||||
.pix-modal {
|
||||
max-width: 500px;
|
||||
width: 90vw;
|
||||
}
|
||||
|
||||
.pix-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-code-section {
|
||||
margin-bottom: 20px;
|
||||
padding: 20px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.qr-code-image {
|
||||
max-width: 200px;
|
||||
height: auto;
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
background: white;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.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;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.btn-copy-pix {
|
||||
background: #00d4aa;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-copy-pix:hover {
|
||||
background: #00b894;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.pix-info {
|
||||
background: #e8f5e8;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
text-align: left;
|
||||
border-left: 4px solid #00d4aa;
|
||||
}
|
||||
|
||||
.pix-instructions {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.btn-pix {
|
||||
background: #00d4aa;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-pix:hover {
|
||||
background: #00b894;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-pix:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.pix-status {
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pix-status.pending {
|
||||
background: #fff3cd;
|
||||
color: #856404;
|
||||
border: 1px solid #ffeaa7;
|
||||
}
|
||||
|
||||
.pix-status.approved {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
|
||||
.pix-status.rejected {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
.pix-timer {
|
||||
background: #fff3cd;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.pix-modal {
|
||||
width: 95vw;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.qr-code-image {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.pix-code-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.btn-copy-pix {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Atualizar .env.example
|
||||
log "Atualizando .env.example com configurações PIX..."
|
||||
cat >> .env.example << 'EOF'
|
||||
|
||||
# =====================================================
|
||||
# CONFIGURAÇÕES PIX - MERCADO PAGO
|
||||
# =====================================================
|
||||
|
||||
# Access Token do Mercado Pago (TEST para desenvolvimento, PROD para produção)
|
||||
MERCADOPAGO_ACCESS_TOKEN=TEST-sua_access_token_aqui
|
||||
|
||||
# Public Key do Mercado Pago
|
||||
MERCADOPAGO_PUBLIC_KEY=pk_test_sua_public_key_aqui
|
||||
|
||||
# URL base para webhooks (importante para produção)
|
||||
BASE_URL=http://localhost:5000
|
||||
|
||||
# =====================================================
|
||||
# INSTRUÇÕES PIX
|
||||
# =====================================================
|
||||
|
||||
# 1. Acesse: https://www.mercadopago.com.br/developers
|
||||
# 2. Crie uma conta de desenvolvedor
|
||||
# 3. Vá em "Suas integrações" > "Criar aplicação"
|
||||
# 4. Escolha "Pagamentos online" e "Checkout Pro"
|
||||
# 5. Copie as credenciais de TEST para desenvolvimento
|
||||
# 6. Para produção, use as credenciais PROD
|
||||
# 7. Configure o webhook URL no painel do Mercado Pago
|
||||
EOF
|
||||
|
||||
# Criar script SQL para PIX
|
||||
log "Criando migração do banco para PIX..."
|
||||
cat > sql/add-pix-fields.sql << 'EOF'
|
||||
-- Adicionar campos PIX na tabela vendas
|
||||
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);
|
||||
ALTER TABLE vendas ADD COLUMN IF NOT EXISTS pix_qr_code TEXT;
|
||||
ALTER TABLE vendas ADD COLUMN IF NOT EXISTS metodo_pagamento VARCHAR(20) DEFAULT 'dinheiro';
|
||||
|
||||
-- Criar índices para performance
|
||||
CREATE INDEX IF NOT EXISTS idx_vendas_status_pagamento ON vendas(status_pagamento);
|
||||
CREATE INDEX IF NOT EXISTS idx_vendas_pix_payment_id ON vendas(pix_payment_id);
|
||||
|
||||
-- Comentários para documentação
|
||||
COMMENT ON COLUMN vendas.status_pagamento IS 'Status do pagamento: pendente, pago, cancelado, expirado';
|
||||
COMMENT ON COLUMN vendas.data_pagamento IS 'Data e hora da confirmação do pagamento';
|
||||
COMMENT ON COLUMN vendas.pix_payment_id IS 'ID do pagamento no Mercado Pago';
|
||||
COMMENT ON COLUMN vendas.pix_qr_code IS 'Código PIX para copiar e colar';
|
||||
COMMENT ON COLUMN vendas.metodo_pagamento IS 'Método: dinheiro, cartao, pix, transferencia';
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
info "🎉 Implementação PIX configurada com sucesso!"
|
||||
echo ""
|
||||
warn "📝 PRÓXIMOS PASSOS:"
|
||||
echo "1. Crie conta no Mercado Pago: https://www.mercadopago.com.br/developers"
|
||||
echo "2. Configure as credenciais no arquivo .env"
|
||||
echo "3. Execute a migração do banco: psql -f sql/add-pix-fields.sql"
|
||||
echo "4. Adicione as rotas PIX no server-supabase.js"
|
||||
echo "5. Implemente o modal PIX no frontend"
|
||||
echo ""
|
||||
info "📖 Consulte o arquivo INTEGRACAO-PIX-GUIDE.md para instruções completas"
|
||||
echo ""
|
||||
log "Arquivos criados:"
|
||||
echo " - config/mercadopago.js (Serviço PIX)"
|
||||
echo " - client/src/styles/pix-integration.css (Estilos)"
|
||||
echo " - sql/add-pix-fields.sql (Migração banco)"
|
||||
echo " - .env.example (Configurações atualizadas)"
|
||||
Reference in New Issue
Block a user