16

Update: This is NOT a duplicate of How do I send a POST request with PHP?. The solutions there don't work for me, they just output the result of the request, I don't want to do this, I want to send the user to the external site, it is secure website for credit card payment processing.

Update 2: I've added a diagram below to try and clearly explain what I'm trying to do

Here's what I'm trying to do:

  1. a html form is submitted to a php script

  2. the php script does some processing on the data and then submits data via POST request to an external website

  3. 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

I'm thinking curl is not suitable for this task as I'm not interested in receiving the result of the request back, I just want to send the user to the next site just as if they submitted the form directly.

To put this another way, I want to submit a form to an external website but I want to submit it to my own script first so I can process the data and send email notifications and then submit onwards to the external website with some new calculated data added.

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 but there has got to be a more straightforward, robust way to do it without relying on javascript. Maybe by manipulating headers, or maybe there is already a php function to simply submit a post request and redirect to the result?

What I'm trying to do

John Slegers
  • 45,213
  • 22
  • 199
  • 169
AidanCurran
  • 2,460
  • 5
  • 20
  • 24
  • possible duplicate of [How do I send a POST request with PHP?](http://stackoverflow.com/questions/5647461/how-do-i-send-a-post-request-with-php) – CaldwellYSR Sep 04 '15 at 01:11
  • This might help you: http://community.sitepoint.com/t/send-post-values-with-header-location/38750 – kojow7 Sep 04 '15 at 01:13
  • @CaldwellYSR - solutions there don't work for me, they just output the result of the request, I don't want to do this, I want to send the user to the external site, it is secure for credit card payment processing – AidanCurran Sep 04 '15 at 03:03
  • @kojow7 - that doesn't work for me either, I'm sending data to an external secure website and I want to use POST, not GET – AidanCurran Sep 04 '15 at 03:08
  • 2
    I wonder why my question is being down-voted, is it a stupid question? is it unclear? – AidanCurran Sep 04 '15 at 03:09
  • 1
    Can you use fsockopen? http://php.net/manual/en/function.fsockopen.php – kojow7 Sep 04 '15 at 04:27
  • 1
    @kojow7 - not sure how that would help. I basically just want to submit a form and redirect the user to the result. I can do it by outputting the form and Javascript to auto-submit it but I figure there must be a more direct way to do it without involving Javascript – AidanCurran Sep 04 '15 at 04:33
  • JavaScript is the direct way of doing it. To do it with PHP the information has to first be sent to your server from the form and then sent to the secure server. With JavaScript you cut your server out of the equation. – CaldwellYSR Sep 04 '15 at 07:17
  • @CaldwellYSR - I think you have a misunderstanding of what I'm trying to do, I NEED to send it to server first as I have to process it on the server side and add in more data, before I submit it on to the external site. – AidanCurran Sep 04 '15 at 08:16
  • Please help me by up-voting this question to counteract the 4 people that have down-voted it which unfortunately causes other stackoverflow members to ignore it resulting in me not getting the answer I need. I think I have been clear in describing the issue and I have searched for an answer but the answers I have found such as cURL and file_get_contents() are not suitable in my case. – AidanCurran Sep 04 '15 at 08:23
  • @AidanCurran I would still use Javascript to make an Ajax request to your server and send the new data to the external server but if you are dead set on avoiding that there might be some solutions to be found here: http://www.lornajane.net/posts/2010/three-ways-to-make-a-post-request-from-php – CaldwellYSR Sep 04 '15 at 14:34
  • I might have to resort to Javascript, it seems like such a hack way to do it though. The solutions at the lornajane link (curl and Pecl_Http) will not work for my situation, they do not redirect the user to external website. This question - http://stackoverflow.com/questions/17148266/php-post-redirect-with-curl-same-as-html-form - asks if it's possible to do the redirect with Curl but it appears it is not possible. It should be possible to write the headers to do a post request though, anyone know how to do that? – AidanCurran Sep 06 '15 at 21:23
  • @AidanCurran In my opinion JavaScript is an only way to complete your task. You can't submit form from server and redirect user to an answer! This is impossible in fact of HTML is statless and you probably wont be able to pass session from external server to a clinet. I would post this form to your server, recalculated the data and return JS code to auto - post to target. OR even more "not tricky" display a summary with hidden form and "confirm" button that will post to external server. – WebHQ Sep 11 '15 at 12:29
  • I wonder why you want the user to completely move out of your domain, you need to get the response from payment gateway and display appropriate information to the user. In that case you should clearly wait for response. I believe there are possible code snippets with payment gateway to deal with it. All the best – art-fan-vikram Sep 11 '15 at 19:15
  • @Vikram It's because credit card details are entered on a secure page provided by payment gateway – AidanCurran Sep 13 '15 at 21:40
  • Could you just make a POST to your handler file (using ajax), verify eveything is correct, let the browser know, browser than posts data to external site? (only works if the external site has some kind of way of knowing what site to return to). –  Sep 14 '15 at 01:54
  • What about rebuilding the modified POST request and using php header() to build the request? I havent tested, but in theory it should be possible to post to your script.php and then post on again, rather than attempting to simply adjust the post mid request (not possible without some form of JS interception). I will test and post an answer if it works... – tobynew Sep 14 '15 at 10:07
  • See http://stackoverflow.com/questions/3045097/php-redirect-and-send-data-via-post/3045155 – symcbean Sep 14 '15 at 17:45
  • There is no solution that does not use Javascript or Curl. Your going to have to choose one. Javascript is the most flexable and Curl is the easiest to implement. That is all you can do with POST data. As you've seen GET is a different story but we know you can't use it. – Blizzardengle Sep 14 '15 at 21:09

10 Answers10

12

Long story short: no, it's not possibile using 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 ...

It's the only way to do it.


The question is a possible duplicate of PHP Redirect with POST data.


As a suicide solution, you may consider to use HTTP 307 - Temporary Redirect.
From the HTTP/1.1 documentation linked above:

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.

My bold simply emphasizes that the redirect without the user confirmation actually depends on the browser's implementation of the protocol.

The redirect can be implemented in the PHP script which receives the POST request as follows*:

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

Basic usage Example:

page1.html - the page which contains the form

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

page2.php - the page which processes your POST data before redirect

<?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 the page to which the POST data has to be redirected (i.e. the external site)

<?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';

&ast; don't try this at home!

Community
  • 1
  • 1
fantaghirocco
  • 4,761
  • 6
  • 38
  • 48
  • 1
    Good point for pointing 307 redirection as a solution. But this wont permit modification – Adam Sep 14 '15 at 11:41
  • 2
    @Adam unfortunately for the OP you're right: in my opinion the best solution still remains javascript submission – fantaghirocco Sep 14 '15 at 11:57
8

It seems to me that you're trying to do a redirect from one page to another, while sending along POST data. I'm afraid that's not possible with PHP.

The simplest workaround I can think of, is using cURL to (1) forward your $_POST data to another server, (2) receive the result from that server and then (3) do a simple redirect to another page. While it requires a total of 3 HTTP requests (a bit much for such a simple problem), it does more or less achieve what you're trying to achieve.


Let me break this approach down to the three steps you mentioned in your question :

For step 1, any HTML form would do, as long as it has a "method" attribute with the value "post". If you want to submit the form without using JavaScript, just make sure it has a "submit" button. That will submit your data to the page defined in the "action" attribute of your form when the submit button is pressed :

Example 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>

For step 2, you'll need to create a page with a name identical to the value of the "action" attribute of your form. In the case of our example, that would be action_page.php. Here, you check if $_POST contains any values for the form fields you submitted. In the case or our example, you could so something like this :

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

For step 3, you'll need to make a second POST request, using the $_POST data you just received from your HTML form. The simplest way to do that, would be using cURL. Then, you redirect your user to a second page, depending on the output of your second POST request.

To improve the readability of the example code, I put all code related to the cURL-request into a function :

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

Note 1 :

I'm afraid there is no generic way to determine whether or not everything goes well on an external system whenever data is submitted to that system.

In my example code, I'm using the HTTP status code of the response received by your cURL request. This solution only works whenever the server returns a status code that is not equal to 200 if something goes wrong on that server. You will need to run some tests to see if this approach is sufficient for your use case.

If you can't use the status code to determine whether everything went well or not, consider checking the last effective URL or look for clues in your response header & your response text.


Note 2 :

Instead of forwarding your user after your cURL request has been processed, you might just want to show the response text from the server to your user. If this result contains a lot of junk you don't need, consider parsing the result using DOMDocument::loadHTML or third party library (like Masterminds/html5-php or PHPPowertools/DOM-Query).

You could also just write your own custom response text.

John Slegers
  • 45,213
  • 22
  • 199
  • 169
  • Thanks for your answer John. However I don't think the redirect part in step 3 will work because I don't want to do a simple redirect. The external website is a secure credit card payment processing page so one cannot simply redirect to it using header(), it needs to follow the POST request. – AidanCurran Sep 08 '15 at 21:39
  • "It seems to me that you're trying to do a redirect from one page to another, while sending along POST data." This is correct. "I'm afraid that's not possible with PHP." It is possible to send a GET request with redirect so why can't it be possible to send POST request with redirect? – AidanCurran Sep 08 '15 at 22:18
  • @AidanCurran : Get requests put their data in the request URL. Redirects allow you to move to another and pass along data in the URL. Post requests put their data in the request body, which cannot be passed along to other pages that easily. – John Slegers Sep 08 '15 at 23:10
  • @AidanCurran : I believe this is done on purpose. POST requests are supposed to be more secure than GET requests. – John Slegers Sep 08 '15 at 23:10
  • @AidanCurran : In my code example, you should use the `forwardRequest` function to redirect to your payment processing page. The `header` redirects are only there to redirect to whatever out put you want, and are optional, as explained in the notes at the bottom! – John Slegers Sep 08 '15 at 23:13
  • I tried out your code anyway just to confirm my understanding of what happens and I have confirmed that this solution will not work. I cannot simply do a redirect to the payment processing page. The request for the payment processing page must be accompanied with the required POST data. Your forwardRequest function returns a result that is an array containing [status], [last_url] and [response]. I cannot simply display the response on my own page as this has to be a secure page for collecting credit card details. Am I missing something? – AidanCurran Sep 09 '15 at 00:16
  • @AidanCurran : You did not mention you need to collect credit card details or have your user interact in any other way on the other server. In that case, I'm afraid you'll need to use clientside JavaScript to modify your fields before sending them to the payment processing page. – John Slegers Sep 09 '15 at 00:34
  • 1
    I've given the bounty to this answer because even though the cURL workaround will not work for my situation and the only solution is to use JavaScript which I was originally attempting to avoid, I appreciate the amount of effort that was put into the answer. – AidanCurran Sep 14 '15 at 21:16
5

I have one solution for you that will work either 99% of the time or 100% of the time depending on how you implement it. All you need to do is process the form with AJAX. I know you want a Javascript free way of doing this but it is the simplest way. If you use the jQuery library the documentation and SO answers are so easy to follow you wound not have to write much code. Just modify some. Here is the concept:

1) Page loads as normal with the forms action pointing to the payment processing website. Since you are using Javascript (jQuery) to submit the form you would have replaced the submit buttons html like so:

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

