Executing Curl with PHP - php

I'm trying to use Docverter to convert LaTeX/markdown files to PDF but am having trouble using PHP to do CURL to access Docverter via their API. I'm know I'm not a total idiot b/c i can get this to work adapting the shell script in this Docverter example and running from command line (Mac OSX).
Using PHP's exec():
$url=$_SERVER["DOCUMENT_ROOT"];
$file='/markdown.md';
$output= $url.'/markdown_to_pdf.pdf';
$command="curl --form from=markdown \
--form to=pdf \
--form input_files[]=#".$url.$file." \
http://c.docverter.com/convert > ".$output;
exec("$command");
This gives no error messages but doesn't work. Is there a path issue somewhere?
UPDATE Based on #John's suggestion, here's an example using PHP's curl_exec() adapted from here. Unfortunately this also doesn't work though at least it gives error messages.
$url = 'http://c.docverter.com/convert';
$fields_string ='';
$fields = array('from' => 'markdown',
'to' => 'pdf',
'input_files[]' => $_SERVER['DOCUMENT_ROOT'].'/markdown.md',
);
//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);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);

I solved my own problem. There were two main problems with the above code:
1) The $fields array was incorrectly formatted for the input_files[]. It needed a #/ and mime-type declaration (see code below)
2) The curl_exec() output (the actual newly created file contents) needed to be returned and not just true/false which is this function's default behavior. This is accomplished by setting the curl option curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); (see code below).
Full working example
//set POST variables
$url = 'http://c.docverter.com/convert';
$fields = array('from' => 'markdown',
'to' => 'pdf',
'input_files[]' => "#/".realpath('markdown.md').";type=text/x-markdown; charset=UTF-8"
);
//open connection
$ch = curl_init();
//set options
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //needed so that the $result=curl_exec() output is the file and isn't just true/false
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
//write to file
$fp = fopen('uploads/result.pdf', 'w'); //make sure the directory markdown.md is in and the result.pdf will go to has proper permissions
fwrite($fp, $result);
fclose($fp);

Related

PHP curl not sending post params

I have an online form to submit data as http post.
If no data is send as post , it will return the following error message
We are sorry, the form that you have submitted is invalid or no longer exists.
I am using the following code to send http post data using curl.But I am always getting the error message as output.
How to resolve this issue.Did I miss anything.I printed the curl request, and the post parameters are not sent.How can I fix this?
My code is given below
function curlUsingPost($url, $data)
{
$content_type = 'application/x-www-form-urlencoded';
if(empty($url) OR empty($data))
{
return 'Error: invalid Url or Data';
}
//url-ify the data for the POST
$fields_string = '';
foreach($data as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
$fields_string = http_build_query($data).'\n';
echo $fields_string;
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
// curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: ' . $content_type]);
curl_setopt($ch, CURLOPT_HTTPHEADER,array($content_type));
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt( $curl_handle, CURLOPT_HTTPHEADER, array( 'Expect:' ) );
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10); # timeout after 10 seconds, you can increase it
//curl_setopt($ch,CURLOPT_HEADER,false);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); # Set curl to return the data instead of printing it to the browser.
curl_setopt($ch, CURLOPT_USERAGENT , "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)"); # Some server may refuse your request if you dont pass user agent
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$info = curl_getinfo($ch);
print_r($info );
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
return $result;
}
$url = 'office.promptip.com:8443/his1.max/Services/Webform.aspx?request=submitwebform&token=202D36560E444E466658461615120F75411B09634C696C6F79454E795E7C7A5154505645414F456C584C17101B443D431D0B654D66686D7C454E795E2D7E5152565341404145625E4213141E4273421E5E66486B666F2A464B7A5B79785F54520645444F15635C454516134422421A0D664A3D68687C454E79587F7D5F52575714424043635E1611181D16704D1D0E654F69696F2A474A7A0A78785807525E45414E406350424016134422421A0D374C6F686C7C44482F59787D5E530150104218426D584316181A4177411B0F';
//echo $url;
$data = [
'C0IFirstName' => 'John Doe',
'C1ILastName' => 'Doe John',
'C2IPosition' =>'Father-Guardian',
'U3I80'=>'8129020464',
'U4I150'=>'johndoe#johndoe.com',
'U5I79'=>'This is the message buddy',
'U6I102' => 'Ann',
'U7I105' =>'Doe',
'U8I52' =>'FS1',
'C9IClientId'=> rand ( 0,100000 ),
'U10I21'=>'Website-Enquiry Form'
];
echo curlUsingPost($url,$data);
Solution
Add this to your curl request:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
And replace & with & in URL you're requesting:
$url = 'office.promptip.com:8443/his1.max/Services/Webform.aspx?request=submitwebform&token=202D36560E444E466658461615120F75411B09634C696C6F79454E795E7C7A5154505645414F456C584C17101B443D431D0B654D66686D7C454E795E2D7E5152565341404145625E4213141E4273421E5E66486B666F2A464B7A5B79785F54520645444F15635C454516134422421A0D664A3D68687C454E79587F7D5F52575714424043635E1611181D16704D1D0E654F69696F2A474A7A0A78785807525E45414E406350424016134422421A0D374C6F686C7C44482F59787D5E530150104218426D584316181A4177411B0F';
Explenation
At first, you're requesting wrong URL, which was probably copied from some HTML documentation. Normally a & entity would be replaced by & char by HTML interpreter, but this does not work with curl and you have to replace the entity manually.
Also the server returns
We are sorry, the form that you have submitted is invalid or no
longer exists.
for each end every request in response body. But for successfull request it also provides a Location header. Normally browser would follow this location, make a second request and display success message. You have to tell cURL to do exactly the same with curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true).

