ASP.NET PayPal Control for Website Payments Standard
Online Documentation.

Skip Navigation Links.

Handling Instant Payment Notification (IPN)

If you are not familiar with PayPal IPN, please visit this page for learning about Post Payment Notifications  before proceed to this documentation.

As you know, IPN provides immediate notification and confirmation of PayPal payments you receive. Using IPN, you receive a notification in the following cases: 

  • When a payment is first sent, indicating that the status of the payment is Completed or Pending.
  • When a payment clears, fails, or is denied, if the status was pending.

The Payment Button Controls (BuyNow Button, Donation Button, Subscription Button, Upload Complete Cart Button but NOT the Add to Cart Button) are designed such a way so that, IPN can be handled like handling an event of a standard asp.net control. You wont have to worry about any settings in your PayPal profile. Only you need to make sure that you have a PayPal premier or business account rather than just a personal account. So, if you place an instance of  BuyNow Button, Donation Button etc, then you can use the same aspx page to place your IPN handling logic and this design pattern gives you the flexibility to use a single aspx page for managing all of your eCommerce related business logics. In order to start, simply attach an event handler method to the IPN_Notified event of your Payment Button Control (i.e. BuyNow, Donation etc..) as shown in the following figure.


 

When PayPal calls your aspx page for notifying IPN, your aspx page that holds the control wont render any html to PayPal as PayPal do not need to see your html contents. The control programmatically suppresses all Html contents of the page. Moreover, suppressing html rendering increases the performance and reduces the PayPal postback time.

 

What is the use of IPN ? How to use it ? What to expect from this event ?

IPN can be used to manage and customize a variety of PayPal-enabled APIs and communications, including:

  • Customize your website's response to customer purchases in real-time
  • Track customers via IPN "pass through" variables
  • Deliver access keys for software downloads and other digital goods
  • Automate your fulfillment operations
  • Track affiliate sales and commissions
  • Store transaction information in your own database

Please note: IPN_Notified event is a non visual event. The customer will not see the IPN_Notified event being fired. It is fired in the background. PayPal notifies your website asynchronously. So, do not perform any User Interface related task in the IPN_Notified event handler. For example, do not set any TextBox Text value or Label's Text property etc UI related tasks as the UI is never visible to your customer. The PayPal_Returned  event is specialized for this purpose like UI related tasks. Although there is no harm in getting and setting UI Control Properties in IPN_Notified event, but it will be useless. Because, PayPal asynchrnously calls your website and it is *PayPal* who sees the IPN_Notified event being fired and this *see*ing is happened in the background. As PayPal does not need to understand any of your page's UI as it only expects the "200 ok" http status from your website and nothing else, this control supress all HTML rendering when the IPN_Notified event fires.

 Usually IPN_Notified event is fired as soon as the payment is completed while your customer is in the PayPal website. Once your customer comes back to your website, the PayPal_Returned  event is fired. So, we can assume that, any stored information (in your database) which was stored in the IPN session is ready to be retrieved (from your database) in the PayPal_Returned event. So, in PayPal_Returned event, you can show your customer a summary of tasks done in IPN_Notified event.

 

When the IPN_Notified event is fired, all transaction information becomes available as strongly typed objects (categorized collection of composite properties and collections) through the Event Argument Class.

Please note: when you are using SpiceLogic PayPal control, you are not limited to receive only PayPal provided transaction data. You can pass unlimited data from your Payment Button which will not be even sent to PayPal, rather it will be saved in your server and when IPN_Notified event is fired, you will be able to retrieve those data. Please visit the page for Passing Additional Data Items  for more details.

There are cases when you may not want to use the same Button hosting page to be your IPN handler page. Specially when you are using ADD TO CART Button you must use a dedicated page for handling IPN. In order to point a different page to be your IPN handler, please Click Here  to learn about Handling IPN from a dedicated page .

 

Practicing Mediator Design Pattern:

If you have many Payment Buttons (i.e. BuyNow button, Donation Button etc..) in a same page, then you can use a common IPN_Notified event handler for all of the button's IPN_Notified Event. But, if you have many Payment Buttons in your web applications where those are not in the same page and if you want to centralize all of your IPN related logic in a single method, then you should Handle IPN from a dedicated page .

 

IPN Notification Validation: Preventing Fraud

