1. HMAC-SHA512
This is the default method. Each event payload is signed using HMAC-SHA512 with your provided signing_key
. The signature is sent in the xpay-signature
header.
private boolean verifySignature(String incomingSignature, String payload, String secret) throws Exception {
Mac sha512Hmac = Mac.getInstance("HmacSHA512");
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA512");
sha512Hmac.init(keySpec);
byte[] macData = sha512Hmac.doFinal(payload.getBytes("UTF-8"));
incomingSignature.equals(Base64.getEncoder().encodeToString(macData));
}
2. ECDSA
xPay supports ECDSA signature verification for webhooks. The signature is sent in the xpay-private-signature
header, and the public key is provided below.
xPay Webhook Public Key
This is the public key used for webhook signature verification. The key below is base64 encoded. You can use this key to verify ECDSA signatures from xPay webhooks.
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBlXbsIwGSYhdXBOtdrZr3L346JXi3dOg8vP9NCcTOV0ucLVl/GPi2ZVMsdBISQKTGIhzXY/gddRl846C27TfPw==
import java.security.*;
import java.security.spec.*;
import java.util.Base64;
public class WebhookVerifier {
public static boolean verifySignature(String publicKeyBase64, String signatureBase64, String payload) throws Exception {
byte[] publicBytes = Base64.getDecoder().decode(publicKeyBase64);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature ecdsaVerify = Signature.getInstance("SHA256withECDSA");
ecdsaVerify.initVerify(pubKey);
ecdsaVerify.update(payload.getBytes("UTF-8"));
byte[] signatureBytes = Base64.getDecoder().decode(signatureBase64);
return ecdsaVerify.verify(signatureBytes);
}
public static void main(String[] args) throws Exception {
String publicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBlXbsIwGSYhdXBOtdrZr3L346JXi3dOg8vP9NCcTOV0ucLVl/GPi2ZVMsdBISQKTGIhzXY/gddRl846C27TfPw==";
String signature = "MEUCIQDncKxd1HEthoRD/+kX2Kw0ZKRbaewtX9IfvW5vE/MPMwIgZ/BLckOaRkHqP3mtIX4DQRRKLXvmt9mmWG3mKMNUZPI=";
String payload = "{\"eventId\":\"whe_g00AGgDy9KeiTPj6\",...}";
boolean isValid = verifySignature(publicKey, signature, payload);
System.out.println("Signature valid: " + isValid);
}
}
{
"xpay-signature" : "s3z2v3ZGwMvDwiQ+9PpAT3WuSYU+PeSZJqvdzZXPmifAh3sT+s502PgJJx9NV4KQaScEaquTEuHJ30v17hK5GA==",
"xpay-private-signature" : "MEYCIQD+649oWWsMkVbTcOsfkxKvxsnbAPbeq0QHptC2i1dFuwIhALN5GHEliiv+MT3/5a2ye8Wbud5rFNDRIMz6ExgWAaYg",
...
}