4

I keep getting this error even after hours of trial and error changes to the code:

The Token field is required.

Perhaps my mistake will be immediately obvious to someone who knows javascript. I did see the other question with this problem and made sure this line was included, at least in the HTML version paired with the Store javascript example. It looks like the Stripe javascript ads this line:

<input type="hidden" id="payment_token" name="payment[token]" value="" />

Hopefully all this code isn't overkill, but I could really use some help and didn't want to leave anything out. The Paypal Express option is working, by the way, and here is the development store index page.

Here are two versions of Javascript in the head I have tried. First, the version from the Store documentation:

<script type="text/javascript">

$(document).ready(function() {
  $.getScript('https://js.stripe.com/v1/', function() {
    Stripe.setPublishableKey('pk_test_QcxvwbfdYTdR3z5vUD1Tq27k');
  });

  /* Ensure your checkout submit button has id="checkout_submit" */
  $("#checkout_submit").click(function() {

    /* Only handle requests for Stripe gateway */
    if (this.form.elements["payment_method"].value == "stripe") {

      /* Temporarily disable the checkout submit button */
      $("#checkout_submit").attr('disabled', true);

      /* Create a Stripe card token */
      Stripe.createToken({
        name: $("#payment_name").val(),
        number: $("#payment_card_no").val(),
        cvc: $("#payment_card_csc").val(),
        exp_month: $("#payment_exp_month").val(),
        exp_year: $("#payment_exp_year").val()
      }, stripeResponseHandler);

      /* We don't want to submit the form yet */
      return false;
    }
  });

  /* This function is triggered once Stripe has generated the token */
  function stripeResponseHandler(status, response) {
    /* Re-enable the checkout submit button */
    $("#checkout_submit").attr('disabled', false);

    /* Check whether we have a valid credit card */
    if (response.error) {
      alert(response.error.message);
    } else {
      /* Set the card token and submit the checkout form */
      $("#payment_token").val(response['id']);
      $("#checkout_submit").unbind("click").click();
    }
  }
});

</script>

This version is from the Stripe documentation. It's notably different, but doesn't work either.

 <!-- The required Stripe lib -->
  <script type="text/javascript" src="https://js.stripe.com/v2/"></script>

  <!-- jQuery is used only for this example; it isn't required to use Stripe -->
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

  <script type="text/javascript">
    // This identifies your website in the createToken call below
    Stripe.setPublishableKey('pk_test_QcxvwbfdYTdR3z5vUD1Tq27k');

    var stripeResponseHandler = function(status, response) {
      var $form = $('#checkout_submit');

      if (response.error) {
        // Show the errors on the form
        $form.find('.payment-errors').text(response.error.message);
        $form.find('button').prop('disabled', false);
      } else {
        // token contains id, last4, and card type
        var token = response.id;
        // Insert the token into the form so it gets submitted to the server
        $form.append($('<input type="hidden" name="stripeToken" />').val(token));
        // and re-submit
        $form.get(0).submit();
      }
    };

    jQuery(function($) {
      $('#checkout_submit').submit(function(e) {
        var $form = $(this);

        // Disable the submit button to prevent repeated clicks
        $form.find('button').prop('disabled', true);

        Stripe.createToken($form, stripeResponseHandler);

        // Prevent the form from submitting with the default action
        return false;
      });
    });
  </script>

This is the Checkout tag and all of its contents:

{exp:store:checkout
    form_class="form-horizontal"
    return="store/order/ORDER_HASH"
    error_delimiters='<span class="help-inline">|</span>'}

    {if no_items}
        {redirect="store_example/checkout"}
    {/if}

