Перенаправлення PHP з даними POST


241

Я зробив кілька досліджень на цю тему, і є деякі експерти, які сказали, що це неможливо , тому я хотів би попросити альтернативне рішення.

Моя ситуація:

Сторінка A: [checkout.php] Клієнт заповнює свої платіжні дані.

Сторінка B: [process.php] Створіть номер рахунка-фактури та збережіть дані клієнта в базі даних.

Сторінка C: [thirdparty.com] Третій шлюз платежів (ТІЛЬКИ ПРИЙМАТИ ПОШТОВІ ДАНІ).

Клієнт заповнює свої реквізити та встановлює свій кошик на сторінці A, потім POST на сторінку B. Всередині process.php, зберігає дані POSTed всередині бази даних та генерує номер рахунка-фактури. Після цього розмістіть дані клієнта та номер рахунку-фактури на платіжний шлюз Thirdparty.com. Проблема полягає у виконанні POST на сторінці B. cURL може розмістити дані на сторінку C, але проблема полягає в тому, що сторінка не перенаправляється на сторінку C. Клієнту потрібно заповнити дані кредитної картки на сторінці C.

Третій шлюз платежних шлюзів дав нам зразок API, зразок - POST номер рахунка-фактури разом із деталями клієнта. Ми не хочемо, щоб система генерувала надлишки небажаних номерів рахунків-фактур.

Чи є для цього рішення? Наше поточне рішення полягає в тому, щоб клієнт заповнив детальну інформацію на сторінці A, тоді на сторінці B ми створимо іншу сторінку, де відображаються всі відомості про клієнта там, де користувач може натиснути кнопку ПІДТВЕРДЖИТИ на POST на сторінку C.

Наша мета полягає в тому, щоб клієнти повинні були натиснути лише один раз.

Сподіваюся, моє питання зрозуміле :)


я не думаю, що це дублікат для цього, це тому, що моя мета знаходиться на сторінці PHP, передайте дані POST і перенаправляйте їх. CURL Я не думаю, що це можливо зробити. Просто шукайте у експерта будь-яку альтернативу
Широ,

ʜᴛᴛᴘ 308 код переадресації?
користувач2284570

Відповіді:


212

Створіть форму на сторінці B із усіма необхідними даними та діями, встановленими на сторінці C, та надішліть її за допомогою JavaScript при завантаженні сторінки. Ваші дані будуть відправлені на сторінку C без особливих клопотів з користувачем.

Це єдиний спосіб зробити це. Переспрямування - це заголовок HTTP 303, який ви можете прочитати на веб-сайті http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html , але я процитую деякі з них:

Відповідь на запит можна знайти під іншим URI, і ДОЛЖЕН бути отриманий за допомогою методу GET на цьому ресурсі. Цей метод існує головним чином, щоб дозволити виводу сценарію, активованого POST, перенаправити агент користувача на обраний ресурс. Новий URI не є заміною посилання на початково запитуваний ресурс. Відповідь 303 НЕ МОЖЕ бути кешована, але відповідь на другий (перенаправлений) запит може бути кешованою.

Єдиний спосіб досягти того, що ви робите, - це проміжна сторінка, яка надсилає користувача на сторінку C. Ось невеликий / простий фрагмент того, як ви можете досягти цього:

<form id="myForm" action="Page_C.php" method="post">
<?php
    foreach ($_POST as $a => $b) {
        echo '<input type="hidden" name="'.htmlentities($a).'" value="'.htmlentities($b).'">';
    }
?>
</form>
<script type="text/javascript">
    document.getElementById('myForm').submit();
</script>

Ви також повинні мати просту форму "підтвердження" всередині тегу noscript, щоб переконатися, що користувачі без Javascript зможуть користуватися вашою послугою.