Execute and POST data to a PHP script from a PHP script without waiting and no exec

I have 2 scripts called "scriptA.php" and "scriptB.php"
I need to be able to start "scriptB.php" from within "scriptA.php" and make it so the browser isn't waiting for "scriptB.php" to fully complete. I don't want to wait for the script to fully finish, I just want it to finish on its own. I still need to be able to do a POST or to pass data from "scriptA.php" to "scriptB.php" when the script is being executed to be ran.
I can NOT use exec, shell_exec or any variation of command line.
EDIT - Trying cURL option
Here are my 2 scripts...
scriptA.php
$url = 'scriptB.php';
$data = array('foo'=>'bar',
'baz'=>'boom',
'cow'=>'milk',
'php'=>'hypertext processor');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'curl');
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
$result = curl_exec($ch);
curl_close($ch);
scriptB.php
ignore_user_abort(true);
set_time_limit(0);
$fp = fopen("myTexts.txt","wb");
$content = "blah ->" . $_GET['foo'];
fwrite($fp,$content);
fclose($fp);
exit;
scriptB.php isn't being called. I called scriptB.php to test to make sure it works, and when I go to the page directly it does work. it does write to the file correctly. Just when i run scriptA.php it isn't being executed.
You can do it in couple ways:
Use standard PHP fork functions: http://php.net/manual/ru/function.pcntl-fork.php
Use external solution like German or RabbitMQ
Use framework queue mechanizm. For example see it in Laravel: http://laravel.com/docs/4.2/queues
Create cronjob that will run your scriptB after some event in your system (for example you can create special env table that crontab will be process and run scriptB after each insert into this table)
I hope it will help
I got it to work finally using cURL so props to Barmar for pointing me into the right direction.
//set POST variables
$url = 'scriptB.php';
$fields = array(
'foo' => urlencode('bar'),
'fname' => urlencode($first_name),
'title' => urlencode($title),
'company' => urlencode($institution),
'age' => urlencode($age),
'email' => urlencode($email),
'phone' => urlencode($phone)
);
//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_TIMEOUT, 1);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
I found this working example from: http://davidwalsh.name/curl-post
Also on scriptB.php I was doing a "$_GET" instead of a "$_POST"
Thank you everyone for your input!

Sending DELETE to API using PHP

I am brand new to using an API outside of an API wrapper. I can access the API using
curl -u username:password https://company.c
om/api/v1/resources/xxxxxxx
That loads up all the information, but what I need to do is send a DELETE to the url based on an array of filenames; e.g. ['/js/jquery.js']. The name of the parameter is Files.
I already have in code the directory and file name variables.
$storageFilename = $directoryname . "/" . $asset->name;
Above returns the /directoryname/filename from the database.
To send an HTTP(S) DELETE using the cURL library in PHP:
$url = 'https://url_for_your_api';
//this is the data you will send with the DELETE
$fields = array(
'field1' => urlencode('data for field1'),
'field2' => urlencode('data for field2'),
'field3' => urlencode('data for field3')
);
/*ready the data in HTTP request format
*(like the querystring in an HTTP GET, after the '?') */
$fields_string = http_build_query($fields);
//open connection
$ch = curl_init();
/*if you need to do basic authentication use these lines,
*otherwise comment them out (like, if your authenticate to your API
*by sending information in the $fields, above. */
$username = 'your_username';
$password = 'your_password';
curl_setopt($process, CURLOPT_USERPWD, $username . ":" . $password);
/*end authentication*/
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
/*unless you have installed root CAs you can't verify the remote server's
*certificate. Disable checking if this is suitable for your application*/
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//perform the HTTP DELETE
$result = curl_exec($ch);
//close connection
curl_close($ch);
/* this answer builds on David Walsh's very good HTTP POST example at:
* http://davidwalsh.name/curl-post
* modified here to make it work for HTTPS and DELETE and Authentication */

