Reindirizzamento PHP con dati POST


241

Ho fatto alcune ricerche su questo argomento e ci sono alcuni esperti che hanno affermato che non è possibile , quindi vorrei chiedere una soluzione alternativa.

La mia situazione:

Pagina A: [checkout.php] Il cliente inserisce i dettagli di fatturazione.

Pagina B: [process.php] Genera un numero di fattura e memorizza i dettagli del cliente nel database.

Pagina C: [thirdparty.com] terzo gateway di pagamento (ACCETTARE SOLO DATI POSTALI).

Il cliente inserisce i propri dettagli e imposta il carrello nella pagina A, quindi i POST nella pagina B. All'interno di process.php, memorizza i dati POST all'interno del database e genera un numero di fattura. Successivamente, POST i dati del cliente e il numero di fattura al gateway di pagamento di terze parti. Il problema è POST nella pagina B. cURL è in grado di POST i dati alla pagina C, ma il problema è che la pagina non ha reindirizzato alla pagina C. Il cliente deve inserire i dettagli della carta di credito nella pagina C.

Il gateway di pagamento di terze parti ci ha fornito l'esempio API, l'esempio è POST il numero di fattura insieme ai dettagli del cliente. Non vogliamo che il sistema generi un eccesso di numeri di fattura indesiderati.

C'è qualche soluzione per questo? La nostra attuale soluzione è che il cliente riempia i dettagli nella Pagina A, quindi nella Pagina B creiamo un'altra pagina che mostra tutti i dettagli del cliente lì, dove l'utente può fare clic su un pulsante CONFERMA per POSTARE alla Pagina C.

Il nostro obiettivo è che i clienti debbano fare clic una sola volta.

Spero che la mia domanda sia chiara :)


non penso sia duplicato per questo, è perché il mio obiettivo è all'interno di una pagina PHP, passare i dati POST e reindirizzarli. CURL Non credo sia possibile farlo. Cerca un esperto qualsiasi alternativa per esso
Shiro

ʜᴛᴛᴘ 308 codice di reindirizzamento?
user2284570

Risposte:


212

Generare un modulo nella pagina B con tutti i dati richiesti e l'azione impostati sulla pagina C e inviarlo con JavaScript sul caricamento della pagina. I tuoi dati verranno inviati alla Pagina C senza troppi problemi all'utente.

Questo è l'unico modo per farlo. Un reindirizzamento è un'intestazione HTTP 303 che puoi leggere su http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html , ma ne citerò alcuni:

La risposta alla richiesta può essere trovata sotto un URI diverso e DOVREBBE essere recuperata utilizzando un metodo GET su quella risorsa. Questo metodo esiste principalmente per consentire all'output di uno script attivato POST di reindirizzare l'agente utente su una risorsa selezionata. Il nuovo URI non è un riferimento sostitutivo per la risorsa richiesta originariamente. La risposta 303 NON DEVE essere memorizzata nella cache, ma la risposta alla seconda richiesta (reindirizzata) potrebbe essere memorizzabile nella cache.

L'unico modo per ottenere quello che stai facendo è con una pagina intermedia che manda l'utente alla Pagina C. Ecco un piccolo / semplice frammento su come farlo:

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

Dovresti anche avere un semplice modulo di "conferma" all'interno di un tag noscript per assicurarti che gli utenti senza Javascript possano usare il tuo servizio.


2
il mio obiettivo è in Pagina A -> Pagina C, Pagina B è il controller (logica aziendale) generare il numero di fattura. Dalla vista del sistema è Pagina A-> Pagina B-> Pagina C, ma dalla vista utente dovrebbe essere Pagina A-> Pagina B, non dovrebbero mai rilasciare la Pagina B.
Shiro,

3
@Peeter: suggerimento intelligente +1. L'unico problema è che quando l'utente sul pulsante Indietro pulsante Pagina C è ripresentato alla pagina C. Inoltre si è dimenticato di codificare il $ae $butilizzando htmlentities/htmlspecialchars, vedi stackoverflow.com/questions/6180072/php-forward-data-post/...
Marco Demaio

8
domanda qui è cosa succede se Javascript è disabilitato sul client? La pagina B non reindirizzerà alla pagina C, vero?
Imran Omar Bukhsh,

