Jump to content

This is nuts. I need help with this JSON error for Stripe payment processor.


imgrooot

Recommended Posts

I am using the Stripe API. Been at it for a day and still no luck. 

I keep getting this error.

POST http://localhost/pay 404 (Not Found)
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position // this error is because of this line .then(handleServerResponse);

It has specifically to do with this function.

function handlePaymentMethodResult(result) {
  if (result.error) {
    // An error happened when collecting card details, show it in the payment form
    resultContainer.textContent = result.error.message;
  } else {
    // Otherwise send paymentMethod.id to your server (see Step 3)
    fetch('/pay', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ payment_method_id: result.paymentMethod.id })
    }).then(function(result) {
      return result.json();
    }).then(handleServerResponse);
  }
}

What is "/pay" suppose to be exactly? I assumed it was a page where i run my server process code. But it keeps giving me that error no matter what I try it.

 

Here is my full mode.

INDEX.php

<?php
require_once 'library/stripe/init.php';
?>

<!DOCTYPE HTML>
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="description" content="---">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <link rel="shortcut icon" href="/images/favicon.png" />
  <link href="css/screen.css?v=1.1" media="screen, projection" rel="stylesheet" />
  <script src="javascripts/jquery-3.2.0.min.js"></script>
  <script src="https://js.stripe.com/v3/"></script>
  <script src="javascripts/client.js" defer></script>
</head>
<body>
  <?php
  $total_amount = 20;
  ?>
  <div id="payment-box">
    <div id="p-box-heading">
      Total Amount: <span>$<?php if(empty($total_amount)){echo '0.00';}else{echo $total_amount;} ?> CAD</span>
    </div>
    <div id="p-box-body">

      <form id="payment-form">
        <div id="card-element"><!-- placeholder for Elements --></div>
        <button id="card-button">Submit Payment</button>
        <p id="payment-result"><!-- we'll pass the response from the server here --></p>
      </form>

    </div>
  </div>
</body>

 

CLIENT.js

var stripe = Stripe("pk_test_ROlyXpDaTbqIvSpndWp7IdxW");

var elements = stripe.elements();
var cardElement = elements.create('card');
cardElement.mount('#card-element');

var form = document.getElementById('payment-form');

var resultContainer = document.getElementById('payment-result');
cardElement.on('change', function(event) {
  if (event.error) {
    resultContainer.textContent = event.error.message;
  } else {
    resultContainer.textContent = '';
  }
});

form.addEventListener('submit', function(event) {
  event.preventDefault();
  resultContainer.textContent = "";
  stripe.createPaymentMethod({
    type: 'card',
    card: cardElement,
  }).then(handlePaymentMethodResult);
});

function handlePaymentMethodResult(result) {
  if (result.error) {
    // An error happened when collecting card details, show it in the payment form
    resultContainer.textContent = result.error.message;
  } else {
    // Otherwise send paymentMethod.id to your server (see Step 3)
    fetch('/pay', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ payment_method_id: result.paymentMethod.id })
    }).then(function(result) {
      return result.json();
    }).then(handleServerResponse);
  }
}

function handleServerResponse(responseJson) {
  if (responseJson.error) {
    // An error happened when charging the card, show it in the payment form
    resultContainer.textContent = responseJson.error;
  } else {
    // Show a success message
    resultContainer.textContent = 'Success!';
  }
}

 

SERVER.php

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

  header('Content-Type: application/json');

  # retrieve JSON from POST body
  $json_str = file_get_contents('php://input');
  $json_obj = json_decode($json_str);
  try {
    // Create the PaymentIntent
    $intent = \Stripe\PaymentIntent::create([
      'amount' => 1099,
      'currency' => 'usd',
      'payment_method' => $json_obj->payment_method_id,

      # A PaymentIntent can be confirmed some time after creation,
      # but here we want to confirm (collect payment) immediately.
      'confirm' => true,

      # If the payment requires any follow-up actions from the
      # customer, like two-factor authentication, Stripe will error
      # and you will need to prompt them for a new payment method.
      'error_on_requires_action' => true,
    ]);
    generateResponse($intent);
  } catch (\Stripe\Exception\ApiErrorException $e) {
    // Display error on client
    echo json_encode(['error' => $e->getMessage()]);
  }

  function generateResponse($intent) {
    if ($intent->status == 'succeeded') {
      // Handle post-payment fulfillment
      echo json_encode(['success' => true]);
    } else {
      // Any other status would be unexpected, so error
      echo json_encode(['error' => 'Invalid PaymentIntent status']);
    }
  }

 

Link to comment
Share on other sites

2 hours ago, imgrooot said:

What is "/pay" suppose to be exactly? I assumed it was a page where i run my server process code. But it keeps giving me that error no matter what I try it.

That's right, it's supposed to be the URL to some processing thing on your server.

