http.HandleFunc("/webhook", func(w http.ResponseWriter, req *http.Request) {
const MaxBodyBytes = int64(65536)
req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes)
payload, err := ioutil.ReadAll(req.Body)
fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err)
w.WriteHeader(http.StatusServiceUnavailable)
requestSignature := req.Header.Get("X-Reloadly-Signature")
requestTimestamp := req.Header.Get("X-Reloadly-Request-Timestamp")
// Find your webhooks signing key in your webhook settings in your
signingKey := "put_your_webhooks_signing_key_here...";
dataToSign := request + ":" + strconv.Itoa(requestTimestamp)
// Create a new HMAC by defining the hash type and the key (as byte array)
hash, err := hmac.New(sha256.New, []byte(signingKey))
fmt.Fprintf(os.Stderr, "Error generating signature: %v\n", err)
// Return a 400 error on a bad signature
w.WriteHeader(http.StatusBadRequest)
hash.Write([]byte(dataToSign))
// Get result and encode as hexadecimal string
computedSignature := hex.EncodeToString(hash.Sum(nil))
if computedSignature != requestSignature {
fmt.Fprintf(os.Stderr, "Error invalid signature: %v\n", err)
// Return a 400 error on a bad signature
w.WriteHeader(http.StatusBadRequest)
// Unmarshal the event request into an appropriate struct depending on its Type
case "airtime_transaction.status":
var airtimeTransaction := AirtimeTransactionStruct{}
err := json.Unmarshal(event.Data, &airtimeTransaction)
fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
w.WriteHeader(http.StatusBadRequest)
fmt.Println("Processing airtime transaction!")
case "giftcard_transaction.status":
var giftcardTransaction := GiftCardTransactionStruct{}
err := json.Unmarshal(event.Data, &giftcardTransaction)
fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
w.WriteHeader(http.StatusBadRequest)
fmt.Println("Processing giftcard transaction!")
// ... handle other event types
fmt.Fprintf(os.Stderr, "Unhandled event type: %s\n", event.Type)
w.WriteHeader(http.StatusOK)