|
本实例使用了工具包SKIT.FlurlHttpClient.Wechat.TenpayV3(github:https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat)
示例中的_repositoryWrapper的相关使用是我们业务中的业务代码,使用者可以根据自己的业务自行删除。
1、生成预支付订单(供前端调用,返回的信息供小程序端或公众号端调起微信支付).- public async Task<PayTransactionDto> GeneratePrePaidOrder(PrePaidOrderRequestDto orderBasic)
- {
- string orderStatus = await _repositoryWrapper.OrderRepository.QueryOrderStatusAsync(orderBasic.OrderId);
- //订单已取消||订单已支付
- if (orderStatus == OrderStatus.Cancel.ToString("D")
- || orderStatus == OrderStatus.PaySuccess.ToString("D"))
- {
- PayTransactionDto payTransaction = new()
- {
- OrderStatus = orderStatus,
- };
- return payTransaction;
- }
- //string serialNumber = RSAUtility.ExportSerialNumber(@"D:\1630126864_20220905_cert\apiclient_cert.pem");
- var manager = new InMemoryCertificateManager();
- var options = new WechatTenpayClientOptions()
- {
- MerchantId = _config["MerchantId"],//商户号
- MerchantV3Secret = _config["MerchantV3Secret"],//商户API v3密钥
- MerchantCertificateSerialNumber = _config["MerchantCertificateSerialNumber"],//商户API证书序列号
- MerchantCertificatePrivateKey = FileContentHelper.ReadFileContent("apiclient_key.pem", Path.Combine(AppContext.BaseDirectory, "apiclient_key.pem")),//商户API证书私钥
- PlatformCertificateManager = manager // 证书管理器的具体用法请参阅下文的高级技巧与加密、验签有关的章节
- };
- var client = new WechatTenpayClient(options);
- /* 以 JSAPI 统一下单接口为例 */
- //var userLogin = await _userService.UserLogin(orderBasic.JSCode);
- Log.Information("OpenId is " + orderBasic.OpenId);
- Log.Information("OrderId is " + orderBasic.OrderId);
- IEnumerable<OrderDetailEntity> orderList = await _repositoryWrapper.OrderRepository.GetOrderPriceAndQty(orderBasic.OrderId);
- int total = 0;
- foreach (OrderDetailEntity orderDetail in orderList)
- {
- total += orderDetail.TicketTypePrice * 100 * orderDetail.Qty;
- }
- total = (int)(total - orderBasic.UseWalletAmount * 100);
- long orderNumber = await _repositoryWrapper.OrderRepository.QueryOrderNumberByOrderIdAsync(orderBasic.OrderId);
- var request = new CreatePayTransactionJsapiRequest()
- {
- OutTradeNumber = orderNumber.ToString(),
- AppId = _config["EmscnplAppId"],//微信 AppId
- Description = $"订单号为{orderNumber}",
- ExpireTime = DateTimeOffset.Now.AddSeconds(200),
- NotifyUrl = _config["wechatPayNotifyUrl"],//回调地址
- Amount = new()
- {
- Total = total
- //Total = 1
- },
- Payer = new()
- {
- OpenId = orderBasic.OpenId
- //OpenId = "oLS5G5C9C2KZuYo-Y9HhyyP-RiFs"
- },
- Attachment = orderBasic.UseWalletAmount.ToString(),
- };
- //var response = await client.ExecuteCreatePayTransactionH5Async(request);
- var response = await client.ExecuteCreatePayTransactionJsapiAsync(request);
- Log.Information("response ExecuteCreatePayTransactionJsapiAsync {@response}", response);
- if (response.IsSuccessful())
- {
- //Console.WriteLine("PrepayId:" + response.PrepayId);
- //var collection = ExtractQueryParams(response.H5Url);
- //var prepayId = collection["prepay_id"];
- //var package= collection["package"];
- var paramMap = client.GenerateParametersForJsapiPayRequest(request.AppId, response.PrepayId);
- Log.Information("response paramMap {@paramMap}", paramMap);
- PayTransactionDto payTransaction = new()
- {
- WechatpayNonce = paramMap["nonceStr"],
- WechatpaySignature = paramMap["paySign"],
- WeChatPrepayId = response.PrepayId,
- TimeStamp = paramMap["timeStamp"],
- SignType = paramMap["signType"],
- Package = paramMap["package"],
- OrderStatus = orderStatus,
- };
- Log.Information("payTransaction information {@payTransaction}", payTransaction);
- await _repositoryWrapper.OrderRepository.UpdateOrderStatusAsync(new Contract.OrderStatusDto
- {
- OrderId = orderBasic.OrderId,
- OrderStatus = OrderStatus.PrePay.ToString("D")
- });
- await _repositoryWrapper.RedPackageRepository.BatchUpdateRedPackeStatus(orderBasic.VoucherId, orderBasic.WeChatId, orderBasic.OrderId, RedpackageUseEnum.Lock);
- await _repositoryWrapper.OrderRepository.BindWechatId(orderBasic.OrderId, orderBasic.WeChatId);
- return payTransaction;
- }
- else
- {
- throw new Exception("ExecuteCreatePayTransactionJsapiAsync call return fail");
- }
- }
复制代码 2、支付完成后的回调方法处理
Controller方法:- /// <summary>
- /// 支付成功后的回调函数
- /// </summary>
- /// <param name="timestamp"></param>
- /// <param name="nonce"></param>
- /// <param name="signature"></param>
- /// <param name="serialNumber"></param>
- /// <returns></returns>
- [HttpPost("WeChatPayNotifyUrl", Name = "WeChatPayNotifyUrl")]
- public async Task WeChatPayNotifyUrl(
- [FromHeader(Name = "Wechatpay-Timestamp")] string timestamp,
- [FromHeader(Name = "Wechatpay-Nonce")] string nonce,
- [FromHeader(Name = "Wechatpay-Signature")] string signature,
- [FromHeader(Name = "Wechatpay-Serial")] string serialNumber)
- {
- // 接收服务器推送
- // 文档:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_2.shtml
- using var reader = new StreamReader(Request.Body, Encoding.UTF8);
- string content = await reader.ReadToEndAsync();
- Log.Information("Wechatpay-Timestamp data is {@content}", content);
- Log.Information("Wechatpay-Nonce {@nonce}", nonce);
- Log.Information("Wechatpay-Signature {@signature}", signature);
- Log.Information("Wechatpay-Serial {@serialNumber}", serialNumber);
- _weChatAppService.ParseNotifyData(timestamp, nonce, content, signature, serialNumber);
-
- }
复制代码 Service方法:- public async void ParseNotifyData(string timeStamp, string nonce, string content, string signature, string serialNumber)
- {
- var manager = new InMemoryCertificateManager();
- var options = new WechatTenpayClientOptions()
- {
- MerchantId = _config["MerchantId"],//商户号
- MerchantV3Secret = _config["MerchantV3Secret"],//商户API v3密钥
- MerchantCertificateSerialNumber = _config["MerchantCertificateSerialNumber"],//商户API证书序列号
- MerchantCertificatePrivateKey = FileContentHelper.ReadFileContent("apiclient_key.pem", Path.Combine(AppContext.BaseDirectory, "apiclient_key.pem")),//商户API证书私钥
- PlatformCertificateManager = manager // 证书管理器的具体用法请参阅下文的高级技巧与加密、验签有关的章节
- };
- var client = new WechatTenpayClient(options);
- var request = new QueryCertificatesRequest();
- var response = await client.ExecuteQueryCertificatesAsync(request);
- if (response.IsSuccessful())
- {
- response = client.DecryptResponseSensitiveProperty(response);
- foreach (var certificateModel in response.CertificateList)
- {
- manager.AddEntry(new CertificateEntry(certificateModel));
- }
- Log.Information("查询微信商户平台证书成功。");
- }
- bool valid = client.VerifyEventSignature(timeStamp, nonce, content, signature, serialNumber, out Exception? error);
- if (valid)
- {
- /* 将 JSON 反序列化得到通知对象 */
- /* 你也可以将 WechatTenpayEvent 类型直接绑定到 MVC 模型上,这样就不再需要手动反序列化 */
- var callbackModel = client.DeserializeEvent(content);
- if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType))
- {
- /* 根据事件类型,解密得到支付通知敏感数据 */
- var callbackResource = client.DecryptEventResource<TransactionResource>(callbackModel);
- string outTradeNumber = callbackResource.OutTradeNumber;
- string transactionId = callbackResource.TransactionId;
- Log.Information("回调返回的解密数据为{@callbackResource}", callbackResource);
- Console.WriteLine("订单 {0} 已完成支付,交易单号为 {1}", outTradeNumber, transactionId);
- Log.Information("outTradeNumber is " + outTradeNumber);
- Log.Information("outTradeNumber is " + transactionId);
- #region[存取支付结果]
- string boxCode = await GetBoxCodeByOrderNumber(Convert.ToInt64(outTradeNumber));
- //解绑机器;
- await _repositoryWrapper.UserBoxRepository.UnBindBox(boxCode);
- var orderId = await _repositoryWrapper.OrderRepository.QueryOrderIdByOrderNumberAsync(Convert.ToInt64(outTradeNumber));
- Log.Information("Update order pay result");
- await _repositoryWrapper.OrderRepository.SavePayResult(new OrderEntity()
- {
- OrderId = orderId,
- OutTradeNo = Int64.Parse(outTradeNumber),
- TradeState = callbackResource.TradeState,
- TradeStateDesc = callbackResource.TradeStateDescription,
- BankType = callbackResource.BankType,
- Total = callbackResource.Amount.Total,
- OpenId = callbackResource.Payer.OpenId,
- PayTotal = callbackResource.Amount.PayerTotal,
- TransactionId = callbackResource.TransactionId,
- SuccessTime = callbackResource.SuccessTime.ToString()
- });
- #endregion
- Log.Information("Update order pay status");
- if (!String.IsNullOrWhiteSpace(callbackResource.Attachment))
- {
- decimal walletAmount = 0m;
- if (Decimal.TryParse(callbackResource.Attachment, out walletAmount) && walletAmount > 0)
- {
- string weChatId = await _repositoryWrapper.OrderRepository.QueryWeChatIdByOrderId(orderId);
- await _repositoryWrapper.WalletRepository.PayUseWallet(new List<long>(), orderId, weChatId, walletAmount, false, true);
- }
- }
- await _repositoryWrapper.OrderRepository.UpdateOrderStatusByOrderNumberAsync(Convert.ToInt64(outTradeNumber), OrderStatus.PaySuccess.ToString("D"), (decimal)callbackResource.Amount.PayerTotal / 100);
- await _repositoryWrapper.RedPackageRepository.BatchUpdateRedPackeStatus(orderId, RedpackageUseEnum.Used);
- }
- else
- {
- /* 根据事件类型,解密得到支付通知敏感数据 */
- var callbackResource = client.DecryptEventResource<TransactionResource>(callbackModel);
- string outTradeNumber = callbackResource.OutTradeNumber;
- JObject obj = new();
- obj.Add("action", "payFail");
- var payFailStr = JsonConvert.SerializeObject(obj);
- await _repositoryWrapper.OrderRepository.UpdateOrderStatusByOrderNumberAsync(Convert.ToInt64(outTradeNumber), OrderStatus.PayFail.ToString("D"), (decimal)callbackResource.Amount.PayerTotal / 100);
- }
- }
- else
- {
- Log.Error("Verify fail");
- Log.Error("Verify fail is {@error}", error);
- }
- }
复制代码 3、查询支付结果- _orderService是我们业务中使用的service,使用方可自行根据自身业务删除。
复制代码- public async Task<PayResultDto> QueryOrderPayStatus(OrderBaseDto orderBasic)
- {
- PayResultDto payResultDto = new PayResultDto();
- string orderStatus = await _repositoryWrapper.OrderRepository.QueryOrderStatusAsync(orderBasic.OrderId);
- if (orderStatus != null)
- {
- OrderStatus orderEnumStatus = OrderStatus.UnDefine;
- if (System.Enum.TryParse(orderStatus, out orderEnumStatus) && orderEnumStatus == OrderStatus.PaySuccess)
- {
- payResultDto.PaySuccess = true;
- payResultDto.ContributionAmount = await _orderService.GetOrderContributionAsync(orderBasic.OrderId); ;
- return payResultDto;
- }
- }
- //string serialNumber = RSAUtility.ExportSerialNumber(@"D:\1630126864_20220905_cert\apiclient_cert.pem");
- var manager = new InMemoryCertificateManager();
- var options = new WechatTenpayClientOptions()
- {
- MerchantId = _config["MerchantId"],//商户号
- MerchantV3Secret = _config["MerchantV3Secret"],//商户API v3密钥
- MerchantCertificateSerialNumber = _config["MerchantCertificateSerialNumber"],//商户API证书序列号
- MerchantCertificatePrivateKey = FileContentHelper.ReadFileContent("apiclient_key.pem", Path.Combine(AppContext.BaseDirectory, "apiclient_key.pem")),//商户API证书私钥
- PlatformCertificateManager = manager // 证书管理器的具体用法请参阅下文的高级技巧与加密、验签有关的章节
- };
- var client = new WechatTenpayClient(options);
- /* 以 JSAPI 统一下单接口为例 */
- //var userLogin = await _userService.UserLogin(orderBasic.JSCode);
- Log.Information("OrderId is " + orderBasic.OrderId);
- long orderNumber = await _repositoryWrapper.OrderRepository.QueryOrderNumberByOrderIdAsync(orderBasic.OrderId);
- var request = new GetPayTransactionByOutTradeNumberRequest()
- {
- OutTradeNumber = orderNumber.ToString(),
- MerchantId = _config["MerchantId"],//商户号
- WechatpayCertificateSerialNumber = _config["MerchantCertificateSerialNumber"]//商户API证书序列号
- };
- var response = await client.ExecuteGetPayTransactionByOutTradeNumberAsync(request);
- Log.Information("response {@response}", response);
- if (response.IsSuccessful() && response.TradeState == "SUCCESS")
- {
- int payTotal = response.Amount.Total;
- Console.WriteLine("pay amount:" + payTotal);
- Log.Information($"QueryOrder order {orderNumber} payTotal is {payTotal}");
- if (payTotal > 0)
- {
- await _repositoryWrapper.OrderRepository.UpdateOrderStatusAsync(new OrderStatusDto()
- {
- OrderId = orderBasic.OrderId,
- OrderStatus = OrderStatus.PaySuccess.ToString("D"),
- });
- payResultDto.PaySuccess = true;
- payResultDto.ContributionAmount = await _orderService.GetOrderContributionAsync(orderBasic.OrderId);
- //payResultDto.Amount = payTotal/100m;
- }
- }
- else
- {
- Log.Information($"response.RawStatus is {response.RawStatus}");
- Log.Information($"response.ErrorCode is {response.ErrorCode},response.ErrorMessage is {response.ErrorMessage}");
- //throw new Exception($"QueryOrder call return fail,orderNumber is {orderNumber}");
- }
- return payResultDto;
- }
复制代码
出处:https://www.cnblogs.com/cby-love本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利.如果您觉得文章对您有帮助,可以点击文章右下角"推荐".您的鼓励是作者坚持原创和持续写作的最大动力!
来源:https://www.cnblogs.com/cby-love/archive/2023/01/05/17026424.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|