fix?!??!?!

This commit is contained in:
C committed 2026-01-03 12:50:36 -08:00
1 parent bd8dd3b93d
commit d95ce1dc7a
1 file changed
+55 -8
+55 -8
View File
@@ -21,19 +21,30 @@ from square.utils.webhooks_helper import verify_signature
SQUARE_WEBHOOK_SIGNATURE_KEY = os.getenv("SANDBOX_SQUARE_WEBHOOK_INVENTORY_ID") SQUARE_WEBHOOK_SIGNATURE_KEY = os.getenv("SANDBOX_SQUARE_WEBHOOK_INVENTORY_ID")
SQUARE_WEBHOOK_URL = os.getenv("SQUARE_WEBHOOK_URL") SQUARE_WEBHOOK_URL = os.getenv("SQUARE_WEBHOOK_URL")
# Debug: Print configuration (redact key)
if SQUARE_WEBHOOK_SIGNATURE_KEY:
print(f"[CONFIG] Signature key loaded: {SQUARE_WEBHOOK_SIGNATURE_KEY[:10]}...")
else:
print("[CONFIG] WARNING: SQUARE_WEBHOOK_SIGNATURE_KEY not set!")
if SQUARE_WEBHOOK_URL:
print(f"[CONFIG] Webhook URL: {SQUARE_WEBHOOK_URL}")
else:
print("[CONFIG] WARNING: SQUARE_WEBHOOK_URL not set!")
# In-memory store for processed event IDs (idempotency) # In-memory store for processed event IDs (idempotency)
processed_event_ids = set() processed_event_ids = set()
MAX_STORED_EVENT_IDS = 10000 MAX_STORED_EVENT_IDS = 10000
# Create FastAPI app # Create FastAPI app
app = FastAPI(title="StudSpider Webhook Server") app = FastAPI(title="Studspider")
@app.get("/") @app.get("/")
async def root(): async def root():
"""Landing page""" """Landing page"""
return { return {
"service": "StudSpider Webhook Server", "service": "Studspider",
"status": "running", "status": "running",
"endpoints": {"webhook": "/hook (POST)", "health": "/health (GET)"}, "endpoints": {"webhook": "/hook (POST)", "health": "/health (GET)"},
} }
@@ -53,7 +64,7 @@ async def health_check():
@app.post("/hook") @app.post("/hook")
async def webhook_handler(request: Request): async def webhook_handler(request: Request):
""" """
Handle Square webhook events Handle Square webhook events - MUST respond within 2 seconds!
Square sends POST requests with: Square sends POST requests with:
- x-square-hmacsha256-signature header - x-square-hmacsha256-signature header
@@ -61,14 +72,22 @@ async def webhook_handler(request: Request):
- event_id for idempotency - event_id for idempotency
""" """
try:
# Log incoming request
print(f"\n[WEBHOOK] Incoming request from {request.client.host}")
print(f"[WEBHOOK] Method: {request.method}")
print(f"[WEBHOOK] URL: {request.url}")
print(f"[WEBHOOK] Headers: {dict(request.headers)}")
# Read raw body for signature verification # Read raw body for signature verification
body = await request.body() body = await request.body()
body_str = body.decode("utf-8") body_str = body.decode("utf-8")
print(f"[WEBHOOK] Body length: {len(body_str)} bytes")
# Get signature header # Get signature header
signature_header = request.headers.get("x-square-hmacsha256-signature", "") signature_header = request.headers.get("x-square-hmacsha256-signature", "")
# Verify Square webhook signature # Verify Square webhook signature (if configured)
if SQUARE_WEBHOOK_SIGNATURE_KEY and SQUARE_WEBHOOK_URL: if SQUARE_WEBHOOK_SIGNATURE_KEY and SQUARE_WEBHOOK_URL:
if not signature_header: if not signature_header:
print( print(
@@ -79,6 +98,12 @@ async def webhook_handler(request: Request):
content={"error": "Missing signature header"}, content={"error": "Missing signature header"},
) )
# Debug signature verification inputs
print(f"[DEBUG] Signature header: {signature_header[:20]}...")
print(f"[DEBUG] Signature key (first 10 chars): {SQUARE_WEBHOOK_SIGNATURE_KEY[:10]}...")
print(f"[DEBUG] Notification URL: {SQUARE_WEBHOOK_URL}")
print(f"[DEBUG] Body (first 100 chars): {body_str[:100]}...")
try: try:
is_valid = verify_signature( is_valid = verify_signature(
request_body=body_str, request_body=body_str,
@@ -88,7 +113,13 @@ async def webhook_handler(request: Request):
) )
if not is_valid: if not is_valid:
print(f"[ERROR] Invalid webhook signature from {request.client.host}") print(
f"[ERROR] Invalid webhook signature from {request.client.host}"
)
print(f"[ERROR] This usually means:")
print(f"[ERROR] 1. SQUARE_WEBHOOK_URL doesn't match Square Dashboard exactly")
print(f"[ERROR] 2. SQUARE_WEBHOOK_SIGNATURE_KEY is incorrect")
print(f"[ERROR] 3. Request body was modified in transit")
return JSONResponse( return JSONResponse(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
content={"error": "Invalid signature"}, content={"error": "Invalid signature"},
@@ -96,10 +127,10 @@ async def webhook_handler(request: Request):
print(f"[INFO] ✓ Webhook signature verified from {request.client.host}") print(f"[INFO] ✓ Webhook signature verified from {request.client.host}")
except Exception as e: except Exception as e:
print(f"[ERROR] Signature verification failed: {e}") print(f"[ERROR] Signature verification exception: {e}")
return JSONResponse( return JSONResponse(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
content={"error": "Signature verification failed"}, content={"error": f"Signature verification failed: {str(e)}"},
) )
else: else:
print( print(
@@ -112,7 +143,8 @@ async def webhook_handler(request: Request):
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
print(f"[ERROR] Invalid JSON from {request.client.host}: {e}") print(f"[ERROR] Invalid JSON from {request.client.host}: {e}")
return JSONResponse( return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST, content={"error": "Invalid JSON"} status_code=status.HTTP_400_BAD_REQUEST,
content={"error": "Invalid JSON"},
) )
# Check idempotency (event_id) # Check idempotency (event_id)
@@ -157,6 +189,21 @@ async def webhook_handler(request: Request):
) )
) )
# Return immediate response
print(f"[INFO] 200 OK response sent for event {event_id_val}")
return JSONResponse(status_code=status.HTTP_200_OK, content=response_data)
except Exception as e:
# Catch-all for any unexpected errors - still respond quickly
print(f"[ERROR] Unexpected error in webhook handler: {e}")
import traceback
traceback.print_exc()
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content={"error": "Internal server error"},
)
# Return immediate response # Return immediate response
return JSONResponse(status_code=status.HTTP_200_OK, content=response_data) return JSONResponse(status_code=status.HTTP_200_OK, content=response_data)