Browse Source

从 WeChatPayClient 拆分出 WeChatPayV3Client 并调整示例

Roc 5 years ago
parent
commit
f2060ac690

+ 21 - 6
samples/WebApplicationSample/Controllers/NotifyController.cs

@@ -270,13 +270,11 @@ namespace WebApplicationSample.Controllers
     public class WeChatPayNotifyController : Controller
     {
         private readonly IWeChatPayNotifyClient _client;
-        private readonly IWeChatPayV3NotifyClient _clientV3;
         private readonly IOptions<WeChatPayOptions> _optionsAccessor;
 
-        public WeChatPayNotifyController(IWeChatPayNotifyClient client, IWeChatPayV3NotifyClient clientV3, IOptions<WeChatPayOptions> optionsAccessor)
+        public WeChatPayNotifyController(IWeChatPayNotifyClient client, IOptions<WeChatPayOptions> optionsAccessor)
         {
             _client = client;
-            _clientV3 = clientV3;
             _optionsAccessor = optionsAccessor;
         }
 
@@ -332,17 +330,34 @@ namespace WebApplicationSample.Controllers
                 return NoContent();
             }
         }
+    }
+
+    #endregion
+
+    #region 微信支付V3异步通知
+
+    [Route("notify/wechatpay/v3")]
+    public class WeChatPayV3NotifyController : Controller
+    {
+        private readonly IWeChatPayV3NotifyClient _client;
+        private readonly IOptions<WeChatPayOptions> _optionsAccessor;
+
+        public WeChatPayV3NotifyController(IWeChatPayV3NotifyClient client, IOptions<WeChatPayOptions> optionsAccessor)
+        {
+            _client = client;
+            _optionsAccessor = optionsAccessor;
+        }
 
         /// <summary>
-        /// 支付结果通知v3
+        /// 支付结果通知
         /// </summary>
-        [Route("v3/transactions")]
+        [Route("transactions")]
         [HttpPost]
         public async Task<IActionResult> Transactions()
         {
             try
             {
-                var notify = await _clientV3.ExecuteAsync<WeChatPayTransactionsNotify>(Request, _optionsAccessor.Value);
+                var notify = await _client.ExecuteAsync<WeChatPayTransactionsNotify>(Request, _optionsAccessor.Value);
                 if (notify.StatusCode == 200)
                 {
                     Console.WriteLine("OutTradeNo: " + notify.OutTradeNo);

+ 1 - 196
samples/WebApplicationSample/Controllers/WeChatPayController.cs

@@ -1,8 +1,6 @@
-using System.Collections.Generic;
-using System.Text.Json;
+using System.Text.Json;
 using System.Threading.Tasks;
 using Essensoft.AspNetCore.Payment.WeChatPay;
-using Essensoft.AspNetCore.Payment.WeChatPay.Domain;
 using Essensoft.AspNetCore.Payment.WeChatPay.Request;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
@@ -583,198 +581,5 @@ namespace WebApplicationSample.Controllers
 
             return View();
         }
-
-        /// <summary>
-        /// 获取平台证书列表
-        /// </summary>
-        [HttpGet]
-        [HttpPost]
-        public async Task<IActionResult> GetCertificates()
-        {
-            if (Request.Method == "POST")
-            {
-                var request = new WeChatPayCertificatesRequest();
-                var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
-                ViewData["response"] = response.Body;
-                return View();
-            }
-
-            return View();
-        }
-
-        /// <summary>
-        /// APP支付-App下单API
-        /// </summary>
-        [HttpGet]
-        public IActionResult AppPayV3()
-        {
-            return View();
-        }
-
-        /// <summary>
-        /// APP支付-App下单API
-        /// </summary>
-        /// <param name="viewModel"></param>
-        [HttpPost]
-        public async Task<IActionResult> AppPayV3(WeChatPayAppPayV3ViewModel viewModel)
-        {
-            var model = new WeChatPayTransactionsAppModel
-            {
-                AppId = _optionsAccessor.Value.AppId,
-                MchId = _optionsAccessor.Value.MchId,
-                Amount = new Amount { Total = viewModel.Total, Currency = "CNY" },
-                Description = viewModel.Description,
-                NotifyUrl = viewModel.NotifyUrl,
-                OutTradeNo = viewModel.OutTradeNo,
-            };
-
-            var request = new WeChatPayTransactionsAppRequest();
-            request.SetBizModel(model);
-
-            var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
-
-            if (response.StatusCode == 200)
-            {
-                var req = new WeChatPayAppSdkRequest
-                {
-                    PrepayId = response.PrepayId
-                };
-
-                var parameter = await _client.ExecuteAsync(req, _optionsAccessor.Value);
-
-                // 将参数(parameter)给 ios/android端 让他调起微信APP(https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5)
-                ViewData["parameter"] = JsonSerializer.Serialize(parameter);
-                ViewData["response"] = response.Body;
-                return View();
-            }
-
-            ViewData["response"] = response.Body;
-            return View();
-        }
-
-        /// <summary>
-        /// 公众号支付-JSAPI下单
-        /// </summary>
-        [HttpGet]
-        public IActionResult PubPayV3()
-        {
-            return View();
-        }
-
-        /// <summary>
-        /// 公众号支付-JSAPI下单
-        /// </summary>
-        /// <param name="viewModel"></param>
-        [HttpPost]
-        public async Task<IActionResult> PubPayV3(WeChatPayPubPayV3ViewModel viewModel)
-        {
-            var model = new WeChatPayTransactionsJsApiModel
-            {
-                AppId = _optionsAccessor.Value.AppId,
-                MchId = _optionsAccessor.Value.MchId,
-                Amount = new Amount { Total = viewModel.Total, Currency = "CNY" },
-                Description = viewModel.Description,
-                NotifyUrl = viewModel.NotifyUrl,
-                OutTradeNo = viewModel.OutTradeNo,
-                Payer = new Payer { OpenId = viewModel.OpenId }
-            };
-
-            var request = new WeChatPayTransactionsJsApiRequest();
-            request.SetBizModel(model);
-
-            var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
-
-            if (response.StatusCode == 200)
-            {
-                var req = new WeChatPayJsApiSdkRequest
-                {
-                    Package = "prepay_id=" + response.PrepayId
-                };
-
-                var parameter = await _client.ExecuteAsync(req, _optionsAccessor.Value);
-
-                // 将参数(parameter)给 公众号前端 让他在微信内H5调起支付(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6)
-                ViewData["parameter"] = JsonSerializer.Serialize(parameter);
-                ViewData["response"] = response.Body;
-                return View();
-            }
-
-            ViewData["response"] = response.Body;
-            return View();
-        }
-
-        /// <summary>
-        /// 扫码支付-Native下单API
-        /// </summary>
-        [HttpGet]
-        public IActionResult QrCodePayV3()
-        {
-            return View();
-        }
-
-        /// <summary>
-        /// 扫码支付-Native下单API
-        /// </summary>
-        /// <param name="viewModel"></param>
-        [HttpPost]
-        public async Task<IActionResult> QrCodePayV3(WeChatPayQrCodePayV3ViewModel viewModel)
-        {
-            var model = new WeChatPayTransactionsNativeModel
-            {
-                AppId = _optionsAccessor.Value.AppId,
-                MchId = _optionsAccessor.Value.MchId,
-                Amount = new Amount { Total = viewModel.Total, Currency = "CNY" },
-                Description = viewModel.Description,
-                NotifyUrl = viewModel.NotifyUrl,
-                OutTradeNo = viewModel.OutTradeNo,
-            };
-
-            var request = new WeChatPayTransactionsNativeRequest();
-            request.SetBizModel(model);
-
-            var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
-
-            // response.CodeUrl 给前端生成二维码
-            ViewData["qrcode"] = response.CodeUrl;
-            ViewData["response"] = response.Body;
-            return View();
-        }
-
-        /// <summary>
-        /// H5支付-H5下单API
-        /// </summary>
-        [HttpGet]
-        public IActionResult H5PayV3()
-        {
-            return View();
-        }
-
-        /// <summary>
-        /// H5支付-H5下单API
-        /// </summary>
-        /// <param name="viewModel"></param>
-        [HttpPost]
-        public async Task<IActionResult> H5PayV3(WeChatPayH5PayV3ViewModel viewModel)
-        {
-            var model = new WeChatPayTransactionsH5Model
-            {
-                AppId = _optionsAccessor.Value.AppId,
-                MchId = _optionsAccessor.Value.MchId,
-                Amount = new Amount { Total = viewModel.Total, Currency = "CNY" },
-                Description = viewModel.Description,
-                NotifyUrl = viewModel.NotifyUrl,
-                OutTradeNo = viewModel.OutTradeNo,
-                SceneInfo = new SceneInfo { PayerClientIp = "127.0.0.1" }
-            };
-
-            var request = new WeChatPayTransactionsH5Request();
-            request.SetBizModel(model);
-
-            var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
-
-            // h5_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,h5_url的有效期为5分钟。
-            ViewData["response"] = response.Body;
-            return View();
-        }
     }
 }

+ 224 - 0
samples/WebApplicationSample/Controllers/WeChatPayV3Controller.cs

@@ -0,0 +1,224 @@
+using System.Text.Json;
+using System.Threading.Tasks;
+using Essensoft.AspNetCore.Payment.WeChatPay;
+using Essensoft.AspNetCore.Payment.WeChatPay.Domain;
+using Essensoft.AspNetCore.Payment.WeChatPay.Request;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using WebApplicationSample.Models;
+
+namespace WebApplicationSample.Controllers
+{
+    public class WeChatPayV3Controller : Controller
+    {
+        private readonly IWeChatPayV3Client _client;
+        private readonly IOptions<WeChatPayOptions> _optionsAccessor;
+
+        public WeChatPayV3Controller(IWeChatPayV3Client client, IOptions<WeChatPayOptions> optionsAccessor)
+        {
+            _client = client;
+            _optionsAccessor = optionsAccessor;
+        }
+
+        /// <summary>
+        /// 微信支付指引页
+        /// </summary>
+        public IActionResult Index()
+        {
+            return View();
+        }
+
+        /// <summary>
+        /// 获取平台证书列表
+        /// </summary>
+        [HttpGet]
+        [HttpPost]
+        public async Task<IActionResult> GetCertificates()
+        {
+            if (Request.Method == "POST")
+            {
+                var request = new WeChatPayCertificatesRequest();
+                var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
+                ViewData["response"] = response.Body;
+                return View();
+            }
+
+            return View();
+        }
+
+        /// <summary>
+        /// APP支付-App下单API
+        /// </summary>
+        [HttpGet]
+        public IActionResult AppPay()
+        {
+            return View();
+        }
+
+        /// <summary>
+        /// APP支付-App下单API
+        /// </summary>
+        /// <param name="viewModel"></param>
+        [HttpPost]
+        public async Task<IActionResult> AppPay(WeChatPayAppPayV3ViewModel viewModel)
+        {
+            var model = new WeChatPayTransactionsAppModel
+            {
+                AppId = _optionsAccessor.Value.AppId,
+                MchId = _optionsAccessor.Value.MchId,
+                Amount = new Amount { Total = viewModel.Total, Currency = "CNY" },
+                Description = viewModel.Description,
+                NotifyUrl = viewModel.NotifyUrl,
+                OutTradeNo = viewModel.OutTradeNo,
+            };
+
+            var request = new WeChatPayTransactionsAppRequest();
+            request.SetBizModel(model);
+
+            var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
+
+            if (response.StatusCode == 200)
+            {
+                var req = new WeChatPayAppSdkRequest
+                {
+                    PrepayId = response.PrepayId
+                };
+
+                var parameter = await _client.ExecuteAsync(req, _optionsAccessor.Value);
+
+                // 将参数(parameter)给 ios/android端 让他调起微信APP(https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5)
+                ViewData["parameter"] = JsonSerializer.Serialize(parameter);
+                ViewData["response"] = response.Body;
+                return View();
+            }
+
+            ViewData["response"] = response.Body;
+            return View();
+        }
+
+        /// <summary>
+        /// 公众号支付-JSAPI下单
+        /// </summary>
+        [HttpGet]
+        public IActionResult PubPay()
+        {
+            return View();
+        }
+
+        /// <summary>
+        /// 公众号支付-JSAPI下单
+        /// </summary>
+        /// <param name="viewModel"></param>
+        [HttpPost]
+        public async Task<IActionResult> PubPay(WeChatPayPubPayV3ViewModel viewModel)
+        {
+            var model = new WeChatPayTransactionsJsApiModel
+            {
+                AppId = _optionsAccessor.Value.AppId,
+                MchId = _optionsAccessor.Value.MchId,
+                Amount = new Amount { Total = viewModel.Total, Currency = "CNY" },
+                Description = viewModel.Description,
+                NotifyUrl = viewModel.NotifyUrl,
+                OutTradeNo = viewModel.OutTradeNo,
+                Payer = new Payer { OpenId = viewModel.OpenId }
+            };
+
+            var request = new WeChatPayTransactionsJsApiRequest();
+            request.SetBizModel(model);
+
+            var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
+
+            if (response.StatusCode == 200)
+            {
+                var req = new WeChatPayJsApiSdkRequest
+                {
+                    Package = "prepay_id=" + response.PrepayId
+                };
+
+                var parameter = await _client.ExecuteAsync(req, _optionsAccessor.Value);
+
+                // 将参数(parameter)给 公众号前端 让他在微信内H5调起支付(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6)
+                ViewData["parameter"] = JsonSerializer.Serialize(parameter);
+                ViewData["response"] = response.Body;
+                return View();
+            }
+
+            ViewData["response"] = response.Body;
+            return View();
+        }
+
+        /// <summary>
+        /// 扫码支付-Native下单API
+        /// </summary>
+        [HttpGet]
+        public IActionResult QrCodePay()
+        {
+            return View();
+        }
+
+        /// <summary>
+        /// 扫码支付-Native下单API
+        /// </summary>
+        /// <param name="viewModel"></param>
+        [HttpPost]
+        public async Task<IActionResult> QrCodePay(WeChatPayQrCodePayV3ViewModel viewModel)
+        {
+            var model = new WeChatPayTransactionsNativeModel
+            {
+                AppId = _optionsAccessor.Value.AppId,
+                MchId = _optionsAccessor.Value.MchId,
+                Amount = new Amount { Total = viewModel.Total, Currency = "CNY" },
+                Description = viewModel.Description,
+                NotifyUrl = viewModel.NotifyUrl,
+                OutTradeNo = viewModel.OutTradeNo,
+            };
+
+            var request = new WeChatPayTransactionsNativeRequest();
+            request.SetBizModel(model);
+
+            var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
+
+            // response.CodeUrl 给前端生成二维码
+            ViewData["qrcode"] = response.CodeUrl;
+            ViewData["response"] = response.Body;
+            return View();
+        }
+
+        /// <summary>
+        /// H5支付-H5下单API
+        /// </summary>
+        [HttpGet]
+        public IActionResult H5Pay()
+        {
+            return View();
+        }
+
+        /// <summary>
+        /// H5支付-H5下单API
+        /// </summary>
+        /// <param name="viewModel"></param>
+        [HttpPost]
+        public async Task<IActionResult> H5Pay(WeChatPayH5PayV3ViewModel viewModel)
+        {
+            var model = new WeChatPayTransactionsH5Model
+            {
+                AppId = _optionsAccessor.Value.AppId,
+                MchId = _optionsAccessor.Value.MchId,
+                Amount = new Amount { Total = viewModel.Total, Currency = "CNY" },
+                Description = viewModel.Description,
+                NotifyUrl = viewModel.NotifyUrl,
+                OutTradeNo = viewModel.OutTradeNo,
+                SceneInfo = new SceneInfo { PayerClientIp = "127.0.0.1" }
+            };
+
+            var request = new WeChatPayTransactionsH5Request();
+            request.SetBizModel(model);
+
+            var response = await _client.ExecuteAsync(request, _optionsAccessor.Value);
+
+            // h5_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,h5_url的有效期为5分钟。
+            ViewData["response"] = response.Body;
+            return View();
+        }
+    }
+}

+ 84 - 0
samples/WebApplicationSample/Models/WeChatPayV3ViewModel.cs

@@ -0,0 +1,84 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace WebApplicationSample.Models
+{
+    public class WeChatPayAppPayV3ViewModel
+    {
+        [Required]
+        [Display(Name = "out_trade_no")]
+        public string OutTradeNo { get; set; }
+
+        [Required]
+        [Display(Name = "description")]
+        public string Description { get; set; }
+
+        [Required]
+        [Display(Name = "total")]
+        public int Total { get; set; }
+
+        [Required]
+        [Display(Name = "notify_url")]
+        public string NotifyUrl { get; set; }
+    }
+
+    public class WeChatPayPubPayV3ViewModel
+    {
+        [Required]
+        [Display(Name = "out_trade_no")]
+        public string OutTradeNo { get; set; }
+
+        [Required]
+        [Display(Name = "description")]
+        public string Description { get; set; }
+
+        [Required]
+        [Display(Name = "total")]
+        public int Total { get; set; }
+
+        [Required]
+        [Display(Name = "notify_url")]
+        public string NotifyUrl { get; set; }
+
+        [Required]
+        [Display(Name = "openid")]
+        public string OpenId { get; set; }
+    }
+
+    public class WeChatPayQrCodePayV3ViewModel
+    {
+        [Required]
+        [Display(Name = "out_trade_no")]
+        public string OutTradeNo { get; set; }
+
+        [Required]
+        [Display(Name = "description")]
+        public string Description { get; set; }
+
+        [Required]
+        [Display(Name = "total")]
+        public int Total { get; set; }
+
+        [Required]
+        [Display(Name = "notify_url")]
+        public string NotifyUrl { get; set; }
+    }
+
+    public class WeChatPayH5PayV3ViewModel
+    {
+        [Required]
+        [Display(Name = "out_trade_no")]
+        public string OutTradeNo { get; set; }
+
+        [Required]
+        [Display(Name = "description")]
+        public string Description { get; set; }
+
+        [Required]
+        [Display(Name = "total")]
+        public int Total { get; set; }
+
+        [Required]
+        [Display(Name = "notify_url")]
+        public string NotifyUrl { get; set; }
+    }
+}

+ 0 - 80
samples/WebApplicationSample/Models/WeChatPayViewModel.cs

@@ -332,84 +332,4 @@ namespace WebApplicationSample.Models
         [Display(Name = "partner_trade_no")]
         public string PartnerTradeNo { get; set; }
     }
