首页 文章

使用POST数据进行PHP重定向

提问于
浏览
206

我做了一些关于这个主题的研究,有些专家说过它不是possible,所以我想问一个替代解决方案 .

我的情况:

页面A:[checkout.php]客户填写其结算明细 .

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

页面C:[thirdparty.com]第三个支付网关(仅接受发布数据) .

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

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

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

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

希望我的问题很清楚:)

8 回答

  • 182

    在页面B上生成一个表单,将所有必需的数据和操作设置为页面C,并在页面加载时使用JavaScript提交 . 您的数据将被发送到Page C而不会给用户带来太多麻烦 .

    这是唯一的方法 . 重定向是一个303 HTTP标头,您可以在http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html上阅读,但我会引用其中一些:

    可以在不同的URI下找到对请求的响应,并且应该使用该资源上的GET方法检索 . 此方法主要用于允许输出POST激活的脚本以将用户代理重定向到选定的资源 . 新URI不是最初请求的资源的替代引用 . 303响应绝不能被缓存,但对第二个(重定向)请求的响应可能是可缓存的 .

    实现您正在做的事情的唯一方法是使用将用户发送到Page 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的用户能够使用您的服务 .

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

    我有另一个解决方案,使这成为可能 . 它要求客户端运行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
      }
    });
    
  • -1

    $ _SESSION是你的朋友,如果你不想搞乱Javascript,并且可以安全一点 .

    假设您正在尝试传递电子邮件:

    在第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>";
    
  • 21

    我知道这是一个老问题,但我还有另一个使用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数据的表单目标页面 .

    附:这种情况需要JavaScript和jQuery . 正如其他答案的评论所暗示的那样,如果禁用JS,您可以使用 <noscript> 标签创建标准HTML表单 .

  • 5

    你可以让PHP做一个POST,但是你的php会得到回报,带来各种各样的复杂情况 . 我认为最简单的方法是让用户真正做POST .

    那么,你建议的那种,你会得到这个部分:

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

    但您实际上可以在页面B上执行javascript提交,因此无需单击 . 使用加载动画将其设为“重定向”页面,然后进行设置 .

  • 5

    有一个简单的黑客,使用 $_SESSION 并创建一个 array 的已发布值,一旦你去 File_C.php 你可以使用它然后你进行处理后销毁它 .

  • 33
    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'});
    

相关问题