WechatPayService.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. /// 微信支付统一下单获取Id(服务商模式)
  104. /// </summary>
  105. [HttpPost("/weChatPay/payPartnerTransaction")]
  106. public async Task<dynamic> CreatePayPartnerTransaction([FromBody] WechatPayTransactionInput input)
  107. {
  108. var request = new CreatePayPartnerTransactionJsapiRequest()
  109. {
  110. OutTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000), // YitIdHelper.NextId(), // 订单号
  111. AppId = _wechatPayOptions.AppId,
  112. MerchantId = _wechatPayOptions.MerchantId,
  113. SubAppId = _wechatPayOptions.AppId,
  114. SubMerchantId = _wechatPayOptions.MerchantId,
  115. Description = input.Description,
  116. Attachment = input.Attachment,
  117. GoodsTag = input.GoodsTag,
  118. ExpireTime = DateTimeOffset.Now.AddMinutes(10),
  119. NotifyUrl = _payCallBackOptions.WechatPayUrl,
  120. Amount = new CreatePayPartnerTransactionJsapiRequest.Types.Amount() { Total = input.Total },
  121. Payer = new CreatePayPartnerTransactionJsapiRequest.Types.Payer() { OpenId = input.OpenId }
  122. };
  123. var response = await _wechatTenpayClient.ExecuteCreatePayPartnerTransactionJsapiAsync(request);
  124. if (!response.IsSuccessful())
  125. throw Oops.Oh(response.ErrorMessage);
  126. // 保存订单信息
  127. var wechatPay = new WechatPay()
  128. {
  129. AppId = _wechatPayOptions.AppId,
  130. MerchantId = _wechatPayOptions.MerchantId,
  131. SubAppId = _wechatPayOptions.AppId,
  132. SubMerchantId = _wechatPayOptions.MerchantId,
  133. OutTradeNumber = request.OutTradeNumber,
  134. Description = input.Description,
  135. Attachment = input.Attachment,
  136. GoodsTag = input.GoodsTag,
  137. Total = input.Total,
  138. OpenId = input.OpenId
  139. };
  140. await _wechatPayUserRep.InsertAsync(wechatPay);
  141. return new
  142. {
  143. response.PrepayId,
  144. request.OutTradeNumber
  145. };
  146. }
  147. /// <summary>
  148. /// 获取支付订单详情
  149. /// </summary>
  150. /// <param name="tradeId"></param>
  151. /// <returns></returns>
  152. [HttpGet("/weChatPay/payInfo")]
  153. public async Task<WechatPay> GetWeChatPayInfo(string tradeId)
  154. {
  155. return await _wechatPayUserRep.GetFirstAsync(u => u.OutTradeNumber == tradeId);
  156. }
  157. /// <summary>
  158. /// 微信支付成功回调(商户直连)
  159. /// </summary>
  160. /// <returns></returns>
  161. [HttpPost("/notify/weChatPay/payCallBack")]
  162. [AllowAnonymous]
  163. public async Task WeChatPayCallBack()
  164. {
  165. using var ms = new MemoryStream();
  166. await App.HttpContext.Request.Body.CopyToAsync(ms);
  167. var b = ms.ToArray();
  168. var callbackJson = Encoding.UTF8.GetString(b);
  169. var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson);
  170. if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType))
  171. {
  172. var callbackResource = _wechatTenpayClient.DecryptEventResource<TransactionResource>(callbackModel);
  173. // 修改订单支付状态
  174. var wechatPay = await _wechatPayUserRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber
  175. && u.MerchantId == callbackResource.MerchantId);
  176. if (wechatPay == null) return;
  177. //wechatPay.OpenId = callbackResource.Payer.OpenId; // 支付者标识
  178. //wechatPay.MerchantId = callbackResource.MerchantId; // 微信商户号
  179. //wechatPay.OutTradeNumber = callbackResource.OutTradeNumber; // 商户订单号
  180. wechatPay.TransactionId = callbackResource.TransactionId; // 支付订单号
  181. wechatPay.TradeType = callbackResource.TradeType; // 交易类型
  182. wechatPay.TradeState = callbackResource.TradeState; // 交易状态
  183. wechatPay.TradeStateDescription = callbackResource.TradeStateDescription; // 交易状态描述
  184. wechatPay.BankType = callbackResource.BankType; // 付款银行类型
  185. wechatPay.Total = callbackResource.Amount.Total; // 订单总金额
  186. wechatPay.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额
  187. wechatPay.SuccessTime = callbackResource.SuccessTime; // 支付完成时间
  188. await _wechatPayUserRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
  189. }
  190. }
  191. /// <summary>
  192. /// 微信支付成功回调(服务商模式)
  193. /// </summary>
  194. /// <returns></returns>
  195. [HttpPost("/notify/weChatPay/payPartnerCallback")]
  196. [AllowAnonymous]
  197. public async Task WeChatPayPartnerCallBack()
  198. {
  199. using var ms = new MemoryStream();
  200. await App.HttpContext.Request.Body.CopyToAsync(ms);
  201. var b = ms.ToArray();
  202. var callbackJson = Encoding.UTF8.GetString(b);
  203. var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson);
  204. if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType))
  205. {
  206. var callbackResource = _wechatTenpayClient.DecryptEventResource<PartnerTransactionResource>(callbackModel);
  207. // 修改订单支付状态
  208. var wechatPay = await _wechatPayUserRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber
  209. && u.MerchantId == callbackResource.MerchantId);
  210. if (wechatPay == null) return;
  211. //wechatPay.OpenId = callbackResource.Payer.OpenId; // 支付者标识
  212. //wechatPay.MerchantId = callbackResource.MerchantId; // 微信商户号
  213. //wechatPay.OutTradeNumber = callbackResource.OutTradeNumber; // 商户订单号
  214. wechatPay.TransactionId = callbackResource.TransactionId; // 支付订单号
  215. wechatPay.TradeType = callbackResource.TradeType; // 交易类型
  216. wechatPay.TradeState = callbackResource.TradeState; // 交易状态
  217. wechatPay.TradeStateDescription = callbackResource.TradeStateDescription; // 交易状态描述
  218. wechatPay.BankType = callbackResource.BankType; // 付款银行类型
  219. wechatPay.Total = callbackResource.Amount.Total; // 订单总金额
  220. wechatPay.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额
  221. wechatPay.SuccessTime = callbackResource.SuccessTime; // 支付完成时间
  222. await _wechatPayUserRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
  223. }
  224. }
  225. }
  226. }