WechatpayGateway.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #if NETCOREAPP3_1
  2. using Microsoft.Extensions.Options;
  3. #endif
  4. using System.Threading.Tasks;
  5. using PaySharp.Core;
  6. using PaySharp.Core.Exceptions;
  7. using PaySharp.Core.Request;
  8. using PaySharp.Core.Utils;
  9. using PaySharp.Wechatpay.Request;
  10. using PaySharp.Wechatpay.Response;
  11. using static PaySharp.Wechatpay.Response.QueryResponse;
  12. namespace PaySharp.Wechatpay
  13. {
  14. /// <summary>
  15. /// 微信支付网关
  16. /// </summary>
  17. public sealed class WechatpayGateway : BaseGateway
  18. {
  19. #region 私有字段
  20. private readonly Merchant _merchant;
  21. #endregion
  22. #region 构造函数
  23. /// <summary>
  24. /// 初始化微信支付网关
  25. /// </summary>
  26. /// <param name="merchant">商户数据</param>
  27. public WechatpayGateway(Merchant merchant)
  28. : base(merchant)
  29. {
  30. _merchant = merchant;
  31. }
  32. #if NETCOREAPP3_1
  33. /// <summary>
  34. /// 初始化微信支付网关
  35. /// </summary>
  36. /// <param name="merchant">商户数据</param>
  37. public WechatpayGateway(IOptions<Merchant> merchant)
  38. : this(merchant.Value)
  39. {
  40. }
  41. #endif
  42. #endregion
  43. #region 属性
  44. public override string GatewayUrl { get; set; } = "https://api.mch.weixin.qq.com";
  45. public new Merchant Merchant => _merchant;
  46. public new NotifyResponse NotifyResponse => (NotifyResponse)base.NotifyResponse;
  47. protected override bool IsPaySuccess => NotifyResponse.ResultCode == "SUCCESS" && !string.IsNullOrEmpty(NotifyResponse.TradeType);
  48. protected override bool IsRefundSuccess => NotifyResponse.RefundStatus == "SUCCESS";
  49. protected override bool IsCancelSuccess { get; }
  50. protected override string[] NotifyVerifyParameter => new string[]
  51. {
  52. "appid", "return_code", "mch_id", "nonce_str"
  53. };
  54. #endregion
  55. #region 方法
  56. protected override async Task<bool> ValidateNotifyAsync()
  57. {
  58. base.NotifyResponse = await GatewayData.ToObjectAsync<NotifyResponse>(StringCase.Snake);
  59. base.NotifyResponse.Raw = GatewayData.Raw;
  60. if (NotifyResponse.ReturnCode != "SUCCESS")
  61. {
  62. throw new GatewayException("不是成功的返回码");
  63. }
  64. if (string.IsNullOrEmpty(NotifyResponse.ReqInfo))
  65. {
  66. NotifyResponse.Coupons = ConvertUtil.ToList<CouponResponse, object>(GatewayData, -1);
  67. if (NotifyResponse.Sign != SubmitProcess.BuildSign(GatewayData, _merchant.Key))
  68. {
  69. throw new GatewayException("签名不一致");
  70. }
  71. }
  72. else
  73. {
  74. var tempNotify = NotifyResponse;
  75. var key = EncryptUtil.MD5(_merchant.Key).ToLower();
  76. var data = EncryptUtil.AESDecrypt(NotifyResponse.ReqInfo, key);
  77. var gatewayData = new GatewayData();
  78. gatewayData.FromXml(data);
  79. base.NotifyResponse = await gatewayData.ToObjectAsync<NotifyResponse>(StringCase.Snake);
  80. GatewayData.Add(NotifyResponse, StringCase.Snake);
  81. NotifyResponse.AppId = tempNotify.AppId;
  82. NotifyResponse.MchId = tempNotify.MchId;
  83. NotifyResponse.NonceStr = tempNotify.NonceStr;
  84. NotifyResponse.ReqInfo = tempNotify.ReqInfo;
  85. NotifyResponse.ReturnCode = tempNotify.ReturnCode;
  86. }
  87. return true;
  88. }
  89. protected override void WriteSuccessFlag()
  90. {
  91. GatewayData.Clear();
  92. GatewayData.Add("return_code", "SUCCESS");
  93. GatewayData.Add("return_msg", "OK");
  94. HttpUtil.Write(GatewayData.ToXml());
  95. }
  96. protected override void WriteFailureFlag()
  97. {
  98. GatewayData.Clear();
  99. GatewayData.Add("return_code", "FAIL");
  100. HttpUtil.Write(GatewayData.ToXml());
  101. }
  102. public override TResponse Execute<TModel, TResponse>(Request<TModel, TResponse> request)
  103. {
  104. if (request is OAuthRequest)
  105. {
  106. return SubmitProcess.AuthExecute(_merchant, request, GatewayUrl);
  107. }
  108. return SubmitProcess.Execute(_merchant, request, GatewayUrl);
  109. }
  110. #endregion
  111. }
  112. }