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


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

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

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

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

 

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

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

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

這個參數是 支付寶公鑰!!   很多小伙伴都寫成了應用公鑰,瞎幾把寫。

參數3:編碼格式,UTF-8,這個一般沒人會錯。

 

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

 

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;
    }

}

好了,差不多就總結了這么多,基本上可以讓你簽名驗證成功了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM