Embedded Onboarding & Signing
When Check Eligibility returns user_status NotFound or Pending, render its signup_url inside an iframe in your marketplace, listen for the completion event, then close the iframe and resume checkout.
Embedding the iframe
Your domain must be whitelisted first
The onboarding page only loads inside origins FINA has whitelisted (a Content-Security-Policy frame-ancestors restriction). Before integrating, share the domains that will embed the iframe — sandbox and production — with the FINA team. An un-whitelisted origin gets a blank iframe blocked by the browser. The same whitelisted domain also has to host the down-payment redirect targets you send in prepaid_payment.success_redirection_url and failure_redirection_url.
Onboarding is buyer-level, not seller-level
The buyer onboards with FINA once, from your marketplace — the flow is not scoped to the seller they happen to be checking out with. A separate case is the seller not being onboarded (eligibility reason SELLER_NOT_ONBOARDED): that cannot be resolved through this iframe, and FINA can't be offered on the order until the seller is onboarded.
<div id="fina-iframe-container">
<iframe
id="fina-iframe"
src="<signup_url returned by Check Eligibility>"
width="100%"
height="600"
frameborder="0"
></iframe>
</div>Completion events (FINA → host)
Communication uses the browser-native window.postMessage API. FINA emits fina:signCompleted only after the signing provider confirms success and FINA's backend has persisted the result — you never see a premature event that could later be reverted.
| Event type | Meaning | Host action |
|---|---|---|
fina:signCompleted | Signing confirmed and persisted by FINA. This is the primary signal. | Close the iframe and proceed with checkout. |
fina:signRejected | Buyer explicitly rejected or cancelled the signing (optional). | Close the iframe or show a specific message. |
fina:signError | Unrecoverable error in the signing pipeline (optional). | Show an error notification; decide whether to keep the iframe open. |
type FinaSignMessage = {
type: 'fina:signCompleted' | 'fina:signRejected' | 'fina:signError';
payload: {
userHashId?: string;
signatureRequestId?: string;
timestamp?: string;
};
};Listening for completion
Validate event.origin against the FINA origin for your environment:
| Environment | FINA origin |
|---|---|
| Sandbox | https://apibe.silqfi.xyz |
| Production | Contact the FINA team for the production origin |
// In the host (parent) window
window.addEventListener('message', function (event) {
// 1. SECURITY: only accept messages from the expected FINA origin
const allowedOrigins = [
'https://apibe.silqfi.xyz', // sandbox — add your production origin here (contact the FINA team)
];
if (!allowedOrigins.includes(event.origin)) {
console.warn('Ignoring message from unknown origin:', event.origin);
return;
}
const data = event.data;
// 2. Handle successful completion
if (data?.type === 'fina:signCompleted') {
document.getElementById('fina-iframe-container').style.display = 'none';
// Resume the checkout flow here
}
// 3. Optional: rejection and errors
if (data?.type === 'fina:signRejected') {
// Buyer cancelled — close the iframe or show a specific state
}
if (data?.type === 'fina:signError') {
// Unrecoverable error — show a notification and decide next steps
}
});Language control
The iframe opens in Arabic by default. Any one of these forces a language:
- Pass
language_code: "en"(or"ar") in the Check Eligibility request — the returned signup_url has&lang=baked in. Recommended. - Append
&lang=ar|ento signup_url manually before setting iframe.src (overrides #1). - Send a runtime message after the iframe loads:
// Optional: switch the iframe language at runtime
document.getElementById('fina-iframe').contentWindow.postMessage(
{ type: 'CHANGE_LANGUAGE', language: 'ar' },
'https://apibe.silqfi.xyz' // your FINA origin; '*' also works — no sensitive data is sent
);
// FINA responds with a LANGUAGE_CHANGED eventSecurity considerations
- Embedding is restricted to whitelisted origins. The onboarding page's
frame-ancestorsCSP only permits origins registered with FINA — this is what stops a malicious site from framing the onboarding flow. If the iframe renders blank, an unregistered origin is the most likely cause; check the browser console for a CSP violation and contact the FINA team to whitelist the domain. - Origin validation is mandatory. Validate
event.originagainst an allowlist of FINA origins before acting on any message — otherwise any embedded page could spoof a "signing complete" event. - In production FINA sends postMessage to your configured host origin, never
'*'. In the other direction, using'*'as the target origin for yourCHANGE_LANGUAGEmessage is acceptable — it carries no sensitive data. - Messages are plain JSON with a well-known
typeandpayload— no executable code or sensitive data. - Cross-origin isolation applies: the host cannot reach into the FINA iframe's DOM; all coordination flows through postMessage.