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

Aid*_*ran 9 php web-services http httprequest http-redirect

更新:这与如何使用PHP发送POST请求不重复.那里的解决方案对我不起作用,他们只是输出请求的结果,我不想这样做,我想把用户发送到外部网站,它是用于信用卡支付处理的安全网站.

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

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

  1. 将html表单提交给php脚本

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

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

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

换句话说,我希望将表单提交到外部网站,但我想首先将其提交到我自己的脚本,这样我就可以处理数据并发送电子邮件通知,然后使用一些新的计算数据向外部网站提交添加.

我可以想到这样做的一种方法是将新表单输出作为隐藏字段与javascript一起输出以自动提交表单,但必须有一种更直接,更健壮的方式来完成它而不依赖于javascript.也许通过操纵标题,或者可能已经有一个PHP函数来简单地提交一个帖子请求并重定向到结果?

我想做什么

fan*_*cco 8

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

我可以想到这样做的一种方法是输出新表单输出作为隐藏字段以及javascript以自动提交表单...

这是唯一的方法.


问题是PHP重定向可能与POST数据重复.


作为自杀解决方案,您可以考虑使用HTTP 307 - 临时重定向.
从上面链接的HTTP/1.1文档:

如果收到307状态代码以响应GET或HEAD以外的请求,则用户代理不得自动重定向请求,除非用户可以确认,因为这可能会改变发出请求的条件.

我的大胆只是强调没有用户确认的重定向实际上取决于浏览器的协议实现.

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

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

基本用法示例:

page1.html - 包含表单的页面

<html>
  <body>
    <form method="POST" action="page2.php">
      <input name="variable1" />
      <input name="variable2" />
      <input type="submit" />
    </form>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

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';
Run Code Online (Sandbox Code Playgroud)

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';
Run Code Online (Sandbox Code Playgroud)

*不要在家尝试这个!

  • @Adam不幸的是OP你是对的:在我看来,最好的解决方案仍然是javascript提交 (2认同)

Joh*_*ers 7

在我看来,你正在尝试从一个页面重定向到另一个页面,同时发送POST数据.我担心PHP无法做到这一点.

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


让我把这个方法分解为你在问题中提到的三个步骤:

对于第1步,任何HTML表单都可以,只要它具有值为"post"的"method"属性即可.如果您想在不使用JavaScript的情况下提交表单,请确保它有一个"提交"按钮.这将在按下提交按钮时将您的数据提交到表单"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>
Run Code Online (Sandbox Code Playgroud)

对于第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!
}
Run Code Online (Sandbox Code Playgroud)

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

为了提高示例代码的可读性,我将与cURL请求相关的所有代码放入一个函数中:

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');
}
Run Code Online (Sandbox Code Playgroud)

注1:

我担心没有通用的方法来确定数据提交到该系统时外部系统上是否一切顺利.

在我的示例代码中,我使用了cURL请求收到的响应的HTTP状态代码.只有当服务器在该服务器上出现问题时返回不等于200的状态代码时,此解决方案才有效.您需要运行一些测试以查看此方法是否足以满足您的用例.

如果您无法使用状态代码确定一切是否顺利,请考虑检查最后一个有效的网址,或在您的回复标题和您的回复文字中查找线索.


笔记2 :

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

您也可以编写自己的自定义响应文本.


Bli*_*gle 5

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

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

<input type="button" value="Check Out" onclick="NameofAjaxFunctionHere();"
Run Code Online (Sandbox Code Playgroud)

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

 $('#formIdHere').attr('action', 'yourPHPpageAndPathHere.php');
Run Code Online (Sandbox Code Playgroud)

此代码适用于 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]
Run Code Online (Sandbox Code Playgroud)

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

 $('#formIdHere').attr('action', 'paymentUrlHere');
Run Code Online (Sandbox Code Playgroud)

现在,付款 URL 已恢复原状,并且所有数据均已更新(如果您需要采用该路线),请像平常应该(或将)那样提交表单。在 jQuery 中,这可以很简单:

 $('#formIdHere').submit();
Run Code Online (Sandbox Code Playgroud)

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

哦 PS - 这就是我在这篇文章开头所说的 99% 和 100% 方式的意思。100%就是我在这里给你的例子。没有人可以在不先将表单发送到您自己的 PHP 页面的情况下发送该表单。99% 的解决方案是在页面中正常提交 html,如下所示:

<input type="submit" ...>
Run Code Online (Sandbox Code Playgroud)

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