最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

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

来源:博客园


(资料图片仅供参考)

本实例使用了工具包SKIT.FlurlHttpClient.Wechat.TenpayV3(github:https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat)

示例中的_repositoryWrapper的相关使用是我们业务中的业务代码,使用者可以根据自己的业务自行删除。

1、生成预支付订单(供前端调用,返回的信息供小程序端或公众号端调起微信支付).

public async Task 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 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方法:

///         /// 支付成功后的回调函数        ///         ///         ///         ///         ///         ///         [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(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(), 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(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 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;        }

关键词: 高级技巧 反序列化 敏感数据