支付寶異步回調驗證簽名的那些走過的坑

今天作支付寶接口回調這塊,不得不說,弄的我焦頭爛額,翻了不少陳年舊帖,試了無數種解決坑的方案,在我成功解決的一瞬間,以爲很是有必要記錄一下這些坑。異步

簽名驗證錯誤的檢查順序(這裏是基於使用官方給的demo,本身封裝的請繞道):ide

1:檢查一下你使用的驗證簽名的方法是否正確?編碼

bool signVerified = AlipaySignature.RSACheckV1(dic, alipay_public_key, config.charset);

 

2:檢查一下你傳入的參數是否正確?加密

參數1:dic,把回調的參數保存到key,value集合中spa

Dictionary<string, string> dic = new Dictionary<string, string>();
var form = HttpContext.Current.Request.Form;
string str = "異步通知:\r\n";
foreach (var key in form)
{
   dic[key.ToString()] = HttpContext.Current.Request.Form[key.ToString()];
   var value = HttpContext.Current.Request.Form[key.ToString()];
   //記錄日誌使用
   str += $"{key.ToString()}:{value}\r\n";
}

參數2:alipay_public_key日誌

這個參數是 支付寶公鑰!!   不少小夥伴都寫成了應用公鑰,瞎幾把寫。code

參數3:編碼格式,UTF-8,這個通常沒人會錯。orm

 

3:檢查一下你的環境,沙盒環境仍是線上環境,沙盒環境會出錯,具體爲何我不知道,百度來的。要在支付寶中給你的回調域名受權,不受權人家懶得回調給你。blog

 

4:檢查一下你的加密解密類型,我從官網下載下來的demo裏面的解密類型默認是RSA,可是官方文檔已經明確說明如今都要用RSA2了,因此記得檢查demo的源碼接口

public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem, string charset)
{
   string sign = parameters["sign"];
   string sign_type = parameters["sign_type"];
   parameters.Remove("sign");
   parameters.Remove("sign_type");
   string signContent = GetSignContent(parameters);
   return RSACheckContent(signContent, sign, publicKeyPem, charset, sign_type);
}

sign_type,這個就是解碼類型,demo寫的好像「RSA」,我這裏改爲動態獲取了,咱們在前期配置的地方也會配置加密類型,從哪獲取均可以,別弄錯了就行。

 

5:這裏不檢查了,回憶一下你的支付寶公鑰,是直接存在文本中的,仍是寫在代碼裏的(區別:公鑰.txt,string 公鑰 = 「巴拉巴拉巴拉一大堆」),一個是文件,一個是直接代碼(我就是代碼,因此我一直到最後才解決)(下面的解決方案只針對代碼保存支付寶公鑰的騷年)

string alipay_public_key = "-----BEGIN PUBLIC KEY-----\r\n" + config.alipay_public_key + "-----END PUBLIC KEY-----\r\n\r\n";
bool signVerified = AlipaySignature.RSACheckV1(dic, alipay_public_key, config.charset);

若是是直接寫在代碼中的,要給支付寶公鑰的頭跟尾加上標識,具體標識看我貼出來的代碼,若是是文件,請自動忽略

還沒結束,官方給的demo也是默認找的文件,但是我用的代碼存的,哪有文件,因此找不到文件是會報錯的,報錯直接返回false了,在修改一下源碼(本身到AlipaySignature這個類裏面去找)

public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset, string signType)
{

    try
    {
        if (string.IsNullOrEmpty(charset))
        {
            charset = DEFAULT_CHARSET;
        }

        if ("RSA2".Equals(signType))
        {
            //這裏就是要改的地方
            //從參數獲取
            string sPublicKeyPEM = publicKeyPem;
            //從文件獲取
            //string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.PersistKeyInCsp = false;
            RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);

            bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), "SHA256", Convert.FromBase64String(sign));
            return bVerifyResultOriginal;

        }
        else
        {
            //這裏就是要改的地方
            //從參數獲取
            string sPublicKeyPEM = publicKeyPem;
            //從文件獲取
            //string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.PersistKeyInCsp = false;
            RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);

            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
            bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), sha1, Convert.FromBase64String(sign));
            return bVerifyResultOriginal;
        }

    }
    catch (Exception e)
    {
        NLogGetter.NLog.ErrorLog(e);
        return false;
    }

}

好了,差很少就總結了這麼多,基本上可讓你簽名驗證成功了。

相關文章
相關標籤/搜索