quantum-ai-v3/wallet/views.py
Claude bfdef5b658 Refactor: Complete architecture reorganization with proper separation of concerns
BREAKING CHANGES:
- Move marketplace and agent discovery views from core to agent_base app
- Transfer all wallet functionality from core to dedicated wallet app
- Move Stripe webhook handling to wallet app for better organization
- Consolidate payment system logic under single responsibility

NEW STRUCTURE:
- core app: Platform pages only (homepage, pricing)
- agent_base app: Complete agent marketplace and catalog system
- wallet app: Full payment system with Stripe integration
- Individual agent apps: Unchanged, self-contained

IMPROVEMENTS:
- Clean URL namespacing (agent_base:marketplace, wallet:wallet)
- Template organization by app responsibility
- Removed deprecated CSS files (header.css)
- Added utility classes (.hidden)
- Updated all template references to new URL structure
- Comprehensive CLAUDE.md documentation updates

TECHNICAL CHANGES:
- Templates moved: marketplace.html, agent_detail.html → agent_base/
- Templates moved: wallet*.html → wallet/
- New files: agent_base/views.py, agent_base/urls.py, wallet/urls.py
- Updated main urls.py routing configuration
- Fixed Django system checks and namespace conflicts
- Verified all functionality with test suite

This reorganization follows Django best practices with single responsibility
principle, making the codebase more maintainable and scalable.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 20:03:53 +05:30

