1

Without class, just plain code my method is working and getting "SUCCESS" response_status, but when i put it in a class i get nothing.

All code:


class THBS_API
{
    private const call_url = "https://xxxxxxxxxxxx.xxx/endsoftware.php";
    private $base_url;
    private $fields;
    private $fields_string;

    public static function getUsers()
    {
        $base_url = $_SERVER['SERVER_NAME'];
        $fields_string = '';

        $fields = array(
        'API_USER' => urlencode('xxxxxx@xxxxxx.xxx'),
        'API_PASS' => urlencode('xxxxxxxxx'),
        'CMD' => urlencode('getUserCount'),
        'FROM' => urlencode($base_url));

        //url-ify the data for the POST
        foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
        rtrim($fields_string, '&');

        //open connection
        $ch = curl_init();

        //set the url, number of POST vars, POST data
        curl_setopt($ch,CURLOPT_URL, $call_url);
        curl_setopt($ch,CURLOPT_POST, count($fields));
        curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);


        //execute post
        $result = curl_exec($ch);

        //close connection
        curl_close($ch);

        $response = json_decode($result, true);
        return $response['response_status'];
    }
}



echo THBS_API::getUsers();

Is very weird, but i think is because declaring variables is different in classes, is the problem i use privar $base_url? and how to solve this?

P.S: that is my first class ever, i worked fine with normal functions, but i still want to learn classes functions

Now i get

Notice: Undefined variable: fields_string in /srv/disk1/3203065/www/xxxxxxxxxxxxxxxxxx.com/API/clientapi.php on line 24

Line 44:

return $response['response_status'];

Code without class (working):

$base_url = $_SERVER['SERVER_NAME'];
  $url = "https://xxxxxxxxxxx.com/API/endsoftware.php";


  $fields = array(
    'API_USER' => urlencode('xxxxxx@xxxxx.xxxx'),
    'API_PASS' => urlencode('xxxxxxxxxx'),
    'CMD' => urlencode('getUserCount'));

//url-ify the data for the POST
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);


//execute post
$result = curl_exec($ch);

//close connection
curl_close($ch);

$response = json_decode($result, true);
echo $response['response_status'];

(returns "SUCCESS")

Thos-Host
  • 67
  • 8

1 Answers1

0

A couple of changes to your code.

  • Since call_url is always going to be constant, you can declare it as a constant in your class.

  • Second is your are concatenating $field values one by one with an & which is not needed. You can use http_build_query function for this.

  • Third is you had curl_setopt($ch,CURLOPT_POST, count($fields)); which is incorrect since this says make a POST request only if we have more than 0 fields. You would want to make a proper request regardless of it. So, set it to true always.

Snippet:

<?php

namespace THBS_API;

class THBS_API{
    private const call_url = "https://xxxxxxxxxxx.com/API/endsoftware.php";

    public static function getUsers(){
        $base_url = $_SERVER['SERVER_NAME'];
        $fields = array(
            'API_USER' => urlencode('xxxxxx@xxxxxx.xxx'),
            'API_PASS' => urlencode('xxxxxxxxx'),
            'CMD' => urlencode('getUserCount'),
            'FROM' => urlencode($base_url)
        );

        //open connection
        $ch = curl_init();

        //set the url, number of POST vars, POST data
        curl_setopt($ch,CURLOPT_URL, self::call_url);
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query($fields));
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false); // add certificates once you have them(recommended)
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        //execute post
        $result = curl_exec($ch);

        //close connection
        curl_close($ch);

        $response = json_decode($result, true);
        return $response['response_status'];
    }
}


echo THBS_API::getUsers();

Update:

As @Dharman mentioned in the comments, you should always add certificates to your cURL requests to avoid man in the middle attacks attacks and this answer shows how you can add one to your cURL request.

Also, you can simply use http_build_query instead of individually encoding each one as http_build_query would do it anyway. So take off the urlencode from the above code.

nice_dev
  • 14,216
  • 2
  • 21
  • 33
  • Oh, and one last question: i made the function to have parameters and changed a little bit (working) How can i use arrow functions for classes functions? Like `$command->THBS_API::CMD_EXTERNAL();` – Thos-Host Feb 07 '20 at 14:22
  • $command is definied by $command = "getUserCount" (can be something like getTheme or anything i defined in my external API) – Thos-Host Feb 07 '20 at 14:25
  • simply i want to use `$command->THBS_API::CMD_EXTERNAL();` instead of `THBS_API::CMD_EXTERNAL($command);` – Thos-Host Feb 07 '20 at 14:25
  • @Thos-Host Ok, not very clear to me, but you can't do `$command->THBS_API::CMD_EXTERNAL();`. We use the `->` syntax in PHP only when we have an object with us and calling a class method with it. – nice_dev Feb 07 '20 at 14:27
  • 1
    **[You should not switch off `CURLOPT_SSL_VERIFYHOST` or `CURLOPT_SSL_VERIFYPEER`](https://paragonie.com/blog/2017/10/certainty-automated-cacert-pem-management-for-php-software)**. It could be a security risk! [Here is how to get the certificate bundle if your server is missing one](https://stackoverflow.com/a/32095378/1839439) – Dharman Feb 08 '20 at 17:46
  • @Dharman yes, that's why there is a comment saying you should attach a cert. – nice_dev Feb 08 '20 at 17:50
  • Why did you switch it off? I don't see these two lines in the question. – Dharman Feb 08 '20 at 17:51
  • @Dharman just in case OP doesn't get a response anymore, because his API site had https. – nice_dev Feb 08 '20 at 17:52
  • So just in case you suggested a way to introduce a vulnerability. What if OP already has a working certificate bundle? – Dharman Feb 08 '20 at 17:53
  • Also I see you are double encoding the parameters. First with `urlencode` and then with `http_build_query` – Dharman Feb 08 '20 at 17:53
  • @Dharman Well, I didn't see that in his post, so how should I be sure about it? – nice_dev Feb 08 '20 at 17:54
  • 1
    My point is don't tell someone how to do a bad thing, just because you might think they would ever need this poor workaround. If you suspect they might have an issue with SSL then tell them how to fix it. – Dharman Feb 08 '20 at 17:55
  • @Dharman Fair enough. I will update my answer with those cert related links. – nice_dev Feb 08 '20 at 17:58
  • @Thos-Host Please look at the update as it is very useful security wise as pointed out by Dharman. – nice_dev Feb 08 '20 at 18:27