WechatPayService.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using Furion;
  2. using Furion.DependencyInjection;
  3. using Furion.DynamicApiController;
  4. using Furion.FriendlyException;
  5. using Microsoft.AspNetCore.Authorization;
  6. using Microsoft.AspNetCore.Mvc;
  7. using Microsoft.Extensions.Options;
  8. using SKIT.FlurlHttpClient.Wechat.TenpayV3;
  9. using SKIT.FlurlHttpClient.Wechat.TenpayV3.Events;
  10. using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
  11. using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
  12. using System;
  13. using System.IO;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. namespace Admin.NET.Core.Service
  17. {
  18. /// <summary>
  19. /// 微信支付服务
  20. /// </summary>
  21. [ApiDescriptionSettings(Name = "微信支付", Order = 99)]
  22. public class WeChatPayService : IDynamicApiController, ITransient
  23. {
  24. private readonly SqlSugarRepository<WechatPay> _wechatPayUserRep;
  25. private readonly WechatPayOptions _wechatPayOptions;
  26. private readonly WechatTenpayClient _wechatTenpayClient;
  27. private readonly PayCallBackOptions _payCallBackOptions;
  28. public WeChatPayService(SqlSugarRepository<WechatPay> wechatPayUserRep,
  29. IOptions<WechatPayOptions> wechatPayOptions,
  30. IOptions<PayCallBackOptions> payCallBackOptions)
  31. {
  32. _wechatPayUserRep = wechatPayUserRep;
  33. _wechatPayOptions = wechatPayOptions.Value;
  34. _wechatTenpayClient = CreateTenpayClient();
  35. _payCallBackOptions = payCallBackOptions.Value;
  36. }
  37. /// <summary>
  38. /// 初始化微信支付客户端
  39. /// </summary>
  40. /// <returns></returns>
  41. private WechatTenpayClient CreateTenpayClient()
  42. {
  43. var tenpayClientOptions = new WechatTenpayClientOptions()
  44. {
  45. MerchantId = _wechatPayOptions.MerchantId,
  46. MerchantV3Secret = _wechatPayOptions.MerchantV3Secret,
  47. MerchantCertificateSerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber,
  48. MerchantCertificatePrivateKey = CommonUtil.GetRootPathFileText(_wechatPayOptions.MerchantCertificatePrivateKey),
  49. PlatformCertificateManager = new InMemoryCertificateManager()
  50. };
  51. return new WechatTenpayClient(tenpayClientOptions);
  52. }
  53. /// <summary>
  54. /// 生成JSAPI调起支付所需参数
  55. /// </summary>
  56. /// <param name="input"></param>
  57. /// <returns></returns>
  58. [HttpPost("/weChatPay/genPayPara")]
  59. public dynamic GenerateParametersForJsapiPay(WechatPayParaInput input)
  60. {
  61. return _wechatTenpayClient.GenerateParametersForJsapiPayRequest(_wechatPayOptions.AppId, input.PrepayId);
  62. }
  63. /// <summary>
  64. /// 微信支付统一下单获取Id
  65. /// </summary>
  66. [HttpPost("/weChatPay/payTransaction")]
  67. public async Task<dynamic> CreatePayTransaction([FromBody] WechatPayTransactionInput input)
  68. {
  69. var request = new CreatePayTransactionJsapiRequest()
  70. {
  71. OutTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000), // YitIdHelper.NextId(), // 订单号
  72. AppId = _wechatPayOptions.AppId,
  73. Description = input.Description,
  74. Attachment = input.Attachment,
  75. GoodsTag = input.GoodsTag,
  76. ExpireTime = DateTimeOffset.Now.AddMinutes(10),
  77. NotifyUrl = _payCallBackOptions.WechatPayUrl,
  78. Amount = new CreatePayTransactionJsapiRequest.Types.Amount() { Total = input.Total },
  79. Payer = new CreatePayTransactionJsapiRequest.Types.Payer() { OpenId = input.OpenId }
  80. };
  81. var response = await _wechatTenpayClient.ExecuteCreatePayTransactionJsapiAsync(request);
  82. if (!response.IsSuccessful())
  83. throw Oops.Oh(response.ErrorMessage);
  84. // 保存订单信息
  85. var wechatPay = new WechatPay()
  86. {
  87. MerchantId = _wechatPayOptions.MerchantId,
  88. OutTradeNumber = request.OutTradeNumber,
  89. Description = input.Description,
  90. Attachment = input.Attachment,
  91. GoodsTag = input.GoodsTag,
  92. Total = input.Total,
  93. OpenId = input.OpenId
  94. };
  95. await _wechatPayUserRep.InsertAsync(wechatPay);
  96. return new
  97. {
  98. response.PrepayId,
  99. request.OutTradeNumber
  100. };
  101. }
  102. /// <summary>
  103. /// 获取支付订单详情
  104. /// </summary>
  105. /// <param name="tradeId"></param>
  106. /// <returns></returns>
  107. [HttpGet("/weChatPay/payInfo")]
  108. public async Task<WechatPay> GetWeChatPayInfo(string tradeId)
  109. {
  110. return await _wechatPayUserRep.GetFirstAsync(u => u.OutTradeNumber == tradeId);
  111. }
  112. /// <summary>
  113. /// 微信支付成功回调(商户平台发来的通知内容)
  114. /// </summary>
  115. /// <returns></returns>
  116. [HttpPost("/notify/weChatPay/unifiedorder")]
  117. [AllowAnonymous]
  118. public async Task WeChatPayCallBack()
  119. {
  120. using var ms = new MemoryStream();
  121. await App.HttpContext.Request.Body.CopyToAsync(ms);
  122. var b = ms.ToArray();
  123. var callbackJson = Encoding.UTF8.GetString(b);
  124. var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson);
  125. if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType))
  126. {
  127. var callbackResource = _wechatTenpayClient.DecryptEventResource<TransactionResource>(callbackModel);
  128. // 修改订单支付状态
  129. var wechatPay = await _wechatPayUserRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber
  130. && u.MerchantId == callbackResource.MerchantId);
  131. if (wechatPay == null) return;
  132. //wechatPay.OpenId = callbackResource.Payer.OpenId; // 支付者标识
  133. //wechatPay.MerchantId = callbackResource.MerchantId; // 微信商户号
  134. //wechatPay.OutTradeNumber = callbackResource.OutTradeNumber; // 商户订单号
  135. wechatPay.TransactionId = callbackResource.TransactionId; // 支付订单号
  136. wechatPay.TradeType = callbackResource.TradeType; // 交易类型
  137. wechatPay.TradeState = callbackResource.TradeState; // 交易状态
  138. wechatPay.TradeStateDescription = callbackResource.TradeStateDescription; // 交易状态描述
  139. wechatPay.BankType = callbackResource.BankType; // 付款银行类型
  140. wechatPay.Total = callbackResource.Amount.Total; // 订单总金额
  141. wechatPay.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额
  142. wechatPay.SuccessTime = callbackResource.SuccessTime; // 支付完成时间
  143. await _wechatPayUserRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
  144. }
  145. }
  146. }
  147. }