# Hosted Checkout and customer portal

A Checkout Session's and a portal session's URLs open the simulator's own pages, which subscribe a customer, change seats and cancel; other hosted URLs lead back to the simulator.

Hosted pages let a browser test finish the flows Stripe hosts: a Checkout Session's `url` and a customer portal session's `url` open the simulator's own pages, on the origin you called, instead of Stripe's. Make a subscription Checkout Session and open its page:

```bash
curl -s "$RYSTIC_URL/v1/prices" -u sk_test_123: -d unit_amount=1500 -d currency=usd -d 'recurring[interval]=month' -d 'product_data[name]=Hosting' | jq -c '{id}'
# -> {"id":"price_1"}
curl -s "$RYSTIC_URL/v1/checkout/sessions" -u sk_test_123: -d mode=subscription -d 'line_items[0][price]=price_1' -d 'line_items[0][quantity]=2' -d success_url=https://example.com/done -d cancel_url=https://example.com/cancel | jq -r .url
# -> .../c/pay/cs_test_a1Rystic0000000000000001#fidRystic1
curl -s -o /dev/null -w '%{http_code}\n' "$RYSTIC_URL/c/pay/cs_test_a1Rystic0000000000000001"
# -> 200
```

### Checkout

A Checkout Session's `url` is re-based from `checkout.stripe.com` onto the origin you called, and `/c/pay/{session}` renders the session's line items, total and prefilled email, with a link back to `cancel_url`. Subscribing on a `subscription`-mode session creates the customer (unless the session names one) and a subscription carrying the session's prices, quantities and `subscription_data[metadata]`, completes the session and redirects to `success_url` with `{CHECKOUT_SESSION_ID}` filled in. `customer.created`, `customer.subscription.created` and `checkout.session.completed` go out in that order. Any card number is accepted, and the session's amounts and `payment_status` read as its line items price them. Submitting a `payment` or `setup` session answers 501 and leaves it `open`. An expired session's page answers 410 and an unknown one's 404.

### Expiry

A Checkout Session expires at its `expires_at`, 24 hours after its create unless the create sets it: once the clock reaches it, an open session reads `expired` with a null `url`, and `checkout.session.expired` goes out, naming no request. A clock move stops at each open session's `expires_at` on its way, so the event's `created` is that `expires_at`; a session the running clock passes between requests expires at the next request, stamped then. `checkout.session.expired` is the platform's event even for a session made acting as a connected account.

The create takes an `expires_at` from 30 minutes to 24 hours after the clock, both ends included. It refuses any other integer with Stripe's 400, and a value that is no integer (`abc`, `1e9`, `1800.0`, an empty or space-prefixed value) with Stripe's 400 `parameter_invalid_integer`, quoting the value as sent. A seeded session whose `expires_at` is missing, null, zero, negative or no timestamp reads and expires a day after its `created`.

### Customer portal

A portal session's `url` is re-based from `billing.stripe.com` onto the origin you called and opens the simulator's portal at `/p/session?secret=…`. It lists the customer's subscriptions with their seats and renewal date, and offers a seat change, a cancellation and a way to take a cancellation back. Canceling sets `cancel_at` to the period end and leaves `cancel_at_period_end` `false`, as Stripe's portal does. Each action is a subscription update that sends `customer.subscription.updated` to your endpoints; once the clock reaches `cancel_at`, the subscription reads `canceled` and `customer.subscription.deleted` goes out. The portal shows no payment method, billing details or invoice history, and an unknown secret answers 404.

### Other hosted URLs

A finalized invoice's `hosted_invoice_url` and `invoice_pdf`, a credit note's `pdf`, a charge's `receipt_url`, a payment link's `url` and a bank debit's `hosted_verification_url` are on the origin you called, never on `invoice.stripe.com`, `pay.stripe.com` or `buy.stripe.com`. The simulator serves no page at those paths: they answer 404.

---

Source: https://www.rystic.ai/docs/simulators/stripe/features/hosted-pages · Markdown: https://www.rystic.ai/docs/simulators/stripe/features/hosted-pages.md
