test(webhook): cover whatsapp ingress verification
This commit is contained in:
@@ -487,7 +487,7 @@ func TestWhatsAppWebhookPersistsIncomingMessage(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := newWebhookLookupTestDB(t)
|
||||
inbox := seedWebhookInbox(t, db, "whatsapp")
|
||||
waChannel := channelmodel.ChannelWhatsApp{AccountID: 1, InboxID: inbox.ID, PhoneNumber: "+15551230000", PhoneNumberID: "phone-id-1", AccessToken: "token"}
|
||||
waChannel := channelmodel.ChannelWhatsApp{AccountID: 1, InboxID: inbox.ID, PhoneNumber: "+15551230000", PhoneNumberID: "phone-id-1", AccessToken: "token", Provider: "whatsapp_cloud", ProviderConfig: `{"app_secret":"wa-secret"}`, WebhookVerifyToken: "verify-token"}
|
||||
if err := db.Create(&waChannel).Error; err != nil {
|
||||
t.Fatalf("create whatsapp channel: %v", err)
|
||||
}
|
||||
@@ -503,6 +503,7 @@ func TestWhatsAppWebhookPersistsIncomingMessage(t *testing.T) {
|
||||
body := []byte(`{"object":"whatsapp_business_account","entry":[{"id":"waba-1","changes":[{"field":"messages","value":{"messaging_product":"whatsapp","metadata":{"display_phone_number":"+15551230000","phone_number_id":"phone-id-1"},"contacts":[{"wa_id":"15550001111","profile":{"name":"WhatsApp User"}}],"messages":[{"from":"15550001111","id":"wamid-1","timestamp":"1710000000","type":"text","text":{"body":"hello whatsapp"}}]}}]}]}`)
|
||||
req := httptest.NewRequest(http.MethodPost, "/webhooks/whatsapp/+15551230000", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Hub-Signature-256", metaSignature("wa-secret", body))
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
r.ServeHTTP(w, req)
|
||||
@@ -513,6 +514,72 @@ func TestWhatsAppWebhookPersistsIncomingMessage(t *testing.T) {
|
||||
assertPersistedMessage(t, db, inbox.ID, "wamid-1", "hello whatsapp")
|
||||
}
|
||||
|
||||
func TestWhatsAppWebhookVerificationEchoesChallenge(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := newWebhookLookupTestDB(t)
|
||||
inbox := seedWebhookInbox(t, db, "whatsapp")
|
||||
waChannel := channelmodel.ChannelWhatsApp{AccountID: 1, InboxID: inbox.ID, PhoneNumber: "+15551230000", PhoneNumberID: "phone-id-1", AccessToken: "token", Provider: "whatsapp_cloud", WebhookVerifyToken: "verify-token"}
|
||||
if err := db.Create(&waChannel).Error; err != nil {
|
||||
t.Fatalf("create whatsapp channel: %v", err)
|
||||
}
|
||||
|
||||
waRepo := whatsappchannel.NewRepository(db)
|
||||
waService := whatsappchannel.NewWhatsAppService(waRepo)
|
||||
waPipeline := whatsappchannel.NewIncomingPipeline(waService)
|
||||
waProvider := whatsappchannel.NewWhatsAppProvider(waService, waRepo, waPipeline)
|
||||
waWebhook := whatsappchannel.NewWebhookHandler(waProvider)
|
||||
h := NewWhatsAppWebhookHandler(waProvider, waWebhook, db)
|
||||
r := gin.New()
|
||||
r.GET("/webhooks/whatsapp/:phone_number", h.HandleWhatsAppVerification)
|
||||
req := httptest.NewRequest(http.MethodGet, "/webhooks/whatsapp/+15551230000?hub.mode=subscribe&hub.verify_token=verify-token&hub.challenge=challenge-wa", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d body=%s", w.Code, w.Body.String())
|
||||
}
|
||||
if w.Body.String() != "challenge-wa" {
|
||||
t.Fatalf("unexpected challenge body: %q", w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestWhatsAppCloudWebhookRejectsMissingSignature(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := newWebhookLookupTestDB(t)
|
||||
inbox := seedWebhookInbox(t, db, "whatsapp")
|
||||
waChannel := channelmodel.ChannelWhatsApp{AccountID: 1, InboxID: inbox.ID, PhoneNumber: "+15551230000", PhoneNumberID: "phone-id-1", AccessToken: "token", Provider: "whatsapp_cloud", ProviderConfig: `{"app_secret":"wa-secret"}`, WebhookVerifyToken: "verify-token"}
|
||||
if err := db.Create(&waChannel).Error; err != nil {
|
||||
t.Fatalf("create whatsapp channel: %v", err)
|
||||
}
|
||||
|
||||
waRepo := whatsappchannel.NewRepository(db)
|
||||
waService := whatsappchannel.NewWhatsAppService(waRepo)
|
||||
waPipeline := whatsappchannel.NewIncomingPipeline(waService)
|
||||
waProvider := whatsappchannel.NewWhatsAppProvider(waService, waRepo, waPipeline)
|
||||
waWebhook := whatsappchannel.NewWebhookHandler(waProvider)
|
||||
h := NewWhatsAppWebhookHandler(waProvider, waWebhook, db)
|
||||
r := gin.New()
|
||||
r.POST("/webhooks/whatsapp/:phone_number", h.HandleWhatsAppWebhook)
|
||||
body := []byte(`{"object":"whatsapp_business_account","entry":[{"id":"waba-1","changes":[{"field":"messages","value":{"messaging_product":"whatsapp","metadata":{"display_phone_number":"+15551230000","phone_number_id":"phone-id-1"},"contacts":[{"wa_id":"15550001111","profile":{"name":"WhatsApp User"}}],"messages":[{"from":"15550001111","id":"wamid-missing-sig","timestamp":"1710000000","type":"text","text":{"body":"hello whatsapp"}}]}}]}]}`)
|
||||
req := httptest.NewRequest(http.MethodPost, "/webhooks/whatsapp/+15551230000", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
if w.Code != http.StatusUnauthorized {
|
||||
t.Fatalf("expected 401, got %d body=%s", w.Code, w.Body.String())
|
||||
}
|
||||
var count int64
|
||||
if err := db.Model(&model.Message{}).Where("inbox_id = ? AND source_id = ?", inbox.ID, "wamid-missing-sig").Count(&count).Error; err != nil {
|
||||
t.Fatalf("count message: %v", err)
|
||||
}
|
||||
if count != 0 {
|
||||
t.Fatalf("expected no persisted message, got %d", count)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTikTokWebhookLookupInboxByBusinessIDAndPayloadExtractor(t *testing.T) {
|
||||
db := newWebhookLookupTestDB(t)
|
||||
inbox := seedWebhookInbox(t, db, "tiktok")
|
||||
|
||||
Reference in New Issue
Block a user