PHP-Umleitung mit POST-Daten

241

Ich habe zu diesem Thema recherchiert, und es gibt einige Experten, die gesagt haben, dass dies nicht möglich ist. Deshalb möchte ich nach einer alternativen Lösung fragen.

Meine Situation:

Seite A: [checkout.php] Der Kunde gibt seine Rechnungsdetails ein.

Seite B: [process.php] Generieren Sie eine Rechnungsnummer und speichern Sie Kundendaten in der Datenbank.

Seite C: [Drittanbieter.com] Drittes Zahlungsgateway (NUR POSTDATEN AKZEPTIEREN).

Der Kunde gibt seine Daten ein und richtet seinen Warenkorb auf Seite A ein, dann POSTs auf Seite B. Speichern Sie in process.php die POST-Daten in der Datenbank und generieren Sie eine Rechnungsnummer. Danach POSTEN Sie die Kundendaten und die Rechnungsnummer an das Zahlungsgateway von Drittanbieter. Das Problem besteht darin, POST auf Seite B durchzuführen. CURL kann die Daten auf Seite C POSTEN, das Problem ist jedoch, dass die Seite nicht auf Seite C umgeleitet wurde. Der Kunde muss die Kreditkartendetails auf Seite C eingeben.

Das Zahlungsgateway eines Drittanbieters hat uns das API-Muster zur Verfügung gestellt. Das Muster ist POST der Rechnungsnummer zusammen mit den Kundendetails. Wir möchten nicht, dass das System einen Überschuss an unerwünschten Rechnungsnummern generiert.

Gibt es dafür eine Lösung? Unsere aktuelle Lösung besteht darin, dass der Kunde Details auf Seite A ausfüllt. Anschließend erstellen wir auf Seite B eine weitere Seite mit allen Kundendaten, auf der der Benutzer auf die Schaltfläche BESTÄTIGEN klicken kann, um auf Seite C zu POSTEN.

Unser Ziel ist es, dass Kunden nur einmal klicken müssen.

Hoffe meine Frage ist klar :)

Shiro
quelle
Ich denke nicht, dass dies doppelt vorhanden ist, da mein Ziel darin besteht, innerhalb einer PHP-Seite die POST-Daten zu übergeben und sie umzuleiten. cURL Ich glaube nicht, dass es möglich ist, das zu tun. Suchen Sie einfach nach einer Alternative für Experten
Shiro
ʜᴛᴛᴘ 308 Umleitungscode?
user2284570

Antworten:

212

Generieren Sie auf Seite B ein Formular mit allen erforderlichen Daten und Aktionen auf Seite C und senden Sie es beim Laden der Seite mit JavaScript. Ihre Daten werden ohne großen Aufwand an den Benutzer an Seite C gesendet.

Dies ist der einzige Weg, dies zu tun. Eine Weiterleitung ist ein 303-HTTP-Header, den Sie unter http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html nachlesen können , aber ich werde einige davon zitieren:

Die Antwort auf die Anfrage kann unter einem anderen URI gefunden werden und sollte mit einer GET-Methode für diese Ressource abgerufen werden. Diese Methode dient hauptsächlich dazu, dass die Ausgabe eines POST-aktivierten Skripts den Benutzeragenten zu einer ausgewählten Ressource umleitet. Der neue URI ist keine Ersatzreferenz für die ursprünglich angeforderte Ressource. Die 303-Antwort darf NICHT zwischengespeichert werden, aber die Antwort auf die zweite (umgeleitete) Anforderung kann zwischengespeichert werden.

Der einzige Weg, um das zu erreichen, was Sie tun, ist eine Zwischenseite, die den Benutzer zu Seite C sendet. Hier ist ein kleiner / einfacher Ausschnitt, wie Sie dies erreichen können:

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

Sie sollten auch ein einfaches Bestätigungsformular in einem Noscript-Tag haben, um sicherzustellen, dass Benutzer ohne Javascript Ihren Dienst nutzen können.

