我做了一些关于这个话题的研究,有一些专家说这是不可能的,所以我想要一个替代的解决方案。

我的情况:

页面A: [checkout.php]客户填写他们的账单细节。

页面B: [process.php]生成发票号码并在数据库中存储客户详细信息。

页面C: [thirdparty.com]第三支付网关(只接受POST数据)。

客户在页面A中填写详细信息并设置购物车,然后post到页面b。在process.php中,将post数据存储在数据库中并生成发票号码。之后,POST客户数据和发票号码到thirdparty.com支付网关。问题是在页面b中进行POST, cURL能够将数据POST到页面C,但问题是页面没有重定向到页面C。客户需要在页面C中填写信用卡详细信息。

第三方支付网关确实给了我们API样本,样本是POST发票号和客户详细信息。 我们不希望系统生成多余的发票号码。

有什么解决办法吗? 我们目前的解决方案是让客户在页面A中填写详细信息,然后在页面B中创建另一个页面,显示那里的所有客户详细信息,用户可以单击确认按钮以POST到页面C。

我们的目标是让客户只需点击一次。

希望我的问题很清楚:)


当前回答

我有另一个解决方案。它要求客户端运行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
  }
});

其他回答

试试这个:

在页面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

你可以让PHP做一个POST,但是你的PHP会得到返回,有各种各样的复杂情况。我认为最简单的是让用户执行POST。

就像你说的,你会得到这部分:

客户在页面A中填写详细信息,然后在页面B中创建另一个页面,显示所有的客户详细信息,单击确认按钮,然后POST到页面C。

但你可以在页面B上提交javascript,所以不需要点击。让它成为一个带有加载动画的“重定向”页面,你就完成了。

/**
  * 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");
  }
}

我知道这是一个老问题,但我有另一个解决方案与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字段,最后提交。页面将转发到附加POST数据的表单目标页面。

p.s.在这种情况下需要JavaScript和jQuery。正如其他答案的注释所建议的那样,您可以使用<noscript>标记来创建一个标准的HTML表单,以防JS被禁用。

您可以使用会话保存$_POST数据,然后检索该数据并在后续请求中将其设置为$_POST。

用户向/dirty- submit -url.php提交请求 做的事:

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

然后浏览器重定向到服务器并从服务器请求/clean- submit -url。您将有一些内部路由来确定如何处理这个问题。 在请求的开始,你将做:

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

现在,通过请求的其余部分,您可以像访问第一个请求一样访问$_POST。