PHP Redirect с данными POST - PullRequest
       26

PHP Redirect с данными POST

213 голосов
/ 07 апреля 2011

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

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

Страница A: [checkout.php] Клиент заполняет свои платежные реквизиты.

Страница B: [process.php] Создайте номер счета и сохраните данные клиента в базе данных.

Страница C: [thirdparty.com] Третий платежный шлюз (ТОЛЬКО ПРИНИМАЕТ ПОЧТОВЫЕ ДАННЫЕ).

Клиент заполняет свои данные и настраивает свою корзину на странице A, затем отправляет на страницу B. Внутри процесса.php, сохраните POST-данные в базе данных и сгенерируйте номер счета.После этого отправьте данные клиента и номер счета на платежный шлюз Thirdparty.com.Проблема заключается в выполнении процедуры POST на странице B. cURL может отправить данные на страницу C, но проблема заключается в том, что страница не перенаправлена ​​на страницу C. Клиент должен заполнить данные кредитной карты на странице C.

Сторонний платежный шлюз предоставил нам пример API, образец POST, номер счета-фактуры и данные клиента.Мы не хотим, чтобы система генерировала избыток нежелательных номеров счетов.

Есть ли какое-то решение для этого?Наше текущее решение заключается в том, чтобы клиент заполнял детали на странице A, а затем на странице B мы создаем еще одну страницу, на которой отображаются все данные клиента, где пользователь может нажать кнопку ПОДТВЕРДИТЬ, чтобы отправить сообщение на страницу C.

Нашцель состоит в том, чтобы клиенты нажимали только один раз.

Надеюсь, мой вопрос ясен:)

Ответы [ 10 ]

189 голосов
/ 07 апреля 2011

Создайте форму на странице 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 могливоспользуйтесь вашим сервисом.

32 голосов
/ 01 марта 2013
/**
 * 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");
    }
}
22 голосов
/ 15 марта 2013

У меня есть другое решение, которое делает это возможным. Требуется, чтобы на клиенте был запущен 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
  }
});
12 голосов
/ 14 февраля 2017

$ _ SESSION - ваш друг, если вы не хотите связываться с Javascript и согласны, что он немного менее защищен.

Допустим, вы пытаетесь передать электронное письмо:

На странице A:

// Start the session
session_start();

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

header('Location: page_b.php');

И на странице B:

<code>// Start the session
session_start();

// Show me the session!  
echo "<pre>";
print_r($_SESSION);
echo "
";
6 голосов
/ 23 марта 2015

Я знаю, что это старый вопрос, но у меня есть еще одно альтернативное решение с 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.

p.s. JavaScript и JQuery необходимы для этого случая. Как следует из комментариев других ответов, вы можете использовать тег <noscript> для создания стандартной формы HTML в случае, если JS отключен.

6 голосов
/ 07 апреля 2011

Вы можете позволить PHP делать POST, но тогда ваш php получит отдачу со всеми видами сложностей.Я думаю, что самым простым было бы на самом деле позволить пользователю сделать POST.

Итак, вроде того, что вы предложили, вы действительно получите эту часть:

Сведения о клиентена странице A, затем на странице B мы создаем еще одну страницу, показываем все детали клиента, нажмите кнопку ПОДТВЕРДИТЬ, затем POST на страницу C.

Но вы можете сделать отправку javascript на странице B,поэтому нет необходимости в клике.Сделайте страницу перенаправления с анимацией загрузки, и все готово.

5 голосов
/ 10 декабря 2015

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

1 голос
/ 25 апреля 2019

Вы можете использовать сеансы для сохранения $_POST данных, затем извлечь эти данные и установить для них значение $_POST для последующего запроса.

Пользователь отправляет запрос на /dirty-submission-url.php
Есть:

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, как и при первом запросе.

0 голосов
/ 18 июня 2019

Попробуйте это:

Отправка данных и запроса с заголовком 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 голосов
/ 23 апреля 2015
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'});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...