PHP cURL command inside foreach loop only shows last result - php

I'm new to programming, and I've made a page using PHP that lets us enter userIDs and add observers using the Canvas API and that worked great. I'm now trying to enter a list of people to be observed and have it process multiple URLs and this is where I'm running into problems. It only seems to process the final userID in the box.
Any ideas what I'm doing wrong? This doesn't need to be run often and I'm not worried about performance so I don't really need the cURL commands to process simultaneously.
$observeeA = explode ("\n", $observee);
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
foreach ($observeeA as $ob2){
if ($idtype == "Canvas") {
$url = $domain . "/api/v1/users/$observer/observees/" . $ob2; }
else {
$url = $domain . "/api/v1/users/sis_user_id:$observer/observees/sis_user_id:" . $ob2; }
curl_setopt($ch, CURLOPT_URL, $url);
$resp = curl_exec($ch);
echo $ob2 . "<br>" . $url . "<br>" . $resp . "<br>";
}
curl_close($ch);
The echo on line 13 outputs all the correct entries for the URL, but it never gets a response until the last one in the list.

It turns out that storing the string into the array with the explode function included extra hidden return characters, so I added $ob2 = trim($ob2); into the foreach loop and it now works.

Related

PHP parse array data using file_get_contents($url)

I have the following data I pulled from an API using PHP's file_get_contents($url), I would like to parse this data and put each comma separated value into a variable whilst looping to the next set (there are thousands of row, I simply extracted the first two), I have tried parsing methods however most have an element consisting of the datalabel:data, any assistance would be gladly appreciated.
[[1610223840000,"3.63410000","3.65100000","3.62900000","3.64150000","14194.01000000",1610223899999,"51684.84892800",195,"7619.89000000","27756.15839400","0"],[1610223900000,"3.64610000","3.65090000","3.63410000","3.65000000","2219.73000000",1610223959999,"8090.68646600",46,"1176.75000000","4290.44934900","0"]]
Ok figured this out today, for anyone who needs it
$ch = curl_init();
$url = "https://api.blahblahblah";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
curl_close($ch);
$obj = json_decode($result, true);
foreach ($obj as $key => $value) {
echo $value[0] . "<br>";
echo $value[1] . "<br>";
}

SMS API in PHP doesn't work if there is space in message

From Angular I am trying to hit a PHP API URL to send SMS.
Everything works fine if there is no space is the message, but if I add a space I am not receiving any messages.
Below is my PHP code:
<?php
header('Access-Control-Allow-Headers:Content-Type,x-prototype-version,x-requested-with');
header('Cache-Control:max-age=900');
include_once("conn.php");
$phno=$_POST['phno'];
$msg=$_POST['msg'];
$final = array();
$msg='Thank you.';
sms($phno,$msg);
$final['status']='success';
$final['message']="Success";
echo json_encode($final);
function sms($phonesms,$msg)
{
//echo 'hello';
$url = 'http://sms.domain.com/Api.aspx?usr=abcapi&pwd=pass123&smstype=TextSMS&to='.$phonesms.'&rout=Transactional&from=SMSACT&msg='.$msg;
echo $url;
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
}
?>
So if $msg='Thank you.'; SMS will not go, and if $msg='Thankyou.'; SMS goes.
I am sure there is something more I need to do here -$url = 'http://sms.domain.com/Api.aspx?usr=abcapi&pwd=pass123&smstype=TextSMS&to='.$phonesms.'&rout=Transactional&from=SMSACT&msg='.$msg;
String concatenation is not an ideal way to build a URL. If you do it this way make sure you apply the proper escaping for all the parameters.
$url = 'http://sms.domain.com/Api.aspx?usr=abcapi&pwd=pass123&smstype=TextSMS&to='
. urlencode($phonesms)
. '&rout=Transactional&from=SMSACT&msg='
. urlencode($msg);
Note: many characters are not legal or have special meaning inside a URL, like spaces; this will convert your spaces to "+" characters, which is their "escaped" version.
See https://www.php.net/manual/en/function.urlencode.php for more info.
use urlencode($msg)
$url = 'http://sms.domain.com/Api.aspx?usr=abcapi&pwd=pass123&smstype=TextSMS&to='.$phonesms.'&rout=Transactional&from=SMSACT&msg='.urlencode($msg);

How to get results names from Google Maps Api Search in PHP