You're the only one who can know what that URL is supposed to be.

Link to comment
Share on other sites

1 hour ago, requinix said:

That's right, it's supposed to be the URL to some processing thing on your server.

You're the only one who can know what that URL is supposed to be.

So if I do /server.php url in it's place, i still get the same error "Unexpected token < in JSON at position" error. Why would it do that if it's a correct url?

Link to comment
Share on other sites

Yes but I think the reason why is because the url doesn't seem to be correct.

// USING THIS URL
/server.php

// WILL GIVE ME THIS
http://localhost/server.php

//BUT I NEED THE URL TO BE LIKE THIS
http://localhost/site/server.php 

How do do this? I've tried "../server.php" but that's all it shows. It doesn't show the main site directory.

Link to comment
Share on other sites

Alright so I think I may have solved the problem. Stripe's documentation sucks at explaining it properly.

// REPLACE /pay WITH YOUR OWN URL THAT PROCESSES THE SERVER SIDE CODE. THAT CODE FILE HAS TO BE JSON AND NOT HTML.
fetch('/pay',

// THE URL HAS TO BE GLOBAL AND NOT RELATIVE.
// SO FOR MY EXAMPLE, I HAD TO PUT THE FULL URL INSTEAD OF JUST THE PAGE FILE.
fetch('http://localhost/site/server.php',

 

I still have to do additional testing but so far it works. No errors.

Link to comment
Share on other sites

20 minutes ago, requinix said:

/site/server.php would have worked just as well. Of course either way you'll still have to fix it all when it goes live. Would be worth some time seeing if you can't rearrange some stuff to avoid having those sorts of problems.

Actually no "/site/server.php" won't work. I've tried it and for some reason it duplicates the site name like this "http://localhost/site/site/server.php". So it seems like the only way is with absolute urls. And yes I will have to change it when on live server.

Link to comment
Share on other sites

57 minutes ago, imgrooot said:

Actually no "/site/server.php" won't work. I've tried it and for some reason it duplicates the site name like this "http://localhost/site/site/server.php".

Sounds like you forgot the leading / then.  How URL's work is pretty standard.  If you're on the page http://localhost/site/index.php then a relative URL resolves as:

server.php       => http://localhost/site/server.php
site/server.php  => http://localhost/site/site/server.php
/server.php      => http://localhost/server.php
/site/server.php => http://localhost/site/server.php

Using an absolute URL is fine, but generally using a root/domain-relative URL (starts with a /) is best imo.

Link to comment
Share on other sites

3 hours ago, kicken said:

Sounds like you forgot the leading / then.  How URL's work is pretty standard.  If you're on the page http://localhost/site/index.php then a relative URL resolves as:


server.php       => http://localhost/site/server.php
site/server.php  => http://localhost/site/site/server.php
/server.php      => http://localhost/server.php
/site/server.php => http://localhost/site/server.php

Using an absolute URL is fine, but generally using a root/domain-relative URL (starts with a /) is best imo.

Good to know.

Now I have another problem. How do I pass a value of a variable from another page to a json processing page? See the code below. Look at "'amount' => 1099". I would like to replace this number with my own product amount($total_amount = 20) that's listed on the index.php.  If I call it directly on this server.php file, it'll get me that error again "Unexpected token < in JSON at position".

//SERVER.PHP PAGE

require_once '../library/stripe/init.php';

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

  header('Content-Type: application/json');

  # retrieve JSON from POST body
  $json_str = file_get_contents('php://input');
  $json_obj = json_decode($json_str);
  try {
    // Create the PaymentIntent
    $intent = \Stripe\PaymentIntent::create([
      'amount' => 1099,
      'currency' => 'usd',
      'payment_method' => $json_obj->payment_method_id,

      # A PaymentIntent can be confirmed some time after creation,
      # but here we want to confirm (collect payment) immediately.
      'confirm' => true,

      # If the payment requires any follow-up actions from the
      # customer, like two-factor authentication, Stripe will error
      # and you will need to prompt them for a new payment method.
      'error_on_requires_action' => true,
    ]);
    generateResponse($intent);
  } catch (\Stripe\Exception\ApiErrorException $e) {
    // Display error on client
    echo json_encode(['error' => $e->getMessage()]);
  }

  function generateResponse($intent) {
    if ($intent->status == 'succeeded') {
      // Handle post-payment fulfillment
      echo json_encode(['success' => true]);
    } else {
      // Any other status would be unexpected, so error
      echo json_encode(['error' => 'Invalid PaymentIntent status']);
    }
  }

 

Link to comment
Share on other sites

Your value is just hard-coded in your index.php file, so you could just hard-code the same into your server.php file. 

A better approach however would be to create a third file which contains the value and include that into both your index.php and server.php files.  That way there is only one place to alter the value in the future if necessary.

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.