-
-    public class WeChatPayAppPayV3ViewModel
-    {
-        [Required]
-        [Display(Name = "out_trade_no")]
-        public string OutTradeNo { get; set; }
-
-        [Required]
-        [Display(Name = "description")]
-        public string Description { get; set; }
-
-        [Required]
-        [Display(Name = "total")]
-        public int Total { get; set; }
-
-        [Required]
-        [Display(Name = "notify_url")]
-        public string NotifyUrl { get; set; }
-    }
-
-    public class WeChatPayPubPayV3ViewModel
-    {
-        [Required]
-        [Display(Name = "out_trade_no")]
-        public string OutTradeNo { get; set; }
-
-        [Required]
-        [Display(Name = "description")]
-        public string Description { get; set; }
-
-        [Required]
-        [Display(Name = "total")]
-        public int Total { get; set; }
-
-        [Required]
-        [Display(Name = "notify_url")]
-        public string NotifyUrl { get; set; }
-
-        [Required]
-        [Display(Name = "openid")]
-        public string OpenId { get; set; }
-    }
-
-    public class WeChatPayQrCodePayV3ViewModel
-    {
-        [Required]
-        [Display(Name = "out_trade_no")]
-        public string OutTradeNo { get; set; }
-
-        [Required]
-        [Display(Name = "description")]
-        public string Description { get; set; }
-
-        [Required]
-        [Display(Name = "total")]
-        public int Total { get; set; }
-
-        [Required]
-        [Display(Name = "notify_url")]
-        public string NotifyUrl { get; set; }
-    }
-
-    public class WeChatPayH5PayV3ViewModel
-    {
-        [Required]
-        [Display(Name = "out_trade_no")]
-        public string OutTradeNo { get; set; }
-
-        [Required]
-        [Display(Name = "description")]
-        public string Description { get; set; }
-
-        [Required]
-        [Display(Name = "total")]
-        public int Total { get; set; }
-
-        [Required]
-        [Display(Name = "notify_url")]
-        public string NotifyUrl { get; set; }
-    }
 }

