Redirecionamento de PHP com dados POST


241

Eu fiz algumas pesquisas sobre esse tópico e alguns especialistas disseram que isso não é possível , então eu gostaria de pedir uma solução alternativa.

Minha situação:

Página A: [checkout.php] O cliente preenche seus detalhes de cobrança.

Página B: [process.php] Gere um número de fatura e armazene detalhes do cliente no banco de dados.

Página C: [thirdparty.com] Terceiro gateway de pagamento (SOMENTE ACEITE DADOS PÓS-POST).

O Cliente preenche seus detalhes e configura seu carrinho na Página A e, em seguida, POSTs na Página B. No process.php, armazene os dados POSTed no banco de dados e gere um número de fatura. Depois disso, envie os dados do cliente e o número da fatura para o gateway de pagamento thirdparty.com. O problema está no POST na página B. O cURL pode POSTAR os dados na página C, mas o problema é que a página não foi redirecionada para a página C. O cliente precisa preencher os detalhes do cartão de crédito na página C.

O gateway de pagamento de terceiros nos deu a amostra da API, a amostra é POST o número da fatura junto com os detalhes do cliente. Não queremos que o sistema gere um excesso de números de faturas indesejados.

Existe alguma solução para isso? Nossa solução atual é que o cliente preencha os detalhes na página A e, na página B, criamos outra página mostrando todos os detalhes do cliente, onde o usuário pode clicar em um botão CONFIRMAR para POSTAR na página C.

Nosso objetivo é que os clientes tenham apenas que clicar uma vez.

Espero que minha pergunta seja clara :)


Eu não acho que seja duplicado para isso, é porque meu objetivo é dentro de uma página PHP, passar os dados do POST e redirecioná-los. cURL Acho que não é possível fazê-lo. Apenas procurar expert qualquer alternativa para ele
Shiro

8 308 código de redirecionamento?
user2284570

Respostas:


212

Gere um formulário na Página B com todos os dados e ações necessários configurados para a Página C e envie-o com JavaScript no carregamento da página. Seus dados serão enviados para a página C sem muito incômodo para o usuário.

Esta é a única maneira de fazê-lo. Um redirecionamento é um cabeçalho HTTP 303 que você pode ler em http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html , mas vou citar alguns deles:

A resposta ao pedido pode ser encontrada em um URI diferente e deve ser recuperada usando um método GET nesse recurso. Esse método existe principalmente para permitir que a saída de um script ativado pelo POST redirecione o agente do usuário para um recurso selecionado. O novo URI não é uma referência substituta para o recurso solicitado originalmente. A resposta 303 NÃO DEVE ser armazenada em cache, mas a resposta à segunda solicitação (redirecionada) pode ser armazenada em cache.

A única maneira de conseguir o que você está fazendo é com uma página intermediária que envia o usuário para a página C. Aqui está um pequeno / simples trecho de como você pode conseguir isso:

<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>

Você também deve ter um formulário "confirmar" simples dentro de uma tag noscript para garantir que usuários sem Javascript possam usar seu serviço.


2
meu objetivo está na página A -> página C, página B é o controlador (lógica comercial) que gera o número da fatura. Na visualização do sistema, está a Página A-> Página B-> Página C, mas, na visualização do usuário, deve ser a Página A-> Página B, eles nunca devem liberar a Página B.
Shiro

3
@ Peter: sugestão inteligente +1. O único problema é que, quando o usuário no botão de retorno da página C é reenviado para a página C. Além disso, você esqueceu de codificar o $ae $busando htmlentities/htmlspecialchars, consulte stackoverflow.com/questions/6180072/php-forward-data-post/…
Marco Demaio

8
pergunta aqui é o que se o Javascript está desativado no cliente? A página B não será redirecionada para a página C, pois não?
Imran Omar Bukhsh

24
<noscript><input type="submit" value="Click here if you are not redirected."/></noscript>dentro do<form>
nullability 27/03

