首页 > 编程语言 >微信支付--JSAPI支付(微信小程序和微信公众号支付都可以采用该方式)

微信支付--JSAPI支付(微信小程序和微信公众号支付都可以采用该方式)

时间:2023-01-05 00:55:06浏览次数:90  
标签:orderBasic Log -- 微信 await 支付 var new response

本实例使用了工具包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;
        }

 

标签:orderBasic,Log,--,微信,await,支付,var,new,response
From: https://www.cnblogs.com/cby-love/p/17026424.html

相关文章

  • Open Source Customer Support Chat System Implementation Of Pop-up Effect JavaScr
    WhenIwasimplementingtheonlinecustomersupportchatsystem'spopupeffectJavaScriptSDK,theSDKcodethatwaspubliclyexposedwasintheformofaself......
  • MYSQL中MVCC是什么?
    基本概念MVCC:全称Multi-VersionConcurrencyControl,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了--个非阻塞读功......
  • 浅谈一下go语言中的slice及其一些小坑
    数组数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。虽然数组元素可以被修改,但是数组长度是固定的,而且在go语言中数组的长度也是数组类......
  • django-重要 节点梳理
    视图继承关系图:  模型类和管理器继承关系图:序列器化关系图: ......
  • hello 2023 E
    关键用到了有向完全图的一些性质定理,还有就是缩点可以有两种理解:1.大的肯定可以,然后判断这个点可不可以,问一定可以的就行了,如果可以把win打死,那就一定可以(度数相同的点......
  • 代码随想录算法训练营第七天 |454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和
    454.四数相加II文章:代码随想录(programmercarl.com)视频:学透哈希表,map使用有技巧!LeetCode:454.四数相加II_哔哩哔哩_bilibili思路:首先定义一个unordered_map,key放a......
  • MySQL中limit的用法
      mySql提供了limit ,主要用于提取前几条或者中间某几行数据。select*fromtablelimitm,n其中m是指记录开始的index,从0开始,表示第一条记录n是指从第m+1条开始,取n......
  • leetcode-653. 两数之和 IV - 输入二叉搜索树
    653.两数之和IV-输入二叉搜索树-力扣(Leetcode)用了迭代进行遍历二叉树,因为二叉搜索树的中序遍历是有序的,所以肯定左边大于右边,然后就可以用一个map来存放之前的数值,......
  • 解决adb devices无法连接各种模拟器
    经常使用到模拟器的童鞋,如果在使用adbdevices命令时,发现出现“Listofdevicesattached”,模拟器USB调试都开启的情况下,也没有连接成功。这种情况一般都是模拟器adb的版......
  • BitLocker驱动器加锁和解锁
    应用场景:单位配备给你使用的电脑(Win10系统),偶尔也会有其他人使用。你可以设置某一个磁盘为你的私密数据存储空间,只有你输入密码后才能进入磁盘。即使系统重装、硬盘被拆......