Peeter
quelle
2
Mein Ziel ist in Seite A -> Seite C, Seite B ist der Controller (Geschäftslogik), der die Rechnungsnummer generiert. In der Systemansicht ist Seite A-> Seite B-> Seite C, in der Benutzeransicht sollte jedoch Seite A-> Seite B sein, sie sollten niemals Seite B freigeben.
Shiro
3
@Peeter: kluger Vorschlag +1. Das einzige Problem ist , dass , wenn der Benutzer auf Seite C Druck zurück - Taste Seite C. erneut vorgelegt wird darüber hinaus Sie das zu kodieren vergessen haben , $aund $bdurch die Verwendung htmlentities/htmlspecialcharsfinden stackoverflow.com/questions/6180072/php-forward-data-post/...
Marco Demaio
8
Frage hier ist, was ist, wenn Javascript auf dem Client deaktiviert ist? Seite B wird dann nicht zu Seite C umgeleitet, oder?
Imran Omar Bukhsh
24
<noscript><input type="submit" value="Click here if you are not redirected."/></noscript>innerhalb der<form>
Nullability
3
Das languageAttribut ist veraltet, es sollte sein<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
quelle
17
Während dies zunächst auch besser aussieht als die akzeptierte Antwort, $urlstelle ich fest, dass es nicht zur bereitgestellten umleitet - Es ersetzt nur den Inhalt der vorhandenen Seite durch den Inhalt der $urlSeite. Wichtig ist , dass der PHP-Code auf der $urlSeite nicht ausgewertet wird.
iPadDeveloper2011
@ iPadDeveloper2011, in der URL hast du keinen PHP-Code! Der PHP-Code wird im SERVER ausgeführt, nicht im Client.
Eduardo Cuomo
1
redirect_post()Der serverseitige PHP-Code sendet eine Anfrage an den SERVER für a $url. Wenn das $urleine .phpSeite ist, stelle ich fest, dass das PHP nicht ausgewertet wird - HTML wird mit PHP-Tags zurückgegeben, die noch darin sind. Ist es nicht der springende Punkt, POST-Daten an ein serverseitiges Skript zu senden?
iPadDeveloper2011
2
@EduardoCuomo Diese Methode funktioniert nur mit absoulten URLs, da fopen () so funktioniert: php.net/manual/en/function.fopen.php Es ist immer noch eine ziemlich raffinierte Antwort.
Omn
@Omn du hast recht! "Das funktioniert nicht mit der relativen URL?" ist keine Frage, ist eine Aussage. Entschuldigung für die Verwirrung
Eduardo Cuomo
25

Ich habe eine andere Lösung, die dies ermöglicht. Es erfordert, dass der Client Javascript ausführt (was meiner Meinung nach heutzutage eine faire Anforderung ist).

Verwenden Sie einfach eine AJAX-Anfrage auf Seite A, um Ihre Rechnungsnummer und Kundendaten im Hintergrund (Ihre vorherige Seite B) zu generieren. Sobald die Anfrage erfolgreich mit den richtigen Informationen zurückgesandt wurde, füllen Sie einfach das Formular aus, das Sie an Ihr Zahlungsgateway senden (Seite C).

Dadurch wird Ihr Ergebnis erzielt, wenn der Benutzer nur auf eine Schaltfläche klickt und zum Zahlungsgateway fährt. Unten ist ein Pseudocode

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 (mit jQuery aus Bequemlichkeitsgründen, aber trivial, um reines Javascript zu erstellen):

$('#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
  }
});
Mike Murko
quelle
1
Diese Lösung hat ein Problem: Wenn jemand das JavaScript auf dieser Seite deaktiviert, aktualisiert und sendet, wird die Zahlungsseite aufgerufen, ohne dass etwas gespeichert wird. Dies könnte eine Lücke sein.
Caoglish
2
Dann nur die Aktion "payForm" mit Javascript festlegen? Wenn JS deaktiviert ist, wird das Formular nicht gesendet.
Mike Murko
Der Benutzer, der JS ausschaltet, sollte uns kein Problem bereiten. Der Grund, warum wir zu Seite B gehen müssen, besteht wahrscheinlich darin, einen Fingerabdruck zu generieren oder einen Bestellcode usw. hinzuzufügen. Ohne diese sollte die Seite C eines Drittanbieters fehlschlagen oder im schlimmsten Fall. Wenn das Ergebnis von Drittanbietern ohne Bestellcode an uns zurückkommt, sollten wir die Bestellung nicht annehmen. Dies ist insgesamt eine gute Lösung, wenn JS akzeptabel ist.
Coder
19

$ _SESSION ist dein Freund, wenn du dich nicht mit Javascript anlegen willst

Angenommen, Sie versuchen, eine E-Mail zu senden:

Auf Seite A:

// Start the session
session_start();

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

header('Location: page_b.php');

Und auf Seite B:

// Start the session
session_start();

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

Um die Sitzung zu zerstören

unset($_SESSION['email']);
session_destroy();
Robert Sinclair
quelle
Warum halten Sie dies für weniger sicher als die Javascript-Version?
Adam Baranyai
1
Nein, ich meine nicht im Vergleich zu Javascript. Nur im Allgemeinen kann $ _SESSION allein etwas weniger sicher sein als $ _SESSION + Cookie, obwohl $ _SESSION für sich genommen ziemlich sicher ist. Weitere Informationen hier: stackoverflow.com/questions/17413480/session-spoofing-php
Robert Sinclair
und wie man die Sitzung schließt?
Sayed Muhammad Idrees
Müssen Sie die Sitzung schließen?
Ivan P.
6

Sie können PHP einen POST machen lassen, aber dann wird Ihr PHP die Rückgabe mit allen möglichen Komplikationen erhalten. Ich denke, das Einfachste wäre, den Benutzer tatsächlich den POST machen zu lassen.

So wie Sie es vorgeschlagen haben, erhalten Sie tatsächlich diesen Teil:

Kunden füllen Details auf Seite A aus, dann erstellen wir auf Seite B eine weitere Seite, auf der alle Kundendetails angezeigt werden. Klicken Sie auf die Schaltfläche BESTÄTIGEN und dann auf Seite C POSTEN.

