Web SDK
PerfectPay hosts the checkout bundle on sdk.perfectpay.ai. Use the Web SDK when you want PerfectPay to handle payment fields, wallets, redirects, and confirmation in the browser.
Integration Flow
Loading diagram...
Before You Embed
- Create a secret key and copy your publishable key from Developers -> API Keys
- Copy your SDK loader URL from Developers -> Settings
- Create the payment on your server and return
client_secretpluspayment_idto the browser
Common Loader Methods
The loader exposes these methods:
widgets(...)confirmPayment(...)retrievePaymentIntent(...)initPaymentSession(...)paymentMethodsManagementElements(...)
1. Load the Hosted Bundle
Use the exact loader URL shown in Developers -> Settings. Hosted SDK URLs are served from sdk.perfectpay.ai.
HTML
<script src="YOUR_SDK_URL"></script>
A typical hosted loader URL looks like:
Text
https://sdk.perfectpay.ai/web/<release>/v1/PerfectLoader.js
2. Initialize the Loader
Use your publishable key and the API base URL for the environment you are targeting.
HTML
<script>
const perfect = window.Perfect(
{
publishableKey: "YOUR_PUBLISHABLE_KEY",
},
{
customBackendUrl: "https://sandbox.perfectpay.ai"
}
);
</script>
Use https://api.perfectpay.ai for production traffic when your account is live there.
3. Create the Widgets Object
Pass the clientSecret from the payment creation response.
HTML
<script>
const widgets = perfect.widgets({
clientSecret: "pay_mbabizu24mvu3mela5njyhpit4_secret_abc123",
appearance: {
labels: "floating"
}
});
</script>
4. Mount the Payment Element
HTML
<div id="payment-element"></div>
<button id="pay-button" type="button">Pay now</button>
<div id="payment-message"></div>
<script>
const paymentElement = widgets.create("payment", {
wallets: {
walletReturnUrl: window.location.origin,
applePay: "auto",
googlePay: "auto",
style: {
theme: "dark",
type: "default",
height: 55
}
}
});
paymentElement.mount("#payment-element");
</script>
5. Confirm the Payment
HTML
<script>
const button = document.getElementById("pay-button");
const message = document.getElementById("payment-message");
button.addEventListener("click", async () => {
const { error, status } = await perfect.confirmPayment({
elements: widgets,
confirmParams: {
return_url: window.location.origin + "/checkout/complete"
}
});
if (error) {
message.textContent = error.message;
return;
}
message.textContent = status || "Payment submitted";
});
</script>
6. Retrieve the Final State
HTML
<script>
const result = await perfect.retrievePaymentIntent("YOUR_CLIENT_SECRET");
console.log(result.paymentIntent?.status);
</script>
Recommended Integration Split
- Create customers and payments on your server with the secret key
- Send only the
client_secret,publishable_key, and payment details to the browser - Let the SDK handle collection, redirects, wallets, and confirmation