2) Swap out the forms action value. Before the actual AJAX code that will send the form behind the scenes to be processed, use something similar to this code to change the action to your own PHP page:

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

This code is for jQuery but it should be easy to change to plain JavaScript if you need. Now also make sure your AJAX code does not reset the form. Many copy and past codes kindly do this for you.

3) (Optional) At this stage the form has been sent to your PHP page and you are done doing what you need to with it. You now have two options:

  • Do not wait for a response and just go on to number 4.
  • Wait for a response and react accordingly + change data if needed

If you need to make sure the data was correct or need to alter some of it do that now. If the forms data fails your process (altered data for example) send back a FALSE and move on to number 4. If you need to change things that is a simple process. Send back all the data that needs updating in an array and loop through it in the same AJAX code that started this process. Using Javascript you can change the forms values.

[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) Swap back the forms action. Your AJAX processing is done. Traditionally it wipes the form and displays a message. If you choose the option from above that sends a FALSE to stop submission in case there was bad data, just return false from the AJAX script now (maybe display something before that return saying the form was not sent).

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

Now that the payment URL is back in place and any data was updated if you need to go that route, submit the form like it normally should (or would) be. IN jQuery this can be as simple as:

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

And I think that covers it. At this point the user is out of your hands and was sent to the payment processing website with a normal POST. You even had the chance to alter data from the form if needed.

