Search code examples
asp.netasp.net-mvcasp.net-mvc-3paypal-ipnpaypal-sandbox

Difficulty confirming Instant Payment Notification (IPN) from Paypal within an MVC3 Application


I am trying to get Paypal's IPN service working within my app.

When I use the Paypal Sandbox IPN Simulator set to the transaction type of, "Web Accept," Paypal says the message went through just fine (and if I mess up the code in my Action that handles the IPN, Paypal says there was a server error, so this seems to be communicating correctly).

However, it doesn't appear to actually be doing anything. If I navigate to my IPN action in a browser myapp.com/Paypal/IPN, I receive a response from paypal that says INVALID (as expected) and this is written to my output via Debug.Write. When I click "Send IPN" in Paypal's simulator, I get no debug messages at all, although my IPN action is full of Debug.Write lines. (Do calls made from outside your local environment simply not allow Debug.Write output?)

For reference, here is the majority of my IPN Action (I've removed various logic for clarity's sake):

public ActionResult IPN()
{
    Debug.Write("entering ipn action ");
    var formVals = new Dictionary<string, string>();
    formVals.Add("cmd", "_notify-validate");

    string response = GetPayPalResponse(formVals, true);
    Debug.Write("IPN Response received: " + response + " <-- That was response. . . ");

    if (response == "VALID")
    {
        Debug.Write("Response Was Verified");
    }

    else
    {
        Debug.Write("RESPONSE WAS NOT VERIFIED");
    }

    return this.View();
}


string GetPayPalResponse(Dictionary<string, string> formVals, bool useSandbox)
{
    string paypalUrl = useSandbox
                            ? "https://www.sandbox.paypal.com/cgi-bin/webscr"
                            : "https://www.paypal.com/cgi-bin/webscr";

    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(paypalUrl);

    //Set values for the request back
    req.Method = "POST";
    req.ContentType = "application/x-www-form-urlencoded";

    byte[] param = Request.BinaryRead(Request.ContentLength);
    string strRequest = Encoding.ASCII.GetString(param);

    StringBuilder sb = new StringBuilder();
    sb.Append(strRequest);

    foreach (string key in formVals.Keys)
    {
        sb.AppendFormat("&{0}={1}", key, formVals[key]);
    }
    strRequest += sb.ToString();
    req.ContentLength = strRequest.Length;

    string response = "";
    using (StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII))
    {
        streamOut.Write(strRequest);
        streamOut.Close();
        using (StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream()))
        {
            response = streamIn.ReadToEnd();
        }
    }
    return response;
}

Am I correct in understanding that if Paypal is actually submitting a request to my IPN action, I should receive the Debug.Write messages the same as when I visit the IPN action within my browser?

It does not appear to me that anything actually happens when Paypal sends the IPN simulated message to my web application, but Paypal says things are ok and Paypal somehow knows if I intentionally make the IPN action have an error when it is caused (so it appears to actually be calling the action somehow).

Can anyone help me understand what I am not understanding here?

I just want my user's to be able to pay using Paypal's standard payment method with a 'buy now' button and be able to change a database value from false to 'true' when the payment is confirmed to have been received.

Thank you for your time.

Note: Another way I tested this was to have the action change something in my database if it was called (I simply did something like MyEntity.Value = new value then db.SaveAll();. This change to my database was made if I navigated directly to the action within my browser, but no change occurs when I had the paypal IPN simulator 'ping' the action.

Update:

Ok, running trace using trace.axd:

<trace enabled="true" requestLimit="100" pageOutput="false" traceMode="SortByTime" localOnly="false" />

It behaves as if nothing happens when I run the Paypal IPN Simulator or if I browse to my web page using a device that is off my local network.

Note that I do see details change when I visit the pages on my local computer:

8   7/8/2012 6:25:01 PM paypal/ipn  200 GET View Details
9   7/8/2012 6:25:02 PM paypal/themes/ui-lightness/jquery-ui-1.8.19.custom.css  404 GET View Details
10  7/8/2012 6:25:02 PM favicon.ico 404 GET View Details
11  7/8/2012 6:25:52 PM favicon.ico 404 GET View Details
12  7/8/2012 6:26:09 PM home/paypaltest 200 GET View Details

Update 2:

I got the debugger to start debugging by attaching the debugger to : w3wp.exe

It appears that Paypal is indeed making it to my page and responding with VERIFIED at this point when I use the IPN simulator. Not sure what this means for me. Will update.

Update 3:

With debugging working I was able to properly test everything and the IPN verification was actually working as intended - I just couldn't tell without proper debugging messages.

Thank you for your time.


Solution

  • With debugging working I was able to properly test everything and the IPN verification was actually working as intended - I just couldn't tell without proper debugging messages.

    Thank you for your time.