c# - 如何验证 PayPal Webhook 签名?

标签 c# .net-core paypal cryptography

验证从 PayPal 收到的 Webhook 时遇到问题。可用的示例不多,集成商没有足够的加密知识来完成任务。

遵循的指南是 Webhook notifications .

不确定代码片段有什么问题,结果总是错误的。

调用 notifications/verify-webhook-signature端点也导致错误。

        /// <summary>Verify PayPal Webhook Signature</summary>
        /// <param name="webhookId">0YF54686R9851380C</param>
        /// <param name="transmissionId">785bc690-901d-11ea-8fc5-17f05150a6df</param>
        /// <param name="transmissionTime">2020-05-07T04:44:33Z</param>
        /// <param name="certUrl">https://api.sandbox.paypal.com/v1/notifications/certs/CERT-.....</param>
        /// <param name="transmissionSignature"></param>
        /// <param name="webHookEvent">"{\"id\":\"WH-5P8216093E7920426-60J97470GW748563B\",\"create_time\":\"2020-05-07T11:43:48.000Z\",....</param>
        private static void VerifyWebhookSignature(string webhookId, string transmissionId, string transmissionTime,
            string certUrl, string transmissionSignature, string webHookEvent)
        {
            Crc32 crc32 = new Crc32();
            String hash = string.Empty;

            var arrayOfBytes = Encoding.UTF8.GetBytes(webHookEvent);
            foreach (byte b in crc32.ComputeHash(arrayOfBytes)) hash += b.ToString("x2").ToLower();

            string expectedSignature = String.Format("{0}|{1}|{2}|{3}", transmissionId,
                transmissionTime, webhookId, hash);

            string certData = new System.Net.WebClient().DownloadString(certUrl);
            X509Certificate2 cert = new X509Certificate2(Encoding.UTF8.GetBytes(certData));

            try
            {
                byte[] signature = Convert.FromBase64String(transmissionSignature);
                byte[] expectedBytes = Encoding.UTF8.GetBytes(expectedSignature);

                using (RSA rsa = cert.GetRSAPublicKey())
                {
                    var verified = rsa.VerifyData(
                        expectedBytes,
                        signature,
                        HashAlgorithmName.SHA256,
                        RSASignaturePadding.Pkcs1);

                    Console.WriteLine($"Verified: {verified}");
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

最佳答案

我可以确认您的实现有效,但我不确定您使用哪个实现来计算 CRC32 校验和。使用 Crc32.NET 时以下片段就足够了:

var arrayOfBytes = Encoding.UTF8.GetBytes(webHookEvent);
string hash = Crc32Algorithm.Compute(arrayOfBytes).ToString();

感谢您在这里提供它,我也在努力寻找一个有效的例子!

PS:刚刚在这里发现了官方实现:https://github.com/paypal/PayPal-NET-SDK/blob/master/Source/SDK/Api/WebhookEvent.cs#L156

关于c# - 如何验证 PayPal Webhook 签名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61651765/

相关文章:

PHP 从 PayPal IPN 过滤 POST?

.net - 使用路径前缀在生产中运行 asp.net core 应用程序

c# - 如何配置 owin/Katana 以监听所有主机 ip 地址

c# - 只绘制矩形的角

c# - 从 C# winforms 读取 html

c# - 将 AddNLog 从 .NET Core 2.2 迁移到 3.0

asp.net - `az webapp up` 不再在 dotnet 发布目录中工作

php - Paypal php Rest API,重定向时出现 "Got Http response code 404"错误

php - 如何通过IOS MSDK2.x从paypal获取payer id?

c# - 在 C# 中,如何在不四舍五入的情况下获得所需的小数点数?