Commit 99a10bbb authored by Your Name's avatar Your Name

feat: implement PayPal OAuth initiation endpoint

parent 44a1f5d0
...@@ -58,7 +58,7 @@ from collections import defaultdict ...@@ -58,7 +58,7 @@ from collections import defaultdict
from pathlib import Path from pathlib import Path
import json import json
import markdown import markdown
from urllib.parse import urljoin from urllib.parse import urljoin, urlencode
# Global variable to store custom config directory # Global variable to store custom config directory
_custom_config_dir = None _custom_config_dir = None
...@@ -6204,7 +6204,7 @@ async def dashboard_set_default_payment_method(request: Request, method_id: int) ...@@ -6204,7 +6204,7 @@ async def dashboard_set_default_payment_method(request: Request, method_id: int)
@app.get("/dashboard/billing/add-method/paypal/oauth") @app.get("/dashboard/billing/add-method/paypal/oauth")
async def dashboard_add_payment_method_paypal_oauth(request: Request): async def dashboard_add_payment_method_paypal_oauth(request: Request):
"""Add PayPal as payment preference (simplified approach)""" """Initiate PayPal OAuth 2.0 flow"""
auth_check = require_dashboard_auth(request) auth_check = require_dashboard_auth(request)
if auth_check: if auth_check:
return auth_check return auth_check
...@@ -6217,55 +6217,64 @@ async def dashboard_add_payment_method_paypal_oauth(request: Request): ...@@ -6217,55 +6217,64 @@ async def dashboard_add_payment_method_paypal_oauth(request: Request):
gateways = db.get_payment_gateway_settings() gateways = db.get_payment_gateway_settings()
paypal_settings = gateways.get('paypal', {}) paypal_settings = gateways.get('paypal', {})
# Validate PayPal is enabled
if not paypal_settings.get('enabled'): if not paypal_settings.get('enabled'):
return templates.TemplateResponse( logger.warning(f"PayPal OAuth attempted but PayPal is not enabled (user_id={user_id})")
request=request, return RedirectResponse(
name="dashboard/paypal_connect.html", url="/dashboard/billing?error=PayPal is not enabled",
context={ status_code=302
"request": request, )
"session": request.session,
"message": "PayPal is not enabled. Please contact the administrator." # Validate PayPal is configured
} client_id = paypal_settings.get('client_id', '').strip()
if not client_id:
logger.error(f"PayPal OAuth attempted but client_id not configured (user_id={user_id})")
return RedirectResponse(
url="/dashboard/billing?error=PayPal is not properly configured",
status_code=302
) )
# Check if user already has PayPal as payment method # Check if user already has PayPal as payment method
existing_methods = db.get_user_payment_methods(user_id) existing_methods = db.get_user_payment_methods(user_id)
for method in existing_methods: for method in existing_methods:
if method.get('type') == 'paypal': if method.get('type') == 'paypal':
logger.info(f"User {user_id} already has PayPal payment method")
return RedirectResponse( return RedirectResponse(
url="/dashboard/billing?error=PayPal is already added as a payment method", url="/dashboard/billing?error=PayPal is already added as a payment method",
status_code=302 status_code=302
) )
# Add PayPal as payment preference (no OAuth needed) # Generate CSRF state token
# This is a simplified approach - PayPal will be used at checkout time import secrets
try: state_token = secrets.token_hex(32) # 64 hex characters
is_default = len(existing_methods) == 0 # First payment method is default request.session['paypal_oauth_state'] = state_token
method_id = db.add_payment_method(
user_id=user_id, # Determine PayPal URLs based on sandbox mode
method_type='paypal', is_sandbox = paypal_settings.get('sandbox', True)
identifier='paypal_account', if is_sandbox:
is_default=is_default, auth_base_url = "https://www.sandbox.paypal.com/signin/authorize"
metadata={'type': 'preference', 'note': 'PayPal will be used at checkout'} else:
) auth_base_url = "https://www.paypal.com/signin/authorize"
if method_id: # Construct callback URL
logger.info(f"PayPal added as payment preference for user {user_id}") base_url = str(request.base_url).rstrip('/')
return RedirectResponse( redirect_uri = f"{base_url}/dashboard/billing/add-method/paypal/callback"
url="/dashboard/billing?success=PayPal added as payment method. You'll be able to pay with PayPal at checkout.",
status_code=302 # Build PayPal authorization URL
) from urllib.parse import urlencode
else: params = {
return RedirectResponse( 'client_id': client_id,
url="/dashboard/billing?error=Failed to add PayPal as payment method", 'response_type': 'code',
status_code=302 'scope': 'openid profile email',
) 'redirect_uri': redirect_uri,
except Exception as e: 'state': state_token
logger.error(f"Error adding PayPal payment preference: {e}") }
return RedirectResponse( paypal_auth_url = f"{auth_base_url}?{urlencode(params)}"
url="/dashboard/billing?error=An error occurred while adding PayPal",
status_code=302 logger.info(f"Initiating PayPal OAuth for user {user_id}, sandbox={is_sandbox}")
) logger.debug(f"PayPal OAuth redirect_uri: {redirect_uri}")
return RedirectResponse(url=paypal_auth_url, status_code=302)
@app.get("/dashboard/billing/add-method/paypal/callback") @app.get("/dashboard/billing/add-method/paypal/callback")
async def dashboard_add_payment_method_paypal_callback(request: Request): async def dashboard_add_payment_method_paypal_callback(request: Request):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment