token
This commit is contained in:
parent
9dbda69db1
commit
a2b076e9a1
6 changed files with 122 additions and 8 deletions
|
|
@ -9,7 +9,13 @@ from sqlalchemy.orm import Session
|
|||
from .auth import current_user
|
||||
from .config import settings
|
||||
from .database import get_db
|
||||
from .models import UserAccount, WhatsAppBusinessAccount, WhatsAppPhoneAsset, WhatsAppWebhookEvent
|
||||
from .models import (
|
||||
UserAccount,
|
||||
WhatsAppBusinessAccount,
|
||||
WhatsAppMetaConnection,
|
||||
WhatsAppPhoneAsset,
|
||||
WhatsAppWebhookEvent,
|
||||
)
|
||||
from .whatsapp_graph_client import WhatsAppGraphClient, WhatsAppGraphError
|
||||
from .whatsapp_config import resolved_whatsapp_app_secret
|
||||
from .whatsapp_onboarding import (
|
||||
|
|
@ -40,6 +46,25 @@ logger = logging.getLogger(__name__)
|
|||
router = APIRouter(prefix="/api/v1/whatsapp", tags=["whatsapp"])
|
||||
|
||||
|
||||
def _webhook_secrets(db: Session) -> list[str]:
|
||||
"""Platform secret for the admin app, plus each customer's own Meta app secret."""
|
||||
found: list[str] = []
|
||||
primary = resolved_whatsapp_app_secret(db).strip()
|
||||
if primary:
|
||||
found.append(primary)
|
||||
extras = db.scalars(
|
||||
select(WhatsAppMetaConnection.meta_app_secret).where(
|
||||
WhatsAppMetaConnection.meta_app_secret.is_not(None),
|
||||
WhatsAppMetaConnection.status != "disconnected",
|
||||
)
|
||||
).all()
|
||||
for item in extras:
|
||||
value = (item or "").strip()
|
||||
if value and value not in found:
|
||||
found.append(value)
|
||||
return found
|
||||
|
||||
|
||||
def _serialize_event(event: WhatsAppWebhookEvent) -> dict:
|
||||
return {
|
||||
"id": str(event.id),
|
||||
|
|
@ -84,10 +109,10 @@ async def receive_webhook(
|
|||
) -> dict[str, str]:
|
||||
"""Receive inbound WhatsApp Business Platform webhook payloads."""
|
||||
raw_body = await request.body()
|
||||
app_secret = resolved_whatsapp_app_secret(db)
|
||||
secrets = _webhook_secrets(db)
|
||||
|
||||
if app_secret:
|
||||
if not verify_meta_signature(app_secret, raw_body, x_hub_signature_256):
|
||||
if secrets:
|
||||
if not any(verify_meta_signature(secret, raw_body, x_hub_signature_256) for secret in secrets):
|
||||
logger.warning("WhatsApp webhook signature validation failed")
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Invalid signature")
|
||||
elif settings.environment == "production":
|
||||
|
|
@ -179,6 +204,7 @@ class ManualTokenRequest(BaseModel):
|
|||
access_token: str = Field(min_length=1, max_length=4096)
|
||||
waba_id: str = Field(min_length=1, max_length=64)
|
||||
phone_number_id: str | None = Field(default=None, max_length=64)
|
||||
app_secret: str | None = Field(default=None, max_length=256)
|
||||
|
||||
|
||||
class SignupCompleteRequest(BaseModel):
|
||||
|
|
@ -227,6 +253,7 @@ async def whatsapp_connect_token(
|
|||
payload.access_token,
|
||||
payload.waba_id,
|
||||
payload.phone_number_id,
|
||||
payload.app_secret,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue