ASP.NET Core 8 MVC项目-嵌入式Stripe支付不起作用

问题描述 投票:0回答:3

我正在按照 Stripe 的在线文档为连接的帐户创建嵌入式付款表单。

https://docs.stripe.com/connect/direct-charges?platform=web&ui=embedded-form&client=html#mount-checkout

我的测试 API 密钥在

Program.cs
中设置正确。

我的控制器中的这个端点大部分直接来自 Stripe 的 API 指南,并且它很高兴地返回客户端密钥:

[HttpGet]
[AllowAnonymous]
public ContentResult StripeCheckoutSession()
{
        var options = new Stripe.Checkout.SessionCreateOptions
        {
            LineItems = new List<Stripe.Checkout.SessionLineItemOptions>
        {
            new Stripe.Checkout.SessionLineItemOptions
            {
                PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions
                {
                    Currency = "aud",
                    ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions
                    {
                        Name = "T-shirt",
                    },
                    UnitAmount = 1000,
                },
                Quantity = 1,
            },
        },
            PaymentIntentData = new Stripe.Checkout.SessionPaymentIntentDataOptions
            {
                ApplicationFeeAmount = 123,
            },
            Mode = "payment",
            UiMode = "embedded",
            ReturnUrl = "abc={CHECKOUT_SESSION_ID}"
        };
        var requestOptions = new RequestOptions
        {
            StripeAccount = "acct_12345...";
        };
        var service = new SessionService();
        Session session = service.Create(options, requestOptions);
        return Content(JsonConvert.SerializeObject(session.ClientSecret));
}

在我的

.cshtml
视图的头部,我添加了这个脚本元素:

<script src="https://js.stripe.com/v3/"></script>

在正文中我有这个标记:

<div id="checkout">
</div>

还在头部我有从 Stripe 的 API 指南复制的 JavaScript。

<script type="text/javascript">
    // initialize Stripe.js
    const stripe = Stripe('pk_test_blah...', {
       stripeAccount: {{CONNECTED_ACCOUNT_ID}},
    });

    initialize();

    // fetch checkout session and retrieve client secret
    async function initialize() {
      const fetchClientSecret = async () => {
        const response = await fetch("/StripeCheckoutSession", {
          method: "POST",
        });
        const { clientSecret } = await response.json();
        return clientSecret;
      };

      // initialize checkout
      const checkout = await stripe.initEmbeddedCheckout({
        fetchClientSecret,
      });

      // mount checkout
      checkout.mount('#checkout');
    }
</script>

注意,我已将

{{CONNECTED_ACCOUNT_ID}}
替换为对视图模型中实际值的引用,如下所示:

'@Model.StripeAccountID'

当我运行该项目时,没有任何反应 - 空白屏幕。我一半预料到了这一点,因为我不明白

initialize()
是如何被调用的。我发现它永远不会执行。

所以我写了js,我认为它应该如下工作:

    <script type="text/javascript">
        // initialize Stripe.js
        const stripe = Stripe('pk_test_blah...', {
            stripeAccount: '@Model.StripeAccountID',
        });

        $(document).ready(function () {
            initialize();
        })

        // fetch checkout session and retrieve the client secret
        async function initialize() {
            try {
                alert('Start');
                const fetchClientSecret = async () => {
                    const response = await fetch("StripeCheckoutSession", {
                        method: "GET",
                    });
                    const { clientSecret } = await response.json();
                    return clientSecret;
                };
                // initialize checkout
                alert('Init checkout');
                const checkout = await stripe.initEmbeddedCheckout({
                    fetchClientSecret,
                });
                // mount checkout
                alert('Finish mount');
                checkout.mount('#checkout');
            }
            catch (err) {
                alert(err);
            }
        }
</script>

我看到

alert('Start')
,然后看到
alert('Finish mount')
,但没有看到
alert('Init checkout')

我还尝试使用一个单独的函数,通过 AJAX 调用来获取客户端密钥。该功能本身有效,但初始化结帐失败。

我做错了什么?谁能帮我解决这个问题吗?

c# asp.net-core-mvc stripe-payments asp.net-core-8
3个回答
0
投票

