From 164fff8be21db7c9fc74312d43a4e8765e9ae671 Mon Sep 17 00:00:00 2001 From: userAdityaa Date: Fri, 8 May 2026 13:39:56 +0545 Subject: [PATCH] fix: stripe portal dead-end with callback return flow --- backend/src/api.rs | 10 ++++++++-- backend/src/billing.rs | 12 ++++++++++-- frontend/src/components/PaymentSetup.tsx | 2 +- frontend/src/lib/api.ts | 5 +++-- frontend/src/pages/Account.tsx | 2 +- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/backend/src/api.rs b/backend/src/api.rs index 677897e..36adf64 100644 --- a/backend/src/api.rs +++ b/backend/src/api.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use anyhow::{Result, anyhow}; use axum::{ Json, Router, - extract::{Path, State}, + extract::{Path, Query as QueryParams, State}, http::{HeaderMap, StatusCode}, response::{IntoResponse, Response}, routing::{get, post}, @@ -1101,10 +1101,16 @@ async fn get_invoice_bolt11( } } +#[derive(serde::Deserialize)] +struct StripeSessionParams { + return_url: Option, +} + async fn create_stripe_session( State(state): State, headers: HeaderMap, Path(pubkey): Path, + QueryParams(params): QueryParams, ) -> std::result::Result { let auth = state.api.extract_auth_pubkey(&headers)?; state.api.require_admin_or_tenant(&auth, &pubkey)?; @@ -1113,7 +1119,7 @@ async fn create_stripe_session( match state .api .billing - .stripe_create_portal_session(&tenant.stripe_customer_id) + .stripe_create_portal_session(&tenant.stripe_customer_id, params.return_url.as_deref()) .await { Ok(url) => Ok(ok(StatusCode::OK, serde_json::json!({ "url": url }))), diff --git a/backend/src/billing.rs b/backend/src/billing.rs index c263b7d..5a58a21 100644 --- a/backend/src/billing.rs +++ b/backend/src/billing.rs @@ -966,12 +966,20 @@ impl Billing { Ok(()) } - pub async fn stripe_create_portal_session(&self, customer_id: &str) -> Result { + pub async fn stripe_create_portal_session( + &self, + customer_id: &str, + return_url: Option<&str>, + ) -> Result { + let mut params = vec![("customer", customer_id.to_string())]; + if let Some(url) = return_url { + params.push(("return_url", url.to_string())); + } let resp = self .http .post(format!("{STRIPE_API}/billing_portal/sessions")) .bearer_auth(&self.stripe_secret_key) - .form(&[("customer", customer_id)]) + .form(¶ms) .send() .await?; diff --git a/frontend/src/components/PaymentSetup.tsx b/frontend/src/components/PaymentSetup.tsx index 81d3c50..9efb438 100644 --- a/frontend/src/components/PaymentSetup.tsx +++ b/frontend/src/components/PaymentSetup.tsx @@ -40,7 +40,7 @@ export default function PaymentSetup(props: PaymentSetupProps) { setRedirecting(true) setError("") try { - const { url } = await createPortalSession(account()!.pubkey) + const { url } = await createPortalSession(account()!.pubkey, window.location.href) window.location.href = url } catch (e) { setError(e instanceof Error ? e.message : "Failed to open billing portal") diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index f9280d7..7ff8765 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -253,8 +253,9 @@ export function reactivateRelay(id: string) { return callApi("POST", `/relays/${id}/reactivate`) } -export function createPortalSession(pubkey: string) { - return callApi("GET", `/tenants/${pubkey}/stripe/session`) +export function createPortalSession(pubkey: string, returnUrl?: string) { + const query = returnUrl ? `?return_url=${encodeURIComponent(returnUrl)}` : "" + return callApi("GET", `/tenants/${pubkey}/stripe/session${query}`) } export function getInvoiceBolt11(invoiceId: string) { diff --git a/frontend/src/pages/Account.tsx b/frontend/src/pages/Account.tsx index 9e9ac27..76610ef 100644 --- a/frontend/src/pages/Account.tsx +++ b/frontend/src/pages/Account.tsx @@ -49,7 +49,7 @@ export default function Account() { async function openPortal() { setPortalLoading(true) try { - const { url } = await createPortalSession(account()!.pubkey) + const { url } = await createPortalSession(account()!.pubkey, window.location.href) window.location.href = url } catch (e) { setError(e instanceof Error ? e.message : "Failed to open billing portal") -- 2.52.0