Sariel187's picture
Update index.html
7fd27e0 verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>SecurePIX | Gerador de Pagamentos</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/imask"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
:root {
--primary-dark: #0a0a0a;
--primary-medium: #1a1a1a;
--primary-light: #2a2a2a;
--accent-light: #e0e0e0;
--accent-medium: #a0a0a0;
--accent-dark: #5a5a5a;
--white: #ffffff;
--black: #000000;
}
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0a0a0a 100%);
min-height: 100vh;
overflow-x: hidden;
position: relative;
color: var(--white);
}
body::before {
content: "";
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(circle at 20% 30%, rgba(255, 255, 255, 0.03) 0%, transparent 40%),
radial-gradient(circle at 80% 70%, rgba(255, 255, 255, 0.02) 0%, transparent 40%),
radial-gradient(circle at 40% 80%, rgba(255, 255, 255, 0.01) 0%, transparent 40%);
z-index: -1;
}
.card-bg {
background: rgba(26, 26, 26, 0.8);
backdrop-filter: blur(15px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow:
0 10px 30px rgba(0, 0, 0, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.neon-glow {
box-shadow:
0 0 15px rgba(255, 255, 255, 0.1),
0 0 30px rgba(255, 255, 255, 0.05),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
}
.gradient-text {
background: linear-gradient(90deg, #e0e0e0 0%, #ffffff 50%, #e0e0e0 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 200% auto;
animation: shimmer 3s linear infinite;
}
@keyframes shimmer {
0% { background-position: 0% center; }
100% { background-position: 200% center; }
}
.float-animation {
animation: float 6s ease-in-out infinite;
}
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
100% { transform: translateY(0px); }
}
.pulse-glow {
animation: pulse-glow 2s infinite;
}
@keyframes pulse-glow {
0% { box-shadow: 0 0 10px rgba(255, 255, 255, 0.1); }
50% { box-shadow: 0 0 20px rgba(255, 255, 255, 0.2); }
100% { box-shadow: 0 0 10px rgba(255, 255, 255, 0.1); }
}
.typewriter {
overflow: hidden;
border-right: 2px solid rgba(255, 255, 255, 0.7);
white-space: nowrap;
animation: typing 3.5s steps(40, end), blink-caret 0.75s step-end infinite;
}
@keyframes typing {
from { width: 0 }
to { width: 100% }
}
@keyframes blink-caret {
from, to { border-color: transparent }
50% { border-color: rgba(255, 255, 255, 0.7) }
}
.particle {
position: absolute;
width: 4px;
height: 4px;
background: rgba(255, 255, 255, 0.5);
border-radius: 50%;
opacity: 0;
}
.particle:nth-child(1) { top: 20%; left: 10%; animation: particle-float 8s infinite; }
.particle:nth-child(2) { top: 60%; left: 85%; animation: particle-float 10s infinite 1s; }
.particle:nth-child(3) { top: 80%; left: 20%; animation: particle-float 12s infinite 2s; }
.particle:nth-child(4) { top: 30%; left: 70%; animation: particle-float 9s infinite 3s; }
.particle:nth-child(5) { top: 70%; left: 40%; animation: particle-float 11s infinite 4s; }
@keyframes particle-float {
0% { transform: translateY(0) translateX(0); opacity: 0; }
50% { opacity: 1; }
100% { transform: translateY(-100px) translateX(20px); opacity: 0; }
}
.btn-hover-effect {
position: relative;
overflow: hidden;
transition: all 0.3s;
}
.btn-hover-effect::before {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
transition: all 0.6s;
}
.btn-hover-effect:hover::before {
left: 100%;
}
.input-focus-effect:focus {
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
}
/* Campo de valor aprimorado */
.amount-input-container {
position: relative;
background: rgba(255, 255, 255, 0.05);
border-radius: 16px;
padding: 1.5rem;
border: 1px solid rgba(255, 255, 255, 0.1);
transition: all 0.3s;
}
.amount-input-container:focus-within {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
}
.amount-input {
font-size: 2.5rem;
font-weight: 700;
background: transparent;
border: none;
color: white;
width: 100%;
text-align: center;
outline: none;
}
.amount-input::placeholder {
color: rgba(255, 255, 255, 0.3);
}
.currency-symbol {
position: absolute;
left: 2rem;
top: 50%;
transform: translateY(-50%);
font-size: 2rem;
color: rgba(255, 255, 255, 0.7);
}
.input-decoration {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 80%;
height: 2px;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
}
/* Modal */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(5px);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
opacity: 0;
visibility: hidden;
transition: all 0.3s;
}
.modal-overlay.active {
opacity: 1;
visibility: visible;
}
.modal-content {
width: 90%;
max-width: 500px;
background: var(--primary-medium);
border-radius: 20px;
padding: 2rem;
transform: translateY(20px);
opacity: 0;
transition: all 0.3s;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.5);
}
.modal-overlay.active .modal-content {
transform: translateY(0);
opacity: 1;
}
.payment-status {
display: flex;
align-items: center;
justify-content: center;
margin-top: 1rem;
padding: 0.75rem;
border-radius: 8px;
background: rgba(0, 0, 0, 0.2);
}
.payment-status.paid {
background: rgba(16, 185, 129, 0.1);
border: 1px solid rgba(16, 185, 129, 0.3);
}
.payment-status.pending {
background: rgba(245, 158, 11, 0.1);
border: 1px solid rgba(245, 158, 11, 0.3);
}
.payment-status.canceled {
background: rgba(239, 68, 68, 0.1);
border: 1px solid rgba(239, 68, 68, 0.3);
}
.qr-code-placeholder {
width: 180px;
height: 180px;
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 1rem auto;
border: 1px dashed rgba(255, 255, 255, 0.2);
}
.qr-code-placeholder i {
font-size: 3rem;
margin-bottom: 0.5rem;
color: rgba(255, 255, 255, 0.3);
}
.close-modal {
position: absolute;
top: 1rem;
right: 1rem;
background: none;
border: none;
color: rgba(255, 255, 255, 0.7);
font-size: 1.5rem;
cursor: pointer;
transition: color 0.2s;
}
.close-modal:hover {
color: var(--white);
}
.logo-icon {
width: 60px;
height: 60px;
border-radius: 16px;
background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%);
display: flex;
align-items: center;
justify-content: center;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.logo-icon i {
font-size: 1.8rem;
color: rgba(255, 255, 255, 0.9);
}
.info-card {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 1.5rem;
border-left: 4px solid rgba(255, 255, 255, 0.2);
margin-top: 1.5rem;
}
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-top: 2rem;
}
.feature-item {
display: flex;
align-items: center;
padding: 1rem;
background: rgba(255, 255, 255, 0.03);
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.05);
}
.feature-icon {
width: 40px;
height: 40px;
border-radius: 10px;
background: rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
justify-content: center;
margin-right: 1rem;
}
.step-indicator {
display: flex;
justify-content: space-between;
position: relative;
margin: 2rem 0;
}
.step-indicator::before {
content: "";
position: absolute;
top: 15px;
left: 0;
right: 0;
height: 2px;
background: rgba(255, 255, 255, 0.1);
z-index: 1;
}
.step {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 2;
}
.step-circle {
width: 32px;
height: 32px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 0.5rem;
border: 2px solid rgba(255, 255, 255, 0.2);
}
.step.active .step-circle {
background: rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.5);
}
.step-text {
font-size: 0.75rem;
color: rgba(255, 255, 255, 0.7);
text-align: center;
}
.security-badge {
display: inline-flex;
align-items: center;
background: rgba(16, 185, 129, 0.1);
color: #10b981;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
margin-left: 0.5rem;
}
.fraude-info {
background: rgba(245, 158, 11, 0.1);
border: 1px solid rgba(245, 158, 11, 0.3);
border-radius: 12px;
padding: 1.5rem;
margin-top: 2rem;
}
.fraude-info h3 {
display: flex;
align-items: center;
color: #f59e0b;
margin-bottom: 0.5rem;
}
.text-input {
color: #000000 !important;
}
.text-input::placeholder {
color: #666666 !important;
}
</style>
</head>
<body class="flex flex-col justify-center items-center p-4 min-h-screen">
<!-- Partículas de fundo -->
<div class="particle"></div>
<div class="particle"></div>
<div class="particle"></div>
<div class="particle"></div>
<div class="particle"></div>
<div class="w-full max-w-2xl relative">
<!-- Cabeçalho -->
<div class="text-center mb-8 relative">
<div class="flex justify-center items-center mb-4">
<div class="logo-icon mr-4 float-animation">
<i class="fas fa-coins"></i>
</div>
<div>
<h1 class="text-4xl font-bold gradient-text">SecurePIX</h1>
</div>
</div>
<p class="text-gray-400 text-lg typewriter">Gerador de código PIX instantâneo</p>
</div>
<!-- Card principal -->
<div class="card-bg rounded-2xl p-6 neon-glow relative overflow-hidden">
<!-- Efeito de brilho interno -->
<div class="absolute inset-0 bg-gradient-to-br from-transparent via-white/5 to-transparent pointer-events-none"></div>
<!-- Indicador de etapas -->
<div class="step-indicator">
<div class="step active">
<div class="step-circle">
<i class="fas fa-dollar-sign text-xs"></i>
</div>
<div class="step-text">Valor</div>
</div>
<div class="step">
<div class="step-circle">
<i class="fas fa-qrcode text-xs"></i>
</div>
<div class="step-text">QR Code</div>
</div>
<div class="step">
<div class="step-circle">
<i class="fas fa-check text-xs"></i>
</div>
<div class="step-text">Concluído</div>
</div>
</div>
<div class="mb-6 relative z-10">
<h2 class="text-xl font-semibold text-white flex items-center">
<i class="fas fa-dollar-sign text-gray-300 mr-2"></i>
Informe o valor do pagamento
<span class="security-badge">
<i class="fas fa-shield-alt mr-1"></i> Seguro
</span>
</h2>
<p class="text-gray-400 text-sm mt-1">
Digite o valor que deseja pagar via PIX
</p>
</div>
<!-- Campo de valor aprimorado -->
<div class="mb-6 relative z-10">
<div class="amount-input-container">
<span class="currency-symbol">R$</span>
<input
type="number"
id="amount"
step="0.01"
min="0.01"
placeholder="0,00"
class="amount-input"
>
<div class="input-decoration"></div>
</div>
<div class="flex justify-between mt-2">
<p class="text-gray-500 text-xs flex items-center">
<i class="fas fa-info-circle mr-1"></i>
Use valores como 25,00 ou 50,00
</p>
<p class="text-gray-500 text-xs">
<span id="amount-preview">R$ 0,00</span>
</p>
</div>
</div>
<!-- Botão de gerar PIX -->
<button
id="generate-pix"
class="w-full bg-gradient-to-r from-gray-800 to-gray-900 text-white font-bold py-4 rounded-xl btn-hover-effect pulse-glow relative overflow-hidden transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-gray-600"
>
<i class="fas fa-bolt mr-2"></i>
GERAR CÓDIGO PIX
<i class="fas fa-qrcode ml-2"></i>
</button>
<!-- Informações de segurança -->
<div class="feature-grid">
<div class="feature-item">
<div class="feature-icon">
<i class="fas fa-shield-alt"></i>
</div>
<div>
<h3 class="font-semibold">Segurança</h3>
<p class="text-gray-400 text-sm">Transação criptografada</p>
</div>
</div>
<div class="feature-item">
<div class="feature-icon">
<i class="fas fa-bolt"></i>
</div>
<div>
<h3 class="font-semibold">Instantâneo</h3>
<p class="text-gray-400 text-sm">Processamento rápido</p>
</div>
</div>
<div class="feature-item">
<div class="feature-icon">
<i class="fas fa-mobile-alt"></i>
</div>
<div>
<h3 class="font-semibold">Prático</h3>
<p class="text-gray-400 text-sm">Copie e cole o código</p>
</div>
</div>
</div>
<!-- Informações sobre avisos de fraude -->
<div class="fraude-info">
<h3><i class="fas fa-exclamation-triangle mr-2"></i> Aviso importante sobre segurança</h3>
<p class="text-gray-300 text-sm">
Alguns bancos podem exibir alertas de segurança durante o pagamento. Isso acontece porque o recebedor processa um grande volume de transações, o que pode ativar sistemas automáticos de prevenção a fraudes.
</p>
<p class="text-gray-300 text-sm mt-2">
Estes avisos são normais e não indicam qualquer problema com sua transação. Nossa plataforma é 100% segura e todas as transações são criptografadas.
</p>
<div class="flex items-center mt-3 text-xs text-gray-400">
<i class="fas fa-info-circle mr-2"></i>
<span>Em caso de dúvidas, entre em contato com nosso suporte.</span>
</div>
</div>
</div>
<!-- Rodapé -->
<div class="text-center mt-6 text-gray-500 text-sm">
<p class="flex items-center justify-center">
<i class="fas fa-lock text-gray-400 mr-2"></i>
Transação 100% segura e criptografada
</p>
<p class="mt-2 flex items-center justify-center">
<i class="fas fa-bolt text-gray-400 mr-2"></i>
Processamento instantâneo
</p>
<p class="mt-2 flex items-center justify-center">
<i class="fas fa-headset text-gray-400 mr-2"></i>
Suporte 24/7 disponível
</p>
</div>
</div>
<!-- Modal para exibição do código PIX -->
<div class="modal-overlay" id="pix-modal">
<div class="modal-content">
<button class="close-modal" id="close-modal">
<i class="fas fa-times"></i>
</button>
<div class="text-center mb-4">
<h2 class="text-2xl font-bold text-white">Código PIX Gerado</h2>
<p class="text-gray-400 mt-1">Copie o código abaixo para realizar o pagamento</p>
</div>
<!-- QR Code Placeholder -->
<div class="qr-code-placeholder">
<i class="fas fa-qrcode"></i>
<span class="text-gray-400 text-sm">QR Code</span>
</div>
<!-- Valor do pagamento -->
<div class="text-center my-4">
<p class="text-gray-400">Valor a pagar:</p>
<p class="text-2xl font-bold text-white" id="modal-amount">R$ 0,00</p>
</div>
<!-- Código PIX para copiar -->
<div class="bg-gray-900 rounded-xl p-4 border border-gray-700 mt-4">
<div class="flex items-center mb-2">
<i class="fas fa-qrcode text-gray-400 mr-2"></i>
<p class="text-white font-medium">Código PIX copia e cola:</p>
</div>
<div class="flex items-center">
<input
type="text"
id="pix-copy-paste"
class="flex-1 bg-white border border-gray-600 rounded-l-lg py-3 px-4 text-input text-sm font-mono focus:outline-none input-focus-effect"
readonly
>
<button
id="copy-pix-button"
class="bg-gradient-to-b from-gray-800 to-gray-900 hover:from-gray-700 hover:to-gray-800 text-white py-3 px-4 rounded-r-lg transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-gray-600 flex items-center btn-hover-effect"
>
<i class="fas fa-copy mr-1"></i> Copiar
</button>
</div>
</div>
<!-- Status do pagamento -->
<div class="payment-status pending mt-4" id="payment-status">
<i class="fas fa-clock text-yellow-500 mr-2"></i>
<span class="text-gray-300">Aguardando pagamento</span>
</div>
<!-- Instruções -->
<div class="mt-4 bg-gray-800/50 rounded-lg p-3 border border-gray-700">
<p class="text-gray-300 text-sm flex items-start">
<i class="fas fa-lightbulb text-gray-400 mr-2 mt-1"></i>
<span>Abra seu app de pagamentos, selecione PIX Copia e Cola, cole o código e confirme o pagamento.</span>
</p>
</div>
<!-- Informações adicionais -->
<div class="info-card mt-4">
<h3 class="font-semibold text-white flex items-center">
<i class="fas fa-info-circle text-gray-400 mr-2"></i>
Importante
</h3>
<p class="text-gray-300 text-sm mt-1">
Após o pagamento, o status será atualizado automaticamente para "Pago". Em caso de problemas, entre em contato com nosso suporte.
</p>
</div>
</div>
</div>
<!-- Informações ocultas -->
<div class="hidden">
<!-- Formulário oculto com dados pré-preenchidos -->
<form id="customer-form">
<input name="name" id="name" type="text">
<input name="phone_number" id="phone_number" type="tel">
<input type="hidden" id="email" name="email">
<input type="hidden" id="document" name="document">
</form>
</div>
<script>
// === CONFIGURAÇÃO IRONPAY ===
const productInfo = {
productName: "Banir Whatsapp",
productImage: "https://dlzpblyjxiqfa.cloudfront.net/2994882476/products/qldxhanwdvi90ee5kh88s7kfr",
productHash: "p7kb7gvu9t",
offerHash: "9v8oiyiytj"
};
// Configurações da API IronPay
const API_ENDPOINT = "https://api.ironpayapp.com.br/api/public/v1";
const API_TOKEN = "MXAZwBvIoLSD2tZIDeLA68HY38eXx7c1HYa65Kj6VMjtAvYe4Q65ZQrIxvc4";
// === LISTAS DE DADOS VÁLIDOS ===
const namesAndPhones = [
{ name: "Ana Carolina Silva", phone: "11987654321" },
{ name: "Bruno Oliveira Santos", phone: "21976543210" },
{ name: "Carla Mendes Rodrigues", phone: "31965432109" },
{ name: "Diego Almeida Costa", phone: "41954321098" },
{ name: "Elisa Pereira Lima", phone: "51943210987" },
{ name: "Fernando Souza Oliveira", phone: "61932109876" },
{ name: "Gabriela Rocha Martins", phone: "71921098765" },
{ name: "Henrique Barbosa Ferreira", phone: "81910987654" },
{ name: "Isabela Carvalho Alves", phone: "12999876543" },
{ name: "João Victor Dias Nunes", phone: "13988765432" },
{ name: "Larissa Santos Costa", phone: "14977654321" },
{ name: "Marcos Vinicius Almeida", phone: "15966543210" },
{ name: "Natália Ferreira Lima", phone: "16955432109" },
{ name: "Otávio Rodrigues Pereira", phone: "17944321098" },
{ name: "Patrícia Souza Oliveira", phone: "18933210987" },
{ name: "Rafael Mendes Carvalho", phone: "19922109876" },
{ name: "Sofia Alves Martins", phone: "21911987654" },
{ name: "Thiago Costa Nunes", phone: "22900876543" },
{ name: "Vanessa Lima Santos", phone: "23999765432" },
{ name: "William Oliveira Rodrigues", phone: "24988654321" },
{ name: "Alice Pereira Almeida", phone: "25977543210" },
{ name: "Breno Carvalho Ferreira", phone: "26966432109" },
{ name: "Camila Martins Costa", phone: "27955321098" },
{ name: "Daniel Nunes Lima", phone: "28944210987" },
{ name: "Eduarda Santos Oliveira", phone: "29933109876" },
{ name: "Felipe Almeida Rodrigues", phone: "31922098765" },
{ name: "Giovanna Ferreira Pereira", phone: "32911987654" },
{ name: "Heitor Lima Carvalho", phone: "33900876543" },
{ name: "Igor Costa Martins", phone: "34999765432" },
{ name: "Julia Oliveira Nunes", phone: "35988654321" },
{ name: "Kevin Rodrigues Santos", phone: "36977543210" },
{ name: "Lucas Pereira Almeida", phone: "37966432109" },
{ name: "Mariana Carvalho Ferreira", phone: "38955321098" },
{ name: "Nathan Martins Costa", phone: "39944210987" },
{ name: "Olivia Nunes Lima", phone: "41933109876" },
{ name: "Pedro Santos Oliveira", phone: "42922098765" },
{ name: "Quezia Almeida Rodrigues", phone: "43911987654" },
{ name: "Ruan Ferreira Pereira", phone: "44900876543" },
{ name: "Stella Lima Carvalho", phone: "45999765432" },
{ name: "Thomas Costa Martins", phone: "46988654321" },
{ name: "Ursula Oliveira Nunes", phone: "47977543210" },
{ name: "Vitor Rodrigues Santos", phone: "48966432109" },
{ name: "Wesley Pereira Almeida", phone: "49955321098" },
{ name: "Xuxa Carvalho Ferreira", phone: "51944210987" },
{ name: "Yasmin Martins Costa", phone: "52933109876" },
{ name: "Zacarias Nunes Lima", phone: "53922098765" },
{ name: "Amanda Santos Oliveira", phone: "54911987654" },
{ name: "Bernardo Almeida Rodrigues", phone: "55900876543" },
{ name: "Clara Ferreira Pereira", phone: "56999765432" },
{ name: "Davi Lima Carvalho", phone: "57988654321" },
{ name: "Elaine Costa Martins", phone: "58977543210" },
{ name: "Fabio Oliveira Nunes", phone: "59966432109" },
{ name: "Geovana Rodrigues Santos", phone: "61955321098" },
{ name: "Hugo Pereira Almeida", phone: "62944210987" },
{ name: "Ingrid Carvalho Ferreira", phone: "63933109876" },
{ name: "Jorge Martins Costa", phone: "64922098765" },
{ name: "Karen Nunes Lima", phone: "65911987654" },
{ name: "Leonardo Santos Oliveira", phone: "66900876543" },
{ name: "Michele Almeida Rodrigues", phone: "67999765432" },
{ name: "Nicolas Ferreira Pereira", phone: "68988654321" },
{ name: "Orlando Lima Carvalho", phone: "69977543210" },
{ name: "Paula Costa Martins", phone: "71966432109" },
{ name: "Quintino Oliveira Nunes", phone: "72955321098" },
{ name: "Renata Rodrigues Santos", phone: "73944210987" },
{ name: "Samuel Pereira Almeida", phone: "74933109876" },
{ name: "Tatiane Carvalho Ferreira", phone: "75922098765" },
{ name: "Ubirajara Martins Costa", phone: "76911987654" },
{ name: "Viviane Nunes Lima", phone: "77900876543" },
{ name: "Wagner Santos Oliveira", phone: "78999765432" },
{ name: "Xande Almeida Rodrigues", phone: "79988654321" },
{ name: "Yara Ferreira Pereira", phone: "81977543210" },
{ name: "Zé Lima Carvalho", phone: "82966432109" },
{ name: "Aline Costa Martins", phone: "83955321098" },
{ name: "Beto Oliveira Nunes", phone: "84944210987" },
{ name: "Cíntia Rodrigues Santos", phone: "85933109876" },
{ name: "Douglas Pereira Almeida", phone: "86922098765" },
{ name: "Ester Carvalho Ferreira", phone: "87911987654" },
{ name: "Flávio Martins Costa", phone: "88900876543" },
{ name: "Gisele Nunes Lima", phone: "89999765432" },
{ name: "Hélio Santos Oliveira", phone: "91988654321" },
{ name: "Iara Almeida Rodrigues", phone: "92977543210" },
{ name: "José Ferreira Pereira", phone: "93966432109" },
{ name: "Kelly Lima Carvalho", phone: "94955321098" },
{ name: "Leandro Costa Martins", phone: "95944210987" },
{ name: "Márcia Oliveira Nunes", phone: "96933109876" },
{ name: "Nelson Rodrigues Santos", phone: "97922098765" },
{ name: "Olívia Pereira Almeida", phone: "98911987654" },
{ name: "Paulo Carvalho Ferreira", phone: "99900876543" },
{ name: "Quésia Martins Costa", phone: "11988765432" },
{ name: "Ricardo Nunes Lima", phone: "12977654321" },
{ name: "Sandra Santos Oliveira", phone: "13966543210" },
{ name: "Tiago Almeida Rodrigues", phone: "14955432109" },
{ name: "Úrsula Ferreira Pereira", phone: "15944321098" },
{ name: "Valter Lima Carvalho", phone: "16933210987" },
{ name: "Wanessa Costa Martins", phone: "17922109876" },
{ name: "Xavier Oliveira Nunes", phone: "18911098765" },
{ name: "Yasmin Rodrigues Santos", phone: "19900987654" }
];
// Função para gerar CPF válido
function generateValidCPF() {
function randomDigit() {
return Math.floor(Math.random() * 10);
}
function calculateDigit(base, factor) {
let total = 0;
for (let i = 0; i < base.length; i++) {
total += base[i] * (factor - i);
}
const remainder = total % 11;
return remainder < 2 ? 0 : 11 - remainder;
}
// Gera 9 dígitos aleatórios
const base = Array.from({ length: 9 }, randomDigit);
// Calcula o primeiro dígito verificador
const firstDigit = calculateDigit(base, 10);
base.push(firstDigit);
// Calcula o segundo dígito verificador
const secondDigit = calculateDigit(base, 11);
base.push(secondDigit);
return base.join('');
}
// Gerar 100 CPFs válidos
const cpfs = Array.from({ length: 100 }, generateValidCPF);
const emails = [
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]"
];
// === ELEMENTOS ===
const customerForm = document.getElementById('customer-form');
const amountInput = document.getElementById('amount');
const amountPreview = document.getElementById('amount-preview');
const generatePixButton = document.getElementById('generate-pix');
const pixModal = document.getElementById('pix-modal');
const closeModalButton = document.getElementById('close-modal');
const pixCopyPasteInput = document.getElementById('pix-copy-paste');
const copyPixButton = document.getElementById('copy-pix-button');
const paymentStatus = document.getElementById('payment-status');
const modalAmount = document.getElementById('modal-amount');
// === FUNÇÕES AUXILIARES ===
function getRandomItem(array) {
return array[Math.floor(Math.random() * array.length)];
}
function autoFillCustomerData() {
// Seleciona aleatoriamente um nome, telefone, CPF e email
const randomUser = getRandomItem(namesAndPhones);
const randomCPF = getRandomItem(cpfs);
const randomEmail = getRandomItem(emails);
// Preenche os campos ocultos
document.getElementById('name').value = randomUser.name;
document.getElementById('phone_number').value = randomUser.phone;
document.getElementById('document').value = randomCPF;
document.getElementById('email').value = randomEmail;
console.log('Dados preenchidos automaticamente:', {
name: randomUser.name,
phone: randomUser.phone,
cpf: randomCPF,
email: randomEmail
});
}
function openModal() {
pixModal.classList.add('active');
document.body.style.overflow = 'hidden';
// Atualiza o valor no modal
const amount = parseFloat(amountInput.value);
modalAmount.textContent = `R$ ${amount.toFixed(2).replace('.', ',')}`;
}
function closeModal() {
pixModal.classList.remove('active');
document.body.style.overflow = 'auto';
}
function updatePaymentStatus(status) {
// Remove todas as classes de status
paymentStatus.classList.remove('pending', 'paid', 'canceled');
// Adiciona a classe correspondente ao status
paymentStatus.classList.add(status);
// Atualiza o texto e ícone conforme o status
switch(status) {
case 'paid':
paymentStatus.innerHTML = '<i class="fas fa-check-circle text-green-500 mr-2"></i><span class="text-gray-300">Pagamento confirmado</span>';
break;
case 'pending':
paymentStatus.innerHTML = '<i class="fas fa-clock text-yellow-500 mr-2"></i><span class="text-gray-300">Aguardando pagamento</span>';
break;
case 'canceled':
paymentStatus.innerHTML = '<i class="fas fa-times-circle text-red-500 mr-2"></i><span class="text-gray-300">Pagamento cancelado</span>';
break;
}
}
// Atualizar preview do valor
amountInput.addEventListener('input', function() {
const amount = parseFloat(this.value) || 0;
amountPreview.textContent = `R$ ${amount.toFixed(2).replace('.', ',')}`;
});
// === API helpers ===
async function fetchTransactionByHashOnce(hash) {
const url = `${API_ENDPOINT}/transactions/${hash}?api_token=${API_TOKEN}`;
const r = await fetch(url, { headers: { Accept: 'application/json' } });
const txt = await r.text();
let j;
try {
j = JSON.parse(txt);
} catch {
j = { raw: txt };
}
return { ok: r.ok, status: r.status, json: j };
}
// === Gerar PIX ===
generatePixButton.addEventListener('click', async () => {
const amount = parseFloat(amountInput.value);
if (!amount || amount <= 0) {
// Efeito visual de erro
amountInput.parentElement.classList.add('border-red-500');
setTimeout(() => {
amountInput.parentElement.classList.remove('border-red-500');
}, 1000);
// Mostrar mensagem de erro
const errorMsg = document.createElement('div');
errorMsg.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-red-600 text-white px-4 py-2 rounded-lg shadow-lg z-50';
errorMsg.innerHTML = '<i class="fas fa-exclamation-triangle mr-2"></i>Por favor, insira um valor válido';
document.body.appendChild(errorMsg);
setTimeout(() => {
document.body.removeChild(errorMsg);
}, 3000);
return;
}
// Efeito de loading no botão
generatePixButton.disabled = true;
generatePixButton.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> GERANDO...';
// Efeito visual de processamento
generatePixButton.classList.remove('pulse-glow');
generatePixButton.classList.add('bg-gray-700');
// Preenche dados automaticamente
autoFillCustomerData();
const customerData = {
name: document.getElementById('name').value,
email: document.getElementById('email').value,
phone_number: document.getElementById('phone_number').value,
document: document.getElementById('document').value,
street_name: "Não informado",
number: "s/n",
complement: "",
neighborhood: "Não informado",
city: "Não informado",
state: "NI",
zip_code: "00000000"
};
// Payload específico da IronPay
const paymentPayload = {
amount: Math.round(amount * 100), // IronPay usa centavos
offer_hash: productInfo.offerHash,
payment_method: "pix",
customer: customerData,
cart: [{
product_hash: productInfo.productHash,
title: productInfo.productName,
cover: null,
price: Math.round(amount * 100),
quantity: 1,
operation_type: 1,
tangible: false
}],
installments: 1,
expire_in_days: 1,
transaction_origin: 'api',
postback_url: ''
};
try {
// 1) Cria a transação na IronPay
const response = await fetch(`${API_ENDPOINT}/transactions?api_token=${API_TOKEN}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(paymentPayload)
});
const text = await response.text();
let result;
try {
result = JSON.parse(text);
} catch {
result = { raw: text };
}
if (!response.ok) {
const msg = result?.message || 'Ocorreu um erro.';
const errs = result?.errors ? '\n' + Object.values(result.errors).map(e => e[0]).join('\n') : '';
throw new Error(msg + errs);
}
// A IronPay retorna o hash diretamente no objeto de resposta
const hash = result?.hash || result?.data?.hash;
if (!hash) throw new Error('Transação criada, mas sem hash na resposta.');
// 2) Faz UM ÚNICO GET para pegar os dados e já renderizar
const { ok, json } = await fetchTransactionByHashOnce(hash);
if (!ok) throw new Error('Não foi possível obter os dados do PIX.');
const data = json.data || json;
const status = String(data.payment_status || data.status || '').toLowerCase();
// A IronPay retorna o QR Code no campo 'pix_qr_code'
const copyPaste = (data.pix_qr_code || data.pix?.pix_qr_code || data.qr_code || data.copy_paste || data.code || '').trim();
// Preenche o código PIX no modal
pixCopyPasteInput.value = copyPaste;
pixCopyPasteInput.setAttribute('value', copyPaste);
// Atualiza o status do pagamento
updatePaymentStatus(status);
// Abre o modal
openModal();
// Efeito de sucesso
generatePixButton.innerHTML = '<i class="fas fa-check mr-2"></i> CÓDIGO GERADO!';
setTimeout(() => {
generatePixButton.innerHTML = '<i class="fas fa-bolt mr-2"></i> GERAR CÓDIGO PIX <i class="fas fa-qrcode ml-2"></i>';
}, 2000);
} catch (error) {
console.error('Falha na operação:', error);
// Efeito visual de erro
generatePixButton.innerHTML = '<i class="fas fa-exclamation-triangle mr-2"></i> ERRO! TENTE NOVAMENTE';
generatePixButton.classList.add('bg-red-600');
setTimeout(() => {
generatePixButton.innerHTML = '<i class="fas fa-bolt mr-2"></i> GERAR CÓDIGO PIX <i class="fas fa-qrcode ml-2"></i>';
generatePixButton.classList.remove('bg-red-600');
generatePixButton.classList.add('pulse-glow');
}, 3000);
// Mostrar mensagem de erro
const errorMsg = document.createElement('div');
errorMsg.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-red-600 text-white px-4 py-2 rounded-lg shadow-lg z-50';
errorMsg.innerHTML = `<i class="fas fa-exclamation-triangle mr-2"></i>${error.message || 'Erro ao gerar PIX'}`;
document.body.appendChild(errorMsg);
setTimeout(() => {
document.body.removeChild(errorMsg);
}, 5000);
} finally {
generatePixButton.disabled = false;
generatePixButton.classList.remove('bg-gray-700');
generatePixButton.classList.add('pulse-glow');
}
});
// Copiar código PIX
copyPixButton.addEventListener('click', async () => {
const text = (pixCopyPasteInput.value || pixCopyPasteInput.getAttribute('value') || '').trim();
if (!text) {
// Efeito visual de erro
const errorMsg = document.createElement('div');
errorMsg.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-red-600 text-white px-4 py-2 rounded-lg shadow-lg z-50';
errorMsg.innerHTML = '<i class="fas fa-exclamation-triangle mr-2"></i>Código PIX não disponível';
document.body.appendChild(errorMsg);
setTimeout(() => {
document.body.removeChild(errorMsg);
}, 3000);
return;
}
try {
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(text);
} else {
const ta = document.createElement('textarea');
ta.value = text;
ta.style.position = 'fixed';
ta.style.left = '-9999px';
document.body.appendChild(ta);
ta.focus();
ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
}
// Efeito visual de sucesso
copyPixButton.innerHTML = '<i class="fas fa-check mr-1"></i> Copiado!';
copyPixButton.classList.remove('bg-gradient-to-b');
copyPixButton.classList.add('bg-green-600');
// Mostrar mensagem de sucesso
const successMsg = document.createElement('div');
successMsg.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-green-600 text-white px-4 py-2 rounded-lg shadow-lg z-50';
successMsg.innerHTML = '<i class="fas fa-check-circle mr-2"></i>Código copiado para a área de transferência!';
document.body.appendChild(successMsg);
setTimeout(() => {
document.body.removeChild(successMsg);
}, 3000);
} catch (e) {
console.error(e);
copyPixButton.innerHTML = '<i class="fas fa-times mr-1"></i> Falhou!';
copyPixButton.classList.remove('bg-gradient-to-b');
copyPixButton.classList.add('bg-red-600');
} finally {
setTimeout(() => {
copyPixButton.innerHTML = '<i class="fas fa-copy mr-1"></i> Copiar';
copyPixButton.classList.remove('bg-green-600', 'bg-red-600');
copyPixButton.classList.add('bg-gradient-to-b');
}, 2000);
}
});
// Fechar modal
closeModalButton.addEventListener('click', closeModal);
// Fechar modal ao clicar fora
pixModal.addEventListener('click', (e) => {
if (e.target === pixModal) {
closeModal();
}
});
// Efeitos interativos
amountInput.addEventListener('focus', function() {
this.parentElement.classList.add('neon-glow');
});
amountInput.addEventListener('blur', function() {
this.parentElement.classList.remove('neon-glow');
});
// Focar no campo de valor ao carregar a página
document.addEventListener('DOMContentLoaded', () => {
amountInput.focus();
// Efeito de digitação automática no campo de valor
setTimeout(() => {
amountInput.placeholder = "25,00";
}, 1000);
});
</script>
</body>
</html>