Я интегрирую Stripe для своей платформы, которая использует Next.js и Laravel.
Я не могу понять, как я могу получить данные и сохранить их в базе данных MY Platform.
Например, пользователь покупает клавиатуру за 50 долларов. Как я могу получить эту информацию item_name
и price
в Laravel.
Ниже мой код. Спасибо.
next.js
: страница предметов
<form action = "/api/checkout_sessions/buy" method = "POST">
<button type = "submit">
Pay $50
</button>
</form>
Итак, если пользователь нажмет кнопку «Заплатить 50 долларов», он будет перенаправлен на страницу оформления заказа, размещенную на stript. А ниже pages/api/checkout_sessions/buy.js
.
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
export default async function handler(req, res) {
if (req.method === 'POST') {
try {
// Create Checkout Sessions from body params.
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
line_items: [
{
// Provide the exact Price ID (for example, pr_1234) of the product you want to sell
price: 'price_random',
quantity: 1,
},
],
mode: 'payment',
success_url: `${req.headers.origin}/?success=true`,
cancel_url: `${req.headers.origin}/?canceled=true`,
});
res.redirect(303, session.url);
} catch (err) {
res.status(err.statusCode || 500).json(err.message);
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
До сих пор я просто следую этим инструкциям: https://stripe.com/docs/checkout/quickstart.
После заполнения необходимой информации на странице оформления заказа, размещенной на Stript, чтобы проверить, прошел платеж успешно или нет, я написал веб-хуки в своем бэкэнде и протестировал его с помощью stripe cli
. А это ниже. Опять же, я просто следую этим инструкциям.
https://stripe.com/docs/payments/checkout/fulfill-orders
api.php
Route::post('webhook', function() {
// Set your secret key. Remember to switch to your live secret key in production.
// See your keys here: https://dashboard.stripe.com/apikeys
\Stripe\Stripe::setApiKey('sk_test_');
function print_log($val) {
return file_put_contents('php://stderr', print_r($val, TRUE));
}
// You can find your endpoint's secret in your webhook settings
$endpoint_secret = 'whsec_';
$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;
try {
$event = \Stripe\Webhook::constructEvent($payload, $sig_header, $endpoint_secret);
}
catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}
function fulfill_order($session) {
// TODO: fill me in
print_log("Fulfilling order...");
print_log($session);
}
// Handle the checkout.session.completed event
if ($event->type == 'checkout.session.completed') {
$session = $event->data->object;
Log::info('session----');
Log::info($session);
Log::info('payload----');
Log::info($payload);
Log::info('event----');
Log::info($event);
// Fulfill the purchase...
fulfill_order($session);
}
if ($event->type == 'payment_intent.succeeded') {
Log::info('payment successful');
}
http_response_code(200);
});
Выполняя приведенную ниже команду в Strip cli,
stripe listen --forward-to localhost:3000/api/webhook (which will execute the above function when I clicked pay in stripe-hosted checkout page)
Я получил следующий результат в консоли stript-cli.
payment_intent.created [evt_random]
2022-05-05 21:46:35 <-- [200] POST http://localhost:3000/api/webhook [evt_random]
2022-05-05 21:46:49 --> payment_intent.created [evt_random]
2022-05-05 21:46:49 <-- [200] POST http://localhost:3000/api/webhook [evt_random]
2022-05-05 21:48:50 --> payment_intent.created [evt_random]
2022-05-05 21:48:50 <-- [200] POST http://localhost:3000/api/webhook [evt_random]
2022-05-05 21:50:55 --> payment_intent.created [evt_random]
2022-05-05 21:50:55 <-- [200] POST http://localhost:3000/api/webhook [evt_random]
Я получил следующий результат в консоли laravel.
[2022-05-05 20:38:58] local.INFO: payment successful
[2022-05-05 20:38:59] local.INFO: session----
[2022-05-05 20:38:59] local.INFO: Stripe\Checkout\Session JSON: {
"id": "cs_test_random",
"object": "checkout.session",
"after_expiration": null,
"allow_promotion_codes": null,
"amount_subtotal": 50,
"amount_total": 50,
"automatic_tax": {
"enabled": false,
"status": null
},
"billing_address_collection": null,
"cancel_url": "http://...?canceled=true",
"client_reference_id": null,
"consent": null,
"consent_collection": null,
"currency": "usd",
"customer": "cus_",
"customer_creation": "always",
"customer_details": {
"address": {
"city": null,
"country": "MM",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": "[email protected]",
"name": "er",
"phone": null,
"tax_exempt": "none",
"tax_ids": []
},
"customer_email": null,
"expires_at": 1651836625,
"livemode": false,
"locale": null,
"metadata": [],
"mode": "payment",
"payment_intent": "pi_random",
"payment_link": null,
"payment_method_options": [],
"payment_method_types": [
"card"
],
"payment_status": "paid",
"phone_number_collection": {
"enabled": false
},
"recovered_from": null,
"setup_intent": null,
"shipping": null,
"shipping_address_collection": null,
"shipping_options": [],
"shipping_rate": null,
"status": "complete",
"submit_type": null,
"subscription": null,
"success_url": "http:...?success=true",
"total_details": {
"amount_discount": 0,
"amount_shipping": 0,
"amount_tax": 0
},
"url": null
}
[2022-05-05 20:38:59] local.INFO: payload----
[2022-05-05 20:38:59] local.INFO: {
"id": "evt_random",
"object": "event",
"api_version": "2018-02-06",
"created": 1651754338,
"data": {
"object": {
"id": "cs_test_random",
"object": "checkout.session",
"after_expiration": null,
"allow_promotion_codes": null,
"amount_subtotal": 50,
"amount_total": 50,
"automatic_tax": {
"enabled": false,
"status": null
},
"billing_address_collection": null,
"cancel_url": "http:...?canceled=true",
"client_reference_id": null,
"consent": null,
"consent_collection": null,
"currency": "usd",
"customer": "cus_random",
"customer_creation": "always",
"customer_details": {
"address": {
"city": null,
"country": "US",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": "[email protected]",
"name": "er",
"phone": null,
"tax_exempt": "none",
"tax_ids": [
]
},
"customer_email": null,
"expires_at": 1651836625,
"livemode": false,
"locale": null,
"metadata": {
},
"mode": "payment",
"payment_intent": "pi_random",
"payment_link": null,
"payment_method_options": {
},
"payment_method_types": [
"card"
],
"payment_status": "paid",
"phone_number_collection": {
"enabled": false
},
"recovered_from": null,
"setup_intent": null,
"shipping": null,
"shipping_address_collection": null,
"shipping_options": [
],
"shipping_rate": null,
"status": "complete",
"submit_type": null,
"subscription": null,
"success_url": "http:...?success=true",
"total_details": {
"amount_discount": 0,
"amount_shipping": 0,
"amount_tax": 0
},
"url": null
}
},
"livemode": false,
"pending_webhooks": 2,
"request": {
"id": null,
"idempotency_key": null
},
"type": "checkout.session.completed"
}
[2022-05-05 23:13:09] local.INFO: event----
[2022-05-05 23:13:09] local.INFO: Stripe\Event JSON: {
"id": "evt_random",
"object": "event",
"api_version": "2018-02-06",
"created": 1651763589,
"data": {
"object": {
"id": "cs_test_random",
"object": "checkout.session",
"after_expiration": null,
"allow_promotion_codes": null,
"amount_subtotal": 50,
"amount_total": 50,
"automatic_tax": {
"enabled": false,
"status": null
},
"billing_address_collection": null,
"cancel_url": "http:...?canceled=true",
"client_reference_id": null,
"consent": null,
"consent_collection": null,
"currency": "usd",
"customer": "cus_random",
"customer_creation": "always",
"customer_details": {
"address": {
"city": null,
"country": "NL",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": "[email protected]",
"name": "sample",
"phone": null,
"tax_exempt": "none",
"tax_ids": []
},
"customer_email": null,
"expires_at": 1651849960,
"livemode": false,
"locale": null,
"metadata": [],
"mode": "payment",
"payment_intent": "pi_random",
"payment_link": null,
"payment_method_options": [],
"payment_method_types": [
"card"
],
"payment_status": "paid",
"phone_number_collection": {
"enabled": false
},
"recovered_from": null,
"setup_intent": null,
"shipping": null,
"shipping_address_collection": null,
"shipping_options": [],
"shipping_rate": null,
"status": "complete",
"submit_type": null,
"subscription": null,
"success_url": "http:...?success=true",
"total_details": {
"amount_discount": 0,
"amount_shipping": 0,
"amount_tax": 0
},
"url": null
}
},
"livemode": false,
"pending_webhooks": 2,
"request": {
"id": null,
"idempotency_key": null
},
"type": "checkout.session.completed"
}
Вопрос:
Платеж прошел успешно! Но как я могу сохранить эти keyboard
и 50
в моей базе данных и где написать этот код, чтобы я знал, что пользователь купил этот товар по этой цене.
В коде обработчика события (либо checkout.session.completed, либо payment_intent.succeeded) вы можете получить нужные поля из объекта события и сохранить их в переменных. Затем вы можете использовать свою библиотеку базы данных Laravel и вставить эти данные в свою базу данных в блоке кода обработчика событий.
Till now, I'm just following these instructions: https://stripe.com/docs/checkout/quickstart.
Если да, то в методе stripe.checkout.sessions.create
следует
// Provide the exact Price ID (for example, pr_1234) of the product you want to sell
как предполагает пример для вашей среды (вместе с документом Как использовать продукт и цены при создании сеанса оформления заказа). Это ключ к ответу на ваш вопрос:
how can I get those keyboard and 50
Итак, что вы должны сделать, чтобы получить идентификатор цены? Обычный способ — отправить lookup_key
из вашей формы. На стороне сервера вы можете искать цену, используя этот ключ:
$priceSearchResult = \Stripe\Price::search([
"query" => "lookup_key:'" . $priceLookupKey . "'"
]);
и создайте сеанс оформления заказа с правильным идентификатором цены:
"line_items" => [
[
"price" => $priceSearchResult->data[0]->id,
"quantity" => 1,
]
]
Спасибо. Я последовал вашим инструкциям и создал цену на панели инструментов Stripe, взял идентификатор цены и жестко закодировал его в next.js. Теперь это нормально. Но что такое $priceLookupKey
в вашем первом блоке кода. Кстати, я добавил объект event
из вебхука в вопрос.
Я добавил lookup_key: 'keyboard'
после line_items
(не в line_items), но получил Received unknown parameter: lookup_key
.
Отправьте ключ поиска от клиента вместо жестко заданного идентификатора цены. На стороне сервера присвойте его значение (например, $_POST["key"]
) $priceLookupKey
. Однако нет возможности добавить lookup_key
на панель инструментов Stripe. Используйте Stripe CLI или другой API-способ для обновления ценового объекта.
Я добавил объект
event
из вебхука в вопрос.