24
<noscript><input type="submit" value="Click here if you are not redirected."/></noscript>all'interno del<form>
nullability

3
l' languageattributo è obsoleto, dovrebbe essere<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
Mentre all'inizio questo sembra anche migliore della risposta accettata, noto che non reindirizza al fornito - $urlSostituisce semplicemente il contenuto della pagina esistente con il contenuto della $urlpagina. È importante sottolineare che il codice PHP nella $urlpagina non viene valutato.
iPadDeveloper2011

@ iPadDeveloper2011, nell'URL, non hai un codice PHP! Il codice PHP viene eseguito nel SERVER, non nel client.
Eduardo Cuomo,

1
redirect_post(), che è lato server, codice php, invia una richiesta al SERVER per a $url. Se $urlè una .phppagina, noto che il php non viene valutato - html viene restituito con tag php ancora presenti. Non è forse il punto di inviare i dati POST a uno script lato server?
iPadDeveloper2011

2
@EduardoCuomo questo metodo funziona solo con gli URL absoulte, a causa di come funziona fopen (): php.net/manual/en/function.fopen.php È ancora una risposta piuttosto ingegnosa.
Omn,

@Omn hai ragione! "Questo non funziona con l'URL relativo?" non è una domanda, è un'affermazione. Ci scusiamo per la confusione
Eduardo Cuomo

25

Ho un'altra soluzione che lo rende possibile. Richiede che il client esegua Javascript (che ritengo sia un requisito equo in questi giorni).

Usa semplicemente una richiesta AJAX nella pagina A per generare il numero di fattura e i dettagli del cliente in background (la tua pagina B precedente), quindi una volta che la richiesta viene restituita correttamente con le informazioni corrette, completa semplicemente l'invio del modulo al gateway di pagamento (Pagina C).

Ciò consentirà di ottenere il risultato dell'utente solo facendo clic su un pulsante e procedendo al gateway di pagamento. Di seguito è riportato uno pseudocodice

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 per praticità ma banale per rendere 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
Questa soluzione ha un problema, se qualcuno disattiva JavaScript in questa pagina, aggiorna e invia, andrà pagina di pagamento senza salvare nulla. questo potrebbe essere una scappatoia.
caoglish

2
Quindi impostare l'azione paymentForm solo con Javascript? Se JS è disabilitato, il modulo non verrà inviato.
MikeMurko,

L'utente che disattiva JS non dovrebbe causarci un problema: il motivo per cui dobbiamo andare alla Pagina B è probabilmente quello di generare un'impronta digitale o aggiungere un codice d'ordine, ecc. Senza di questi, la pagina C di terze parti dovrebbe fallire o, nel peggiore dei casi, quando il risultato ci viene restituito dalla terza parte senza un codice d'ordine, non dovremmo accettare l'ordine. Questa è nel complesso una buona soluzione se JS è accettabile.
Coder

19

$ _SESSION è tuo amico se non vuoi fare confusione con Javascript

Supponiamo che tu stia provando a inviare un'email:

A pagina A:

// Start the session
session_start();

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

header('Location: page_b.php');

E a pagina B:

// Start the session
session_start();

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

Per distruggere la sessione

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

perché ritieni che questo sia meno sicuro della versione javascript?
Adam Baranyai,

1
no, intendo non rispetto a javascript. Solo in generale $ _SESSION da solo può essere un po 'meno sicuro di dire $ _SESSION + cookie, sebbene $ _SESSION sia abbastanza sicuro da solo. Maggiori informazioni qui: stackoverflow.com/questions/17413480/session-spoofing-php
Robert Sinclair

e come chiudere la sessione?
Ha detto Muhammad Idrees il

Devi chiudere la sessione?
Ivan P.

6

Puoi lasciare che PHP faccia un POST, ma poi il tuo php otterrà il ritorno, con ogni sorta di complicazioni. Penso che il modo più semplice sarebbe consentire all'utente di fare il POST.

Quindi, un po 'di quello che hai suggerito, otterrai davvero questa parte:

Dettagli di riempimento cliente nella pagina A, quindi nella pagina B creiamo un'altra pagina che mostra tutti i dettagli del cliente lì, fare clic su un pulsante CONFERMA, quindi POST alla pagina C.

