Redireccionamiento PHP con datos POST

241

Investigué un poco sobre este tema, y ​​hay algunos expertos que han dicho que no es posible , por lo que me gustaría pedir una solución alternativa.

Mi situación:

Página A: [checkout.php] El cliente completa sus detalles de facturación.

Página B: [process.php] Genere un número de factura y almacene los detalles del cliente en la base de datos.

Página C: [thirdparty.com] Tercera pasarela de pago (SOLO ACEPTA DATOS POSTALES).

El cliente completa sus datos y configura su carrito en la página A, luego envía las POST a la página B. Dentro de process.php, almacena los datos publicados en la base de datos y genera un número de factura. Después de eso, PUBLICA los datos del cliente y el número de factura en la pasarela de pago de thirdparty.com. El problema es hacer POST en la página B. cURL puede PUBLICAR los datos en la página C, pero el problema es que la página no redirigió a la página C. El cliente debe completar los detalles de la tarjeta de crédito en la página C.

La pasarela de pago de terceros nos dio la muestra de API, la muestra es PUBLICAR el número de factura junto con los detalles del cliente. No queremos que el sistema genere un exceso de números de factura no deseados.

¿Hay alguna solución para esto? Nuestra solución actual es que el cliente complete los detalles en la página A, luego en la página B creamos otra página que muestra todos los detalles del cliente allí, donde el usuario puede hacer clic en un botón CONFIRMAR para PUBLICAR en la página C.

Nuestro objetivo es que los clientes solo tengan que hacer clic una vez.

Espero que mi pregunta sea clara :)

Shiro
fuente
No creo que sea duplicado para esto, es porque mi objetivo es dentro de una página PHP, pasar los datos POST y redirigirlos. CURL No creo que sea posible hacerlo. Solo busque un experto, cualquier alternativa para ello
Shiro
code Código de redireccionamiento 308?
usuario2284570

Respuestas:

212

Genere un formulario en la página B con todos los datos y acciones requeridos establecidos en la página C y envíelo con JavaScript al cargar la página. Sus datos serán enviados a la página C sin mucha molestia para el usuario.

Esta es la única forma de hacerlo. Una redirección es un encabezado HTTP 303 que puede leer en http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html , pero citaré algunos de ellos:

La respuesta a la solicitud se puede encontrar en un URI diferente y DEBE recuperarse utilizando un método GET en ese recurso. Este método existe principalmente para permitir que la salida de un script activado por POST redirija al agente de usuario a un recurso seleccionado. El nuevo URI no es una referencia sustitutiva del recurso solicitado originalmente. La respuesta 303 NO DEBE almacenarse en caché, pero la respuesta a la segunda solicitud (redirigida) puede ser almacenable en caché.

La única forma de lograr lo que está haciendo es con una página intermedia que envía al usuario a la página C. Aquí hay un fragmento pequeño / simple sobre cómo puede lograrlo:

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

También debe tener un simple formulario de "confirmación" dentro de una etiqueta noscript para asegurarse de que los usuarios sin Javascript puedan usar su servicio.