OH PS - Here is what I meant about the 99% and 100% way at the start of this post. 100% is the example I gave you here. No one can send the form without making it to your own PHP page first. The 99% solution would be to but the normal submit html in the page like so:

<input type="submit" ...>

Then using Javascript stop the default submit action and follow my steps 1-4. That way if someone disables javascript (or is on a device that blocks it) the form still sends to the payment processor at least. Up to you what you want to do.

Blizzardengle
  • 992
  • 1
  • 17
  • 30
  • I should point out, using this concept you can send the form to several pages. If you felt like it you could send it to 10 different PHP scripts before actually submitting it to the payment site. You still can only redirect the user ONCE with the data though. POST does this for security. It seems you have only two choices. Javascript or PHP's Curl. – Blizzardengle Sep 14 '15 at 02:59
3

Short answer :

  • POST to external server
  • parse response
  • do not echo out anything
  • use header('Location: url?param=res') ;
  • exit ; //this is kind of important

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

If you are sending a POST request from a PHP script, then the response will ALWAYS come back to the same PHP script. I think what you want is NOT to send this the response back to the user, but instead redirect the user to a another URL. For which you make sure you are doing.

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

and not sending anything to the client before the header() call

gyaani_guy
  • 3,191
  • 8
  • 43
  • 51
  • The comment I made to John's answer also applies here - I can't simply do a redirect to a credit card payment processing page, the page needs to be requested with a POST request. I could easily do a GET request using header('Location: url?field1=vlaue1&field2=value2&field3=value3'). Is there some way to do a redirect and send POST data along with it? – AidanCurran Sep 08 '15 at 21:45
