diff --git a/backend/whatsapp.py b/backend/whatsapp.py index fb8b9b4..e026547 100644 --- a/backend/whatsapp.py +++ b/backend/whatsapp.py @@ -531,6 +531,17 @@ class WhatsAppService: "components": components, }, } + + # Validate payload before sending + if not components: + logger.warning( + f"[WhatsApp] Warning: No components being sent. " + f"Header type: {header_type}, body_values: {body_values}" + ) + if not body_values: + logger.warning( + f"[WhatsApp] Warning: No body parameters. Template expects {len(tpl.get('body_params', []))} params." + ) import json logger.info( @@ -538,6 +549,9 @@ class WhatsAppService: f"lang={language_code} to={to_e164} header_type={header_type} " f"header_params={header_values} body_params={body_values}" ) + logger.info( + f"[WhatsApp] Complete payload before sending:\n{json.dumps(payload, indent=2, ensure_ascii=False)}" + ) logger.debug( "[WhatsApp] payload: %s", json.dumps(payload, ensure_ascii=False), @@ -553,17 +567,41 @@ class WhatsAppService: timeout=30.0, ) + result = response.json() + + # Check for HTTP errors if response.status_code not in (200, 201): - error_data = response.json() - error_msg = error_data.get("error", {}).get("message", "Unknown error") - logger.error(f"[WhatsApp] API error ({response.status_code}): {error_msg}") + error_msg = result.get("error", {}).get("message", "Unknown error") + error_code = result.get("error", {}).get("code", "UNKNOWN") + logger.error( + f"[WhatsApp] API error ({response.status_code}) - Code: {error_code} - Message: {error_msg}\n" + f"Full response: {result}" + ) raise WhatsAppError( f"WhatsApp API error ({response.status_code}): {error_msg}" ) - - result = response.json() - message_id = result.get("messages", [{}])[0].get("id") - logger.info(f"[WhatsApp] Message sent successfully via template key. ID: {message_id}") + + # Check for warnings or errors in successful response + if "error" in result: + error_msg = result["error"].get("message", "Unknown error") + logger.error(f"[WhatsApp] Error in response: {error_msg}\nFull response: {result}") + raise WhatsAppError(f"WhatsApp message rejected: {error_msg}") + + # Validate message was actually created + messages = result.get("messages", []) + if not messages: + logger.error(f"[WhatsApp] No message ID in response: {result}") + raise WhatsAppError("No message ID returned from WhatsApp API") + + message_id = messages[0].get("id") + if not message_id: + logger.error(f"[WhatsApp] Message ID missing from response: {result}") + raise WhatsAppError("Message ID missing from WhatsApp API response") + + logger.info( + f"[WhatsApp] Message sent successfully! ID: {message_id}\n" + f"Template: {meta_name}, To: {to_e164}, Status: {response.status_code}" + ) return { "message_id": message_id, "status": "sent", @@ -574,10 +612,12 @@ class WhatsAppService: } except httpx.HTTPError as e: + logger.error(f"[WhatsApp] HTTP request failed: {str(e)}") raise WhatsAppError(f"HTTP request failed: {str(e)}") except WhatsAppError: raise except Exception as e: + logger.error(f"[WhatsApp] Unexpected error: {str(e)}", exc_info=True) raise WhatsAppError(f"Failed to send WhatsApp template: {str(e)}") def handle_webhook_verification(self, challenge: str) -> str: diff --git a/backend/whatsapp_templates.py b/backend/whatsapp_templates.py index 51901c4..4802aac 100644 --- a/backend/whatsapp_templates.py +++ b/backend/whatsapp_templates.py @@ -107,7 +107,16 @@ def save_custom_templates(db: Session, data: Dict[str, Dict[str, Any]]) -> None: def get_all_templates(db: Session) -> Dict[str, Dict[str, Any]]: """Return merged dict: built-in TEMPLATES + user custom templates.""" merged = dict(TEMPLATES) - merged.update(load_custom_templates(db)) + custom = load_custom_templates(db) + merged.update(custom) + + # Debug logging + import logging + logger = logging.getLogger(__name__) + if custom: + logger.info(f"[Templates] Loaded {len(custom)} custom templates from database: {list(custom.keys())}") + logger.debug(f"[Templates] All available templates: {list(merged.keys())}") + return merged