Эта тема на forum.dklab.ru


Денис В.: как из ПХП передать данные методом POST другому серверу
суть такая, есть сайт, туда водятся даные, они проверяются, если все окей заносятся в базу и пересылаются другому сайту
через
header("location: http://www.site.com/pay.php?n1=1&n2=2&n3=3");

нужно что бы эти данные отсылались методом post
в книге ПХП 4 эта тема затрагивалась, но я так и не понял и там на СИ, мне нужен готовый код на ПХП

спасибо

http://forum.dklab.ru/viewtopic.php?p=78518#78518
ниже код взятый отсюда. там один параметр передается а мне нужно много (семь)

function post($host,$uri,$post){
$len=strlen($post);

$fp=fsockopen($host,80); if(!$fp) return 0;
fputs($fp,"POST $uri HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/msword, */*
Accept-Encoding: deflate
Accept-Language: ru
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
Host: $host
Referer: http://www.rambler.ru
If-Modified-Since: Sun, 21 Nov 2002 14:58:46 GMT
Content-Length: $len
Connection: keep-alive\n\n$post");



$r="";
while(!feof($fp)) {
$r=$r.fgets($fp,1000);
}
fclose($fp);
return $r;
}

Дмитрий Котеров:
А в чем проблема? В $post запишите что-то типа a=123&b=456&c=789&... - в том же самом формате, короче, что передается в GET.
chin:
Была подобная тема. Даже написана функция для этого.
http://forum.dklab.ru/php/heap/MethodPost.html
edit
Упс, мои извинения, плохо прочитал топик... Ну тогда буду исправляться :) Немного переделал мною приведенную в том топике функцию. Теперь она может передавать и массив (не только строку).
function post($host,$uri,$post)
{
if(is_array($post) && (($count_array = count($post)) > 0))
{
$temporary_string = "";

$counter = 1;

while(list($key,$value) = each($post))
{
$temporary_string .= $key . '=' . $value;

if($counter < $count_array)
{
$temporary_string .= '&';
}

$counter++;
}

$post = $temporary_string;
}

$out = "POST $uri HTTP/1.1\r\n";
$out.= "Host: $host\r\n";
$out.= "Content-type: application/x-www-form-urlencoded\r\n";
$out.= "Referer: http://www.rambler.ru\r\n";
$out.= "Content-Length: ".strlen($post)."\r\n";
$out.= "Connection: close\r\n\r\n$post";

if(($fp = @fsockopen($host,80,$errno,$error,30)) === FALSE) {
$message = "Can`t connect;<br />\nerrno: $errno; error: $error";
die($message);
}

fputs($fp,$out);

$return_string = "";

while(!feof($fp))
{
$return_string .= fgets($fp,128);
}

fclose($fp);

return $return_string;
}

// Использование:
$array = array(
"n1" => 1,
"n2" => 2,
"n3" => 3,
);

post("site.com","/pay.php",$array);
// Функция сама преобразует массив в такую форму: n1=1&n2=2&n3=3
Денис В.:
А в чем проблема? В $post запишите что-то типа a=123&b=456&c=789&... - в том же самом формате, короче, что передается в GET.

и что разве сработает? сейчас попробую, не знал!
Денис В.:
так а я что то не понял вот это что обязательно передовать (попробую разобраться)


if(($fp = @fsockopen($host,80,$errno,$error,30)) === FALSE) {
$message = "Can`t connect;<br />\nerrno: $errno; error: $error";
die($message);
}


то есть в даном участке кода можно проверить соединение, если его нету то можно просто возратить пользователю сообщение что сервер пока не доступен, повробуйте повторить через некоторое время, так? стандартный ход програмы не прерывается?

переменые $errno,$error сами назначаются???? или в них что то свое писать нужно?
30 секунд не много?



fputs($fp,$out);



далее через fputs мы записываем в файл данные в нашем случае в открытое соединение????
то есть все даные которые мы пишем сразу уходят подключенному серверу? правильно?



$return_string = "";

while(!feof($fp))
{
$return_string .= fgets($fp,128);
}



а вот этим участком кода мы что делаем???
то есть мы данные которые записали через fputs($fp,$out); их обратно считываем, так получается??? а зачем???
или этим считвывются заголовки сервера то есть его ответ?

мне нужно другое. пользователь водит даные, cкрипт проверяет их, проеряет соединение если все окей то он перенаправляет пользователя на на другой сайт и одновремено передает ему данные методом post, если же ошибки то он остается на моем сайте. как это сделать в пхп?

