diff --git a/backend/handlers/main.go b/backend/handlers/main.go index 0a2937c..65a5367 100644 --- a/backend/handlers/main.go +++ b/backend/handlers/main.go @@ -422,4 +422,60 @@ func DeleteUser(db *gorm.DB) http.HandlerFunc { } w.WriteHeader(http.StatusNoContent) } -} \ No newline at end of file +} + +func HandleTemplateTest(db *gorm.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + val := r.Context().Value("ssoid") + ssoid, ok := val.(string) + if !ok || ssoid == "" { + http.Error(w, "Non authentifié", http.StatusUnauthorized) + return + } + + if err := r.ParseForm(); err != nil { + http.Error(w, "Form invalide", http.StatusBadRequest) + return + } + + to := r.FormValue("to") + templateName := r.FormValue("template_name") + lang := r.FormValue("language") + + var params []string + for i := 1; i <= 5; i++ { + val := r.FormValue(fmt.Sprintf("param%d", i)) + if val != "" { + params = append(params, val) + } + } + + var user models.User + if err := db.Where("sso_id = ?", ssoid).First(&user).Error; err != nil || user.ID == 0 { + http.Error(w, "Utilisateur introuvable", http.StatusUnauthorized) + return + } + + message := models.NewTemplateMessage(to, templateName, lang, params) + jsonBody, _ := json.MarshalIndent(message, "", " ") + + apiURL := fmt.Sprintf("https://graph.facebook.com/v22.0/%s/messages", user.WhatsappPhoneNumberID) + req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonBody)) + if err != nil { + http.Error(w, "Requête WhatsApp échouée", http.StatusInternalServerError) + return + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", "Bearer "+user.WhatsappToken) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + http.Error(w, "Échec de l'appel API WhatsApp", http.StatusBadGateway) + return + } + defer resp.Body.Close() + + io.Copy(w, resp.Body) + } +} diff --git a/backend/models/models.go b/backend/models/models.go index 76ed929..0524c64 100644 --- a/backend/models/models.go +++ b/backend/models/models.go @@ -59,6 +59,25 @@ type MonthlyConsumption struct { Month string `gorm:"type:char(7);index;not null"` // Format YYYY-MM TotalUsed uint `gorm:"not null"` // Crédits utilisés ce mois } +type Template struct { + Name string `json:"name"` + Language TemplateLanguage `json:"language"` + Components []TemplateComponent `json:"components"` +} + +type TemplateLanguage struct { + Code string `json:"code"` +} + +type TemplateComponent struct { + Type string `json:"type"` + Parameters []TemplateParameter `json:"parameters"` +} + +type TemplateParameter struct { + Type string `json:"type"` + Text string `json:"text"` +} type WhatsappMessage struct { MessagingProduct string `json:"messaging_product"` // always "whatsapp" @@ -76,6 +95,7 @@ type WhatsappMessage struct { Contacts []Contact `json:"contacts,omitempty"` Interactive *Interactive `json:"interactive,omitempty"` Reaction *Reaction `json:"reaction,omitempty"` + Template *Template `json:"template,omitempty"` // ✅ Ajoute ce champ } type Address struct { @@ -376,3 +396,45 @@ func BuildMessageFromPayload(payload map[string]interface{}) (interface{}, error return nil, fmt.Errorf("failed to build message") } +func NewTemplateMessage(to, name, lang string, params []string) WhatsappMessage { + paramList := make([]TemplateParameter, len(params)) + for i, p := range params { + paramList[i] = TemplateParameter{ + Type: "text", + Text: p, + } + } + + return WhatsappMessage{ + MessagingProduct: "whatsapp", + To: to, + Type: "template", + Template: &Template{ + Name: name, + Language: TemplateLanguage{Code: lang}, + Components: []TemplateComponent{ + { + Type: "body", + Parameters: paramList, + }, + }, + }, + } +} + +// Enregistre une erreur de statut dans la table Conversation +func SaveMessageStatusError(db *gorm.DB, userID uint, recipient, msgID, status, errorMsg string) error { + conv := Conversation{ + UserID: userID, + From: "system", + To: recipient, + MessageID: msgID, + Type: "status", + Content: errorMsg, + Direction: "outbound", + Status: status, + CreatedAt: time.Now(), + } + return db.Create(&conv).Error +} + diff --git a/backend/routes/routes.go b/backend/routes/routes.go index e452572..869ff49 100644 --- a/backend/routes/routes.go +++ b/backend/routes/routes.go @@ -38,6 +38,7 @@ func RoutesProtected(r *mux.Router, db *gorm.DB) { r.HandleFunc("/admin/user/new", renders.AdminUserCreate()).Methods("GET") r.HandleFunc("/dashboard", renders.Dashboard(db)) r.HandleFunc("/test/send", renders.TestMessagesPages) + r.HandleFunc("/api/message/send", handlers.HandleTemplateTest(db)).Methods("POST") diff --git a/frontend/templates/test-send.pages.tmpl b/frontend/templates/test-send.pages.tmpl new file mode 100644 index 0000000..9e6c352 --- /dev/null +++ b/frontend/templates/test-send.pages.tmpl @@ -0,0 +1,52 @@ +{{ define "test-send.pages.tmpl" }} +{{ template "head" . }} + + +
+
+

📤 Test envoi de message WhatsApp - Template

+ +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+
+
+ +{{ end }}