stymiee

Handling Online Payments Part 2 - Reading In And Sanitizing Submitted Data

by All Star ‎01-13-2011 07:26 PM - edited ‎10-20-2011 09:59 AM (8,560 Views)

This is part two of a multi-part series on handling online payments.

 

In Part I of this series we identified our goals (creating a payment form that was usable, accessible, and secure) and began by creating the form we will use to capture payment information. We're going to continue this process by exploring how we will handle the data submitted by that form.

 

There are three parts of handling user submitted information. They are:

 

  • Reading In And Sanitizing Submitted Data

    Before we can do anything with the information sent to us we need to receive the information and place them into variables to be used later in our code. This is also a good place to remove unwanted information that may or may not have been included.

  • Validating The Information

    Once we receive the user submitted information we need to make sure we have everything we are looking for and that it in a format that we expect.

  • Collecting And Displaying Errors

    If the information submitted to us is invalid or missing information we need to collect a list of what errors we found and display them to the user in a friendly and easy to understand format.

 

In this blog post we're going to focus on reading in and sanitizing user data.

 

The code below uses the HTML form we created in Part I of this series. Be sure to have that handy as we will continue to build upon it as this series continues.

 

Reading In And Sanitizing Submitted Data

 

This is probably the simplest portion of handling a form submission but is not well understood or handled by many developers. As the point of entry for user submitted data this is the perfect place to begin ensuring our code is secure. The first mistake many PHP developers make is to use the $_REQUEST superglobal variable to receive form submissions. As you will remember we explicitly created our form to send all form data via POST. PHP allows us to specifically look only for data submitted via POST with the $_POST superglobal. By using $_POST instead of $_REQUEST we remove the possibility of an attacker submitting form information using GET. This isn't a huge security issue but since we can easily prevent these kinds of attacks and abuse simply by using $_POST instead of $_REQUEST we would be remiss not to do so.

 

Here's an example of reading in a submission from our form using $_POST. It goes at the very top of the page where you have your form. You'll notice that we explicitly check that a form submission has been made using POST using the PHP superglobal $_SERVER['REQUEST_METHOD']. This is how we'll know the form has been submitted and not just the page being loaded for the first time.

 

<?php
    if ('POST' === $_SERVER['REQUEST_METHOD'])
    {
        $credit_card           = $_POST['credit_card'];
        $expiration_month      = $_POST['expiration_month'];
        $expiration_year       = $_POST['expiration_year'];
        $cvv                   = $_POST['cvv'];
        $cardholder_first_name = $_POST['cardholder_first_name'];
        $cardholder_last_name  = $_POST['cardholder_last_name'];
        $billing_address       = $_POST['billing_address'];
        $billing_address2      = $_POST['billing_address2'];
        $billing_city          = $_POST['billing_city'];
        $billing_state         = $_POST['billing_state'];
        $billing_zip           = $_POST['billing_zip'];
        $telephone             = $_POST['telephone'];
        $email                 = $_POST['email'];
        $recipient_first_name  = $_POST['recipient_first_name'];
        $recipient_last_name   = $_POST['recipient_last_name'];
        $shipping_address      = $_POST['shipping_address'];
        $shipping_address2     = $_POST['shipping_address2'];
        $shipping_city         = $_POST['shipping_city'];
        $shipping_state        = $_POST['shipping_state'];
        $shipping_zip          = $_POST['shipping_zip'];
    }
?>

 

Although we have successfully received the form submission we should sanitize the information before we try to use it. There are three things we should lookout for and handle at this stage:

 

  • White Space

    White space before or after data, although meaningless to human eyes, make all the difference to computers. " hi " does not equal "hi" to a computer. So if you're searching your data base for "hi" but it is stored as " hi " you will have difficulty finding that record. Fortunately it is easy to ensure that our data does not have extraneous white space attached to it. PHP's built in trim() function removes leading and trailing white space for us automatically.

  • HTML

    I may not have travelled the world as extensively as some people but I have yet to meet or hear of a person who has HTML code in their name or address. None of the information we will be collecting in our form should ever have HTML included in it. So it would be a good idea to remove it before we even begin to examine it. This is where PHP's built in strip_tags() function comes in handy. It removes unwanted HTML from variables, and strings, and returns a "clean" string for us.

  • Numbers Should Always Be Number

    Some information is always expected to be a number. The expiration date's year is a good example of that. In cases like this we can cast information into a data type of our choosing, in this case an integer. We have a couple of different ways of doing this. One is to place (int) to the right of the assignment operator (=) when assigning the value to a variable. Another is to use PHP's built in intval() function.

 

