微信支付--JSAPI支付(微信小程序和微信公众号支付都可以采用该方式)
本实例使用了工具包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>
public async Task WeChatPayNotifyUrl(
string timestamp,
string nonce,
string signature,
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本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利.如果您觉得文章对您有帮助,可以点击文章右下角"推荐".您的鼓励是作者坚持原创和持续写作的最大动力!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]