<div class="row">
    <div class="large-10 large-centered columns">
        <div class="row">
            <div class="large-4 columns">
                    <dl>
                        <dt>Billing Details</dt>
                            <dd>{billing_name}</dd>
                            <dd>{billing_address1}</dd>
                            <dd>{billing_address2}</dd>
                            <dd>{billing_address3} {billing_postcode}</dd>
                            <dd>{billing_region_name}</dd>
                            <dd>{billing_country_name}</dd>
                            <dd>{billing_phone}</dd>
                            <dd>{order_email}</dd>
                    </dl>
                </div>

            <div class="large-4 columns">
                    <dl>
                        <dt>Shipping Details</dt>
                            {if shipping_same_as_billing}
                                Same as Billing Details
                            {if:else}
                                <dd><b>{shipping_name}</b></dd>
                                <dd>{shipping_address1}</dd>
                                <dd>{shipping_address2}</dd>
                                <dd>{shipping_address3} {shipping_postcode}</dd>
                                <dd>{shipping_region_name}</dd>
                                <dd>{shipping_country_name}</dd>
                                <dd>{shipping_phone}</dd>
                            {/if}
                    </dl>
                </div>

            <div class="large-4 columns">
                <fieldset>
                    <legend>Order Summary</legend>

                    <table>
                        <thead>
                            <tr>
                                <th width="800" style="text-align:left">Product</th>
                                <th width="200" style="text-align:right">Total</th>
                            </tr>
                        </thead>
                        <tbody>
                            {items}
                                <tr>
                                    <td style="text-align:left">{item_qty} &times; {title}</td>
                                    <td style="text-align:right">{item_subtotal}</td>
                                </tr>
                            {/items}
                            <tr>
                                <th style="text-align:left">Subtotal</th>
                                <th style="text-align:right">{order_subtotal}</th>
                            </tr>
                            {if shipping_method_id}
                                <tr>
                                    <td style="text-align:left">Shipping ({shipping_method})</td>
                                    <td style="text-align:right">{order_shipping}</td>
                                </tr>
                            {/if}
                            {if order_tax_val}
                                <tr>
                                    <td style="text-align:left">{tax_name} ({tax_percent}%)</td>
                                    <td style="text-align:right">{order_tax}</td>
                                </tr>
                            {/if}
                            <tr>
                                <th style="text-align:left">Total</th>
                                <th style="text-align:right">{order_total}</th>
                            </tr>
                        </tbody>
                    </table>
                </fieldset>
        </div>
        </div>

        <div class="row">
            <div class="small-12 columns"
            <fieldset>
                <legend>Payment</legend>

                {if error:payment_method}
                    <div>
                        <div class="alert alert-error">{error:payment_method}</div>
                    </div>
                {/if}       

                <label for="payment_method"><input type="radio"  checked = "checked" name="payment_method" id="stripe" value="stripe"> Checkout with our secure form.</label>

                <div>
                    <label class="control-label" for="payment_card_no">Card No</label>
                    <div class="controls">
                        <input type="text" id="payment_card_no" value="" />
                    </div>
                </div>

                <div>
                    <label class="control-label" for="payment_name">Name</label>
                    <div class="controls">
                        <input type="text" id="payment_name" value="" />
                    </div>
                </div>

                <div>
                    <label class="control-label" for="payment_exp_month">Expiry</label>
                    <div class="controls">
                        <select id="payment_exp_month" style="width:auto">
                            <option value=""></option>
                            {exp_month_options}
                        </select>
                        <select id="payment_exp_year" style="width:auto">
                            <option value=""></option>
                            {exp_year_options}
                        </select>
                    </div>
                </div>

                <div>
                    <label class="control-label" for="payment_csc">CSC</label>
                    <div class="controls">
                        <input type="text" id="payment_card_csc" value="" class="input-mini" />
                    </div>
                </div>

                <label for="payment_method"><input type="radio" id="paypal" name="payment_method" value="paypal_express"> or Pay with Paypal</label>

            </fieldset>
        </div>
        <div class="form-actions">
            <a href="{path='store/shipping'}" class="store-button back">Back</a>
            <input type="hidden" id="payment_token" name="payment[token]" value="" />
            <input type="submit" id="checkout_submit" name="submit" value="Place Order" class="store-button order" />
        </div>

    </div>
</div>
{/exp:store:checkout}
  • Hi Sean, which version of the API are you using? The big difference between the two examples above is that the Store docs refer to API v1 whereas the Stripe docs are using API v2. If you log into your Stripe account and go to Your Account > Settings > API Keys. What version is mentioned? – Ian Jun 20 '13 at 17:03
  • Also for troubleshooting can you make the token field a regular text field instead of a hidden field then also check the console to see if you are getting any JS errors preventing the Token field from getting filled in. – Justin Long Jun 20 '13 at 17:47
  • Can you take a copy of the store_example templates and add the necessary Stripe JS from the exp-resso docs and change the name to ID attributes and sees if Stripe checkout works. When I look at your checkout pages I am seeing over 2k errors for JS looking for certain elements. Stripe passes all this information via JS so the errors might be preventing the token field from being populated properly. (cb_core.js specifically) – Justin Long Jun 20 '13 at 20:23
  • @Ian, I'm using "API version 2013-02-13 (latest)". Stripe documentation contains examples using both V1 and V2 and the Exp-resso docs show V1. – Sean O'Brien Jun 21 '13 at 2:19
  • @JustinLong I have changed the store_example templates as you suggested. Earlier today I had "Require SSL connection for checkout and order tags" set to "no". That option is now "yes" but I still get the same error. Not knowing Javascript, I'm not sure what I can do with error notifications aside from hiring someone knowledgable in the language. I do have to put a product in my cart in my custom template and then switch over to the store example templates or I get this error: "The URI you submitted has disallowed characters." Thanks for taking a look at this issue. What else can I do to help? – Sean O'Brien Jun 21 '13 at 2:49
1

This issue resulted from the use of radio buttons in the submit form. One radio button selected Paypal and the other selected Stripe as the payment method. There was a bug in the Store code didn't work with this setup.

The guys at Expresso took care of it quickly and included the fix in the next build of Store (before the release of Store 2). If you run into a similar problem, make sure you're running the latest Store build.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.