Ajax passing JS variable to PHP Stripe SCK to set amount dynamically

Hello everybody

I am trying to set the amount in Stripe checkout (I am using Stripe SCK plugin for Kirby) dynamically, but I am struggling to pass the js variable to php (ajax). This is what I have so far:

1. Snippet “sck-qty” with integrated stripe script

var quantity = document.getElementById("qty").value;
var subtotal = document.getElementById('total').innerHTML = 'Total ' + quantity * 298 + ".-";
let counter = document.getElementById("qty").value;

function subt(){
var quantity = document.getElementById("qty").value = --counter;
document.getElementById('total').innerHTML = 'Total ' + quantity * 298 + ".-";
ajax();
}

function incr(){
var quantity = document.getElementById("qty").value = ++counter;
document.getElementById('total').innerHTML = 'Total ' + quantity * 298 + ".-";
ajax();
}
// AJAX REQUEST
function ajax() {
**var current** = document.getElementById('total').innerHTML;
  $.ajax({
      type: 'POST',
      url: 'ajax.php',
      data: {current:current},
   success: function(data) {
    alert("Success!");
       }
  })
}

The checkout has increment and subtract buttons to set the amount of products. I want to update the amount at every click via ajax in order to pass the amount to a php variable on the same site.

…Snippet “sck-qty” with integrated stripe script

...
// Get amount from form script

require('ajax.php');

//STRIPE SCRIPT 
<form action="#" method="POST">
  <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
  data-key="<?= $pk; ?>"
  data-amount= "<?= $currentamount; ?>"  // amount I want to set dynamically
  data-name="<?= $page->formtitle() ?>"
  data-label="<?= $page->label() ?>"
  data-description="<?= $page->formdescription() ?>"
  data-image="<?= $logo; ?>"
  data-locale="auto"
  data-billing-address="false"
  data-shipping-address="true"
  data-allow-remember-me="<?= $rememberMe; ?>"
  data-currency="<?= $currency; ?>">
  </script>
</form>

2. Snippet ajax.php

$currentamount = $_POST['current'];

So basically what I try to achieve:

1.) Get the article amount from user
2.) Send the amount via AJAX to a php variable on the same page
3.) Include the amount as a php variable into the generic Stripe script
The three steps happens in the same file (“sck-qty.php”) but I use “ajax.php” for the ajax call and include the ajax snippet in the same file before the Stripe script.

Now with the current setting this doesn’t seem to work. When loading the site, I get an undefined index error for:
$currentamount = $_POST['current'];
in the ajax.php.

This is the first time I use ajax, so I’m not sure, if I understand the concept completely. Does my setup makes sense at all?

First of all, to get rid of the undefined. index error, you have to check if you have a post request at all and if the index exists

if(r::is('post') and get('current')) {
  // do something
}

And also where you print variable.

Secondly, where are the subs() and incr() functions called?

Thanks @texnixe, this brought me a step further, the undefined index error is gone, but now I have an undefined variable ($currentamount) in the main snippet. It seems it can’t get the variable from ajax.php?

ajax.php looks like that now:

if(r::is('post') and get('current')) {
$currentamount = $_POST['current'];
}

Well, as I said above, you have to check if the variable is set in the main snippet as well

<?= isset($currentamount)):$currentamount:null ?>

But if the page is not reloaded, the variable will never be updated. Why do you need to store it in a PHP variable?

Sorry, I’m not sure how to deal with that line. Should it replace my PHP variable in the Stripe script, like so (Line 4)?

<form action="#" method="POST">
  <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
  data-key="<?= $pk; ?>"
  data-amount= "<?php isset($currentamount)):$currentamount:null ?>"
  data-name="<?= $page->formtitle() ?>"
  data-label="<?= $page->label() ?>"
  data-description="<?= $page->formdescription() ?>"
  data-image="<?= $logo; ?>"
  data-locale="auto"
  data-billing-address="false"
  data-shipping-address="true"
  data-allow-remember-me="<?= $rememberMe; ?>"
  data-currency="<?= $currency; ?>">
  </script>
</form>

PHP variables seem to be the only one working in this generic Stripe script. I think I can’t use the JS variables because the data-attribute “data-amount” (which I want to update) only takes strings. Or is there an other way to get the amount into it?

Page reload: I have an add and a subtract button, which each triggers the subt() and the incr() function with the ajax included. My idea was to call the ajax() function at every click and therefore to make an ajax call at every click in order to update the amount. Isn’t the point of ajax, that I don’t have to reload the page?

Sorry if I’m a bit complicated…

YEs, but that only makes sense if you get some data from the server to inject it into the page without reloading.

Of course, you can also send data to the server, but in this case, it doesn’t seem to make sense because you are not doing anything with that data on the server, like storing it somewhere. So I don’t see a point in doing that and would just inject the new value with JS

I have an error in the above, should be

data-amount= "<?php isset($currentamount)?$currentamount:null ?>"

So I don’t see a point in doing that and would just inject the new value with JS

Sure, I would like to keep it that simple but it doesn’t work with JS variables. Is there maybe a way to set the data-amount value with JS from outside the Stripe script?

You could try Stripe Elements. This has more flexibility and you’ll be able to set variables in JS. You’ll have to combine it with the Stripe-PHP wrapper. The SCK plugin could give some guidance.

@sun Thanks for the hint, I’ll give it a try.

You can create a route which when hit through ajax and a form will send the variable through the JS . Something like:

c::set('routes', array(
    array(
        'pattern' => 'products/(:any)/charge',
        'method' => 'POST',
        'action'  => function() {
            stripeCheckout();
        },
    ),
));