After your server receives Instant Payment Notification, PayPal requires your site to confirm that your server received it. This is known as notification validation, which is a means for PayPal to help you prevent spoofing or “man-in-the-middle” attacks. When you are using this control, you wont need to worry about this phase. This control sends a POST back to PayPal after it receives the IPN and verify the correctness of the data and an event argument object (e.IPN.Status) holds the result of this validation. You just need to check the value of e.IPN.Status in your IPN_Notified event handler as follows:

if(e.IPN.Status == PayPalIPN.StatusCodes.Verified)
{
   // Verified
}
Once you have checked that the validation result was Verified, you must check the price, transaction ID, PayPal receiver email address and other data sent to you by IPN to ensure that they are correct. By examining these data you can be sure that you are not being spoofed.

When you receive a VERIFIED response, perform the following checks: 

 

  1. Check that the e.PaymentInfo.PaymentStatus is Completed. For example, the following snippet shows the usage.
    if (e.PaymentInfo.PaymentStatus == IPNPDTPaymentInfo.PaymentStatusValues.Completed) 
    {
      // Completed.
    }
  2. If the payment status is Completed, check the e.TransactionID against the previous PayPal transaction you have processed to ensure it is not a duplicate.
  3. After you have checked the e.PaymentInfo.PaymentStatus and e.TransactionID, make sure the e.ReceiverEmail is an email address registered in your PayPal account.
  4. Check that the price, e.PaymentInfo.McGross, and currency, e.PaymentInfo.Mc_Currency, are correct for the item, e.ItemInfo.ItemName or e.ItemInfo.ItemNumber
  5. Once you have completed the above checks, you can update your database based on the information provided and proceed to automating your product delivery procedure.

If you find e.IPN.Status == PayPalIPN.StatusCodes.Invalid, you should investigate. In some cases, this response is caused by an IPN error, possibly from a change in the IPN format. To determine if it is an IPN error, first examine your code.

 

How to Test IPN ? Is it possible to test the IPN feature right from my localhost (or Desktop Computer) ?

In a word, you CANNOT test IPN right from your development environment unless your development environment got a public domain which is accessible from outside world using a browser. What does it mean ? Well, as we explained, IPN is a Server to Server Communication. When a transaction request is made from your browser to PayPal server, the control will also notify paypal about your url of the page where the BuyNow button is hosted. PayPal will send notification to that page but, notice, when you are testing from your environment, you got an url like, http://localhost/xxxxxx.aspx ..... Right ? Is this url http://localhost/xxxxxx.aspx accissible from outside your PC ? NO, right ? So, when PayPal receives the transaction request, PayPal will send IPN to the url http://localhost/xxxxxx.aspx and as usual, PayPal will not find this url and the IPN will be lost. You will see that your IPN_Notified event is not being fired. So, in order to test IPN, you do need to upload your test page to your production server where your payment button hosting page got a real URL which is accessible by public. This problem is not prominent for all other feature of this control. You can test anything else of this control right from your localhost. Just the IPN is tricky. This limitation is not there for testing PDT though. You can test PDT right from your localhost.

 

How to Debug IPN ?

Again, in order to debug IPN, you must upload your test page to a public domain server (your production server) where you got a real URL for your button page which is accessible by outside world (so that PayPal server can access that page). As you understood that, IPN is an asynchronous event, which is exposed only to the IPN sender (PayPal) and so, you cannot set a breakpoint on your IPN_Notified event handler method and step through the lines. You may use Debug / Trace methods to log the messages within your IPN_Notified event handler method. The IPN_Notified Event argument object's IPN.ToString() method is overriden and it contains a set of useful information like what was the raw string posted to your server as IPN, which string was sent back to PayPal (or IPN sender) server, what was the Http status code received after sending back the data to IPN for verification etc. Here is a sample ToString() value returned by e.IPN.ToString() from the IPN_Notified Event Argument Object of a BuyNow button.

How to get this string ? Ok, handle the IPN_Notified event and in your event handler method, assign the value of e.IPN.ToString() to a string type variable. Then, you may email that string value to yourself or store that to your database or any of your WRITE PERMISSION given folder in your server as a text file. The following snippet shows the usage:

protected void BuyNowButton1_IPN_Notified(object sender, BuyNowIPNNotifiedEventArgs e)