3
o languageatributo foi descontinuado, deveria ser #<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
Embora no início isso pareça melhor do que a resposta aceita, observe que ele não é redirecionado para o fornecido $url- apenas substitui o conteúdo da página existente pelo conteúdo da $urlpágina. Importante , o código php na $urlpágina não é avaliado.
iPadDeveloper2011

@ iPadDeveloper2011, na URL, você não tem um código PHP! O código PHP é executado no SERVER, não no cliente.
Eduardo Cuomo

1
redirect_post(), que é do lado do servidor, código php, envia uma solicitação ao SERVIDOR para a $url. Se $urlfor uma .phppágina, observo que o php não é avaliado - o html é retornado com as tags php ainda nele. O objetivo principal não é enviar dados POST para um script do lado do servidor?
iPadDeveloper2011

2
@EduardoCuomo esse método funciona apenas com URLs ausentes, por causa de como o fopen () funciona: php.net/manual/en/function.fopen.php Ainda é uma resposta bastante bacana.
Omn

@ Oh, você está certo! "Isso não funciona com URL relativo?" não é uma pergunta, é uma afirmação. Desculpe pela confusão
Eduardo Cuomo

25

Eu tenho outra solução que torna isso possível. Requer que o cliente esteja executando Javascript (o que eu acho que é um requisito justo nos dias de hoje).

Basta usar uma solicitação AJAX na página A para gerar o número da fatura e os detalhes do cliente em segundo plano (sua página B anterior) e, depois que a solicitação for retornada com sucesso com as informações corretas - basta preencher o envio do formulário no seu gateway de pagamento (Página C).

Isso alcançará o resultado do usuário clicando apenas em um botão e prosseguindo para o gateway de pagamento. Abaixo está algum pseudocódigo

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 (usando jQuery por conveniência, mas trivial para criar Javascript puro):

$('#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
Esta solução tem um problema: se alguém desativar o JavaScript nesta página, atualizar e enviar, ela será enviada para a página de pagamento sem salvar nada. isso pode ser uma brecha.
caoglish

2
Em seguida, defina apenas a ação paymentForm com Javascript? Se o JS estiver desativado, o formulário não será enviado.
precisa saber é o seguinte

O usuário que desativa o JS não deve nos causar um problema - a razão pela qual temos que ir para a página B é provavelmente gerar uma impressão digital ou adicionar um código de pedido etc. quando o resultado retornar de terceiros sem um código de pedido, não devemos aceitar o pedido. No geral, é uma boa solução se JS for aceitável.
Coder

19

$ _SESSION é seu amigo se você não quiser mexer com Javascript

Digamos que você esteja tentando passar um email:

Na página A:

// Start the session
session_start();

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

header('Location: page_b.php');

E na página B:

// Start the session
session_start();

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

Para destruir a sessão

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

por que você considera isso menos seguro que a versão javascript?
precisa

1
não, quero dizer, não comparado ao javascript. Em geral, apenas $ _SESSION sozinho pode ser um pouco menos seguro do que dizer $ _SESSION + cookie, embora $ _SESSION seja bastante seguro por si só. Mais informações aqui: stackoverflow.com/questions/17413480/session-spoofing-php
Robert Sinclair

e como fechar a sessão?
Sayed Muhammad Idrees

Você precisa fechar a sessão?
Ivan P.

6

Você pode deixar o PHP fazer um POST, mas o seu php receberá o retorno, com todo tipo de complicações. Eu acho que o mais simples seria realmente deixar o usuário fazer o POST.

Então, tipo o que você sugeriu, você terá essa parte:

Detalhes de preenchimento do cliente na página A e, na página B, criamos outra página, mostrando todos os detalhes do cliente, clique no botão CONFIRMAR e, em seguida, POSTAR na página C.

Mas você pode realmente enviar um envio de javascript na página B, para que não seja necessário clicar. Torne uma página de "redirecionamento" com uma animação de carregamento e pronto.


É isso que fazemos agora. Eu estou pensando que existe alguma lógica melhor do PHP para resolvê-lo. Obrigado. ;)
Shiro

