Behavior for the payment page, pay.html.
The page takes a payment in two steps, both authored in the page:
#pay-form— what the visitor is paying (an invoice by number, a fixed-price service, or another agreed amount), their name and email, and a Cloudflare Turnstile check that appears on their first edit. On submit it POSTs to/.netlify/functions/pay, which looks the amount up in Stripe and answers with a client secret (seenetlify/functions/pay.mjs).#pay-step-payment— Stripe's Payment Element, mounted with that secret and styled from the site's own tokens and fonts, so card, Apple Pay and Google Pay sit inside the page's design. Card details go from the element to Stripe; this script never sees them.
The result ([data-pay-result]) and every error ([data-pay-error]) are authored
in the page; this module only reveals the right one (The Three Layers Rule). The
two things it writes are data, not copy: the amount and what it's for, returned by
the function, and a decline reason from Stripe, each into an authored slot
([data-pay-slot]).
The button in an invoice email opens pay.html?invoice=CHA-1001. When the value looks
like an invoice number it is put in the invoice field; the visitor still gives their
name and email, and the function still checks the number against that email. The
email address is never carried in the URL.
The invoice field carries its CHA- prefix as authored text beside the box, so the
visitor types only the digits; wholeInvoiceNumber() puts the prefix back before the
request, and takes a whole number pasted in just the same — including an older
invoice's own prefix (MGK2PT28-0001), which stands the CHA- aside.
Stripe.js is loaded only when the payment step is reached, from
https://js.stripe.com/endive/stripe.js (the release matching the function's
Stripe-Version). A payment method that redirects comes back to this page with
payment_intent_client_secret in the URL, and the result is read from that.
Members
(inner, constant) ENDPOINT
The function that prices the payment and returns a client secret.
(inner, constant) FONT_YSABEAU
The site's fonts, handed to the Payment Element by URL (it renders in Stripe's frame).
(inner, constant) INVOICE_PREFIX
The prefix every invoice we issue carries (Stripe numbers the account CHA-1001 and up).
(inner, constant) INVOICE_RE
A whole invoice number: Stripe's PREFIX-0001, the same shape netlify/functions/pay.mjs accepts.
(inner, constant) STRIPE_SRC
Stripe.js, version-pinned to the API release the function uses.
(inner, constant) TOKEN_WAIT_MS
How long a submit waits for a Turnstile token before going ahead without one.
(inner, constant) TURNSTILE_SRC
Cloudflare's Turnstile script, rendered explicitly into our placeholder.
(inner, constant) form
The form, or null on any other page. @type {HTMLFormElement|null}
Methods
(inner) appearance() → {Object}
The Payment Element's appearance, built from the site's tokens: the same inks, surface, line, focus ring and 8px field corners as the page's own form.
Returns:
A Stripe Elements appearance object.
- Type
- Object
(inner) fonts() → {Array.<Object>}
The fonts the Payment Element may use, as absolute URLs (it renders on Stripe's origin; netlify.toml sends the CORS header that allows this).
Returns:
Stripe Elements font sources.
- Type
- Array.<Object>
(inner) initPay(formEl) → {void}
Sets up the payment page.
Parameters:
| Name | Type | Description |
|---|---|---|
formEl |
HTMLFormElement | The |
Returns:
- Type
- void
(inner) loadScript(src) → {Promise.<void>}
Loads a classic script once and resolves when it has run.
Parameters:
| Name | Type | Description |
|---|---|---|
src |
string | The script URL. |
Returns:
Resolves on load, rejects on error.
- Type
- Promise.<void>
(inner) money(cents, currency) → {string}
Formats an amount in the smallest currency unit, for the summary slot.
Parameters:
| Name | Type | Description |
|---|---|---|
cents |
number | The amount, for example 22500. |
currency |
string | The ISO currency, for example |
Returns:
For example $225.00.
- Type
- string
(inner) token(name) → {string}
Reads a CSS custom property from <html>, so the Payment Element follows the
theme the page is showing.
Parameters:
| Name | Type | Description |
|---|---|---|
name |
string | The property, for example |
Returns:
Its computed value, trimmed.
- Type
- string
(inner) wholeInvoiceNumber(raw) → {string}
Turns what's in the invoice field into a whole invoice number.
The field shows CHA- beside it and asks for the digits alone, but a visitor who
pastes the number from their email gets the same answer, with or without the dash,
and an older invoice's own prefix is kept rather than replaced.
Parameters:
| Name | Type | Description |
|---|---|---|
raw |
string | The field's value as typed or pasted. |
Returns:
The whole number in upper case, or the value unchanged when it isn't a number at all (the caller's test then fails it).
- Type
- string