WeChatPayNotifyClient.cs 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using System.IO;
  2. using System.Text;
  3. using System.Threading.Tasks;
  4. using Essensoft.AspNetCore.Payment.Security;
  5. using Essensoft.AspNetCore.Payment.WeChatPay.Notify;
  6. using Essensoft.AspNetCore.Payment.WeChatPay.Parser;
  7. using Essensoft.AspNetCore.Payment.WeChatPay.Utility;
  8. using Microsoft.AspNetCore.Http;
  9. using Microsoft.Extensions.Logging;
  10. using Microsoft.Extensions.Options;
  11. namespace Essensoft.AspNetCore.Payment.WeChatPay
  12. {
  13. /// <summary>
  14. /// WeChatPay 通知解析客户端。
  15. /// </summary>
  16. public class WeChatPayNotifyClient : IWeChatPayNotifyClient
  17. {
  18. private readonly ILogger _logger;
  19. private readonly IOptionsSnapshot<WeChatPayOptions> _optionsSnapshotAccessor;
  20. #region WeChatPayNotifyClient Constructors
  21. public WeChatPayNotifyClient(
  22. ILogger<WeChatPayNotifyClient> logger,
  23. IOptionsSnapshot<WeChatPayOptions> optionsAccessor)
  24. {
  25. _logger = logger;
  26. _optionsSnapshotAccessor = optionsAccessor;
  27. }
  28. #endregion
  29. #region IWeChatPayNotifyClient Members
  30. public async Task<T> ExecuteAsync<T>(HttpRequest request) where T : WeChatPayNotify
  31. {
  32. return await ExecuteAsync<T>(request, null);
  33. }
  34. public async Task<T> ExecuteAsync<T>(HttpRequest request, string optionsName) where T : WeChatPayNotify
  35. {
  36. var options = string.IsNullOrEmpty(optionsName) ? _optionsSnapshotAccessor.Value : _optionsSnapshotAccessor.Get(optionsName);
  37. var body = await new StreamReader(request.Body, Encoding.UTF8).ReadToEndAsync();
  38. _logger.Log(options.LogLevel, "Request:{body}", body);
  39. var parser = new WeChatPayXmlParser<T>();
  40. var notify = parser.Parse(body);
  41. if (notify is WeChatPayRefundNotify)
  42. {
  43. var key = MD5.Compute(options.Key).ToLower();
  44. var data = AES.Decrypt((notify as WeChatPayRefundNotify).ReqInfo, key, AESCipherMode.ECB, AESPaddingMode.PKCS7);
  45. _logger.Log(options.LogLevel, "Decrypt Content:{data}", data); // AES-256-ECB 解密内容
  46. notify = parser.Parse(body, data);
  47. }
  48. else
  49. {
  50. CheckNotifySign(notify, options);
  51. }
  52. return notify;
  53. }
  54. #endregion
  55. #region Common Method
  56. private void CheckNotifySign(WeChatPayNotify notify, WeChatPayOptions options)
  57. {
  58. if (string.IsNullOrEmpty(notify.Body))
  59. {
  60. throw new WeChatPayException("sign check fail: Body is Empty!");
  61. }
  62. if (notify.Parameters.Count == 0)
  63. {
  64. throw new WeChatPayException("sign check fail: Parameters is Empty!");
  65. }
  66. if (!notify.Parameters.TryGetValue("sign", out var sign))
  67. {
  68. throw new WeChatPayException("sign check fail: sign is Empty!");
  69. }
  70. var cal_sign = WeChatPaySignature.SignWithKey(notify.Parameters, options.Key);
  71. if (cal_sign != sign)
  72. {
  73. throw new WeChatPayException("sign check fail: check Sign and Data Fail!");
  74. }
  75. }
  76. #endregion
  77. }
  78. }