From f7cdad42736c565eaf3e96badac42b2c4cdc6a97 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 12 Jul 2025 12:25:51 +0530 Subject: [PATCH] Replace hardcoded Stripe payment links with dynamic checkout sessions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove hardcoded payment link URLs that were environment-specific - Implement dynamic Stripe checkout session creation with automatic domain detection - Add success/cancel URLs that automatically work on localhost and Railway - Update StripePaymentHandler to use request.build_absolute_uri() for proper URL generation - Add wallet top-up success and cancel views with proper user feedback - This fixes the issue where payment success redirected to old/wrong URLs 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- core/urls.py | 2 ++ core/views.py | 16 ++++++++++- wallet/stripe_handler.py | 60 ++++++++++++++++++++++++++++++---------- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/core/urls.py b/core/urls.py index b0031d3..de2fc48 100644 --- a/core/urls.py +++ b/core/urls.py @@ -10,6 +10,8 @@ urlpatterns = [ path('agents//', views.agent_detail_view, name='agent_detail'), path('wallet/', views.wallet_view, name='wallet'), path('wallet/topup/', views.wallet_topup_view, name='wallet_topup'), + path('wallet/top-up/success/', views.wallet_topup_success_view, name='wallet_topup_success'), + path('wallet/top-up/cancel/', views.wallet_topup_cancel_view, name='wallet_topup_cancel'), path('stripe/webhook/', views.stripe_webhook_view, name='stripe_webhook'), path('api/agents/', views.agents_api_view, name='agents_api'), ] \ No newline at end of file diff --git a/core/views.py b/core/views.py index 1133aa7..26b42a0 100644 --- a/core/views.py +++ b/core/views.py @@ -118,7 +118,7 @@ def wallet_topup_view(request): # Create Stripe checkout session stripe_handler = StripePaymentHandler() - session_data = stripe_handler.create_checkout_session(request.user, amount) + session_data = stripe_handler.create_checkout_session(request.user, amount, request) return redirect(session_data['payment_url']) @@ -129,6 +129,20 @@ def wallet_topup_view(request): return render(request, 'core/wallet_topup.html') +@login_required +def wallet_topup_success_view(request): + """Payment success page""" + messages.success(request, 'Payment successful! Your wallet balance has been updated.') + return redirect('core:wallet') + + +@login_required +def wallet_topup_cancel_view(request): + """Payment cancel page""" + messages.info(request, 'Payment was cancelled. No charges were made.') + return redirect('core:wallet_topup') + + @csrf_exempt @require_http_methods(["POST"]) def stripe_webhook_view(request): diff --git a/wallet/stripe_handler.py b/wallet/stripe_handler.py index 7d41904..5742fcd 100644 --- a/wallet/stripe_handler.py +++ b/wallet/stripe_handler.py @@ -11,25 +11,55 @@ stripe.api_key = settings.STRIPE_SECRET_KEY class StripePaymentHandler: def __init__(self): - self.payment_links = { - 10: 'https://buy.stripe.com/test_28EbJ16AA7ly3ic7vh2VG0a', - 50: 'https://buy.stripe.com/test_4gM00jbUUgW83ic3f12VG0b', - 100: 'https://buy.stripe.com/test_aFadR99MM35ibOI6rd2VG0c', - 500: 'https://buy.stripe.com/test_14AbJ12kk7lyf0U16T2VG0d' - } + self.allowed_amounts = [10, 50, 100, 500] - def create_checkout_session(self, user, amount): + def create_checkout_session(self, user, amount, request=None): """Create a Stripe checkout session for wallet top-up""" - if amount not in self.payment_links: - raise ValueError(f"Invalid amount: {amount}") + if amount not in self.allowed_amounts: + raise ValueError(f"Invalid amount: {amount}. Allowed amounts: {self.allowed_amounts}") - payment_link = self.payment_links[amount] + # Build URLs based on current request domain + if request: + success_url = request.build_absolute_uri('/wallet/top-up/success/') + cancel_url = request.build_absolute_uri('/wallet/top-up/cancel/') + else: + # Fallback URLs (shouldn't happen in normal flow) + success_url = 'https://netcop.up.railway.app/wallet/top-up/success/' + cancel_url = 'https://netcop.up.railway.app/wallet/top-up/cancel/' - # Return the payment link URL with user reference - return { - 'payment_url': f"{payment_link}?client_reference_id={user.id}&prefilled_email={user.email}", - 'session_id': None # Payment links don't have session IDs - } + try: + session = stripe.checkout.Session.create( + payment_method_types=['card'], + line_items=[{ + 'price_data': { + 'currency': 'aed', + 'product_data': { + 'name': f'NetCop Wallet Top-up', + 'description': f'Add {amount} AED to your wallet balance' + }, + 'unit_amount': int(amount * 100), # Convert to cents + }, + 'quantity': 1, + }], + mode='payment', + success_url=success_url, + cancel_url=cancel_url, + client_reference_id=str(user.id), + customer_email=user.email, + metadata={ + 'user_id': str(user.id), + 'amount': str(amount), + 'type': 'wallet_topup' + } + ) + + return { + 'payment_url': session.url, + 'session_id': session.id + } + + except stripe.error.StripeError as e: + raise ValueError(f"Failed to create checkout session: {str(e)}") def verify_payment(self, session_id): """Verify payment from Stripe webhook"""