mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-18 11:02:54 +00:00
feat: Add webhook client for carrier connector profile event notifications to API server
- Add WebhookClient struct with httpClient (10s timeout), webhookURL, and apiKey fields - Add WebhookEvent struct with event_type, timestamp, profile_iccid, and data fields - Add event type constants (profile.downloaded, activated, deactivated, deleted, status_changed, download.failed) - Add SendNotification method with JSON marshaling, Bearer token auth, and error handling for 4xx/5xx responses - Add helper
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// WebhookClient sends notifications to the api-server
|
||||
type WebhookClient struct {
|
||||
httpClient *http.Client
|
||||
webhookURL string
|
||||
apiKey string
|
||||
}
|
||||
|
||||
// NewWebhookClient creates a new webhook client
|
||||
func NewWebhookClient(webhookURL, apiKey string) *WebhookClient {
|
||||
return &WebhookClient{
|
||||
httpClient: &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
},
|
||||
webhookURL: webhookURL,
|
||||
apiKey: apiKey,
|
||||
}
|
||||
}
|
||||
|
||||
// WebhookEvent represents a webhook notification event
|
||||
type WebhookEvent struct {
|
||||
EventType string `json:"event_type"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
ProfileICCID string `json:"profile_iccid"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// Event types
|
||||
const (
|
||||
EventProfileDownloaded = "profile.downloaded"
|
||||
EventProfileActivated = "profile.activated"
|
||||
EventProfileDeactivated = "profile.deactivated"
|
||||
EventProfileDeleted = "profile.deleted"
|
||||
EventProfileStatusChange = "profile.status_changed"
|
||||
EventDownloadFailed = "download.failed"
|
||||
)
|
||||
|
||||
// SendNotification sends a webhook notification to the api-server
|
||||
func (w *WebhookClient) SendNotification(ctx context.Context, event *WebhookEvent) error {
|
||||
if w.webhookURL == "" {
|
||||
return nil // Webhook disabled
|
||||
}
|
||||
|
||||
payload, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal webhook event: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", w.webhookURL, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create webhook request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if w.apiKey != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+w.apiKey)
|
||||
}
|
||||
|
||||
resp, err := w.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send webhook: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
return fmt.Errorf("webhook returned status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendProfileDownloaded sends a notification when a profile is downloaded
|
||||
func (w *WebhookClient) SendProfileDownloaded(ctx context.Context, iccid string, data map[string]interface{}) error {
|
||||
event := &WebhookEvent{
|
||||
EventType: EventProfileDownloaded,
|
||||
Timestamp: time.Now(),
|
||||
ProfileICCID: iccid,
|
||||
Data: data,
|
||||
}
|
||||
return w.SendNotification(ctx, event)
|
||||
}
|
||||
|
||||
// SendProfileActivated sends a notification when a profile is activated
|
||||
func (w *WebhookClient) SendProfileActivated(ctx context.Context, iccid string, data map[string]interface{}) error {
|
||||
event := &WebhookEvent{
|
||||
EventType: EventProfileActivated,
|
||||
Timestamp: time.Now(),
|
||||
ProfileICCID: iccid,
|
||||
Data: data,
|
||||
}
|
||||
return w.SendNotification(ctx, event)
|
||||
}
|
||||
|
||||
// SendProfileDeleted sends a notification when a profile is deleted
|
||||
func (w *WebhookClient) SendProfileDeleted(ctx context.Context, iccid string, data map[string]interface{}) error {
|
||||
event := &WebhookEvent{
|
||||
EventType: EventProfileDeleted,
|
||||
Timestamp: time.Now(),
|
||||
ProfileICCID: iccid,
|
||||
Data: data,
|
||||
}
|
||||
return w.SendNotification(ctx, event)
|
||||
}
|
||||
|
||||
// SendDownloadFailed sends a notification when a profile download fails
|
||||
func (w *WebhookClient) SendDownloadFailed(ctx context.Context, iccid string, errorMessage string) error {
|
||||
event := &WebhookEvent{
|
||||
EventType: EventDownloadFailed,
|
||||
Timestamp: time.Now(),
|
||||
ProfileICCID: iccid,
|
||||
Data: map[string]interface{}{
|
||||
"error": errorMessage,
|
||||
},
|
||||
}
|
||||
return w.SendNotification(ctx, event)
|
||||
}
|
||||
Reference in New Issue
Block a user