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
|
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:
|
def handle_webhook_verification(self, challenge: str) -> str:
|
||||||
"""
|
"""
|
||||||
Handle webhook verification challenge from Meta
|
Handle webhook verification challenge from Meta
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user