I have an online gateway which requires an HTML form to be submitted with hidden fields. I need to do this via a PHP script without any HTML forms (I have the data for the hidden fields in a DB)
To do this sending data via GET:
header('Location: http://www.provider.com/process.jsp?id=12345&name=John');
And to do this sending data via POST?
You can't do this using PHP.
As others have said, you could use cURL - but then the PHP code becomes the client rather than the browser.
If you must use POST, then the only way to do it would be to generate the populated form using PHP and use the window.onload hook to call javascript to submit the form.
here is the workaround sample.
function redirect_post($url, array $data)
{
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function closethisasap() {
document.forms["redirectpost"].submit();
}
</script>
</head>
<body onload="closethisasap();">
<form name="redirectpost" method="post" action="<? echo $url; ?>">
<?php
if ( !is_null($data) ) {
foreach ($data as $k => $v) {
echo '<input type="hidden" name="' . $k . '" value="' . $v . '"> ';
}
}
?>
</form>
</body>
</html>
<?php
exit;
}
A better and neater solution would be to use $_SESSION:
Using the session:
$_SESSION['POST'] = $_POST;
and for the redirect header request use:
header('Location: http://www.provider.com/process.jsp?id=12345&name=John', true, 307;)
307 is the http_response_code you can use for the redirection request with submitted POST values.
Another solution if you would like to avoid a curl call and have the browser redirect like normal and mimic a POST call:
save the post and do a temporary redirect:
function post_redirect($url) {
$_SESSION['post_data'] = $_POST;
header('Location: ' . $url);
}
Then always check for the session variable post_data:
if (isset($_SESSION['post_data'])) {
$_POST = $_SESSION['post_data'];
$_SERVER['REQUEST_METHOD'] = 'POST';
unset($_SESSION['post_data']);
}
There will be some missing components such as the apache_request_headers() will not show a POST Content header, etc..
It would involve the cURL PHP extension.
$ch = curl_init('http://www.provider.com/process.jsp');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "id=12345&name=John");
curl_setopt($ch, CURLOPT_RETURNTRANSFER , 1); // RETURN THE CONTENTS OF THE CALL
$resp = curl_exec($ch);
/**
* Redirect with POST data.
*
* #param string $url URL.
* #param array $post_data POST data. Example: array('foo' => 'var', 'id' => 123)
* #param array $headers Optional. Extra headers to send.
*/
public function redirect_post($url, array $data, array $headers = null) {
$params = array(
'http' => array(
'method' => 'POST',
'content' => http_build_query($data)
)
);
if (!is_null($headers)) {
$params['http']['header'] = '';
foreach ($headers as $k => $v) {
$params['http']['header'] .= "$k: $v\n";
}
}
$ctx = stream_context_create($params);
$fp = #fopen($url, 'rb', false, $ctx);
if ($fp) {
echo #stream_get_contents($fp);
die();
} else {
// Error
throw new Exception("Error loading '$url', $php_errormsg");
}
}
Use curl for this. Google for "curl php post" and you'll find this: http://www.askapache.com/htaccess/sending-post-form-data-with-php-curl.html.
Note that you could also use an array for the CURLOPT_POSTFIELDS option. From php.net docs:
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.
Your going to need CURL for that task I'm afraid. Nice easy way to do it here: http://davidwalsh.name/execute-http-post-php-curl
Hope that helps
Alternatively, setting a session variable before the redirect and test it in the destination url, can solve this problem for me.
You have to open a socket to the site with fsockopen and simulate a HTTP-Post-Request.
Google will show you many snippets how to simulate the request.
I used the following code to capture POST data that was submitted from form.php and then concatenate it onto a URL to send it BACK to the form for validation corrections. Works like a charm, and in effect converts POST data into GET data.
foreach($_POST as $key => $value) {
$urlArray[] = $key."=".$value;
}
$urlString = implode("&", $urlArray);
echo "Please <a href='form.php?".$urlString."'>go back</a>";
An old post but here is how I handled it. Using newms87's method:
if($action == "redemption")
{
if($redemptionId != "")
{
$results = json_decode($rewards->redeemPoints($redemptionId));
if($results->success == true)
{
$redirectLocation = $GLOBALS['BASE_URL'] . 'rewards.phtml?a=redemptionComplete';
// put results in session and redirect back to same page passing an action paraameter
$_SESSION['post_data'] = json_encode($results);
header("Location:" . $redirectLocation);
exit();
}
}
}
elseif($action == "redemptionComplete")
{
// if data is in session pull it and unset it.
if(isset($_SESSION['post_data']))
{
$results = json_decode($_SESSION['post_data']);
unset($_SESSION['post_data']);
}
// if you got here, you completed the redemption and reloaded the confirmation page. So redirect back to rewards.phtml page.
else
{
$redirectLocation = $GLOBALS['BASE_URL'] . 'rewards.phtml';
header("Location:" . $redirectLocation);
}
}
Yes, you can do this in PHP e.g. in
Silex or Symfony3
using subrequest
$postParams = array(
'email' => $request->get('email'),
'agree_terms' => $request->get('agree_terms'),
);
$subRequest = Request::create('/register', 'POST', $postParams);
return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
A workaround wich works perfectly :
In the source page,, start opening a session and assign as many values as you might want.
Then do the relocation with "header" :
<!DOCTYPE html>
<html>
<head>
<?php
session_start();
$_SESSION['val1'] = val1;
...
$_SESSION['valn'] = valn;
header('Location: http//Page-to-redirect-to');
?>
</head>
</html>
And then, in the targe page :
<!DOCTYPE html>
<?php
session_start();
?>
<html>
...
<body>
<?php
if (isset($_SESSION['val1']) && ... && isset($_SESSION['valn'])) {
YOUR CODE HERE based on $_SESSION['val1']...$_SESSION['valn'] values
}
?>
</body>
</html>
No need of Javascript nor JQuery..
Good luck !
Related
Context
I have the following POST pipeline:
index.php -> submit.php ->list/item/new/index.php
index.php has a normal form with an action="submit.php" property.
submit.php decides where to send the following post request by some logic based on the POST variable content.
The problem is that I haven't found a successful way to debug this pipeline. Somewhere, something is failing and I would appreciate a fresh pair of eyes.
What I have tried
I have tried running list/item/new/index.php with dummy parameters through a regular GET request. DB updates successfully.
I have tried running submit.php (below) with dummy parameters through a regular GET request. The value of $result is not FALSE, indicating the file_get_contents request was successful, but it's value is the literal content of list/new/index.php instead of the generated content, which I expect to be the result of
echo $db->new($hash,$content) && $db->update_content_key($hash);
Here is submit.php
$url = 'list/new/index.php';
if($test){
$content = $_GET["i"];
$hash = $_GET["h"];
}else{
$content = $_POST["item"]["content"];
$hash = $_POST["list"]["hash"];
}
$data = array(
'item'=>array('content' => $content),
'list'=>array('hash' => $hash)
);
$post_content = http_build_query($data);
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n".
"Content-Length: " . strlen($post_content) . "\r\n",
'method' => 'POST',
'content' => $post_content
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) {
echo "error";
//commenting out for testing. should go back to index.php when it's done
//header('Location: '.$root_folder_path.'list/?h='.$hash.'&f='.$result);
}
else{
var_dump($result);
//commenting out for testing. should go back to index.php when it's done
//header('Location: '.$root_folder_path.'list/?h='.$hash.'&f='.str_replace($root_folder_path,"\n",""));
}
And here is list/item/new/index.php
$db = new sql($root_folder_path."connection_details.php");
if($test){
$content = $_GET["i"];
$hash = $_GET["h"];
}else{
$content = $_POST["item"]["content"];
$hash = $_POST["list"]["hash"];
}
// insert into DB, use preformatted queries to prevent sqlinjection
echo $db->new($hash,$content) && $db->update_content_key($hash);
The worst thing about this is that I don't know enough of PHP to effectively debug this (I actually had it working at some point today but I did not commit right then...).
All comments and suggestions are welcome. I appreciate your time.
Got it.
I'm not sure what to call the error I was making (or what is actually going on behind the scenes) but it was the following:
on the POST request I was using
$url='list/item/new/index.php'
I used the whole url scheme:
$url = 'https://example.com/list/item/new/index.php';`
Here's my problem. A few months ago, I wrote a PHP script to get connected to my account on a website. I was using CURL to get connected and everything was fine. Then, they updated the website and now I am no longer able to get connected. The problem is not with CURL, as I do not get any error from CURL, but it is the website itself which tells me that I am not able.
Here's my script :
<?php
require('simple_html_dom.php');
//Getting the website main page
$url = "http://www.kijiji.ca/h-ville-de-quebec/1700124";
$main = file_get_html($url);
$links = $main -> find('a');
//Finding the login page
foreach($links as $link){
if($link -> innertext == "Ouvrir une session"){
$page = $link;
}
}
$to_go = "http://www.kijiji.ca/".$page->href;
//Getting the login page
$main = file_get_html($to_go);
$form = $main -> find("form");
//Parsing the page for the login form
foreach($form as $f){
if($f -> id == "login-form"){
$cform = $f;
}
}
$form = str_get_html($cform);
//Getting my post data ready
$postdata = "";
$tot = count($form->find("input"));
$count = 0;
/*I've got here a foreach loop to find all the inputs in the form. As there are hidden input for security, I make my script look for all the input and get the value of each, and then add them in my post data. When the name of the input is emailOrNickname or password, I enter my own info there, then it gets added to the post data*/
foreach($form -> find("input") as $input){
$count++;
$postdata .= $input -> name;
$postdata .= "=";
if($input->name == "emailOrNickname"){
$postdata.= "my email address ";
}else if($input->name == "password"){
$postdata.= "my password";
}else{
$postdata .= $input -> value;
}
if($count<$tot){
$postdata .= "&";
}
}
//Getting my curl session
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $to_go,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postdata,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_COOKIESESSION => true,
CURLOPT_COOKIEJAR => 'cookie.txt'
));
$result = curl_exec ($ch);
curl_close ($ch);
echo $result;
?>
CURL nor PHP return any error. In fact, it returns the webpage of the website, but this webpage tells me that there's an error that occurred, as if there was missing some post data.
What do you think can cause that ? Could it be some missing curl_setopts ? I've got no idea, do you have any ?
$form = $main -> find("form") finds first occurrence of element
and that is <form id="SearchForm" action="/b-search.html">
you will need to change that into $form = $main->find('#login-form')
Most likely the problem is that the site (server) checks cookies. This process mainly consists of two phases:
1) When you visit the site first time on some page, e.g. on the login page, the server sets cookies with some data.
2) On each subsequent page visit or POST request the server checks cookies it has set.
So you have to reproduce this process in your script which mean you have to use CURL to get any page from the site, including the login page which should be getting by CURL, not file_get_html.
Furthemore you have to set both CURLOPT_COOKIEJAR and CURLOPT_COOKIEFILE options to the same absolute path value ('cookies.txt' is a relative path) on each request. This is necessary in order to enable cookies auto-handling (session maintaining) within entire series of requests (including redirects) the script will perform.
I know this is bad form, but we can't change the hidden input name as it is set by SalesForce. I have a form with an input like this:
<input type="hidden" name="00N5000000XXXXX" value="Demo_Account" />
and my PHP to post to them via cURL
$00N5000000XXXXX = $_POST['00N5000000XXXXX'];
which obviously won't work as it has number for a variable name.
When I change the name to:
$Foo = $_POST['00N5000000XXXXX'];
the back end doesn't work because it is expecting the form to submit a value with a name of 00N5000000XXXXX, not Foo or whatever I want to call it.
Obviously, Im not a PHP developer but need some advice on how to get around this.
Thank you.
You don't have to save it to a variable first:
<?php
$transferPostFields = array(
'00N5000000XXXXX'
);
$postFields = array();
foreach ($_POST as $key => $value) {
if (in_array($key, $transferPostFields)) {
$postFields[$key] = $value;
}
}
$curlHandle = curl_init();
curl_setopt_array($curlHandle, array(
CURLOPT_URL => 'http://api.salesforce.com/whatever/urls/they/use',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($postFields)
));
$output = curl_exec($curlHandle);
echo 'The output we received from SalesForce was: ' . $output;
?>
If you want to transfer all post fields, simply change the top part (anything above $curlHandle = curl_init() to:
$postFields = $_POST;
If you don't need to go past your own server first, then simply change your form:
<form method="post" action="http://api.salesforce.com/whatever/urls/they/use">
I'm testing something. I would like to redirect my website (http://mywebsite.com) to a Landing Page (http://landingpage.com) ONLY when I pass a GET value. For example: id=23. So when it exists the page redirects.
My questions is that is there any script with the I can capture the list where I got redirected? I want the full link, like: http://mywebsite.com/index.php?id=23
Is there any possibility to capture that?
Also is there any possiblity to do the same with POST and capture that POST value on the Landing Page?
FOR GET:
You can simply attach $_SERVER['QUERY_STRING'] to the landingpage:
<?php
$get = ($_SERVER['QUERY_STRING']) ? "?".$_SERVER['QUERY_STRING']: "";
$url = 'http://landingpage.com'.$get;
header("Location: $url");
?>
FOR POST: use CURL
if($_POST){
$ch = curl_init();
$curlConfig = array(
CURLOPT_URL => "http://landingpage.com",
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $_POST,
);
curl_setopt_array($ch, $curlConfig)
$result = curl_exec($ch);
curl_close($ch);
}
Why not just store the data in a session variable? All you have to do is start the session again on the redirected page, and retrieve the session variables there.
Tutorial if you're not already aware of it: http://www.tizag.com/phpT/phpsessions.php
For example, on mywebsite.com:
session_start();
if (isset($_REQUEST['id'])) {
$_SESSION['id'] = $_REQUEST['id'];
$_SESSION['url'] = "http://" . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
}
on landingpage.com:
session_start();
$url = $_SESSION['url'] . '?id=' . $_SESSION['id'];
echo $url;
Although pretty sure this won't work if the pages are stored on two different servers, so I may be misunderstanding the question. If it's between servers, you could use a cookie instead.
I'm trying to setup gitkit in my website, but can't get past this one single line of code. No matter what I do, file_get_contents keeps returning empty.
I've already set my php.ini : always_populate_raw_post_data = On
My environment is PHP 5.3.3, Apache 2.2.6, localhost.
Here's some code.
In my index.php, I call the google API and try to login with gmail account, in other words, federated login.
(this is from the Google API Console)
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/googleapis/0.0.4/googleapis.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/jsapi"></script>
<script type="text/javascript">
google.load("identitytoolkit", "1", {packages: ["ac"], language:"en"});
</script>
<script type="text/javascript">
$(function() {
window.google.identitytoolkit.setConfig({
developerKey: "HERE_GOES_MY_DEVELOPER_KEY",
companyName: "Valentinos Pizzaria",
callbackUrl: "http://localhost/valentinos/callback.php",
realm: "",
userStatusUrl: "http://localhost/valentinos/userstatus.php",
loginUrl: "http://localhost/valentinos/login.php",
signupUrl: "http://localhost/valentinos/register.php",
homeUrl: "http://localhost/valentinos/index.php",
logoutUrl: "http://localhost/valentinos/logout.php",
idps: ["Gmail", "Yahoo"],
tryFederatedFirst: true,
useCachedUserStatus: false,
useContextParam: true
});
$("#navbar").accountChooser();
});
</script>
I get the IDP response, log in, and am asked for permissions. Upon returning to my callback page, in which I used the code sample provided by Google (which is below), this one line of code doesn't seem to be returning correctly.
Am I doing anything stupid at all?
Any help will be appreciated.
Here's whole callback.php so far (there's no HTML whatsoever, for now):
session_start();
$url = EasyRpService::getCurrentUrl();
#$postData = #file_get_contents('php://input');
$postData = file_get_contents('php://input');
$result = EasyRpService::verify($url, $postData);
// Turn on for debugging.
// var_dump($result);
class EasyRpService {
// Replace $YOUR_DEVELOPER_KEY
private static $SERVER_URL = 'https://www.googleapis.com/rpc?key=HERE_GOES_MY_DEVELOPER_KEY';
public static function getCurrentUrl() {
$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
$url .= $_SERVER['SERVER_NAME'];
if ($_SERVER['SERVER_PORT'] != '80') {
$url .= ':'. $_SERVER['SERVER_PORT'];
}
$url .= $_SERVER['REQUEST_URI'];
return $url;
}
private static function post($postData) {
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => EasyRpService::$SERVER_URL,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER => array('Content-Type: application/json'),
CURLOPT_POSTFIELDS => json_encode($postData)));
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code == '200' && !empty($response)) {
return json_decode($response, true);
}
return NULL;
}
public static function verify($continueUri, $response) {
$request = array();
$request['method'] = 'identitytoolkit.relyingparty.verifyAssertion';
$request['apiVersion'] = 'v1';
$request['params'] = array();
$request['params']['requestUri'] = $continueUri;
$request['params']['postBody'] = $response;
$result = EasyRpService::post($request);
if (!empty($result['result'])) {
return $result['result'];
}
return NULL;
}
} # End Class EasyRpService
Before anyone asks, I do replace HERE_GOES_MY_DEVELOPER_KEY with my Developer Key...
Once again, any help will be much appreciated.
C ya.
Did you try using $_POST ? php://input don't work for enctype="multipart/form-data". May be you are getting response as multipart/form-data in this case $_POST[0] should work.
HTTP POST data is usually populated in $_POST, php://input will usually contain PUT data.