feat(webhook): align chatwoot ingress routes
This commit is contained in:
@@ -4,17 +4,19 @@ package webhook
|
||||
// Reference: Facebook webhook adapter pattern (facebook_webhook.go)
|
||||
//
|
||||
// URL patterns:
|
||||
// /webhooks/twilio/sms/:inbox_id — inbound SMS/MMS
|
||||
// /webhooks/twilio/status/:inbox_id — delivery status callbacks
|
||||
// /webhooks/sms/:phone_number — Chatwoot-compatible inbound SMS/MMS
|
||||
// /webhooks/twilio/sms/:phone_number — legacy inbound SMS/MMS
|
||||
// /webhooks/twilio/status/:phone_number — delivery status callbacks
|
||||
//
|
||||
// Method: POST (Twilio sends form-encoded data, not JSON)
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
twiliochannel "github.com/gochat/gochat/internal/channel/twilio"
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
channelmodel "github.com/gochat/gochat/internal/model/channel"
|
||||
applogger "github.com/gochat/gochat/pkg/logger"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -37,18 +39,17 @@ func NewTwilioWebhookHandler(twilioWebhook *twiliochannel.WebhookHandler, db *go
|
||||
|
||||
// HandleTwilioInboundSMS processes an incoming Twilio SMS webhook Gin request.
|
||||
func (h *TwilioWebhookHandler) HandleTwilioInboundSMS(c *gin.Context) {
|
||||
inboxIDStr := c.Param("inbox_id")
|
||||
inboxID, err := strconv.ParseUint(inboxIDStr, 10, 32)
|
||||
if err != nil {
|
||||
applogger.L().Warnf("Twilio webhook: invalid inbox_id %s", inboxIDStr)
|
||||
phoneNumber := c.Param("phone_number")
|
||||
if phoneNumber == "" {
|
||||
applogger.L().Warn("Twilio webhook: missing phone_number in path")
|
||||
c.Data(http.StatusOK, "application/xml", []byte("<Response></Response>"))
|
||||
return
|
||||
}
|
||||
|
||||
// Lookup inbox from database
|
||||
inbox, err := h.lookupInbox(uint(inboxID))
|
||||
inbox, err := h.lookupInboxByPhoneNumber(phoneNumber)
|
||||
if err != nil {
|
||||
applogger.L().Warnf("Twilio webhook: inbox lookup failed for id %d: %v", inboxID, err)
|
||||
applogger.L().Warnf("Twilio webhook: inbox lookup failed for phone_number %s: %v", phoneNumber, err)
|
||||
c.Data(http.StatusOK, "application/xml", []byte("<Response></Response>"))
|
||||
return
|
||||
}
|
||||
@@ -60,18 +61,17 @@ func (h *TwilioWebhookHandler) HandleTwilioInboundSMS(c *gin.Context) {
|
||||
|
||||
// HandleTwilioDeliveryStatus processes a Twilio delivery status callback.
|
||||
func (h *TwilioWebhookHandler) HandleTwilioDeliveryStatus(c *gin.Context) {
|
||||
inboxIDStr := c.Param("inbox_id")
|
||||
inboxID, err := strconv.ParseUint(inboxIDStr, 10, 32)
|
||||
if err != nil {
|
||||
applogger.L().Warnf("Twilio status webhook: invalid inbox_id %s", inboxIDStr)
|
||||
phoneNumber := c.Param("phone_number")
|
||||
if phoneNumber == "" {
|
||||
applogger.L().Warn("Twilio status webhook: missing phone_number in path")
|
||||
c.Status(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
// Lookup inbox from database
|
||||
inbox, err := h.lookupInbox(uint(inboxID))
|
||||
inbox, err := h.lookupInboxByPhoneNumber(phoneNumber)
|
||||
if err != nil {
|
||||
applogger.L().Warnf("Twilio status webhook: inbox lookup failed for id %d: %v", inboxID, err)
|
||||
applogger.L().Warnf("Twilio status webhook: inbox lookup failed for phone_number %s: %v", phoneNumber, err)
|
||||
c.Status(http.StatusOK)
|
||||
return
|
||||
}
|
||||
@@ -87,4 +87,23 @@ func (h *TwilioWebhookHandler) lookupInbox(inboxID uint) (*model.Inbox, error) {
|
||||
return nil, err
|
||||
}
|
||||
return &inbox, nil
|
||||
}
|
||||
}
|
||||
|
||||
// lookupInboxByPhoneNumber fetches an Inbox through the Twilio SMS channel record.
|
||||
// Chatwoot exposes /webhooks/sms/:phone_number and routes by the phone number.
|
||||
func (h *TwilioWebhookHandler) lookupInboxByPhoneNumber(phoneNumber string) (*model.Inbox, error) {
|
||||
if h.db == nil {
|
||||
return nil, fmt.Errorf("twilio webhook database is not configured")
|
||||
}
|
||||
|
||||
var channel channelmodel.ChannelTwilioSMS
|
||||
if err := h.db.Where("phone_number = ?", phoneNumber).First(&channel).Error; err != nil {
|
||||
return nil, fmt.Errorf("twilio sms channel not found for phone_number=%s: %w", phoneNumber, err)
|
||||
}
|
||||
|
||||
var inbox model.Inbox
|
||||
if err := h.db.Where("id = ? AND channel_type IN ?", channel.InboxID, []string{"twilio_sms", "sms"}).First(&inbox).Error; err != nil {
|
||||
return nil, fmt.Errorf("twilio inbox not found for channel inbox_id=%d: %w", channel.InboxID, err)
|
||||
}
|
||||
return &inbox, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user