package whatsapp import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/model" channelmodel "github.com/gochat/gochat/internal/model/channel" "gorm.io/driver/sqlite" "gorm.io/gorm" ) func newWhatsAppWebhookTestDB(t *testing.T) *gorm.DB { t.Helper() db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) if err != nil { t.Fatalf("open sqlite: %v", err) } if err := db.AutoMigrate(&model.Inbox{}, &channelmodel.ChannelWhatsApp{}); err != nil { t.Fatalf("migrate whatsapp models: %v", err) } return db } func TestWhatsAppWebhookLookupByVerifyToken(t *testing.T) { db := newWhatsAppWebhookTestDB(t) inbox := model.Inbox{AccountID: 1, Name: "wa", ChannelType: "whatsapp", ChannelID: 1, Enabled: true} if err := db.Create(&inbox).Error; err != nil { t.Fatalf("create inbox: %v", err) } channel := channelmodel.ChannelWhatsApp{ AccountID: 1, InboxID: inbox.ID, PhoneNumber: "+15551234567", PhoneNumberID: "phone-number-id", AccessToken: "access-token", Provider: "whatsapp_cloud", WebhookVerifyToken: "verify-token", ProviderConfig: `{"app_secret":"app-secret"}`, BusinessAccountID: "waba-id", WhatsAppAccountName: "WA", } if err := db.Create(&channel).Error; err != nil { t.Fatalf("create whatsapp channel: %v", err) } repo := NewRepository(db) provider := NewWhatsAppProvider(nil, repo, nil) h := NewWebhookHandler(provider) found, err := h.lookupByVerifyToken("verify-token") if err != nil { t.Fatalf("lookup verify token: %v", err) } if found.ID != channel.ID { t.Fatalf("unexpected channel id: %d", found.ID) } if secret := resolveCloudAppSecret(found); secret != "app-secret" { t.Fatalf("unexpected app secret: %q", secret) } } func TestWhatsAppCloudSignatureUsesAppSecret(t *testing.T) { gin.SetMode(gin.TestMode) body := []byte(`{"object":"whatsapp_business_account"}`) mac := hmac.New(sha256.New, []byte("app-secret")) mac.Write(body) signature := "sha256=" + hex.EncodeToString(mac.Sum(nil)) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodPost, "/webhooks/whatsapp/phone", nil) c.Request.Header.Set("X-Hub-Signature-256", signature) h := NewWebhookHandler(nil) if err := h.verifyCloudSignature(c, body, "app-secret"); err != nil { t.Fatalf("verify signature: %v", err) } if err := h.verifyCloudSignature(c, body, "wrong-secret"); err == nil { t.Fatal("expected wrong app secret to fail") } }