Update Stripe publishable key storage in Stripe Settings
1. Updated UpdateStripeSettingsRequest - Added publishable_key field 2. Updated update_stripe_settings endpoint - Now validates and stores: - stripe_publishable_key (not encrypted - it's public) - stripe_secret_key (encrypted) - stripe_webhook_secret (encrypted) - Also validates that publishable and secret keys are from the same environment (both test or both live) 3. Added new public endpoint GET /api/config/stripe - Returns the publishable key to the frontend (no auth required since it's meant to be public) 4. Updated get_stripe_status endpoint - Now includes publishable_key_prefix and publishable_key_set in the response
This commit is contained in:
Binary file not shown.
58
server.py
58
server.py
@@ -8395,6 +8395,29 @@ def set_setting(
|
||||
|
||||
db.commit()
|
||||
|
||||
@api_router.get("/config/stripe")
|
||||
async def get_stripe_public_config(db: Session = Depends(get_db)):
|
||||
"""
|
||||
Get Stripe publishable key for frontend (public endpoint).
|
||||
|
||||
This endpoint provides the publishable key needed for Stripe.js
|
||||
to initialize payment forms. No authentication required since
|
||||
publishable keys are meant to be public.
|
||||
"""
|
||||
publishable_key = get_setting(db, 'stripe_publishable_key', decrypt=False)
|
||||
|
||||
if not publishable_key:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Stripe is not configured. Please contact the administrator."
|
||||
)
|
||||
|
||||
return {
|
||||
"publishable_key": publishable_key,
|
||||
"environment": "test" if publishable_key.startswith('pk_test_') else "live"
|
||||
}
|
||||
|
||||
|
||||
@api_router.get("/admin/settings/stripe/status")
|
||||
async def get_stripe_status(
|
||||
current_user: User = Depends(get_current_superadmin),
|
||||
@@ -8405,6 +8428,7 @@ async def get_stripe_status(
|
||||
|
||||
Returns:
|
||||
- configured: Whether credentials exist in database
|
||||
- publishable_key_prefix: First 12 chars of publishable key
|
||||
- secret_key_prefix: First 10 chars of secret key (for verification)
|
||||
- webhook_configured: Whether webhook secret exists
|
||||
- environment: test or live (based on key prefix)
|
||||
@@ -8413,10 +8437,11 @@ async def get_stripe_status(
|
||||
import os
|
||||
|
||||
# Read from database
|
||||
publishable_key = get_setting(db, 'stripe_publishable_key', decrypt=False)
|
||||
secret_key = get_setting(db, 'stripe_secret_key', decrypt=True)
|
||||
webhook_secret = get_setting(db, 'stripe_webhook_secret', decrypt=True)
|
||||
|
||||
configured = bool(secret_key)
|
||||
configured = bool(secret_key) and bool(publishable_key)
|
||||
environment = 'unknown'
|
||||
|
||||
if secret_key:
|
||||
@@ -8436,6 +8461,8 @@ async def get_stripe_status(
|
||||
|
||||
return {
|
||||
"configured": configured,
|
||||
"publishable_key_prefix": publishable_key[:12] if publishable_key else None,
|
||||
"publishable_key_set": bool(publishable_key),
|
||||
"secret_key_prefix": secret_key[:10] if secret_key else None,
|
||||
"secret_key_set": bool(secret_key),
|
||||
"webhook_secret_set": bool(webhook_secret),
|
||||
@@ -8444,6 +8471,7 @@ async def get_stripe_status(
|
||||
"instructions": {
|
||||
"location": "Database (system_settings table)",
|
||||
"required_settings": [
|
||||
"stripe_publishable_key (pk_test_... or pk_live_...)",
|
||||
"stripe_secret_key (sk_test_... or sk_live_...)",
|
||||
"stripe_webhook_secret (whsec_...)"
|
||||
],
|
||||
@@ -8501,6 +8529,7 @@ async def test_stripe_connection(
|
||||
|
||||
class UpdateStripeSettingsRequest(BaseModel):
|
||||
"""Request model for updating Stripe settings"""
|
||||
publishable_key: str = Field(..., min_length=1, description="Stripe publishable key (pk_test_... or pk_live_...)")
|
||||
secret_key: str = Field(..., min_length=1, description="Stripe secret key (sk_test_... or sk_live_...)")
|
||||
webhook_secret: str = Field(..., min_length=1, description="Stripe webhook secret (whsec_...)")
|
||||
|
||||
@@ -8517,6 +8546,13 @@ async def update_stripe_settings(
|
||||
Stores Stripe credentials encrypted in the database.
|
||||
Changes take effect immediately without server restart.
|
||||
"""
|
||||
# Validate publishable key format
|
||||
if not (request.publishable_key.startswith('pk_test_') or request.publishable_key.startswith('pk_live_')):
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Invalid Stripe publishable key format. Must start with 'pk_test_' or 'pk_live_'"
|
||||
)
|
||||
|
||||
# Validate secret key format
|
||||
if not (request.secret_key.startswith('sk_test_') or request.secret_key.startswith('sk_live_')):
|
||||
raise HTTPException(
|
||||
@@ -8531,7 +8567,27 @@ async def update_stripe_settings(
|
||||
detail="Invalid Stripe webhook secret format. Must start with 'whsec_'"
|
||||
)
|
||||
|
||||
# Validate key environment consistency (publishable and secret should match)
|
||||
pk_is_live = request.publishable_key.startswith('pk_live_')
|
||||
sk_is_live = request.secret_key.startswith('sk_live_')
|
||||
if pk_is_live != sk_is_live:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Publishable key and Secret key must be from the same environment (both test or both live)"
|
||||
)
|
||||
|
||||
try:
|
||||
# Store publishable key (NOT encrypted - it's meant to be public)
|
||||
set_setting(
|
||||
db=db,
|
||||
key='stripe_publishable_key',
|
||||
value=request.publishable_key,
|
||||
user_id=str(current_user.id),
|
||||
description='Stripe publishable key for frontend payment forms',
|
||||
is_sensitive=False,
|
||||
encrypt=False
|
||||
)
|
||||
|
||||
# Store secret key (encrypted)
|
||||
set_setting(
|
||||
db=db,
|
||||
|
||||
Reference in New Issue
Block a user