【问题标题】:Adyen, Unable to get correct SHA-256 encryptionAdyen,无法获得正确的 SHA-256 加密
【发布时间】:2017-09-25 09:50:55
【问题描述】:

我正在使用签名字符串和私钥来生成使用 SHA-256 加密的公钥。

散列函数是标准的 C# SHA-256 散列函数:

string CalculateHMAC256(string hmacKey, string signingstring)
    {
        byte[] key = Encoding.UTF8.GetBytes(hmacKey);
        byte[] data = Encoding.UTF8.GetBytes(signingstring);
        using (HMACSHA256 hmac = new HMACSHA256(key))
        {
            byte[] result = hmac.ComputeHash(data);
            return Convert.ToBase64String(result);
        }
    }

字符串签名如下所示: allowedMethods:blockedMethods:countryCode:currencyCode:merchantAccount:merchantReference:offset:orderData:paymentAmount:sessionValidity:shipBeforeDate:shopperEmail:shopperLocale:shopperReference:skinCode:::GB:GBP:MyTest:abc:::1:2017-04-28T15: 07:10+01:00:2017-04-30::en_US::neDRF4H4

我也按照建议使用转义的 ':' 进行了尝试: allowedMethods:blockedMethods:countryCode:currencyCode:merchantAccount:merchantReference:offset:orderData:paymentAmount:sessionValidity:shipBeforeDate:shopperEmail:shopperLocale:shopperReference:skinCode:::GB:GBP:MyTest:abc:::1:2017-04-29T13: 34:48+01:00:2017-05-01::en_US::neDRF4H4

然后我的 html 表单如下所示:

 <form ngNoForm name="frmsp" id="frmsp" target="_blank" 
    action="https://test.barclaycardsmartpay.com/hpp/pay.shtml"
    method="post">
    <input type="hidden" name="merchantSig" [value]="merchantSignature" />
    <input type="hidden" name="currencyCode" [value]="smartPayment?.currencyCode" />
    <input type="hidden" name="merchantAccount" [value]="smartPayment?.merchantAccount" />
    <input type="hidden" name="merchantReference" [value]="smartPayment?.merchantReference" />
    <input type="hidden" name="paymentAmount" [value]="smartPayment?.paymentAmount" />
    <input type="hidden" name="sessionValidity" [value]="smartPayment?.sessionValidity" />
    <input type="hidden" name="shipBeforeDate" [value]="smartPayment?.shipBeforeDate" />
    <input type="hidden" name="shopperLocale" [value]="smartPayment?.shopperLocale" />
    <input type="hidden" name="orderData" [value]="smartPayment?.orderData" />
    <input type="hidden" name="skinCode" [value]="smartPayment?.skinCode" />
    <input type="hidden" name="countryCode" [value]="smartPayment?.countryCode" />
    <input type="hidden" name="shopperEmail" [value]="smartPayment?.shopperEmail" />
    <input type="hidden" name="shopperReference" [value]="smartPayment?.shopperReference" />
    <input type="hidden" name="allowedMethods" [value]="smartPayment?.allowedMethods" />
    <input type="hidden" name="blockedMethods" [value]="smartPayment?.blockedMethods" />
    <input type="hidden" name="offset" [value]="smartPayment?.offset" />    
    <input type="submit" value="Process Payment" (click)="buttonClicked()">

使用 angular2 计算字段值的位置 - 使用用于构建签名字符串的相同值,因此我确信数据匹配。

当我发送表单时,我收到一条错误消息,指出商家签名不正确。

也许签名字符串的格式不正确? 我正在尝试使用托管支付来调用 Barclaycard Smartpay。此处的文档: 托管支付页面集成指南

注意:barclays 文档已过时(最后更新于 2012 年),并且对 SHA-1 的引用现在使用 SHA-256。它是使用 Adyen 支付系统构建的,我使用以下示例代码重用了字符串生成示例:https://github.com/Adyen/adyen-asp.net-sample-code

【问题讨论】:

  • 我现在也在做同样的事情 :) 你试过 checkhmac 页面上的表格吗? ca-test.adyen.com/ca/ca/skin/checkhmac.shtml
  • 超级好,希望我们能一起解决这个问题。我做到了。我可以通过在该页面上生成签名然后创建一个类似于上面的 html 表单来匹配测试页面中的这些值来使其工作。问题来了,我永远无法获得与该页面上生成的签名相匹配的商家签名。 (我其实用的是barclays smartpay测试页面,我想和你说的页面基本一致)。
  • 您是否将您的签名字符串与测试页面上生成的签名字符串进行了比较?我看到您的签名字符串包含“:”,应该替换为“\:”
  • 我尝试了以下签名字符串: allowedMethods\:blockedMethods\:countryCode\:currencyCode\:merchantAccount\:merchantReference\:offset\:orderData\:paymentAmount\:sessionValidity\:shipBeforeDate\: shopperEmail\:shopperLocale\:shopperReference\:skinCode\:\:\:GB\:GBP\:MyTest\:abc\:\:\:1\:2017-04-29T13\:34\:48+01\: 00\:2017-05-01\:\:en_US\:\:neDRF4H4 我需要在 html 表单中转义日期吗?我尝试使用测试页面中的签名字符串,然后使用该签名字符串获取签名,但这给了我不正确的 SHA-256 加密。
  • 您只需要替换值中的“:”! “:”用作分隔符。

标签: c# encryption sha payment-processing adyen


【解决方案1】:

您的签名字符串有问题。您需要将所有值中的“\”替换为“\”,将“:”替换为“:”。

我还建议在GIT 上使用此示例中的代码来生成您的加密签名。

使用下面的代码,我得到的签名与 Adyen 提供的测试页上的签名相同。

 // Computes the Base64 encoded signature using the HMAC algorithm with the HMACSHA256 hashing function.
    string CalculateHMAC(string hmacKey, string signingstring)
{
    byte[] key = PackH(hmacKey);
    byte[] data = Encoding.UTF8.GetBytes(signingstring);

    try
    {
        using (HMACSHA256 hmac = new HMACSHA256(key))
        {
            // Compute the hmac on input data bytes
            byte[] rawHmac = hmac.ComputeHash(data);

            // Base64-encode the hmac
            return Convert.ToBase64String(rawHmac);
        }
    }
    catch (Exception e)
    {
        throw new Exception("Failed to generate HMAC : " + e.Message);
    }
}

byte[] PackH(string hex)
{
    if ((hex.Length % 2) == 1)
    {
        hex += '0';
    }

    byte[] bytes = new byte[hex.Length / 2];
    for (int i = 0; i < hex.Length; i += 2)
    {
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    }

    return bytes;
}

尝试只使用有限数量的字段,看看是否有任何结果。 我使用了下面的字段(还要考虑它们的顺序!)

currencyCode:merchantAccount:merchantReference:paymentAmount:sessionValidity:shipBeforeDate:shopperLocale:skinCode

【讨论】:

  • 你是我的英雄。谢谢ThdK!我已经坚持了这么久。实际上,我的代码中有另一种方法,但是当我的字符串没有正确转义时,它就不起作用了。也许您还可以在答案中提及转义。
猜你喜欢
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 2014-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
相关资源
最近更新 更多