php PHP重定向与POST数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5576619/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP Redirect with POST data
提问by Shiro
I did some research on this topic, and there are some experts who have said that it is not possible, so I would like to ask for an alternative solution.
我对这个主题做了一些研究,有一些专家说这是不可能的,所以我想寻求一个替代解决方案。
My situation:
我的情况:
Page A: [checkout.php] Customer fills in their billing details.
页面 A:[checkout.php] 客户填写他们的账单详细信息。
Page B: [process.php] Generate an invoice number and store customer details in database.
页面 B:[process.php] 生成发票编号并将客户详细信息存储在数据库中。
Page C: [thirdparty.com] Third Payment Gateway (ONLY ACCEPT POST DATA).
C 页:[thirdparty.com] 第三支付网关(仅接受发布数据)。
Customer fills in their details and sets up their cart in Page A, then POSTs to Page B. Inside process.php, store the POSTed data inside the database and generate an invoice number. After that, POST the customer data and invoice number to thirdparty.com payment gateway. The problem is doing POST in page B. cURL is able to POST the data to Page C, but the problem is the page didn't redirect to page C. The customer needs to fill in Credit Card details on Page C.
客户在页面 A 中填写他们的详细信息并设置他们的购物车,然后发布到页面 B。在 process.php 中,将发布的数据存储在数据库中并生成发票编号。之后,将客户数据和发票编号发布到第三方.com 支付网关。问题是在页面 B 中进行 POST。cURL 能够将数据 POST 到页面 C,但问题是页面没有重定向到页面 C。客户需要在页面 C 上填写信用卡详细信息。
The third party payment gateway did give us the API sample, the sample is POST the invoice number together with customer detail. We don't want the system to generate an excess of unwanted invoice numbers.
第三方支付网关确实为我们提供了 API 示例,该示例是将发票编号与客户详细信息一起发布。我们不希望系统生成过多不需要的发票编号。
Is there any solution for this? Our current solution is for the customer to fill detail in Page A, then in Page B we create another page showing all the customer details there, where the user can click a CONFIRM button to POST to Page C.
有什么解决办法吗?我们目前的解决方案是让客户在页面 A 中填写详细信息,然后在页面 B 中创建另一个页面,显示那里的所有客户详细信息,用户可以在其中单击确认按钮以发布到页面 C。
Our goal is for customers to only have to click once.
我们的目标是让客户只需点击一次。
Hope my question is clear :)
希望我的问题很清楚:)
采纳答案by Peeter
Generate a form on Page B with all the required data and action set to Page C and submit it with JavaScript on page load. Your data will be sent to Page C without much hassle to the user.
在页面 B 上生成一个表单,将所有必需的数据和操作设置为页面 C,并在页面加载时使用 JavaScript 提交它。您的数据将被发送到页面 C,不会给用户带来太多麻烦。
This is the only way to do it. A redirect is a 303 HTTP header that you can read up on http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html, but I'll quote some of it:
这是唯一的方法。重定向是一个 303 HTTP 标头,您可以在http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html上阅读,但我会引用其中的一些内容:
The response to the request can be found under a different URI and SHOULD be retrieved using a GET method on that resource. This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource. The new URI is not a substitute reference for the originally requested resource. The 303 response MUST NOT be cached, but the response to the second (redirected) request might be cacheable.
可以在不同的 URI 下找到对请求的响应,并且应该使用该资源上的 GET 方法检索。此方法的存在主要是为了允许 POST 激活脚本的输出将用户代理重定向到选定的资源。新的 URI 不是原始请求资源的替代引用。303 响应不能被缓存,但对第二个(重定向)请求的响应可能是可缓存的。
The only way to achieve what you're doing is with a intermediate page that sends the user to Page C. Here's a small/simple snippet on how you can achieve that:
实现您正在做的事情的唯一方法是使用将用户发送到页面 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>
You should also have a simple "confirm" form inside a noscript tag to make sure users without Javascript will be able to use your service.
您还应该在 noscript 标签中有一个简单的“确认”表单,以确保没有 Javascript 的用户能够使用您的服务。
回答by Eduardo Cuomo
/**
* 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");
}
}
回答by MikeMurko
I have another solution that makes this possible. It requires the client be running Javascript (which I think is a fair requirement these days).
我有另一个解决方案可以使这成为可能。它要求客户端运行 Javascript(我认为现在这是一个公平的要求)。
Simply use an AJAX request on Page A to go and generate your invoice number and customer details in the background (your previous Page B), then once the request gets returned successfully with the correct information - simply complete the form submission over to your payment gateway (Page C).
只需在页面 A 上使用 AJAX 请求在后台生成您的发票编号和客户详细信息(您之前的页面 B),然后一旦请求成功返回并提供正确的信息 - 只需将表单提交到您的支付网关(C 页)。
This will achieve your result of the user only clicking one button and proceeding to the payment gateway. Below is some pseudocode
这将实现用户只需单击一个按钮并进入支付网关的结果。下面是一些伪代码
HTML:
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 (using jQuery for convenience but trivial to make pure Javascript):
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
}
});
回答by Robert Sinclair
$_SESSION is your friend if you don't want to mess with Javascript
$_SESSION 是你的朋友,如果你不想弄乱 Javascript
Let's say you're trying to pass an email:
假设您正在尝试传递电子邮件:
On page A:
在 A 页:
// Start the session
session_start();
// Set session variables
$_SESSION["email"] = "[email protected]";
header('Location: page_b.php');
And on Page B:
在页面 B 上:
// Start the session
session_start();
// Show me the session!
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
To destroy the session
销毁会话
unset($_SESSION['email']);
session_destroy();
回答by Nanne
You can let PHP do a POST, but then your php will get the return, with all sorts of complications. I think the simplest would be to actually let the user do the POST.
您可以让 PHP 执行 POST,但随后您的 php 将获得回报,并带来各种复杂情况。我认为最简单的方法是让用户进行 POST。
So, kind-of what you suggested, you'll get indeed this part:
所以,就像你建议的那样,你确实会得到这部分:
Customer fill detail in Page A, then in Page B we create another page show all the customer detail there, click a CONFIRM button then POST to Page C.
客户在页面 A 中填写详细信息,然后在页面 B 中创建另一个页面,在那里显示所有客户详细信息,单击确认按钮,然后发布到页面 C。
But you can actually do a javascript submit on page B, so there is no need for a click. Make it a "redirecting" page with a loading animation, and you're set.
但是您实际上可以在页面 B 上执行 javascript 提交,因此无需单击。将其设置为带有加载动画的“重定向”页面,您就完成了。
回答by Raptor
I know this is an old question, but I have yet another alternative solution with jQuery:
我知道这是一个老问题,但我还有另一个使用 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();
The above code uses jQuery to create a form tag, appending hidden fields as post fields, and submit it at last. The page will forward to the form target page with the POST data attached.
上面的代码使用jQuery创建了一个表单标签,附加隐藏字段作为post字段,最后提交。该页面将转发到附加了 POST 数据的表单目标页面。
p.s. JavaScript & jQuery are required for this case. As suggested by the comments of the other answers, you can make use of <noscript>
tag to create a standard HTML form in case JS is disabled.
ps 在这种情况下需要 JavaScript 和 jQuery。正如其他答案的评论所建议的那样,您可以使用<noscript>
标签来创建标准的 HTML 表单,以防 JS 被禁用。
回答by Jeffery ThaGintoki
There is a simple hack, use $_SESSION
and create an array
of the posted values, and once you go to the File_C.php
you can use it then do you process after that destroy it.
有一个简单的hack,使用$_SESSION
并创建一个array
发布的值,一旦你去File_C.php
你可以使用它然后你在销毁它之后进行处理。
回答by CONvid19
I'm aware the question is php
oriented, but the best way to redirect a POST
request is probably using .htaccess
, ie:
我知道这个问题是php
定向的,但重定向POST
请求的最佳方法可能是使用.htaccess
,即:
RewriteEngine on
RewriteCond %{REQUEST_URI} string_to_match_in_url
RewriteCond %{REQUEST_METHOD} POST
RewriteRule ^(.*)$ https://domain.tld/ [L,R=307]
Explanation:
解释:
By default, if you want to redirect request with POST data, browser redirects it via GET with 302 redirect
. This also drops all the POST data associated with the request. Browser does this as a precaution to prevent any unintentional re-submitting of POST transaction.
默认情况下,如果您想使用 POST 数据重定向请求,浏览器会通过 GET 使用302 redirect
. 这也会删除与请求关联的所有 POST 数据。浏览器这样做是为了防止无意中重新提交 POST 事务。
But what if you want to redirect anyway POST request with it's data? In HTTP 1.1, there is a status code for this. Status code 307
indicates that the request should be repeatedwith the same HTTP method and data. So your POST request will be repeated along with it's data if you use this status code.
但是,如果您想重定向带有数据的 POST 请求怎么办?在 HTTP 1.1 中,有一个状态码。状态码307
表示应该使用相同的 HTTP 方法和数据重复请求。因此,如果您使用此状态代码,您的 POST 请求将与其数据一起重复。
回答by kaya
I faced similar issues with POST Request where GET Request was working fine on my backend which i am passing my variables etc. The problem lies in there that the backend does a lot of redirects, which didnt work with fopen or the php header methods.
我在 POST 请求中遇到了类似的问题,其中 GET 请求在我的后端工作正常,我正在传递我的变量等。问题在于后端做了很多重定向,这些重定向不适用于 fopen 或 php 标头方法。
So the only way i got it working was to put a hidden form and push over the values with a POST submit when the page is loaded.
所以我让它工作的唯一方法是放置一个隐藏的表单并在页面加载时使用 POST 提交推送值。
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>';
回答by Reed
You can use sessions to save $_POST
data, then retrieve that data and set it to $_POST
on the subsequent request.
您可以使用会话来保存$_POST
数据,然后检索该数据并将其设置$_POST
为后续请求。
User submits request to /dirty-submission-url.php
Do:
用户提交请求到 /dirty-submission-url.php
做:
if (session_status()!==PHP_SESSION_ACTIVE)session_start();
$_SESSION['POST'] = $_POST;
}
header("Location: /clean-url");
exit;
Then the browser redirects to and requests /clean-submission-url
from your server. You will have some internal routing to figure out what to do with this.
At the beginning of the request, you will do:
然后浏览器重定向到/clean-submission-url
您的服务器并从您的服务器请求。您将有一些内部路由来确定如何处理。
在请求开始时,您将执行以下操作:
if (session_status()!==PHP_SESSION_ACTIVE)session_start();
if (isset($_SESSION['POST'])){
$_POST = $_SESSION['POST'];
unset($_SESSION['POST']);
}
Now, through the rest of your request, you can access $_POST
as you could upon the first request.
现在,通过您的其余请求,您可以$_POST
按照第一个请求进行访问。