From f512e9d367f886b15688b5f89a34b9be4d83df10 Mon Sep 17 00:00:00 2001 From: xiong Date: Sun, 26 Jul 2026 19:46:39 +0800 Subject: [PATCH] fix: enable sdk payment checkout providers --- .../Commerce/AlipayProvider.cs | 50 ++++++++++++++-- .../Commerce/WechatPayProvider.cs | 58 +++++++++++++++++-- 2 files changed, 100 insertions(+), 8 deletions(-) diff --git a/Tiku.Infrastructure/Commerce/AlipayProvider.cs b/Tiku.Infrastructure/Commerce/AlipayProvider.cs index e9e0645..ac08a4f 100644 --- a/Tiku.Infrastructure/Commerce/AlipayProvider.cs +++ b/Tiku.Infrastructure/Commerce/AlipayProvider.cs @@ -1,5 +1,7 @@ using System.Text.Json; using Aop.Api; +using Aop.Api.Domain; +using Aop.Api.Request; using Aop.Api.Util; using Tiku.Application.Commerce; @@ -14,10 +16,47 @@ internal sealed class AlipayProvider : IPaymentProvider CreatePaymentProviderRequest request, CancellationToken cancellationToken = default) { - _ = BuildClient(account); - throw new PaymentProviderException( - "Alipay SDK is configured; checkout call is enabled in the commerce checkout batch.", - "alipay_checkout_not_enabled"); + _ = cancellationToken; + var client = BuildClient(account); + var alipayRequest = new AlipayTradeWapPayRequest(); + alipayRequest.SetNotifyUrl(request.NotifyUrl); + if (!string.IsNullOrWhiteSpace(request.ReturnUrl)) + { + alipayRequest.SetReturnUrl(request.ReturnUrl); + } + + alipayRequest.SetBizModel(new AlipayTradeWapPayModel + { + OutTradeNo = request.OrderNo, + Subject = request.Subject, + TotalAmount = FormatYuan(request.AmountCents), + ProductCode = "QUICK_WAP_WAY", + QuitUrl = request.QuitUrl + }); + var response = client.pageExecute(alipayRequest); + if (string.IsNullOrWhiteSpace(response.Body)) + { + throw new PaymentProviderException("Alipay create payment returned an empty body.", "alipay_create_failed"); + } + + var clientPayload = JsonSerializer.SerializeToElement(new + { + formHtml = response.Body + }); + var rawPayload = JsonSerializer.SerializeToElement(new + { + response.Body, + request.OrderNo, + request.AmountCents + }); + + return Task.FromResult(new CreatePaymentProviderResult( + Provider, + request.Method, + "pending", + null, + clientPayload, + rawPayload)); } public Task ParsePaymentNotificationAsync( @@ -138,4 +177,7 @@ internal sealed class AlipayProvider : IPaymentProvider ? (int)Math.Round(amount * 100, MidpointRounding.AwayFromZero) : 0; } + + private static string FormatYuan(int cents) => + (cents / 100m).ToString("0.00", System.Globalization.CultureInfo.InvariantCulture); } diff --git a/Tiku.Infrastructure/Commerce/WechatPayProvider.cs b/Tiku.Infrastructure/Commerce/WechatPayProvider.cs index 35460e8..67fa077 100644 --- a/Tiku.Infrastructure/Commerce/WechatPayProvider.cs +++ b/Tiku.Infrastructure/Commerce/WechatPayProvider.cs @@ -16,10 +16,7 @@ internal sealed class WechatPayProvider : IPaymentProvider CreatePaymentProviderRequest request, CancellationToken cancellationToken = default) { - _ = BuildClient(account); - throw new PaymentProviderException( - "WeChat Pay SDK is configured; checkout call is enabled in the commerce checkout batch.", - "wechat_pay_checkout_not_enabled"); + return CreatePaymentCoreAsync(account, request, cancellationToken); } public Task ParsePaymentNotificationAsync( @@ -73,6 +70,59 @@ internal sealed class WechatPayProvider : IPaymentProvider return WechatTenpayClientBuilder.Create(options).Build(); } + private async Task CreatePaymentCoreAsync( + PaymentProviderAccount account, + CreatePaymentProviderRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrWhiteSpace(request.OpenId)) + { + throw new PaymentProviderException("WeChat Pay JSAPI requires openId.", "wechat_pay_openid_required"); + } + + var client = BuildClient(account); + var appId = Required(account.ConfigPublic, "appId"); + var wxRequest = new CreatePayTransactionJsapiRequest + { + AppId = appId, + Description = request.Subject, + OutTradeNumber = request.OrderNo, + NotifyUrl = request.NotifyUrl, + Amount = new CreatePayTransactionJsapiRequest.Types.Amount + { + Total = request.AmountCents + }, + Payer = new CreatePayTransactionJsapiRequest.Types.Payer + { + OpenId = request.OpenId + } + }; + var response = await client.ExecuteCreatePayTransactionJsapiAsync(wxRequest, cancellationToken); + if (!response.IsSuccessful()) + { + throw new PaymentProviderException( + $"WeChat Pay create transaction failed: {response.ErrorCode}", + "wechat_pay_create_failed"); + } + + var clientPayload = JsonSerializer.SerializeToElement( + client.GenerateParametersForJsapiPayRequest(appId, response.PrepayId)); + var rawPayload = JsonSerializer.SerializeToElement(new + { + response.PrepayId, + request.OrderNo, + request.AmountCents + }); + + return new CreatePaymentProviderResult( + Provider, + request.Method, + "pending", + null, + clientPayload, + rawPayload); + } + private static string Required(JsonElement element, params string[] keys) { if (element.ValueKind == JsonValueKind.Object)