From 54d48ed679dfb6d8182f3681378bbba6ea59481d Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Mon, 11 May 2026 17:33:53 -0500 Subject: [PATCH 1/2] ci: trigger rebuild after registry cleanup -- 2.52.0 From 7be2b49300be250a564f3422fed8a5b960e08200 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Mon, 11 May 2026 19:45:39 -0500 Subject: [PATCH 2/2] Free plan: use $0 PaymentIntent instead of SetupIntent for age verification All plans now use the same payment intent flow. Free creates a $0 PI with payment_method_types[]=card and setup_future_usage=off_session. No charge, card saved. Removes setup_mode=true for free plan. Fix submit button label: show 'Verify age & get started' for free instead of 'Complete purchase'. Retire checkout-free.el. --- src/js/checkout-free.el | 20 +++----------------- src/js/checkout-stripe.el | 2 +- src/main.el | 24 +++++++++++------------- 3 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/js/checkout-free.el b/src/js/checkout-free.el index 9a475d1..e9ce6fd 100644 --- a/src/js/checkout-free.el +++ b/src/js/checkout-free.el @@ -1,20 +1,6 @@ -// checkout-free.el -- Free plan: show success panel after auth completes. -// Watches the auth-badge element; when it becomes visible, hides the auth -// section and shows the free-success panel. No card required for free tier. -// Compiled with: elc --target=js --bundle --minify --obfuscate +// checkout-free.el -- RETIRED. Free plan now uses the standard Stripe +// payment flow (checkout-stripe.el) with a $0 PaymentIntent for age +// verification. This file is no longer compiled or loaded. fn main() -> Void { - native_js("(function() { - var success = document.getElementById('free-success'); - var auth = document.getElementById('auth-section'); - if (!success) return; - var timer = setInterval(function() { - var badge = document.getElementById('auth-badge'); - if (badge && badge.offsetParent !== null) { - if (auth) auth.style.display = 'none'; - success.style.display = ''; - clearInterval(timer); - } - }, 150); -})()") } diff --git a/src/js/checkout-stripe.el b/src/js/checkout-stripe.el index cb1751a..99ec933 100644 --- a/src/js/checkout-stripe.el +++ b/src/js/checkout-stripe.el @@ -101,7 +101,7 @@ fn main() -> Void { if (submitLabel) { submitLabel.textContent = window._neuronMode === 'setup' ? 'Save my card - no charge today →' - : 'Complete purchase →'; + : PLAN === 'free' ? 'Verify age & get started →' : 'Complete purchase →'; } waitForStripe(function() { if (!stripe) stripe = Stripe(STRIPE_PK); diff --git a/src/main.el b/src/main.el index 3b2a4f1..254b1fd 100644 --- a/src/main.el +++ b/src/main.el @@ -697,23 +697,21 @@ fn handle_request_inner(method: String, path: String, headers: Map, body: String } } - // Free tier: creates a SetupIntent for age verification (18+ requirement). - // No charge — but the user must provide a valid payment method. + // Free tier: $0 PaymentIntent for age verification (18+ requirement). + // Card is verified and saved (setup_future_usage=off_session). No charge. if str_eq(plan, "free") { - let free_si_body: String = "automatic_payment_methods[enabled]=true" - + "&usage=off_session" + let free_pi_body: String = "amount=0" + + "¤cy=usd" + + "&payment_method_types[]=card" + + "&setup_future_usage=off_session" + "&metadata[plan]=free" + "&metadata[purpose]=age_verification" - let free_si_body = if !str_eq(pi_cus_id, "") { free_si_body + "&customer=" + pi_cus_id } else { free_si_body } - let free_si_resp: String = http_post_form_auth( - "https://api.stripe.com/v1/setup_intents", - free_si_body, + let free_pi_body = if !str_eq(pi_cus_id, "") { free_pi_body + "&customer=" + pi_cus_id } else { free_pi_body } + let free_pi_resp: String = http_post_form_auth( + "https://api.stripe.com/v1/payment_intents", + free_pi_body, auth_header) - if str_starts_with(free_si_resp, "{") { - let inner: String = str_slice(free_si_resp, 1, str_len(free_si_resp)) - return "{\"setup_mode\":true,\"plan\":\"free\"," + inner - } - return free_si_resp + return free_pi_resp } // Setup-mode path: save payment method, do not charge. Only valid -- 2.52.0