I have a url like this, that search something in a location:
https://maps.google.com/maps?q=dentist+Austin+Texas&hl=en&mrt=yf=l
I need a list of the first 2 results like (“Dentist Mr.Example1”,”Dentist Ex.2”).
Watching this question: What parameters should I use in a Google Maps URL to go to a lat-lon? , I think the url is correct.
And watching this one: Get latitude and longitude automatically using php, API
I try this two options:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_PROXYPORT, 3128);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);
$response_a = json_decode($data);
and also this:
$content= file_get_contents($url);
preg_match_all("|<span class=\"pp-place-title\">(.*?)</span></span>|",$content,$result);
In both case I have no results at all.
Thanks in advance!
I have a url like this, that search something in a location:
https://maps.google.com/maps?q=dentist+Austin+Texas&hl=en&mrt=yf=l
I need a list of the first 2 results like (“Dentist
Mr.Example1”,”Dentist Ex.2”).
This is a Google Maps API Request.
Here you go:
$searchTerm = 'dentist+austin+texas';
$url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' . $searchTerm;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);
$array = json_decode($response, true);
// var_dump($array);
// Output
$array = $array['results'];
foreach($array as $index => $component)
{
echo '#' . $index . ' ' . $component['formatted_address'] . '<br>';
// show only the first 2 items (#0 & #1)
if($index === 1) {
break;
}
}
Some notes:
Your search term is "dentist Austin textas" and that becomes 'dentist+austin+texas' when it's part of an URL.
The searchTerm is attached to the API URL.
This URL is used for the cURL request.
The raw response is $response.
This is turned into an $array by setting the second paramter of json_decode() to true.
You might var_dump() the array to see the keys. Or simply call this URL in a browser: https://maps.googleapis.com/maps/api/geocode/json?address=dentist+austin+texas
For the display part: that's a simply array iteration. You can get rid of the top-level 'results' array by re-assigning the values to $array.
The output is a numbered list of dentists
Referencing: https://developers.google.com/maps/documentation/geocoding/
This is almost perfect, but I would like to get also the phone number and the ranking (stars for reviews).
The initial question was to list the first to results for dentists in austin,tx using the Google Maps API.
This additional requirement changes the API / webservice to use, in order to retrieve rich data. You want more details about the addresses.
The data elements "phone_number" and "rating" are part of the Google Places Webservice (Place Details). You need to add your key to the request URLs (&key=API_KEY) in order to access this service.
https://developers.google.com/places/webservice/details#PlaceDetailsRequests
This is a Place Detail Requests:
1) From the first request you extract the "place_id"s.
2) With subsequent requests you retrieve the details about each place via the "Place Details" webservice.
Example: here i'm using the placeid for the first entry:
https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJ0aPBm9xLW4YRLBdfVhz_2P0&key=AIzaSyCj9yH5x6_5_Om8ebAO2pBlaqJZB-TIViY
New code:
<?php
// Google GeoCode API
$address = 'dentist+austin+texas';
$array = getGoogleGeoCode($address);
$array = $array['results'];
//var_dump($array);
foreach($array as $index => $component)
{
echo '#' . $index . ' ' . $component['formatted_address'] . ', ' ;
// subsequent request for "Place Details"
$details = getGooglePlaceDetails($component['place_id']);
$details = $details['result'];
//var_dump($details);
echo 'Phone: ' . $details['formatted_phone_number']. ', ' ;
// rating contains the place's rating, from 1.0 to 5.0, based on aggregated user reviews.
if(isset($details['rating'])) {
echo 'Rating: ' . $details['rating'];
}
// show only the first two entries
/*if($index === 1) {
break;
}*/
echo '<br>';
}
function getGooglePlaceDetails($placeid)
{
// your google API key
$key = 'AIzaSyCj9yH5x6_5_Om8ebAO2pBlaqJZB-TIViY';
$url = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=' . $placeid . '&key=' . $key;
return curlRequest($url);
}
function getGoogleGeoCode($address)
{
$url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' . $address;
return curlRequest($url);
}
function curlRequest($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
Result:
The array element rating is not always present, because it's review based. Just use var_dump($details); to see what is there and pick what you need.
To reduce the list, remove the comments around the break statement.

Curl and Sagepay

I'm having a lot of trouble integrating Sagepay InFrame Server with PHP, as there are no integration kits available for the new protocol (v3). I have the old kits for v2.23 but much of the code therein is deprecated.
At the moment the only way i have been successful in retrieving an OK status from the Sagepay Server servers is to have a form with the collection of hidden values required by Sagepay, including the cryptography field, and using the server URL as the form action. This gives me a status of 'OK' and the SecurityKey etc in the browser tab, but its not much use in the browser tab as i need that POST response back on my server, not on theirs.
For this i opted for curl. I hold the return values for curl_exec in a variable called $rawresponse, and dump the response after each attempt, and as it stands $rawresponse is returning as a false boolean:
$curlSession = curl_init();
curl_setopt ($curlSession, CURLOPT_URL, $url);
curl_setopt ($curlSession, CURLOPT_HEADER, 0);
curl_setopt ($curlSession, CURLOPT_POST, 1);
$data['Crypt'] = new CurlFile('filename.png', 'image/png', 'filename.png');
curl_setopt ($curlSession, CURLOPT_POSTFIELDS, $data);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER,1);
curl_setopt($curlSession, CURLOPT_TIMEOUT,30);
curl_setopt($curlSession, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curlSession, CURLOPT_SSL_VERIFYHOST, 0);
$rawresponse = curl_exec($curlSession);
Now as you can see here I am having to force the Crypt value to be of type CurlFile, which is what i think is breaking the request, however if i dont do that i get the following error:
"The usage of the #filename API for file uploading is deprecated. Please use the CURLFile class instead"
I can only ascertain from this that the cryptography is being mistaken for a file (possibly because the string starts with #), and to counter this im trying to force it to be an image.
So my question is this - is there a particular way to use CurlFile so cryptography strings can be understood? Is there a better way of integrating this functionality with Sagepay that anyone knows about? It really is a very confusing system, and the good documentation is let down by a complete lack of example.
Apologies for this, I was building the string the wrong way. Just in case anyone has a similar problem in the future i'll paste the code that works for me:
public function registerTransaction()
{
$VPSProtocol = urlencode($_POST['VPSProtocol']);
$TxType = urlencode($_POST['TxType']);
$Vendor = urlencode($_POST['Vendor']);
$VendorTxCode = urlencode($_POST['VendorTxCode']);
$Currency = urlencode($_POST['Currency']);
$Amount = urlencode($_POST['Amount']);
$NotificationURL = urlencode($_POST['NotificationURL']);
$Description = urlencode($_POST['Description']);
$BillingSurname = urlencode($_POST['BillingSurname']);
$BillingFirstnames = urlencode($_POST['BillingFirstnames']);
$BillingAddress1 = urlencode($_POST['BillingAddress1']);
$BillingCity = urlencode($_POST['BillingCity']);
$BillingPostCode = urlencode($_POST['BillingPostCode']);
$BillingCountry = urlencode($_POST['BillingCountry']);
$DeliverySurname = urlencode($_POST['DeliverySurname']);
$DeliveryFirstnames = urlencode($_POST['DeliveryFirstnames']);
$DeliveryAddress1 = urlencode($_POST['DeliveryAddress1']);
$DeliveryCity = urlencode($_POST['DeliveryCity']);
$DeliveryPostCode = urlencode($_POST['DeliveryPostCode']);
$DeliveryCountry = urlencode($_POST['DeliveryCountry']);
$url = "?VPSProtocol=" . $VPSProtocol;
$url .= "&TxType=" . $TxType;
$url .= "&Vendor=" . $Vendor;
$url .= "&VendorTxCode=" . $VendorTxCode;
$url .= "&Currency=" . $Currency;
$url .= "&Amount=" . $Amount;
$url .= "&NotificationURL=" . $NotificationURL;
$url .= "&Description=" . $Description;
$url .= "&BillingSurname=" . $BillingSurname;
$url .= "&BillingFirstnames=" . $BillingFirstnames;
$url .= "&BillingAddress1=" . $BillingAddress1;
$url .= "&BillingCity=" . $BillingCity;
$url .= "&BillingPostCode=" . $BillingPostCode;
$url .= "&BillingCountry=" . $BillingCountry;
$url .= "&DeliverySurname=" . $DeliverySurname;
$url .= "&DeliveryFirstnames=" . $DeliveryFirstnames;
$url .= "&DeliveryAddress1=" . $DeliveryAddress1;
$url .= "&DeliveryCity=" . $DeliveryCity;
$url .= "&DeliveryPostCode=" . $DeliveryPostCode;
$url .= "&DeliveryCountry=" . $DeliveryCountry;
$strPurchaseURL = "https://test.sagepay.com/gateway/service/vspserver-register.vsp";
$arrResponse = $this->requestPost($strPurchaseURL, $url);
dd($arrResponse);
}
public function requestPost($url, $data){
// Set a one-minute timeout for this script
set_time_limit(60);
// Initialise output variable
$output = array();
// Open the cURL session
$curlSession = curl_init();
curl_setopt ($curlSession, CURLOPT_URL, $url);
curl_setopt ($curlSession, CURLOPT_HEADER, 0);
curl_setopt ($curlSession, CURLOPT_POST, 1);
curl_setopt ($curlSession, CURLOPT_POSTFIELDS, $data);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER,1);
curl_setopt($curlSession, CURLOPT_TIMEOUT,30);
curl_setopt($curlSession, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curlSession, CURLOPT_SSL_VERIFYHOST, 2);
$rawresponse = curl_exec($curlSession);
dd($rawresponse);
//Store the raw response for later as it's useful to see for integration and understanding
$_SESSION["rawresponse"]=$rawresponse;
//Split response into name=value pairs
$response = preg_split(chr(10), $rawresponse);
// Check that a connection was made
if (curl_error($curlSession)){
// If it wasn't...
$output['Status'] = "FAIL";
$output['StatusDetail'] = curl_error($curlSession);
}
// Close the cURL session
curl_close ($curlSession);
// Tokenise the response
for ($i=0; $i<count($response); $i++){
// Find position of first "=" character
$splitAt = strpos($response[$i], "=");
// Create an associative (hash) array with key/value pairs ('trim' strips excess whitespace)
$output[trim(substr($response[$i], 0, $splitAt))] = trim(substr($response[$i], ($splitAt+1)));
} // END for ($i=0; $i<count($response); $i++)
// Return the output
return $output;
} // END function requestPost()

