Call JSON API from within PHP Cron Job - php

I have a large system with an API.
On the frontend, JavaScript uses AJAX to talk to the API.
I have a PHP file that runs every 5-min as a CRON job.
I want this PHP code to interact with the API.
All it has to submit is query-vars.
All that is sent back is a single number.
For Example:
https://examplesite.com/api/create?id=1&data=2
This replies with a simple number that is the SQL last-insert-id.
EXTRA:
The API also needs two Session variables (user-id and system-id)
Can I just start session and set them before calling the API I guess?
I need the PHP script, ran by the CRON system, to talk to this API.
I have tried using cURL but no luck yet:
//Need to add a user-id to session, does this work?
session_start();
$_SESSION['user-id'] = 1;
//HOW TO CALL API FROM CRON?
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($ch, CURLOPT_URL, 'https://example.com/api/create?id=1&gid=2');
//curl_setopt($ch, CURLOPT_URL, 'http://example.com/api/create?id=1&gid=2');
curl_setopt($ch, CURLOPT_URL, 'file://../framework/api/create.php?id=1&data=2');
$result = curl_exec($ch);
curl_close($ch);
$result = str_replace("\n", '', $result); // remove new lines
$result = str_replace("\r", '', $result); // remove carriage returns
//Expect Result to be a number only
file_put_contents("curl.log", "[".date('Y-m-d H:i:s')."] $result\n\n", FILE_APPEND);
The file method doesn't seem to work... maybe path issue with ../
The http method doesn't seem to work... server loopback issue?
Any advice on how to best have my PHP CRON robot use my API will be much appreciated.
I have simply copied API code into the CRON, but then I am duplicating code, and not allowing the robot to test the real API.
Thanks.

