是否可以使用 PHP 重定向发送 POST 数据?

Is it possible to send POST data with a PHP redirect?

更新:这不是 How do I send a POST request with PHP? 的副本。那里的解决方案对我不起作用,它们只是输出请求的结果,我不想这样做,我想将用户发送到外部站点,它是信用卡支付处理的安全网站。

更新 2:我在下面添加了一张图表,试图清楚地解释我要做什么

这是我正在尝试做的事情:

  1. 一个 html 表单被提交到一个 php 脚本

  2. php脚本对数据进行一些处理,然后通过POST请求向外部网站提交数据

  3. 我不想在我的 PHP 脚本中接收 POST 请求的结果,相反我只想将用户发送到他们看到的外部站点POST

  4. 的结果

我认为 curl 不适合这项任务,因为我对接收返回的请求结果不感兴趣,我只想将用户发送到下一个站点,就像他们直接提交表单一样.

换句话说,我想将表单提交到外部网站,但我想先将其提交到我自己的脚本,以便我可以处理数据并发送电子邮件通知,然后再提交到外部网站添加了一些新的计算数据。

我能想到的一种方法是将新表单输出作为隐藏字段与 javascript 一起输出到 auto-submit 表单,但必须有一种更直接、更可靠的方法在不依赖 javascript 的情况下做到这一点。也许通过操纵 headers,或者也许已经有一个 php 函数来简单地提交一个 post 请求并重定向到结果?

在我看来,您正在尝试从一个页面重定向到另一个页面,同时发送 POST 数据。恐怕 PHP.

是不可能的

我能想到的最简单的解决方法是使用 cURL (1) 将您的 $_POST 数据转发到另一台服务器,(2) 从该服务器接收结果,然后 (3 ) 做一个简单的重定向到另一个页面。虽然它总共需要 3 个 HTTP 请求(对于这样一个简单的问题来说有点多),但它或多或少地实现了您想要实现的目标。


让我将此方法分解为您在问题中提到的三个步骤:

对于步骤 1,任何 HTML 表单都可以,只要它具有值为 "post" 的 "method" 属性。如果您想在不使用 JavaScript 的情况下提交表单,只需确保它有一个 "submit" 按钮即可。当按下提交按钮时,这会将您的数据提交到表单的 "action" 属性中定义的页面:

示例HTML:

<form action="action_page.php" method="post">
    First name:<br />
    <input type="text" name="firstname" value="Mickey"><br />

    Last name:<br />
    <input type="text" name="lastname" value="Mouse" /><br /><br />

    <input type="submit" value="Submit" />
</form>

对于第 2 步,您需要创建一个名称与表单的 "action" 属性值相同的页面。在我们的示例中,这将是 action_page.php。在这里,您检查 $_POST 是否包含您提交的表单字段的任何值。在本例或我们的示例中,您可以这样:

if (isset($_POST['firstname']) && isset($_POST['lastname'])) {
    // Do the stuff you want to do on your own server here!
} else {
    // Do nothing here!
}

对于第 3 步,您需要使用刚刚从 [=71] 收到的 $_POST 数据发出第二个 POST 请求=] 形式。最简单的方法是使用 cURL。然后,根据第二个 POST 请求的输出,将用户重定向到第二个页面。

为了提高示例代码的可读性,我把所有与cURL-request相关的代码都放到了一个函数中:

