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

Windows平台.NET MAUI应用集成Stripe支付网关的问题

在Windows平台的.NET MAUI中集成Stripe支付网关的解决方案

核心结论

Windows平台的.NET MAUI完全可以集成Stripe支付,且无需依赖网页跳转就能完成支付流程。你当前遇到的500内部错误,主要是因为Checkout Session的URL配置不当导致的,下面分步骤解决问题:


一、修复当前500错误的直接方案

你的SessionCreateOptions配置存在两个关键问题:

  1. URL格式错误:SuccessUrl中的{CHECKOUT_SESSION_ID}占位符没有正确嵌入(字符串拼接逻辑错误),导致Stripe无法识别合法的回调地址。
  2. 回调URL类型错误:MAUI桌面应用不需要Web页面作为回调地址,应使用自定义协议URL(如yourapp://checkout/success)或直接依赖Webhook处理结果。

修正后的SessionCreateOptions代码:

var options = new SessionCreateOptions
{
    // 使用自定义协议URL,MAUI可拦截该跳转
    SuccessUrl = "yourapp://checkout/success?sessionId={CHECKOUT_SESSION_ID}",
    CancelUrl = "yourapp://checkout/cancel",
    PaymentMethodTypes = new List<string>
    {
        "card"
    },
    LineItems = new List<SessionLineItemOptions>
    {
        new()
        {
            PriceData = new SessionLineItemPriceDataOptions
            {
                UnitAmount = (long)product.Price, // 注意:单位为USD美分
                Currency = "USD",
                ProductData = new SessionLineItemPriceDataProductDataOptions
                {
                    Name = product.BaseRequestId.ToString(),
                },
            },
            Quantity = 1,
        },
    },
    Mode = "payment" // 一次性支付模式
};

修正后重新创建Session,500错误应该会消失。


二、无需跳转的支付实现(推荐方案)

对于MAUI这类桌面/移动端应用,更适合使用Payment Intent + Stripe Payment Element的方案,完全避免页面跳转:

1. 后端创建Payment Intent

直接在后端生成Payment Intent,返回客户端需要的client_secret:

// CheckoutController.cs中的代码
[HttpPost]
public async Task<IActionResult> CreatePaymentIntent([FromBody] Order order)
{
    var product = /* 从订单中获取商品信息 */;
    var options = new PaymentIntentCreateOptions
    {
        Amount = (long)product.Price,
        Currency = "usd",
        AutomaticPaymentMethods = new PaymentIntentAutomaticPaymentMethodsOptions
        {
            Enabled = true, // 自动启用支持的支付方式
        },
    };

    var service = new PaymentIntentService();
    var paymentIntent = await service.CreateAsync(options);

    // 返回client_secret给MAUI客户端
    return Ok(new { ClientSecret = paymentIntent.ClientSecret });
}

2. MAUI客户端加载Payment Element

在MAUI页面中使用WebView加载本地HTML文件(嵌入Stripe.js),完成支付后通过JS与C#交互通知结果:

  • 本地HTML文件示例(放在MAUI项目的Resources/Raw目录):
<script src="https://js.stripe.com/v3/"></script>
<div id="payment-element"></div>
<button id="pay-button">确认支付</button>

<script>
  // 初始化Stripe,替换为你的公钥
  const stripe = Stripe('pk_test_your_public_key');
  const elements = stripe.elements();
  
  // 从C#端获取client_secret
  let clientSecret;
  window.chrome.webview.postMessage('request_client_secret');
  
  // 监听C#发送的client_secret
  window.addEventListener('message', async (event) => {
    if (event.data.type === 'client_secret') {
      clientSecret = event.data.value;
      // 创建并挂载Payment Element
      const paymentElement = elements.create('payment', {clientSecret});
      paymentElement.mount('#payment-element');
    }
  });

  // 处理支付提交
  document.getElementById('pay-button').addEventListener('click', async () => {
    const {error} = await stripe.confirmPayment({
      elements,
      confirmParams: {
        return_url: 'yourapp://payment/complete'
      }
    });

    if (error) {
      // 通知MAUI支付失败
      window.chrome.webview.postMessage({status: 'failed', message: error.message});
    } else {
      // 通知MAUI支付成功
      window.chrome.webview.postMessage({status: 'success'});
    }
  });
</script>
  • MAUI页面的C#代码:
// ReadyOrders.xaml.cs
private async void LoadPaymentForm()
{
    // 先从后端获取client_secret
    var response = await HttpClient.PostAsJsonAsync("https://localhost:44368/api/Checkout/CreatePaymentIntent", order);
    response.EnsureSuccessStatusCode();
    var result = await response.Content.ReadFromJsonAsync<PaymentIntentResponse>();

    // 加载本地HTML文件
    paymentWebView.Source = new HtmlWebViewSource
    {
        Html = await FileSystem.OpenAppPackageFileAsync("payment-form.html").ReadAsStringAsync()
    };

    // 监听WebView的消息
    paymentWebView.WebMessageReceived += (sender, e) =>
    {
        var message = JsonSerializer.Deserialize<WebMessage>(e.WebMessageAsString);
        if (message.Type == "request_client_secret")
        {
            // 发送client_secret给JS
            paymentWebView.EvaluateJavaScriptAsync($"window.postMessage({{type: 'client_secret', value: '{result.ClientSecret}'}}, '*');");
        }
        else if (message.Status == "success")
        {
            // 处理支付成功逻辑,比如更新订单状态
            MainThread.BeginInvokeOnMainThread(() =>
            {
                DisplayAlert("支付成功", "您的订单已完成支付", "确定");
            });
        }
        else if (message.Status == "failed")
        {
            MainThread.BeginInvokeOnMainThread(() =>
            {
                DisplayAlert("支付失败", message.Message, "确定");
            });
        }
    };
}

// 辅助类
public class PaymentIntentResponse { public string ClientSecret { get; set; } }
public class WebMessage { public string Type { get; set; } public string Status { get; set; } public string Message { get; set; } }

3. 配置Webhook确保结果可靠性

为了避免前端通知丢失,必须在Stripe后台配置Webhook,监听payment_intent.succeeded和payment_intent.payment_failed事件,在后端更新订单状态。MAUI客户端可以通过轮询后端接口或推送通知获取最终支付结果。


三、如果坚持使用Checkout Session的跳转方案

若仍想使用Checkout Session,需在MAUI中注册自定义协议来拦截Stripe的跳转:

  1. 在Windows项目的Package.appxmanifest中添加协议声明:
<Extensions>
  <uap:Extension Category="windows.protocol">
    <uap:Protocol Name="yourapp">
      <uap:DisplayName>你的应用名称</uap:DisplayName>
    </uap:Protocol>
  </uap:Extension>
</Extensions>
  1. 在App.xaml.cs中处理协议激活事件:
protected override void OnActivated(ActivatedEventArgs args)
{
    if (args is ProtocolActivatedEventArgs protocolArgs)
    {
        var uri = protocolArgs.Uri;
        if (uri.AbsolutePath == "/checkout/success")
        {
            var sessionId = uri.Query.Split('=')[1];
            // 调用后端接口验证Session状态,处理成功逻辑
            HandlePaymentSuccess(sessionId);
        }
        else if (uri.AbsolutePath == "/checkout/cancel")
        {
            // 处理支付取消逻辑
            HandlePaymentCancel();
        }
    }
    base.OnActivated(args);
}

内容的提问来源于stack exchange,提问作者CMlllll

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 15:14:52