Sie können jedoch tatsächlich eine Javascript-Übermittlung auf Seite B durchführen, sodass kein Klick erforderlich ist. Machen Sie es zu einer "Umleitungs" -Seite mit einer Ladeanimation, und schon sind Sie fertig.

Nanne
quelle
Das machen wir jetzt. Ich denke, gibt es eine bessere PHP-Logik, um es zu lösen. Vielen Dank. ;)
Shiro
Ja, mehr in Richtung HTTP, aber ich arbeite in einer PHP-Umgebung, also denke ich, dass beide Tags sind. Vielen Dank! Col. Shrapnel.
Shiro
6

Ich weiß, dass dies eine alte Frage ist, aber ich habe noch eine andere alternative Lösung mit 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();

Der obige Code verwendet jQuery, um ein Formular-Tag zu erstellen, versteckte Felder als Post-Felder anzuhängen und es schließlich zu senden. Die Seite wird mit den angehängten POST-Daten an die Formularzielseite weitergeleitet.

ps Für diesen Fall sind JavaScript und jQuery erforderlich. Wie aus den Kommentaren der anderen Antworten hervorgeht, können Sie mithilfe des <noscript>Tags ein Standard-HTML-Formular erstellen, falls JS deaktiviert ist.

Raubvogel
quelle
5

Es gibt einen einfachen Hack, verwenden $_SESSIONund erstellen Sie einen arrayder veröffentlichten Werte, und sobald Sie zu dem gehen, File_C.phpkönnen Sie ihn verwenden, dann verarbeiten Sie ihn danach und zerstören ihn.

Jeffery ThaGintoki
quelle
Können Sie ein kleines Beispiel dafür geben, was Sie meinen?
Caro
3
Nach meinem Verständnis ist Seite C eine externe Quelle, die Post-Werte, aber keine Sitzungen verwendet.
Narayan Bhandari
3

Ich bin mir bewusst, dass die Frage phporientiert ist, aber der beste Weg, eine POSTAnfrage umzuleiten, ist wahrscheinlich die Verwendung von .htaccess:

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

Erläuterung:

Wenn Sie eine Anforderung mit POST-Daten umleiten möchten, leitet der Browser diese standardmäßig über GET mit um 302 redirect. Dadurch werden auch alle mit der Anforderung verknüpften POST-Daten gelöscht . Der Browser tut dies als Vorsichtsmaßnahme, um ein unbeabsichtigtes erneutes Senden der POST-Transaktion zu verhindern.

Aber was ist, wenn Sie die POST-Anfrage trotzdem mit ihren Daten umleiten möchten? In HTTP 1.1 gibt es hierfür einen Statuscode. Der Statuscode 307gibt an, dass die Anforderung mit derselben HTTP-Methode und denselben Daten wiederholt werden soll . Wenn Sie diesen Statuscode verwenden, wird Ihre POST-Anfrage zusammen mit den Daten wiederholt.

SRC

CONvid19
quelle
2

Ich hatte ähnliche Probleme mit POST Request, bei denen GET Request auf meinem Backend einwandfrei funktionierte, wobei ich meine Variablen usw. übergebe. Das Problem besteht darin, dass das Backend viele Weiterleitungen ausführt, die mit fopen oder den PHP-Header-Methoden nicht funktionierten.

Die einzige Möglichkeit, es zum Laufen zu bringen, bestand darin, ein verstecktes Formular einzufügen und die Werte mit einem POST-Submit zu verschieben, wenn die Seite geladen wird.

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

Sie können Sitzungen verwenden, um $_POSTDaten zu speichern, diese Daten dann abzurufen und $_POSTbei der nachfolgenden Anforderung festzulegen.

Benutzer überfordern zu /dirty-submission-url.php
Do:

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

Anschließend leitet der Browser zu /clean-submission-urlIhrem Server weiter und fordert ihn an. Sie haben ein internes Routing, um herauszufinden, was Sie damit tun sollen.
Zu Beginn der Anfrage werden Sie Folgendes tun:

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

Jetzt können Sie über den Rest Ihrer Anfrage $_POSTwie bei der ersten Anfrage darauf zugreifen .

Schilf
quelle
Alternativ können Sie die $_POSTDaten zu einer Abfragezeichenfolge verarbeiten und auf diese Weise an die nachfolgende Seite übergeben. Aber dann können die Daten nicht zu groß sein. Und das funktioniert wahrscheinlich nicht, wenn Dateien hochgeladen werden, aber ich bin mir nicht sicher.
Reed
0

Versuche dies:

Senden Sie Daten und fordern Sie mit dem http-Header auf Seite B an, zum Gateway umzuleiten

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

Zusätzliche Überschriften:

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
user3754884
quelle
-1

Hier gibt es einen anderen Ansatz, der für mich funktioniert:

Wenn Sie zu einer anderen Webseite umleiten müssen ( user.php) und eine PHP-Variable ( $user[0]) enthält:

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

oder

header("Location:./user.php?u_id=$user[0]");
Lucho
quelle
Diese Alternativen sollen das GET-Protokoll verwenden. Es macht Variablen im Browser des Clients verfügbar. OP wollte stattdessen dasselbe Verhalten mit 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();
}

Beispiel:

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