+ 3 - 0
samples/WebApplicationSample/Views/Shared/_Layout.cshtml

@@ -34,6 +34,9 @@
                     <li class="nav-item @Html.IsActive("WeChatPay")">
                         <a class="nav-link" asp-controller="WeChatPay" asp-action="Index">微信支付</a>
                     </li>
+                    <li class="nav-item @Html.IsActive("WeChatPayV3")">
+                        <a class="nav-link" asp-controller="WeChatPayV3" asp-action="Index">微信支付V3</a>
+                    </li>
                 </ul>
             </div>
         </div>

+ 0 - 30
samples/WebApplicationSample/Views/WeChatPay/Index.cshtml

@@ -126,35 +126,5 @@
             <td><a href="https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4" target="_blank">https://fraud.mch.weixin.qq.com/risk/getpublickey</a></td>
             <td><a asp-controller="WeChatPay" asp-action="GetPublicKey">立即测试</a></td>
         </tr>
-        <tr>
-            <th scope="row">19</th>
-            <td>获取平台证书列表</td>
-            <td><a href="https://wechatpay-api.gitbook.io/wechatpay-api-v3/jie-kou-wen-dang/ping-tai-zheng-shu" target="_blank">https://api.mch.weixin.qq.com/v3/certificates</a></td>
-            <td><a asp-controller="WeChatPay" asp-action="GetCertificates">立即测试</a></td>
-        </tr>
-        <tr>
-            <th scope="row">20</th>
-            <td>APP支付-App下单</td>
-            <td><a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_1.shtml" target="_blank">https://api.mch.weixin.qq.com/v3/pay/transactions/app</a></td>
-            <td><a asp-controller="WeChatPay" asp-action="AppPayV3">立即测试</a></td>
-        </tr>
-        <tr>
-            <th scope="row">21</th>
-            <td>公众号支付-JSAPI下单</td>
-            <td><a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_2.shtml" target="_blank">https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi</a></td>
-            <td><a asp-controller="WeChatPay" asp-action="PubPayV3">立即测试</a></td>
-        </tr>
-        <tr>
-            <th scope="row">22</th>
-            <td>扫码支付-Native下单</td>
-            <td><a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_3.shtml" target="_blank">https://api.mch.weixin.qq.com/v3/pay/transactions/native</a></td>
-            <td><a asp-controller="WeChatPay" asp-action="QrCodePayV3">立即测试</a></td>
-        </tr>
-        <tr>
-            <th scope="row">23</th>
-            <td>H5支付-H5下单</td>
-            <td><a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_4.shtml" target="_blank">https://api.mch.weixin.qq.com/v3/pay/transactions/h5</a></td>
-            <td><a asp-controller="WeChatPay" asp-action="H5PayV3">立即测试</a></td>
-        </tr>
     </tbody>
 </table>

