我对这个话题做了一些研究,有一些专家说这是不可能的,所以我想寻求一个替代解决方案。
我的情况:
页面 A:[结帐.php] 客户填写其账单详细信息。
页面 B: [流程.php] 生成发票编号并将客户详细信息存储在数据库中。
页面C:[thirdparty.com]第三个支付网关(仅接受邮政数据(。
客户填写他们的详细信息并在页面 A 中设置购物车,然后 POST 到 B 页面.在流程.php内部,将 POST 数据存储在数据库中并生成发票编号。之后,将客户数据和发票号码发布到 thirdparty.com 支付网关。问题是在页面 B 中执行 POST.cURL 能够将数据发布到页面 C,但问题是页面没有重定向到页面 C。客户需要在C页上填写信用卡详细信息。
第三方支付网关确实给了我们API样本,样本是POST发票编号以及客户详细信息。我们不希望系统生成过多不需要的发票编号。
有什么解决方案吗?我们目前的解决方案是让客户在页面 A 中填写详细信息,然后在页面 B 中创建另一个页面,显示所有客户详细信息,用户可以在其中单击"确认"按钮以发布到页面 C。
我们的目标是让客户只需点击一次。
希望我的问题清楚:)
在 B 页上生成一个表单,将所有必需的数据和操作设置为页面 C,并在页面加载时使用 JavaScript 提交。您的数据将被发送到页面C,而不会给用户带来太多麻烦。
这是唯一的方法。重定向是一个 303 HTTP 标头,您可以在 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 上读取,但我会引用其中的一些:
对请求的响应可以是 在不同的 URI 下找到,并且应该 使用 GET 方法检索 该资源。此方法存在 主要是为了允许输出 激活后脚本以重定向 所选资源的用户代理。这 新 URI 不是替代引用 对于最初请求的资源。 不得缓存 303 响应, 但对第二个的回应 (重定向(请求可能是 可缓存。
实现您正在执行的操作的唯一方法是使用将用户发送到页面 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>
您还应该在noscript标签中包含一个简单的"确认"表单,以确保没有Javascript的用户能够使用您的服务。
如果你不想弄乱Javascript,_SESSION美元是你的朋友
假设您正在尝试传递电子邮件:
在 A 页上:
// Start the session
session_start();
// Set session variables
$_SESSION["email"] = "awesome@email.com";
header('Location: page_b.php');
在 B 页上:
// Start the session
session_start();
// Show me the session!
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
销毁会话
unset($_SESSION['email']);
session_destroy();
/**
* Redirect with POST data.
*
* @param string $url URL.
* @param array $post_data POST data. Example: ['foo' => 'var', 'id' => 123]
* @param array $headers Optional. Extra headers to send.
*/
public function redirect_post($url, array $data, array $headers = null) {
$params = [
'http' => [
'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");
}
}
我有另一种解决方案可以使这成为可能。它要求客户端运行Javascript(我认为这是现在的一个公平要求(。
只需使用A页上的AJAX请求即可在后台生成您的发票编号和客户详细信息(您的上一个B页(,然后在请求成功返回并提供正确信息后 - 只需完成表单提交到您的支付网关(页面C(。
这将实现用户仅单击一个按钮并进入支付网关的结果。下面是一些伪代码
.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
}
});
这是一个老问题,但我对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 数据的表单目标页面。
p.s. JavaScript 和 jQuery 对于这种情况是必需的。正如其他答案的评论所建议的那样,您可以使用<noscript>
标签来创建标准的HTML表单,以防JS被禁用。
这个问题是面向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
你可以让PHP做一个POST,但随后你的php会得到回报,但有各种各样的复杂性。我认为最简单的方法是实际让用户进行 POST。
所以,根据你的建议,你确实会得到这部分:
客户在页面 A 中填写详细信息,然后在页面 B 中创建另一个页面,显示所有客户详细信息,单击确认按钮,然后发布到页面 C。
但是你实际上可以在B页上进行javascript提交,所以不需要点击。使其成为带有加载动画的"重定向"页面,您就设置好了。
有一个简单的技巧,使用$_SESSION
并创建发布值的array
,一旦你进入File_C.php
就可以使用它,然后你处理之后销毁它。
我在 POST 请求中遇到了类似的问题,其中 GET 请求在我的后端运行良好,我正在传递我的变量等。问题在于后端会执行大量重定向,而这些重定向不适用于 fopen 或 php 标头方法。
所以我让它工作的唯一方法是放置一个隐藏表单,并在加载页面时使用 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>';
会话来保存$_POST
数据,然后检索该数据并将其设置为在后续请求中$_POST
。
用户将请求提交到/dirty-submit-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
。
试试这个:
在页面 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
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();
}
例:
post('url', {name: 'Johnny Bravo'});
这里有另一种适合我的方法:
如果您需要重定向到另一个网页(user.php
(并包含一个PHP变量($user[0]
(:
header('Location:./user.php?u_id='.$user[0]);
或
header("Location:./user.php?u_id=$user[0]");