How can I use Stripe Checkout with dynamic prices?

Viewed 4655

I am using Stripe for payment on a page. There are three items on the page and each one has a price that is set dynamically based on inputs on the page. Let's call them plan A, B and C. I have Stripe Checkout working successfully with a hard-coded price but I need to pass the price to Stripe based on which button is clicked and the value of that item.

PHP:

<?php require_once('/stripe/init.php');
\Stripe\Stripe::setApiKey('TEST KEY');

$session = new \Stripe\Checkout\Session::create([
    'payment_method_types' => ['card'],
    'line_items' => [[
      'price_data' => [
        'currency' => 'usd',
        'product_data' => [
          'name' => 'Insurance Plan',
        ],
        'unit_amount' => 4000, //need to set this dynamically
      ],
      'quantity' => 1,
    ]],
    'mode' => 'payment',
    'success_url' => 'https://example.com/success',
    'cancel_url' => 'https://example.com/cancel',
  ]);
?>

JS:

<script>
var stripe = Stripe('PUB KEY');
    jQuery('.checkout-button').on('click', function(e) {
        e.preventDefault();
        var price = jQuery(this).find('.price').val(); //need to do something like this
        stripe.redirectToCheckout({
            sessionId: "<?php echo $session->id; ?>"
        });
    });
</script>

Essentially, I need to create a $post request on button click that hits another file (checkout.php) and in that file, I will create the session after I have set the variable for price using the $post data. Thanks in advance!!!

4 Answers

Eureka! Here is the solution for anyone else who stumbles upon this issue which is not documented at all on Stripe's website.

charge.php file

require_once('./php/init.php');

\Stripe\Stripe::setApiKey('sk_test');

$content = json_decode(file_get_contents('php://input'), true);

$name = $content['name'];
$amount = intval($content['amount']*100);

$session = \Stripe\Checkout\Session::create([
    'payment_method_types' => ['card'],
    'line_items' => [[
      'price_data' => [
        'currency' => 'usd',
        'product_data' => [
          'name' => $name,
        ],
        'unit_amount' => $amount,
      ],
      'quantity' => 1,
    ]],
    'mode' => 'payment',
    'success_url' => 'https://example.com/success',
    'cancel_url' => 'https://example.com/cancel',
  ]);

echo json_encode($session);

Javascript

var stripe = Stripe('pk_test');

    jQuery('.checkout-button').on('click', function() {
        $name = jQuery(this).prev().prev().prev().text();
        $amount = jQuery(this).prev().find('.dollar-amount').text();
      fetch('/charge.php', {
        method: 'POST',
        body: JSON.stringify({
            name: $name,
            amount: $amount
        }),
        headers: {
            'Content-type': 'application/json; charset=UTF-8'
        }
      })
      .then(function(response) {
        return response.json();
      })
      .then(function(session) {
        console.log(session);
        return stripe.redirectToCheckout({ sessionId: session.id });
      })
      .then(function(result) {
        if (result.error) {
          alert(result.error.message);
        }
      })
      .catch(function(error) {
        console.log('Fetch Error :-S', error);
      });
    });

For people using Node.js:

stripe.checkout.sessions.create({
  customer: stripeCustomerId,
  mode: data.mode,
  payment_method_types: [
    'card',
  ],
  success_url: `${MY_DOMAIN}/admin/stripe`,
  cancel_url: `${MY_DOMAIN}/admin/stripe`,
  line_items: [ // all arguments are required
    {
      price_data: {
        unit_amount: 4000,
        currency: 'usd',
        product_data: {
          name: 'Test Product'
        },
      },
      quantity: 1,
    },
  ],
})

You can read more about Ad-hoc prices here. You can also pass price_data into the Checkout, Invoice Items, and Subscription Schedule APIs.

Update: July 2022

The link to Stripe docs was updated.

Instead of creating the Checkout session during the page render, you'll need to defer that until your customer clicks one of your buttons. You'll make a request from your front end to your server to create the session then with the variable amount, return the session to the client and redirect.

Effectively its the same flow, you'll just replace that 4000 value with a value to provide in a request.

You can see an example of this (though using a Python server) in this video, or compare to this PHP example of passing a payment amount (this is not using Checkout, but the server request pattern is analogous). In your case you would pass would like body: JSON.stringify({amount: 1234}) and access it with $body -> amount to the server if the "items" pattern doesn't apply.

Related