+ 2 - 2
samples/WebApplicationSample/Views/WeChatPay/AppPayV3.cshtml → samples/WebApplicationSample/Views/WeChatPayV3/AppPay.cshtml

@@ -4,14 +4,14 @@
 }
 <nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-        <li class="breadcrumb-item"><a asp-controller="WeChatPay" asp-action="Index">微信支付</a></li>
+        <li class="breadcrumb-item"><a asp-controller="WeChatPayV3" asp-action="Index">微信支付V3</a></li>
         <li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
     </ol>
 </nav>
 <br />
 <div class="card">
     <div class="card-body">
-        <form asp-controller="WeChatPay" asp-action="AppPayV3">
+        <form asp-controller="WeChatPayV3" asp-action="AppPay">
             <div asp-validation-summary="All" class="text-danger"></div>
             <div class="form-group">
                 <label asp-for="OutTradeNo"></label>

+ 2 - 2
samples/WebApplicationSample/Views/WeChatPay/GetCertificates.cshtml → samples/WebApplicationSample/Views/WeChatPayV3/GetCertificates.cshtml

@@ -3,14 +3,14 @@
 }
 <nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-        <li class="breadcrumb-item"><a asp-controller="WeChatPay" asp-action="Index">微信支付</a></li>
+        <li class="breadcrumb-item"><a asp-controller="WeChatPayV3" asp-action="Index">微信支付V3</a></li>
         <li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
     </ol>
 </nav>
 <br />
 <div class="card">
     <div class="card-body">