3

you are only can post the values at the time of the form submission

action = "path/filename.php";

in this form you can post the form values.

if you want to redirect the file at the time you can able to pass the values via the URL

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

try this for a local file values which you want to post.

first you need to assign the values from the form, then you relocate header with the variables. that's may be the right solution from my side. thank you.

Sathish Kumar D
  • 274
  • 6
  • 20
2

it's not possibile using PHP.

But you can use this tweak, In http://example.com/script.php you can write some javascript auto submit code with the checksum. E.g.

<body onload="document.frm1.submit()">   
<form method="POST" action="https://gatewaysite.com" name="frm1">
  <input name="checksum" value="yourchecksumvalue" />
  <input name="variable2" />
</form>
</body>
Malay M
  • 1,659
  • 1
  • 14
  • 22
1

Its not possible,beacuase the page loaded entirely,there is a chance with empty data with POST request,instead of using this create Sessions when ever required,and after usage of that session just destroy the session. And the second one is usage of CURL .

1

You have excellent plan in you description. Why you just don't generate 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

Community
  • 1
  • 1
Oleg Sapishchuk
  • 667
  • 6
  • 18
  • By 'generate new POST request' you mean output a html form and auto submit it with Javascript? I'm not familiar with Postman but if it's just for testing I probably don't need it as I have a test environment to work with. – AidanCurran Sep 13 '15 at 21:32
  • Auto submit or use curl. My opinion is that there are no, such clear and `best practices` method for this solution. I would better write helper or library for such issue and don't look so darkly on rest ideas. Anyway good luck with resolving this issue. – Oleg Sapishchuk Sep 14 '15 at 16:16
0

AJAX could be use in this case.

The form on mysite.com/pay points to gatewaysite. On submit you run a function which will call script.php. Only if script.php confirms that the data is correct, the form will be submitted.

-1

If you are the owner of both websites, then you can just include the sites in each .htacess file, that will remain encypted.

The qualifications for this is SSL CA on both sites.

in your .htaccess, you do this by: this added in site#1's htaccess:

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

this added in site#2's htaccess:

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

Then you can use a standard html form on site#1 like:

       <form action="https://wwww.site2.com" method="POST">
drtechno
  • 298
  • 2
  • 9