public Hashtable IPN(Hashtable request)
{
Hashtable reply = new Hashtable ();
// Does not matter what we send back to PP here.
reply["int_response_code"] = 200;
// 200 OK
reply["str_response_string"] = "IPN Processed - Have a nice day.";
reply["content_type"] = "text/html";
if (!m_active) {
m_log.Error ("[FreeMoney] Recieved IPN request, but module is disabled. Aborting.");
reply["str_response_string"] = "IPN Not processed. Module is not enabled.";
return reply;
}
Dictionary<string, object> postvals = ServerUtils.ParseQueryString ((string)request["body"]);
string originalPost = (string)request["body"];
string modifiedPost = originalPost + "&cmd=_notify-validate";
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create (m_ppprotocol+"://" + m_ppurl +
m_pprequesturi);
httpWebRequest.Method = "POST";
httpWebRequest.ContentLength = modifiedPost.Length;
StreamWriter streamWriter = new StreamWriter (httpWebRequest.GetRequestStream ());
streamWriter.Write (modifiedPost);
streamWriter.Close ();
string response;
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse ();
using (StreamReader streamReader = new StreamReader (httpWebResponse.GetResponseStream ())) {
response = streamReader.ReadToEnd ();
streamReader.Close ();
}
if (httpWebResponse.StatusCode != HttpStatusCode.OK) {
m_log.Error ("[FreeMoney] IPN Status code != 200. Aborting.");
debugStringDict (postvals);
return reply;
}
if (!response.Contains ("VERIFIED")) {
m_log.Error ("[FreeMoney] IPN was NOT verified. Aborting.");
debugStringDict (postvals);
return reply;
}
// Handle IPN Components
try {
if ((string)postvals["payment_status"] != "Completed") {
m_log.Warn ("[FreeMoney] Transaction not confirmed. Aborting.");
debugStringDict (postvals);
return reply;
}
if (((string)postvals["mc_currency"]).ToUpper () != m_gridCurrencyCode) {
m_log.Error ("[FreeMoney] Payment was made in an incorrect currency (" +
postvals["mc_currency"] + "). Aborting.");
debugStringDict (postvals);
return reply;
}
// Check we have a transaction with the listed ID.
UUID txnID = new UUID ((string)postvals["item_number"]);
FreeMoneyTransaction txn;
lock (m_transactionsInProgress) {
if (!m_transactionsInProgress.ContainsKey (txnID)) {
m_log.Error ("[FreeMoney] Recieved IPN request for Payment that is not in progress. Aborting.");
debugStringDict (postvals);
return reply;
}
txn = m_transactionsInProgress[txnID];
}
// Check user paid correctly...
if (((string)postvals["business"]).ToLower () != txn.SellersEmail.ToLower ()) {
m_log.Error ("[FreeMoney] Expected payment to " + txn.SellersEmail +
" but receiver was " + (string)postvals["business"] + " instead. Aborting.");
debugStringDict (postvals);
return reply;
}
Decimal amountPaid = Decimal.Parse ((string)postvals["mc_gross"]);
if (System.Math.Abs (ConvertAmountToCurrency (txn.Amount) - amountPaid) > (Decimal)0.001) {
m_log.Error ("[FreeMoney] Expected payment was " + ConvertAmountToCurrency (txn.Amount) +
" but received " + amountPaid + " " + postvals["mc_currency"] + " instead. Aborting.");
debugStringDict (postvals);
return reply;
}
// At this point, the user has paid, paid a correct amount, in the correct currency.
// Time to deliver their items. Do it in a seperate thread, so we can return "OK" to PP.
Util.FireAndForget (delegate { TransferSuccess (txn); });
} catch (KeyNotFoundException) {
m_log.Error ("[FreeMoney] Received badly formatted IPN notice. Aborting.");
debugStringDict (postvals);
return reply;
}
// Wheeeee
return reply;
}