Thursday, 16 August 2012

Implement PayPal's Instant Payment Notification IPN with .NET

PayPal's Instant Payment Notification (IPN) allows you to program your back-end operations to automate transactions when you receive payments from your customers. As of this initial writing, no samples on the entire searchable Internet have illustrated how this simple task can be done with the .NET Framework. If you are already familiar with the background of PayPal, then jump right to the .NET code.
Background
Whenever purchases are made through PayPal by a customer, PayPal uses IPN to post the transaction information to a resource that you specify:
Example (Fake Url): https://www.myserver.com/PayPal/PaymentNotification.aspx
Once your resource receives the post, you must complete five steps:
  1. Notification Validation
    In this step, your job is to post the data that was posted to you back to PayPal. This ensures that the original post indeed came from PayPal, and is not sort of fraud. In the data that you post back, you must append the "cmd=_notify-validate" value to the POST string. Once the data is posted back to PayPal, PayPal will respond with a string of either "VERIFIED" or "INVALID". "VERIFIED" means that PayPal sent the original post, and that you should continue your automation process as part of the transaction. "INVALID" means that PayPal did not send the original post, and it should probably be logged and investigated for possible fraud.
  2. Payment Status Check
    In this step, you should check that the "payment_status" form field is "Completed". This ensures that the customer's payment has been processed by PayPal, and it has been added to the seller's account.
  3. Transaction Duplication Check
    In this step, you should check that the "txn_id" form field, transaction ID, has not already been processed by your automation system. A good thing to do is to store the transaction ID in a database or file for duplication checking. If the transaction ID posted by PayPal is a duplicate, you should not continue your automation process for this transaction. Otherwise, this could result in sending the same product to a customer twice.
  4. Seller Email Validation
    In this step, you simply make sure that the transaction is for your account. Your account will have specific email addresses assigned to it. You should verify that the "receiver_email" field has a value that corresponds to an email associated with your account.
  5. Payment Validation
    As of now, this step is not listed on other sites as a requirement, but it is very important. Because any customer who is familiar with query strings can modify the cost of a seller's product, you should verify that the "payment_gross" field corresponds with the actual price of the item that the customer is purchasing. It is up to you to determine the exact price of the item the customer is purchasing using the form fields. Some common fields you may use to lookup the item being purchased include "item_name" and "item_number". To see for yourself, follow these steps:
  • Click on a button used to purchase one of your products.
  • Locate the "payment_gross" field in the query string and change its value.
  • Use the changed URL and perform a re-request, typically by hitting [ENTER] in the browser Address Bar.
  • Notice the changed price for your product on the PayPal order page.

public class PaymentNotification : System.Web.UI.Page
{
  // This helper method encodes a string correctly for an HTTP POST
  private string Encode(string oldValue)
  {
    string newValue = oldValue.Replace("\"", "'");
    newValue = System.Web.HttpUtility.UrlEncode(newValue);
    newValue = newValue.Replace("%2f", "/");
    return newValue;
  }
  
  private void Page_Load(object sender, System.EventArgs e)
  {
    // Step 1a: Modify the POST string.
    string formPostData = "cmd = _notify-validate";
    foreach (String postKey in Request.Form)
    {
      string postValue = Encode(Request.Form[postKey]);
      formPostData += string.Format("&{0}={1}", postKey, postValue);
    }
    
    // Step 1b: POST the data back to PayPal.
    WebClient client = new WebClient();
    client.Headers.Add("Content-Type","application/x-www-form-urlencoded");
    byte[] postByteArray = Encoding.ASCII.GetBytes(formPostData);
    byte[] responseArray = client.UploadData("https://www.paypal.com/cgi-bin/webscr", "POST", postByteArray);
    string response = Encoding.ASCII.GetString(responseArray);
    
    // Step 1c: Process the response from PayPal.
    switch (response)
    {
      case "VERIFIED":
      {
        // Perform steps 2-5 above. // Continue with automation processing if all steps succeeded.
        break
        ;
      }
      default:
      {
        // Possible fraud. Log for investigation.
        break;
      }
    }
  }
}

No comments:

Post a Comment