Assuming you still wanted to use a session. Your first curl should be a request that to a script that will create the SESSION then respond.
I created this get_cookie.php this to test this concept:
<?php
session_start();
$_SESSION['time'] = time();
echo 'Time=' . $_SESSION['time'];
?>
I called this script to get the PHPSESSID from the response cookie
$ch = curl_init('http://example.com/get_cookie.php');
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE));
$head = substr($response,0,$skip);
$data = substr($response,$skip);
$end = 0;
$start = strpos($head,'Set-Cookie: ',$end);
$start += 12;
$end = strpos($head,';',$start );
$cookie = substr($head,$start ,$end-$start );
file_put_contents('cookie.txt',$cookie);
echo "\ncookie=$cookie";
echo "\n$data\n";
RESPONSE:
cookie=PHPSESSID=bc65c95468d08dd02cc5ab8ab87bbd39
Time=1664237484
The CRON job URL, session.php:
<?php
session_start();
echo 'Time=' . $_SESSION['time'];
?>
This is the CRON job script.
$cookie = file_get_contents('cookie.txt');
$ch = curl_init('http://example.com/session.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIE, $cookie );
curl_setopt($ch, CURLOPT_HEADER, false);
$response = curl_exec($ch);
echo $response;
RESPONSE:
Time=1664237484
The result "Time" ($_SESSION['TIME']) is always the same as the time from the get_cookie.php.

Thanks for the help, but in the end my alternate approach will be easiest and work best. Here is the answer for others in need...
To have an external PHP (run via CRON) test an internal PHP API (that the frontend JavaScript usually talks to via AJAX), this is the easiest solution, including passing query-variables and session-vars.
STEP 1: Don't worry about start_session() or passing any query variables, just add what you need to the arrays ahead of time.
STEP 2: Capture the output buffer and simply include the PHP API file:
$_SESSION['user-id'] = ' works! ';
$_REQUEST['var'] = ' too ';
ob_start();
include '/var/www/sitename.com/framework/api/create.php';
$result = ob_get_contents();
ob_end_clean();
file_put_contents("/var/www/sitename.com/cron/curl.log", "[".date('Y-m-d H:i:s')."] Result: $result\n\n", FILE_APPEND);
/* OUTPUT in curl.log:
[2022-09-26 22:30:01] Result: works! / too
*/
/* create.php API
$user = $_SESSION['user-id']??' did not work ';
$req = $_REQUEST['var' ]??' novar ';
echo $user.'/'.$req;
*/
(obviously the CRON has to be on the same server as the website/api, otherwise you will have to use cURL with Cookie/Session/QueryVar-Arrays)

Related

how do php scripts for data mining from web pages work?

[Edited for better explanation and code included]
Hi! I have a php script on my web server that logs in to my heat pump web interface nibeuplink.com and gets all my temperature readings and so forth and returns them in a json-format.
freeboard.io is a free service for visualizing data, so I'm making a freeboard.io for my heat pump values. in freeboard.io I can add any json data as a data source, so I have added the link to my php-script. It fetches the data once but it seems there is some kind of cached values that it uses after that so they are not updated with new values from the script. freeboard.io uses a get-function to get the url. If i use a normal web browser to run the php script and refresh it, the values are updated - and also immediately updated in freeboard.io. Freeboard.io has a setting to automatically update the data source every 5 seconds.
It seems that there is something that triggers the script correctly when it is fetched from my web browser, but not when it is fetched from freeboard.io that uses a get function every 5 seconds to get new data.
in freeboard I can add headers to the get request, is there some header that would help me here to discard any cached data?
I hope that explains my problem better.
Is there anything i can add to my code in the beginning to always force an override of any cached data?
<?php
/*
* read nibe heatpump values from nibeuplink status web page and return them in json format.
* based on: https://www.symcon.de/forum/threads/25663-Heizung-Nibe-F750-Nibe-Uplink-auslesen-auswerten
* to get the code which is required as parameter, log into nibe uplink, open status page of your heatpump, and check url:
* https://www.nibeuplink.com/System/<code>/Status/Overview
*
* usage: nibe.php?email=<email>&password=<password>&code=<code>
*/
// to add additional debug output to the resulting page:
$debug = false;
date_default_timezone_set('Europe/Helsinki');
$date = time();
// Create temp file to store cookies
$ckfile = tempnam ("/tmp", "CURLCOOKIE");
// URL to login page
$url = "https://www.nibeuplink.com/LogIn";
// Get Login page and its cookies and save cookies in the temp file
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile); // Stores cookies in the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
// Now you have the cookie, you can POST login values
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, "Email=".$_GET['email']."&Password=".$_GET['password']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); // Uses cookies from the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Tells cURL to follow redirects
$output = curl_exec($ch);
curl_setopt($ch, CURLOPT_URL, "https://www.nibeuplink.com/System/".$_GET['code']."/Status/ServiceInfo");
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_POST, 0);
$result = curl_exec($ch);
$pattern = '/<h3>(.*?)<\/h3>\s*<table[^>]*>.+?<tbody>(.+?)<\/tbody>\s*<\/table>/s';
if ($debug) echo "pattern: <xmp>".$pattern."</xmp><br>";
$pattern2 = '/<tr>\s*<td>(.+?)<span[^>]*>[^<]*<\/span>\s*<\/td>\s*<td>\s*<span[^>]*>([^<]*)<\/span>\s*<\/td>\s*<\/tr>/s';
if ($debug) echo "pattern2: <xmp>".$pattern2."</xmp><br>";
preg_match_all($pattern, $result, $matches);
// build json format from matches
echo '{';
$first = true;
foreach ($matches[1] as $i => $title) {
echo ($first ? '"' : ',"').trim($title).'":{';
$content = $matches[2][$i];
preg_match_all($pattern2, $content, $values);
$nestedFirst = true;
foreach ($values[1] as $j => $field) {
echo ($nestedFirst ? '"' : ',"').trim($field).'":"'.$values[2][$j].'"';
$nestedFirst = false;
}
echo "}";
$first = false;
}
echo ",\"time\":{\"Last fetch\":\"$date\"}";
echo "}";
if ($debug) {
echo "<pre><xmp>";
echo print_r($matches);
echo "<br><br>";
echo $result;
echo "</xmp></pre>";
}
?>
You can make an ajax call to php script to refresh the part of webpage. I don't understand what do you mean by io i.e. are you talking about fetching the data from database and if any changes occurred in database then only newly added records must be fetched. If you mean it in that sense then you can use cookie to track any new records added into database and only if it finds new records it can make ajax call to php script to run your algorithm on fetched total dataset.

sms sending in php by passing variables in url by using curl