function forwardRequest($url, $data) {
    $result = [
        'status' => NULL,
        'last_url' => NULL,
        'response' => NULL
    ];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    $result['response'] = curl_exec($ch);
    $result['status'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $result['last_url'] = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
    curl_close ($ch);
    return $result;
}

if (isset($_POST['firstname']) && isset($_POST['lastname'])) {
    // Do the stuff you want to do on your own server here!

    $result = forwardRequest("http://www.example.com/processdata.php", $_POST);

    if ($result['status'] === 200) {
        header('Location: http://www.example.com/ok.php');
    } else {
        header('Location: http://www.example.com/error.php');
    }
} else {
    header('Location: http://www.example.com/youshouldnotbehere.php');
}

注1:

恐怕没有通用的方法来确定在向外部系统提交数据时是否一切正常。

在我的示例代码中,我使用了您的 cURL 请求收到的响应的 HTTP status code。如果服务器出现问题,此解决方案仅在服务器 returns 状态代码不等于 200 时才有效。您将需要 运行 进行一些测试,看看这种方法是否足以满足您的用例。

如果您无法使用状态代码来确定是否一切顺利,请考虑检查最后一个有效 URL 或在您的回复 header 和您的回复文本中寻找线索。


注2:

在处理完您的 cURL 请求后,您可能不想转发您的用户,您可能只想显示从服务器到您的用户的响应文本。如果此结果包含大量您不需要的垃圾,请考虑使用 DOMDocument::loadHTML 或第三方库(如 Masterminds/html5-php or PHPPowertools/DOM-Query)解析结果。

您也可以编写自己的自定义回复文本。

简答:

  • POST 到外部服务器
  • 解析响应
  • 不要回显任何东西
  • 使用header('Location: url?param=res');
  • 退出; //这有点重要

I do not want to receive the result of the POST request in my PHP script, instead I just want to send the user to the external site where they see the result of the POST

如果您从 PHP 脚本发送 POST 请求,那么响应将始终返回到相同的 PHP 脚本。我认为您想要的不是将此响应发送回用户,而是将用户重定向到另一个 URL。为此,您确保自己正在做。

header('Location: url?param=res') ;
exit ;

并且在 header() 调用之前不向客户端发送任何内容

您只能post表单提交时的值

action = "path/filename.php";

在此表单中,您可以 post 表单值。

如果您当时想重定向文件,您可以通过 URL

传递值
header('Location: url/filename.php?param1=      ');

为您想要 post.

的本地文件值尝试此操作

首先您需要从表单中分配值,然后使用变量重新定位 header。这可能是我这边的正确解决方案。 谢谢。

长话短说:不,不可能使用 PHP

One way I can think of doing this is to output the new form output as hidden fields along with javascript to auto-submit the form ...

这是唯一的方法。


该问题可能与 PHP Redirect with POST data 重复。


作为 suicide solution, you may consider to use HTTP 307 - Temporary Redirect.
来自上面链接的 HTTP/1.1 文档:

If the 307 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

我的粗体只是简单的强调一下,没有用户确认的重定向其实是依赖于浏览器对协议的实现。

重定向可以在接收 POST 请求的 PHP 脚本中实现,如下所示*:

header('HTTP/1.1 307 Temporary Redirect');
header('Location: <your page in an external site>');

基本用法示例:

page1.html - 包含表单

的页面
<html>
  <body>
    <form method="POST" action="page2.php">
      <input name="variable1" />
      <input name="variable2" />
      <input type="submit" />
    </form>
  </body>
</html>

page2.php - 重定向前处理您的 POST 数据的页面

<?php

if (isset($_POST['variable1']) && isset($_POST['variable2'])) {

  //do your processing stuff

  header('HTTP/1.1 307 Temporary Redirect');
  header('Location: page3.php');

  exit;
} else
    echo 'variable1 and variable2 are not set';

page3.php POST 数据必须重定向到的页面(即 外部站点 )

<?php

if (isset($_POST['variable1']) && isset($_POST['variable2'])) {

    foreach ($_POST as $key=>$val)
        echo $key . ' = ' . $val . '<br>';

} else
    echo 'variable1 and variable2 are not set';

* 不要在家里尝试这个!

这是不可能的,因为页面已完全加载,POST 请求有可能出现空数据,而不是在需要时使用此创建会话,并在使用该会话后销毁会话. 第二个是 CURL 的用法。

你的描述中有很好的计划。为什么你不生成 new POST request to 3 page with edited data on your page 2 after formatting? You can test your new POST requst with Chrome extension Postman

我为您提供了一个解决方案,它可以在 99% 或 100% 的时间内正常工作,具体取决于您的实施方式。您需要做的就是使用 AJAX 处理表格。我知道您想要一种 Javascript 免费的方式来执行此操作,但这是最简单的方式。如果您使用 jQuery 库,文档和 SO 答案很容易理解,您不必编写太多代码。只是修改一些。这是概念:

1) 页面正常加载,表单操作指向支付处理网站。由于您正在使用 Javascript (jQuery) 提交表单,因此您会像这样替换提交按钮 html:

