如何使用 Django 和 JavaScript 为多个产品创建 Stripe Checkout Session?

How can I Create Stripe Checkout Session for multiple products with Django and JavaScript?

我正在构建一个网站,其中包含使用 Django 和 Stripe Checkout 购买的一些产品。我可以毫无问题地获得一种产品的结帐页面。但我想做的是创建一个包含多种产品的结帐页面。这是我在 Django views.py 中的功能。请注意,它以产品名称作为参数。如果我将我的条纹产品硬编码到 line_items 中,我可以获得包含多个产品的结帐会话。

def create_stripe_checkout_session(request, product_name):
    domain_url = 'http://localhost:5000/'
    try:
        checkout_session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            shipping_rates=[''],
            shipping_address_collection={'allowed_countries': ['US', 'CA']},
            metadata={'product_name': product_name, },
            line_items=[{'price': PRODUCTS_STRIPE_PRICING_ID[product_name],
                         'quantity': 1, 'adjustable_quantity': {'enabled': True, 'minimum': 1, 'maximum': 10, }, }],
            mode='payment',
            success_url=domain_url + 'success?session_id={CHECKOUT_SESSION_ID}',
            cancel_url=domain_url + 'cancelled.html',)

        return JsonResponse({'id': checkout_session.id})

    except Exception as e:
        print(e)
        raise SuspiciousOperation(e)

我的困难在于 JavaScript 获取。我的 .html 页面有一堆带有 class 'buy-button' 的产品按钮以及唯一的按钮值和 add/subtract 到购物车按钮。我能够跟踪我需要为多少产品和哪些产品创建结帐会话。我只是不知道如何用一个对象 literal/dictionary 或我可以传递给我的 create_stripe_checkout_session() 函数的其他数据结构替换 JS productName 变量,以便我能够收到多个付款产品而不仅仅是一个。

  
<script type="text/javascript">
    // Create an instance of the Stripe object with your publishable API key
    var stripe = Stripe('pk_test_6O........................4u00tQlwvoa9');


    // Gets all buy buttons
    var buttons = document.getElementsByClassName('buy-button');
    for (i = 0; i < buttons.length; i++) {

    // for every button we will add a Stripe POST request action
    buttons[i].addEventListener('click', function(event) {
    var targetElement = event.target || event.srcElement;
    var productName =  targetElement.value;
    console.log('Buying: ' + productName);

    // Our endpoint with the chosen product name
    var url = '/create-checkout-session/' + productName
    console.log(url);
    // Create a new Checkout Session
    fetch(url, {
      method: 'POST',
    })
    .then(function(response) {
      return response.json();
    })
    .then(function(session) {
      return stripe.redirectToCheckout({ sessionId: session.id });

    })
    .then(function(result) {
      // If `redirectToCheckout` fails due to a browser or network
      // error, you should display the localized error message to your
      // customer using `error.message`.
      if (result.error) {
        alert(result.error.message);
      }
    })
    .catch(function(error) {
      console.error('Error:', error);
    });

  });

}
</script>


所以我终于想出了如何使用 fetch body 参数来完成这个。希望其他人会发现这很有用,因为我花了一段时间,经过相当广泛的搜索后我找不到任何关于如何做的文档。我正在使用事件侦听器来获取我正在使用购物车按钮点击计数器跟踪的 item_1 和 item_2 值。此信息通过数据变量与 fetch 一起传递。

<script type="text/javascript">
    // Create an instance of the Stripe object with your publishable API key
    var stripe = Stripe('pk_test_51IuUC4K.........voa9');

    // Gets all buy buttons
    var buttons = document.getElementsByClassName('buy-button');
    for (i = 0; i < buttons.length; i++) {

   // for every button we will add a Stripe POST request action
    buttons[i].addEventListener('click', function(event) {
    var targetElement = event.target || event.srcElement;
    var productName =  targetElement.value;
    console.log('Buying: ' + productName);

    var data = JSON.stringify({
    item: ["item_1", "item_2"],
    item_quantity: [1, 3]
    })

    // Our endpoint with the chosen product name
    var url = '/create-checkout-session/' + productName
    console.log(url);
    // Create a new Checkout Session
    fetch(url, {
      method: 'POST',
      body: data,
      headers: { 'Accept': 'application/json, text/plain, */*','Content-Type': 'application/json'
        }
    })
    .then(function(response) {
      return response.json();
    })
    .then(function(session) {
      return stripe.redirectToCheckout({ sessionId: session.id });

    })
    .then(function(result) {
      // If `redirectToCheckout` fails due to a browser or network
      // error, you should display the localized error message to your
      // customer using `error.message`.
      if (result.error) {
        alert(result.error.message);
      }
    })
    .catch(function(error) {
      console.error('Error:', error);
    });

    });

    }

回到我的 views.py 文件,我现在可以将数据作为字典访问,并将其传递到 create_stripe_checkout_session() 函数中的 line_items 参数。这会覆盖用于发出原始结账会话请求的 productName 变量。

def create_stripe_checkout_session(request, product_name):
    domain_url = 'http://localhost:5000/'

    data = json.loads(request.body.decode("utf-8"))
    item = data['item']
    item_quantity = data['item_quantity']

    line_items_list = []
    for i, q in zip(item, item_quantity):
        line_items_list.append({'price': PRODUCTS_STRIPE_PRICING_ID[i],
                         'quantity': q, 'adjustable_quantity': {'enabled': True, 'minimum': 1, 'maximum': 10, }, })
    try:
        checkout_session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            shipping_rates=['shr_1J9fRXKMrN2iY6OwFXjmnVQP'],
            shipping_address_collection={'allowed_countries': ['US', 'CA']},
            line_items=line_items_list,
            mode='payment',
            success_url=domain_url + 'success?session_id={CHECKOUT_SESSION_ID}',
            cancel_url=domain_url + 'cancelled.html',)

        return JsonResponse({'id': checkout_session.id})