Friday, January 13, 2012

Single-item PayPal buttons and rendering them using a ASP.NET MVC Html Helper method

On my FO processor website (also see my blog) users can download a created PDF without watermarks after having payed a small amount. I use PayPal to accept single-item payments and it took me some time to find out what the HTML form for the Buy Now button should look like. Which hidden form fields were required, and which optional fields I could also use to further configure the payment process? After some experimenting my HTML form became:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
    <!-- Specify a Buy Now button. --> 
    <input type="hidden" name="cmd" value="_xclick" />

    <!-- Identify your business so that you can collect the payments. --> 
    <input type="hidden" name="business" value="jeroen@xyz.com" /> 

    <!-- Specify details about the item that buyers will purchase. --> 
    <input type="hidden" name="item_name" value="Your PDF file without watermarks" />
    <input type="hidden" name="item_number" value="2ca168a959bb48e28a2ddb4b4640c568" />
    <input type="hidden" name="amount" value="1.99" />
    <input type="hidden" name="currency_code" value="USD" /> 

    <!-- Specify a URL for the payment confirmation page and a page that is displayed
         if the user cancels a transaction. Also specify a URL that PayPal can post IPN
         messages to (see explanation below). --> 
    <input type="hidden" name="return" value="http://xslfop.com/order/complete" />
    <input type="hidden" name="cancel_return" value="http://xslfop.com/order/cancel" />
    <input type="hidden" name="notify_url" value="http://xslfop.com/order/ipn" />

    <!-- Do not prompt customers to include a note with their payment. --> 
    <input type="hidden" name="no_note" value="1" />

    <!-- Display the payment button. -->
    <input type="image" name="submit"
        src="https://www.sandbox.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif"
        alt="PayPal — The safer, easier way to pay online." />
    <img src="https://www.sandbox.paypal.com/en_US/i/scr/pixel.gif"
        width="1" height="1" alt="" />
</form>
In this example the form is posted to the PayPal sandbox test environment.

The item_number field is an optional pass-through variable that allows me to track orders. It will be posted back to the notify_url URL at the completion of a payment, in a IPN message. When the notify_url URL successfully processes the IPN, the order status can be updated to 'payed' automatically (probably in a database). You are typically notified of events by email as well, but the IPN message service enables you to automate your response to events.

What if I want to create another Buy Now button on my site? I can simply put the HTML form on another page, but if anything needs to be changed later there are two places to change it. I also think that editing the forms by hand is prone to typing errors. Since I am a ASP.NET MVC programmer, I have created a simple Html helper method that encapsulates the PayPal button form code. It can easily be extended by including more method arguments and rendering their corresponding form fields. For example, the following hidden field will prompt buyers to enter item quantities on the payment page:
<input type="hidden" name="undefined_quantity" value="1" /> 
Here is the skeleton of the helper method. The complete code can be downloaded following the link at the bottom of this post.
using System.Text;
using System.Web.Mvc;

namespace Antrix.Web.Mvc
{
    public static class HtmlHelpers
    {
        public enum EButtonType
        {
            BuyNow = 1,
            PayNow = 2
        }

        public enum ECurrencyCode
        {
            USD = 1,
            EUR = 2
        }

        public static MvcHtmlString PayPalButton(this HtmlHelper helper,
            bool useSandbox, EButtonType buttonType, string email,
            string itemName, string itemNumber, float amount, ECurrencyCode currency,
            string completeUrl, string cancelUrl, string ipnUrl)
        {
            string action = useSandbox ?
                "https://www.sandbox.paypal.com/cgi-bin/webscr" :
                "https://www.paypal.com/cgi-bin/webscr";
            StringBuilder html = new StringBuilder("\r\n<form action=\"")
               .Append(action).Append("\">");

            // ...
            // Append HTML for the hidden form fields and the payment button.
            // ...

            html.Append("\r\n</form>");

            return new MvcHtmlString(html.ToString());
        }
    }
}
The following call to the helper method in a ASP.MVC Razor view will render the same PayPal form as the one at the beginning of this post.
@using Antrix.Web.Mvc

@Html.PayPalButton(true,
    HtmlHelpers.EButtonType.BuyNow,
    "jeroen@xyz.com",
    "Your PDF file without watermarks",
    "2ca168a959bb48e28a2ddb4b4640c568",
    1.99f,
    HtmlHelpers.ECurrencyCode.USD,
    "http://xslfop.com/order/complete",
    "http://xslfop.com/order/cancel",
    "http://xslfop.com/order/ipn")

1 comment:

  1. Legend, just what I was looking for. Thank you very much!

    ReplyDelete