PayPal IPN Get Method Using ASP.Net, C#

0

Posted on : 16-03-2006 | By : caroline | In : Search Engine Marketing

Q. How do I take one-time, variable-amount, variable-reason web site payment using PayPal IPN, ASP.Net and C#?
A. Build a StringBuilder URL request and redirect the Response to PayPal.

This answer is the “get” method, because we’re going to redirect the response to PayPal using a query string.

Payment Form: make_payment.aspx
Create a web form that collects user input for:

  • payment purpose
  • amount

Anything else you collect on this form should be saved to the PayPal custom variable as demonstrated below. This data might be the customer’s name, address, email and company name.

protected void btnPay_Click(object sender, EventArgs e)

{ if (!Page.IsValid) { return;}

StringBuilder sbPayPal = new StringBuilder();
StringBuilder custom = new StringBuilder();
custom.Append(Server.UrlEncode(firstname.Text));
custom.Append(" ");
custom.Append(Server.UrlEncode(lastname.Text));
custom.Append(", ");
custom.Append(Server.UrlEncode(this.amount.Text));
custom.Append(",");
custom.Append(Server.UrlEncode(companyname.Text));
custom.Append(",");
custom.Append(Server.UrlEncode(email.Text));
custom.Append(",");
custom.Append(Server.UrlEncode(purpose.Text));
custom.Append(",");
if (sandbox.Checked) { sbPayPal.Append("https://www.sandbox.paypal.com/xclick/business=yoursandbox@emailhere.com");
} else {

// if you use this you'll really be paying me

sbPayPal.Append("https://www.paypal.com/xclick/business=caroline@bogartcomputing.com");}

sbPayPal.Append("&item_name=");
sbPayPal.Append(Server.UrlEncode(purpose.Text));
sbPayPal.Append("&quantity=1");
sbPayPal.Append("&custom=");
sbPayPal.Append(custom.ToString());
sbPayPal.Append("&amount=");
sbPayPal.Append(Server.UrlEncode(amount.Text));
sbPayPal.Append("&invoice=");
sbPayPal.Append(System.Guid.NewGuid().ToString());
sbPayPal.Append("&
nonote=1");
sbPayPal.Append("&no_shipping=1");
sbPayPal.Append("&return=");
sbPayPal.Append("http://bogartcomputing.com/payment_thankyou.aspx");
sbPayPal.Append("&
cancel_return=");
sbPayPal.Append("http://bogartcomputing.com/payment_cancel.aspx");
sbPayPal.Append("notify_url=");
sbPayPal.Append("http://bogartcomputing.com/YOUR_IPN_Form.aspx");
Response.Redirect(sbPayPal.ToString());
Response.Write(Server.UrlDecode(sbPayPal.ToString().Replace("&", " ")));
}

Cancellation Form: payment_cancel.aspx
Create a web form that statically informs the user that the payment was cancelled.

Payment Cancellation Your payment was not processed. Click here to make a payment

Thank You Form: payment_thankyou.aspx
Create a web form that accepts a post (Request.Form) to:

  • display payment details
  • statically inform the customer that he will receive an email when the payment is confirmed

if (Request.Form.Keys.Count>0)

{

try {

lblPaymentDate.Text=FormItem("payment_date");
lblTransactionType.Text= FormItem("txn_type");
lblLastName.Text= FormItem("last_name");
lblResidenceCountry.Text= FormItem("residence_country");
lblItemName.Text= FormItem("item_name");
lblPaymentGross.Text= FormItem("payment_gross");
lblMcCurrency.Text= FormItem("mc_currency");
lblBusiness.Text= FormItem("business");
lblPaymentType.Text= FormItem("payment_type");
lblVerifySign.Text= FormItem("verify_sign");
lblPayerStatus.Text= FormItem("payer_status");
lblTax.Text= FormItem("tax");
lblPayerEmail.Text= FormItem("payer_email");
lblTransactionID.Text= FormItem("txn_id");
lblQuantity.Text= FormItem("quantity");
lblReceiverEmail.Text=FormItem("receiver_email");
lblFirstName.Text= FormItem("first_name");
lblPayerID.Text= FormItem("payer_id");
lblReceiverId.Text= FormItem("receiver_id");
lblMemo.Text= FormItem("memo");
lblItemNumber.Text= FormItem("item_number");
lblPaymentStatus.Text= FormItem("payment_status");
lblPaymentFee.Text= FormItem("payment_fee");
lblMcFee.Text= FormItem("mc_fee");
lblShipping.Text= FormItem("shipping");
lblMcGross.Text= FormItem("mc_gross");
lblCustom.Text= FormItem("custom");
lblPendingReason.Text=FormItem("pending_reason");
lblAddressName.Text=FormItem("address_name");
lblAddressStreet.Text=FormItem("address_street");
lblAddressCity.Text=FormItem("address_city");
lblAddressStatus.Text=FormItem("address_status");
lblAddressState.Text=FormItem("address_state");
lblAddressZip.Text=FormItem("address_zip");
lblAddressCountryCode.Text=FormItem("address_country_code");
lblAddressCountry.Text=FormItem("address_country");
lblAddressCountry.Text=FormItem("address_country");
lblInvoice.Text=FormItem("invoice");
lblMcCurrency.Text=FormItem("mc_currency");
} catch (System.Exception ex) { Response.Write(ex.Message);
} }

Create an IPN (Instant Payment Notification) Form: YOUR_IPN_form.aspx

PayPal will post to this page when it has processed the transaction. You will check that the transaction is verified (the post to the page really came from PayPal) and not a duplicate (you’ve already processed this txn_id).

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Net;
using System.IO;
using System.Text;
using System.Net.Mail;
public partial class payment_notify : System.Web.UI.Page { TextWriter log = null;
mail m = null;
StringBuilder sb = null;
string txn_id, txn_type, payment_date, last_name, residence_country, item_name, payment_gross;
string item_number, payment_status, payment_fee, mc_fee, shipping, mc_gross, custom, pending_reason, address_name, address_street, address_city, address_state, address_status, address_zip, address_country, address_country_code, invoice, quantity, receiver_email, first_name, payer_id, receiver_id, memo, mc_currency, business, payment_type, verify_sign, payer_status, tax, payer_email;
StringBuilder merchantMsg;
StringBuilder customerMsg;
protected void Page_Load(object sender, EventArgs e) { try { // writes local log file CreateLog();
} catch (System.Exception logex) { Response.Write(logex.Message);
return;
} try { // sends me notice that ipn script has been triggered // TriggerEmail();
} catch (System.Exception teex) { Response.Write(teex.Message);
return;
} try { // checks Request.Form data against call to PayPal // checks txn_id against local database if (IsValidIPN() && !IsDupeTxn()) { // send message to merchant, customer that payment string is valid. // Doesn't mean payment is done, it means transaction has processed, perhaps to completion, to cancellation, to denial. CreateMessages();
SendMessages();
} } catch (System.Exception allex) { Response.Write(allex.Message);
return;
} finally { try { log.Flush();
log.Close();
} catch (System.Exception ioex) { Response.Write(ioex.Message);
} } } private void SendDebugMessage(string subject, string body) { try { m = new mail();
m.Body=body;
m.From="caroline@bogartcomputing.com";
m.FromDisplayName="web site paypal ipn debug msg";
m.IsBodyHtml=true;
m.Subject=subject;
m.To="ctbogart@yahoo.com";
m.send();
} catch {} } private void CreateMessages() { // PayPal has posted to this page. Get the Request.Form items. // Build customer and merchant email messages. log.WriteLine("CreateMessages()");
StringBuilder ctemp=new StringBuilder();
StringBuilder mtemp = new StringBuilder();
StringBuilder sb = new StringBuilder();
// merchant txn details invoice =FormItem("invoice");
item_number = FormItem("item_number");
item_name = FormItem("item_name");
quantity = FormItem("quantity");
memo = FormItem("memo");
custom = FormItem("custom");
sb.Append("Invoice: ");
sb.Append(invoice);
sb.Append("
");
sb.Append("Item Number: ");
sb.Append(item_number);
sb.Append("
");
sb.Append("Quantity: ");
sb.Append(quantity);
sb.Append("
");
sb.Append("Memo from buyer: ");
sb.Append(memo);
sb.Append("
");
ctemp.Append(sb.ToString());
mtemp.Append(sb.ToString());
// paypal txn details payment_date =FormItem("payment_date");
verify_sign = FormItem("verify_sign");
payment_status = FormItem("payment_status");
pending_reason =FormItem("pending_reason");
txn_id = FormItem("txn_id");
txn_type = FormItem("txn_type");
business = FormItem("business");
receiver_email = FormItem("receiver_email");
receiver_id = FormItem("receiver_id");
sb = new StringBuilder();
sb.Append("Payment date: ");
sb.Append(payment_date);
sb.Append("
");
ctemp.Append(sb.ToString());
mtemp.Append(sb.ToString());
mtemp.Append("Verify sign: ");
mtemp.Append(verify_sign);
mtemp.Append("
");
mtemp.Append("Payment status: ");
mtemp.Append(payment_status);
mtemp.Append("
");
mtemp.Append("Pending reason: ");
mtemp.Append(pending_reason);
mtemp.Append("
");
mtemp.Append("Transaction ID: ");
mtemp.Append(txn_id);
mtemp.Append("
");
mtemp.Append("Transaction Type: ");
mtemp.Append(txn_type);
mtemp.Append("
");
mtemp.Append("Business (email): ");
mtemp.Append(business);
mtemp.Append("
");
mtemp.Append("Receiver Email: ");
mtemp.Append(receiver_email);
mtemp.Append("
");
mtemp.Append("Receiver ID: ");
mtemp.Append(receiver_id);
mtemp.Append("
");
// paypal money details mc_currency = FormItem("mc_currency");
payment_gross = FormItem("payment_gross");
mc_gross = FormItem("mc_gross");
payment_type = FormItem("payment_type");
tax = FormItem("tax");
shipping = FormItem("shipping");
payment_fee = FormItem("payment_fee");
mc_fee = FormItem("mc_fee");
sb = new StringBuilder();
sb.Append("Currency: ");
sb.Append(mc_currency);
sb.Append("
");
sb.Append("Tax: ");
sb.Append(tax);
sb.Append("
");
sb.Append("Shipping: ");
sb.Append(shipping);
sb.Append("
");
sb.Append("Amount: ");
sb.Append(mc_gross);
sb.Append("
");
sb.Append("Payment Type: ");
sb.Append(payment_type);
sb.Append("
");
ctemp.Append(sb.ToString());
mtemp.Append(sb.ToString());
mtemp.Append("Fee: ");
mtemp.Append(mc_fee);
sb.Append("
");
// customer details last_name = FormItem("last_name");
first_name = FormItem("first_name");
address_name =FormItem("address_name");
address_street =FormItem("address_street");
address_city =FormItem("address_city");
address_status =FormItem("address_status");
address_state =FormItem("address_state");
address_zip =FormItem("address_zip");
address_country = FormItem("address_country");
address_country_code = FormItem("address_country_code");
residence_country = FormItem("residence_country");
payer_id = FormItem("payer_id");
payer_status = FormItem("payer_status");
payer_email = FormItem("payer_email");
sb = new StringBuilder();
sb.Append("Customer: ");
sb.Append(first_name);
sb.Append(" ");
sb.Append(last_name);
sb.Append("
");
sb.Append("Addressed To: ");
sb.Append(address_name);
sb.Append("
");
sb.Append(address_street);
sb.Append("
");
sb.Append(address_city);
sb.Append(", ");
sb.Append(address_state);
sb.Append(" ");
sb.Append(address_zip);
sb.Append("
");
sb.Append(address_country);
sb.Append(" (");
sb.Append(address_country_code);
sb.Append(")");
sb.Append("
");
ctemp.Append(sb.ToString());
mtemp.Append(sb.ToString());
mtemp.Append("Residence Country: ");
mtemp.Append(residence_country);
mtemp.Append("
");
mtemp.Append("Payer ID: ");
mtemp.Append(payer_id);
mtemp.Append("
");
mtemp.Append("Payer Status: ");
mtemp.Append(payer_status);
mtemp.Append("
");
mtemp.Append("Payer Email: ");
mtemp.Append(payer_email);
mtemp.Append("
");
customerMsg=new StringBuilder();
customerMsg.Append("Dear ");
customerMsg.Append(first_name);
customerMsg.Append(" ");
customerMsg.Append(last_name);
customerMsg.Append(",
");
customerMsg.Append("Thank you for your purchase. Your details are below.
");
customerMsg.Append(ctemp.ToString());
merchantMsg=new StringBuilder();
merchantMsg.Append("To: ");
merchantMsg.Append(business);
merchantMsg.Append("
");
merchantMsg.Append("
");
merchantMsg.Append("Custom pass through data: ");
merchantMsg.Append(custom);
merchantMsg.Append("
");
merchantMsg.Append(mtemp.ToString());
log.WriteLine(customerMsg.ToString());
log.WriteLine(merchantMsg.ToString());
} private void SendMessages() { log.WriteLine("SendMessage");
try

{

m = new mail();
m.Body=customerMsg.ToString();
m.From="caroline@bogartcomputing.com";
m.FromDisplayName="Bogart Computing Payment Received";
m.IsBodyHtml=true;
m.Subject="Bogart Computing PayPal Payment Received";
m.To=payer_email;
log.WriteLine("Sending customer email");
log.WriteLine(m.To.ToString());
m.send();
m.Body=merchantMsg.ToString();
m.To=business;
log.WriteLine("sending merchant email");
log.WriteLine(m.To.ToString());
m.send();
} catch (System.Exception smex)

{

log.WriteLine(smex.Message);
}

}

private bool IsDupeTxn()

{ return false;
}

private void CreateLog()

{

try

{

StringBuilder logname=new StringBuilder();
logname.Append(Request.MapPath("."));
logname.Append("\\log_");
logname.Append(DateTime.Now.Ticks.ToString());
logname.Append(".txt");
string filename = logname.ToString();
log = new StreamWriter(filename);
log.WriteLine(DateTime.Now.ToString());
log.WriteLine("Form");
log.Write(Request.Form.ToString());
} catch (System.Exception logex) { try { SendDebugMessage("IPN create log failed", logex.Message);
} catch { } throw logex;
} } private void TriggerEmail() { log.WriteLine("TriggerEmail()");
try { // send me note that ipn was triggered // inform owner that ipn is triggered mail m = new mail();
m.From="caroline@bogartcomputing.com";
m.FromDisplayName="Bogart Computing web site";
m.To="caroline@bogartcomputing.com";
m.Subject="bogart computing ipn triggered";
m.IsBodyHtml=true;
m.Body=Request.Form.ToString().Replace("&", "
");
log.WriteLine("about to send email cb notification start email");
try { m.send();
} catch (System.Exception ex) { log.WriteLine(ex.Message);
throw ex;
} } catch (System.Exception mex) { throw mex;
} } private bool IsValidIPN() { log.WriteLine("IsValidIPN()");
try { // ask PayPal if this is a valid IPN string value, response;
string form = Request.Form.ToString();
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.sandbox.paypal.com/cgi-bin/webscr");
req.Method = "POST";
req.ContentType="application/x-www-form-urlencoded";
value=form + "&cmd=_notify-validate";
req.ContentLength=value.Length;
log.WriteLine("create streamout");
StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
streamOut.Write(value);
streamOut.Close();
log.WriteLine("create streamin");
StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
// response from PayPal response = streamIn.ReadToEnd();
streamIn.Close();
log.WriteLine(response);
return (response.ToLower()=="verified");
} catch (System.Exception ex) { log.WriteLine(ex.Message);
throw ex;
} } private string FormItem(string formAddress) { string result;
try { result=Server.HtmlEncode(Request.Form[formAddress]);
} catch { result="N/A";
} if (result==null) { result="N/A";
} return result;
} }

Google Patent: an accelerating rate of document changes

0

Posted on : 17-05-2005 | By : caroline | In : Search Engine Marketing

More on The March 31 05 Google Patent

Why does Google reward an accelerating rate of document changes?

The answer to this — and every other Google patent question, for that matter — is that accelerating document changes indicate that the document has a higher likelihood of being high quality and authoritative.

Google is biased against stale documents, presumably because a new information would generally tend to supercede old information.

Given two sets of documents, decide which is of higher quality and more authoritative.

First we have hundreds of years of scribe-transcribed papyrus declaring the flatness of the universe. We have a huge quantity of reference to the flat earth and some priests vested with intellectual authority writing them.

Next we have a couple of pages that maintain that the world is round. At first these documents have little weight and little authority. As the earth’s roundness gets confirmed, more and more explorers write of the round earth. Their documents point to one another (“…as Columbus has already said, the earth is, indeed round, and I can confirm that…”).

The new documents increase with an accelerated pace as more and more explorers confirm each others’ findings. Meanwhile, the flat earth documents get staler and staler.

New paradigms with contagiously righteous information will generate a pile-on effect, creating lots of content quickly. By the time the round earth notion reaches critical mass, the flat earth web master quits and that site’s documents stop getting updated all together.

Hence, an accelerating rate of document changes implies a new source of authoritative, peer-reference content.

Google Patent Implications: updated outbound link anchor tag text

0

Posted on : 06-05-2005 | By : caroline | In : Search Engine Marketing

Why does Google want to see updated outbound link anchor tag text?

At first glance this patent rule seems somewhat contradictory to Google’s mission of delivering high-quality content.

In their never-ending quest for quality content, Google implements an anchor tag algorithm that categorizes updated content as good and stale content as bad.

At first this seems wrong, as so eloquently pointed out by riottech (Google recent patent historical data and page rankings).

It will be interesting to see how Google handles “stale” documents. It seems like a page not having recently updated content will not always mean that it is not a good source of information. Many encyclopedia articles and reference pages should not change often, I would think. Does fresh content always mean better content?

I suppose that Google’s reasoning is like this: “In 1491 the world was flat. In 1492, not so much.”

In other words, what are the chances that an updated document is less accurate than an older one? Let’s assume that document updates imply higher document accuracy.

Updated inbound link anchor text indicates a probable document correction.

Google Patent implications: High and probable rate of back link growth

0

Posted on : 26-04-2005 | By : caroline | In : Search Engine Marketing

On the Google Patent back link growth rule…

I can’t begin to express how clever this rule is, and how clever it must be.

It’s elegantly anti-spam
Google puts a high value on incoming links to your site. You have content. People point to you. You must be an authority. Google wants to display high-quality authoritative content. Google displays your site in its search listings.

This scenario has led to a multi-million dollar industry in link spam. Link farms, link exchanges, text ads advertising as links… all of which lower the quality of Google’s search results.

The rule is clever because it’s so elegantly anti-spam.

How clever it must be
If I put something hot in a thermos, it stays hot.

If I put something cold in a thermos, it stays cold.

how does it know?

Google records the quantity and quality of your site’s back links (incoming links). True link backs grow slowly. As content providers discover how clever, interesting and compelling your site is they put up links that say: here, look at this clever, interesting and compelling web page.

Google recognizes that links backs might grow in spurts… a TV show creates huge exposure, creating buzz, creating link backs. As part of the patent, Google will take bursts into account.

Measuring the rate of growth is a simple calculation. But determining if an inbound link is really a text ad, or if a burst in link growth is valid takes some pretty intelligent algorithms.

You know what’s nice about Google?
After struggling with Microsoft’s products for 25 years, isn’t it nice that we have a computing giant in Google that implements quality with academic attention to detail? We are worthy, and it’s damned nice to really respect a software company for a change.