2
Моя мета полягає у сторінці A -> Сторінка C, Сторінка B - це контролер (бізнес-логіка) генерування номера рахунка-фактури. З перегляду системи - Сторінка A-> Сторінка B-> Сторінка C, але з перегляду користувача повинна бути Сторінка A-> Сторінка B, вони ніколи не повинні звільняти Сторінку B існувати.
Широ

3
@Peeter: розумна пропозиція +1. Єдина проблема в тому , що , коли користувач на кнопку відтіснити Page C повторно передається сторінці C. Крім того , ви забули кодувати $aі $bза допомогою htmlentities/htmlspecialchars, см stackoverflow.com/questions/6180072/php-forward-data-post / ...
Marco DeMaio

8
тут питання, що якщо Javascript відключений на клієнті? Сторінка B не перенаправить на сторінку C, чи не так?
Імран Омар Бухш

24
<noscript><input type="submit" value="Click here if you are not redirected."/></noscript>всередині<form>
обнуленість

3
languageатрибут є застарілим, він повинен бути<script type="text/javascript">...</script>
Alex W

34
/**
 * 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");
    }
}

17
Хоча спочатку це також виглядає краще, ніж прийнята відповідь, зауважу, що він не перенаправляє на доданий - $urlВін просто замінює вміст існуючої сторінки змістом $urlсторінки. Важливо , що PHP-код на $urlсторінці не оцінюється.
iPadDeveloper2011

@ iPadDeveloper2011, у URL-адресі у вас немає коду PHP! PHP-код виконується в СЕРВЕРІ, а не в клієнті.
Едуардо Куомо

1
redirect_post(), що є стороною сервера, PHP-кодом, надсилає запит на СЕРВЕР для $url. Якщо сторінка $url- це .php, я зазначу, що php не оцінюється - html повертається з тегами php, які все ще знаходяться на ній. Чи не вся суть у тому, щоб надсилати дані POST до сценарію на стороні сервера?
iPadDeveloper2011

2
@EduardoCuomo цей метод працює лише з absoulte URL-адресами, через те, як fopen () працює: php.net/manual/en/function.fopen.php Це все ще досить чудова відповідь.
Омн

@Omn ти маєш рацію! "Це не працює з відносною URL-адресою?" не питання, це твердження. Вибачте за плутанину
Едуардо Куомо

25

У мене є ще одне рішення, яке робить це можливим. Він вимагає, щоб клієнт запускав Javascript (що, на мою думку, в наші дні справедлива вимога).

Просто скористайтеся запитом AJAX на сторінці A, щоб перейти та генерувати номер рахунку-фактури та реквізити клієнта у фоновому режимі (попередня сторінка B), після того як запит буде успішно повернуто з правильною інформацією - просто заповніть подання форми на ваш шлюз платежів (Сторінка C).

Це дозволить досягти вашого результату, коли користувач натисне лише одну кнопку і перейде до шлюзу платежів. Нижче - псевдокод

HTML:

<form id="paymentForm" method="post" action="https://example.com">
  <input type="hidden" id="customInvoiceId" .... />
  <input type="hidden" .... />

  <input type="submit" id="submitButton" />
</form>

JS (використовуючи jQuery для зручності, але тривіально для чистого Javascript):

$('#submitButton').click(function(e) {
  e.preventDefault(); //This will prevent form from submitting

  //Do some stuff like build a list of things being purchased and customer details

  $.getJSON('setupOrder.php', {listOfProducts: products, customerDetails: details }, function(data) {
  if (!data.error) {
    $('#paymentForm #customInvoiceID').val(data.id);
    $('#paymentForm').submit();   //Send client to the payment processor
  }
});

1
У цьому рішенні є проблема, якщо хтось вимкне JavaScript на цій сторінці, оновить і надішле, він перейде на сторінку оплати, не зберігаючи нічого. це може бути лазівка.
caoglish

2
Тоді лише встановити дію PaymentForm за допомогою Javascript? Якщо JS відключений, форма не надсилається.
MikeMurko

Користувач, що вимикає JS, не повинен викликати у нас проблеми - причина, з якої ми маємо перейти на сторінку B, ймовірно, щоб генерувати відбитки пальців або додавати код замовлення тощо. Без цього сторінка C третьої сторони повинна вийти з ладу, або в гіршому випадку, коли результат повертається до нас від третьої сторони без коду замовлення, ми не повинні приймати замовлення. Це загалом гарне рішення, якщо JS прийнятний.
Кодер

19

$ _SESSION - ваш друг, якщо ви не хочете возитися з Javascript

Скажімо, ви намагаєтесь надіслати електронний лист:

На сторінці A:

// Start the session
session_start();

// Set session variables
$_SESSION["email"] = "awesome@email.com";

header('Location: page_b.php');

І на сторінці B:

// Start the session
session_start();

// Show me the session!  
echo "<pre>";
print_r($_SESSION);
echo "</pre>";

Щоб знищити сеанс

unset($_SESSION['email']);
session_destroy();

чому ви вважаєте, що це менш безпечно, ніж версія JavaScript?
Адам Бараняй

1
ні, я маю на увазі не порівняно з JavaScript. Взагалі лише $ _SESSION може бути трохи менш безпечним, ніж скажімо файл cookie $ _SESSION +, хоча $ _SESSION досить безпечний сам по собі. Більше інформації тут: stackoverflow.com/questions/17413480/session-spoofing-php
Роберт Сінклер

і як закрити сеанс?
Сейед Мухаммед

Вам потрібно закрити сеанс?
Іван П.

6

Ви можете дозволити PHP зробити POST, але тоді ваш php отримає повернення, з усілякими ускладненнями. Я думаю, що найпростіше було б насправді дозволити користувачеві виконувати пошту.

Отже, з того, що ви запропонували, ви отримаєте справді цю частину:

Інформація про заповнення клієнта на сторінці A, потім на сторінці B ми створюємо іншу сторінку, де відображаються всі деталі клієнта там, натискаємо кнопку ПІДТВЕРДЖИТИ, а потім розмістимо на сторінку C.

Але ви можете насправді зробити подання javascript на сторінці B, тому немає необхідності в натисканні. Зробіть це сторінкою "переадресації" з анімацією завантаження, і ви налаштовані.


Це те, що ми робимо зараз. Я думаю, чи є якась PHP краща логіка для її вирішення. Дякую. ;)
Широ

Так, більше на HTTP, але я працюю в середовищі PHP, тому я думаю, що це тег. Дякую! Полковник Шрапнель.
Широ

6

Я знаю, що це старе питання, але у мене є ще одне альтернативне рішення з jQuery:

var actionForm = $('<form>', {'action': 'nextpage.php', 'method': 'post'}).append($('<input>', {'name': 'action', 'value': 'delete', 'type': 'hidden'}), $('<input>', {'name': 'id', 'value': 'some_id', 'type': 'hidden'}));
actionForm.submit();

Вищевказаний код використовує jQuery для створення тегу форми, додавши приховані поля до поштових полів та нарешті подаючи його. Сторінка буде спрямована на цільову сторінку форми із доданими даними POST.

ps JavaScript та jQuery потрібні для цього випадку. Як запропоновано коментарями інших відповідей, ви можете використовувати <noscript>тег для створення стандартної форми HTML у випадку, якщо JS відключений.


5

Існує простий хак, використовуйте $_SESSIONта створіть arrayопубліковані значення, і як тільки ви перейдете до File_C.phpви можете використовувати його, то обробляйте після цього його знищуйте.


чи можете ви надати невеликий приклад того, що ви маєте на увазі?
caro

3
Я розумію, що Сторінка C - це зовнішнє джерело, яке приймає значення, але не сеанси.
Нараян Бхандарі

3

Мені відомо, що питання phpорієнтоване, але найкращим способом перенаправлення POSTзапиту є, мабуть, використання .htaccess, тобто:

RewriteEngine on
RewriteCond %{REQUEST_URI} string_to_match_in_url
RewriteCond %{REQUEST_METHOD} POST
RewriteRule ^(.*)$ https://domain.tld/$1 [L,R=307]

Пояснення:

За замовчуванням, якщо ви хочете перенаправити запит з даними POST, браузер перенаправляє його через GET з 302 redirect. Це також скасовує всі дані POST, пов'язані із запитом . Веб-переглядач робить це в якості запобіжних заходів для запобігання будь-якого ненавмисного повторного надсилання транзакцій POST.

Але що робити, якщо ви хочете все-таки переспрямувати запит POST з його даними? У HTTP 1.1 існує код статусу для цього. Код стану 307вказує, що запит повинен бути повторений тим самим методом HTTP та даними. Тож ваш запит POST буде повторено разом із його даними, якщо ви використовуєте цей код статусу.

SRC


2

Я зіткнувся з подібними проблемами із запитом POST, де GET Request добре працював на моєму бекенді, який я передаю свої змінні тощо. Проблема полягає в тому, що бекенд робить багато переадресацій, які не працювали з fopen або методами заголовка php.

Таким чином, єдиний спосіб, коли я працював, - це вкласти приховану форму і перетиснути значення при надсиланні POST при завантаженні сторінки.

echo
'<body onload="document.redirectform.submit()">   
    <form method="POST" action="http://someurl/todo.php" name="redirectform" style="display:none">
    <input name="var1" value=' . $var1. '>
    <input name="var2" value=' . $var2. '>
    <input name="var3" value=' . $var3. '>
    </form>
</body>';

1

Ви можете використовувати сеанси для збереження $_POSTданих, а потім отримати ці дані та встановити їх $_POSTу наступному запиті.

Користувач подає запит на /dirty-submission-url.php
Do:

if (session_status()!==PHP_SESSION_ACTIVE)session_start();
     $_SESSION['POST'] = $_POST;
}
header("Location: /clean-url");
exit;

Потім браузер перенаправляє на /clean-submission-urlваш сервер і запитує його. У вас з'явиться деяка внутрішня маршрутизація, щоб зрозуміти, що з цим робити.
На початку запиту ви зробите:

if (session_status()!==PHP_SESSION_ACTIVE)session_start();
if (isset($_SESSION['POST'])){
    $_POST = $_SESSION['POST'];
    unset($_SESSION['POST']);
}

Тепер, через решту вашого запиту, ви можете отримати доступ, $_POSTяк могли за першим запитом.


Ви також можете обробити $_POSTдані в рядок запиту і передати їх на наступну сторінку таким чином. Але тоді дані не можуть бути надто великими. І це, мабуть, не працює, якщо йдеться про завантаження файлів, але я не впевнений.
Рід

0

Спробуйте це:

Надішліть дані та запитайте за допомогою заголовка http на сторінці B для переадресації на шлюз

<?php
$host = "www.example.com";
$path = "/path/to/script.php";
$data = "data1=value1&data2=value2";
$data = urlencode($data);

header("POST $path HTTP/1.1\\r\
" );
header("Host: $host\\r\
" );
header("Content-type: application/x-www-form-urlencoded\\r\
" );
header("Content-length: " . strlen($data) . "\\r\
" );
header("Connection: close\\r\
\\r\
" );
header($data);
?>

Додаткові заголовки:

Accept: \*/\*
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like 
Gecko) Chrome/74.0.3729.169 Safari/537.36

0

Тут є ще один підхід, який працює для мене:

якщо вам потрібно перенаправити на іншу веб-сторінку ( user.php) і включає змінну PHP ( $user[0]):

header('Location:./user.php?u_id='.$user[0]);

або

header("Location:./user.php?u_id=$user[0]");

Ці альтернативи покликані використовувати протокол GET. Він відкриває змінні в браузері клієнта. ОП хотіла такої ж поведінки з POST.
Серхіо А.

-2
function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.



    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}

Приклад:

 post('url', {name: 'Johnny Bravo'});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.