4

I am trying to make a custom payment form for Stripe, and I want to make the AJAX call to Stripe manually. (instead of a submit event)

However, first off I am pretty sure I am posting it to the wrong place. But I can't figure out what URL I'm supposed to make this post request to.

If I am using the right url. I am getting a 405 not allowed response. With no information on what is wrong with my request.

Here's what I got:

Stripe.setPublishableKey('pk_test_12345');
    Stripe.card.createToken({
      number: ccNum,
      cvc: ccCVC,
      exp_month: ccMonth,
      exp_year: ccYear
    }, stripeResponseHandler);

This part works fine, gives me a 200 OK status and I got a token back from the server.

function stripeResponseHandler(status, response) {
      console.log('card status: ', status);
      console.log('token: ', response.id);
      $.ajax({
        type: 'POST',
        url: 'https://checkout.stripe.com/checkout.js',
        headers: {
          stripeToken: response.id
        },
        data: {
          number: ccNum,
          cvc: ccCVC,
          exp_month: ccMonth,
          exp_year: ccYear
        },
        success: (response) => {
          console.log('successful payment: ', response);
        },
        error: (response) => {
          console.log('error payment: ', response);
        }
      })
    }

This however, gives me the 405 Not Allowed. It seems a bit weird to me that the endpoint would be a .js file. Which is why I am assuming I got the wrong URL.

Can anyone help me figure out how to make a manual post request for a Stripe payment?

MLyck
  • 4,959
  • 13
  • 43
  • 74
  • Hi, please check stripe docs. https://stripe.com/docs/checkout#integration-custom and https://checkout.stripe.com/checkout.js is a javascript file supposed to be loaded on your page via HTML script tags. – user2267175 Aug 07 '16 at 23:39

2 Answers2

3

EDIT: This is insecure (and outdated)! You shouldn't send your user's card information directly to your own server. Instead, you should directly send it to Stripe. There's an up-to-date (using intents, etc) example here


You need to POST to a PHP file in your $.ajax() function:

  $.ajax({
    type: 'POST',
    url: './stripe-payment.php',
    headers: {
      stripeToken: response.id
    },
    data: {
      number: ccNum,
      cvc: ccCVC,
      exp_month: ccMonth,
      exp_year: ccYear
    },
    success: (response) => {
      console.log('successful payment: ', response);
    },
    error: (response) => {
      console.log('error payment: ', response);
    }
  })

Your PHP should have something like the Stripe PHP bindings require()d to use the Stripe payment API, and that PHP file should look something like this, from this SO question:

<?php

require_once('Stripe.php');

// Set your secret key: remember to change this to your live secret key in production
// See your keys here https://manage.stripe.com/account
Stripe::setApiKey("sk_test_APIKEYREDACTED");

// Get the credit card details submitted by the form
$token = json_decode($_POST['chargeData']);
$tokenid = $token['id'];

// Create the charge on Stripe's servers - this will charge the user's card
try {
$charge = Stripe_Charge::create(array(
  "amount" => 2000, // amount in cents, again
  "currency" => "usd",
  "card" => $tokenid,
  "description" => "payinguser@example.com")
);
echo 'success';
} catch(Stripe_CardError $e) {
  // The card has been declined
    echo $tokenid;
}

?>

Refer to that Github's README for more, as well as the Stripe documentation.

Nick Bull
  • 9,518
  • 6
  • 36
  • 58
  • @TemporaryName: This isn't overkill -- it's the right way to do it. The token must be sent to the merchant's backend server, where it will be used in a charge creation request. If you send the token to the API directly from the frontend request, you reveal the secret API key. – Ywain Aug 08 '16 at 08:48
  • @TemporaryName Yup, actually looking at this again, this is exactly what the API you've linked to says to do... – Nick Bull Aug 08 '16 at 08:51
  • @Ywain, you're both right I'm an idiot. I didn't realize the token was a secret key. – TemporaryName Aug 08 '16 at 15:34
  • 1
    It works but its not the appropriate way its against the PCI rules to send card info to your server. What stripe suggests is to generate a source by sending card info to stripe and then send that source to backend and handle payments accordingly. It's very clear in their documentation. – Yousaf Hassan Jul 15 '20 at 17:50
  • @YousafHassan You know what they say about re-reading code you wrote in the past. You're right! – Nick Bull Jul 16 '20 at 13:10
3

Disclaimer: This works, but it is TERRIBLE practice. Don't use this for a real project. I needed it for a front-end only testing environment. As other users on this page has pointed out, you should be doing this on the backend!

I finally found some useful documentation at: https://stripe.com/docs/api#create_charge

As I suspected the URL I was using was wrong.

after getting the right URL, the following ajax call works:

Hope That helps someone else as well! As most answers, are PHP or other backend languages.

$.ajax({
        type: 'POST',
        url: 'https://api.stripe.com/v1/charges',
        headers: {
          Authorization: 'Bearer sk_test_YourSecretKeyHere'
        },
        data: {
          amount: 3000,
          currency: 'usd',
          source: response.id,
          description: "Charge for madison.garcia@example.com"
        },
        success: (response) => {
          console.log('successful payment: ', response);
        },
        error: (response) => {
          console.log('error payment: ', response);
        }
      })
MLyck
  • 4,959
  • 13
  • 43
  • 74
  • 2
    @MLyck: if you post to the API directly from your frontend code, you're revealing your secret key for anyone to see. You need to send the token to your backend, and send the charge creation request from the backend code, as the other answer suggests. – Ywain Aug 08 '16 at 08:47
  • 1
    @Ywain is very correct - my first comment that it might be a better way is not true. Requests **have** to be made at the backend – Nick Bull Aug 08 '16 at 08:52
  • @Ywain I am a frontend student, My project doesn't have a backend, hence the request for a Javascript only version. But thanks for clarifying the reason it was SOO hard to find a Javascript version of this. – MLyck Aug 08 '16 at 14:25
  • Front end and back end are concepts. The folder your code resides in is the backend, alongside whatever infrastructure, environment and applications that serve your code. You may not have the latter, but the former is part of the backend; you could very easily use Apache Server on your computer to run PHP with that. It's not complicated *at all*. Install XAMPP, start it by clicking buttons, paste your index.html and other files into the htdocs folder, then change index.html to index.php. You can now use PHP - super easy! See here: http://www.phpknowhow.com/basics/working-with-xampp/ – Nick Bull Aug 08 '16 at 15:51
  • @MLyck There are third-party integrations that (at additional cost) let you accept payments with just frontend code, such as https://www.commencepayments.com/. But if you have any interest in it, as Nick said backend development is not that difficult. Since you seem already familiar with JavaScript, you can check out Node.js to use JavaScript server-side. Stripe has an official library for it. – Ywain Aug 08 '16 at 16:17
  • I am aware. But my project requirements was to use Stripe, and we don't have any environments or chance to do a backend server at this time. I did however edit my answer, to clarify that this is Indeed TERRIBLE practice. And should not be used for a real life application. Non the less, it's the answer I was looking for. – MLyck Aug 08 '16 at 23:57