-        <form asp-controller="WeChatPay" asp-action="GetCertificates">
+        <form asp-controller="WeChatPayV3" asp-action="GetCertificates">
             <button type="submit" class="btn btn-primary">提交请求</button>
         </form>
         <hr />

+ 2 - 2
samples/WebApplicationSample/Views/WeChatPay/H5PayV3.cshtml → samples/WebApplicationSample/Views/WeChatPayV3/H5Pay.cshtml

@@ -4,14 +4,14 @@
 }
 <nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-        <li class="breadcrumb-item"><a asp-controller="WeChatPay" asp-action="Index">微信支付</a></li>
+        <li class="breadcrumb-item"><a asp-controller="WeChatPayV3" asp-action="Index">微信支付V3</a></li>
         <li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
     </ol>
 </nav>
 <br />
 <div class="card">
     <div class="card-body">
-        <form asp-controller="WeChatPay" asp-action="H5PayV3">
+        <form asp-controller="WeChatPayV3" asp-action="H5Pay">
             <div asp-validation-summary="All" class="text-danger"></div>
             <div class="form-group">
                 <label asp-for="OutTradeNo"></label>

+ 52 - 0
samples/WebApplicationSample/Views/WeChatPayV3/Index.cshtml

@@ -0,0 +1,52 @@
+@{
+    ViewData["Title"] = "微信支付V3";
+}
+<nav aria-label="breadcrumb">
+    <ol class="breadcrumb">
+        <li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">首页</a></li>
+        <li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
+    </ol>
+</nav>
+<br />
+<table class="table table-bordered table-hover">
+    <thead>
+        <tr>
+            <th scope="col">#</th>
+            <th scope="col">产品</th>
+            <th scope="col">接口</th>
+            <th scope="col">#</th>
+        </tr>
+    </thead>
+    <tbody>
+        <tr>
+            <th scope="row">1</th>
+            <td>获取平台证书列表</td>
+            <td><a href="https://wechatpay-api.gitbook.io/wechatpay-api-v3/jie-kou-wen-dang/ping-tai-zheng-shu" target="_blank">https://api.mch.weixin.qq.com/v3/certificates</a></td>
+            <td><a asp-controller="WeChatPayV3" asp-action="GetCertificates">立即测试</a></td>
+        </tr>
+        <tr>
+            <th scope="row">2</th>
+            <td>APP支付-App下单</td>
+            <td><a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_1.shtml" target="_blank">https://api.mch.weixin.qq.com/v3/pay/transactions/app</a></td>
+            <td><a asp-controller="WeChatPayV3" asp-action="AppPay">立即测试</a></td>
+        </tr>
+        <tr>
+            <th scope="row">3</th>
+            <td>公众号支付-JSAPI下单</td>
+            <td><a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_2.shtml" target="_blank">https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi</a></td>
+            <td><a asp-controller="WeChatPayV3" asp-action="PubPay">立即测试</a></td>
+        </tr>
+        <tr>
+            <th scope="row">4</th>
+            <td>扫码支付-Native下单</td>
+            <td><a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_3.shtml" target="_blank">https://api.mch.weixin.qq.com/v3/pay/transactions/native</a></td>
+            <td><a asp-controller="WeChatPayV3" asp-action="QrCodePay">立即测试</a></td>
+        </tr>
+        <tr>
+            <th scope="row">5</th>
+            <td>H5支付-H5下单</td>
+            <td><a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transactions/chapter3_4.shtml" target="_blank">https://api.mch.weixin.qq.com/v3/pay/transactions/h5</a></td>
+            <td><a asp-controller="WeChatPayV3" asp-action="H5Pay">立即测试</a></td>
+        </tr>
+    </tbody>
+</table>

+ 2 - 2
samples/WebApplicationSample/Views/WeChatPay/PubPayV3.cshtml → samples/WebApplicationSample/Views/WeChatPayV3/PubPay.cshtml

@@ -4,14 +4,14 @@
 }
 <nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-        <li class="breadcrumb-item"><a asp-controller="WeChatPay" asp-action="Index">微信支付</a></li>
+        <li class="breadcrumb-item"><a asp-controller="WeChatPayV3" asp-action="Index">微信支付V3</a></li>
         <li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
     </ol>
 </nav>
 <br />
 <div class="card">
     <div class="card-body">
-        <form asp-controller="WeChatPay" asp-action="PubPayV3">
+        <form asp-controller="WeChatPayV3" asp-action="PubPay">
             <div asp-validation-summary="All" class="text-danger"></div>
             <div class="form-group">
                 <label asp-for="OutTradeNo"></label>

+ 2 - 2
samples/WebApplicationSample/Views/WeChatPay/QrCodePayV3.cshtml → samples/WebApplicationSample/Views/WeChatPayV3/QrCodePay.cshtml

@@ -4,14 +4,14 @@
 }
 <nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-        <li class="breadcrumb-item"><a asp-controller="WeChatPay" asp-action="Index">微信支付</a></li>
+        <li class="breadcrumb-item"><a asp-controller="WeChatPayV3" asp-action="Index">微信支付V3</a></li>
         <li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
     </ol>
 </nav>
 <br />
 <div class="card">
     <div class="card-body">
