Summary:A flexible PayPal "Buy Now" button markup
Prerequisites:PayPal Merchant Account & admin access
Status:Works for contributor's account
Categories: Payment

Questions answered by this recipe

The PayPalButtons recipe is great but can it be more flexible?


I've taken XES's recipe a bit further to cater for a need I have. This version gives you the following two markups

(:BuyNow name="Product name" id=ABC001 value="24.95":)
(:BuyNow name="Product name" id=ABC001 value="24.95" options=yes:)

First, generate your button code... (thanks to XES for some of the wording here!)

  1. Get the button code from PayPal. Merchants click on "Merchant Services" tab and locate the links for "Buy Now Buttons" (currently under "Key Features").
  2. Fill in the amount, give your item a name so people are sure they clicked on the right button. Say "no" to the encrypted button.
    Note that there may be good reasons to encrypt your PayPal code since people can change your prices and essentially hijack your purchases if you don't encrypt. If you wish to encrypt, go back to the original entry under PayPalButtons. This recipe is far easier than mine, but I wanted encryption. -- XES
    Another caution -- I'm working on using this version so that I can dynamically change the prices on the site, but note that using the plaintext version leaves your paypal account email address open to the public for spiders to sniff it out and send you spam and pfishing emails. -- XES January 31, 2007, at 08:49 AM
  3. On the following screen there's a box full of HTML form code - keep it handy or copy to a text editor for reference.

The example code below is based on my requirements and could easily be customised to yours. What you have to do is look at the code generated from your account and look at the example code and see the differences. I'll try to point them all out. You need to put this code into your local customisation file (typically local/config.php)


#Define PayPal Buy Now button markup
Markup('BuyNow', 'inline',  '/\\(:BuyNow (.*?):\\)/e', 'PayPalBuyNow("$1")');

function PayPalBuyNow($opts) {

  $PayPalBuyNow_Account = '';

  $args = ParseArgs($opts);

  $output = "<form action='' method='post'>
<input type='hidden' name='cmd' value='_xclick'>
<input type='hidden' name='business' value='".$PayPalBuyNow_Account."'>
<input type='hidden' name='item_name' value='".$args['name']."'>
<input type='hidden' name='item_number' value='".$args['id']."'>
<input type='hidden' name='amount' value='".$args['value']."'>
<input type='hidden' name='no_shipping' value='1'>
<input type='hidden' name='return' value=''>
<input type='hidden' name='cancel_return' value=''>
<input type='hidden' name='no_note' value='1'>
<input type='hidden' name='currency_code' value='USD'>
<input type='hidden' name='bn' value='PP-BuyNowBF'>";

if ($args['options'] == 'yes') {
$output .="<table><tr><td><input type='hidden' name='on0' value='First issue'>First issue</td><td>
<select name='os0'><option value='Current issue'>Current issue<option value='Next issue'>Next issue
</select></td></tr></table>"; }

$output .= "<input type='image' src=''
border='0' name='submit' alt='Make payments with PayPal - it's fast, free and secure!'>
<img alt='' border='0' src='' width='1' height='1'>

return Keep($output);

First, the markup itself is defined. You shouldn't need to change this.

Next we define a special function which will process the markup. The first line inside this function specifies a variable which holds your PayPal account name (usually an email address). I've done this for easy editing and you could similarly factor out other information if so desired.

Following are a few lines of no concern, then the line that defines 'business' - using our variable previously defined.

Next comes 'item name', 'item number' and 'amount'. These are all specified by the values you include in the markup as name=, id= and value= respectively.

Now comes some stuff you'll likely want to edit.

'no_shipping' specifies, in this case, that I don't want to include shipping details in the transaction. 'return', 'cancel_return' and 'currency' should be fairly self explanatory if you've got your own button code to hand. Substitute values as required. Make sure any edits leave everything single quoted. PayPal generates HTML with double quotes.

'bn' I'm not sure about. Copy from your own generated code as necessary.

The next section is only included if the markup contains options=yes and I am using this to include 'additional options' on the transaction - in this case, which issue a new subscription should start with, giving the buyer the choice. If you don't want this kind of capability, delete the entire if, or just never use the options=yes markup value.

Finally, we close off the code with a submit button. Here you'll want to make sure you have the correct reference to the button image you want. This is specified after <input type='image' src='

And that's it. Not necessarily as straightforward as some would like, but it is a start!


  • There are still a fair number of values in the form that are hard coded. I have shown two ways of factoring these out:
    • Specifying a variable in the function, which means editing for specific sites is slightly easier, but the setting is still 'site-wide' (or at least as wide as the scope of the customization file).
    • Specifying a markup value. You can see how to include these values in the three lines for 'item name', 'item number' and 'amount'. The ParseArgs() function does all the hard work of extracting the values so you can just insert a new reference to $args['whatever'] and then you can use whatever= in your markup.
  • A nice touch would be to find a way to convert a string 'Main.Paid' to the equivalent full URL so that either a variable or markup value could be used to specify the 'return' and 'cancel_return' pages. If anyone can tell me how to do the URL translation (which would need to take account of short URL settings) then I will add in the required code.

Release Notes

Marc 27th, 2006 Recipe added.

This is my first cut. The only change I think I need to make for my own purposes would be the URL conversion from page names. Anybody else feel free to improve on this.


Comment: PayPal Donate Button

I have created an update for PayPal Donate buttons which use only the encrypted data. Put this in your config.php:

#Define PayPal Donate button
Markup('Donate', 'inline',  '/\\(:Donate (.*?):\\)/e', 'PayPalDonate("$1")');

function PayPalDonate($opts) {
        $args = ParseArgs($opts);
        $but = $args['but'];
        if (empty($but)) : $but = 21; endif;

        $output = "<form action='' method='post'>
        <input type='hidden' name='cmd' value='_s-xclick'>
        <input type='image' src='".$but.".gif' name='submit' 
        alt='Make payments with PayPal - it's fast, free and secure!'>
        <img alt='' src='' width='1' height='1'>
        <input type='hidden' name='encrypted' value='-----BEGIN PKCS7-----".$args['details']."-----END PKCS7-----'></form>";

        return Keep($output);

Use it inside your content as: (:Donate but=05 details=HERECOMESTHELONGENCODEDCONTENT:) where but is the button number you want to use, from It is also available at

See Also

Cookbook /
PayPalButtons  Creating neat markup for otherwise sloppy PayPal button forms (stable)
PayPalCart  Provides markup for PayPal shopping cart buttons. (in active use)
PPDonate  Create links to accept donations via PayPal (Beta)