header("location: http://www.site.com/pay.php?n1=1&n2=2&n3=3"); это перенаправляет методом get
Денис В.:

$post="n1=1&n2=2&n3=3"; // сами данные

$len=strlen($post); //длина сообщения
$fp=fsockopen($host,80); if(!$fp) return 0; // проверяем связь с сайтом
fclose($fp); // закрываем, так как он больше не нужен


//отправляем даные через header();
header("POST $uri HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/msword, */*
Accept-Encoding: deflate
Accept-Language: ru
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
Host: $host
Referer: http://www.rambler.ru
If-Modified-Since: Sun, 21 Nov 2002 14:58:46 GMT
Content-Length: $len
Connection: keep-alive

$post");//конец отправки
exit;// заканчиваем


правильно?
странник:
сорри за повторение, не увидел этой темы.
заголовки передаются, а вот $_POST пуст, нету данных
странник:
function PostIt($host, $path, $data)
{

$result = '';

$fp = fsockopen($host, 80, $errno, $errstr, 30);

if (!$fp)
die($errstr.'('. $errno .')<br>');


$head = "POST http://$host/$path HTTP/1.1\r\n".
"Referer: http://ya.ru\r\n".
"Host: $host\r\n".
"Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Lenght: ". strlen($data) ."\r\n".
"Connection: Close\r\n\r\n$data";

fputs($fp, $head);

while (!feof($fp)) {

$result .= fgets($fp, 128);

}

fclose($fp);

return $result;
}


PostIt('allcafe','admin/books/2.php',"key1=value");

chin:
Я понял задачу, но к сожалению, она неразрешима с использованием перенаправления. Данные post передаются через соответствующюю функцию, и тот ответ, который выдаст скрипт получив эти данные, будет ею возвращен. Если просто послать данные, а потом перенаправить, данные не засчитаются после перенаправления, так как это новое соединение и там совсем другие данные, а нашими переменными post там и не пахнет. Альтернативный вариант - просто вывести ответ сервера ( переменная $answer - то что вернет функция post() ). Так же, кому не понятен принцып работы, прочитайте комментарии скрипта: на этот раз я о них позаботился.
Я использовал в данном случае перенаправление, но работать так как надо оно не будет. Кому интересно, можете разкомментировать вывод ответа и посмотреть, что будет.
// Данные, которые нам надо послать серверу перед тем, как редиректить
$array = array(
"var1" => "value1",
"var2" => "value2",
"var3" => "value3",
);

// Если не получилось отправить данные, говорим об этом
if(($answer = post("somehost.com","/pay.php",$array)) === FALSE)
{
echo "К сожалению, не удается наладить связь с сервером. Попробуйте еще раз.";
}
else
{
/* Выводим ответ
echo $answer;
exit;
*/

// Если получилось, перенаправляем пользователя
header("Location: http://somehost.com/pay.php");

exit;
}

/*
* Функция post(string host, string uri, mixed post)
* Первый параметр: host (string)
* - имя хоста, на который будет образовываться подключение
* Второй параметр: uri (string)
* - путь (имя скритпа), на который будут отправляться данные
* Третий параметр: post (mixed)
* - данные, которые будем отправлять на сервер
* - может быть как строкой (формата var1=value1&var2=value2..) так и массивом
*/
function post($host,$uri,$post)
{
// Первым делом разбираем переменную данных. Если это строка,
// оставляем все так как есть. Если же это массив, переводим его
// в строку.

if(is_array($post) && (($count_array = count($post)) > 0)) // Если массив и не пустой
{
// Инициализируем временную строку, в которую будет все помещать
// а потом ее присвоим переменной post (в конце)
$temporary_string = "";

// Счетчик элементов массива (для того, чтобы знать в циле,
// на каком по счету элементе мы находимся
$counter = 1;

// Перебираем массив по элементам
while(list($key,$value) = each($post))
{
// Дописываем нашей временной строке текущюю пару
// в формате key=value
$temporary_string .= $key . '=' . $value;

// Если это не последний элемент массива,
// дописываем разделитель переменных '&'
if($counter < $count_array)
{
$temporary_string .= '&';
}

// Прибавляем счетчик
$counter++;
}

// Преобразовываем наш массив в только что
// сгенерированную строку
$post = $temporary_string;

// Удаляем ненужные переменные (не обязательно, зато правильно)
unset($count_array,$temporary_string,$counter,$key,$value);
}

//
// Генерируем запрос для сервера (заголовки и наши данные)
//

$out = "POST $uri HTTP/1.1\r\n";
$out.= "Host: $host\r\n";
$out.= "Content-type: application/x-www-form-urlencoded\r\n";
$out.= "Referer: http://www.rambler.ru\r\n";
$out.= "Content-Length: ".strlen($post)."\r\n";
$out.= "Connection: close\r\n\r\n$post";

// Удаляем ненужную (уже) нам переменную
unset($post);

// Пытаемся наладить соединение с сервером, если не получается,
// возвращаем FALSE;
// fsockopen() :
// 1 - сервер, к которому подключаемся
// 2 - порт, по которому подключаемся
// 3 - номер возвращаемой ошибки (если произошла)
// 4 - в эту переменную поместится сама ошибка (в случае ее позникновения)
// 5 - таймаут соединения (если на протяжении "таймаут" секунд
// не удастся наладить соединение с сервером...)
if(($fp = @fsockopen($host,80,$errno,$error,30)) === FALSE)
{
return FALSE;
}

// Отправляем по налаженому соединению сгенерированный ранее запрос
// Если не получается, возвращаем FALSE
if(!fputs($fp,$out))
{
return FALSE;
}

// Инициализируем строковую переменную для записи в нее
// ответа с сервера
$return_string = "";

// Читаем ответ сервера
while(!feof($fp))
{
// Дописываем в переменную по 128 байт ответа
$return_string .= fgets($fp,128);
}

// Закрываем соединение
fclose($fp);

// Возвращаем ответ
return $return_string;
}
Денис В.:

while(list($key,$value) = each($post))
{
// Дописываем нашей временной строке текущюю пару
// в формате key=value
$temporary_string .= $key . '=' . $value;

// Если это не последний элемент массива,
// дописываем разделитель переменных '&'
if($counter < $count_array)
{
$temporary_string .= '&';
}

// Прибавляем счетчик
$counter++;
}


я конечно не знаю но я обычно масивы перебераю таким способом, это гораздо быстрей и проще


$z=""; $str="";
foreach($array as $k => $v)
{
$str.="$z$k=$v"; $z="&";
}

в первом круге, z пустое, потом к нему подставляется значение
Денис В.:
я так понял решение этого вопроса нету.
а тогда по другому как сделать, то есть мне нужно что бы при нажатии кнопки субмит, чел перебрасывался на сайт партнера, а тот уже запрашивал скипт на моем сайте и выводил ответ у себя

первая часть кода понятна (с доработками)


function PostIt($host, $path, $data)
{

$result = '';

$fp = fsockopen($host, 80, $errno, $errstr, 30);

if (!$fp)
die($errstr.'('. $errno .')<br>');


$head = "POST http://$host/$path HTTP/1.1\r\n".
"Referer: http://ya.ru\r\n".
"Host: $host\r\n".
"Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Lenght: ". strlen($data) ."\r\n".
"Connection: Close\r\n\r\n$data";

fputs($fp, $head);

while (!feof($fp)) {

$result .= fgets($fp, 128);

}

fclose($fp);

return $result;
}


то есть в результе он получит ответ, вопрос!
там будут и заголовки и само тело ответа?
в каком виде мне отсылать ему ответ лучше
я предпологаю так, если мой сайт проверил его даные и возращает ОК значит можно продолжать, а если возращает текст ошибки то этот текст вывадится в браузере с предложением вернутся назад и все исправить.

вопрос в следущем, как парсить ответ сервера, что бы убрать заголовки и получить только само тело ответа?
что бы сайт получил только один ответ без заголовков (т.е. само "тело"), как это сделать

надеюсь вопрос понятен.
спасибо!
странник:
отправляй почту через сокет. наверное с sendmail'ом фигня какая то
Liolik 2006:
А вот у меня проблемка с работой скрипта возникла!
Я посылаю на сервер запрос и пару переменных, где одна из них - текст в формате HTML, который естественно имеет такие символы как &hellip, &mdash.
Ну так в этом случае и получается, что я как бы посылаю несколько переменных.

Может всетаки как то можно разделить переменные каким нибудь другим образом?
Liolik 2006:
Сорри, сам быстренько разобрался, но предлагаю включить это в код на всякий случай.
При обработки переменных, надо еще воспользоваться прекрастной функцией urlencode.

А имеено
$temporary_string .= $key . '=' . $value;
заменить на
$temporary_string .= $key . '=' . urlencode($value);
Дмитрий Котеров:
Я вам больше скажу - даже на

$temporary_string .= urlencode($key) . '=' . urlencode($value);
chin:
Да что вы к этой функции прицепились??? (:
Извините, что без комментариев, ибо влом писать...
Функция возвращает массив из двух значений (заголовок ответа, содержание отвера). Если есть $post данные - генерирует запрос с методом POST, иначе - с GET. Так же, может отправлять Cookie (подаются точно так-же - массивом)
function Request($url,$referer=NULL,$post=NULL,$cookie=NULL)
{
$arrays = array("post"=>"&","cookie"=>"; ");

foreach($arrays as $n => $s) {
if(is_array($$n)) {
$tmp_str = ""; $c = 0; $cnt = count($$n);
foreach($$n as $key => $value) {
$tmp_str .= urlencode($key)."=".urlencode($value).((++$c < $cnt) ? $s : "");
}
$$n = $tmp_str;
}
}

$method = ( $post ? "POST" : "GET" );

if(!$urldata = parse_url($url)) return array(FALSE,FALSE);

$port = ( !empty($urldata['port']) ? $urldata['port'] : 80 );
$path = ( !empty($urldata['path']) ? $urldata['path'] : '/' );
$path .= ( !empty($urldata['query']) ? "?".$urldata['query'] : "" );

$request = "$method $path HTTP/1.1\r\n";
$request .= "Host: ".$urldata['host']."\r\n";
if($method === "POST") {
$request .= "Content-type: application/x-www-form-urlencoded\r\n";
$request .= "Content-Length: ".strlen($post)."\r\n";
}
if($referer) $request .= "Referer: $referer\r\n";
if($cookie) $request .= "Cookie: $cookie\r\n";
$request .= "Connection: close\r\n\r\n";
if($post) $request .= $post;

if(($fp = @fsockopen($urldata['host'],$port,$errno,$error,30)) === FALSE) return array(FALSE,FALSE);
if(!fputs($fp,$request)) return array(FALSE,FALSE);

$ret_str = "";
while(!feof($fp)) $ret_str .= fgets($fp,1024);
fclose($fp);

$ret_str = explode("\r\n\r\n",$ret_str,2);
$content = ( isset($ret_str[1]) ? $ret_str[1] : "" );

return array(isset($ret_str[0])?$ret_str[0]:'',$content);
}
пример использования:
list($header,$content) = Request(
"http://forum.dklab.ru/", // Страница, к которой обращаемся
"http://rambler.ru/" // Referer
);

/* HTTP запрос получается такой:
GET / HTTP/1.1
Host: forum.dklab.ru
Referer: http://rambler.ru/
Connection: close
*/

list($header,$content) = Request(
"http://forum.dklab.ru/", // Страница, к которой обращаемся
NULL, // Мы не хотим подавать referer
array( // POST данные
"a" => "b", // простое значение
"html" => "<html>&amp;</html>", // HTML
)
);

/* HTTP запрос получается такой:
POST / HTTP/1.1
Host: forum.dklab.ru
Content-type: application/x-www-form-urlencoded
Content-Length: 41
Connection: close

a=b&html=%3Chtml%3E%26amp%3B%3C%2Fhtml%3E
*/

list($header,$content) = Request(
"http://forum.dklab.ru/", // Страница, к которой обращаемся
NULL, // Мы не хотим подавать referer
NULL, // Мы не хотим подавать POST данные
array( // Cookie
"session_id" => "bab1b41bafhaa",
"html" => "тест",
)
);

/* HTTP запрос получается такой:
GET / HTTP/1.1
Host: forum.dklab.ru
Cookie: session_id=bab1b41bafhaa; html=%F2%E5%F1%F2
Connection: close
*/

list($header,$content) = Request(
"http://forum.dklab.ru/php/heap/", // Страница, к которой обращаемся
"http://rambler.ru/", // Referer
array( // POST данные
"a" => "b", // простое значение
"html" => "<html>&amp;</html>", // HTML
),
array( // Cookie
"session_id" => "bab1b41bafhaa",
"html" => "тест",
)
);

/* HTTP запрос получается такой:
POST /php/heap/ HTTP/1.1
Host: forum.dklab.ru
Content-type: application/x-www-form-urlencoded
Content-Length: 41
Referer: http://rambler.ru/
Cookie: session_id=bab1b41bafhaa; html=%F2%E5%F1%F2
Connection: close

a=b&html=%3Chtml%3E%26amp%3B%3C%2Fhtml%3E
*/
Ну и так далее...
Если будут какие-то ошибки - говорите. Я ее особо не тестировал, но вроде работает нормально.

Эта тема на forum.dklab.ru