Проверка Stripe API с несколькими элементами
У меня проблема с методом Checkout Session в Stripe API. Когда я жестко запрограммировал значения для цены и количества, 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",
]);
Может ли кто-нибудь заметить ошибку, которую я делаю? Я полагаю, что я не помещаю значения в массив соответствующим образом.
4 ответа
$line_items_array = array(
'price' => "{$price['id']}",
'quantity' => "{$value}"
);
и
'line_items' => [[$line_items_array]],
Я столкнулся с этим несколько недель назад. Служба поддержки Stripe не была заинтересована в помощи.
Обзор:
- Создайте то, что вы хотите, с помощью кода внешнего интерфейса.
- т.е.: массив объектов с такими ключами, как:
product
,quantity
, так далее. - Передайте этот массив объектов (через
JSON.stringify()
) на серверную часть PHP. - Прокрутите его в PHP и поместите в массив.
- Передайте этот массив в
line_items
ключ\Stripe\Checkout\Session::create()
.
Это довольно просто, но было сложно понять, потому что я не привык к PHP.
Мне, как новичку в PHP, это действительно помогло:
- https://jonsuh.com/blog/convert-loop-through-json-php-javascript-arrays-objects/
- https://www.geeksforgeeks.org/how-to-create-an-array-for-json-using-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]);
Возможно, сейчас немного поздно отвечать, но в любом случае после долгих испытаний и проб и ошибок вот что сработало для меня.
Я обнаружил, что передача списка массивов была серьезной проблемой, поэтому мне пришлось заново собрать массив, как только я получил его из ввода как json, перед передачей его в Stripe Create, который даже тогда, казалось, работал правильно только тогда, когда я использовал eval для массив при его передаче. В основном размещаю это, чтобы помочь кому-либо избежать боли, через которую я прошел :), я уверен, что есть способы сделать это лучше, но в то время я не мог найти нигде примеров, и это работает нормально уже почти год, поэтому я пока не пытался улучшить или изменить.
<?php
header("Content-Type: application/json");
require_once('stripe/vendor/autoload.php');
// Set your secret key. Remember to switch to your live secret key in production!
// See your keys here: https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey('whateveryouroneis');
// grab the json data from the cart, sent via php input
$data = (array) json_decode(file_get_contents("php://input"), TRUE);
//get the current webpage URL
$returnToPage = $_COOKIE["whateveryoursis"];
/**
* recursive read though what we recieved, try to get it to pass by rebuilding it
*/
function displayArrayRecursively($arr) {
if ($arr) {
foreach ($arr as $key => $value) {
if (is_array($value)) {
$arrs .= displayArrayRecursively($value);
} else {
// Output
if ( $key == 'name' ) {
$arrs .= " [ \"$key\" => '$value', \n";
}
elseif ( $key == 'quantity' ) {
$arrs .= " \"$key\" => $value , ], \n";
}
elseif ( in_array($key, ['description','currency'], true )) {
$arrs .= " \"$key\" => '$value', \n";
}
elseif ( $key == 'amount' ) {
$arrs .= " \"$key\" => " . $value * 100 . ", \n";
}
else {
$arrs .= " \"$key\" => ['$value'], \n";
}
}
}
}
return $arrs;
}
$line_items_str = displayArrayRecursively($data);
$createSession_str = (
"'payment_method_types' => ['card']," .
"'success_url' => '" . $returnToPage . "?success=1'," .
"'cancel_url' => '" . $returnToPage . "'," .
"'shipping_address_collection' => [" .
"'allowed_countries' => ['GB'], ]," .
"'line_items' => [" . $line_items_str . " ], ");
// create the checkout session on Stripe
eval ( $session = "\$session = \Stripe\Checkout\Session::create( [ " .
$createSession_str . " ] );" );
$stripeSession = array($session);
// test while working on it :-
// var_dump($stripeSession);
$sessId = ($stripeSession[0]['id']);
echo $sessId;
Я не уверен, но вы пытались удалить скобки в:'line_items' => [$line_items_array],
чтобы это выглядело так?'line_items' => $line_items_array,
У меня такое ощущение, что в исходных двойных скобках 'line_items' => [[внутренняя скобка объявляет массив, а внешняя скобка служит чем-то похожим на push или [] = array (для создания нового индекса для каждого элемента строки .
Итак, если вы передаете готовый массив, у меня такое чувство, что скобок не должно быть. Но я не знаю.