I'm using softtouch API with WordPress, and posting data to API via curl.
But in response I am not able to send the big integer value in function. I'm not getting is that data type range issue or curl.
Below is my code:
//create reservation
$prod_items = array();
$single_item = array('product_uid'=>11449701010101);
$prod_items[] = $single_item;
$res_params = array(
'customer_id' => 1111,
'payment_type' => '',
'invoice_address_id' => 123,
'delivery_address_id' => 142,
'giftlist_id' => '',
'store_id' => '',
'items' => $prod_items
);
$res_url = $base_url . 'reservations';
$res_content = json_encode($res_params);
$res_curl = curl_init();
curl_setopt($res_curl, CURLOPT_HTTPHEADER, array('Authorization: ' . $authToken, 'Content-Type: application/json'));
curl_setopt($res_curl, CURLOPT_POST, true);
curl_setopt($res_curl, CURLOPT_POSTFIELDS, $res_content);
curl_setopt($res_curl, CURLOPT_URL, $res_url);
curl_setopt($res_curl, CURLOPT_RETURNTRANSFER, true);
$res_response = curl_exec($res_curl);
if ($res_response === FALSE)
die(curl_error($res_curl));
curl_close($res_curl);
$res_array = json_decode($res_response);
While sending data to the curl_exec() function it removes the last two digits of the product_uid, as I passed it 11449701010101 it send it as 114497010101.
Is that any integer range issue or something curl function issue?
tl:dr There would seem to be something else (in the script that processes the CURL request) that is truncating the product_uid. (?)
array('product_uid'=>11449701010101)
If you are on a 32 bit system (PHP compiled as 32 bit) then 11449701010101 does exceed the 32 bit integer range. However, in such cases, PHP silently converts the number to a float and nothing is "lost" in this instance.
json_encode($res_params);
The PHP function json_encode() converts the passed array into a string respresentation (JSON string). Nothing is lost. The 11449701010101 value is preserved.
While sending data to the curl_exec() function it removes the last two digits
The (POST) data being transmitted is an ordinary string, so nothing can be lost to the individual properties at this stage.
If the receiving script then decodes the transmitted JSON string, encodes it again and sends it back, the data is returned intact. The product_uid is a float, not an integer (as it is in the original data).
If you specifically force 11449701010101 to an integer (eg. (int)11449701010101) then you get -681801035 - the last 2 digits are not simply truncated. For the last 2 digits to be truncated there would seem to be some kind of string manipulation going on?
So, there would seem to be something else (not shown here) during the processing of this data that is perhaps truncating the value. (?)
Related
this is an issue I've run into before using curl. We do a mass data import at the beginning of the day for and part of that is geocoding some addresses. We use google's API to do this, so a simple curl loop (should) work, at least that's what I thought.
Here are my two functions: Note that the properties variable contains about 100 entries. However, no matter how many times I refresh, the loop always stops calling the curl function after the 5th iteration. Note that the loop does not terminate, only the call to the curl function appears to be lost.
function geocode()
{
$service_url = 'https://maps.googleapis.com/maps/api/geocode/json?key=' . GAPI_KEY . '&address=';
$properties = $this->listing_model->get_non_geocoded();
if ($properties) {
foreach ($properties->result() as $property) {
$service_url .= urlencode($property->address . "," . $property->city . "," . $property->state . " " . $property->zip);
try {
$search = $this->curl($service_url);
} catch (Exception $e) {
var_dump($e);
}
}
}
}
function curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
unset($ch);
return $result;
}
And of course the var dumps:
...previous (first) 3 entries...
string '14' (length=2)
object(stdClass)[116]
public 'lat' => float #######
public 'lng' => float #######
string '15' (length=2)
object(stdClass)[131]
public 'lat' => float #######
public 'lng' => float #######
string '16' (length=2)
null <-- ? Should be from curl
string '17' (length=2)
null <-- ? Should be from curl
string '18' (length=2)
null <-- ? Should be from curl
string '19' (length=2)
null <-- ? Should be from curl
According to the API's documentation found here: https://developers.google.com/maps/documentation/geocoding/, it looks like you can only do five calls a second with a total of 2500 requests per day.
So now, I think your question is how to properly handle the rate limit and it looks like there are some good ideas here: How to manage request limited API calls
(Keeping track of every request, sleeping between every set of five requests, etc.)
Best of luck!
EDIT: Sorry! Didn't see that you had it solved. Figured that since the limit on the API was five and your loop was failing every five iterations, there was a correlation.
I have a homemade web interface with several text and text area input fields. The primary text field are being sent to Parse in a php script via REST API. It works brilliant until I input approximately more than 3.000 characters in one of the textarea input fields.
When below approx. 3.000 characters, everything works fine. When above approx. 3.000 characters, the data gets sent to parse, and I can see it among the other push messages in my dashboard with a green check mark in "status", but the push notification is NOT being sent to any of the subscribed devices!
I'm using it for sending out news articles, so it is a must to be able to send whole articles above approx. 3.000 characters.
Is there any limitations in relation to the amount of characters to be sent or anything similar?
Does anyone know something that can help me or has any suggestions to how I can resolve this issue?!
The Parse parts of my script:
/*
* PUSHING THE ARTICLE NOTIFICATION TO DEVICES SUBSCRIBING TO SPECIFIC CHANNELS(S)
*/
$url = PUSH_URL;
$appId = PUSH_APP_ID;
$restKey = PUSH_REST_KEY;
$channels = array($channelArray);
$headers = array(
"Content-Type: application/json",
"X-Parse-Application-Id: " . $appId,
"X-Parse-REST-API-Key: " . $restKey
);
$objectData = json_encode(array(
"data" => array(
"id" => $id ,
"watchTitle" => stripslashes($watchTitle) ,
"title" => $textTitle ,
"alert" => $textSubtitle ,
"mainText" => $textMain ,
"imgUrl" => $imgUrl ,
"uri" => "http://watch.jgskytte.com/parse/article.php?p=" . $id ,
),
"channels" => $channels ,
));
$rest = curl_init($url);
curl_setopt($rest, CURLOPT_HTTPHEADER, $headers);
curl_setopt($rest, CURLOPT_POST, true);
curl_setopt($rest, CURLOPT_POSTFIELDS, $objectData);
curl_setopt($rest, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($rest);
echo $response;
curl_close($rest);
There's no explicit limit on string length, but Parse Objects are limited to 128k. Otherwise, you should use a Parse File.
This is probably occurring because you're hitting the maximum length limit for a URL. To get around this, you can use a POST request instead which will send the query string as part of the HTTP request body, which has no such length limit.
Since Parse's REST API expects this query to be sent as a GET request, you will need to pass an additional header to let Parse know to treat this POST as a GET:
X-HTTP-Method-Override: GET
I tried implementing the following PHP code to POST JSON via PHP: cURL (SOME FORCE.COM WEBSITE is a tag that signifies the URL that I want to POST):
$url = "<SOME FORCE.COM WEBSITE>";
$data =
'application' =>
array
(
'isTest' => FALSE,
key => value,
key => value,
key => value,
...
)
$ch = curl_init($url);
$data_string = json_encode($data);
curl_setopt($ch, CURLOPT_POST, true);
//Send blindly the json-encoded string.
//The server, IMO, expects the body of the HTTP request to be in JSON
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER,
array
(
'Content-Type:application/json',
'Content-Length: ' . strlen($data_string)
)
);
$result = curl_exec($ch);
curl_close($ch);
print_r($result);
echo '<pre>';
echo $_POST;
$jsonStr = file_get_contents('php://input'); //read the HTTP body.
var_dump($jsonStr);
var_dump(json_decode($jsonStr));
echo '</pre>';
The output of the above is the following:
"Your TEST POST is correct, please set the isTest (Boolean) attribute on the application to FALSE to actually apply."
Arraystring(0) ""
NULL
OK, the above confirms that I formatted the JSON data correctly by using json_encode, and the SOME FORCE.COM WEBSITE acknowledges that the value of 'isTest' is FALSE. However, I am not getting anything from "var_dump($jsonStr)" or "var_dump(json_decode($jsonStr))". I decided to just ignore that fact and set 'isTest' to FALSE, assuming that I am not getting any JSON data because I set 'isTest' to TRUE, but chaos ensues when I set 'isTest' to FALSE:
[{"message":"System.EmailException: SendEmail failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Missing body, need at least one of html or plainText: []\n\nClass.careers_RestWebService.sendReceiptEmail: line 165, column 1\nClass.careers_RestWebService.postApplication: line 205, column 1","errorCode":"APEX_ERROR"}]
Arraystring(0) ""
NULL
I still do not get any JSON data, and ultimately, the email was unable to be sent. I believe that the issue is resulting from an empty email body because there is nothing coming from "var_dump($jsonStr)" or "var_dump(json_decode($jsonStr))". Can you help me retrieve the JSON POST? I would really appreciate any hints, suggestions, etc. Thanks.
I solved this question on my own. I was not sure if I was doing this correctly or not, but it turns out that my code was perfect. I kept refreshing my website, from where I am POSTing to SOME FORCE.COM WEBSITE. I believe that the people managing SOME FORCE.COM WEBSITE were having issues on their end. Nothing was wrong with what I did. For some reason, I got a code 202 and some gibberish text to go along with it. I would be glad to show the output, but I do not want to POST again for the sake of the people managing SOME FORCE.COM WEBSITE that I am POSTing to. Thank you guys for your help.
I'm currently running into a massive wall due to a problem i cannot seem to solve.
The problem is that, when you issue a payment through the Facebook payment platform (facebook javascript sdk), it sends data to your callback page, which should handle the payment on the background.
This all works decent, but there is 1 problem: The order ID that facebook uses is a 64bit ID, and my server is a 32bits server, thus it loses precision on the ID when it gets saved to a variable in the callback page. This ultimately results in not being able to get a proper order_ID in the end, because it cannot save the ID.
The issue has been described on several pages on this forum, for example:
facebook credit callback, order_id changes format changes after moving to a new server
and
PHP: Converting a 64bit integer to string
Yet, on both pages there is no solution to the problem, and i cannot seem to fix this myself.
I have tried to convert the json data that facebook sends to my callback page into string data instead of an array with integers (this happens in the basic code provided by facebook), but i just cannot get this to work.
Seeing that others have overcome this problem (without having to migrate everything to a 64bits server), i am wondering how.
Is anyone able to shine a light on this subject?
Edit:
I have tried converting to string, the standard facebook code that gets called to decode the json data (code provided by facebook):
$request = parse_signed_request($_POST['signed_request'], $app_secret);
This calls the function parse_signed_request, which does:
function parse_signed_request($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
error_log('Unknown algorithm. Expected HMAC-SHA256');
return null;
}
// check sig
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
This function decodes the encrypted json data from facebook (using the app secret) and should decode the json data to a PHP array.
That function uses the following function (the exact:
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
Now, the above code results in the order ID not being saved properly, and it loses its precision, resulting in an id like: 4.8567130814993E+14
I have tried to use the following function to somehow decode the json data into a string (so the 64bit integer ID does not lose its precision), but to no avail:
function largeint($rawjson) {
$rawjson = substr($rawjson, 1, -1);
$rawjson = explode(',' , $rawjson);
array_walk($rawjson, 'strfun');
$rawjson = implode(',', $rawjson);
$rawjson = '{' . $rawjson . '}';
$json = json_decode($rawjson);
return $json;
}
function strfun(&$entry, $key) {
$data = explode(':', $entry);
if (FALSE === strpos($data[1], '"')) {
$data[1] = '"' . $data[1] . '"';
$entry = implode(':', $data);
}
}
Edit (Eugenes answer):
If i were to try modifying the JSON data before i use json_decode to make it a php variable, i should be using the preg_replace function?
Below is an example of the initial JSON data that gets sent to the callback page to initiate the payment process.
Here you can already see what the problem is (this is after using json_decode, the id and other data lose their precision). The ID's are modified to not reflect any real data.
If you compare the buyer ID on the top and user id on the bottom, you can see precision is lost.
Array
(
[algorithm] => HMAC-SHA256
[credits] => Array
(
[buyer] => 1.0055555551318E+14
[receiver] => 1.0055555551318E+14
[order_id] => 5.2555555501665E+14
[order_info] => {"item_id":"77"}
[test_mode] => 1
)
[expires] => 1358456400
[issued_at] => 1358452270
[oauth_token] => AAAH4s2ZCCEMkBAPiGSNsmj98HNdTandalotmoredata
[user] => Array
(
[country] => nl
[locale] => nl_NL
[age] => Array
(
[min] => 21
)
)
[user_id] => 100555555513181
)
Edit #3:
I have tried the following to make all the integers in the JSON data seen as strings, but that results in an error from the facebook platform. It does however change the integers to a string, so i do not lose precision (too bad nothing else works now xD)
preg_replace('/([^\\\])":([0-9]{10,})(,|})/', '$1":"$2"$3', $a)
Which version of PHP are you running?
If you are running a version of PHP that supports the JSON "JSON_BIGINT_AS_STRING" option, that may be your answer. You may have to modify their library wherever json_decode is being used to add that option. See http://php.net/manual/en/function.json-decode.php
If your PHP version does not support JSON_BIGINT_AS_STRING, then your options are limited to:
The hacky option: Do some kind of regex operation on the JSON string as it comes back from the FB API and wrap that big ints in double-quotes, so that they decode as a string and not a big int.
The ideal option: Bite the bullet and migrate to a 64 bit environment. It will save you from a lot of headaches in the long run.
This question already has answers here:
curl POST format for CURLOPT_POSTFIELDS
(10 answers)
Closed 4 years ago.
I have this curl request below, which was successfully troubleshooted in another post. Right now, my PHP seems to work through this code without any errors, moves onto the next part of the IF statement and sends the confirmation email. It just doesn't update the database as it should from the web service. I will have to email the creator of the web service if this does not work but I just want to be sure that the code is fairly solid before I do this. Any one have any ideas? Here is the code:
$url = 'http://127.0.0.1:85/AccountCreator.ashx';
$curl_post_data = array(
'companyName' =>urlencode($companyName),
'mainContact' =>urlencode($mainContact),
'telephone1' =>urlencode($telephone1),
'email' => urlencode($email),
'contact2' => urlencode($contact2),
'telephone2' => urlencode($telephone2),
'email2' => urlencode($email2),
'package' => urlencode($package)
);
foreach($curl_post_data as $key=>$value) {$fields_string .=$key. '=' .$value.'&';
}
rtrim($fields_string, '&');
//die("Test: ".$fields_string);
$ch = curl_init();
curl_setopt ($ch, CURLOPT, $url);
curl_setopt ($ch, CURLOPT_POST, count($curl_post_data));
curl_setopt ($ch, CURLOPT_POSTFIELDS, $fields_string);
$result = curl_exec($ch);
curl_close($ch);
Firstly, what is the problem? It would be easier to troubleshoot it if you explained exactly what the failure in the code was. Secondly, there are a couple of odd things you are doing in this code:
I don't see why you are doing
curl_setopt ($ch, CURLOPT_POST, count($curl_post_data));
CURLOPT_POST requires a boolean (true/false) setting. You should set it to true.
Secondly, you don't need to encode CURLOPT_POSTFIELDS manually. Make an array and let cURL deal with it internally:
$curl_post_data = array(
'companyName' =>$companyName,
'mainContact' =>$mainContact,
'telephone1' =>$telephone),
'email' => $email,
'contact2' => $contact2,
'telephone2' => $telephone2,
'email2' => $email2,
'package' => $package
);
These might not fix the problem, but they may help.
The CURLOPT_POSTFIELDS option accepts an associative array of POST-data. Probably better to use that one rather than to construct the query string yourself so you got someone else to blame when it blows up.
PHP Manual:
The full data to post in a HTTP "POST"
operation. To post a file, prepend a
filename with # and use the full path.
This can either be passed as a
urlencoded string like
'para1=val1¶2=val2&...' or as an
array with the field name as key and
field data as value. If value is an
array, the Content-Type header will be
set to multipart/form-data.