Curl request response not getting

I am sending payment info to Virtual merchant payment gateway for payment system using curl. This is my code :
$Url= "https://www.myvirtualmerchant.com/VirtualMerchant/process.do";
// is cURL installed yet?
if (!function_exists('curl_init')){
die('Sorry cURL is not installed!');
}
// OK cool - then let's create a new cURL resource handle
$ch = curl_init();
// Now set some options (most are optional)
// Set URL to download
curl_setopt($ch, CURLOPT_URL, $Url);
// Include header in result? (0 = yes, 1 = no)
// curl_setopt($ch, CURLOPT_HEADER, 0);
// Should cURL return or print out the data? (true = return, false = print)
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Timeout in seconds
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$fields = array(
'ssl_card_number'=>urlencode($_POST['ssl_card_number']),
'ssl_exp_date'=>urlencode($_POST['ssl_exp_date']),
'ssl_cvv2cvc2'=>urlencode($_POST['ssl_cvv2cvc2']),
'ssl_avs_address'=>urlencode($_POST['ssl_avs_address']),
'ssl_avs_zip'=>urlencode($_POST['ssl_avs_zip']),
'ssl_merchant_id'=>urlencode($_POST['ssl_merchant_id']),
'ssl_user_id'=>urlencode($_POST['ssl_user_id']),
'ssl_pin'=>urlencode($_POST['ssl_pin']),
'ssl_transaction_type'=>urlencode($_POST['ssl_transaction_type']),
'ssl_amount'=>urlencode($_POST['ssl_amount']),
'ssl_show_form'=>urlencode($_POST['ssl_show_form']),
'TransactionType'=>urlencode($_POST['TransactionType'])
);
//url-ify the data for the POST
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
// Download the given URL, and return output
echo $output = curl_exec($ch);
// Close the cURL resource, and free system resources
curl_close($ch);
print_r($output);
But in $output i am getting nothing, not any error or message. Am i doing it wrong ? please tell me ?
First I'd check your mechant_id, pin, etc. Below is working code I created after working through a similar problem.
<html>
<body>
<p>--start--</p>
<?php
//if you have a live account don't use the "demo" post url it won't work
$post_url = 'https://www.myvirtualmerchant.com/VirtualMerchant/process.do';
//replace the xxx's with your proper merchant_id, etc.
//they will give you these when you activate your account
//I've set form to not show, and ssl_result_format =>ascii to get a string returned
$fields = array(
'ssl_merchant_id' =>'xxxxxx',
'ssl_user_id' =>'xxx',
'ssl_pin' =>'xxxxx',
'ssl_show_form' =>'false',
'ssl_result_format' =>'ascii',
'ssl_test_mode' =>'false',
'ssl_transaction_type' =>'ccsale',
'ssl_amount' =>'1.44',
'ssl_card_number' =>'5000300020003003',
'ssl_exp_date' =>'1214',
'ssl_avs_address' =>'Test 3',
'ssl_avs_zip' =>'123456',
'ssl_cvv2cvc2' =>'123',
);
//build the post string
$fields_string = '';
foreach($fields as $key=>$value) { $fields_string .=$key.'='.$value.'&'; }
rtrim($fields_string, "&");
//open curl session
// documentation on curl options at http://www.php.net/curl_setopt
$ch = curl_init();
//begin seting curl options
//set URL
curl_setopt($ch, CURLOPT_URL, $post_url);
//set method
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//set post data string
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
//these two options are frequently necessary to avoid SSL errors with PHP
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$result = curl_exec($ch);
if($result === FALSE) {
//post failed
die(curl_error($ch));
} else {
//got a response
//some people seem to get name/value pairs delimited with "&"
//but currently mine is \n
//support told me there's no way to change it..
$response_array = explode("\n",$result);
//make it nice and useful
foreach( $response_array as $k=>$v ){
$v=explode("=",$v);
$a[$v[0]]=$v[1];
}
//show the whole array
print_r($a);
//use a specific return value
//returns "APPROVAL" if it went through
echo('<h1>'. $a[ssl_result_message] . '</h1>');
}
?>
<p>--end--</p>
</body>
</html>
The code above should net you a screen like this:
--start--
Array ( [ssl_card_number] => 50**********3003 [ssl_exp_date] => 1214 [ssl_amount] => 1.44 [ssl_customer_code] => [ssl_salestax] => [ssl_invoice_number] => [ssl_description] => [ssl_departure_date] => [ssl_completion_date] => [ssl_company] => [ssl_first_name] => [ssl_last_name] => [ssl_avs_address] => Test 3 [ssl_address2] => [ssl_city] => [ssl_state] => [ssl_avs_zip] => 123456 [ssl_country] => [ssl_phone] => [ssl_email] => [ssl_result] => 0 [ssl_result_message] => APPROVAL [ssl_txn_id] => AA49315-1234567-F78F-468F-AF1A-F5C4ADCFFB1E [ssl_approval_code] => N53032 [ssl_cvv2_response] => [ssl_avs_response] => [ssl_account_balance] => 0.00 [ssl_txn_time] => 01/15/2014 11:53:15 AM )
APPROVAL
--end--
Make sure you delete all these test purchases when you finished testing. I'm told they will inhibit your real purchases from posting.
try this to find out the error
var_dump(curl_error($ch));
before and calling curl_exec($ch);
You are calling an HTTPS page. Please refer to following link
http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/
Try to find error give this code before curl close:--
echo "Curl Error :--" . curl_error($ch);
if no error found do like this:-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
then
print_r($result);
exit;
Try this:
$output = curl_exec($ch);
$response = curl_getinfo($ch);
echo "<pre>";
print_r($response);
echo "</pre>";
Hope you get the response :)

