Implement Paypal Buy Now Button with ZK

From Documentation
DocumentationSmall Talks2006JulyImplement Paypal Buy Now Button with ZK
Implement Paypal Buy Now Button with ZK

Author
Henri Chen ,Principal Engineer ,Potix Corporation
Date
July 20, 2006
Version
Applicable to ZK 2.1.1 and later.


What is Paypal Buy Now Button?

The Paypal Buy Now Button is used to let merchant to sell individual items on a web site. End users can buy the item immediately by just pressing the button, pay the price(via credit card, wiring, etc.), and complete the purchase on line.


What is ZK?

ZK is an open-source Ajax Web framework that enables rich UI for Web applications with no JavaScript and little programming.


A Form Only

A legacy Paypal Buy Now Button is really only a form that submit to Paypal website. And that is the way that Paypal teachs you how to put a "Buy Now" button in your own mechant web site (See here for details.). Before jumping in the details on how to implement a ZK Paypal Buy Now Button component, let us see the form first:

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
  <input type="hidden" name="cmd" value="_xclick">
  <input type="hidden" name="business" value="henrichen@potix.com">
  <input type="hidden" name="item_name" value="ItemName">
  <input type="hidden" name="item_number" value="ItemID">
  <input type="hidden" name="amount" value="123.00">
  <input type="hidden" name="no_shipping" value="2">
  <input type="hidden" name="no_note" value="1">
  <input type="hidden" name="currency_code" value="USD">
  <input type="hidden" name="bn" value="PP-BuyNowBF">
  <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but23.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
  <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>


This form is generated via the Paypal's "Website Payments Standard: Single-Item Purchases" page. There can be more option attributes. However, to simplify the discussion, we will limit the attibutes to the list below:

  • business: the merchant Paypal account (the one who will get the wired money)
  • item_name: the description of the item.
  • item_number: the item number so merchant can track purchases.
  • amount: the price of the item, not including shipping, handling, and tax.
  • no_shipping:
  • Default or 0: customer will be prompted to include a shipping address.
  • 1: customer is not asked for a shipping address.
  • 2: customer must provide a shipping address.
  • no_note:
  • Default or 0: customer is prompted to include a note.
  • 1: customer is not prompted to include a note.
  • currency_code: currency of price.
  • Default or USD: U.S. Dolloars.
  • AUD: Australian Dollars.
  • CAD: Canadian Dollars.
  • EUR: Euros.
  • GBP: Pounds Sterling.
  • JPY: Japan Yen.


Why do we need a ZK Buy Now Button?

Since the Paypal Buy Now Button is simply a form, can't we just copy-paste the form to the ZUL page? The smalltalk Work with Legacy Web Applications, Part I - Servlets and Forms has told us how to do that, hasn't it? Sure, you can do it that way. However, implementing a ZK Paypal Buy Now Button got a lot of advatages because ZK can do things dynamically:

  • Localization: The button is shown as an image that can be easily setup on the fly by ZK. Therefore, the button can be setup proper image and label per the preferred language of the user's browser. Copy-paste would not possible to do that.
  • Security: The legacy form source code can be easily viewed by the end user. Your paypal account, item's price, and other details can be altered by a third party and the money can be wired to some malicious account. ZK can generate the form dynamically just before the form is submitted. No information is leaked out. Someone familiar with Paypal might have known that Paypal provides encryption mechanism to secure the form attributes from being seen and altered. We will cover that encryption part in the next smalltalk on how to use ZK to dynamically encrypt the form attributes before that encrypted form is submitted. A even secure way.
  • Convenience: A ZK Paypal Buy Now button does it all. You don't need to copy-paste a form and you can programmatically create the button or via the ZUML XML authoring. It is more convenient.

The implementation

The Paypal Buy Now Button is a kind of button. It is natural to extends it from the Zul's Button class.

import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zul.*;
import org.zkoss.zul.event.*;
import org.zkoss.zhtml.Form;
import org.zkoss.zhtml.Input;

public class PaypalBuyNowButton extends Button {
    private String _business = null;
    private String _itemName = "";
    private String _itemNumber = "";
    private String _amount = null;
    private String _noShipping = "0";
    private String _noNote = "0";
    private String _currencyCode = "USD";
    
    //setters
    public void setBusiness(String str) {
        _business = str;
    }
    
    public void setItemName(String str) {
        _itemName = str;
    }
    
    public void setItemNumber(String str) {
        _itemNumber = str;
    }

    public void setAmount(String str) {
        _amount = str;
    }
    
    public void setNoShipping(String str) {
        _noShipping = str;
    }
    
    public void setNoNote(String str) {
        _noNote = str;
    }
    
    public void setCurrencyCode(String str) {
        _currencyCode = str;
    }
    
    ...
}


Apparently, We have to provide setters so end user can setup the attributes of the Paypal form. The key part of the Paypal Buy Now Button is really when user click the button. We will create a form dynamically and sumbit it.

