首页 > 解决方案 > 带多个项目的 Stripe API 结帐

问题描述

Stripe API 中的 Checkout Session 方法有问题。当我硬编码价格和数量的值时,Stripe 将允许我在结帐时使用多个项目,但是当我尝试动态加载这些值时,它只会列出购物车中的第一个产品。这是硬编码值的示例:

          $product = \Stripe\Product::create([
            'name' => "{$row['product_title']}",
            'images' => [
              "https://moto-d.net/wp-content/uploads/2018/01/webshop.jpg"
              ]
          ]);
          
          $price_100 = $row['product_price'] * 100;

          $price = \Stripe\Price::create([
            'product' => "{$product['id']}",
            'unit_amount' => "{$price_100}",
            'currency' => 'eur'
          ]);
  
      $session = \Stripe\Checkout\Session::create([
        'payment_method_types' => ['card'],
        'line_items' => [[
          'price' => 'price_1H1qQRAvwpgnxaFsFErrYUQs',
          'quantity' => 1
        ], [
          'price' => 'price_1H1qQSAvwpgnxaFsXR3XO8Sg',
          'quantity' => 1
        ], [
          'price' => 'price_1H1qQTAvwpgnxaFsfAAn8FMI',
          'quantity' => 1
        ], [
          'price' => 'price_1H1qQUAvwpgnxaFsX9KRfDPE',
          'quantity' => 1
        ]],
        'mode' => 'payment',
        'success_url' => "http://localhost/e-com-master/public/thank_you.php",
        'cancel_url' => "http://localhost/e-com-master/public/index.php",
     ]);
    }
   }
  }
      return $session['id'];

使用此代码,它可以完美运行。但是,问题就在这里(我使用数组来存储这些值):

         $line_items_array = array(
           "price" => $price['id'],
           "quantity" => $value
          );

      $session = \Stripe\Checkout\Session::create([
        'payment_method_types' => ['card'],
        'line_items' => [$line_items_array],
        'mode' => 'payment',
        'success_url' => "http://localhost/e-com-master/public/thank_you.php",
        'cancel_url' => "http://localhost/e-com-master/public/index.php",
      ]);

有人能注意到我犯的错误吗?我想我没有以适当的方式推送数组中的值。

标签: phpcheckoutstripe-payments

解决方案


几周前我刚刚遇到了这个问题。Stripe 支持没有兴趣提供帮助。

概述:

  • 通过前端代码构建line_items您想要的。
  • 即:具有键的对象数组,例如:productquantity等。
  • 将该对象数组(通过JSON.stringify())传递给后端 PHP。
  • 在 PHP 中循环遍历它并将其推送到一个数组中。
  • line_items在 的键中传递该数组\Stripe\Checkout\Session::create()

这很简单,但是因为我不习惯 PHP,所以很难正确处理。

作为 PHP 新手,这些对我很有帮助:

我包括你的文件的一切。create-checkout-session.php不只是foreach().

<?php


/* Standard Stripe API stuff */
require 'vendor/autoload.php';
\Stripe\Stripe::setApiKey("STRIPE_LIVE_SECRET_KEY_HERE");
header('Content-Type: application/json');
$YOUR_DOMAIN = 'http://localhost:4242';


/* Read in the JSON sent via the frontend */
$json_str = file_get_contents('php://input');


/*
 * Convert to PHP object
 * - NOT setting `json_decode($json_str, TRUE)` because having the data decoded into an *object* seems to work well. Also, Stripe's own sample code, for custom flows, does not set to `TRUE`.
 * - https://www.php.net/manual/en/function.json-decode.php
 */
$data = json_decode($json_str);


/* Create array to accept multiple `line_item` objects */
$lineItemsArray = [];


/*
 * [OPTIONAL] Create array to combine multiple keys from each`line_item` into a single one for `payment_intent_data.description`
 * - Only required if you want to pass along this type of description that's either provided by the user or by your frontend logic.
 * - IOW: It was useful to me, but it might not be to you.
 */
$descriptionInternal = [];


/* Convert the incoming JSON key/values into a PHP array() that the Stripe API will accept below in `\Stripe\Checkout\Session::create()` */
foreach($data as $key => $value) {

  /*
   * Swap frontend `price` for backend Stripe `price id`
   * - If you have Products/Prices that you created in the Stripe Dashboard, you might want to keep those Ids secret (although I don't know if that matters).
   * - So you'll need to convert whatever you define them as on the frontend (public), to the Stripe PriceId equivalents (private).
   * - This switch statement does that.
   */
  switch ($value->price) {
    case 50:
      $value->price = "price_1Iaxxxxxxx";
      break;
    case 100:
      $value->price = "price_1Ibxxxxxxx";
      break;
    case 150:
      $value->price = "price_1Icxxxxxxx";
      break;
    default:
      $value->price = "price_1Iaxxxxxxx";
  }


  /* `array_push` this object shape, for each `line_item` entry, into the array created outside of this `foreach()` loop. */
  array_push($lineItemsArray, 
    [
      "price" => $value->price, 
      "quantity" => $value->quantity,
      "customerName" => $value->customer_name,
      "recipientName" => $value->recipient_name,
      "description" => $value->description /* Customer facing on the Stripe "Pay" page */
      /*
       * Add whatever else you want to include, with each `line_item`, here.
       * - Stripe API allows:
       * - https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-line_items
      */
    ]);


  /*
   * [OPTIONAL] `array_push` some or all of the `line_item` key values in a combined form.
   * - Handy (in some cases) if you want to see a quick readout of the entire purchase in your Stripe Dashboard "Purchases" listing (i.e.: Saves you from having click into it to see the details).
   * - Or you could construct this via your frontend code and pass it as a string.
   * - But I'm including this here, in case you want to do it, or something like it, in in PHP.
   * - Example final result: "[Axl: 3 Guns N' Roses for Duff] [Slash: 6 Guns N' Roses for Izzy]"
   */
  array_push(
    $descriptionInternal, 
    ("[" . $value->customerName . ": " . $value->quantity . " Guns N' Roses for " . $value->recipientName) . "]");

}


/* [OPTIONAL] `payment_intent_data.description` takes a string, not an array. */
$descriptionInternal = implode(" ", $descriptionInternal);


/* https://stripe.com/docs/api/checkout/sessions/create */
$checkout_session = \Stripe\Checkout\Session::create([
  'payment_method_types' => ['card'],

  /* Takes in the array from above */
  'line_items' => $lineItemsArray,

  /* [OPTIONAL] Single `payment_intent_data.description` */
  'payment_intent_data' => [
    'description' => $descriptionInternal, /* This version of "Description" is displayed in the Dashboard and on Customer email receipts. */

  ],

  'mode' => 'payment',

  'success_url' => $YOUR_DOMAIN . '/success.html',
  'cancel_url' => $YOUR_DOMAIN . '/cancel.html',
]);

echo json_encode(['id' => $checkout_session->id]);

推荐阅读