Go Example
Go presents unique challenges due to non-deterministic map key ordering. The signature validation requires consistent field ordering, which
map[string]interface{}cannot guarantee.
Recommended Approaches
Option 1: Define a struct with explicit field order
This requires knowing Aeropay's exact field order.
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"strings"
)
type WebhookPayload struct {
Topic string `json:"topic"`
Data map[string]interface{} `json:"data"`
PayloadVersion string `json:"payloadVersion"`
Date string `json:"date"`
URL string `json:"url"`
}
func validateWebhook(receivedSig string, body []byte, signingKey string, webhookURL string) bool {
// Parse webhook body
var payload WebhookPayload
json.Unmarshal(body, &payload)
// Add URL
payload.URL = webhookURL
// Marshal to JSON with spacing
jsonBytes, _ := json.Marshal(payload)
payloadStr := string(jsonBytes)
// Add spaces to match Python formatting
payloadStr = strings.ReplaceAll(payloadStr, "\":", "\": ")
payloadStr = strings.ReplaceAll(payloadStr, ",\"", ", \"")
// Compute signature
mac := hmac.New(sha256.New, []byte(signingKey))
mac.Write([]byte(payloadStr))
expectedSig := hex.EncodeToString(mac.Sum(nil))
// Constant-time comparison
return hmac.Equal([]byte(receivedSig), []byte(expectedSig))
}
Option 2: Use an ordered-map library
Use a library like github.com/iancoleman/orderedmap to preserve key order when parsing JSON.
Option 3: Use Python or Node.js
Due to the complexity of Go's JSON serialization for this use case, we recommend Python or Node.js for webhook validation unless you have specific Go requirements.
Regardless of approach, you must test your implementation thoroughly against real sandbox webhooks to verify it produces signatures matching Aeropay's format.
Updated about 9 hours ago
