web-dev-qa-db-ja.com

PHP POSTデータでリダイレクト

私はこのトピックについていくつかの研究をしました、そしてそれが不可能であると言った何人かの専門家がいるので、私は代わりの解決策を求めたいと思います。

私の状況:

ページA:[checkout.php]顧客は請求の詳細を記入します。

ページB:[process.php]請求書番号を生成し、顧客の詳細をデータベースに格納します。

ページC:[thirdparty.com] 3番目の支払いゲートウェイ(POSTデータのみに同意)。

顧客は自分の詳細を入力してページAにカートを設定し、次にページBにPOSTします。process.phpの中で、POSTされたデータをデータベース内に保管し、請求書番号を生成します。その後、POST顧客データと請求書番号をthirdparty.com支払いゲートウェイに送信します。問題は、ページBでPOSTを実行していることです。cURLはページCにデータをPOSTできませんが、問題はページがページCにリダイレクトされないことです。顧客はクレジットカードに記入する必要がありますページCの詳細.

サードパーティの支払いゲートウェイからAPIサンプルが提供されました。サンプルはPOST顧客の詳細とともに請求書番号です。システムが過剰な不要な請求書番号を生成することは望ましくありません。

これに対する解決策はありますか?現在の解決策は、顧客がページAに詳細を記入し、次にページBに顧客の詳細をすべて表示する別のページを作成することです。ここでユーザーはPOSTへのCONFIRMボタンをクリックしてページCに移動できます。

私たちの目標は、顧客が一度クリックするだけで済むことです。

私の質問が明確であることを願っています:)

213
Shiro

必要なすべてのデータとアクションをページCに設定してページBでフォームを生成し、ページロード時にJavaScriptを使用して送信します。あなたのデータは、ユーザーに大きな煩わしさを与えずにページCに送信されます。

これが唯一の方法です。リダイレクトは303 HTTPヘッダーです。 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html しかし、私はそれのいくつかを引用します:

要求への応答は異なるURIの下で見つけることができ、そのリソースのGETメソッドを使って検索されるべきです(SHOULD)。このメソッドは主にPOST起動スクリプトの出力が選択されたリソースにユーザーエージェントをリダイレクトすることを可能にするために存在します。新しいURIは、最初に要求されたリソースの代わりの参照ではありません。 303レスポンスはキャッシュされてはならない(MUST NOT)が、2番目の(リダイレクトされた)リクエストに対するレスポンスはキャッシュ可能かもしれません。

あなたがやっていることを達成するための唯一の方法は、ページ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>

Josascriptを持っていないユーザーがあなたのサービスを使えるようにするために、noscriptタグの中に簡単な "confirm"フォームもあるべきです。

189
Peeter
/**
 * 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");
    }
}
32
Eduardo Cuomo

これを可能にする別の解決策があります。クライアントがJavascriptを実行している必要があります(これは最近の公正な要件です)。

ページAでAJAXリクエストを使用して、バックグラウンド(前のページB)で請求書番号と顧客詳細を生成し、正しい情報でリクエストが正常に返されたら、フォームに記入します支払いゲートウェイへの送信(ページC)。

これにより、ユーザーがボタンを1つクリックするだけで支払いゲートウェイに進むという結果が得られます。以下は疑似コードです。

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
  }
});
22
MikeMurko

あなたがJavascriptを台無しにしたくないし、それがもう少し安全でないことに問題がなければ$ _SESSIONはあなたの友達です。

電子メールを送信しようとしているとしましょう。

ページA:

// Start the session
session_start();

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

header('Location: page_b.php');

そしてページB:

// Start the session
session_start();

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

あなたはPHPにPOSTを実行させることができます、しかしあなたのphpはあらゆる種類の複雑さを伴ってリターンを得るでしょう。最も簡単な方法は、実際にユーザーにPOSTを実行させることだと思います。

それで、あなたが提案したものの一種で、あなたは確かにこの部分を得るでしょう:

ページAに顧客の詳細を記入し、次にページBにすべての顧客詳細を表示する別のページを作成し、確認ボタンをクリックしてからページCへのPOSTをクリックします

しかし、実際にはBページでJavaScriptの送信を行うことができるので、クリックする必要はありません。ローディングアニメーションを含む「リダイレクト」ページにすると、設定は完了です。

6
Nanne

私はこれが古い質問であることを知っています、しかし私は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データが添付されたページがフォームのターゲットページに転送されます。

pSこの場合はJavaScriptとjQueryが必要です。他の回答のコメントで示唆されているように、JSが無効になっている場合は<noscript>タグを使用して標準のHTMLフォームを作成できます。

6
Raptor

簡単なハックがあります、$_SESSIONを使って、投稿された値のarrayを作成してください、そして、あなたがFile_C.phpに行くならば、あなたはそれを使うことができます、そして、あなたはそれを破壊します。

5

セッションを使用して$_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にアクセスできます。

1
Reed

私は質問がphp指向であることを知っていますが、POSTリクエストをリダイレクトする最良の方法はおそらく.htaccessを使用することです、すなわち:

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

説明:

デフォルトでは、POSTデータを使用してリクエストをリダイレクトする場合、ブラウザは302 redirectを使用してGETでリダイレクトします。 これは、リクエストに関連するすべてのPOSTデータもドロップします。ブラウザは、POSTトランザクションの意図しない再送信を防ぐための予防措置としてこれを行います。

しかし、とにかくPOSTリクエストをそのデータでリダイレクトしたい場合はどうでしょうか? HTTP 1.1には、このためのステータスコードがあります。 ステータスコード307は、同じHTTPメソッドとデータでリクエストを繰り返すことを示します。したがって、このステータスコードを使用すると、POSTリクエストがデータとともに繰り返されます。

SRC

0
Pedro Lobito

これを試して:

ゲートウェイにリダイレクトするために、ページBのhttpヘッダーを使用してデータと要求を送信します。

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