<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hosted Fields</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 500px; margin: 50px auto; padding: 20px; }
.field { margin-bottom: 16px; }
label { display: block; margin-bottom: 4px; font-weight: 500; }
.input-container { border: 1px solid #ccc; border-radius: 4px; padding: 10px; height: 40px; }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
button { width: 100%; padding: 12px; background: #0066cc; color: white; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; }
button:disabled { opacity: 0.6; cursor: not-allowed; }
.error { color: #dc2626; font-size: 14px; margin-top: 8px; display: none; }
</style>
</head>
<body>
<form id="payment-form">
<div class="field">
<label>Card Number</label>
<div class="row">
<div id="card-number" class="input-container"></div>
<div id="brand-selector"></div>
</div>
</div>
<div class="field">
<label>Cardholder Name</label>
<div id="cardholder-name" class="input-container"></div>
</div>
<div class="row">
<div class="field">
<label>Expiry Date</label>
<div id="expiry-date" class="input-container"></div>
</div>
<div class="field">
<label>CVV</label>
<div id="cvv" class="input-container"></div>
</div>
</div>
<button type="submit" id="submit-btn">Pay Now</button>
<div id="error" class="error"></div>
</form>
<script type="module">
import * as Purse from "https://cdn.purse-sandbox.com/headless-checkout/latest/purse.esm.js";
const checkout = await Purse.createHeadlessCheckout(clientSession.widget.data);
checkout.paymentMethods.subscribe((methods) => {
const creditCard = methods.find(m => m.method === "creditcard");
if (!creditCard) return;
const hostedFields = creditCard.getHostedFields({
fields: {
brandSelector: { target: "brand-selector" },
cardNumber: { target: "card-number", placeholder: "1234 5678 9012 3456" },
holderName: { target: "cardholder-name", placeholder: "John Doe" },
expDate: { target: "expiry-date", placeholder: "MM/YY" },
cvv: { target: "cvv", placeholder: "123" }
},
theme: {
input: {
fontSize: "16px",
color: "#111827",
':focus': { color: "#111827" },
':invalid': { color: "#dc2626" }
}
}
});
hostedFields.render();
});
document.getElementById("payment-form").addEventListener("submit", async (e) => {
e.preventDefault();
const submitBtn = document.getElementById("submit-btn");
const errorDiv = document.getElementById("error");
submitBtn.disabled = true;
submitBtn.textContent = "Processing...";
errorDiv.style.display = "none";
try {
await checkout.submitPayment();
} catch (error) {
errorDiv.textContent = error.message || "Payment failed";
errorDiv.style.display = "block";
} finally {
submitBtn.disabled = false;
submitBtn.textContent = "Pay Now";
}
});
</script>
</body>
</html>