Peeter
fuente
2
mi objetivo está en la página A -> página C, la página B es el controlador (lógica de negocios) genera el número de factura. Desde la vista del sistema es Página A-> Página B-> Página C, pero desde la vista del usuario debe ser Página A-> Página B, nunca deben liberar Página B existe.
Shiro
3
@Peeter: sugerencia inteligente +1. El único problema es que cuando el usuario en el botón de retroceso de la página C se vuelve a enviar a la página C. Además, olvidó codificar $ay, $bal usar htmlentities/htmlspecialchars, consulte stackoverflow.com/questions/6180072/php-forward-data-post/…
Marco Demaio
8
La pregunta aquí es ¿qué pasa si Javascript está deshabilitado en el cliente? La página B no redirigirá a la página C, ¿verdad?
Imran Omar Bukhsh
24
<noscript><input type="submit" value="Click here if you are not redirected."/></noscript>dentro de<form>
nulabilidad
3
el languageatributo está en desuso, debería serlo<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");
    }
}
Eduardo Cuomo
fuente
17
Si bien al principio esto también se ve mejor que la respuesta aceptada, noto que no se redirige a lo suministrado, $urlsolo reemplaza el contenido de la página existente con el contenido de la $urlpágina. Es importante destacar que el código php en la $urlpágina no se evalúa.
iPadDeveloper2011
@ iPadDeveloper2011, en la URL, ¡no tienes un código PHP! El código PHP se ejecuta en el SERVIDOR, no en el cliente.
Eduardo Cuomo
1
redirect_post(), que es del lado del servidor, código php, envía una solicitud al SERVIDOR para a $url. Si $urles una .phppágina, noto que no se evalúa el php: html se devuelve con las etiquetas php todavía en él. ¿No tiene sentido enviar datos POST a un script del lado del servidor?
iPadDeveloper2011
2
@EduardoCuomo, este método solo funciona con URL absolutas, debido a cómo funciona fopen (): php.net/manual/en/function.fopen.php Sigue siendo una respuesta bastante ingeniosa.
Omn
@ ¡Oh, tienes razón! "¿Esto no funciona con la URL relativa?" No es una pregunta, es una declaración. Perdón por la confusión
Eduardo Cuomo
25

Tengo otra solución que hace esto posible. Requiere que el cliente ejecute Javascript (lo que creo que es un requisito justo en estos días).

Simplemente use una solicitud AJAX en la página A para ir y generar su número de factura y los detalles del cliente en segundo plano (su página B anterior), luego, una vez que la solicitud se devuelva con éxito con la información correcta, simplemente complete el envío del formulario a su pasarela de pago (Página C).

Esto logrará el resultado de que el usuario solo haga clic en un botón y se dirija a la pasarela de pago. A continuación hay un 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 conveniencia pero trivial para hacer 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
  }
});
MikeMurko
fuente
1
Esta solución tiene un problema, si alguien apaga el JavaScript en esta página, lo actualiza y lo envía, pasará a la página de pago sin guardar nada. Esto podría ser una escapatoria.
caoglish
2
Entonces, ¿solo establece la acción de PaymentForm con Javascript? Si JS está deshabilitado, el formulario no se enviará.
MikeMurko
El usuario que apaga JS no debería causarnos un problema: la razón por la que tenemos que ir a la página B es probablemente para generar una huella digital o agregar un código de pedido, etc. Sin esto, la página de terceros C debería fallar, o en el peor de los casos, Cuando el tercero nos devuelve el resultado sin un código de pedido, no debemos aceptar el pedido. En general, esta es una buena solución si JS es aceptable.
Codificador
19

$ _SESSION es tu amigo si no quieres meterte con Javascript

Digamos que estás intentando pasar un correo electrónico:

En la página A:

// Start the session
session_start();

// Set session variables
$_SESSION["email"] = "[email protected]";

header('Location: page_b.php');

Y en la página B:

// Start the session
session_start();

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

Para destruir la sesión

unset($_SESSION['email']);
session_destroy();
Robert Sinclair
fuente
¿Por qué considera que esto es menos seguro que la versión de JavaScript?
Adam Baranyai
1
no, quiero decir no comparado con javascript. Solo en general, $ _SESSION solo puede ser un poco menos seguro que decir $ _SESSION + cookie, aunque $ _SESSION es bastante seguro por sí mismo. Más información aquí: stackoverflow.com/questions/17413480/session-spoofing-php
Robert Sinclair
y como cerrar sesión?
Sayed Muhammad Idrees
¿Necesitas cerrar sesión?
Ivan P.
6

Puede dejar que PHP haga una POST, pero luego su php obtendrá el retorno, con todo tipo de complicaciones. Creo que lo más simple sería dejar que el usuario haga la POST.

Entonces, más o menos de lo que sugirió, obtendrá esta parte:

Detalles del cliente en la página A, luego en la página B creamos otra página que muestra todos los detalles del cliente allí, haga clic en el botón CONFIRMAR y luego PUBLICAR en la página C.

Pero en realidad puede hacer un envío de JavaScript en la página B, por lo que no es necesario hacer clic. Conviértalo en una página de "redireccionamiento" con una animación de carga y listo.

