Trying to get Google Checkout and PayPal to work with a custom .NET site or solution has been a problem for as long as they’ve been around. If you don’t know what you’re doing, it can be a daunting task, and sometimes even if you do know what you’re doing! Well, I am going to take the guesswork out of this chore once and for all, as I have recently discovered the ultimate way to integrate these payment gateways into your website.
If you’re saying, “Wait a second, haven’t you already written an article on this?” you are correct. However, the solution I present to you here is infinitely simpler and requires fewer moving parts. The only reason I didn’t take the previous article down is because it does present interesting information about nesting MasterPages.
In their documentation, PayPal and Google Checkout both mention that you must put their code into your site exactly as they have it, using the HTML forms they way they have structured them. This is not true. There are only a few bits of information that are required, and so long as they are present in an acceptable fashion, your pass-off to these gateways will work smoothly and flawlessly.
Get rid of your form tags. That’s right. Lose the form tags. You will only need your
<form runat="server">tag, no more nested HTML forms. W3C compliancy, here we come! However, don’t lose the information contained in your old
<form>tag attributes. You’ll still need some of that.
Create image buttons for Google Checkout and PayPal. While they don’t have to be image buttons (for functionality’s sake), both Google and PayPal will get upset if you have standard buttons instead of their images as checkout buttons. It is in this button where the magic happens – the button has a property called
PostBackURL. This is where you will put the
actionstring from your form. For instance, PayPal’s
PostBackURLvalue is “https://www.paypal.com/us/cgi-bin/webscr”. Google’s will be “https://checkout.google.com/cws/v2/Merchant/%5Byour merchant number]/checkoutForm”. You can put both Google’s and PayPal’s buttons next to each other. Here is some sample code:
<asp:imagebutton id="btnSubmitPaypal" runat="server" imageurl="/images/checkout-paypal.gif" alternatetext="Purchase Using Paypal" postbackurl="https://www.paypal.com/us/cgi-bin/webscr" />
Create your hidden inputs to transfer information to PayPal and Google Checkout (from the same page, no extra postbacks!). However you dynamically create your hidden input tags, keep doing it. Just keep this in mind: Google Checkout and PayPal have no tags in common except one, the “item_name_x” (where “x” is a number) tag. If this is the same for both Google Checkout and PayPal, leave it alone and only have one! If you must have two (as I do), make sure you put Google’s tags before PayPal’s. This is important because Google reads the first tags that match what it’s looking for and ignores everything else. PayPal will take the last tag that matches its requirements.
I mention this because Google Checkout has an “item_description_x” attribute that will take additional information about the item where PayPal does not, meaning that PayPal users have to cram all the info about their product into the “item_name_x” tag. Thus, if you change the order, Google will display double information (PayPal’s “item_name_x” plus their own “item_description_x” tag) and PayPal will display only what you want to transfer to Google Checkout (the last “item_name_x” tag).
BONUS: Hook up Google Analytics. For those advanced users who want to hook up their Google Analytics, you still can using this method. The
asp:buttonelement has an attribute called
OnClientClick. Put the following as the value for this attribute in your Google Checkout image button:
For those looking for some sample code on how to dynamically generate your input tags, simply create a literal somewhere on the page and populate it with the following function:
Public Function CreateCheckoutTag(ByVal att As String, ByVal value As String) As String Dim input As String = "<input type=""hidden"" name=""" & att & """ value=""" & CleanText(value) & """ />" Return input End Function
CleanText(value) function cleans any possible special characters from the value. Not necessary, but recommended.And that’s it! Three or four easy steps and you’re ready to use both Google Checkout and PayPal Website Payments on your website! I hope this saves someone 60 or 70 hours of their life, as it would have mine had I known about it three years ago 🙂
“Unknown runtime error”
I tried many different combinations of contents for the panel, but the only one that seemed to produce the error was whenever a form was present inside the panel. This was very frustrating, as no one around the internet community really seemed to have run across this error, and modifying the MasterPage to account for this single scenario would be a nightmare.
A working solution I came up with for this rare error is to wrap your content (on your .aspx page) with another UpdatePanel and set your triggers to post back when the button is pressed. While the client may have to suffer another postback, it’s not as bad as a total loss of functionality.
If you can find a more elegant solution to this problem, I would love to hear it!
EDIT (2/29/08): I believe the error occurs whenever you are using nested HTML forms within your runat=”server”. If you’re looking to post to another form, please see my article on integrating PayPal and Google Checkout.
Once you have your design converted into HTML/CSS, why should you have to worry about breaking it every time you create a new page? Abstract yourself from this with MasterPages, while still enabling yourself to easily make design changes. MasterPages are wonderful for standardizing your site and your design, in addition to making it easier to maintain and to build new pages. They are a very powerful and easily customizable way to template your site. This article is for those who don’t have much or any experience with MasterPages or are converting an old ASP.NET site to a MasterPage-driven site. If this is you, don’t be afraid—You can do it in just three easy steps!
1. Create a new MasterPage
Right click your project, go to “Add” and then “New Item…” and select MasterPage. Name it something useful, like “main.master” and hit ok. You should be presented with a barebones XHTML skeleton. Notice that your skeleton has this tag in it:
<asp:contentplaceholder id="ContentPlaceHolder1" runat="server" />. This is the location where your content will be loaded from your .aspx pages. Fill your new MasterPage with the XHTML that you wish to use on every page. If you want some things to change based on certain variables, you can do so in the codebehind. Treat the MasterPage like any other .aspx page. The only thing different about it (on a basic level) is that it does not contain your content, but rather what encompasses your content.
2. Link your old pages to your MasterPage in the Page Directive
In your <%@ Page directive, add the following attribute:
3. Tell the MasterPage What Content Goes Where
If you only have one ContentPlaceHolder, you will add the following tag around all of your content in your .aspx pages:
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">Hello, World!
</asp:Content>, where “ContentPlaceHolder1” is the ID of the placeholder in your MasterPage that you linked to in step 2. If you have more than one ContentPlaceHolder in your MasterPage, simply wrap the tags around the correlating content.
And that’s it! That’s really all there is to it! Just apply steps 2 and 3 to each of your .aspx pages. There is an optional step for those who may have changed their pages’ codebehind inheritance:
4. Change CodeFile Inheritance
Simply replace whatever inheritance you have with
Please read my articles ASP.NET: How To Easily Reference MasterPage Members and my ASP.NET and AJAX: So Freaking Easy series for more tips on how to get yourself set up even better using MasterPages.
For example, my original post-mangling ID was “ctl00_cphMain_txtBackgroundColor”, and after I nested my MasterPages, the ID changed to “ctl00_ctl00_cphMain_cphMain_txtBackgroundColor”. So, when using the document.getElementByID() function, it couldn’t locate the control, and thus threw me a yellow triangle.
After searching high and low for a solution to the PayPal/Google Checkout dilemma (trying to submit your shopping cart to them using ASP.NET was a problem because you couldn’t use nested forms), I have come up with a (non-kludgy) technique that will work, and actually provides the developer with another level of abstraction that could potentially be useful elsewhere.
EDIT: 2/27/2008 – There is a much better way to integrate PayPal and Google Checkout. Please see my new article, ASP.NET: How To Integrate Both Google Checkout and PayPal In 3 Steps. The article on the page you are currently viewing should be used as a reference on how to nest MasterPages.
What’s this technique? Nested MasterPages, of course! Here’s what I did step by step:
- Create a wrapper MasterPage that includes everything that will be common on all of your pages except for your
- Create a ContentPlaceHolder inside your wrapper MasterPage
- Create a child MasterPage that calls the wrapper as its MasterPage
- Inside the child’s
<asp:Content>tag, put your form
- Once you’ve placed your form inside your child MasterPage’s content tag, create a ContentPlaceHolder, and then add a content page (.aspx page)
Be sure to reference your wrapper from your child MasterPage’s page directive, like so:
<%@ Master Language="VB" MasterPageFile="~/masterWrap.Master" CodeFile="masterChild.master.vb" Inherits="masterChild" %>
Once you’ve set up this level of abstraction, you can create another child master page without the
<form runat="server"> tag in it, and do all your necessary PayPal and Google Checkout form construction! I usually use literals to create the forms and their hidden fields on the server side.
I created this abstraction very easily in about five minutes in an application that was using MasterPages already, so it’s not hard to retrofit if you need to. Remember also that a child can only reference its direct parent (and that MasterPages render LAST!), so if you need pass info to your wrapper MasterPage, create properties in the MasterPages up the line and pass them along in the Page_Load subroutine (don’t forget to set up MasterPage referencing).
So for those of you looking for a method to use PayPal and Google Checkout within your current MasterPage setup, this may solve your woes! It solved mine!
NOTE: By doing this, you will lose design-time support in (at least) Visual Studios 2005, since it does not support nested MasterPages in design mode. I guess everything comes with a price.
I’ll lay it out very simply:
- On your .aspx page, include the following:
<%@ MasterType virtualpath="~/myMasterPage.master" %>
- To reference the members, simply type
That’s it! It’s better than casting a new master page object for every function, that’s for sure.
NOTE: Content pages load BEFORE master pages, so if you’re going to reference something on your master page, be sure you don’t need it during your content page’s Page_Load event!