Using the GoogleAPI to return the number of search results for 2 different queries. (PHP)

I'm working on a small experiment for my Honours Project. What I'm trying to achieve is to compute the similarity between the amount of results returned, based on 2 Google search queries. When I have the 2 results, I wish to divide one by the other in order to return a 'ratio' of sorts.
Now, it's easy enough to return one result using the API, I've been using this code:
$query="CinammonRolls";
$url = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=$query";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$body = curl_exec($ch);
curl_close($ch);
$json = json_decode($body);
print 'The results for ' . $query . ' are: ' . $json->responseData->cursor->estimatedResultCount;
That piece of code, returns the result fine. However I'm relatively new to PHP so the follow code, wasn't ever going to work; but I gave it a bash.
$query="CinammonRolls";
$query2="CinammonRollsChinese";
$url = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=$query";
$url2 = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=$query2";
$ch = curl_init();
$ch2 = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch2, CURLOPT_URL, $url2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 2);
$body = curl_exec($ch);
$body2 = curl_exec($ch2);
curl_close($ch);
curl_close($ch2);
$json = json_decode($body);
$json2 = json_decode($body2);
print 'The results for ' . $query . ' are: ' . $json->responseData->cursor->estimatedResultCount;
print 'The results for ' . $query2 . ' are: ' . $json2->responseData->cursor->estimatedResultCount;
That just returns the error:
Notice: Undefined property: stdClass::$estimatedResultCount in C:\Program Files\EasyPHP-5.3.9\www\googleTest.php on line 24
So I emplore you all, is there a way to get round this? Would it be something like computing both the results in separate functions? I'm stumped.
Thanks for any help.
I think you meant:
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 2);
to be:
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);
The option is to be turned on and off based on the 3rd parameter which is boolean, so 0 or 1. I think when you copied and pasted the lines for the 2nd query and was changing 1 to 2 you accidentally changed the 1 boolean to 2 (non-boolean).
"CinammonRollsChinese" returns NO RESULTS thus there is not estimated result count. You need to check to see if $json2->responseData->cursor->estimatedResultCount exists before doing anything with it since not every search string will yield results.
Avoid code repetition by extracting the querying code to a method, or to a class it it gets more complicated. See the rewrite below:
function print_google_query_results($query) {
$url = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=$query";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$body = curl_exec($ch);
curl_close($ch);
$json = json_decode($body);
print 'The results for ' . $query . ' are: ' . $json->responseData->cursor->estimatedResultCount;
}
$query="CinammonRolls";
$query2="CinammonRollsChinese";
print_google_query_results($query);
print_google_query_results($query2);
Thanks to everyone for the help, I really appreciate it. It's working exactly as I hoped now (with much cleaner code too!). Even though the main problem was the cause of me 'having the dumb'! Thanks for pointing that out, I'd be stuck with this till midnight. The problem was that a) My code was pretty lousy and could be compiled much better. and b) I didn't check to see if my second query 'CinammonRollsChinese' actually returned any results. It didn't.
Here is the final working code.
$query="CinammonRolls";
$query2="DeliciousCake";
print_google_query_results($query);
print '<br>';
print_google_query_results($query2);
function print_google_query_results($query) {
$url = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=$query";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$body = curl_exec($ch);
curl_close($ch);
$json = json_decode($body);
print 'The results for ' . $query . ' are: ' . $json->responseData->cursor->estimatedResultCount;
}
Superb. Huge thanks again to everyone.

Categories