-        <form asp-controller="WeChatPay" asp-action="QrCodePayV3">
+        <form asp-controller="WeChatPayV3" asp-action="QrCodePay">
             <div asp-validation-summary="All" class="text-danger"></div>
             <div class="form-group">
                 <label asp-for="OutTradeNo"></label>

+ 0 - 16
src/Essensoft.AspNetCore.Payment.WeChatPay/IWeChatPayClient.cs

@@ -34,21 +34,5 @@ namespace Essensoft.AspNetCore.Payment.WeChatPay
         /// <param name="request">具体的WeChatPay Sdk请求</param>
         /// <param name="options">配置选项</param>
         Task<WeChatPayDictionary> ExecuteAsync(IWeChatPaySdkRequest request, WeChatPayOptions options);
-
-        /// <summary>
-        /// 执行 WeChatPay APIv3 Get请求。
-        /// </summary>
-        /// <param name="request">具体的WeChatPay APIv3 Get请求</param>
-        /// <param name="options">配置选项</param>
-        /// <returns>领域对象</returns>
-        Task<T> ExecuteAsync<T>(IWeChatPayV3GetRequest<T> request, WeChatPayOptions options) where T : WeChatPayV3Response;
-
-        /// <summary>
-        /// 执行 WeChatPay APIv3 Post请求。
-        /// </summary>
-        /// <param name="request">具体的WeChatPay APIv3 Post请求</param>
-        /// <param name="options">配置选项</param>
-        /// <returns>领域对象</returns>
-        Task<T> ExecuteAsync<T>(IWeChatPayV3PostRequest<T> request, WeChatPayOptions options) where T : WeChatPayV3Response;
     }
 }

+ 30 - 0
src/Essensoft.AspNetCore.Payment.WeChatPay/IWeChatPayV3Client.cs

@@ -0,0 +1,30 @@
+using System.Threading.Tasks;
+
+namespace Essensoft.AspNetCore.Payment.WeChatPay
+{
+    public interface IWeChatPayV3Client
+    {
+        /// <summary>
+        /// 执行 WeChatPay Sdk请求。
+        /// </summary>
+        /// <param name="request">具体的WeChatPay Sdk请求</param>
+        /// <param name="options">配置选项</param>
+        Task<WeChatPayDictionary> ExecuteAsync(IWeChatPaySdkRequest request, WeChatPayOptions options);
+
+        /// <summary>
+        /// 执行 WeChatPay APIv3 Get请求。
+        /// </summary>
+        /// <param name="request">具体的WeChatPay APIv3 Get请求</param>
+        /// <param name="options">配置选项</param>
+        /// <returns>领域对象</returns>
+        Task<T> ExecuteAsync<T>(IWeChatPayV3GetRequest<T> request, WeChatPayOptions options) where T : WeChatPayV3Response;
+
+        /// <summary>
+        /// 执行 WeChatPay APIv3 Post请求。
+        /// </summary>
+        /// <param name="request">具体的WeChatPay APIv3 Post请求</param>
+        /// <param name="options">配置选项</param>
+        /// <returns>领域对象</returns>
+        Task<T> ExecuteAsync<T>(IWeChatPayV3PostRequest<T> request, WeChatPayOptions options) where T : WeChatPayV3Response;
+    }
+}

+ 1 - 0
src/Essensoft.AspNetCore.Payment.WeChatPay/ServiceCollectionExtensions.cs

@@ -15,6 +15,7 @@ namespace Microsoft.Extensions.DependencyInjection
             services.AddSingleton<WeChatPayClientCertificateManager>();
             services.AddSingleton<WeChatPayPlatformCertificateManager>();
             services.AddSingleton<IWeChatPayClient, WeChatPayClient>();
+            services.AddSingleton<IWeChatPayV3Client, WeChatPayV3Client>();
 
 #if NETCOREAPP3_1
             services.AddSingleton<IWeChatPayNotifyClient, WeChatPayNotifyClient>();

+ 1 - 136
src/Essensoft.AspNetCore.Payment.WeChatPay/WeChatPayClient.cs

@@ -17,15 +17,13 @@ namespace Essensoft.AspNetCore.Payment.WeChatPay
 
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly WeChatPayClientCertificateManager _clientCertificateManager;
-        private readonly WeChatPayPlatformCertificateManager _platformCertificateManager;
 
         #region WeChatPayClient Constructors
 
-        public WeChatPayClient(IHttpClientFactory httpClientFactory, WeChatPayClientCertificateManager clientCertificateManager, WeChatPayPlatformCertificateManager platformCertificateManager)
+        public WeChatPayClient(IHttpClientFactory httpClientFactory, WeChatPayClientCertificateManager clientCertificateManager)
         {
             _httpClientFactory = httpClientFactory;
             _clientCertificateManager = clientCertificateManager;
-            _platformCertificateManager = platformCertificateManager;
         }
 
         #endregion
@@ -207,92 +205,6 @@ namespace Essensoft.AspNetCore.Payment.WeChatPay
 
         #endregion
 
