'use client'; import { useEffect, useMemo, useState } from 'react'; import { initMercadoPago, Payment } from '@mercadopago/sdk-react'; import { toast } from 'react-hot-toast'; interface DadosComprador { nome?: string; email?: string; } interface MercadoPagoPaymentBrickProps { pedidoId: string; valorTotal: number; dadosComprador?: DadosComprador; faturaId?: string | null; onSuccess?: (payment: any) => void; onError?: (error: string) => void; onProcessingChange?: (processing: boolean) => void; } export const MercadoPagoPaymentBrick = ({ pedidoId, valorTotal, dadosComprador, faturaId, onSuccess, onError, onProcessingChange }: MercadoPagoPaymentBrickProps) => { const [brickReady, setBrickReady] = useState(false); const [processing, setProcessing] = useState(false); const publicKey = process.env.NEXT_PUBLIC_MERCADO_PAGO_PUBLIC_KEY; const amount = useMemo(() => { const parsed = Number(valorTotal || 0); return Number(parsed.toFixed(2)); }, [valorTotal]); useEffect(() => { if (!publicKey) { console.error('❌ NEXT_PUBLIC_MERCADO_PAGO_PUBLIC_KEY não configurada'); return; } // 🔍 Log da chave pública para verificar ambiente (sandbox vs produção) const keyPrefix = publicKey.substring(0, 15); const isSandbox = publicKey.includes('TEST'); initMercadoPago(publicKey, { locale: 'pt-BR' }); }, [publicKey]); const enviarPagamento = async (formData: any) => { if (!pedidoId) { throw new Error('Pedido não encontrado'); } onProcessingChange?.(true); setProcessing(true); const nome = dadosComprador?.nome?.trim() || 'Cliente SaveInMed'; const [firstName, ...resto] = nome.split(' '); const lastName = resto.join(' ') || 'SaveInMed'; const payload = { ...formData, transaction_amount: amount, pedidoId, faturaId: faturaId || undefined, description: `Pagamento do pedido ${pedidoId}`, payer: { ...formData.payer, email: dadosComprador?.email || formData?.payer?.email, first_name: firstName, last_name: lastName }, metadata: { origem: 'checkout', pedidoId } }; const response = await fetch('/api/mercadopago/pagamentos', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json(); console.log('📡 [API RESPONSE] Status:', response.status); console.log('📡 [API RESPONSE] OK?:', response.ok); console.log('📡 [API RESPONSE] Body:', result); if (!response.ok || !result.success) { console.error('❌ [API ERROR] Detalhes completos:', { status: response.status, result: result, error: result.error, details: result.details }); throw new Error(result.error || 'Erro ao criar pagamento'); } return result.payment; }; const handleSubmit = ({ formData }: { formData: any }) => { return new Promise(async (resolve, reject) => { try { // ⚠️ Validação crítica: verificar se token existe para cartões if (formData.payment_method_id !== 'pix' && !formData.token) { console.error('❌ [PAYMENT BRICK] Token do cartão não foi gerado! formData:', formData); throw new Error('Token do cartão não foi gerado. Por favor, verifique os dados do cartão e tente novamente.'); } const payment = await enviarPagamento(formData); const status = payment.status as string; if (status === 'approved') { toast.success('Pagamento aprovado com sucesso!'); } else if (status === 'pending' && payment.payment_method_id === 'pix') { toast.success('PIX gerado! Conclua no seu aplicativo bancário.'); } else { toast.success('Pagamento iniciado! Aguarde a confirmação.'); } onSuccess?.(payment); resolve(payment); } catch (error) { console.error('❌ [PAYMENT BRICK] Erro:', error); const message = error instanceof Error ? error.message : 'Erro ao processar pagamento'; toast.error(message); onError?.(message); reject(error); } finally { onProcessingChange?.(false); setProcessing(false); } }); }; if (!publicKey) { return (
NEXT_PUBLIC_MERCADO_PAGO_PUBLIC_KEY
e tente novamente.
Pagamento Seguro
Mercado Pago
{amount.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })}
Cartão à vista • PIX • Sem taxas extras
Pagamento 100% Seguro
Seus dados são protegidos com criptografia de ponta. Não armazenamos informações do cartão.