You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:07:09