home
/
u529748449
/
domains
/
borabilhete.com
/
public_html
/
public
➕ New
📤 Upload
✎ Editing:
comprar.php
← Back
<?php // public/comprar.php session_start(); if (!isset($_SESSION['cliente_id'])) { header("Location: login.php"); exit; } if (!isset($_SESSION['dados_compra'])) { header("Location: eventos.php"); exit; } include '../admin/conexao.php'; error_reporting(E_ALL); ini_set('display_errors', 1); // ---------------- Sessão ---------------- $dados = $_SESSION['dados_compra']; $id_evento = (int)($dados['id_evento'] ?? 0); $setores = $dados['setor_id'] ?? []; $quantidades = $dados['quantidade'] ?? []; $nome_cliente = $_SESSION['cliente_nome'] ?? ''; $primeiro_nome = explode(' ', trim($nome_cliente))[0]; // garante e-mail na sessão $cliente_email = $_SESSION['cliente_email'] ?? ''; if (empty($cliente_email) && !empty($_SESSION['cliente_id'])) { if ($stc = $conn->prepare("SELECT email FROM clientes WHERE id=? LIMIT 1")) { $stc->bind_param('i', $_SESSION['cliente_id']); $stc->execute(); $rowC = $stc->get_result()->fetch_assoc(); $stc->close(); if (!empty($rowC['email'])) { $cliente_email = $rowC['email']; $_SESSION['cliente_email'] = $cliente_email; } } } // ---------------- Evento + taxa ---------------- $evento = null; if ($id_evento > 0) { $st = $conn->prepare(" SELECT id, nome, slug, taxa_tipo, taxa_percentual, taxa_valor FROM eventos WHERE id = ? LIMIT 1 "); $st->bind_param('i', $id_evento); $st->execute(); $evento = $st->get_result()->fetch_assoc(); $st->close(); } if (!$evento) { echo "<p style='color:red'>Evento inválido.</p>"; exit; } if (empty($_SESSION['dados_compra']['slug']) && !empty($evento['slug'])) { $_SESSION['dados_compra']['slug'] = $evento['slug']; } function taxa_unitaria(float $preco, ?string $tipo, ?float $perc, ?float $fixo): float { if ($tipo === 'fixa' && $fixo !== null) { return round(max(0, $fixo), 2); } $p = ($tipo === 'percentual' && $perc !== null) ? ($perc / 100.0) : 0.09; return round(max(0, $preco * $p), 2); } $taxa_tipo = $evento['taxa_tipo'] ?? null; $taxa_percentual = isset($evento['taxa_percentual']) ? (float)$evento['taxa_percentual'] : null; $taxa_valor = isset($evento['taxa_valor']) ? (float)$evento['taxa_valor'] : null; // ---------------- Itens ---------------- $setores_escolhidos = []; $total_geral = 0.0; $itensCount = min(count($setores), count($quantidades)); for ($i = 0; $i < $itensCount; $i++) { $qtd = (int)$quantidades[$i]; if ($qtd <= 0) continue; $id_setor = (int)$setores[$i]; $stmt = $conn->prepare(" SELECT nome_setor, preco FROM setores WHERE id = ? AND id_evento = ? LIMIT 1 "); $stmt->bind_param("ii", $id_setor, $id_evento); $stmt->execute(); $res = $stmt->get_result(); $row = $res->fetch_assoc(); $stmt->close(); if (!$row) continue; $preco_unit = (float)$row['preco']; $taxa_unit = taxa_unitaria($preco_unit, $taxa_tipo, $taxa_percentual, $taxa_valor); $preco_cheio = $preco_unit + $taxa_unit; $valor_total = $preco_cheio * $qtd; $total_geral += $valor_total; $setores_escolhidos[] = [ 'id' => $id_setor, 'nome' => $row['nome_setor'], 'preco' => $preco_unit, 'taxa_unit' => $taxa_unit, 'qtd' => $qtd, 'valor_total' => $valor_total ]; } if (empty($setores_escolhidos)) { echo "<p style='color:red;'>Você não selecionou nenhum ingresso válido.</p>"; exit; } $slug_evento = $_SESSION['dados_compra']['slug'] ?? null; ?> <!DOCTYPE html> <html lang="pt-BR"> <head> <meta charset="UTF-8" /> <title>Finalizar Compra</title> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link rel="stylesheet" href="css/baseingressos.css" /> <link rel="stylesheet" href="css/header.css" /> <link rel="stylesheet" href="css/footer.css" /> <link rel="stylesheet" href="css/comprar.css?v=6" /> <style> #mp-payment { margin-top: 16px; } #pix-qr canvas { width: 100%; height: auto; } .hint-checkout-brick { color:#6b7280; font-size:13px; margin:10px 0 0; } </style> </head> <body> <?php include __DIR__ . '/includes/header.php'; ?> <main class="page-checkout" role="main"> <section class="checkout-card" role="region" aria-labelledby="titulo-checkout"> <h2 id="titulo-checkout">Confirme sua compra</h2> <p class="hello"> Olá, <strong><?= htmlspecialchars($primeiro_nome) ?></strong>! <a class="link-logout" href="logout.php">Não sou eu, sair</a> </p> <div class="table-scroll"> <table class="table-checkout"> <thead> <tr> <th>Setor</th><th>Qtd</th><th>Preço + taxa</th><th>Subtotal</th><th></th> </tr> </thead> <tbody> <?php foreach ($setores_escolhidos as $item): ?> <tr class="linha-setor"> <td data-label="Setor"><?= htmlspecialchars($item['nome']) ?></td> <td data-label="Qtd"><?= (int)$item['qtd']; ?></td> <td data-label="Preço + taxa">R$ <?= number_format($item['preco'] + $item['taxa_unit'], 2, ',', '.'); ?></td> <td data-label="Subtotal" class="valor-total">R$ <?= number_format($item['valor_total'], 2, ',', '.'); ?></td> <td class="td-actions"> <button type="button" class="remover" onclick="removerLinha(this)" aria-label="Remover item"> <i class="fa-solid fa-trash"></i> </button> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> <div class="checkout-actions"> <p class="total" aria-live="polite">Total: R$ <?= number_format($total_geral, 2, ',', '.'); ?></p> <?php if ($slug_evento): ?> <a href="evento/<?= htmlspecialchars($slug_evento) ?>.php?editar=1" class="btn btn-outline"> <i class="fa-solid fa-pen-to-square"></i> Editar carrinho </a> <?php else: ?> <form action="template_evento.php" method="GET"> <input type="hidden" name="id_evento" value="<?= (int)$id_evento; ?>"> <button type="submit" class="btn btn-outline"> <i class="fa-solid fa-pen-to-square"></i> Editar carrinho </button> </form> <?php endif; ?> </div> <div id="mp-payment"></div> <!-- PIX QR --> <div id="pix-qr" style="display:none; margin-top:16px; text-align:center;"> <canvas id="pixCanvas" style="max-width:320px;"></canvas> <p id="pixCopy" style="word-break:break-all; font-size:12px;"></p> <button class="btn btn-outline" id="btnCopiarPix">Copiar código Pix</button> </div> <p class="hint-checkout-brick">Pagamento seguro pelo Mercado Pago, sem sair do nosso site.</p> </section> </main> <?php include __DIR__ . '/footer.php'; ?> <script> // --- tabela --- function removerLinha(btn){ btn.closest("tr").remove(); atualizarTotal(); } function atualizarTotal(){ let total=0; document.querySelectorAll(".linha-setor .valor-total").forEach(td=>{ const val = parseFloat(td.innerText.replace("R$","").replace(/\./g,"").replace(",",".")); if(!isNaN(val)) total+=val; }); const p = document.querySelector(".total"); if(p) p.innerText = "Total: R$ " + total.toFixed(2).replace(".", ","); } // --- PIX helpers --- function mostrarPixBase64(b64, copiaCola) { const img = new Image(); img.onload = function(){ const cv = document.getElementById("pixCanvas"); const ctx = cv.getContext("2d"); cv.width = img.width; cv.height = img.height; ctx.drawImage(img, 0, 0); }; img.src = "data:image/png;base64," + b64; document.getElementById("pix-qr").style.display = "block"; document.getElementById("pixCopy").innerText = copiaCola || ""; document.getElementById("pix-qr").scrollIntoView({behavior:'smooth', block:'center'}); } document.getElementById("btnCopiarPix")?.addEventListener("click", async () => { try { await navigator.clipboard.writeText(document.getElementById("pixCopy").innerText); alert("Código Pix copiado!"); } catch { alert("Não foi possível copiar automaticamente."); } }); // --- polling de status (PIX) --- let _pollTimer=null; function startPixWatcher(pedidoId){ let tries=0, maxTries=120; clearInterval(_pollTimer); _pollTimer=setInterval(async()=>{ tries++; try{ const r = await fetch(`api/mp/pedido_status.php?pedido_id=${encodeURIComponent(pedidoId)}`, {cache:'no-store'}); const j = await r.json(); if(j?.status==='pago'){ clearInterval(_pollTimer); location.href=`processar_pedido.php?pedido_id=${encodeURIComponent(pedidoId)}`; } else if(j?.status==='cancelado' || tries>=maxTries){ clearInterval(_pollTimer); if(j?.status==='cancelado') alert('Pagamento cancelado/rejeitado.'); } }catch(e){ console.warn('poll falhou',e); } },5000); } </script> <!-- SDK Mercado Pago --> <script src="https://sdk.mercadopago.com/js/v2"></script> <script> const TOTAL = <?= json_encode((float)$total_geral) ?>; const ITENS = <?= json_encode($setores_escolhidos, JSON_UNESCAPED_UNICODE) ?>; const ID_EVENTO = <?= (int)$id_evento ?>; const EMAIL_SESS = <?= json_encode($cliente_email) ?>; const mp = new MercadoPago("APP_USR-c5aadb2b-cefd-4fbf-8181-f176046485e0", { locale: "pt-BR" }); const bricksBuilder = mp.bricks(); let paymentController = null; bricksBuilder.create("payment", "mp-payment", { initialization: { amount: TOTAL, payer: { email: EMAIL_SESS || "", entityType: "individual", identification: { type:"CPF", number:"<?= $_SESSION['cliente_cpf'] ?? '' ?>" } } }, customization: { paymentMethods: { bankTransfer: "all", creditCard: "all" }, checkoutForm: { initiallySelectedPaymentMethod: "credit_card" }, visual: { paymentMethodsOrder: ["credit_card","bank_transfer"] } }, callbacks: { onReady: (ctrl) => { paymentController = ctrl; console.log("[BRICK] onReady"); const pixBox = document.getElementById("pix-qr"); if(pixBox) pixBox.style.display="none"; }, onError: (err) => { console.error("[BRICK] onError:", err); alert("Erro ao iniciar o pagamento. Veja o Console (F12)."); }, // >>> AQUI: Recebemos cardFormData do Brick (prioritário) onSubmit: (cardFormData) => { return new Promise(async (resolve) => { const done = ()=>resolve(); try { let selected = null; // Preferimos o que o Brick informou… if (cardFormData && typeof cardFormData === 'object') { selected = cardFormData.selectedPaymentMethod || null; } // …mas garantimos via DOM se necessário if (!selected) { const ccChecked = document.querySelector('[data-test-id="payment-method-credit_card"] input[type="radio"]')?.checked; const pixChecked = document.querySelector('[data-test-id="payment-method-bank_transfer"] input[type="radio"]')?.checked; selected = ccChecked ? "credit_card" : (pixChecked ? "bank_transfer" : "credit_card"); } // Monta objeto final a enviar const formData = (cardFormData && cardFormData.formData && typeof cardFormData.formData==='object') ? cardFormData.formData : (await (paymentController?.getFormData?.() || Promise.resolve({}))); // Garante e-mail if (!formData.payer) formData.payer = {}; if (!formData.payer.email && EMAIL_SESS) formData.payer.email = EMAIL_SESS; // Se PIX, marque explicitamente if (selected === "bank_transfer") { formData.payment_method_id = "pix"; } console.log("[BRICK] formData enviado:", {selectedPaymentMethod:selected, formData}); const resp = await fetch("api/mp/process_payment.php", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ amount: TOTAL, items: ITENS, id_evento: ID_EVENTO, payData: { selectedPaymentMethod: selected, payer: formData.payer || {}, formData } }) }); const txt = await resp.text(); let data; try{ data = JSON.parse(txt); } catch { data = null; } console.log("[BACKEND]", resp.status, data ?? txt); if (!resp.ok || !data) { alert((data && data.message) ? data.message : "Falha ao processar.\n" + txt); return done(); } if (data.status === "approved") { location.href = "processar_pedido.php?pedido_id=" + encodeURIComponent(data.pedido_id); return; } if (data.payment_method_id === "pix") { if (data.qr_code_base64) mostrarPixBase64(data.qr_code_base64, data.qr_code || ""); else if (data.qr_code) { document.getElementById("pix-qr").style.display="block"; document.getElementById("pixCopy").innerText=data.qr_code; } else alert("PIX criado, mas sem QR no retorno."); document.getElementById("pix-qr").scrollIntoView({behavior:'smooth', block:'center'}); if (data.pedido_id) startPixWatcher(data.pedido_id); return done(); } if (data.status === "rejected") { alert("Pagamento recusado: " + (data.status_detail || "")); return done(); } alert("Status do pagamento: " + (data.status || "indefinido")); return done(); } catch (e) { console.error("[BRICK] submit erro:", e); alert("Erro inesperado ao processar pagamento."); return done(); } }); } } }); // alternar exibição do bloco de QR quando mudar método document.addEventListener("change", () => { const pixBox = document.getElementById("pix-qr"); if (!pixBox) return; const isPix = document.querySelector('[data-test-id="payment-method-bank_transfer"] input[type="radio"]')?.checked; pixBox.style.display = isPix ? pixBox.style.display : "none"; }); </script> </body> </html>
💾 Save Changes
Cancel
📤 Upload File
×
Select File
Upload
Cancel
➕ Create New
×
Type
📄 File
📁 Folder
Name
Create
Cancel
✎ Rename Item
×
Current Name
New Name
Rename
Cancel
🔐 Change Permissions
×
Target File
Permission (e.g., 0755, 0644)
0755
0644
0777
Apply
Cancel