Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Patwan's avatar

Problem Using AJAX to hit PHP Curl several times

I am working on a Laravel application whereby I am calling a payment gateway to get the payment status by the user. According to the documentation of the gateway, if I get a response of 500, I should continue hitting the API for a maximum of 5 times, if the response does not change to 200 stop the transaction.

I have written a PHP curl function that is used to reach out to the gateway and fetch the response together with the status(either 500 or 200). I have also written AJAX code to post data to the back end controller

How to write JS logic in the AJAX code to keep hitting the API so long as the status is 500 for a maximum of 6 times?

AJAX code posting data to the controller

<script type="text/javascript">

  $('.mpesa').on('click', function () {

    var type = $('.mpesa').prop('id');
    var quote = $('#quote').val();
    var phone = $('#phone').val();
    //Converts to a JSON object
    var type ={
      'type': type,
      'quote' : quote,
      'phone' : phone,
    };

    $.ajax({
      type:"POST",
      url:"checkStat",
      data:JSON.stringify(type),
      contentType: "application/json",
      cache:false,
      success: function(data)
      {
          alert(data)
      }
      error: function error(data) {
          alert('Error');
      }
     });   
    });
</script>

Routes file

Route::any( '/checkStat', 'B2CController@checkStat')->name('b2c.checkStat');

Controller

public function checkStat(Request $request){
        //dd($request->all);

        //convert to JSON string
        $data =(object)$request->all();
        //dd($data);

        $ref = $data->payment_reference;

        $type = $data->payment_type;

        $data = array(
            'payment_reference' => $ref,
            'payment_type' => $type,
        );

        //dd($data);

         //Set maximum execution time
        ini_set('max_execution_time ', 75);
        set_time_limit(75);
        //Loop through the code 3 times
        for($try=1; $try<=3; $try++) {
            sleep(10);
            $payStat = $this->global_Curl_payStat($data, 'api/payment/status')->data;
        }
        var_dump($payStat);
        dd($payStat);
    }

Curl function to hit the API that is being called in the controller above

public function global_Curl_payStat($data, $url, $try = 1)
    {
        //dd($_ENV['API_ENDPOINT_NGINX_IP'] . '/' . $url);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, ($_ENV['API_ENDPOINT_NGINX_IP'] . '/' . $url));
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //Prevents URL cache
        curl_setopt($ch, CURLOPT_FRESH_CONNECT, TRUE);
        //Fetch response
        $response = curl_exec($ch);
        //Get HTTP header status code
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        //dd($statusCode, $response);

        curl_close($ch);

        return $response;
}
0 likes
8 replies
lostdreamer_nl's avatar

add the same code I gave you for the getStatus request to this payStat method (the part that checks the statuscode == 500 and if so, retries the request.

If you do that, you dont have to put it in the JS code.

public function global_Curl_payStat($data, $url, $try = 1)
    {
        //dd($_ENV['API_ENDPOINT_NGINX_IP'] . '/' . $url);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, ($_ENV['API_ENDPOINT_NGINX_IP'] . '/' . $url));
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //Prevents URL cache
        curl_setopt($ch, CURLOPT_FRESH_CONNECT, TRUE);
        //Fetch response
        $response = curl_exec($ch);
        //Get HTTP header status code

        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 
        $response = json_decode(curl_exec($ch));
        curl_close($ch);

        if($statusCode == 500 && $try < 5) {
                // on HTTP status 500, we'll try up to 5x (dont want any eternal loop)
                // let's also wait for a second before trying again
                sleep(1);
                return $this->global_Curl_payStat($data, $url, ++$try);
        }

        return $response;
}

If you really want to do this in JS (but I really suggest doing this part in the PHP code)

error: function(jqXHR, textStatus, errorThrown) {
    alert(jqXHR.status);  // this could then be 500, so you should do the request again.
    alert(textStatus);
    alert(errorThrown);
}
1 like
Patwan's avatar

@lostdreamer_nl I implemented what you had previously advised me to do,, the issue is that even after trying for 5 times the 500 internal server error is still being passed when I call the curl function

The code am using to call the curl function is

       //Set maximum execution time
        ini_set('max_execution_time ', 75);
        set_time_limit(75);
        //Loop through the code 3 times
        for($try=1; $try<=3; $try++) {
            sleep(10);
            $payStat = $this->global_Curl_payStat($data, 'api/payment/status')->data;
        }
        var_dump($payStat);
        dd($payStat);

But I still get the 500 internal server error when I dd() as shown in the code above

Cronix's avatar

According to the documentation of the gateway, if I get a response of 500, I should continue hitting the API for a maximum of 5 times, if the response does not change to 200 stop the transaction.

Huge red flag. Get a payment gateway that doesn't suck and is actually available.

1 like
Patwan's avatar

@Cronix Sure,, will check out for another API gateway...concerning the code I posted above,, what do you think of the maximum execution time,, Maybe it is the course of 500 500 internal server error

Cronix's avatar

Your error logs should tell you that regarding the 500 error. I don't see why you'd need to set a max_execution_time/set_time_limit() limit at all here really. It's already basically contained in the loop since you have a max retry of 3 times. Yes, if everything takes longer than 75 seconds, it will cause a 500 error because of that limit. I'd remove them.

Snapey's avatar

does it ever work? Is it an issue that your code will always fail for some other problem?

Patwan's avatar

@Snapey When I dd the status code sometimes I get a 200 Status code while majority of the time it shows 500 status code. Since am testing,, am using the same payload multiple times.. Not sure if it is the cause of the error...

Cronix's avatar

Did you check your error logs? /storage/logs/laravel.log

Please or to participate in this conversation.