Hi i need to send sms by using php. I am using curl method to post variables in url but i cant get sms. I can get result by using get method, is there any problem in my code?
$url = 'http://online.chennaisms.com/api/mt/SendSMS?';
$postData = array();
$postData['user'] = 'abc';
$postData['password'] = 'qwftgry ';
$postData['senderid'] ='reyty';
$postData['channel'] ='Trans';
$postData['DCS'] =0;
$postData['flashsms'] =0;
$postData['number'] = 91XXXXXXXXXX;
$postData['text'] ='hai ';
$postData['route'] =28;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
$result = curl_exec($ch);
curl_close($ch);
Try to delete ? character at the end of url
I don't see any problem in your code, apart from the lack of any error-checking on the cURL transaction (by means of curl_error() etc), so you should probably look elsewhere - was an error message returned by the SMS provider, for example?

using php curl to pass variables to another site

I saw the following code on another post...
<?php
$ch = curl_init(); // create curl handle
$url = "http://www.google.com";
/**
* For https, there are more options that you must define, these you can get from php.net
*/
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query(['array_of_your_post_data']));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3); //timeout in seconds
curl_setopt($ch,CURLOPT_TIMEOUT, 20); // same for here. Timeout in seconds.
$response = curl_exec($ch);
curl_close ($ch); //close curl handle
echo $response;
?>
The only thing is I have no clue how to actually implement it or how it will work.
Here is what I am trying to do...
sitea.com/setup is setting php variables. If you visited that page, it would set $var1 = "hello" $var2="hi"
If someone visits siteb.com, I want to use php and somehow get those variables from sitea.com/setup to siteb.com and set them as new php variables. I'm assuming curl is the best option from what I've read, but can't figure out how to get it to work (or where to put it and how to call it) for that matter.
I'm experimenting with code trying to see how to do something for an upcoming project. Any help would be greatly appreciated.
I should note that I need this to be able to work from one domain on server1 to another domain on server2.
In a simple way it can be done like:
Site a: file.php
<?php
$a = 10;
$b = 20;
echo $a . ':' . $b;
?>
Site b: curl.php
<?php
$ch = curl_init(); // create curl handle
$url = "http://sitea/file.php";
/**
* For https, there are more options that you must define, these you can get from php.net
*/
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query(['array_of_your_post_data']));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3); //timeout in seconds
curl_setopt($ch,CURLOPT_TIMEOUT, 20); // same for here. Timeout in seconds.
$response = curl_exec($ch);
curl_close ($ch); //close curl handle
echo $response;
$parts = explode(':', $response);
$var1 = $parts[0];
$var2 = $parts[1];
?>

Reading cURL request from receiving side to find out which file is requesting

Is there a way to read a curl request from receiving side to find out which files they are requesting from?
Below is the curl request from requesting side...
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $feed_url);
$content = curl_exec($ch);
curl_close($ch);
$x = new SimpleXmlElement($content);
foreach($x->channel->item as $entry) {
echo "<p><b> $entry->title </b></p>";
echo "<p> $entry->description </p>";
}
Pass the filename as a GET or POST parameter in your curl call.
in PHP it is as simple as using __FILE__ variable as one of the POST/GET parameters.
Do you have access to your server log files? The log files should contain a list of all requests, including those made by curl.

To get around the ajax 'same origin policy', code for a PHP ajax request forwarder?

I want to bypass the ajax same-origin policy by having a php page on my site that basically acts like a JSON proxy. Eg i make an ajax request like this:
mysite.com/myproxy.php?url=blah.com/api.json&a=1&b=2
It then makes a request to:
blah.com/api.json?a=1&b=2
And returns the JSON (or whatever) result to the original requester.
Now i assume i'd be stupidly reinventing the wheel if i wrote this php code (plus i don't know php!) - is there some pre-existing code to do this? I'm sure i'm not the only one who's butted my head up against the same-origin policy before.
Oh yeah JSONP isn't an option for this particular api.
Thanks all
Okay, here's something -
Slap this into a php script, call it like this
script.php?url=blah
post the contents you want posted to the server.
<?php
$curlPost = http_build_query($_POST);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
$data = curl_exec($ch);
curl_close($ch);
echo json_encode($data);
?>
Now this script is a bit too open for my liking, so to increase security I would recommend that you add a list of domains to a white list.
So add this to the top:
$whitelist = array('http://www.google.com','http://www.ajax.com');
$list = array();
foreach($whitelist as $w)
$list[] = parse_url($w,PHP_URL_HOST);
$url = $_GET['url'];
$url = pathinfo($url,PHP_URL_HOST);
if(!in_array($url, $list)) die('no access to that domain');

Categories