Here's the same code as above but with our sanitation efforts included:

 

<?php
    if ('POST' === $_SERVER['REQUEST_METHOD'])
    {
        $credit_card           = trim(strip_tags($_POST['credit_card']));
        $expiration_month      = (int) trim(strip_tags($_POST['expiration_month']));
        $expiration_year       = (int) trim(strip_tags($_POST['expiration_year']));
        $cvv                   = trim(strip_tags($_POST['cvv']));
        $cardholder_first_name = trim(strip_tags($_POST['cardholder_first_name']));
        $cardholder_last_name  = trim(strip_tags($_POST['cardholder_last_name']));
        $billing_address       = trim(strip_tags($_POST['billing_address']));
        $billing_address2      = trim(strip_tags($_POST['billing_address2']));
        $billing_city          = trim(strip_tags($_POST['billing_city']));
        $billing_state         = trim(strip_tags($_POST['billing_state']));
        $billing_zip           = trim(strip_tags($_POST['billing_zip']));
        $telephone             = trim(strip_tags($_POST['telephone']));
        $email                 = trim(strip_tags($_POST['email']));
        $recipient_first_name  = trim(strip_tags($_POST['recipient_first_name']));
        $recipient_last_name   = trim(strip_tags($_POST['recipient_last_name']));
        $shipping_address      = trim(strip_tags($_POST['shipping_address']));
        $shipping_address2     = trim(strip_tags($_POST['shipping_address2']));
        $shipping_city         = trim(strip_tags($_POST['shipping_city']));
        $shipping_state        = trim(strip_tags($_POST['shipping_state']));
        $shipping_zip          = trim(strip_tags($_POST['shipping_zip']));
    }
?>

 

Tip: A good idea would be to combine trim() and strip_tags() into one function. This makes it easier to reuse this code and makes your code cleaner and easier to maintain. Be sure to use trim() last as stripping HTML may cause white space to be added to a value.

<?php
    function sanitize($value)
    {
        return trim(strip_tags($value));
    }

    // sample usage

    $credit_card = sanitize($_POST['credit_card']);
?>

Our Form Page So Far

 

Here is a our form with our new code thus far added to it:

 

<?php
    if ('POST' === $_SERVER['REQUEST_METHOD'])
    {
        $credit_card           = sanitize($_POST['credit_card']);
        $expiration_month      = (int) sanitize($_POST['expiration_month']);
        $expiration_year       = (int) sanitize($_POST['expiration_year']);
        $cvv                   = sanitize($_POST['cvv']);
        $cardholder_first_name = sanitize($_POST['cardholder_first_name']);
        $cardholder_last_name  = sanitize($_POST['cardholder_last_name']);
        $billing_address       = sanitize($_POST['billing_address']);
        $billing_address2      = sanitize($_POST['billing_address2']);
        $billing_city          = sanitize($_POST['billing_city']);
        $billing_state         = sanitize($_POST['billing_state']);
        $billing_zip           = sanitize($_POST['billing_zip']);
        $telephone             = sanitize($_POST['telephone']);
        $email                 = sanitize($_POST['email']);
        $recipient_first_name  = sanitize($_POST['recipient_first_name']);
        $recipient_last_name   = sanitize($_POST['recipient_last_name']);
        $shipping_address      = sanitize($_POST['shipping_address']);
        $shipping_address2     = sanitize($_POST['shipping_address2']);
        $shipping_city         = sanitize($_POST['shipping_city']);
        $shipping_state        = sanitize($_POST['shipping_state']);
        $shipping_zip          = sanitize($_POST['shipping_zip']);
    }

    function sanitize($value)
    {
        return trim(strip_tags($value));
    }