他们的示例使用index.js +index.html,其工作方式与 MVC/Razor 页面略有不同。一件事是异步处理有点关闭。考虑尝试而不是包装新的异步方法:

async function initialize() {
    try {
        alert('Start');
        await fetch("StripeCheckoutSession", {
            method: "GET",
            headers: {
                'Content-Type': 'application/json'
            },
        }).then (response => {
            if (response.ok) {
                return response.json();
            } else { /* handle server exception */ }
        )}.then (data => {
            // initialize checkout
            alert('Init checkout');
            const checkout = await stripe.initEmbeddedCheckout({
                data.clientSecret
            });
            // mount checkout
            alert('Finish mount');
            checkout.mount('#checkout');
        });
    catch (err) {
        alert(err);
    }
}

除此之外,启用浏览器调试工具并检查控制台中的错误,并考虑在 JS 中设置断点以验证是否按预期调用了内容。


0
投票

我们首先要做的是打开浏览器控制台,看看初始化stripe.js时是否有错误

接下来,确保 @Model.StripeAccountID 解析为帐户 ID。您可以打印一些日志来确认这一点。我不熟悉 .net,但我找到了另一个page,它展示了如何将变量从 .net 传递到 javascript。


0
投票

这是给您的工作示例,您可以先检查一下。在此示例代码中我使用的是 IActionResult,而不是 ContentResult。

enter image description here

@model Demo.StripeSettings

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Stripe Embedded Checkout</title>
    <script src="https://js.stripe.com/v3/"></script>
</head>
<body>
    <div id="checkout"></div>

    <script type="text/javascript">

        const stripe = Stripe('@Model.PublishableKey', {
            stripeAccount: 'acct_1Q***XAU',
        });

        document.addEventListener("DOMContentLoaded", function () {
            initialize();
        });

        async function initialize() {
            try {
                const response = await fetch('/Payment/CreateCheckoutSession', {
                    method: 'GET',
                });
                const data = await response.json();
                const clientSecret = data.clientSecret;

                const checkout = await stripe.initEmbeddedCheckout({
                    clientSecret: clientSecret,
                });

                checkout.mount('#checkout');
            } catch (error) {
                console.error('Error:', error);
            }
        }
    </script>
</body>
</html>

控制器

using Demo.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Stripe.Checkout;
using Stripe;
using System.Diagnostics;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;

namespace Demo.Controllers
{
    public class PaymentController : Controller
    {
        private readonly ILogger<PaymentController> _logger;

        public PaymentController(ILogger<PaymentController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            var stripeSettings = new StripeSettings
            {
                PublishableKey = "pk_test_51QHc8D2LtiFaqkvHQ4VaoOG******NBOZuXO4WGqL00Mx3gYALt"
            };
            return View(stripeSettings);
        }


        [HttpGet]
        [AllowAnonymous]
        public IActionResult CreateCheckoutSession()
        {
            var options = new Stripe.Checkout.SessionCreateOptions
            {
                LineItems = new List<Stripe.Checkout.SessionLineItemOptions>
        {
            new Stripe.Checkout.SessionLineItemOptions
            {
                PriceData = new Stripe.Checkout.SessionLineItemPriceDataOptions
                {
                    Currency = "aud",
                    ProductData = new Stripe.Checkout.SessionLineItemPriceDataProductDataOptions
                    {
                        Name = "T-shirt",
                    },
                    UnitAmount = 1000,
                },
                Quantity = 1,
            },
        },
                PaymentIntentData = new Stripe.Checkout.SessionPaymentIntentDataOptions
                {
                    ApplicationFeeAmount = 123,
                },
                Mode = "payment",
                UiMode = "embedded",
                ReturnUrl = "https://your-domain.com/return?session_id=cs_test_a1b2c3d4e5f6g7h8i9j0k"
            };

            var requestOptions = new RequestOptions
            {
                StripeAccount = "acct_1Q***XAU",
            };

            var service = new SessionService();
            Session session = service.Create(options, requestOptions);

            return Json(new { clientSecret = session.ClientSecret });
        }
    }
}

条纹设置

namespace Demo
{
    public class StripeSettings
    {
        public string? SecretKey { get; set; }
        public string? PublishableKey { get; set; }
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.