<input type="button" value="Check Out" onclick="NameofAjaxFunctionHere();"

2) 交换表单操作值。在实际的 AJAX 代码将在后台发送表单进行处理之前,使用类似于此代码的内容将操作更改为您自己的 PHP 页面:

 $('#formIdHere').attr('action', 'yourPHPpageAndPathHere.php');

此代码适用于 jQuery,但如果需要,应该很容易更改为普通 JavaScript。现在还要确保您的 AJAX 代码不会重置表单。许多复制和过去的代码都会为您做这件事。

3) (可选)在此阶段,表单已发送到您的 PHP 页面,您已完成所需的操作。您现在有两个选择:

  • 不要等待回复,直接转到第 4 条。
  • 等待响应并做出相应反应 + 根据需要更改数据

如果您需要确保数据正确或需要更改其中的某些数据,请立即进行。如果表单数据未能通过您的流程(例如更改的数据),则发回 FALSE 并继续执行第 4 步。如果您需要更改内容,这是一个简单的流程。发回数组中需要更新的所有数据,并在启动此过程的相同 AJAX 代码中循环遍历它。使用 Javascript 您可以更改表单值。

[Code missing because I think you can figure this out if you need to do that. If not comment and when I have time I will post an example]

4) 换回表单操作。您的 AJAX 处理已完成。传统上它会擦除表单并显示一条消息。如果您从上面选择发送 FALSE 的选项以在出现错误数据时停止提交,那么现在 AJAX 脚本中的 return false(可能会在 return 之前显示一些内容,说表格未发送)。

 $('#formIdHere').attr('action', 'paymentUrlHere');

既然付款 URL 已经恢复到位并且所有数据都已更新(如果您需要走那条路),请像往常一样(或将)提交表格。在 jQuery 这可以很简单:

 $('#formIdHere').submit();

我认为这涵盖了它。此时,用户已脱离您的控制,并以正常 POST 被发送到支付处理网站。如果需要,您甚至有机会更改表单中的数据。

OH PS - 这就是我在本 post 开头所说的 99% 和 100% 方式。 100% 是我在这里给你的例子。没有人可以先将表格发送到您自己的 PHP 页面。 99% 的解决方案是在页面中正常提交 html,如下所示:

<input type="submit" ...>

然后使用 Javascript 停止默认提交操作并按照我的步骤 1-4 进行操作。这样,如果有人禁用 javascript(或在阻止它的设备上),表单至少仍会发送到支付处理器。由你决定你想做什么。

无法使用 PHP。

但是您可以使用此调整,在 http://example.com/script.php 中,您可以编写一些 javascript 带有校验和的自动提交代码。例如。

<body onload="document.frm1.submit()">   
<form method="POST" action="https://gatewaysite.com" name="frm1">
  <input name="checksum" value="yourchecksumvalue" />
  <input name="variable2" />
</form>
</body>

如果您是这两个网站的所有者,那么您可以只在每个 .htacess 文件中包含这些网站,该文件将保持加密状态。

这两个站点的资格都是 SSL CA。

在您的 .htaccess 中,您可以通过以下方式执行此操作: 这在站点#1 的 htaccess 中添加:

     RewriteCond %{HTTP_REFERER} !^https://www.site2.com/.*$      [NC]
     RewriteCond %{HTTP_REFERER} !^https://www.site2.com$      [NC]

这已添加到站点#2 的 htaccess 中:

     RewriteCond %{HTTP_REFERER} !^https://www.site1.com/.*$      [NC]
     RewriteCond %{HTTP_REFERER} !^https://www.site1.com$      [NC]

然后您可以在站点#1 上使用标准 html 表单,例如:

       <form action="https://wwww.site2.com" method="POST">
在这种情况下可以使用

AJAX。

mysite 上的表单。com/pay 指向 gatewaysite。 在向您提交 运行 一个将调用 script.php 的函数时。 只有script.php确认数据正确,才会提交表单。