From 0cc965aff65245a2d3e9f450688943e3d4dafc85 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 14 May 2026 10:02:12 +0300 Subject: [PATCH] Fix SSL/TLS issue and remove hina_invitation from built-in templates (user-managed only) --- backend/main.py | 35 ++++++++++-------------- backend/whatsapp.py | 51 +++++------------------------------ backend/whatsapp_templates.py | 25 ----------------- 3 files changed, 21 insertions(+), 90 deletions(-) diff --git a/backend/main.py b/backend/main.py index 2422b13..523a595 100644 --- a/backend/main.py +++ b/backend/main.py @@ -74,21 +74,11 @@ def _fix_template_parameters(): import json db = SessionLocal() try: - # First, delete any old custom hina_invitation records (it's now built-in only) - old_templates = db.query(models.WhatsAppTemplate).filter( - (models.WhatsAppTemplate.template_key == 'hina_invitation') | - (models.WhatsAppTemplate.meta_name == 'hina_invitation') - ).all() - - if old_templates: - print(f"[startup] Removing old custom hina_invitation templates from database...") - for old_tpl in old_templates: - print(f" Deleting: {old_tpl.template_key} (had {old_tpl.body_params} params)") - db.delete(old_tpl) - db.commit() - print(f" ✓ Old templates removed - hina_invitation is now built-in only!") + # No built-in template fixes needed currently + # hina_invitation is now user-managed only (not built-in) + pass except Exception as e: - print(f"[startup] Template cleanup warning: {e}") + print(f"[startup] Template fix warning: {e}") finally: db.close() @@ -1988,16 +1978,19 @@ async def test_whatsapp_send( service = get_whatsapp_service(db) - # hina_invitation template needs both parameters: - # - contact_name: for body {{1}} (guest's name) - # - event_id: for button {{1}} (dynamic URL) + # Test with wedding_invitation template (built-in template with basic params) params = { - "contact_name": "Test", - "event_id": "test-event-123" + "contact_name": "Test User", + "groom_name": "Groom", + "bride_name": "Bride", + "venue": "Test Venue", + "event_date": "01/06", + "event_time": "18:00", + "guest_link": "https://invy.dvirlabs.com/guest/test-event-123" } - # Use hina_invitation template - template_key = "hina_invitation" + # Use wedding_invitation template + template_key = "wedding_invitation" result = await service.send_by_template_key( template_key=template_key, diff --git a/backend/whatsapp.py b/backend/whatsapp.py index 9fecd7f..f03fa27 100644 --- a/backend/whatsapp.py +++ b/backend/whatsapp.py @@ -17,51 +17,14 @@ logger = logging.getLogger(__name__) async def create_http_client() -> httpx.AsyncClient: """ Create an httpx client with proper certificate verification. - Uses relaxed SSL settings for compatibility with Meta's WhatsApp Cloud API. + Uses certifi for CA bundle - simple and reliable. """ - import ssl - - try: - # Create a more permissive SSL context for compatibility - ssl_context = ssl.create_default_context(cafile=certifi.where()) - - # Allow TLS 1.0+ for maximum compatibility - ssl_context.minimum_version = ssl.TLSVersion.TLSv1 - - # Relax cipher restrictions - ssl_context.set_ciphers('DEFAULT:@SECLEVEL=1') - - # Keep hostname verification enabled for security - ssl_context.check_hostname = True - ssl_context.verify_mode = ssl.CERT_REQUIRED - - return httpx.AsyncClient( - verify=ssl_context, - timeout=httpx.Timeout(30.0, connect=10.0), - http2=False, # Disable HTTP/2 for better compatibility - limits=httpx.Limits(max_keepalive_connections=5, max_connections=10) - ) - except Exception as e: - logger.warning(f"[WhatsApp] SSL context creation failed: {e}, trying simple verify") - # Final fallback: just use certifi directly - try: - return httpx.AsyncClient( - verify=certifi.where(), - timeout=httpx.Timeout(30.0, connect=10.0), - http2=False, - limits=httpx.Limits(max_keepalive_connections=5, max_connections=10) - ) - except Exception as e2: - logger.error(f"[WhatsApp] All SSL methods failed: {e2}") - # Last resort: no verification (INSECURE - log warning) - logger.warning("⚠️ Using INSECURE SSL (no verification) - FIX YOUR SSL SETUP!") - return httpx.AsyncClient( - verify=False, - timeout=httpx.Timeout(30.0, connect=10.0), - http2=False, - limits=httpx.Limits(max_keepalive_connections=5, max_connections=10) - ) - + return httpx.AsyncClient( + verify=certifi.where(), + timeout=httpx.Timeout(30.0, connect=10.0), + http2=False, + limits=httpx.Limits(max_keepalive_connections=5, max_connections=10) + ) class WhatsAppError(Exception): diff --git a/backend/whatsapp_templates.py b/backend/whatsapp_templates.py index ef7b646..4802aac 100644 --- a/backend/whatsapp_templates.py +++ b/backend/whatsapp_templates.py @@ -240,31 +240,6 @@ TEMPLATES: Dict[str, Dict[str, Any]] = { "guest_link": "https://invy.dvirlabs.com/guest", }, }, - - # ── hina_invitation ──────────────────────────────────────────────────────── - # Special event template with dynamic IMAGE header, body params, and button - # Header: IMAGE (dynamic - sent from event.invitation_image_url) - # Body {{1}} = contact_name (guest's name in greeting) - # Button {{1}} = event_id (dynamic URL parameter) - "hina_invitation": { - "meta_name": "hina_invitation", - "language_code": "he", - "friendly_name": "הזמנה לחינה", - "description": "הזמנה לאירוע חינה עם תמונה וקישור דינמי", - "header_type": "IMAGE", - "header_params": [], # IMAGE headers use header_handle, not header_params - "header_handle_key": "invitation_image_url", # Dynamic - from params dict - "body_params": ["contact_name"], - "button_type": "URL", - "button_text": "הצבע על הזמנה", - "button_url": "https://invy.dvirlabs.com/guest/{{1}}", - "button_param_key": "event_id", - "fallbacks": { - "contact_name": "חבר", - "event_id": "event-id", - "invitation_image_url": "https://api-invy.dvirlabs.com/uploads/default.jpg", - }, - }, }