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.