5
\$\begingroup\$

I'm using a payment gateway and am trying to implement the post and response handling with CURL so that it all happens on one page.

The following is tested and works but I want to double check it's secure. I'm not storing the card details but I'm essentially posting them to myself (via AJAX) and then curling that through to the gateway. I can't AJAX post it directly to the gateway because of cross domain restrictions.

So, this all happens in https://mysite.com/payment.php:

HTML

<form method="post" action="https://mysite.com/payment.php">
    <input type="hidden" name="Amount" value="1.00">

    <!-- fingerprint is a hash of my gateway passwords and fields on this form -->   
    <input type="hidden" name="Gateway_Fingerprint" value="<?php echo $fingerprint ?>"> 
    <input type="hidden" name="Gateway_ReturnURL" value="https://mysite.com/payment.php">
    <input type="hidden" name="Card_Number" value="">
</form>


PHP

// when payment form is submitted
if(isset($_POST['Card_Number'])){

   // CURL the data to payment gateway
   foreach($data as $key => $value){ 
       $fields .= $key . '=' . $value . '&'; 
   }

   rtrim($fields, '&');

   $post = curl_init();

   curl_setopt($post, CURLOPT_VERBOSE, true);
   curl_setopt($post, CURLOPT_URL, 'https://gatewayurlhere');
   curl_setopt($post, CURLOPT_POST, count($data));
   curl_setopt($post, CURLOPT_POSTFIELDS, $fields);
   curl_setopt($post, CURLOPT_RETURNTRANSFER, 1);

   $result = curl_exec($post);

   // output result from gateway as JSON
   header('Content-Type: application/json');

   echo $result;

   curl_close($post);

   exit();
} 

// result returned from gateway, this will be the CURL result data
if(isset($_POST['restext']))
{
   echo json_encode($_POST);
   exit();
}
\$\endgroup\$
  • \$\begingroup\$ Is the Gateway_Fingerprint unique? or is it the same over all requests? \$\endgroup\$ – Pinoniq Jun 25 '13 at 13:53
  • \$\begingroup\$ It's a hash of the gateway password, amount ($), timestamp and our merchant ref. That said I should probably add it to the post data before curling instead of putting in the form. \$\endgroup\$ – user138341 Jun 25 '13 at 22:00
  • \$\begingroup\$ You simply should. You are sending data to the client it shouldn't know about in the first place. \$\endgroup\$ – Pinoniq Jun 25 '13 at 22:29
5
\$\begingroup\$

Well, security from what type of threat? You need to figure out what you want to protect against before you can protect against it! Since I'm unsure of what you're protecting against, I'll point out relevant setopt flags.

  • CURLOPT_VERBOSE - This is fine for a developer, but make sure the client doesn't see this returned information. It could lead to a possible exploit. More on the output later on.
  • CURLOPT_POST - You're using this incorrectly. The value should be true or an alternate HTTP POST.
  • CURLOPT_RETURNTRANSFER - Using 1 does result in TRUE, but it's easier to read if the explicit boolean is used.

Here are some flags you may way to consider in order to help secure this connection even more. Each can be found in the docs.

  • bool CURLOPT_FAILONERROR - Just in case the page you fetch is "out of order".
  • bool CURLOPT_FORBID_REUSE - Force the connection to close on finish, and prevent the reuse of a connection. Also see bool CURLOPT_FRESH_CONNECT.
  • Make sure you keep bool CURLOPT_SSL_VERIFYPEER set to TRUE.
  • int CURLOPT_TIMEOUT - Timeout if the connection takes too long.
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.