//generate form and submit
public void onClick(MouseEvent event) {
    //create paypal form
    Form form = new Form();
    form.setDynamicProperty("action", "https://www.paypal.com/cgi-bin/webscr");
    form.setDynamicProperty("method", "post");
    form.setPage(this.getPage());
    
    //cmd
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "cmd");
        input.setValue("_xclick");
    }
    
    //business
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "business");
        input.setValue(_business);
    }
    
    //item_name
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "item_name");
        input.setValue(_itemName);
    }

    //item_number
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "item_number");
        input.setValue(_itemNumber);
    }
    
    //amount
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "amount");
        input.setValue(_amount);
    }
    
    //no_shipping
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "no_shipping");
        input.setValue(_noShipping);
    }

    //no_note
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "no_note");
        input.setValue(_noNote);
    }

    //currency_code
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "currency_code");
        input.setValue(_currencyCode);
    }
    
    //bn
    {
        Input input = new Input();
        input.setParent(form);
        input.setDynamicProperty("type", "hidden");
        input.setDynamicProperty("name", "bn");
        input.setValue("PP-BuyNowBF");
    }
    
    //submit the form
    Clients.submitForm(form);
}


Ok, the Paypal Buy Now Button implementation is inside the file PaypalBuyNow.java. There should be more code regarding attribute validation. e.g. The _buisiness and _amount should not be empty; the _amount has to be properly formated, etc. However, to simplify the code, we omit that part here. Also note that how an XHTML input is created and how some properties (attributes) are setup. The XHTML component implements DynamicPropertied so it accepts any attributes. Excepts some important attribute, e.g. setValue(), most other attributes are implemented as setDynamicProperty(String name, String value);


Use the Paypal Buy Now Button

To use the Paypal Buy Now Button, there are serveral ways:

  • button component with use attribute: <button label="Buy Now" use="PaypalBuyNowButton"/>
  • component directive to avoid type use attribute everytime:
      <?component name="buynow" extends="button" class="PaypalBuyNowButton"?>
      ...

      <buynow ...>
          
      ...
  • setup it in lang-addon.xml under metainfo/zk and use it as a "native" component.
  • directly coding in java by new PaypalBuyNowButton(); ...


Following is the paypal1.zul example that use the Paypal Buy Now Button:

<?component name="buynow" extends="button" class="PaypalBuyNowButton" 
  label="" image="https://www.paypal.com/en_US/i/btn/x-click-but23.gif"
  style="border: 0; background-color:transparent" noShipping="2" noNote="1"
  business="henrichen@potix.com" tooltiptext="Make payments with PayPal - it's fast, free and secure!"?>
<zk>
    <zscript src="PaypalBuyNowButton.java"/>
    
    <grid width="100%">
        <columns>
            <column label="Item No." width="100px"/>
            <column label="Item Description" width="200px"/>
            <column label="Price" width="100px"/>
            <column label=" "/>
        </columns>
        <rows>
            <row><label value="A100"/>ZK in action<label value="$39.99 USD"/><buynow amount="39.90" itemName="ZK in action" itemNumber="A100"/></row>
            <row><label value="A200"/>Thinking in ZK<label value="$49.99 USD"/><buynow amount="49.99" itemName="Thinking in ZK" itemNumber="A200"/></row>
            <row><label value="A300"/>ZK Examples<label value="$29.99 USD"/><buynow amount="29.99" itemName="ZK Examples"  itemNumber="A300"/></row>
            <row><label value="A400"/>ZK Clustering<label value="$79.99 USD"/><buynow amount="79.99" itemName="ZK Clustering" itemNumber="A400"/></row>
        </rows>
    </grid>
</zk>


Copy the paypal1.zul and the PaypalBuyNowButton.java to zkdemo/test then visit to zkdemo/test/paypal1.zul, you will see the testing code. Note that the form is submitted to real Paypal site. Don't press the "Pay" button in the Paypal page. We are not responsible for the "fund" that you wired to the Paypal account.

And, the snapshot is as follows.

Paypal1.gif


Notes and Enhancements

In this article, we illustrate how to dynamically create a Paypal Buy Now Button form and how to encapsulate it into a PaypalBuyNowButton component. However, this is only the first step. The Paypal also provides submitting an encripted Buy Now Form that would further secure the form from being hacked. In the next smalltalk, we will show you how to encript and sumbit a Buy Now form using this ZK form submitting mechanism.


Summary

The ZK ajax framework allows you to dynamically generate a HTML form and submit it with Java methods. Anything that regarding submitting a form can be implmented this way. This PaypalBuyNowButton is an example; the smalltalk, Validate Forms, is another example. I think you should see the potential of this mechanism since all legacy web applications are form based and they can be "value-added" or "componentized" easily into ZK framework.




Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.