fix: add missing send_by_template_key method to WhatsAppService
This commit is contained in:
parent
d338722880
commit
c50544d4bd
@ -411,6 +411,123 @@ class WhatsAppService:
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
async def send_by_template_key(
|
||||
self,
|
||||
template_key: str,
|
||||
to_phone: str,
|
||||
params: dict,
|
||||
) -> dict:
|
||||
"""
|
||||
Send a WhatsApp template message using the template registry.
|
||||
|
||||
Looks up *template_key* in whatsapp_templates.py, resolves header and
|
||||
body parameter lists (with fallbacks) from *params*, then builds and
|
||||
sends the Meta API payload dynamically.
|
||||
|
||||
Args:
|
||||
template_key: Registry key (e.g. "wedding_invitation").
|
||||
to_phone: Recipient phone number (normalized to E.164).
|
||||
params: Dict of {param_key: value} for all placeholders.
|
||||
|
||||
Returns:
|
||||
dict with message_id and status.
|
||||
"""
|
||||
from whatsapp_templates import get_template, build_params_list
|
||||
|
||||
tpl = get_template(template_key)
|
||||
meta_name = tpl["meta_name"]
|
||||
language_code = tpl.get("language_code", "he")
|
||||
|
||||
header_values, body_values = build_params_list(template_key, params)
|
||||
|
||||
to_e164 = self.normalize_phone_to_e164(to_phone)
|
||||
if not self.validate_phone(to_e164):
|
||||
raise WhatsAppError(f"Invalid phone number: {to_phone}")
|
||||
|
||||
components = []
|
||||
if header_values:
|
||||
components.append({
|
||||
"type": "header",
|
||||
"parameters": [{"type": "text", "text": str(v)} for v in header_values],
|
||||
})
|
||||
if body_values:
|
||||
components.append({
|
||||
"type": "body",
|
||||
"parameters": [{"type": "text", "text": str(v)} for v in body_values],
|
||||
})
|
||||
|
||||
# Handle url_button component if defined in template
|
||||
url_btn = tpl.get("url_button", {})
|
||||
if url_btn and url_btn.get("enabled"):
|
||||
param_key = url_btn.get("param_key", "event_id")
|
||||
btn_value = str(params.get(param_key, "")).strip()
|
||||
if btn_value:
|
||||
components.append({
|
||||
"type": "button",
|
||||
"sub_type": "url",
|
||||
"index": str(url_btn.get("button_index", 0)),
|
||||
"parameters": [{"type": "text", "text": btn_value}],
|
||||
})
|
||||
|
||||
payload = {
|
||||
"messaging_product": "whatsapp",
|
||||
"to": to_e164,
|
||||
"type": "template",
|
||||
"template": {
|
||||
"name": meta_name,
|
||||
"language": {"code": language_code},
|
||||
"components": components,
|
||||
},
|
||||
}
|
||||
|
||||
import json
|
||||
logger.info(
|
||||
f"[WhatsApp] send_by_template_key '{template_key}' → meta='{meta_name}' "
|
||||
f"lang={language_code} to={to_e164} "
|
||||
f"header_params={header_values} body_params={body_values}"
|
||||
)
|
||||
logger.debug(
|
||||
"[WhatsApp] payload: %s",
|
||||
json.dumps(payload, ensure_ascii=False),
|
||||
)
|
||||
|
||||
url = f"{self.base_url}/{self.phone_number_id}/messages"
|
||||
try:
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.post(
|
||||
url,
|
||||
json=payload,
|
||||
headers=self.headers,
|
||||
timeout=30.0,
|
||||
)
|
||||
|
||||
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}")
|
||||
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}")
|
||||
return {
|
||||
"message_id": message_id,
|
||||
"status": "sent",
|
||||
"to": to_e164,
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"type": "template",
|
||||
"template": meta_name,
|
||||
}
|
||||
|
||||
except httpx.HTTPError as e:
|
||||
raise WhatsAppError(f"HTTP request failed: {str(e)}")
|
||||
except WhatsAppError:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise WhatsAppError(f"Failed to send WhatsApp template: {str(e)}")
|
||||
|
||||
def handle_webhook_verification(self, challenge: str) -> str:
|
||||
"""
|
||||
Handle webhook verification challenge from Meta
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user