.NET Core 6.0 Web应用集成Stripe支付及触发逻辑改造咨询
在.NET Core 6 Web应用中集成Stripe支付功能
以下是针对需求的完整实现方案,点击Save按钮时将触发发票保存+信用卡支付的完整流程:
1. 安装Stripe.NET SDK
通过NuGet安装适配.NET 6的Stripe官方SDK:
Install-Package Stripe.net -Version 43.0.0 # 选择稳定兼容版本
2. 配置Stripe密钥
在appsettings.json中添加从Stripe控制台获取的密钥信息:
{ "Stripe": { "SecretKey": "sk_test_你的私有密钥", "PublishableKey": "pk_test_你的公开密钥", "WebhookSecret": "whsec_你的Webhook密钥" // 可选,用于后续异步支付状态通知 }, "ConnectionStrings": { "DBConnection": "你的数据库连接字符串" } }
3. 修改视图(View)
更新视图引入Stripe支付组件,替换同步表单提交为异步支付流程:
@model SalesInvoiceModel <h2>Create Invoice</h2> <!-- 引入Stripe.js --> <script src="https://js.stripe.com/v3/"></script> <script> // 初始化Stripe实例 const stripe = Stripe('@Configuration["Stripe:PublishableKey"]'); const elements = stripe.elements(); // 渲染信用卡输入组件 const cardElement = elements.create('card'); cardElement.mount('#card-element'); // 处理Save按钮点击事件 document.getElementById('save-pay-btn').addEventListener('click', async (e) => { e.preventDefault(); // 第一步:提交发票信息到后端创建发票并获取支付凭证 const invoiceResponse = await fetch('/SalesInvoice/CreateInvoiceAndInitPayment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value }, body: JSON.stringify({ Id: document.getElementById('Id').value, TotalAmount: document.getElementById('TotalAmount').value }) }); if (!invoiceResponse.ok) { alert('发票创建失败,请重试'); return; } const paymentData = await invoiceResponse.json(); // 第二步:唤起Stripe支付界面完成信用卡验证 const { error, paymentIntent } = await stripe.confirmCardPayment( paymentData.clientSecret, { payment_method: { card: cardElement, billing_details: { name: '客户姓名' // 可根据业务需求从表单获取 } } } ); if (error) { alert(`支付失败:${error.message}`); } else if (paymentIntent.status === 'succeeded') { // 支付成功后跳转至发票列表页 window.location.href = '/SalesInvoice/InvoiceList'; } }); </script> @using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary() @Html.HiddenFor(m => m.Id) <div class="form-group"> <label asp-for="TotalAmount"></label> <input asp-for="TotalAmount" class="form-control" id="TotalAmount" readonly /> <span asp-validation-for="TotalAmount" class="text-danger"></span> </div> <!-- Stripe信用卡输入区域 --> <div class="form-group mt-3"> <label>信用卡信息</label> <div id="card-element" class="form-control"></div> <div id="card-errors" role="alert" class="text-danger mt-1"></div> </div> <br /> <button type="button" id="save-pay-btn" class="btn btn-primary">Save & Pay</button> }
4. 更新控制器(Controller)
新增Action处理发票创建+支付初始化逻辑,保留原有数据库操作:
using Stripe; public class SalesInvoiceController : Controller { private readonly IConfiguration _configuration; public SalesInvoiceController(IConfiguration configuration) { _configuration = configuration; // 全局初始化Stripe密钥 StripeConfiguration.ApiKey = _configuration["Stripe:SecretKey"]; } // 创建发票并生成Stripe支付凭证 [HttpPost] public async Task<IActionResult> CreateInvoiceAndInitPayment(SalesInvoiceModel model) { if (!ModelState.IsValid) { return BadRequest(ModelState); } int invoiceId = 0; // 1. 将发票信息保存到数据库 using (SqlConnection connection = new SqlConnection(_configuration.GetConnectionString("DBConnection"))) { using (SqlCommand command = new SqlCommand("sp_AddInvoiceDetails", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@Id", model.Id); command.Parameters.AddWithValue("@TotalAmount", model.TotalAmount); connection.Open(); invoiceId = Convert.ToInt32(command.ExecuteScalar()); } } // 2. 创建Stripe支付意向(PaymentIntent) var paymentOptions = new PaymentIntentCreateOptions { Amount = (long)(model.TotalAmount * 100), // Stripe金额单位为分 Currency = "usd", // 按需修改为对应货币,如"cny" Metadata = new Dictionary<string, string> { { "InvoiceId", invoiceId.ToString() } // 关联发票ID,用于后续状态更新 } }; var paymentService = new PaymentIntentService(); PaymentIntent paymentIntent = await paymentService.CreateAsync(paymentOptions); // 返回支付凭证给前端 return Json(new { clientSecret = paymentIntent.ClientSecret }); } // 原有CreateInvoice方法(可保留作为无支付场景备用) [HttpPost] public IActionResult CreateInvoice(SalesInvoiceModel model) { using (SqlConnection connection = new SqlConnection(_configuration.GetConnectionString("DBConnection"))) { using (SqlCommand command = new SqlCommand("sp_AddInvoiceDetails", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@Id", model.Id); command.Parameters.AddWithValue("@TotalAmount", model.TotalAmount); connection.Open(); int userId = Convert.ToInt32(command.ExecuteScalar()); TempData["SuccessMessage"] = "Invoice created successfully."; return RedirectToAction("InvoiceList", "SalesInvoice"); } } } // 可选:Stripe Webhook处理(异步更新支付状态) [HttpPost] public async Task<IActionResult> StripeWebhook() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); var stripeEvent = EventUtility.ConstructEvent( json, Request.Headers["Stripe-Signature"], _configuration["Stripe:WebhookSecret"] ); if (stripeEvent.Type == Events.PaymentIntentSucceeded) { var paymentIntent = stripeEvent.Data.Object as PaymentIntent; var invoiceId = int.Parse(paymentIntent.Metadata["InvoiceId"]); // 更新数据库中发票的支付状态 using (SqlConnection connection = new SqlConnection(_configuration.GetConnectionString("DBConnection"))) { using (SqlCommand command = new SqlCommand("sp_UpdateInvoicePaymentStatus", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@InvoiceId", invoiceId); command.Parameters.AddWithValue("@IsPaid", true); connection.Open(); command.ExecuteNonQuery(); } } } return Ok(); } }
核心注意事项
- Stripe金额单位为分,需将
TotalAmount乘以100后传入 - 生产环境必须使用HTTPS协议,否则Stripe支付组件无法正常工作
- Webhook为可选但推荐配置,用于确保支付状态更新的可靠性(避免前端跳转导致的状态丢失)
内容的提问来源于stack exchange,提问作者Anisha Ramanuj
相关产品推荐
相关产品推荐

