171 lines
7.2 KiB
HTML
171 lines
7.2 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Subscribe to Clavitor</title>
|
|
<script src="https://cdn.paddle.com/paddle/paddle.js"></script>
|
|
<style>
|
|
body { font-family: system-ui; max-width: 600px; margin: 50px auto; padding: 20px; }
|
|
.plan { border: 2px solid #ddd; padding: 20px; margin: 15px 0; border-radius: 8px; cursor: pointer; }
|
|
.plan:hover { border-color: #0066cc; }
|
|
.plan.selected { border-color: #0066cc; background: #f0f7ff; }
|
|
.plan h3 { margin: 0 0 10px 0; }
|
|
.price { font-size: 24px; font-weight: bold; color: #0066cc; }
|
|
button { width: 100%; padding: 15px; font-size: 18px; background: #0066cc; color: white; border: none; border-radius: 8px; cursor: pointer; }
|
|
button:disabled { background: #ccc; }
|
|
#error { color: red; margin: 15px 0; }
|
|
#success { color: green; margin: 15px 0; }
|
|
input { width: 100%; padding: 12px; font-size: 16px; margin: 10px 0; box-sizing: border-box; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Choose Your Plan</h1>
|
|
|
|
<div id="plans">
|
|
<div class="plan" data-price-id="pri_01knejm7ft2ska5r4qff2gm9r4" onclick="selectPlan(this)">
|
|
<h3>Personal</h3>
|
|
<div class="price">$12/year</div>
|
|
<p>1 vault, 5 agents, 2 devices</p>
|
|
</div>
|
|
|
|
<div class="plan" data-price-id="pri_01knejm7xs9kqt0vn61dx6q808" onclick="selectPlan(this)">
|
|
<h3>Family</h3>
|
|
<div class="price">$29/year</div>
|
|
<p>1 vault, 15 agents, 6 devices</p>
|
|
</div>
|
|
|
|
<div class="plan" data-price-id="pri_01knejm8djq4p63rmsxze7by58" onclick="selectPlan(this)">
|
|
<h3>Pro</h3>
|
|
<div class="price">$49/year</div>
|
|
<p>1 vault, 50 agents, unlimited devices</p>
|
|
</div>
|
|
|
|
<div class="plan" data-price-id="pri_01knejm8twprj5ca4zem1g4g56" onclick="selectPlan(this)">
|
|
<h3>Team 10</h3>
|
|
<div class="price">$249/employee/year</div>
|
|
<p>Up to 10 employees, company vault included</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="checkout-form" style="display:none;">
|
|
<h2>Complete Your Subscription</h2>
|
|
<input type="email" id="email" placeholder="Your email address" required>
|
|
<input type="text" id="vault-l0" placeholder="Vault ID (if you have one)" style="display:none;">
|
|
<div id="error"></div>
|
|
<div id="success"></div>
|
|
<button id="checkout-btn" onclick="openCheckout()">Subscribe Now</button>
|
|
</div>
|
|
|
|
<script>
|
|
// SANDBOX MODE - for local development
|
|
// Get your sandbox client token from: https://sandbox-vendors.paddle.com/authentication
|
|
// Create one at: Developer Tools > Authentication
|
|
const PADDLE_CLIENT_TOKEN = 'YOUR_SANDBOX_CLIENT_TOKEN_HERE';
|
|
|
|
let selectedPlan = null;
|
|
|
|
// Initialize Paddle.js in SANDBOX mode
|
|
if (PADDLE_CLIENT_TOKEN && PADDLE_CLIENT_TOKEN !== 'YOUR_SANDBOX_CLIENT_TOKEN_HERE') {
|
|
Paddle.Setup({
|
|
token: PADDLE_CLIENT_TOKEN,
|
|
environment: 'sandbox' // Use 'production' for live
|
|
});
|
|
console.log('Paddle.js initialized in SANDBOX mode');
|
|
} else {
|
|
console.error('Please set your Paddle SANDBOX client token');
|
|
document.getElementById('error').textContent =
|
|
'Developer: Set PADDLE_CLIENT_TOKEN in checkout.html (get from sandbox-vendors.paddle.com)';
|
|
}
|
|
|
|
function selectPlan(element) {
|
|
// Remove selected from all
|
|
document.querySelectorAll('.plan').forEach(p => p.classList.remove('selected'));
|
|
// Add to clicked
|
|
element.classList.add('selected');
|
|
selectedPlan = element.dataset.priceId;
|
|
|
|
// Show checkout form
|
|
document.getElementById('checkout-form').style.display = 'block';
|
|
document.getElementById('error').textContent = '';
|
|
}
|
|
|
|
async function openCheckout() {
|
|
const email = document.getElementById('email').value;
|
|
const errorDiv = document.getElementById('error');
|
|
const successDiv = document.getElementById('success');
|
|
const btn = document.getElementById('checkout-btn');
|
|
|
|
if (!email) {
|
|
errorDiv.textContent = 'Please enter your email';
|
|
return;
|
|
}
|
|
|
|
if (!selectedPlan) {
|
|
errorDiv.textContent = 'Please select a plan';
|
|
return;
|
|
}
|
|
|
|
btn.disabled = true;
|
|
btn.textContent = 'Opening checkout...';
|
|
|
|
try {
|
|
// Call our backend to create the checkout
|
|
const response = await fetch('/api/checkout', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
price_id: selectedPlan,
|
|
email: email,
|
|
vault_l0: document.getElementById('vault-l0').value || null
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (!result.success) {
|
|
errorDiv.textContent = result.error || 'Failed to create checkout';
|
|
btn.disabled = false;
|
|
btn.textContent = 'Subscribe Now';
|
|
return;
|
|
}
|
|
|
|
// Option 1: Redirect to Paddle hosted checkout
|
|
// window.location.href = result.checkout_url;
|
|
|
|
// Option 2: Open Paddle.js inline checkout (better UX)
|
|
if (typeof Paddle !== 'undefined' && Paddle.Checkout) {
|
|
Paddle.Checkout.open({
|
|
transactionId: result.transaction_id,
|
|
successCallback: function(data) {
|
|
successDiv.textContent = 'Payment successful! Redirecting to your vault...';
|
|
// Redirect to vault
|
|
setTimeout(() => {
|
|
window.location.href = '/app/?subscription=active';
|
|
}, 2000);
|
|
},
|
|
closeCallback: function() {
|
|
btn.disabled = false;
|
|
btn.textContent = 'Subscribe Now';
|
|
}
|
|
});
|
|
} else {
|
|
// Fallback: redirect to hosted checkout
|
|
window.location.href = result.checkout_url;
|
|
}
|
|
|
|
} catch (err) {
|
|
errorDiv.textContent = 'Error: ' + err.message;
|
|
btn.disabled = false;
|
|
btn.textContent = 'Subscribe Now';
|
|
}
|
|
}
|
|
|
|
// Check for success parameter (returning from Paddle)
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
if (urlParams.get('subscription') === 'active') {
|
|
document.getElementById('success').textContent =
|
|
'Your subscription is active! You can now use your vault.';
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|