Introduction
PayPal provides a rich interface for securely processing payments from your website. However, for many of us, this is simply overkill. It might be that all we really need is a simple buy-now button.
PayPal understand this and provides a small snippet of HTML you can paste into your web pages to produce buy-now buttons. This snippet may look something like that shown in Listing 1.
Listing 1. HTML Code to Insert a PayPal Button
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="YOUR-PAYPAL-EMAIL-HERE">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="item_name" value="Widget">
<input type="hidden" name="amount" value="100.00">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="bn"
value="PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest">
<input type="image"
src="https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif"
border="0" name="submit" alt="">
<img alt="" border="0"
src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1"
height="1">
</form>
Unfortunately, this code is not fully compatible with most ASP.NET Webforms pages. The problem is that PayPal's HTML code is contained within a <form> tag while Webforms pages have their own <form> tag, which normally wraps the entire page. And nested <form> tags are not allowed.
In this article, I'll present three solutions to this problem that each have their own problems. Finally, I'll present another, very simple solution that sidesteps these issues completely.
Adding Multiple Form Tags
While it's true that you cannot nest <form> tags, it's still okay to have multiple form tags on a page. And so one solution is to add the PayPal code at the end of the page, after the ASP.NET form's closing </form> tag.
While this works, it kind of limits where you can place your buy-now buttons, and also limits where you can place ASP.NET controls, which may need to be within the ASP.NET form. For the most part, your ASP.NET controls would need to be near the top of the page while the PayPal button would need to be near the end.
This approach can be used to solve the problem but is certainly not ideal.
Sharing a Single Form
Another approach is to strip the <form> tags from the PayPal code and paste what remains inside the ASP.NET <form> tags. Afterall, all <form> tags use the same postback mechanism. Why can't everything share the same form?
For best results, you'll probably want to make a few additional changes to the PayPal code so that it looks something like that shown in Listing 2. Note the ImageButton's PostBackUrl is set to the URL provided by PayPal. When the button is clicked, the entire page is posted to this URL. Although this is more information that PayPal needs, PayPal can still find the values it does need and process the request.
Listing 2. PayPal Button Placed within the ASP.NET Form
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="YOUR-PAYPAL-EMAIL-HERE">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="item_name" value="Widget">
<input type="hidden" name="amount" value="100.00">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="bn"
value="PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest">
<asp:ImageButton ID="ImageButton1" runat="server"
ImageUrl="https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif"
PostBackUrl="https://www.paypal.com/cgi-bin/webscr" />
This approach is a little brittle. For example, if you duplicate one of the element names in other parts of your ASP.NET page, PayPal may not be able to locate the information it needs. Aside from that, this approach actually seems to work pretty well.
An Ugly Hack
Another approach worth mentioning uses a regular ASP.NET button for your buy-now button. Listing 3 shows the handler for the button's Click event.
Listing 3. Ugly Hack to Perform Non-ASP.NET Postback
protected void btnPayPal_Click(object sender, ImageClickEventArgs e)
{
System.Web.HttpContext.Current.Response.Clear();
System.Web.HttpContext.Current.Response.Write("<html><head>");
System.Web.HttpContext.Current.Response.Write(
"</head><body onload='document.form1.submit()'>");
System.Web.HttpContext.Current.Response.Write(
"<form action='https://www.paypal.com/cgi-bin/webscr' " +
"name='form1' method='post'>");
System.Web.HttpContext.Current.Response.Write(
"<input type='hidden' name='cmd' value='_xclick'>");
System.Web.HttpContext.Current.Response.Write(
"<input type='hidden' name='business' " +
"value='YOUR-PAYPAL-EMAIL-HERE'>");
System.Web.HttpContext.Current.Response.Write(
"<input type='hidden' name='lc' value='US'>");
System.Web.HttpContext.Current.Response.Write(
"<input type='hidden' name='item_name' value='Widget'>");
System.Web.HttpContext.Current.Response.Write(
"<input type='hidden' name='amount' value='100.00'>");
System.Web.HttpContext.Current.Response.Write(
"<input type='hidden' name='currency_code' value='USD'>
System.Web.HttpContext.Current.Response.Write(
"<input type='hidden' name='bn' " +
"value='PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest'>
System.Web.HttpContext.Current.Response.Write(
"<input type='image' " +
"src='https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif' " +
"border='0' name='submit' alt=''>");
System.Web.HttpContext.Current.Response.Write(
"<img alt='' border='0' " +
"src='https://www.paypal.com/en_US/i/scr/pixel.gif' " +
"width='1' height='1'>");
System.Web.HttpContext.Current.Response.Write("</form>");
System.Web.HttpContext.Current.Response.Write("</body></html>");
System.Web.HttpContext.Current.Response.End();
}
This handler creates a new web page on the fly and feeds that page back to the browser. The calls to Response.Clear() at the start and Response.End() at the end prevent anything else from being included in the response that is not part of this dynamic page.
The page this code creates contains the PayPal code along with some JavaScript to postback the form as soon as it loads. So the browsers gets the page, performs the postback, and the information is sent to PayPal.
While this approach works and I found it rather amusing, it's definitely an ugly hack that makes the page harder to understand and maintain. Also, if the user hits the back button from the PayPal site, the browser will reload the dynamic page that was created instead of the page where the order was placed. Not only that, but when the dynamic page is loaded, it will want to automatically postback again.
Definitely not an ideal approach!
An Easy Solution
Okay, so now I'll offer a much easier solution as promised. PayPal also allows you to create a buy-now button using a simple link. Listing 4 demonstrates this technique.
Listing 4: A Very Simple PayPal Buy-Now Button
<a href="https://www.paypal.com/cgi-bin/webscr
?cmd=_xclick&business=YOUR-PAYPAL-EMAIL-HERE
&item_name=Widget
&amount=29.00
&undefined_quantity=1
¤cy_code=USD">
<img src="http://www.paypal.com/en_US/i/btn/x-click-but23.gif"
border="0" alt="Buy Now Using PayPal" />
</a>
Note that the href value of the a tag should all go on a single line. (I wrapped the text here only so it would fit within the page.)
As you can see, we provide several bits of information. After our account email, we provide an item name, the price (amount), and I included the optional currency code.
The undefined_quantity parameter allows the user to enter the quantity, and PayPal will calculate the total based on the price you specified and the quantity entered by the user. Alternatively, you can instead say quantity=5 to fix the quantity so that the user cannot edit it.
Although that should be all you need for a simple buy-now button, Table 1 lists some additional arguments you can include.
Table 1: Additional Query Arguments
Argument |
Description |
business |
Email address associated with seller's PayPal account |
quantity |
Quantity of items being sold |
undefined_quantity |
Allows user to edit quantity |
item_name |
Name of item |
item_number |
Optional item number |
amount |
Price of each item (without currency symbol) |
undefined_amount |
Allows user to edit the amount (good for donations) |
shipping |
Price of shipping |
currency_code |
Code for type of currency (Default appears to be USD) |
first_name |
Customer's first name |
last_name |
Customer's last name |
address1 |
Customer's first address line |
address2 |
Customer's second address line |
city |
Customer's city |
state |
Customer's state |
zip |
Customer's zip code |
email |
Customer's email address |
night_phone_a |
Customers telephone area code |
night_phone_b |
Customers telephone prefix |
night_phone_c |
Remainder of customer's telephone number |
The arguments listed in Table 1 are not exhaustive. Other arguments are available as well. For the simple task I'm describing, this list should be more than enough.
Of course, you also have the option of programmatically forming this link and then using code to redirect to it. This allows you, for example, to set the quantity based on a value entered by the user on your own site.
Conclusion
Note that none of these techniques (including pasting the PayPal buy-now button code directly onto a non-ASP.NET page) are completely secure. In all cases, users can see your PayPal email address (although they can't access your password.). Users can also save your page to disk and then edit the link to have a different product, price, or quantity. So all numbers should be verified. For more sophisticated PayPal order processing, you would want to look into PayPal's API.
Nonetheless, for a simple buy-now button, this technique works great and couldn't be simpler to implement.
End-User License
Use of this article and any related source code or other files is governed
by the terms and conditions of
.
Author Information
Jonathan Wood
I'm a software/website developer working out of the greater Salt Lake City area in Utah. I've developed many websites including Black Belt Coder, Insider Articles, and others.