Files
Crussell/backend/handlers/webhooks/square.go
T

80 lines
2.1 KiB
Go

package webhooks
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"io"
"log"
"net/http"
"os"
)
type SquareWebhookEvent struct {
Type string `json:"type"`
EventID string `json:"event_id"`
CreatedAt string `json:"created_at"`
Data json.RawMessage `json:"data"`
LocationID string `json:"location_id"`
}
func HandleSquareWebhook(w http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(w, r.Body, 512*1024)
body, err := io.ReadAll(r.Body)
if err != nil {
log.Printf("Failed to read webhook body: %v", err)
http.Error(w, "request body too large or unreadable", http.StatusRequestEntityTooLarge)
return
}
defer r.Body.Close()
signature := r.Header.Get("x-square-signature")
signingKey := os.Getenv("SQUARE_WEBHOOK_SIGNATURE_KEY")
if signingKey != "" && signature != "" {
if !verifySquareSignature(body, signature, signingKey) {
log.Printf("Invalid Square webhook signature")
http.Error(w, "Invalid signature", http.StatusForbidden)
return
}
}
var event SquareWebhookEvent
if err := json.Unmarshal(body, &event); err != nil {
log.Printf("Failed to parse webhook event: %v", err)
http.Error(w, "Invalid event", http.StatusBadRequest)
return
}
log.Printf("[SQUARE-WEBHOOK] Received event: %s", event.Type)
switch event.Type {
case "payment.updated":
handlePaymentUpdated(event.Data)
case "refund.updated":
handleRefundUpdated(event.Data)
case "dispute.created":
log.Printf("[SQUARE-WEBHOOK] Dispute created: %s", event.EventID)
default:
log.Printf("[SQUARE-WEBHOOK] Unknown event type: %s", event.Type)
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}
func verifySquareSignature(body []byte, signature, signingKey string) bool {
mac := hmac.New(sha256.New, []byte(signingKey))
mac.Write(body)
expected := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(signature), []byte(expected))
}
func handlePaymentUpdated(data json.RawMessage) {
log.Printf("[SQUARE-WEBHOOK] payment.updated: %s", string(data))
}
func handleRefundUpdated(data json.RawMessage) {
log.Printf("[SQUARE-WEBHOOK] refund.updated: %s", string(data))
}