import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"encoding/json"
"io"
"net/http"
"os"
)
// Verify the Waffo signature
func verifyWaffoSignature(body string, signature string) bool {
pubKeyPEM := []byte(os.Getenv("WAFFO_PUBLIC_KEY"))
block, _ := pem.Decode(pubKeyPEM)
pubKey, _ := x509.ParsePKIXPublicKey(block.Bytes)
sig, _ := base64.StdEncoding.DecodeString(signature)
hash := sha256.Sum256([]byte(body))
err := rsa.VerifyPKCS1v15(pubKey.(*rsa.PublicKey), crypto.SHA256, hash[:], sig)
return err == nil
}
// Sign the merchant response
func signResponse(responseBody string) string {
privKeyPEM := []byte(os.Getenv("MERCHANT_PRIVATE_KEY"))
block, _ := pem.Decode(privKeyPEM)
privKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
hash := sha256.Sum256([]byte(responseBody))
sig, _ := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA256, hash[:])
return base64.StdEncoding.EncodeToString(sig)
}
func webhookHandler(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
signature := r.Header.Get("X-SIGNATURE")
if !verifyWaffoSignature(string(body), signature) {
failedBody, _ := json.Marshal(map[string]string{"message": "failed"})
w.Header().Set("X-SIGNATURE", signResponse(string(failedBody)))
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
w.Write(failedBody)
return
}
// Process the event...
successBody, _ := json.Marshal(map[string]string{"message": "success"})
w.Header().Set("X-SIGNATURE", signResponse(string(successBody)))
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
w.Write(successBody)
}