Hosted Form
Use getPaymentElement() with the hostedForm option to render a pre-built, PCI-DSS compliant payment form directly inside your checkout page. The SDK renders a complete, styled form β you only configure labels, placeholders, and a theme. Choose this approach when you want a quick integration with moderate customization and support for multiple payment methods. For full control over each individual field's position and HTML structure, use Hosted Fields instead.
This recipe assumes you have a checkout instance already initialized. See the Getting Started guide if you haven't done this yet.
1. Add a container element to your HTMLβ
Add a single container where the SDK will mount the complete form:
<div id="purse-hosted-form"></div>
<button id="pay-button">Pay Now</button>
2. Render the Hosted Formβ
Call checkout.getPaymentElement() with the target partner / method and the hostedForm option, then mount it with appendTo():
checkout.getPaymentElement({
partner: "ingenico",
method: "creditcard",
hostedForm: {
panInputLabel: "Card number",
panPlaceholder: "1234 5678 9012 3456",
cvvInputLabel: "Security code",
cvvPlaceholder: "123",
expirationInputLabel: "Expiration date",
expirationPlaceholder:"MM/YY",
holderInputLabel: "Cardholder name",
holderPlaceholder: "John Doe"
}
}).appendTo("purse-hosted-form");
π‘
appendTo("purse-hosted-form")mounts the complete form into the element with that ID.
Throws PurseHeadlessCheckoutError PAYMENT_METHOD_NOT_FOUND if no primary method matches the partner/method pair.
3. Customize appearanceβ
Labels and placeholdersβ
All field labels and placeholder texts are configurable via the hostedForm object (see step 2 above).
Themeβ
Pass a theme object alongside hostedForm to control the visual styling. The Hosted Form supports a richer set of theme scopes than Hosted Fields:
checkout.getPaymentElement({
partner: "ingenico",
method: "creditcard",
hostedForm: { /* ...labels and placeholders... */ },
theme: {
global: {
color: '#1f2933',
fontFamily: 'Arial, sans-serif',
fontSize: '16px',
gap: '8px'
},
input: {
padding: '12px',
borderRadius: '4px',
border: '1px solid #cbd5e0',
backgroundColor: '#ffffff',
':focus': { borderColor: '#4299e1', boxShadow: '0 0 0 3px rgba(66,153,225,0.1)' },
':invalid': { borderColor: '#dc2626' }
},
label: {
fontWeight: '500',
margin: '0 0 4px 0',
color: '#374151'
},
helperText: {
fontSize: '14px',
color: '#6b7280',
margin: '4px 0 0 0'
}
}
}).appendTo("purse-hosted-form");
Supported theme scopes: global, input, label, helperText, tooltip. Each scope supports standard CSS properties and pseudo-selectors (:focus, :hover, :invalidβ¦).
See Theme references for all available keys.
Custom fontsβ
For compliance reasons, please contact the Purse team before using custom fonts β you must provide the font file in advance.
theme: {
global: {
fontSrc: 'custom-font-file', // only needed for non-pre-approved fonts
fontFamily: 'MyFont, sans-serif',
fontSize: '16px'
}
}
4. Handle payment submissionβ
Call checkout.submitPayment() on button click:
document.getElementById("pay-button").addEventListener("click", async (e) => {
e.preventDefault();
const payButton = document.getElementById("pay-button");
payButton.disabled = true;
payButton.textContent = "Processing...";
try {
await checkout.submitPayment();
// Redirect or show success message
} catch (error) {
console.error("Payment failed:", error.message);
alert(error.message || "Payment failed");
} finally {
payButton.disabled = false;
payButton.textContent = "Pay Now";
}
});
Error handlingβ
- Expired session β Create a new client session
- Invalid configuration β Check that the
hostedFormoptions are correctly set - Payment method not supported β The method does not support the Hosted Form rendering mode
- Technical error β The payment method could not be initialized
Complete exampleβ
See alsoβ
- Hosted Fields β Render isolated card input iframes with
getHostedFields()for full layout control - Customization β Theme the default payment element with
getPaymentElement() - Event Handling β React to checkout events during the payment flow