A first-party checkout experience

Stripe Embedded Checkout that keeps your product in view.

Open a responsive payment modal on your own product domain, mount Stripe directly inside it, and let Yito Pay manage the server-side order, Session, status, and recovery flow.

The right kind of embedding

Mount Stripe Embedded Checkout without a second cross-domain frame.

Stripe Embedded Checkout is designed to live in a container on the product page. Yito Pay’s browser widget creates an accessible modal, loads the current Stripe.js release train, and calls createEmbeddedCheckoutPage with the client secret returned by the product backend.

The widget does not place a complete Yito Pay page inside another iframe. That avoids a double-frame design that can interfere with wallets, browser permissions, authentication redirects, focus management, and mobile viewport behavior. The only protected payment frame is the one Stripe creates.

Stripe Link can appear inside that same protected iframe when it is enabled for the selected Stripe account and the customer is eligible. Yito Pay does not load a separate Link SDK, and Link is not required for ordinary card checkout.

The product controls when the modal opens and what happens after server confirmation. Yito Pay controls which order the client secret belongs to and whether its price, app, user, merchant route, and return URL passed server checks.

01

Product-owned trigger

Your authenticated interface asks its own backend to start checkout. No app secret reaches the browser.

02

Provider-owned fields

Card numbers, CVC values, wallet credentials, and authentication screens remain under Stripe or the explicitly selected provider’s control.

03

Server-owned result

The modal polls your backend after completion while the webhook pipeline confirms and fulfills the order.

A small browser surface

Use one shared widget across products.

After a product backend creates a checkout, it returns the publishable key, client secret, order ID, and a same-origin status endpoint to its browser. The page then opens the Yito Pay widget. It never receives the Stripe secret key, the app API key, or a trusted amount.

The widget fills the available desktop modal while switching to a full-height sheet on small screens. Focus begins on the close control, the dialog has an accessible label, and customers can leave without changing order state.

  • Responsive desktop and mobile dialog layout.
  • Current Stripe.js dahlia release train.
  • Optional same-origin order status polling.
  • Explicit close, confirmed, and error callbacks.
  • No dependency on a product framework.
Browser
<script src="https://pay.yito.ai/sdk/v1/pay-widget.js"></script>

<script>
  const checkout = await fetch('/api/billing/start', {
    method: 'POST'
  }).then(response => response.json());

  YitoPay.open({
    publishableKey: checkout.publishable_key,
    clientSecret: checkout.client_secret,
    statusUrl: '/api/billing/orders/' + checkout.order_id,
    onConfirmed: () => location.assign('/billing/success')
  });
</script>

Redirects still have a place

Stay embedded for normal cards and respect required authentication.

The Checkout Session uses redirect_on_completion: if_required. A normal card payment can finish in the modal. A payment method that must visit a bank or authorization app can leave temporarily and return to the pre-registered product URL. That return URL is loaded from the app record; a browser cannot substitute a phishing destination.

Completion in the modal means Stripe finished the client flow. It does not mean the product should immediately issue credits or unlock a subscription. The widget changes to a confirmation state and polls the product backend. Access appears only when the authoritative webhook path marks the order paid or fulfilled.

This distinction protects customers during connectivity loss and protects the product from fabricated success pages. A user can close the tab, lose a mobile connection, or never reach the return screen without losing the server-side payment fact.

Hosted recovery

A top-level fallback at pay.yito.ai

If a product runs in an incompatible in-app browser, has a restrictive content security policy, or cannot mount the widget, it can offer a short-lived Yito Pay checkout URL as an explicit recovery action. The first-party page clears its signed fragment token, exchanges it for a host-only HttpOnly browser session, and only then loads Stripe to present the existing Session as a top-level document.

The token contains no amount, API key, or merchant secret. It expires with the Checkout Session and maps only to the existing local order. Products must not redirect to it during the normal flow.

Payment domain registration

Register the hostname that actually displays Checkout.

When the Stripe modal appears at app.example.com, that exact hostname must be enabled as a Stripe payment method domain for wallets and supported payment methods. A root domain does not silently cover every subdomain. Yito Pay registration records the exact HTTPS origin and keeps checkout disabled until ownership and Stripe status are verified.

The hosted recovery page displays Checkout at pay.yito.ai, so that hostname is registered separately. Approved product domains remain explicit rather than relying on permissive CORS or wildcard return URLs.

Optional PayPal route

Keep the product context while PayPal owns approval.

An approved PayPal checkout uses the same Yito Pay modal shell, then starts PayPal JS v6 with presentationMode: auto. PayPal normally tries its popup and can fall back to a provider-controlled modal; required authentication or mobile behavior can still redirect. Yito Pay cannot force PayPal’s authorization UI to remain inside its own DOM.

PayPal is not an automatic fallback for a failed Stripe checkout. It must be enabled globally and for the app, must use the Shinstar seller boundary, and must have matching catalog and webhook configuration. Browser approval still does not grant access; Yito Pay confirms the canonical PayPal resource or a verified webhook first.

Questions, answered

Frequently asked questions

Does Embedded Checkout guarantee that the browser never redirects?

No. Standard card flows can remain in the modal, but some banks, wallets, and local payment methods require an external authentication step. The Session returns only to the product URL registered for the app.

Should pay.yito.ai be embedded in an iframe on every product?

No. Products should mount Stripe Embedded Checkout directly in their own modal. The Yito Pay hosted page is a top-level fallback, not an outer iframe around Stripe.

Can the modal grant access in its onComplete callback?

No. Completion should show a confirming state and poll a server endpoint. Entitlements are granted only after Yito Pay confirms the provider resource or processes a verified provider webhook.

Can Stripe Link stay inside the product modal?

Yes. Eligible Link checkout is rendered by Stripe inside the same Embedded Checkout iframe. It needs the exact payment domain and account eligibility, but no separate Link SDK in the product.

Does PayPal always stay inside the same DOM modal?

No. The product remains the starting page and Yito Pay keeps its modal shell, but PayPal controls whether approval uses a popup, PayPal modal, or required redirect. PayPal is an explicitly enabled provider route, not a silent Stripe fallback.

Build on a reliable payment boundary

Give every SaaS product one secure way to charge.

Start with the integration guide, then register the app, domain, and server credentials before enabling checkout.