96 lines
3.2 KiB
Python
96 lines
3.2 KiB
Python
import httpx
|
|
from typing import Dict, Any, Optional
|
|
from app.providers.base import BaseProvider
|
|
from app.core.config import settings
|
|
|
|
class WhatsAppCloudProvider(BaseProvider):
|
|
"""WhatsApp Cloud API provider (Meta)"""
|
|
|
|
def __init__(self):
|
|
self.access_token = settings.WHATSAPP_CLOUD_ACCESS_TOKEN
|
|
self.phone_number_id = settings.WHATSAPP_CLOUD_PHONE_NUMBER_ID
|
|
self.base_url = "https://graph.facebook.com/v18.0"
|
|
|
|
def send_message(
|
|
self,
|
|
to: str,
|
|
template_name: Optional[str],
|
|
template_body: str,
|
|
variables: Dict[str, str],
|
|
language: str = "en"
|
|
) -> str:
|
|
"""
|
|
Send message via WhatsApp Cloud API.
|
|
|
|
If template_name is provided, sends a template message.
|
|
Otherwise, sends a text message.
|
|
"""
|
|
url = f"{self.base_url}/{self.phone_number_id}/messages"
|
|
headers = {
|
|
"Authorization": f"Bearer {self.access_token}",
|
|
"Content-Type": "application/json"
|
|
}
|
|
|
|
if template_name:
|
|
# Send template message
|
|
# Build template parameters
|
|
components = []
|
|
if variables:
|
|
parameters = [
|
|
{"type": "text", "text": value}
|
|
for value in variables.values()
|
|
]
|
|
components.append({
|
|
"type": "body",
|
|
"parameters": parameters
|
|
})
|
|
|
|
payload = {
|
|
"messaging_product": "whatsapp",
|
|
"to": to.replace("+", ""),
|
|
"type": "template",
|
|
"template": {
|
|
"name": template_name,
|
|
"language": {
|
|
"code": language
|
|
},
|
|
"components": components
|
|
}
|
|
}
|
|
else:
|
|
# Send text message (only for contacts with conversation window)
|
|
# Substitute variables in body
|
|
message_text = template_body
|
|
for key, value in variables.items():
|
|
message_text = message_text.replace(f"{{{{{key}}}}}", value)
|
|
|
|
payload = {
|
|
"messaging_product": "whatsapp",
|
|
"to": to.replace("+", ""),
|
|
"type": "text",
|
|
"text": {
|
|
"body": message_text
|
|
}
|
|
}
|
|
|
|
try:
|
|
with httpx.Client(timeout=30.0) as client:
|
|
response = client.post(url, headers=headers, json=payload)
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
message_id = data.get("messages", [{}])[0].get("id")
|
|
|
|
if not message_id:
|
|
raise Exception("No message ID in response")
|
|
|
|
return message_id
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
raise Exception(f"WhatsApp API error: {e.response.status_code} - {e.response.text}")
|
|
except Exception as e:
|
|
raise Exception(f"Send error: {str(e)}")
|
|
|
|
def get_provider_name(self) -> str:
|
|
return "whatsapp_cloud"
|