{

    string ipnDebugData = e.IPN.ToString();

    File.WriteAllText(MapPath(string.Format("~/MyLogDir/ipn_{0}.txt", e.TransactionID)), ipnDebugData);

}

You can also get the data in parts by dedicated properties. For example, e.IPN.Status will give you the enumerated status code. e.IPN.OriginalRawData will give you the original unmodified IPN data posted by PayPal (or the IPN sender) etc.

In order to access the specific variable string data (for both IPN & PDT) received by PayPal, you can use a NameValueCollection type event argument property named "PostedData". For example, you can get the Payment date as strongly typed object like this : DateTime paymentDate = e.PaymentDateTime; but if you want to see what was the actual string for "payment_date" variable posted by PayPal in case you are suspecting that you are getting wrong data. So the following snippet will give you the exact string for the PayPal variable "payment_date"

string PayPal_Posted_DateTime_String = e.PostedData["payment_date"];

Also, if you want to get a value of a new ipn data which is not available from this control's IPN_Notified event argument object (it is highly unlikely unless the ipn version is updated very recently by PayPal and our development team took some time to synchronize our control with that ipn version. Also we may find some undocumented and unimportant variables introduced recently which is not included in the IPN_Notified event argument object. For example, we did not find 'protection_eligibility' variable important to include to the type safe list of properties as it is not even well documented by PayPal.), you can get that value from e.PostedData NameValueCollection like this:

string ProtectionEligibility = e.PostedData["protection_eligibility"];

 

Membership users, please note:

If you are using ASP.NET Memberhsip feature in your website, then, you need to allow PayPal to see your page where you placed your IPN_Notified event handler code. That meanst, if you are handling IPN_Notified event right from your Payment button (BuyNow button, Donation button etc), then, the page that hosts your Payment button should be visible to all. If you are Handling IPN from a dedicated page  then, your IPN handler page should be accessible to all users. Assume that you hosted your BuyNow button at "Products/Purchase.aspx" page. Then, you need to add the following section to you web.config file.

If you do not permit paypal to post IPN to your page, then, you will find that IPN_Notified event is not being fired.

By this time, I hope you already realized that, IPN is a different SESSION created by PayPal to your website and this SESSION is not the same SESSION created by your customer to your website. Since any asp.net designer wanting to set up a site where users pay a membership fee to join, would very likely want to put a user in a Role on IPN_Notified event handler method. It will be a common mistake if you assume that the Customer is logged in as a member in the IPN SESSION.  So, how would you pass the username of the Customer to the IPN_Notified event so that you can write code to add your customer in a paid member role by the customer's user name ? Yes, we have designed a very special property named "Additional Data Items". This is a Dictionary type property which can be populated either in design time or programmatically. So, you can pass your customer's username by Additional Data Items to the Payment Button and you can access that data right from IPN_Notified event handler method. Once you retrieve that user name of the customer from Additional Data Item, you can add him/her to your paid member role. In order to learn about Additional Data Items, please visit this page .

 

Code Example:

Hosting Trust Level issue:

Please note: Although we tried as much as possible to make this control compatible with Medium Trust Configuration hosting, yet In order to handle IPN, you must have FULL TRUST level configuration in your hosting. If you do not have FULL TRUST configuration, then you will always get

   e.IPN.Status == PayPalIPN.StatusCodes.Communication_Error

 

Explanation: 

In the notification validation process, the control sends a POST back to PayPal after it receives the IPN and verify the correctness of the data. In order to post to a website, the component needs to call one of the method from the WebClient class library available from System.Net namespace.

Now, executing WebClient class methods requires Full Trust configuration in the hosting and if you do not have full trust configuration, then not only using this control, but also you cannot get any status code using any other control at all.

But, but, if you got any solution about calling a website from the web application in medium trust level, simply let us know and we will modify our control to make it compatible with medium trust hosting and offer you a FREE developer license for this control.

SSL Not Required for IPN

Because credit card and bank information is not transmitted in Instant Payment Notification (IPN), PayPal does not require Secure Sockets Layer (SSL) to encrypt IPN transmissions. 

Still Confused ?

If you are still confused, please check the sample application that comes with the setup.exe file you have downloaded from our website. Also please do not hesitate to ask us as many questions as you want from our Help Desk