1

Ajax Code:

<script>
jQuery(function($) {
  $('#payment-form').submit(function(event) {
    var $form = $(this);

    // Disable the submit button to prevent repeated clicks
    $form.find('input[type=submit]').attr('disabled', true);

        $.ajax({
            type: "POST",
            url: "https://example.com/ipn.php",
            data: { "tid": "123456", "amount": "9.99" },
            success: function() { document.location = "https://example.com/success.php" },
        });

    return false;
  });
});
</script>

Script working OK, show my logs:

[Mon May 29 14:47:57 2023][13694] POST data: 
          'tid' => '123456',
          'amount' => '9.99'

But for the script to work properly, I need a JSON version with which the server will call the address itself.

Here is my JSON code

$id = '123456';
$a = '9.99';

$url = 'https://example.com/ipn.php';

$ch = curl_init( $url );
# Setup request to send json via POST.
$payload = json_encode( array( "tid"=> $id, "amount"=> $a ) );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
# Return response instead of printing.
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
# Send request.
$result = curl_exec($ch);
curl_close($ch);
# Print response.
echo "<pre>$result</pre>";

Unfortunately, but in the logs it crashes something that is wrong and shows an error

[Mon May 29 16:17:30 2023][24645] POST data: 
          'POSTDATA' => '{&#x22;tid&#x22;:&#x22;2447655759&#x22;,&#x22;amount&#x22;:&#x22;9.99&#x22;}'

I would like the server to send a response using JSON. Please help!

I want the script to run in json

r4nt
  • 11
  • 1
  • The code to recieve JSON would be different from that to receive POST form data. Please also provide the source code of ipn.php so we can suggest how to modify it. – Koala Yeung May 29 '23 at 14:46
  • 2
    Please overthink your question title. JSON is sent via AJAX. – Markus Zeller May 29 '23 at 15:07
  • Good morning. In the log that you posted, the `POSTDATA` appears to be html encoded. A couple things you could look into that might help you: 1. See if you are HTML encoding the JSON before sending it. If you find you are accidentally encoding it, remove the encoding. 2. Look into decoding the HTML encoded JSON before processing it, https://www.php.net/manual/en/function.html-entity-decode.php – jeremysawesome May 29 '23 at 15:11
  • Hi r4nt, I reread your question and believe this will answer your question: https://stackoverflow.com/a/6587249/296889 Your Problem, as I now understand it: your jQuery post is not sending JSON the way you want it to. You'll need to use `JSON.stringify` and `contentType: 'application/json; charset=utf-8'` as mentioned in that answer to convert your payload to JSON. – jeremysawesome May 29 '23 at 15:18
  • 2
    I suppose you mean send via cURL vs. AJAX. Both can be used for sending JSON and any number of other formats. What does your endpoint expect to receive? Adjust to that, whether AJAX or cURL. – Markus AO May 29 '23 at 19:35

1 Answers1

0

Your Javascript does not send data in JSON format. Your PHP does. The response of your endpoint (https://example.com/ipn.php) shows that it only accepts application/x-www-form-urlencoded with POST request.

So you should either modify your PHP code to do application/x-www-form-urlencoded request, or modify your https://example.com/ipn.php to accept JSON.

How to Correctly Receive JSON in POST request body

If you want to receive both application/x-www-form-urlencoded and application/json request, you should modify ipn.php. Because you haven't shared any code there, I can only write a code snippet as an example,

$method = $_SERVER['REQUEST_METHOD'] ?? null;
if ($method === 'POST') {
        $content_type = strtolower($_SERVER['HTTP_CONTENT_TYPE'] ?? null);
        $input = file_get_contents('php://input');

        $data = match ($content_type) {
                'application/json' => json_decode(file_get_contents('php://input')),
                default => $_POST,
        };

        // Example response only
        echo json_encode([
                'method' => $method,
                'content_type' => $content_type,
                'data' => $data,
        ]);
}

How to Send POST form data in PHP

If you are unable to modify ipn.php, then you can only modify your PHP to do POST form data request:

$id = '123456';
$a = '9.99';

$url = 'https://example.com/ipn.php';

$ch = curl_init( $url );
# Setup request to send json via POST.
$payload = http_build_query( array( "tid"=> $id, "amount"=> $a ) );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded; charset=utf-8'));
# Return response instead of printing.
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
# Send request.
$result = curl_exec($ch);
curl_close($ch);
# Print response.
echo "<pre>$result</pre>";

Modifications:

  1. Using http_build_query() instead of json_encode() to encode form data.
  2. Use Content-Type: application/x-www-form-urlencoded; charset=utf-8 in header.

Side note: How to Correctly do JSON API call in Javascript with jQuery.ajax()?

You're using an object as data in your jQuery.ajax() call. By default, jQuery.ajax() encodes object and array in data to application/x-www-form-urlencoded format.

For example, { a: "bc", d: "e,f" } is converted to the string "a=bc&d=e%2Cf". Details are in their documentation:

Document of jQuery.ajax, the "data" section

So the AJAX call done by your function was actually a simple POST form data request. Much like a simple form submission with POST method.

If you really want to do a JSON API call with jQuery.ajax(),

jQuery(function($) {
  $('#payment-form').submit(function(event) {
    var $form = $(this);

    // Disable the submit button to prevent repeated clicks
    $form.find('input[type=submit]').attr('disabled', true);

        $.ajax({
            type: "POST",
            contentType: "application/json",
            url: "https://example.com/ipn.php",
            data: JSON.stringify({ "tid": "123456", "amount": "9.99" }),
            success: function() { document.location = "https://example.com/success.php" },
        });

    return false;
  });
});

JSON.stringify() would convert the object into string. And jQuery.ajax() would use the string to be correctly encoded request body and leave it untouched. The contentType field would be the Content-Type header in the request call.

Koala Yeung
  • 7,475
  • 3
  • 30
  • 50