title: Paypal IPN keeps failing, what am I doing wrong?
body: <p>I've been trying to make this thing work since last Friday.
  I'm working with a C# asp.net 4.5 project, and Paypal example codes only have MVC and .net CORE examples, both of which I'm not familiar that much.</p>
  
  <p>I've done very little MVC programming. So I decided to bite the bullet and I built a separate MVC project and added a controller with the following code:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Collections.Specialized;
  using System.IO;
  using System.Net;
  using System.Text;
  using System.Threading.Tasks;
  using System.Web;
  using System.Web.Mvc;
  
  namespace paypal_ipn.Controllers
  {
      public class IPNlistenerController : Controller
      {
          // GET: IPNlistener
          public ActionResult Index()
          {
              return Receive();
          }
  
          [HttpPost]
          public HttpStatusCodeResult Receive()
          {
              //Store the IPN received from PayPal
              LogRequest(Request);
  
              //Fire and forget verification task
              Task.Run(() =&gt; VerifyTask(Request));
  
              //Reply back a 200 code
              return new HttpStatusCodeResult(HttpStatusCode.OK);
          }
  
          private void VerifyTask(HttpRequestBase ipnRequest)
          {
              ShantMailer.SendEmail("my@email.com", "IPN MVC called", "yup");
              var verificationResponse = string.Empty;
  
              //Post back to either sandbox or live
              string strSandbox = "https://ipnpb.sandbox.paypal.com/cgi-bin/webscr";
              string strLive = "https://ipnpb.paypal.com/cgi-bin/webscr";
              string strRequest= string.Empty;
              try
              {
                  var verificationRequest = (HttpWebRequest)WebRequest.Create(strSandbox);
                  //Set values for the verification request
                  verificationRequest.Method = "POST";
                  verificationRequest.ContentType = "application/x-www-form-urlencoded";
                  var param = Request.BinaryRead(ipnRequest.ContentLength);
                  strRequest = Encoding.ASCII.GetString(param);
  
                  //Add cmd=_notify-validate to the payload
                  strRequest = "cmd=_notify-validate&amp;" + strRequest;
                  verificationRequest.ContentLength = strRequest.Length;
  
                  //Attach payload to the verification request
                  var streamOut = new StreamWriter(verificationRequest.GetRequestStream(), Encoding.ASCII);
                  streamOut.Write(strRequest);
                  streamOut.Close();
  
                  //Send the request to PayPal and get the response
                  var streamIn = new StreamReader(verificationRequest.GetResponse().GetResponseStream());
                  verificationResponse = streamIn.ReadToEnd();
                  streamIn.Close();
  
              }
              catch (Exception ex)
              {
                  string nvcs = "Name Value Pairs: &lt;br/&gt;";
                  try
                  {
                      NameValueCollection these_argies = HttpUtility.ParseQueryString(strRequest);
                      foreach (string s in these_argies)
                          foreach (string v in these_argies.GetValues(s))
                              nvcs += s + ": " + v + "&lt;br/&gt;";
                  }
                  catch { }
                  ShantMailer.SendError(ex.Message + "&lt;br/&gt;&lt;br/&gt;" + ex.InnerException + "&lt;br/&gt;&lt;br/&gt;" + ex.StackTrace + "&lt;br/&gt;&lt;br/&gt;" + nvcs + "&lt;br/&gt;&lt;br/&gt;Request: " + strRequest + "&lt;br/&gt;&lt;br/&gt;Response: " + verificationResponse);
  
                  //Capture exception for manual investigation
              }
  
              ProcessVerificationResponse(verificationResponse, strRequest);
          }
  
  
          private void LogRequest(HttpRequestBase request)
          {
              // Persist the request values into a database or temporary data store
          }
  
          private void ProcessVerificationResponse(string verificationResponse, string strRequest)
          {
              if (verificationResponse.Equals("VERIFIED"))
              {
                  ShantMailer.SendEmail("my@email.com", "IPN", strRequest + " &lt;br&gt;&lt;br&gt;&lt;br&gt; " + verificationResponse);
                  // check that Payment_status=Completed
                  // check that Txn_id has not been previously processed
                  // check that Receiver_email is your Primary PayPal email
                  // check that Payment_amount/Payment_currency are correct
                  // process payment
              }
              else if (verificationResponse.Equals("INVALID"))
              {
                  ShantMailer.SendEmail("my@email.com", "IPN", strRequest + " &lt;br&gt;&lt;br&gt;&lt;br&gt; " + verificationResponse);
                  //Log for manual investigation
              }
              else
              {
                  //Log error
              }
          }
      }
  }
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/CWijg.png" rel="nofollow noreferrer">My solution explorer looks like this</a></p>
  
  <p>Now, when I call the page from my browser I see the HttpResponse 200 in the Chrome developer console (Network tab)</p>
  
  <p>And as you see I've even included checkpoints in my code that sends me email notifications for debugging purposes. I'm getting the "IPN MVC Called" email when I load the page myself in the browser. But when I give it to the IPN Simulator, Paypal keeps saying "IPN was not sent, and the handshake was not verified. Review your information."</p>
  
  <p>Paypal is not consistent in their documentation, some pages say use "<a href="https://ipnpb.paypal.com/cgi-bin/webscr" rel="nofollow noreferrer">https://ipnpb.paypal.com/cgi-bin/webscr</a>" and in their code samples it's "<a href="https://www.paypal.com/cgi-bin/webscr" rel="nofollow noreferrer">https://www.paypal.com/cgi-bin/webscr</a>"</p>
  
  <p>Or for sandbow "<a href="https://ipnpb.sandbox.paypal.com/cgi-bin/webscr" rel="nofollow noreferrer">https://ipnpb.sandbox.paypal.com/cgi-bin/webscr</a>" vs their code example "<a href="https://www.sandbox.paypal.com/cgi-bin/webscr" rel="nofollow noreferrer">https://www.sandbox.paypal.com/cgi-bin/webscr</a>"</p>
  
  <p>In any case, I have tried all possible combinations and still not sure what's wrong.</p>
  
  <p>This is where my listener is hosted: <a href="https://www.shantwebdesign.com/paypal_ipn/IPNlistener/Index/" rel="nofollow noreferrer">https://www.shantwebdesign.com/paypal_ipn/IPNlistener/Index/</a></p>
  
  <p>Any help or lead with this is greatly appreciated.
  Thank you</p>