Nanne
fuente
Esto es lo que hacemos ahora. Estoy pensando si hay alguna lógica PHP mejor para resolverlo. Gracias. ;)
Shiro
Sí, más hacia HTTP, pero yo trabajo en un entorno PHP, así que creo que es la etiqueta. ¡Gracias! Col. Metralla.
Shiro
6

Sé que esta es una vieja pregunta, pero tengo otra solución alternativa con 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();

El código anterior usa jQuery para crear una etiqueta de formulario, agregando campos ocultos como campos de publicación y, por último, enviarlo. La página reenviará a la página de destino del formulario con los datos POST adjuntos.

ps JavaScript y jQuery son necesarios para este caso. Como lo sugieren los comentarios de las otras respuestas, puede utilizar la <noscript>etiqueta para crear un formulario HTML estándar en caso de que JS esté deshabilitado.

Rapaz
fuente
5

Hay un truco simple, usa $_SESSIONy crea uno arrayde los valores publicados, y una vez que vas a File_C.phpusarlo, puedes usarlo y luego procesarlo después de destruirlo.

Jeffery ThaGintoki
fuente
¿Puedes dar un pequeño ejemplo de lo que quieres decir?
caro
3
Según tengo entendido, la página C es una fuente externa, que toma valores de publicación pero no sesiones.
Narayan Bhandari
3

Soy consciente de que la pregunta está phporientada, pero la mejor manera de redirigir una POSTsolicitud es probablemente usando .htaccess, es decir:

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

Explicación:

De forma predeterminada, si desea redirigir la solicitud con datos POST, el navegador la redirige a través de GET con 302 redirect. Esto también elimina todos los datos POST asociados con la solicitud . El navegador hace esto como precaución para evitar cualquier reenvío involuntario de la transacción POST.

Pero, ¿qué pasa si desea redirigir la solicitud POST de todos modos con sus datos? En HTTP 1.1, hay un código de estado para esto. El código de estado 307indica que la solicitud debe repetirse con el mismo método y datos HTTP. Por lo tanto, su solicitud POST se repetirá junto con sus datos si utiliza este código de estado.

SRC

CONvid19
fuente
2

Me enfrenté a problemas similares con la solicitud POST donde la solicitud GET funcionaba bien en mi backend, que estoy pasando mis variables, etc. El problema radica en que el backend realiza muchas redirecciones, que no funcionaron con fopen o los métodos de encabezado php.

Entonces, la única manera de hacerlo funcionar fue poner un formulario oculto y empujar los valores con un envío POST cuando se carga la página.

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>';
kaya
fuente
1

Puede usar sesiones para guardar $_POSTdatos, luego recuperar esos datos y configurarlos $_POSTen la solicitud posterior.

El usuario envía su solicitud a /dirty-submission-url.php.
Haga:

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

Luego, el navegador redirige y solicita /clean-submission-urla su servidor. Tendrá un enrutamiento interno para descubrir qué hacer con esto.
Al comienzo de la solicitud, hará:

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

Ahora, a través del resto de su solicitud, puede acceder $_POSTcomo podría a la primera solicitud.

Junco
fuente
Alternativamente, podría procesar los $_POSTdatos en una cadena de consulta y pasarlos a la página siguiente de esa manera. Pero entonces los datos no pueden ser demasiado grandes. Y esto probablemente no funcione si están involucradas las cargas de archivos, pero no estoy seguro.
Reed
0

Prueba esto:

Envíe datos y solicite con el encabezado http en la página B para redirigir a 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);
?>

Encabezados adicionales:

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
usuario3754884
fuente
0

Aquí hay otro enfoque que funciona para mí:

si necesita redirigir a otra página web ( user.php) e incluye una variable PHP ( $user[0]):

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

o

header("Location:./user.php?u_id=$user[0]");
Lucho
fuente
Esas alternativas están destinadas a usar el protocolo GET. Expone variables en el navegador del cliente. OP quería el mismo comportamiento con POST en su lugar.
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();
}

Ejemplo:

 post('url', {name: 'Johnny Bravo'});
njoshsn
fuente