diff --git a/src/test_server.py b/src/test_server.py index 6725d83..f12087b 100644 --- a/src/test_server.py +++ b/src/test_server.py @@ -87,41 +87,77 @@ def valid_uuid(val): async def hook_handler(request: web.Request) -> web.Response: """Handle incoming JSON webhook POSTs on /hook endpoint""" try: + current_time = int(asyncio.get_event_loop().time()) + # Verify request method if request.method != "POST": logger.error( - f"{time}\tInvalid request method to /hook from %s", request.remote + f"{current_time}\tInvalid request method to /hook from %s", + request.remote, ) return web.Response(status=405, text="Method not allowed. Use POST.") # Get JSON data from request try: data = await request.json() - except json.JSONDecodeError: - logger.error("Invalid JSON to /hook from %s", request.remote) + except json.JSONDecodeError as e: + print(f"[@DEBUG] Invalid JSON to /hook from {request.remote}: {str(e)}") + logger.error(f"Invalid JSON to /hook from {request.remote}: {str(e)}") return web.Response(status=400, text="Invalid JSON in request body") - # Log the received webhook - print(f"[@DEBUG] Webhook received at {time} from {request.remote}") + # Log the received webhook with detailed output + print(f"\n{'='*60}") + print(f"[@DEBUG] WEBHOOK RECEIVED at {current_time}") + print(f"[@DEBUG] From: {request.remote}") + print(f"[@DEBUG] Headers: {dict(request.headers)}") + print(f"[@DEBUG] Data type: {data.get('type', 'unknown')}") + print(f"[@DEBUG] Event ID: {data.get('event_id', 'none')}") + print(f"[@DEBUG] Full payload:") + print(json.dumps(data, indent=2)) + print(f"{'='*60}\n") + logger.info( - f"{time}\tWebhook received from {request.remote}: {json.dumps(data)}" + f"{current_time}\tWebhook received from {request.remote}: {json.dumps(data)}" ) # Process the webhook data here # TODO: Add your webhook processing logic + webhook_type = data.get("type", "unknown") + + if webhook_type == "inventory.count.updated": + print(f"[@DEBUG] Processing inventory count update...") + # Extract inventory data + inventory_counts = ( + data.get("data", {}).get("object", {}).get("inventory_counts", []) + ) + for count in inventory_counts: + print(f"[@DEBUG] Catalog Object: {count.get('catalog_object_id')}") + print(f"[@DEBUG] Quantity: {count.get('quantity')}") + print(f"[@DEBUG] State: {count.get('state')}") response_data = { "status": "success", - "message": "Webhook received", - "timestamp": time, + "message": f"Webhook received: {webhook_type}", + "timestamp": current_time, + "event_id": data.get("event_id"), "data_received": data, } return web.json_response(response_data) + except json.JSONDecodeError as e: + error_msg = f"JSON decode error in webhook: {str(e)}" + print(f"[@DEBUG] {error_msg}") + logger.error(error_msg) + return web.Response(status=400, text=error_msg) except Exception as e: - logger.error(f"Webhook handler error: {str(e)}") - print(f"Webhook handler error: {str(e)}") + error_msg = f"Webhook handler error: {str(e)}" + print(f"[@DEBUG] {error_msg}") + print(f"[@DEBUG] Exception type: {type(e).__name__}") + import traceback + + print(f"[@DEBUG] Traceback:\n{traceback.format_exc()}") + logger.error(f"{error_msg}\n{traceback.format_exc()}") return web.Response(status=500, text="Internal server error") @@ -168,7 +204,7 @@ async def request_handler(request: web.Request) -> web.Response: if decoded_cmd == "RUNUPDATE": response_data = {"status": "success", "message": "Update started"} await run_update() - logging.info(f"{time()}\tUpdate command processed successfully") + logging.info(f"{time}\tUpdate command processed successfully") return web.json_response(response_data) else: return web.Response(status=400, text=f"Unknown command: {decoded_cmd}") diff --git a/src/test_webhook.py b/src/test_webhook.py new file mode 100644 index 0000000..430b5c8 --- /dev/null +++ b/src/test_webhook.py @@ -0,0 +1,65 @@ +""" +Test script for webhook endpoint +Sends the Square inventory.count.updated webhook payload +""" + +import asyncio +import aiohttp +import json + + +async def test_webhook(): + url = "http://localhost:7432/hook" + + # Your Square webhook payload + payload = { + "merchant_id": "6SSW7HV8K2ST5", + "type": "inventory.count.updated", + "event_id": "df5f3813-a913-45a1-94e9-fdc3f7d5e3b6", + "created_at": "2019-10-29T18:38:45.455006797Z", + "data": { + "type": "inventory_counts", + "id": "84e4ac73-d605-4dbd-a9e5-ffff794ddb9d", + "object": { + "inventory_counts": [ + { + "calculated_at": "2019-10-29T18:38:45.10296Z", + "catalog_object_id": "FGQ5JJWT2PYTHF35CKZ2DSKP", + "catalog_object_type": "ITEM_VARIATION", + "location_id": "YYQR03DGCTXA4", + "quantity": "10", + "state": "IN_STOCK", + } + ] + }, + }, + } + + print("Sending webhook test payload...") + print(json.dumps(payload, indent=2)) + print("\n" + "=" * 60 + "\n") + + try: + async with aiohttp.ClientSession() as session: + async with session.post(url, json=payload) as resp: + print(f"Status: {resp.status}") + print(f"Response headers: {dict(resp.headers)}") + + response_text = await resp.text() + print(f"\nResponse body:") + + try: + response_json = json.loads(response_text) + print(json.dumps(response_json, indent=2)) + except json.JSONDecodeError: + print(response_text) + + except aiohttp.ClientConnectorError as e: + print(f"Connection error: {e}") + print("Make sure the server is running with: python src/test_server.py") + except Exception as e: + print(f"Error: {e}") + + +if __name__ == "__main__": + asyncio.run(test_webhook())