Table of Contents
Paypal Plugin Integration
This document details the variables that will be provided to payment gateway objects, and values that are expected to be returned. This is primarily intended for interaction between the PayPal plugin and other plugins.
Starting with version 0.5.0, inter-plugin communications are handled by web service functions in services.inc.php. The format of the function call is
$status = PLG_invokeService('paypal', 'ServiceName', $args, $output, $svc_msg);
The returned value will be one of the constants defined in lib-plugins.php, such as PLG_RET_OK or PLG_RET_ERROR. The value will be returned in $output and may be an array or a scalar value.
The $args parameter is normally an array and its values will depend on the service being invoked.
Button Creation
Purchase buttons for external items are created by calling PLG_invokeService('paypal', 'genButton', $args, $output, $svc_msg). The $args parameter should be an array and should contain the following name⇒value pairs:
Name | Type | Description |
---|---|---|
item_number | string | (required) Product number or SKU. Plugins should preface this with plugin_name:, e.g. subscription:201029347 . Options selected in the shopping cart (color, size, etc.) are joined by colons and appended following the pipe character. |
item_name | string | (required) Name of item or short description |
amount | float | (required) Total purchase amount. This number should include any processing fees. |
btn_type | string | The type of “Buy Now” button being requested. Valid options are “buy_now”, “pay_now”, “subscription”, and “donation”. This item may be omitted, but the request should include at least a buy_now option or the add_cart option. |
add_cart | mixed | Setting this parameter to any value causes an “Add to Cart” button to be included in the $output array. |
custom | array | Array of custom parameters to pass to the gateway. This can contain other information related to the purchase that might not otherwise be known when the IPN message is processed, such as the user ID or some product options. The use for this is gateway-specific. PayPal accepts a custom string that is returned unmodified in the IPN notification. For Amazon, this is appended to the item number. |
quantity | float | The quantity of items purchased. If omitted, the gateway may prompt the buyer for a quantity. |
options | array | (optional) Similar to the “custom” value, this contains product options. Some gateways don't support the use of product options, so information in this variable should also be contained in “custom”. |
weight | float | Product shipping weight. If greater than zero this will be used to indicate that there is a shipping charge. Otherwise the product will be considered not shipped, such as a virtual product. |
shipping_type | integer | Valid values: 0, 1, 2. Used to override the no_shipping value. There is no default for this. |
shipping_amt | float | If product is shipped, this indicates the shipping amount. |
taxable | integer | If greather than zero, the product is taxable. |
tax | float | Tax amount. Only applied if “taxable” > 0. |
return | string | An optional URL where the buyer is sent after completing the purchase. The PayPal plugin's home page is used by default. |
The $output variable is an array of buttons, containing the requested button type (“buy_now”, “pay_now”, etc.) and/or an add_cart element:
$output = array( 'buy_now' => "Buy Now" button code, 'add_cart' => "Add to Cart" button code );
Example:
$args = array( 'btn_type' => 'donation', 'item_number' => 'donation:2238746', 'item_name' => 'Donation to the Food Drive', 'amount' => 10, 'quantity' => 1 ); $status = PLG_invokeService('paypal', 'genButton', $args, $output, $svc_msg); if ($status == PLG_RET_OK) { $button_code = $output['buy_now']; } else { $button_code = ''; }
Finding the Currency
A service function is available to return the configured currency as a short string (“USD”, “CAD”, “GBP”). In this case the $args parameter is not used and $output contains a string.
$status = PLG_invokeService('paypal', 'getCurrency', $args, $output, $svc_msg); $currency = $status == PLG_RET_OK ? $output : 'Unknown';
Getting a URL
For an external plugin to get a URL to a page controlled by the PayPal plugin, the getUrl service can be invoked. Currently the only URL available is for a specific IPN transaction so that another plugin can link to the transaction by which it was paid.
$args = array( 'type' => 'ipn', // the only type currently supported 'id' => $ipn_txn_id ); $status = PLG_invokeService('paypal', 'getUrl', $args, $output, $svc_msg); if ($status == PLG_RET_OK) { $url = $output; // something like "http://yoursite.com/paypal/index.php?view=ipnlog&op=single&txn_id=29384857" }
Plugin Services
Plugins wishing to interact with the PayPal plugin must provide some service functions of their own. These are also called via PLG_invokeService(), so functions that don't exist will be ignored.
service_productinfo_piName
Sets the $output variable to an array of values describing the plugin's product. The full product ID is already known to the Paypal plugin, and is provided in the $args parameter as an array:
$args = array($plugin_name, $item_id);
The plugin's service_productinfo_X() function then creates the $output value:
$output = array( 'product_id' => implode(':', $args), 'name' => $item_name, 'short_description' => $item_description 'description' => $item_full_description, 'price' => $unit_price, );
The description is optional, but all other fields should be defined.
service_handlePurchase_piName
This function is called by the payment gateway's IPN processor and handles the actual purchase. The $args array is populated with information from the IPN message in two parts: 'item' contains item information while 'ipn_data' contains the full IPN message. The $output variable should be populated with information similar to service_productinfo_piName, but with a bit more detail.
$item = $args['item']; $ipn_data = $args['ipn_data']; $item_id = explode(':', $item['item_id']); // split id into plugin name and item ID $sql = {query to retrieve an item} $A = DB_fetchArray(DB_query($sql), false); $output = array('product_id' => $item['item_id'], 'name' => $A['name'], 'short_description' => $A['name'], 'description' => $A['description'], 'price' => (float)$A['price'], // The rest are needed only for file download items: 'expiration' => NULL, 'download' => 0, 'file' =>'' );
Detail of the 'item' element of the $args array:
Name | Description |
---|---|
item_id | Item ID number, as received with options |
item_number | The item number alone, removing the options |
name | The item's name |
quantity | Quantity purchased |
price | Total price for the items, excluding shipping, tax, etc. |
shipping | Shipping charge |
handling | Handling charge |
tax | Sales tax |
options | String of options, colon-separated |
Payment Processing (IPN)
Notifications are received via Instant Payment Notification. The return URL is specified with the button code from PAYPAL_genButton(). The notification variables are based on PayPal's IPN structure, so other gateways should convert their variable names to PayPal's. These are the variables that are used.
Name | Description |
---|---|
txn_id | Transaction ID |
payer_email | Payer's email address used to log into the gateway |
payer_name | Payer's full name |
pmt_date | Payment Date |
pmt_gross | Gross payment amount including all fees, taxes & charges, and before deducting the gateway's payment fee. |
pmt_tax | Tax amount charged |
pmt_handling_amount | Handling charge |
pmt_shipping | Shipping charge |
currency | Currency, e.g. “USD” or “CDN” |
gw_name | Name of gateway, e.g. “PayPal” or “Amazon” |
pmt_status | Payment status, e.g. “Completed”. Meaning of this depends on the gateway. |
custom | Array of custom items, such as user ID, order ID, transaction type. |
Other Integrations
Once Paypal is able to notify plugins regarding transactions, the possiblity exists to have a general-purpose “credits” plugin which will store account balances. This could be used to allow site users to purchase “points” via Paypal which could then be applied to future use.
Points could also be awarded for forum participation (perhaps when a positive Group Comfort Level is awarded), published stories, or other activities.
Plugins would need to check for the Credits plugin, and decisions need to be made on how to handle Paypal-Credits-{plugin} transactions. The internal workings would be a bit different. For example, the Classifieds plugin would need to track the days available to users as they are purchased and used. If a Credits plugin is used, then Classifieds would interact with it to redeem points, where (for example) one day = 500 points. A dollar value would also need to be assigned to points, such as $0.01 per point.
It may also be desirable to track Free points, awarded by administrators or for site participation, from Paid points. Paid points may be refundable, Free points certainly are not. If awarding points for “Donations”, they should go into the Free point pool, and Free points should be used first when points are redeemed.