Construct a PHP POST request with binary data

I'm trying to construct a PHP POST request that includes some binary data, following on from a previous StackOverflow question. The data is being submitted to this API call: http://www.cyclestreets.net/api/#addphoto
This is my PHP code:
$file = $_FILES['mediaupload'];
$file_field="#$file[tmp_name]";
$fields = array(
'mediaupload'=>$file_field,
'username'=>urlencode($_POST["username"]),
'password'=>urlencode($_POST["password"]),
'latitude'=>urlencode($_POST["latitude"]),
'longitude'=>urlencode($_POST["longitude"]),
'datetime'=>urlencode($_POST["datetime"]),
'category'=>urlencode($_POST["category"]),
'metacategory'=>urlencode($_POST["metacategory"]),
'caption'=>urlencode($_POST["description"])
);
$fields_string = http_build_query($fields);
echo 'FIELDS STRING: ' . $fields_string;
$url = 'https://www.cyclestreets.net/api/addphoto.json?key=$key';
$ch = curl_init();
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, 1);
$response = curl_exec ($ch);
This is what my PHP file outputs:
FIELDS STRING: mediaupload=%40%2Fprivate%2Fvar%2Ftmp%2FphpHjfkRP&username=testing&password=testing&latitude=auto&longitude=auto&datetime=auto&category=cycleparking&metacategory=good&caption=
API RESPONSE: {"request":{"datetime":"1309886656"},"error":{"code":"unknown","message":"The photo was received successfully, but an error occurred while processing it."},"result":{}}
I believe this means that everything else about the request is OK, apart from the format of the binary data. Can anyone tell me what I am doing wrong?
CURL can accept a raw array of key=>value pairs for POST fields. There's no need to do all that urlencode() and http_build_query() stuff. Most likely the # in the array is being mangled into %40, so CURL doesn't see it as a file upload attempt.
$fields = array(
'mediaupload'=>$file_field,
'username'=> $_POST["username"),
etc...
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields);
The http_build_query function generates a URL encoded query string which means that the "#file.ext" is URL encoded in the output as a string and cURL doesn't know that you're trying to upload a file.
My advice would be not to include the file to upload in the http_build_query call and included manually in the CURLOPT_POSTFIELDS.
$file = $_FILES['mediaupload'];
$file_field="#$file[tmp_name]";
$fields = array(
'username'=>urlencode($_POST["username"]),
'password'=>urlencode($_POST["password"]),
'latitude'=>urlencode($_POST["latitude"]),
'longitude'=>urlencode($_POST["longitude"]),
'datetime'=>urlencode($_POST["datetime"]),
'category'=>urlencode($_POST["category"]),
'metacategory'=>urlencode($_POST["metacategory"]),
'caption'=>urlencode($_POST["description"])
);
$fields_string = http_build_query($fields);
echo 'FIELDS STRING: ' . $fields_string;
$url = 'https://www.cyclestreets.net/api/addphoto.json?key=$key';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, 'mediaupload=' . $file_field . '&' . $fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec ($ch);

Categories