?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
        <head>
            <title>Payment Form</title>
            <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
            <meta http-equiv="Content-Language" content="en-us">
        </head>
        <body>
            <form action="/payment-form.php" method="post">
                <p>
                    <label for="credit_card">Credit Card Number</label>
                    <input type="text" name="credit_card" id="credit_card" autocomplete="off" maxlength="19" value="">
                </p>
                <p>
                    <label for="expiration_month">Expiration Date</label>
                    <select name="expiration_month" id="expiration_month">
                        <option value="0"> </option>
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                        <option value="4">4</option>
                        <option value="5">5</option>
                        <option value="6">6</option>
                        <option value="7">7</option>
                        <option value="8">8</option>
                        <option value="9">9</option>
                        <option value="10">10</option>
                        <option value="11">11</option>
                        <option value="12">12</option>
                    </select>
                    <select name="expiration_year" id="expiration_year">
                        <option value="0"> </option>
                        <option value="2010">2010</option>
                        <option value="2011">2011</option>
                        <option value="2012">2012</option>
                        <option value="2013">2013</option>
                        <option value="2014">2014</option>
                        <option value="2015">2015</option>
                        <option value="2016">2016</option>
                        <option value="2017">2017</option>
                        <option value="2018">2018</option>
                        <option value="2019">2019</option>
                        <option value="2020">2020</option>
                        <option value="2021">2021</option>
                    </select>
                </p>
                <p>
                    <label for="cvv">Security Code</label>
                    <input type="text" name="cvv" id="cvv" autocomplete="off" value="" maxlength="4">
                </p>
                <p>
                    <label for="cardholder_first_name">Cardholder's First Name</label>
                    <input type="text" name="cardholder_first_name" id="cardholder_first_name" maxlength="30" value="">
                </p>
                <p>
                    <label for="cardholder_last_name">Cardholder's Last Name</label>
                    <input type="text" name="cardholder_last_name" id="cardholder_last_name" maxlength="30" value="">
                </p>
                <p>
                    <label for="billing_address">Billing Address</label>
                    <input type="text" name="billing_address" id="billing_address" maxlength="45" value="">
                </p>
                <p>
                    <label for="billing_address2">Suite/Apt #</label>
                    <input type="text" name="billing_address2" id="billing_address2" maxlength="45" value="">
                </p>
                <p>
                    <label for="billing_city">City</label>
                    <input type="text" name="billing_city" id="billing_city" maxlength="25" value="">
                </p>
                <p>
                    <label for="billing_state">State</label>
                    <select id="billing_state" name="billing_state">
                        <option value="0"> </option>
                        <option value="AL">Alabama</option>
                        <option value="AK">Alaska</option>
                        <option value="AZ">Arizona</option>
                        <option value="AR">Arkansas</option>
                        <option value="CA">California</option>
                        <option value="CO">Colorado</option>
                        <option value="CT">Connecticut</option>
                        <option value="DE">Delaware</option>
                        <option value="DC">District Of Columbia</option>
                        <option value="FL">Florida</option>
                        <option value="GA">Georgia</option>
                        <option value="HI">Hawaii</option>
                        <option value="ID">Idaho</option>
                        <option value="IL">Illinois</option>
                        <option value="IN">Indiana</option>
                        <option value="IA">Iowa</option>
                        <option value="KS">Kansas</option>
                        <option value="KY">Kentucky</option>
                        <option value="LA">Louisiana</option>
                        <option value="ME">Maine</option>
                        <option value="MD">Maryland</option>
                        <option value="MA">Massachusetts</option>
                        <option value="MI">Michigan</option>
                        <option value="MN">Minnesota</option>
                        <option value="MS">Mississippi</option>
                        <option value="MO">Missouri</option>
                        <option value="MT">Montana</option>
                        <option value="NE">Nebraska</option>
                        <option value="NV">Nevada</option>
                        <option value="NH">New Hampshire</option>
                        <option value="NJ">New Jersey</option>
                        <option value="NM">New Mexico</option>
                        <option value="NY">New York</option>
                        <option value="NC">North Carolina</option>
                        <option value="ND">North Dakota</option>
                        <option value="OH">Ohio</option>
                        <option value="OK">Oklahoma</option>
                        <option value="OR">Oregon</option>
                        <option value="PA">Pennsylvania</option>
                        <option value="RI">Rhode Island</option>
                        <option value="SC">South Carolina</option>
                        <option value="SD">South Dakota</option>
                        <option value="TN">Tennessee</option>
                        <option value="TX">Texas</option>
                        <option value="UT">Utah</option>
                        <option value="VT">Vermont</option>
                        <option value="VA">Virginia</option>
                        <option value="WA">Washington</option>
                        <option value="WV">West Virginia</option>
                        <option value="WI">Wisconsin</option>
                        <option value="WY">Wyoming</option>
                    </select>
                </p>
                <p>
                    <label for="billing_zip">Zip Code</label>
                    <input type="text" name="billing_zip" id="billing_zip" maxlength="5" value="">
                </p>
                <p>
                    <label for="telephone">Telephone Number</label>
                    <input type="text" name="telephone" id="telephone" maxlength="20" value="">
                </p>
                <p>
                    <label for="email">Email Address</label>
                    <input type="text" name="email" id="email" maxlength="20" value="">
                </p>
                <p>
                    <label for="recipient_first_name">Recipient's First Name</label>
                    <input type="text" name="recipient_first_name" id="recipient_first_name" maxlength="30" value="">
                </p>
                <p>
                    <label for="recipient_last_name">Recipient's Last Name</label>
                    <input type="text" name="recipient_last_name" id="recipient_last_name" maxlength="30" value="">
                </p>
                <p>
                    <label for="shipping_address">Shipping Address</label>
                    <input type="text" name="shipping_address" id="shipping_address" maxlength="45" value="">
                </p>
                <p>
                    <label for="shipping_address2">Suite/Apt #</label>
                    <input type="text" name="shipping_address2" id="shipping_address2" maxlength="45" value="">
                </p>
                <p>
                    <label for="shipping_city">City</label>
                    <input type="text" name="shipping_city" id="shipping_city" maxlength="30" value="">
                </p>
                <p>
                    <label for="shipping_state">State</label>
                    <select id="shipping_state" name="shipping_state">
                        <option value="0"> </option>
                        <option value="AL">Alabama</option>
                        <option value="AK">Alaska</option>
                        <option value="AZ">Arizona</option>
                        <option value="AR">Arkansas</option>
                        <option value="CA">California</option>
                        <option value="CO">Colorado</option>
                        <option value="CT">Connecticut</option>
                        <option value="DE">Delaware</option>
                        <option value="DC">District Of Columbia</option>
                        <option value="FL">Florida</option>
                        <option value="GA">Georgia</option>
                        <option value="HI">Hawaii</option>
                        <option value="ID">Idaho</option>
                        <option value="IL">Illinois</option>
                        <option value="IN">Indiana</option>
                        <option value="IA">Iowa</option>
                        <option value="KS">Kansas</option>
                        <option value="KY">Kentucky</option>
                        <option value="LA">Louisiana</option>
                        <option value="ME">Maine</option>
                        <option value="MD">Maryland</option>
                        <option value="MA">Massachusetts</option>
                        <option value="MI">Michigan</option>
                        <option value="MN">Minnesota</option>
                        <option value="MS">Mississippi</option>
                        <option value="MO">Missouri</option>
                        <option value="MT">Montana</option>
                        <option value="NE">Nebraska</option>
                        <option value="NV">Nevada</option>
                        <option value="NH">New Hampshire</option>
                        <option value="NJ">New Jersey</option>
                        <option value="NM">New Mexico</option>
                        <option value="NY">New York</option>
                        <option value="NC">North Carolina</option>
                        <option value="ND">North Dakota</option>
                        <option value="OH">Ohio</option>
                        <option value="OK">Oklahoma</option>
                        <option value="OR">Oregon</option>
                        <option value="PA">Pennsylvania</option>
                        <option value="RI">Rhode Island</option>
                        <option value="SC">South Carolina</option>
                        <option value="SD">South Dakota</option>
                        <option value="TN">Tennessee</option>
                        <option value="TX">Texas</option>
                        <option value="UT">Utah</option>
                        <option value="VT">Vermont</option>
                        <option value="VA">Virginia</option>
                        <option value="WA">Washington</option>
                        <option value="WV">West Virginia</option>
                        <option value="WI">Wisconsin</option>
                        <option value="WY">Wyoming</option>
                    </select>
                </p>
                <p>
                    <label for="shipping_zip">Zip Code</label>
                    <input type="text" name="shipping_zip" id="shipping_zip" maxlength="5" value="">
                </p>
                <p>
                    <input type="submit" value="Checkout">
                </p>
            </form>
        </body>
    </html>

What's Next?

 

Now that we have successfully received and sanitized our form data we can begin the process of validating it to make sure we have everything we need and in a format that we expect. In the next part of this series we will see how to validate this information and bring our form one step closer to reality.

 

The Handling Online Payments Series

 

  1. Part 1 - Basic Information and Our Form
  2. Part 2 - Reading In And Sanitizing Submitted Data
  3. Part 3 - Data Validation
  4. Part 4 - Handling Validation Errors
  5. Part 5 - Processing Payment and Handling the Response
  6. Part 6 - Preventing Duplicate Submissions with POST/REDIRECT/GET
  7. Part 7 - Preventing Automated Form Submissions
  8. Part 8 - Using JavaScript To Increase Usability
  9. Part 9 - HTML and CSS Enhancements
  10. Part 10 - A Little Bit More PHP
---------------------------------------------------------------------------------------------------


John Conde is a certified Authorize.Net developer

About the Author
  • Authorize.Net Developer Community Manager
Announcements
Labels