sim, mais no HTTP, mas eu trabalho no ambiente PHP, então acho que é a tag. Obrigado! Coronel Shrapnel.
Shiro

6

Sei que essa é uma pergunta antiga, mas tenho outra solução alternativa com o 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();

O código acima usa o jQuery para criar uma tag de formulário, anexando campos ocultos como campos de postagem e enviando-o finalmente. A página será encaminhada para a página de destino do formulário com os dados do POST anexados.

ps JavaScript e jQuery são necessários para este caso. Conforme sugerido pelos comentários das outras respostas, você pode usar a <noscript>tag para criar um formulário HTML padrão, caso JS esteja desativado.


5

Existe um hack simples, use $_SESSIONe crie um arraydos valores postados e, uma vez acessado, File_C.phpvocê poderá usá-lo e processá-lo depois de destruí-lo.


você pode fornecer um pequeno exemplo do que você quer dizer?
caro

3
Meu entendimento é que a página C é uma fonte externa, que aceita valores de postagem, mas não sessões.
Narayan Bhandari

3

Estou ciente de que a pergunta é phporientada, mas a melhor maneira de redirecionar uma POSTsolicitação provavelmente está usando .htaccess, ou seja:

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

Explicação:

Por padrão, se você deseja redirecionar a solicitação com dados POST, o navegador a redireciona via GET with 302 redirect. Isso também descarta todos os dados do POST associados à solicitação . O navegador faz isso como uma precaução para impedir o reenvio não intencional da transação POST.

Mas e se você quiser redirecionar de qualquer maneira a solicitação POST com seus dados? No HTTP 1.1, há um código de status para isso. O código de status 307indica que a solicitação deve ser repetida com o mesmo método HTTP e dados. Portanto, sua solicitação POST será repetida junto com os dados, se você usar esse código de status.

SRC


2

Eu enfrentei problemas semelhantes com a solicitação POST, na qual a solicitação GET estava funcionando bem no meu back-end, que estou passando minhas variáveis ​​etc. O problema reside no fato de que o back-end faz muitos redirecionamentos, que não funcionavam com os métodos fopen ou php header.

Portanto, a única maneira de fazê-lo funcionar era colocar um formulário oculto e enviar os valores com um envio POST quando a página é carregada.

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

Você pode usar sessões para salvar $_POSTdados, recuperá-los e configurá-los $_POSTna solicitação subsequente.

Submete usuário solicitar a /dirty-submission-url.php
Do:

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

Em seguida, o navegador redireciona e solicita /clean-submission-urldo seu servidor. Você terá algum roteamento interno para descobrir o que fazer com isso.
No início da solicitação, você fará:

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

Agora, através do restante da sua solicitação, você pode acessar $_POSTcomo pôde na primeira solicitação.


Como alternativa, você pode processar os $_POSTdados em uma string de consulta e passá-los para a página subsequente dessa maneira. Mas então os dados não podem ser terrivelmente grandes. E isso provavelmente não funciona se o upload de arquivos estiver envolvido, mas não tenho certeza.
Reed

0

Tente o seguinte:

Envie dados e solicite com cabeçalho http na página B para redirecionar para o Gateway

<?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);
?>

Cabeçalhos adicionais:

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

-1

Aqui há outra abordagem que funciona para mim:

se você precisar redirecionar para outra página da web ( user.php) e incluir uma variável PHP ( $user[0]):

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

ou

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

Essas alternativas devem usar o protocolo GET. Expõe variáveis ​​no navegador do cliente. O OP queria o mesmo comportamento com o POST.
Sergio A.

-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();
}

Exemplo:

 post('url', {name: 'Johnny Bravo'});
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.