I'm trying stripe.redirectToCheckout in Laravel 6. And it's been days now, I can't find anything helpful on internet. I used strip documentation for creating a user session and redirectToCheckout and implemented stripe session in web/routes and redirectToCheckout in JavaScript.
The following is the button for pay with stripe
<button id="checkout-button"
data="{{$id}}" href="https://checkout.stripe.com/checkout.js"
role="link" style="width: 100%"
class="btn btn-dark">Pay with stripe
</button>
The following is the JavaScript function for redirectToCheckout
<script>
(function () {
var stripe = window.Stripe('pk_test_ZuGUA3XxCsWvZVbqnOkFMQnM00PV2c0Acm');
var checkoutButton = document.getElementById('checkout-button');
checkoutButton.addEventListener('click', function () {
// When the customer clicks on the button, redirect
// them to Checkout.
console.log('button clicked');
var product_name = document.getElementById('#p_name');
var product_price = document.getElementById('#p_price');
var name, price;
// var checkout_btn = document.getElementById('#checkout-button-plan_GI1dhi4ljEzk0R');
btn = $(this).attr('data');
console.log(btn);
stripe.redirectToCheckout({
items: [
// Replace with the ID of your SKU
{sku: 'sku****', quantity: 1}
],
successUrl: 'http://4c655de9.ngrok.io/success',
cancelUrl: 'http://4c655de9.ngrok.io/canceled',
clientReferenceId: btn
}).then(function (result) {
console.log('result');
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer
// using `result.error.message`.
console.log(result.error.message);
});
});
})();
</script>
The following is the web/route.php function for \Stripe\Checkout\Session
Route::get('/', function () {
\Stripe\Stripe::setApiKey('sk****');
$session = \Stripe\Checkout\Session::create([
'success_url' => 'http://4c655de9.ngrok.io/success',
'cancel_url' => 'http://4c655de9.ngrok.io/canceled',
'payment_method_types' => ['card'],
'line_items' => [
[
'name' => 'T-shirt',
'description' => 'Comfortable cotton t-shirt',
'amount' => 1500,
'currency' => 'usd',
'quantity' => 2,
],
],
]);
$id = $session->id;
return view('home')->with('id', $id);
Related
I'm trying to implement Stripe on my Symony web app. The checkout page is displayed fine, but I can't make the price and title displayed be those of the product concerned.
Page code above:
booking.html.twig
{% extends "base.html.twig" %}
{% block title %}Réservation
{% endblock %}
{% block body %}
<h1>Bienvenue sur la page de réservation</h1>
<div class="card">
<div class="card-header">
Réserver et payer son activité
</div>
<div class="card-body">
<h5 class="card-title">{{product.title}}</h5>
<p class="card-text">{{product.price}}</p>
<button id="checkout-button">Payer {{product.price / 100}} €</button>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script type="text/javascript">
var stripe = Stripe("pk_test_51LkttkIFe6WM20DzgFS9hQa8fx9jydub6UygVtVg0VBj1xTFt8g04EjfbYjdQkrQOpjiptaesRjTCpxUt0H9W4Qy00vl8ZEgpN");
var checkoutButton = document.getElementById("checkout-button");
checkoutButton.addEventListener('click', function () {
fetch('/create-checkout-session', {
method : 'POST',
})
.then(function(response) {
return response.json()
})
.then(function(session) {
return stripe.redirectToCheckout({ sessionId : session.id});
})
.then(function(result) {
if (result.error) {
alert(result.error.message);
}
})
.catch(function(error) {
console.error('Error', error);
});
});
</script>
{% endblock %}
Here is the controller linked to the reservation page (page where the checkout button is) and to the creation of the checkout session :
BookingController.php :
class BookingController extends AbstractController
{
#[Route('/reservation', name: 'booking')]
public function index(ProductRepository $product)
{
$event = $product->findOneBy(['id' => $_GET['id']]);
dump($event);
// App\Entity\Product {#627 ▼
// -id: 14
// -title: "Cours de cuisine"
// -photo: "30-ecole-de-cuisine-4-scaled-1662990399.jpg"
// -description: "Cours de cuisine"
// -start_date: DateTime #1663056000 {#585 ▶}
// -end_date: DateTime #1663070400 {#632 ▶}
// -place: "Restaurant Place St Jean - 77000 MELUN"
// -duration: DateTime #14400 {#577 ▶}
// -price: "15000.00"
// -creator: App\Entity\User {#830 ▶}
//
}//
return $this->render('booking/booking.html.twig', [
'product' => $event
]);
}
#[Route('/create-checkout-session', name: 'checkout')]
public function checkout()
{
\Stripe\Stripe::setApiKey('*confidential*');
$session = \Stripe\Checkout\Session::create([
"locale" => "fr",
'line_items' => [[
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => '**HERE PUT THE NAME OF THE PRODUCT CONCERNED** ',
],
'unit_amount' => **HERE PUT THE PRICE OF THE PRODUCT CONCERNED**,
],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => $this->generateUrl('success', [], UrlGeneratorInterface::ABSOLUTE_URL),
'cancel_url' => $this->generateUrl('error', [], UrlGeneratorInterface::ABSOLUTE_URL),
]);
return new JsonResponse(['id' => $session->id]);
}
The goal is to put a variable to retrieve the name of the product and its price and integrate it into the checkout session to have a dynamic payment page. I have not found any information that works in this case.
You can try to send the product ID in your FETCH
checkoutButton.addEventListener('click', function () {
fetch('/create-checkout-session?productId=2', {
method : 'POST',
})
Now in your controller
#[Route('/create-checkout-session', name: 'checkout')]
public function checkout(Request $request, ProductRepository $product)
{
\Stripe\Stripe::setApiKey('*confidential*');
$product = $repository->findOneBye(['id' => $request->query->get('productId')]);
//If product not found
if(!$product){
return new JsonResponse(['message' => 'Product not found'], 404);
}
$session = \Stripe\Checkout\Session::create([
"locale" => "fr",
'line_items' => [[
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => $product->getTitle(),
],
'unit_amount' => $product->getPrice(),
],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => $this->generateUrl('success', [], UrlGeneratorInterface::ABSOLUTE_URL),
'cancel_url' => $this->generateUrl('error', [], UrlGeneratorInterface::ABSOLUTE_URL),
]);
return new JsonResponse(['id' => $session->id]);
}
By passing in your controller, for the route ... Inject the Class Request and use this to get the product ID. Your method is not recommended because it is risky
#[Route('/reservation', name: 'booking')]
public function index(ProductRepository $product, Request $request)
{
$event = $product->findOneBy(['id' => $request->query->get('id')]);
This is my server side code
<?php
ini_set('display_errors',1);
error_reporting(E_ALL);
use Slim\Http\Request;
use Slim\Http\Response;
use Stripe\Stripe;
require 'vendor/autoload.php';
$dotenv = Dotenv\Dotenv::create(__DIR__);
$dotenv->load();
require './config.php';
$app = new \Slim\App;
$app->add(function ($request, $response, $next) {
Stripe::setApiKey(getenv('STRIPE_SECRET_KEY'));
return $next($request, $response);
});
$app->get('/', function (Request $request, Response $response, array $args) {
return $response->write(file_get_contents(getenv('STATIC_DIR') . '/index.html'));
});
$app->post('/checkout_sessions', function(Request $request, Response $response) use ($app) {
$params = json_decode($request->getBody());
$payment_method_types = [
'usd' => ['card'],
'eur' => ['card'],
'cad' => ['card']
];
$products = [
'cause-a' => 'prod_KP3YP2a3IGYqsb',
'cause-b' => 'prod_KP3iZRGcEjn5W8',
];
$session = \Stripe\Checkout\Session::create([
'success_url' => 'http://localhost:4242/success.html?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'http://localhost:4242/?cancel=true',
'mode' => 'payment',
'payment_method_types' => $payment_method_types[$params->currency],
'metadata' => [
'cause' => $params->cause,
'currency' => $params->currency,
],
'submit_type' => 'donate',
'line_items' => [[
'price_data' => [
'currency' => $params->currency,
'product' => $products[$params->cause],
'unit_amount' => $params->amount,
],
'quantity' => 1,
]]
]);
return $response->withJson([
'id' => $session->id
]);
});
$app->get('/order', function (Request $request, Response $response) {
$id = $_GET['sessionId'];
$checkout_session = \Stripe\Checkout\Session::retrieve($id);
echo json_encode($checkout_session);
});
$app->run();
this is the success page with javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Order Confirm</title>
</head>
<body>
<div id="main">
<div id="checkout">
<div id="payment-forum">
<h1>Success</h1>
payment status: <span id="payment-status"></span>
<pre>
</pre>
</div>
</div>
</div>
</body>
<script>
var paymentStatus = document.getElementById('payment-status');
var urlParams = new URLSearchParams(window.location.search);
var sessionId = urlParams.get("session_id")
if (sessionId) {
fetch("/order?sessionId=" + sessionId).then(function(result){
return result.json()
}).then(function(session){
var sessionJSON = JSON.stringify(session, null, 2);
document.querySelector("pre").textContent = sessionJSON;
}).catch(function(err){
console.log('Error when fetching Checkout session', err);
});
}
</script>
</html>
i need help with product detail , customer name , amount on success page and if possible payment paid or not paid status on it.... cant find any tutorial on it or any detail step by step guide on it
i am close but cant get it to bullseyes please help me with it
yeah on success page all i get is payment status and blank
Looks like here is what happened:
Your Checkout Session defined success_url to success.html
Your success.html fired another request to "/success?session_id=xxx"
Your backend handled this with $app->get('/success', function...
It could be confusing to name both HTML in step 2 and the handling URL in step 3 as "success". You may want to use a different name such as "success" and "get-checkout-session" like Stripe example on Github. After that, debug your server log on step 3 to see whether you got the session id correctly and have retrieved the Customer Id.
There is more information to extract from a CheckoutSession. See Stripe's API Reference on available properties. You probably want to expand its payment_intent to see the amount and payment status.
how can i send variable amount on my line item as it only accept integers please rest everything works but this varible amount is not working tried $params->amount not working
<?php
require_once('vendor/autoload.php');
\Stripe\Stripe::setApiKey('sk_test_key');
$session = \Stripe\Checkout\Session::create([
'payment_method_types' => ['card'],
'line_items' => [[
'price_data' => [
'currency' => 'usd',
'product_data' => [
'name' => 'T-shirt',
],
'unit_amount' => 2000,
],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => 'https://example.com/success',
'cancel_url' => 'https://example.com/cancel',
]);
?>
<html>
<head>
<title>Buy cool new product</title>
<script src="https://js.stripe.com/v3/"></script>
</head>
<body>
<div class="field">
<label for="amount">Amount to pay</label>
<input type="number" id="amount" step="0.01" value="5.00">
</div>
<button id="checkout-button">Checkout</button>
<script>
var stripe = Stripe('pk_test_51JWkHLK7X12cK8Ptf5y5DQn6Ugf6miu3AqSuhH9wdLsyTB9ouf0TY31vDQxq19xIt6YH76uMTEX1kU9HMyrcEb6w00MTxHnGxc');
var amount = document.getElementById('amount');
const btn = document.getElementById("checkout-button")
btn.addEventListener('click', function(e) {
e.preventDefault();
stripe.redirectToCheckout({
sessionId: "<?php echo $session->id; ?>"
});
})
</script>
</body>
</html>
how can i send variable amount on my line item as it only accept integers please rest everything works but this varible amount is not working tried $params->amount not working
The code to create the payment intent with your secret key needs to be run server-side - you must not use your secret key in client-side code.
You should follow the guide here to see how you can generate a payment intent and provide the secret key in a server rendered template, or you can make an async request to your server from an SPA to get a payment intent client secret. The guide goes through both options.
I'm new in yii2.
When use the url to call an action, it redirects to login page correctly.
Example on nav-bar
['label' => Yii::t('app', 'Đat san'), 'url' => ['/datsan/create']],
But, when use Javascript to get data from server, it does not auto redirect to login page. How do I fix it?
var vUrl = $("#datsan-url-create").data('url');
$.get(vUrl, function(data){
$('#modal-datsan').modal('show').find('.modalContent').html(data); // update data for modal
}
with
<input type="hidden" id="datsan-url-create" data-url='<?= Url::to(['/datsan/create']) ?>'>
I checked Console, it shows below error
Forbidden (#403): Login Required
/.DatsanController.php
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['create', 'update', 'delete'],
'rules' => [
[
'actions' => ['create'],
'allow' => true,
'roles' => ['#'],
],
[
'actions' => ['update', 'delete'],
'allow' => true,
'roles' => ['#'],
'matchCallback' => function ($rule, $action) {
if (Yii::$app->user->identity->isAdmin || $this->isUserAuthor()) {
return true;
}
return false;
}
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
Well You are doing AJAX request it won't redirect if You don't say so. I believe You want something like:
$.get(vUrl, function(data, textStatus, jqXHR){
if (jqXHR.status == 403) {
window.location = vUrl; // or whatever login url is
} else {
$('#modal-datsan').modal('show')
.find('.modalContent').html(data); // update data for modal
}
}
I keep receiving error code 400 on my stripe dashboard. It seems like im using the same stripe token more than once and this produces an error. Below is my code.
Js:
<script src="https://checkout.stripe.com/checkout.js"></script>
<script>
var handler = StripeCheckout.configure({
key: 'pk_test_******************',
image: '/img/documentation/checkout/marketplace.png',
token: function(token) {
/*$.post("php/charge.php",{stripeToken:token.id},function(data,status){
console.log("Data: "+ data+"\nStatus: "+status);
});*/
alert(token.used);//alerts false
$.post("php/charge.php",{stripeToken:token.id});
alert(token.used);// still alerts false
}
});
$('#myButton').on('click', function(e) {
// Open Checkout with further options
handler.open({
name: 'Demo Site',
description: '2 widgets',
currency: "cad",
amount: 2000
});
e.preventDefault();
});
// Close Checkout on page navigation
$(window).on('popstate', function() {
handler.close();
});
</script>
Php:
<?php
require_once('config.php');
$token = $_POST['stripeToken'];
$customer = \Stripe\Customer::create(array(
'email' => 'test#test.com',
'card' => $token
));
//try {
$charge = \Stripe\Charge::create(array(
"amount" => 1000, // amount in cents, again
"currency" => "cad",
"source" => $token,
"description" => "Example charge")
);
//}catch(\Stripe\Error\Card $e) {
// The card has been declined
//}
?>
Can anyone tell my why I cant charge a customer? How am I using a key multiple times?
You do use the token twice.
First, when creating the customer.
Second, when trying to charge the card.
Instead, you can create a customer and and then pass $customer->id to Stripe when you create the charge:
$charge = \Stripe\Charge::create(array(
"amount" => 1000, // amount in cents, again
"currency" => "cad",
"customer" => $customer->id,
"description" => "Example charge")
);
You have to create the customer to charge him multiple times.
1) Add the Credit card token to customer and create customer
2) Use the customer Id to charge users
if (isset($_POST['stripeToken'])){
$token = $_POST['stripeToken'];
// Create a Customer
$customer = \Stripe\Customer::create(array(
"source" => $token,
"description" => "Example customer")
);
// Charge the Customer instead of the card
\Stripe\Charge::create(array(
"amount" => 1000, # amount in cents, again
"currency" => "usd",
"customer" => $customer->id)
);
}
for more help visit: https://stripe.com/docs/tutorials/charges