Skip to content

Commit a199d86

Browse files
Sai Sridhar Tarraclaude
authored andcommitted
Fix: add callback_url to Razorpay subscription + poll for plan update after payment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5048624 commit a199d86

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

backend/services/razorpay_service.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ async def create_subscription(user_id: str, plan_id: str, email: str = "") -> st
5656
"Create plans at razorpay.com → Subscriptions → Plans."
5757
)
5858

59+
frontend_url = (settings.FRONTEND_URL or "http://localhost:3000").rstrip("/")
5960
client = _client()
6061
try:
6162
subscription = client.subscription.create({
@@ -65,6 +66,8 @@ async def create_subscription(user_id: str, plan_id: str, email: str = "") -> st
6566
"customer_notify": 1,
6667
"notes": {"user_id": user_id},
6768
"notify_info": {"notify_email": email} if email else {},
69+
"callback_url": f"{frontend_url}/billing?success=true",
70+
"callback_method": "get",
6871
})
6972

7073
short_url = subscription.get("short_url")

frontend/pages/billing/index.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,22 @@ export default function BillingPage() {
101101
}
102102
}, [session, sessionLoading, router]);
103103

104-
// Handle Stripe return
104+
// Handle Razorpay return
105+
const { mutate: refreshBilling } = useBillingStatus();
105106
useEffect(() => {
106-
const { success, canceled } = router.query;
107+
const { success } = router.query;
107108
if (success === 'true') {
108-
toast.success('Subscription activated! Welcome to your new plan.');
109-
router.replace('/billing', undefined, { shallow: true });
110-
} else if (canceled === 'true') {
111-
toast('Checkout canceled.', { icon: 'ℹ️' });
109+
toast.success('Payment successful! Activating your plan...');
112110
router.replace('/billing', undefined, { shallow: true });
111+
// Poll every 3s for up to 30s until plan updates via webhook
112+
let attempts = 0;
113+
const interval = setInterval(() => {
114+
refreshBilling();
115+
attempts++;
116+
if (attempts >= 10) clearInterval(interval);
117+
}, 3000);
113118
}
114-
}, [router]);
119+
}, [router.query.success]);
115120

116121
if (sessionLoading || billingLoading) return <LoadingSpinner fullPage />;
117122
if (!session) return null;

0 commit comments

Comments
 (0)