如何在Blazor WASM应用中处理Stripe的3D身份验证?
Blazor WASM集成Stripe Elements处理3D验证方案
核心思路
当支付意向(PaymentIntent)状态为requires_action时,通过Stripe.js的handleCardAction方法在当前页面内完成3D验证,无需跳转至Stripe服务器,验证完成后将结果同步回Blazor组件。
步骤1:服务器端修改PaymentIntent处理逻辑
创建PaymentIntent后,根据状态返回不同结果,将3D验证所需的client_secret传递给前端:
// 服务器端API方法 public async Task<IActionResult> ProcessPayment(long amount, string paymentMethodId) { PaymentIntentCreateOptions options = new() { Amount = amount, Currency = "gbp", PaymentMethod = paymentMethodId, Confirm = true, ConfirmationMethod = "automatic", // 按Stripe要求设置return_url,实际验证无需跳转,可设为结账页面URL ReturnUrl = "https://your-blazor-app.com/checkout" }; PaymentIntentService service = new(); PaymentIntent paymentIntent = await service.CreateAsync(options); // 根据状态返回对应数据 if (paymentIntent.Status == "requires_action") { return Ok(new { Status = paymentIntent.Status, ClientSecret = paymentIntent.ClientSecret, PaymentIntentId = paymentIntent.Id }); } else if (paymentIntent.Status == "succeeded") { return Ok(new { Status = "success", PaymentIntentId = paymentIntent.Id }); } else { return BadRequest(new { Status = paymentIntent.Status, Error = paymentIntent.LastPaymentError?.Message }); } }
步骤2:前端JS新增3D验证处理函数
在Stripe初始化的JS代码中,添加处理3D验证的函数,接收client_secret并调用Stripe的handleCardAction:
// 全局保存Stripe实例和CardElement引用 let stripe; let cardElement; let dotNetHelper; // 初始化Stripe和Elements async function initializeStripe(publishableKey) { stripe = Stripe(publishableKey); const elements = stripe.elements(); cardElement = elements.create('card'); cardElement.mount('#card-element'); } // 原创建PaymentMethod的函数(保留) async function createPaymentMethod(dotNetHelperRef) { dotNetHelper = dotNetHelperRef; const { error, paymentMethod } = await stripe.createPaymentMethod({ type: 'card', card: cardElement, billing_details: {} }); if (!error && dotNetHelper) { dotNetHelper.invokeMethodAsync('PaymentMethodCreated', JSON.stringify(paymentMethod)); } } // 新增处理3D验证的函数 async function handle3DSecure(clientSecret) { const { error, paymentIntent } = await stripe.handleCardAction(clientSecret); if (dotNetHelper) { if (error) { dotNetHelper.invokeMethodAsync('3DSecureFailed', error.message); } else { dotNetHelper.invokeMethodAsync('3DSecureCompleted', JSON.stringify(paymentIntent)); } } }
步骤3:Blazor组件处理验证流程
在Blazor组件中,接收服务器返回的结果,若需要3D验证则调用JS函数,并处理验证后的回调:
@inject IJSRuntime JSRuntime @inject HttpClient Http // 组件内字段 private DotNetObjectReference<CheckoutComponent>? _dotNetHelper; private string _paymentMethodId = string.Empty; protected override void OnInitialized() { _dotNetHelper = DotNetObjectReference.Create(this); // 初始化Stripe,替换为你的公钥 JSRuntime.InvokeVoidAsync("initializeStripe", "pk_test_your-stripe-publishable-key"); } // 接收PaymentMethod创建完成的回调 [JSInvokable] public async Task PaymentMethodCreated(string paymentMethodJson) { var paymentMethod = JsonSerializer.Deserialize<PaymentMethod>(paymentMethodJson); _paymentMethodId = paymentMethod.Id; // 调用服务器端处理支付 var response = await Http.PostAsJsonAsync("api/payment/process", new { Amount = 1000, PaymentMethodId = _paymentMethodId }); var result = await response.Content.ReadFromJsonAsync<PaymentResult>(); if (result.Status == "requires_action") { // 触发3D验证 await JSRuntime.InvokeVoidAsync("handle3DSecure", result.ClientSecret); } else if (result.Status == "success") { // 支付成功,更新UI StateHasChanged(); } else { // 处理其他错误 } } // 3D验证成功回调 [JSInvokable] public async Task 3DSecureCompleted(string paymentIntentJson) { var paymentIntent = JsonSerializer.Deserialize<PaymentIntent>(paymentIntentJson); if (paymentIntent.Status == "succeeded") { // 支付完成,更新UI或完成订单流程 } else { // 处理验证后的其他状态 } } // 3D验证失败回调 [JSInvokable] public void 3DSecureFailed(string errorMessage) { // 显示错误信息 } // 定义用于接收服务器结果的DTO public class PaymentResult { public string Status { get; set; } = string.Empty; public string? ClientSecret { get; set; } public string? PaymentIntentId { get; set; } public string? Error { get; set; } } public class PaymentMethod { public string Id { get; set; } = string.Empty; } public class PaymentIntent { public string Status { get; set; } = string.Empty; }
关键说明
handleCardAction会在当前页面弹出Stripe的3D验证界面,无需跳转,完全符合留在结账页面的需求。- 服务器端设置
ReturnUrl是Stripe的要求,但实际验证过程中不会触发跳转,可设为你的结账页面URL。 - 验证完成后,Stripe会自动更新PaymentIntent的状态,前端可直接根据返回的结果判断支付是否成功,也可再次调用服务器端接口确认状态以保证数据一致性。
内容的提问来源于stack exchange,提问作者Avrohom Yisroel
相关产品推荐
相关产品推荐

