| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Advanced Card Generator</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script> |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> |
| <style> |
| body { |
| font-family: 'Inter', sans-serif; |
| background-color: #f8fafc; |
| } |
| .card-shadow { |
| box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); |
| } |
| .card-gradient { |
| background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%); |
| } |
| .card-number { |
| letter-spacing: 2px; |
| } |
| .loading-spinner { |
| border-top-color: transparent; |
| animation: spin 1s linear infinite; |
| } |
| @keyframes spin { |
| to { transform: rotate(360deg); } |
| } |
| .fade-in { |
| animation: fadeIn 0.3s ease-in; |
| } |
| @keyframes fadeIn { |
| from { opacity: 0; transform: translateY(10px); } |
| to { opacity: 1; transform: translateY(0); } |
| } |
| </style> |
| </head> |
| <body class="min-h-screen bg-gray-50"> |
| <div class="container mx-auto px-4 py-8 max-w-6xl"> |
| |
| <header class="mb-8"> |
| <h1 class="text-3xl font-bold text-gray-900 mb-2">Advanced Card Generator</h1> |
| <p class="text-gray-600">Generate valid test card numbers for development and testing purposes</p> |
| </header> |
|
|
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> |
| |
| <div class="lg:col-span-2 space-y-6"> |
| |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <h2 class="text-lg font-semibold text-gray-800 mb-4">Card Type</h2> |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-3"> |
| <button onclick="setCardType('visa')" class="card-type-btn flex items-center justify-center p-4 border rounded-lg hover:bg-gray-50 transition-colors"> |
| <img src="https://upload.wikimedia.org/wikipedia/commons/5/5e/Visa_Inc._logo.svg" alt="Visa" class="h-8"> |
| </button> |
| <button onclick="setCardType('mastercard')" class="card-type-btn flex items-center justify-center p-4 border rounded-lg hover:bg-gray-50 transition-colors"> |
| <img src="https://upload.wikimedia.org/wikipedia/commons/2/2a/Mastercard-logo.svg" alt="Mastercard" class="h-8"> |
| </button> |
| <button onclick="setCardType('amex')" class="card-type-btn flex items-center justify-center p-4 border rounded-lg hover:bg-gray-50 transition-colors"> |
| <img src="https://upload.wikimedia.org/wikipedia/commons/3/30/American_Express_logo.svg" alt="American Express" class="h-8"> |
| </button> |
| <button onclick="setCardType('discover')" class="card-type-btn flex items-center justify-center p-4 border rounded-lg hover:bg-gray-50 transition-colors"> |
| <img src="https://upload.wikimedia.org/wikipedia/commons/5/5f/Discover_Card_logo.svg" alt="Discover" class="h-8"> |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <h2 class="text-lg font-semibold text-gray-800 mb-4">Card Details</h2> |
| <div class="space-y-4"> |
| |
| <div> |
| <label for="bin" class="block text-sm font-medium text-gray-700 mb-1">BIN (Bank Identification Number)</label> |
| <div class="relative"> |
| <input type="text" id="bin" maxlength="6" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="First 6 digits" oninput="formatBin(this)"> |
| <div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none text-gray-400" id="bin-status"> |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> |
| <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" /> |
| </svg> |
| </div> |
| </div> |
| <p class="mt-1 text-xs text-gray-500">Enter the first 6 digits to generate cards with specific BIN</p> |
| </div> |
|
|
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label for="range-start" class="block text-sm font-medium text-gray-700 mb-1">Range Start</label> |
| <input type="text" id="range-start" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Optional"> |
| </div> |
| <div> |
| <label for="range-end" class="block text-sm font-medium text-gray-700 mb-1">Range End</label> |
| <input type="text" id="range-end" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Optional"> |
| </div> |
| </div> |
|
|
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Expiry Date</label> |
| <div class="relative"> |
| <input type="text" id="expiry-date" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="MM/YYYY" readonly> |
| <div class="absolute inset-y-0 right-0 flex items-center pr-3"> |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor"> |
| <path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd" /> |
| </svg> |
| </div> |
| </div> |
| </div> |
| <div> |
| <label for="cvv-length" class="block text-sm font-medium text-gray-700 mb-1">CVV Length</label> |
| <select id="cvv-length" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| <option value="3">3 digits</option> |
| <option value="4">4 digits</option> |
| </select> |
| </div> |
| </div> |
|
|
| |
| <div> |
| <label for="batch-size" class="block text-sm font-medium text-gray-700 mb-1">Number of Cards to Generate</label> |
| <select id="batch-size" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| <option value="1">1</option> |
| <option value="5" selected>5</option> |
| <option value="10">10</option> |
| <option value="20">20</option> |
| <option value="50">50</option> |
| </select> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="flex justify-end"> |
| <button id="generate-btn" onclick="generateCards()" class="px-6 py-3 bg-indigo-600 text-white font-medium rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors flex items-center"> |
| <span>Generate Cards</span> |
| <svg id="generate-spinner" class="hidden ml-2 h-5 w-5 text-white loading-spinner" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> |
| <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> |
| <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> |
| </svg> |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="space-y-6"> |
| |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <h2 class="text-lg font-semibold text-gray-800 mb-4">Card Preview</h2> |
| <div class="card-gradient rounded-xl p-6 text-white card-shadow"> |
| <div class="flex justify-between items-start mb-8"> |
| <div> |
| <p class="text-sm opacity-80">Card Type</p> |
| <p class="font-medium" id="preview-card-type">Visa</p> |
| </div> |
| <div id="preview-card-logo" class="h-8"> |
| <img src="https://upload.wikimedia.org/wikipedia/commons/5/5e/Visa_Inc._logo.svg" alt="Visa" class="h-full"> |
| </div> |
| </div> |
| <div class="mb-6"> |
| <p class="text-sm opacity-80 mb-1">Card Number</p> |
| <p class="text-xl font-semibold tracking-wider card-number" id="preview-card-number">•••• •••• •••• ••••</p> |
| </div> |
| <div class="flex justify-between"> |
| <div> |
| <p class="text-sm opacity-80 mb-1">Expiry Date</p> |
| <p class="font-medium" id="preview-expiry">••/••</p> |
| </div> |
| <div> |
| <p class="text-sm opacity-80 mb-1">CVV</p> |
| <p class="font-medium" id="preview-cvv">•••</p> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="bin-info" class="bg-white rounded-xl shadow-sm p-6 hidden"> |
| <h2 class="text-lg font-semibold text-gray-800 mb-4">BIN Information</h2> |
| <div class="space-y-3"> |
| <div class="flex justify-between"> |
| <span class="text-gray-600">Brand:</span> |
| <span class="font-medium" id="bin-brand">Visa</span> |
| </div> |
| <div class="flex justify-between"> |
| <span class="text-gray-600">Type:</span> |
| <span class="font-medium" id="bin-type">Credit</span> |
| </div> |
| <div class="flex justify-between"> |
| <span class="text-gray-600">Bank:</span> |
| <span class="font-medium" id="bin-bank">Example Bank</span> |
| </div> |
| <div class="flex justify-between"> |
| <span class="text-gray-600">Country:</span> |
| <span class="font-medium" id="bin-country">United States</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="generated-cards" class="mt-12 hidden"> |
| <div class="flex justify-between items-center mb-6"> |
| <h2 class="text-xl font-bold text-gray-900">Generated Cards</h2> |
| <div class="flex space-x-3"> |
| <button id="copy-all-btn" onclick="copyAllCards()" class="px-4 py-2 bg-gray-100 text-gray-700 font-medium rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors flex items-center"> |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor"> |
| <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z" /> |
| <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z" /> |
| </svg> |
| Copy All |
| </button> |
| <button id="download-btn" onclick="downloadCards()" class="px-4 py-2 bg-indigo-600 text-white font-medium rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors flex items-center"> |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor"> |
| <path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" /> |
| </svg> |
| Download |
| </button> |
| </div> |
| </div> |
|
|
| <div id="cards-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> |
| |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="toast" class="fixed bottom-4 right-4 hidden"> |
| <div class="bg-green-500 text-white px-4 py-2 rounded-md shadow-lg flex items-center"> |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor"> |
| <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" /> |
| </svg> |
| <span id="toast-message">Copied to clipboard!</span> |
| </div> |
| </div> |
|
|
| <script> |
| |
| let currentCardType = 'visa'; |
| let generatedCards = []; |
| const cardTypes = { |
| visa: { |
| name: 'Visa', |
| logo: 'https://upload.wikimedia.org/wikipedia/commons/5/5e/Visa_Inc._logo.svg', |
| pattern: /^4/, |
| lengths: [13, 16], |
| cvvLength: 3 |
| }, |
| mastercard: { |
| name: 'Mastercard', |
| logo: 'https://upload.wikimedia.org/wikipedia/commons/2/2a/Mastercard-logo.svg', |
| pattern: /^5[1-5]/, |
| lengths: [16], |
| cvvLength: 3 |
| }, |
| amex: { |
| name: 'American Express', |
| logo: 'https://upload.wikimedia.org/wikipedia/commons/3/30/American_Express_logo.svg', |
| pattern: /^3[47]/, |
| lengths: [15], |
| cvvLength: 4 |
| }, |
| discover: { |
| name: 'Discover', |
| logo: 'https://upload.wikimedia.org/wikipedia/commons/5/5f/Discover_Card_logo.svg', |
| pattern: /^6(?:011|5)/, |
| lengths: [16], |
| cvvLength: 3 |
| } |
| }; |
| |
| |
| function setCardType(type) { |
| currentCardType = type; |
| document.querySelectorAll('.card-type-btn').forEach(btn => { |
| btn.classList.remove('border-indigo-500', 'bg-indigo-50'); |
| }); |
| event.currentTarget.classList.add('border-indigo-500', 'bg-indigo-50'); |
| |
| |
| document.getElementById('preview-card-type').textContent = cardTypes[type].name; |
| document.getElementById('preview-card-logo').innerHTML = `<img src="${cardTypes[type].logo}" alt="${cardTypes[type].name}" class="h-full">`; |
| |
| |
| document.getElementById('cvv-length').value = cardTypes[type].cvvLength; |
| document.getElementById('preview-cvv').textContent = '•'.repeat(cardTypes[type].cvvLength); |
| } |
| |
| |
| function formatBin(input) { |
| let value = input.value.replace(/\D/g, ''); |
| input.value = value; |
| |
| if (value.length === 6) { |
| |
| document.getElementById('bin-status').innerHTML = ` |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500" viewBox="0 0 20 20" fill="currentColor"> |
| <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" /> |
| </svg> |
| `; |
| |
| |
| updatePreviewWithBin(value); |
| |
| |
| fetchBinInfo(value); |
| } else { |
| |
| document.getElementById('bin-status').innerHTML = ` |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> |
| <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" /> |
| </svg> |
| `; |
| |
| |
| document.getElementById('bin-info').classList.add('hidden'); |
| } |
| } |
| |
| |
| function updatePreviewWithBin(bin) { |
| const previewNumber = document.getElementById('preview-card-number'); |
| const cardLength = cardTypes[currentCardType].lengths[0]; |
| |
| |
| let formatted = bin + '••••••••'.substring(0, cardLength - bin.length - 4); |
| if (formatted.length > 4) { |
| formatted = formatted.substring(0, 4) + ' ' + formatted.substring(4); |
| } |
| if (formatted.length > 9) { |
| formatted = formatted.substring(0, 9) + ' ' + formatted.substring(9); |
| } |
| if (formatted.length > 14) { |
| formatted = formatted.substring(0, 14) + ' ' + formatted.substring(14); |
| } |
| |
| previewNumber.textContent = formatted; |
| } |
| |
| |
| function fetchBinInfo(bin) { |
| |
| setTimeout(() => { |
| document.getElementById('bin-brand').textContent = cardTypes[currentCardType].name; |
| document.getElementById('bin-type').textContent = 'Credit'; |
| document.getElementById('bin-bank').textContent = 'Example Bank'; |
| document.getElementById('bin-country').textContent = 'United States'; |
| document.getElementById('bin-info').classList.remove('hidden'); |
| }, 500); |
| } |
| |
| |
| function generateCards() { |
| const bin = document.getElementById('bin').value; |
| const rangeStart = document.getElementById('range-start').value; |
| const rangeEnd = document.getElementById('range-end').value; |
| const batchSize = parseInt(document.getElementById('batch-size').value); |
| const cvvLength = parseInt(document.getElementById('cvv-length').value); |
| |
| |
| const expiryDate = '12/25'; |
| document.getElementById('preview-expiry').textContent = expiryDate; |
| |
| |
| const generateBtn = document.getElementById('generate-btn'); |
| const generateSpinner = document.getElementById('generate-spinner'); |
| generateBtn.disabled = true; |
| generateSpinner.classList.remove('hidden'); |
| |
| |
| setTimeout(() => { |
| generatedCards = []; |
| const cardLength = cardTypes[currentCardType].lengths[0]; |
| |
| for (let i = 0; i < batchSize; i++) { |
| let cardNumber; |
| |
| if (bin.length === 6) { |
| |
| const remainingLength = cardLength - bin.length - 1; |
| let randomPart = ''; |
| for (let j = 0; j < remainingLength; j++) { |
| randomPart += Math.floor(Math.random() * 10); |
| } |
| cardNumber = bin + randomPart; |
| |
| |
| let sum = 0; |
| let isSecond = false; |
| for (let k = cardNumber.length - 1; k >= 0; k--) { |
| let digit = parseInt(cardNumber.charAt(k)); |
| if (isSecond) { |
| digit *= 2; |
| if (digit > 9) { |
| digit -= 9; |
| } |
| } |
| sum += digit; |
| isSecond = !isSecond; |
| } |
| const checkDigit = (10 - (sum % 10)) % 10; |
| cardNumber += checkDigit; |
| } else { |
| |
| cardNumber = generateRandomCardNumber(cardLength); |
| } |
| |
| |
| let cvv = ''; |
| for (let j = 0; j < cvvLength; j++) { |
| cvv += Math.floor(Math.random() * 10); |
| } |
| |
| generatedCards.push({ |
| number: cardNumber, |
| expiry: expiryDate, |
| cvv: cvv, |
| type: currentCardType |
| }); |
| } |
| |
| |
| displayGeneratedCards(); |
| |
| |
| generateBtn.disabled = false; |
| generateSpinner.classList.add('hidden'); |
| }, 1000); |
| } |
| |
| |
| function generateRandomCardNumber(length) { |
| let cardNo = ''; |
| for (let i = 0; i < length - 1; i++) { |
| cardNo += Math.floor(Math.random() * 10); |
| } |
| |
| |
| let sum = 0; |
| let isSecond = false; |
| for (let i = cardNo.length - 1; i >= 0; i--) { |
| let digit = parseInt(cardNo.charAt(i)); |
| if (isSecond) { |
| digit *= 2; |
| if (digit > 9) { |
| digit -= 9; |
| } |
| } |
| sum += digit; |
| isSecond = !isSecond; |
| } |
| const checkDigit = (10 - (sum % 10)) % 10; |
| |
| return cardNo + checkDigit; |
| } |
| |
| |
| function displayGeneratedCards() { |
| const container = document.getElementById('cards-container'); |
| container.innerHTML = ''; |
| |
| generatedCards.forEach((card, index) => { |
| const formattedNumber = formatCardNumber(card.number); |
| |
| const cardElement = document.createElement('div'); |
| cardElement.className = 'bg-white rounded-lg shadow-sm p-4 border border-gray-200 fade-in'; |
| cardElement.innerHTML = ` |
| <div class="flex justify-between items-start mb-3"> |
| <div> |
| <p class="text-xs text-gray-500">Card #${index + 1}</p> |
| <p class="font-medium">${cardTypes[card.type].name}</p> |
| </div> |
| <img src="${cardTypes[card.type].logo}" alt="${cardTypes[card.type].name}" class="h-6"> |
| </div> |
| <div class="mb-4"> |
| <p class="text-sm text-gray-500 mb-1">Card Number</p> |
| <div class="flex items-center justify-between"> |
| <p class="font-mono text-lg tracking-wider">${formattedNumber}</p> |
| <button onclick="copyToClipboard('${card.number}', 'Card number copied!')" class="text-gray-400 hover:text-gray-600"> |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> |
| <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z" /> |
| <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z" /> |
| </svg> |
| </button> |
| </div> |
| </div> |
| <div class="grid grid-cols-2 gap-4"> |
| <div> |
| <p class="text-sm text-gray-500 mb-1">Expiry</p> |
| <p class="font-medium">${card.expiry}</p> |
| </div> |
| <div> |
| <p class="text-sm text-gray-500 mb-1">CVV</p> |
| <div class="flex items-center justify-between"> |
| <p class="font-medium">${card.cvv}</p> |
| <button onclick="copyToClipboard('${card.cvv}', 'CVV copied!')" class="text-gray-400 hover:text-gray-600"> |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> |
| <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z" /> |
| <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z" /> |
| </svg> |
| </button> |
| </div> |
| </div> |
| </div> |
| <div class="mt-4 pt-4 border-t border-gray-100"> |
| <button onclick="generateQRCode(${index})" class="w-full py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200 flex items-center justify-center"> |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v4m6 2h4m-10 4H8m6 4v-4m6-2h4M4 14h4m6-6h4M4 8h4m-4 4h16" /> |
| </svg> |
| Generate QR Code |
| </button> |
| </div> |
| <div id="qr-container-${index}" class="mt-3 hidden flex justify-center"></div> |
| `; |
| |
| container.appendChild(cardElement); |
| }); |
| |
| |
| document.getElementById('generated-cards').classList.remove('hidden'); |
| } |
| |
| |
| function formatCardNumber(number) { |
| if (number.length === 15) { |
| return number.replace(/(\d{4})(\d{6})(\d{5})/, '$1 $2 $3'); |
| } else { |
| return number.replace(/(\d{4})(?=\d)/g, '$1 '); |
| } |
| } |
| |
| |
| function copyToClipboard(text, message) { |
| navigator.clipboard.writeText(text).then(() => { |
| showToast(message); |
| }); |
| } |
| |
| |
| function copyAllCards() { |
| let allCardsText = generatedCards.map(card => { |
| return `${formatCardNumber(card.number)}\t${card.expiry}\t${card.cvv}`; |
| }).join('\n'); |
| |
| navigator.clipboard.writeText(allCardsText).then(() => { |
| showToast('All cards copied to clipboard!'); |
| }); |
| } |
| |
| |
| function downloadCards() { |
| let csvContent = "data:text/csv;charset=utf-8,"; |
| csvContent += "Card Number,Expiry Date,CVV,Type\n"; |
| |
| generatedCards.forEach(card => { |
| csvContent += `${formatCardNumber(card.number)},${card.expiry},${card.cvv},${cardTypes[card.type].name}\n`; |
| }); |
| |
| const encodedUri = encodeURI(csvContent); |
| const link = document.createElement("a"); |
| link.setAttribute("href", encodedUri); |
| link.setAttribute("download", "generated_cards.csv"); |
| document.body.appendChild(link); |
| link.click(); |
| document.body.removeChild(link); |
| |
| showToast('Cards downloaded as CSV!'); |
| } |
| |
| |
| function generateQRCode(index) { |
| const card = generatedCards[index]; |
| const qrContainer = document.getElementById(`qr-container-${index}`); |
| |
| if (qrContainer.classList.contains('hidden')) { |
| qrContainer.innerHTML = ''; |
| qrContainer.classList.remove('hidden'); |
| |
| QRCode.toCanvas(qrContainer, `${card.number}|${card.expiry}|${card.cvv}`, { |
| width: 150, |
| margin: 1, |
| color: { |
| dark: '#000000', |
| light: '#ffffff' |
| } |
| }, function (error) { |
| if (error) console.error(error); |
| }); |
| } else { |
| qrContainer.classList.add('hidden'); |
| } |
| } |
| |
| |
| function showToast(message) { |
| const toast = document.getElementById('toast'); |
| const toastMessage = document.getElementById('toast-message'); |
| |
| toastMessage.textContent = message; |
| toast.classList.remove('hidden'); |
| |
| setTimeout(() => { |
| toast.classList.add('hidden'); |
| }, 3000); |
| } |
| |
| |
| document.addEventListener('DOMContentLoaded', () => { |
| |
| setCardType('visa'); |
| |
| |
| const now = new Date(); |
| const nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1); |
| const formattedDate = `${String(nextMonth.getMonth() + 1).padStart(2, '0')}/${nextMonth.getFullYear().toString().slice(-2)}`; |
| document.getElementById('expiry-date').value = formattedDate; |
| document.getElementById('preview-expiry').textContent = formattedDate; |
| }); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=offerpk3/bigwhale5" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |
|
|