Browse Source

IAlipayNotifyClient 新增 CertificateExecuteAsync

Roc 5 years ago
parent
commit
1af50952de

+ 48 - 2
src/Essensoft.AspNetCore.Payment.Alipay/AlipayNotifyClient.cs

@@ -35,9 +35,9 @@ namespace Essensoft.AspNetCore.Payment.Alipay
                 throw new ArgumentNullException(nameof(options.SignType));
             }
 
-            if (string.IsNullOrEmpty(options.AppPrivateKey))
+            if (string.IsNullOrEmpty(options.AlipayPublicKey))
             {
-                throw new ArgumentNullException(nameof(options.AppPrivateKey));
+                throw new ArgumentNullException(nameof(options.AlipayPublicKey));
             }
 
             var parameters = GetParameters(request);
@@ -48,6 +48,33 @@ namespace Essensoft.AspNetCore.Payment.Alipay
 
         #endregion
 
+        #region IAlipayNotifyClient Members
+
+        public Task<T> CertificateExecuteAsync<T>(HttpRequest request, AlipayOptions options) where T : AlipayNotify
+        {
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            if (string.IsNullOrEmpty(options.SignType))
+            {
+                throw new ArgumentNullException(nameof(options.SignType));
+            }
+
+            if (string.IsNullOrEmpty(options.AlipayPublicCert))
+            {
+                throw new ArgumentNullException(nameof(options.AlipayPublicCert));
+            }
+
+            var parameters = GetParameters(request);
+            var rsp = AlipayDictionaryParser.Parse<T>(parameters);
+            CheckNotifySignCertificate(parameters, options);
+            return Task.FromResult(rsp);
+        }
+
+        #endregion
+
         #region Common Method
 
         private Dictionary<string, string> GetParameters(HttpRequest request)
@@ -89,6 +116,25 @@ namespace Essensoft.AspNetCore.Payment.Alipay
             }
         }
 
+        private void CheckNotifySignCertificate(IDictionary<string, string> dictionary, AlipayOptions options)
+        {
+            if (dictionary == null || dictionary.Count == 0)
+            {
+                throw new AlipayException("sign check fail: dictionary is Empty!");
+            }
+
+            if (!dictionary.TryGetValue("sign", out var sign))
+            {
+                throw new AlipayException("sign check fail: sign is Empty!");
+            }
+
+            var prestr = GetSignContent(dictionary);
+            if (!AlipaySignature.RSACheckContent(prestr, sign, options.AlipayPublicCertificate, options.SignType))
+            {
+                throw new AlipayException("sign check fail: check Sign Data Fail!");
+            }
+        }
+
         private static string GetSignContent(IDictionary<string, string> dictionary)
         {
             if (dictionary == null || dictionary.Count == 0)

+ 3 - 3
src/Essensoft.AspNetCore.Payment.Alipay/AlipayOptions.cs

@@ -82,9 +82,9 @@ namespace Essensoft.AspNetCore.Payment.Alipay
             get => appCert;
             set
             {
-                appCert = value;
                 if (!string.IsNullOrEmpty(value))
                 {
+                    appCert = value;
                     var cert = AntCertificationUtil.ParseCert(value);
                     AppCertSN = AntCertificationUtil.GetCertSN(cert);
                 }
@@ -99,9 +99,9 @@ namespace Essensoft.AspNetCore.Payment.Alipay
             get => alipayPublicCert;
             set
             {
-                alipayPublicCert = value;
                 if (!string.IsNullOrEmpty(value))
                 {
+                    alipayPublicCert = value;
                     AlipayPublicCertificate = AntCertificationUtil.ParseCert(value);
                     AlipayPublicCertSN = AntCertificationUtil.GetCertSN(AlipayPublicCertificate);
                     AlipayPublicCertKey = AntCertificationUtil.ExtractPemPublicKeyFromCert(AlipayPublicCertificate);
@@ -117,9 +117,9 @@ namespace Essensoft.AspNetCore.Payment.Alipay
             get => rootCert;
             set
             {
-                rootCert = value;
                 if (!string.IsNullOrEmpty(value))
                 {
+                    rootCert = value;
                     RootCertSN = AntCertificationUtil.GetRootCertSN(value);
                 }
             }

+ 9 - 0
src/Essensoft.AspNetCore.Payment.Alipay/IAlipayNotifyClient.cs

@@ -18,6 +18,15 @@ namespace Essensoft.AspNetCore.Payment.Alipay
         /// <param name="options">配置选项</param>
         /// <returns>领域对象</returns>
         Task<T> ExecuteAsync<T>(HttpRequest request, AlipayOptions options) where T : AlipayNotify;
+
+        /// <summary>
+        /// 执行 Alipay 通知请求解析。
+        /// </summary>
+        /// <typeparam name="T">领域对象</typeparam>
+        /// <param name="request">控制器的请求</param>
+        /// <param name="options">配置选项</param>
+        /// <returns>领域对象</returns>
+        Task<T> CertificateExecuteAsync<T>(HttpRequest request, AlipayOptions options) where T : AlipayNotify;
     }
 }
 

+ 14 - 0
src/Essensoft.AspNetCore.Payment.Alipay/Utility/AlipaySignature.cs

@@ -2,6 +2,7 @@
 using System.Security.Cryptography;
 using System.Text;
 using Essensoft.AspNetCore.Payment.Security;
+using Org.BouncyCastle.X509;
 
 namespace Essensoft.AspNetCore.Payment.Alipay.Utility
 {
@@ -53,6 +54,19 @@ namespace Essensoft.AspNetCore.Payment.Alipay.Utility
             }
         }
 
+        public static bool RSACheckContent(string data, string sign, X509Certificate publicCert, string signType)
+        {
+            var publicKey = AntCertificationUtil.ExtractPemPublicKeyFromCert(publicCert);
+            var key = RSAUtilities.GetRSAParametersFormPublicKey(publicKey);
+            switch (signType)
+            {
+                case "RSA2":
+                    return SHA256WithRSA.Verify(data, sign, key);
+                default:
+                    return SHA1WithRSA.Verify(data, sign, key);
+            }
+        }
+
         public static string AESEncrypt(string data, string encyptKey)
         {
             return AES.Encrypt(data, encyptKey, AES_IV, CipherMode.CBC, PaddingMode.PKCS7);