diff --git a/src/gui/src/UI/UIWindowCardVerificationRequired.js b/src/gui/src/UI/UIWindowCardVerificationRequired.js index 4a57bec5e..6823e3b49 100644 --- a/src/gui/src/UI/UIWindowCardVerificationRequired.js +++ b/src/gui/src/UI/UIWindowCardVerificationRequired.js @@ -29,6 +29,18 @@ import UIWindow from './UIWindow.js'; // Stripe.js is loaded lazily from the CDN only when this dialog actually opens. // Used as a hard gate for low-reputation signups (after phone verification), so // by default it has no close button. +// +// `options.phone_fallback` opens the same dialog as the SMS escape hatch: a +// user the phone gate keeps blocking verifies a card instead, which clears the +// phone gate server-side (see /card-verification/confirm). Two things change in +// that mode: +// - The dialog can be dismissed back to phone verification, so choosing the +// card path is never a one-way door. +// - `card_verified` alone is NOT treated as success. The phone gate only +// lifts when the server also reports `phone_verified`; anything else (the +// kill switch short-circuit, in particular) would close a dialog that +// reports success while the account is still phone-gated and every gated +// route keeps 403ing. `options.on_unavailable` is called instead. const STRIPE_JS_URL = 'https://js.stripe.com/v3/'; @@ -65,6 +77,7 @@ function UIWindowCardVerificationRequired(options) { 'circle anim'; const verify_btn_txt = 'Verify Card'; const retry_btn_txt = 'Try Again'; + const back_to_phone_txt = 'Verify by phone instead'; let h = ''; if (options.show_close_button !== false) { @@ -83,8 +96,9 @@ function UIWindowCardVerificationRequired(options) { // -- Card entry: Stripe Payment Element (hidden until setup succeeds) -- h += '