-        #region IWeChatPayClient Members
-
-        public async Task<T> ExecuteAsync<T>(IWeChatPayV3GetRequest<T> request, WeChatPayOptions options) where T : WeChatPayV3Response
-        {
-            if (options == null)
-            {
-                throw new ArgumentNullException(nameof(options));
-            }
-
-            if (string.IsNullOrEmpty(options.MchId))
-            {
-                throw new ArgumentNullException(nameof(options.MchId));
-            }
-
-            if (string.IsNullOrEmpty(options.Certificate))
-            {
-                throw new ArgumentNullException(nameof(options.Certificate));
-            }
-
-            var client = _httpClientFactory.CreateClient(nameof(WeChatPayClient));
-            var (serial, timestamp, nonce, signature, body, statusCode) = await client.GetAsync(request, options);
-            var parser = new WeChatPayV3ResponseJsonParser<T>();
-            var response = parser.Parse(body, statusCode);
-
-            // 为下载微信支付平台证书证书响应时,
-            if (response is WeChatPayCertificatesResponse resp)
-            {
-                foreach (var certificate in resp.Certificates)
-                {
-                    // 若证书序列号未被缓存,解密证书并加入缓存
-                    if (!_platformCertificateManager.ContainsKey(certificate.SerialNo))
-                    {
-                        switch (certificate.EncryptCertificate.Algorithm)
-                        {
-                            case nameof(AEAD_AES_256_GCM):
-                                {
-                                    var certStr = AEAD_AES_256_GCM.Decrypt(certificate.EncryptCertificate.Nonce, certificate.EncryptCertificate.Ciphertext, certificate.EncryptCertificate.AssociatedData, options.V3Key);
-                                    var cert = new X509Certificate2(Encoding.UTF8.GetBytes(certStr));
-                                    _platformCertificateManager.TryAdd(certificate.SerialNo, cert);
-                                }
-                                break;
-                            default:
-                                throw new WeChatPayException("Unknown algorithm!");
-                        }
-                    }
-                }
-            }
-
-            await CheckV3ResponseSignAsync(options, serial, timestamp, nonce, signature, body);
-
-            return response;
-        }
-
-        #endregion
-
-        #region IWeChatPayClient Members
-
-        public async Task<T> ExecuteAsync<T>(IWeChatPayV3PostRequest<T> request, WeChatPayOptions options) where T : WeChatPayV3Response
-        {
-            if (options == null)
-            {
-                throw new ArgumentNullException(nameof(options));
-            }
-
-            if (string.IsNullOrEmpty(options.MchId))
-            {
-                throw new ArgumentNullException(nameof(options.MchId));
-            }
-
-            if (string.IsNullOrEmpty(options.Certificate))
-            {
-                throw new ArgumentNullException(nameof(options.Certificate));
-            }
-
-            var client = _httpClientFactory.CreateClient(nameof(WeChatPayClient));
-            var (serial, timestamp, nonce, signature, body, statusCode) = await client.PostAsync(request, options);
-            var parser = new WeChatPayV3ResponseJsonParser<T>();
-            var response = parser.Parse(body, statusCode);
-
-            await CheckV3ResponseSignAsync(options, serial, timestamp, nonce, signature, body);
-
-            return response;
-        }
-
-        #endregion
-
         #region Check Response Method
 
         private void CheckResponseSign(WeChatPayResponse response, WeChatPayOptions options, WeChatPaySignType signType)
@@ -322,53 +234,6 @@ namespace Essensoft.AspNetCore.Payment.WeChatPay
             }
         }
 
-        private async Task CheckV3ResponseSignAsync(WeChatPayOptions options, string serial, string timestamp, string nonce, string signature, string body)
-        {
-            if (string.IsNullOrEmpty(serial))
-            {
-                throw new WeChatPayException($"sign check fail: {nameof(serial)} is empty!");
-            }
-
-            if (string.IsNullOrEmpty(signature))
-            {
-                throw new WeChatPayException($"sign check fail: {nameof(signature)} is empty!");
-            }
-
-            var cert = await LoadPlatformCertificateAsync(serial, options);
-            var signatureSourceDate = BuildSignatureSourceDate(timestamp, nonce, body);
-
-            if (!cert.GetRSAPublicKey().Verify(signatureSourceDate, signature))
-            {
-                throw new WeChatPayException("sign check fail: check Sign and Data Fail!");
-            }
-        }
-
-        private string BuildSignatureSourceDate(string timestamp, string nonce, string body)
-        {
-            return $"{timestamp}\n{nonce}\n{body}\n";
-        }
-
-        private async Task<X509Certificate2> LoadPlatformCertificateAsync(string serial, WeChatPayOptions options)
-        {
-            // 如果证书序列号已缓存,则直接使用缓存的
-            if (_platformCertificateManager.TryGetValue(serial, out var certificate2))
-            {
-                return certificate2;
-            }
-
-            // 否则重新下载新的平台证书
-            var request = new WeChatPayCertificatesRequest();
-            var response = await ExecuteAsync(request, options);
-            if (response.Certificates.Count > 0 && _platformCertificateManager.TryGetValue(serial, out certificate2))
-            {
-                return certificate2;
-            }
-            else
-            {
-                throw new WeChatPayException("Download certificates failed!");
-            }
-        }
-
         #endregion
     }
 }

+ 199 - 0
src/Essensoft.AspNetCore.Payment.WeChatPay/WeChatPayV3Client.cs

