I'm integrating Stripe for my platform which uses Next.js and Laravel.
I can't figure out how can I get the data and store it in MY Platform database.
For example, a user buys a 50$ keyboard. How can I get that item_name
and price
information in Laravel.
Below is my code. Thank you.
next.js
: items page
<form action="/api/checkout_sessions/buy" method="POST">
<button type="submit">
Pay $50
</button>
</form>
So, if the user clicks Pay $50 button, he will be redirected to stript-hosted checkout page. And below is 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: [
{
price_data: {
currency: 'usd',
product_data: {
name: "Keyboard", // here is the item name. (Q1: How can I get item name dynamically from previous page?)
},
unit_amount: 50
},
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');
}
}
Till now, I'm just following these instructions: https://stripe.com/docs/checkout/quickstart.
After filling necessary info in the stript-hosted checkout page, to test the payment is successful or not, I wrote web hooks in my backend and test it with stripe cli
. And it is below. Again, I'm just follwing these instructions.
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);
});
While running the below command in 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)
I got following result in the stript-cli console.
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]
I got following result in the laravel console.
[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"
}
Question:
The payment is successful! But, how can I get those keyboard
and 50
to save into my database and where to write those code so that I know that user have purchased that item with that price.
CodePudding user response:
Within the event's handler code (either checkout.session.completed or payment_intent.succeeded), you can grab the fields you need from the event object and store them to variables. Then, you can use your Laravel database library and insert that data into your database within the event handler code block.
CodePudding user response:
Till now, I'm just following these instructions: https://stripe.com/docs/checkout/quickstart.
If so, in the method stripe.checkout.sessions.create
you should
// Provide the exact Price ID (for example, pr_1234) of the product you want to sell
as the example for your environment suggests (along with the doc How to use product and prices when creating Checkout Session). This is the key for the answer to your question:
how can I get those keyboard and 50
So, what should you do to get price id? The common way is to submit a lookup_key
from your form. At the server side you can search for price using this key:
$priceSearchResult = \Stripe\Price::search([
"query" => "lookup_key:'" . $priceLookupKey . "'"
]);
and create the checkout session with the proper price id:
"line_items" => [
[
"price" => $priceSearchResult->data[0]->id,
"quantity" => 1,
]
]