Je suis en train d'essayer de mettre en œuvre un webhook à bandes en utilisant la bibliothèque the C# Stripe.net de Jayme Davis. J'ai mis en place le point final de test dans le tableau de bord de bande et généré le secret. Le point de terminaison est en cours d'exécution et génère l'événement StripeEvent à l'aide de StripeEventUtility.ParseEvent. Le problème est avec l'utilisation de la fonction ConstructEvent je ne peux pas faire correspondre les signatures. Toute aide ou suggestion serait grandement appréciée.Échec de la signature webhook Stripe - Stripe.net
isSignaturePresent retourne faux
//call to create event
stripeEvent = ConstructEvent(json, Request.Headers["Stripe-Signature"],
SecretFromStripeDashBoard);
private StripeEvent ConstructEvent(string json, string
stripeSignatureHeader, string secret, int tolerance = 300)
{
var signatureItems = parseStripeSignature(stripeSignatureHeader);
var signature = computeSignature(secret, signatureItems["t"].FirstOrDefault(), json);
if (!isSignaturePresent(signature, signatureItems["v1"]))
throw new Exception("The signature for the webhook is not present in the Stripe-Signature header.");
//var utcNow = EpochUtcNowOverride ?? DateTime.UtcNow.ConvertDateTimeToEpoch();
//var webhookUtc = Convert.ToInt32(signatureItems["t"].FirstOrDefault());
//if (utcNow - webhookUtc > tolerance)
// throw new Exception("The webhook cannot be processed because the current timestamp is above the allowed tolerance.");
return Mapper<StripeEvent>.MapFromJson(json);
}
private ILookup<string, string> parseStripeSignature(string stripeSignatureHeader)
{
return stripeSignatureHeader.Trim()
.Split(',')
.Select(item => item.Trim().Split('='))
.ToLookup(item => item[0], item => item[1]);
}
private bool isSignaturePresent(string signature, IEnumerable<string> signatures)
{
return signatures.Any(key => secureCompare(key, signature));
}
private string computeSignature(string secret, string timestamp, string payload)
{
var secretBytes = Encoding.UTF8.GetBytes(secret);
var payloadBytes = Encoding.UTF8.GetBytes($"{timestamp}.{payload}");
var cryptographer = new HMACSHA256(secretBytes);
var hash = cryptographer.ComputeHash(payloadBytes);
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
private bool secureCompare(string a, string b)
{
if (a.Length != b.Length) return false;
var result = 0;
for (var i = 0; i < a.Length; i++)
{
result |= a[i]^b[i];
}
return result == 0;
}
}
Comment initialisez-vous la variable 'json'? – Ywain
J'utilise var json = JsonSerializer.SerializeToString (request); – stephen
Vous resérialisez donc le corps de requête désérialisé. Cependant, il est très improbable que cela renvoie exactement la même chaîne que le corps de la demande d'origine. Vous devez utiliser le corps de la requête brute tel qu'il a été transmis par votre serveur/framework Web. – Ywain