244 lines
9.7 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from .stripe_handler import StripePaymentHandler
import datetime
import stripe
from django.conf import settings
# Global webhook logs for debugging (in production, use proper logging)
webhook_logs = []
@login_required
def wallet_view(request):
"""Wallet management page"""
transactions = request.user.wallet_transactions.all()[:50]
# Calculate statistics
total_spent = sum(abs(t.amount) for t in transactions if t.type == 'agent_usage')
total_topped_up = sum(t.amount for t in transactions if t.type == 'top_up')
context = {
'transactions': transactions,
'total_spent': total_spent,
'total_topped_up': total_topped_up,
'current_balance': request.user.wallet_balance,
}
return render(request, 'wallet/wallet.html', context)
@login_required
def wallet_topup_view(request):
"""Wallet top-up page"""
if request.method == 'POST':
amount = request.POST.get('amount')
try:
amount = float(amount)
if amount not in [10, 50, 100, 500]:
messages.error(request, 'Invalid amount selected')
return redirect('wallet:wallet_topup')
# Create Stripe checkout session
stripe_handler = StripePaymentHandler()
session_data = stripe_handler.create_checkout_session(request.user, amount, request)
return redirect(session_data['payment_url'])
except (ValueError, TypeError):
messages.error(request, 'Invalid amount')
return redirect('wallet:wallet_topup')
return render(request, 'wallet/wallet_topup.html')
@login_required
def wallet_topup_success_view(request):
"""Payment success page with automatic payment verification (NO WEBHOOKS NEEDED)"""
session_id = request.GET.get('session_id')
if not session_id:
messages.error(request, 'No payment session found. Please contact support if you completed a payment.')
return redirect('wallet:wallet')
# Verify payment directly with Stripe API (bypasses webhook issues)
try:
stripe_handler = StripePaymentHandler()
print(f"💳 [SUCCESS PAGE] Verifying payment for session: {session_id}")
result = stripe_handler.verify_payment(session_id)
if result['success']:
if result['processed']:
messages.success(request, f'Payment successful! {result["amount"]} AED has been added to your wallet.')
print(f"✅ [SUCCESS PAGE] Payment verified and wallet updated for user {request.user.id}")
else:
messages.info(request, 'Payment already processed. Your wallet balance is up to date.')
print(f" [SUCCESS PAGE] Payment already processed for session {session_id}")
else:
messages.warning(request, f'Payment verification failed: {result.get("error", "Unknown error")}. Please contact support.')
print(f"❌ [SUCCESS PAGE] Payment verification failed: {result}")
except Exception as e:
print(f"❌ [SUCCESS PAGE] Error verifying payment: {e}")
messages.error(request, 'Unable to verify payment. Please contact support if you completed a payment.')
return redirect('wallet:wallet')
@login_required
def wallet_topup_cancel_view(request):
"""Payment cancel page"""
messages.info(request, 'Payment was cancelled. No charges were made.')
return redirect('wallet:wallet_topup')
@login_required
def stripe_debug_view(request):
"""Debug endpoint to show Stripe API configuration and test connectivity"""
debug_info = {
'timestamp': datetime.datetime.now().isoformat(),
'user_id': request.user.id,
'user_email': request.user.email,
}
try:
# Test Stripe API connectivity
print(f"🔍 [STRIPE DEBUG] Testing Stripe API connectivity...")
# Get API key info (masked)
api_key = settings.STRIPE_SECRET_KEY
debug_info['stripe_api_key_last4'] = api_key[-4:] if api_key else 'Not set'
debug_info['stripe_api_key_prefix'] = api_key[:7] if api_key else 'Not set'
debug_info['stripe_api_version'] = stripe.api_version
# Test account connectivity
try:
account = stripe.Account.retrieve()
debug_info['stripe_account'] = {
'id': account.id,
'email': account.email,
'display_name': account.display_name,
'country': account.country,
'default_currency': account.default_currency,
'business_profile': account.business_profile,
'charges_enabled': account.charges_enabled,
'payouts_enabled': account.payouts_enabled,
}
print(f"✅ [STRIPE DEBUG] Account connected: {account.id}")
except Exception as account_error:
debug_info['stripe_account_error'] = str(account_error)
print(f"❌ [STRIPE DEBUG] Account error: {account_error}")
# Test recent checkout sessions
try:
sessions = stripe.checkout.Session.list(limit=5)
debug_info['recent_sessions'] = []
for session in sessions.data:
debug_info['recent_sessions'].append({
'id': session.id,
'status': session.status,
'payment_status': session.payment_status,
'amount_total': session.amount_total,
'currency': session.currency,
'customer_email': session.customer_email,
'client_reference_id': session.client_reference_id,
'created': session.created,
'metadata': session.metadata,
})
print(f"✅ [STRIPE DEBUG] Retrieved {len(sessions.data)} recent sessions")
except Exception as sessions_error:
debug_info['sessions_error'] = str(sessions_error)
print(f"❌ [STRIPE DEBUG] Sessions error: {sessions_error}")
# Test recent payments
try:
charges = stripe.Charge.list(limit=5)
debug_info['recent_charges'] = []
for charge in charges.data:
debug_info['recent_charges'].append({
'id': charge.id,
'amount': charge.amount,
'currency': charge.currency,
'status': charge.status,
'paid': charge.paid,
'customer': charge.customer,
'description': charge.description,
'created': charge.created,
'metadata': charge.metadata,
})
print(f"✅ [STRIPE DEBUG] Retrieved {len(charges.data)} recent charges")
except Exception as charges_error:
debug_info['charges_error'] = str(charges_error)
print(f"❌ [STRIPE DEBUG] Charges error: {charges_error}")
debug_info['status'] = 'success'
except Exception as e:
debug_info['error'] = str(e)
debug_info['status'] = 'error'
print(f"❌ [STRIPE DEBUG] General error: {e}")
return JsonResponse(debug_info, indent=2)
@csrf_exempt
def stripe_webhook_view(request):
"""Handle Stripe webhook events with comprehensive logging"""
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
# Log everything for debugging
print(f"🎯 [{timestamp}] Stripe webhook received!")
print(f"🎯 Method: {request.method}")
print(f"🎯 Content-Type: {request.content_type}")
print(f"🎯 Remote IP: {request.META.get('REMOTE_ADDR', 'unknown')}")
print(f"🎯 User Agent: {request.META.get('HTTP_USER_AGENT', 'unknown')}")
print(f"🎯 Full headers: {dict(request.META)}")
# Store in webhook logs for the test page
webhook_log_entry = {
'timestamp': timestamp,
'method': request.method,
'headers': dict(request.META),
'body': request.body.decode('utf-8') if request.body else '',
'content_type': request.content_type,
'source': 'stripe_webhook',
'ip_address': request.META.get('REMOTE_ADDR', 'unknown'),
'user_agent': request.META.get('HTTP_USER_AGENT', 'unknown')
}
# Add to webhook logs
webhook_logs.append(webhook_log_entry)
if len(webhook_logs) > 50:
webhook_logs.pop(0)
if request.method != 'POST':
print(f"❌ Invalid method: {request.method}")
return JsonResponse({'status': 'error', 'message': f'Method {request.method} not allowed'}, status=405)
payload = request.body
sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')
print(f"📦 Payload length: {len(payload)} bytes")
print(f"📦 Payload preview: {payload[:200]}...")
print(f"🔐 Signature header: {sig_header is not None}")
print(f"🔐 Full signature header: {sig_header}")
# Always return success first to see if Stripe is reaching us
if not sig_header:
print(f"⚠️ No Stripe signature - might be a test request")
return JsonResponse({'status': 'received', 'message': 'No signature verification'})
stripe_handler = StripePaymentHandler()
result = stripe_handler.handle_webhook(payload, sig_header)
print(f"✅ Webhook result: {result}")
if result['success']:
return JsonResponse({'status': 'success'})
else:
return JsonResponse({'status': 'error', 'message': result['error']}, status=400)