@@ -0,0 +1,199 @@
+using System;
+using System.Net.Http;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading.Tasks;
+using Essensoft.AspNetCore.Payment.Security;
+using Essensoft.AspNetCore.Payment.WeChatPay.Parser;
+using Essensoft.AspNetCore.Payment.WeChatPay.Request;
+using Essensoft.AspNetCore.Payment.WeChatPay.Response;
+using Essensoft.AspNetCore.Payment.WeChatPay.Utility;
+
+namespace Essensoft.AspNetCore.Payment.WeChatPay
+{
+    public class WeChatPayV3Client : IWeChatPayV3Client
+    {
+        private readonly IHttpClientFactory _httpClientFactory;
+        private readonly WeChatPayPlatformCertificateManager _platformCertificateManager;
+
+        #region WeChatPayClient Constructors
+
+        public WeChatPayV3Client(IHttpClientFactory httpClientFactory, WeChatPayPlatformCertificateManager platformCertificateManager)
+        {
+            _httpClientFactory = httpClientFactory;
+            _platformCertificateManager = platformCertificateManager;
+        }
+
+        #endregion
+
+        #region IWeChatPayClient Members
+
+        public Task<WeChatPayDictionary> ExecuteAsync(IWeChatPaySdkRequest request, WeChatPayOptions options)
+        {
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            if (string.IsNullOrEmpty(options.AppId))
+            {
+                throw new ArgumentNullException(nameof(options.AppId));
+            }
+
+            if (string.IsNullOrEmpty(options.MchId))
+            {
+                throw new ArgumentNullException(nameof(options.MchId));
+            }
+
+            if (string.IsNullOrEmpty(options.Key))
+            {
+                throw new ArgumentNullException(nameof(options.Key));
+            }
+
+            var sortedTxtParams = new WeChatPayDictionary(request.GetParameters());
+
+            request.PrimaryHandler(options, sortedTxtParams);
+
+            return Task.FromResult(sortedTxtParams);
+        }
+
+        #endregion
+
+        #region IWeChatPayClient Members
+
+        public async Task<T> ExecuteAsync<T>(IWeChatPayV3GetRequest<T> request, WeChatPayOptions options) where T : WeChatPayV3Response
+        {
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            if (string.IsNullOrEmpty(options.MchId))
+            {
+                throw new ArgumentNullException(nameof(options.MchId));
+            }
+
+            if (string.IsNullOrEmpty(options.Certificate))
+            {
+                throw new ArgumentNullException(nameof(options.Certificate));
+            }
+
+            var client = _httpClientFactory.CreateClient(nameof(WeChatPayClient));
+            var (serial, timestamp, nonce, signature, body, statusCode) = await client.GetAsync(request, options);
+            var parser = new WeChatPayV3ResponseJsonParser<T>();
+            var response = parser.Parse(body, statusCode);
+
+            // 为下载微信支付平台证书证书响应时,
+            if (response is WeChatPayCertificatesResponse resp)
+            {
+                foreach (var certificate in resp.Certificates)
+                {
+                    // 若证书序列号未被缓存,解密证书并加入缓存
+                    if (!_platformCertificateManager.ContainsKey(certificate.SerialNo))
+                    {
+                        switch (certificate.EncryptCertificate.Algorithm)
+                        {
+                            case nameof(AEAD_AES_256_GCM):
+                                {
+                                    var certStr = AEAD_AES_256_GCM.Decrypt(certificate.EncryptCertificate.Nonce, certificate.EncryptCertificate.Ciphertext, certificate.EncryptCertificate.AssociatedData, options.V3Key);
+                                    var cert = new X509Certificate2(Encoding.UTF8.GetBytes(certStr));
+                                    _platformCertificateManager.TryAdd(certificate.SerialNo, cert);
+                                }
+                                break;
+                            default:
+                                throw new WeChatPayException("Unknown algorithm!");
+                        }
+                    }
+                }
+            }
+
+            await CheckV3ResponseSignAsync(options, serial, timestamp, nonce, signature, body);
+
+            return response;
+        }
+
+        #endregion
+
+        #region IWeChatPayClient Members
+
+        public async Task<T> ExecuteAsync<T>(IWeChatPayV3PostRequest<T> request, WeChatPayOptions options) where T : WeChatPayV3Response
+        {
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            if (string.IsNullOrEmpty(options.MchId))
+            {
+                throw new ArgumentNullException(nameof(options.MchId));
+            }
+
+            if (string.IsNullOrEmpty(options.Certificate))
+            {
+                throw new ArgumentNullException(nameof(options.Certificate));
+            }
+
+            var client = _httpClientFactory.CreateClient(nameof(WeChatPayClient));
+            var (serial, timestamp, nonce, signature, body, statusCode) = await client.PostAsync(request, options);
+            var parser = new WeChatPayV3ResponseJsonParser<T>();
+            var response = parser.Parse(body, statusCode);
+
+            await CheckV3ResponseSignAsync(options, serial, timestamp, nonce, signature, body);
+
+            return response;
+        }
+
+        #endregion
+
+        #region Check Response Method
+
+        private async Task CheckV3ResponseSignAsync(WeChatPayOptions options, string serial, string timestamp, string nonce, string signature, string body)
+        {
+            if (string.IsNullOrEmpty(serial))
+            {
+                throw new WeChatPayException($"sign check fail: {nameof(serial)} is empty!");
+            }
+
+            if (string.IsNullOrEmpty(signature))
+            {
+                throw new WeChatPayException($"sign check fail: {nameof(signature)} is empty!");
+            }
+
+            var cert = await LoadPlatformCertificateAsync(serial, options);
+            var signatureSourceDate = BuildSignatureSourceDate(timestamp, nonce, body);
+
+            if (!cert.GetRSAPublicKey().Verify(signatureSourceDate, signature))
+            {
+                throw new WeChatPayException("sign check fail: check Sign and Data Fail!");
+            }
+        }
+
+        private string BuildSignatureSourceDate(string timestamp, string nonce, string body)
+        {
+            return $"{timestamp}\n{nonce}\n{body}\n";
+        }
+
+        private async Task<X509Certificate2> LoadPlatformCertificateAsync(string serial, WeChatPayOptions options)
+        {
+            // 如果证书序列号已缓存,则直接使用缓存的
+            if (_platformCertificateManager.TryGetValue(serial, out var certificate2))
+            {
+                return certificate2;
+            }
+
+            // 否则重新下载新的平台证书
+            var request = new WeChatPayCertificatesRequest();
+            var response = await ExecuteAsync(request, options);
+            if (response.Certificates.Count > 0 && _platformCertificateManager.TryGetValue(serial, out certificate2))
+            {
+                return certificate2;
+            }
+            else
+            {
+                throw new WeChatPayException("Download certificates failed!");
+            }
+        }
+
+        #endregion
+    }
+}

+ 2 - 2
src/Essensoft.AspNetCore.Payment.WeChatPay/WeChatPayV3NotifyClient.cs

@@ -19,9 +19,9 @@ namespace Essensoft.AspNetCore.Payment.WeChatPay
         #region WeChatPayV3NotifyClient Constructors
 
         private readonly WeChatPayPlatformCertificateManager _platformCertificateManager;
-        private readonly IWeChatPayClient _client;
+        private readonly IWeChatPayV3Client _client;
 
-        public WeChatPayV3NotifyClient(WeChatPayPlatformCertificateManager platformCertificateManager, IWeChatPayClient client)
+        public WeChatPayV3NotifyClient(WeChatPayPlatformCertificateManager platformCertificateManager, IWeChatPayV3Client client)
         {
             _platformCertificateManager = platformCertificateManager;
             _client = client;