Ma puoi effettivamente inviare un javascript a pagina B, quindi non è necessario un clic. Trasformalo in una pagina di "reindirizzamento" con un'animazione di caricamento e sei pronto.


Questo è quello che facciamo ora. Sto pensando che c'è qualche migliore logica di PHP per risolverlo. Grazie. ;)
Shiro

Sì, più verso HTTP, ma lavoro in ambiente PHP, quindi penso che sia entrambi tag. Grazie! Col. Shrapnel.
Shiro

6

So che questa è una vecchia domanda, ma ho ancora un'altra soluzione 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();

Il codice sopra riportato utilizza jQuery per creare un tag modulo, aggiungere campi nascosti come campi postali e infine inviarlo. La pagina verrà inoltrata alla pagina di destinazione del modulo con i dati POST allegati.

ps JavaScript e jQuery sono richiesti per questo caso. Come suggerito dai commenti delle altre risposte, è possibile utilizzare il <noscript>tag per creare un modulo HTML standard nel caso in cui JS sia disabilitato.


5

C'è un semplice hack, usa $_SESSIONe crea uno arraydei valori pubblicati, e una volta che vai su File_C.phppuoi usarlo e poi lo elabori dopo averlo distrutto.


puoi fornire un piccolo esempio di cosa intendi?
caro

3
La mia comprensione è che Pagina C è una fonte esterna, che accetta valori post ma non sessioni.
Narayan Bhandari,

3

Sono consapevole che la domanda è phporientata, ma il modo migliore per reindirizzare una POSTrichiesta sta probabilmente usando .htaccess, cioè:

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

Spiegazione:

Per impostazione predefinita, se si desidera reindirizzare la richiesta con dati POST, il browser reindirizza tramite GET con 302 redirect. Ciò elimina anche tutti i dati POST associati alla richiesta . Il browser lo fa per precauzione per impedire l'inoltro involontario della transazione POST.

Ma cosa succede se si desidera reindirizzare comunque la richiesta POST con i suoi dati? In HTTP 1.1, esiste un codice di stato per questo. Il codice di stato 307indica che la richiesta deve essere ripetuta con lo stesso metodo e dati HTTP. Quindi la tua richiesta POST verrà ripetuta insieme ai suoi dati se usi questo codice di stato.

SRC


2

Ho riscontrato problemi simili con la richiesta POST in cui la richiesta GET stava funzionando bene sul mio back-end e sto passando le mie variabili, ecc. Il problema sta nel fatto che il back-end esegue molti reindirizzamenti, che non ha funzionato con i metodi header fpen o php.

Quindi l'unico modo per farlo funzionare era mettere un modulo nascosto e spingere i valori con un invio POST quando la pagina è caricata.

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

È possibile utilizzare le sessioni per salvare i $_POSTdati, quindi recuperarli e impostarli $_POSTsulla richiesta successiva.

L'utente invia la richiesta a /dirty-submission-url.php
Do:

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

Quindi il browser reindirizza e richiede /clean-submission-urldal tuo server. Avrai un percorso interno per capire cosa fare con questo.
All'inizio della richiesta, farai:

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

Ora, attraverso il resto della tua richiesta, puoi accedere $_POSTcome puoi alla prima richiesta.


In alternativa, è possibile elaborare i $_POSTdati in una stringa di query e passarli alla pagina successiva in quel modo. Ma poi i dati non possono essere troppo grandi. E questo probabilmente non funziona se sono coinvolti caricamenti di file, ma non ne sono sicuro.
Reed,

0

Prova questo:

Invia i dati e richiedi con l'intestazione http nella pagina B per reindirizzare 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);
?>

Intestazioni aggiuntive:

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

Ecco un altro approccio che funziona per me:

se devi reindirizzare a un'altra pagina web ( user.php) e include una variabile PHP ( $user[0]):

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

o

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

Queste alternative hanno lo scopo di utilizzare il protocollo GET. Espone le variabili sul browser del client. OP voleva invece lo stesso comportamento con 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();
}

Esempio:

 post('url', {name: 'Johnny Bravo'});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.