State of the state
September 18th, 2007I gave it one and a half strong days but in the end I was defeated by the programmer-unfriendly but incredibly user-friendly WordPress. I learned WordPress and Paypal from scratch in a short time frame and as I see it things are not that far from completion. Here is what I learned and how I would handle the road map. You, of course, can do whatever you’d like
I won’t have time to complete this module.. sorry.
For clarification I renamed the plugin to siabpp for ShowInABoxPayPal. The Have Money Will Vlog module is named pledgedrive.
First let me start with how to interact with paypal.
The pledgedrive plugin is using the NVP (NameValuePair) method of communicating with Paypal. Its pretty straightforward. The site simply POSTS to Paypal with specifically named POST variables (ex. <input name=”myvar” type=”hidden”>. Paypal will then do a POST back to the site returning a transaction identifier, response code, amount and other wonderful data. Paypal also provides some nice options to verify that it the POST did indeed come from Paypal (ipn.php is a perfect implementation of this.. done by the original author)
Now for the dataflow with the pledgedrive plugin. We’ll ignore the project specific information for this because it’ll be thrown out the window anyhow. Paypal information was sent via the comments area on the site. This is the flow
- Project page is presented with a comment form on the bottom. The comment form was modified via the theme to add in the donation information.
- When the comment was posted the <form> was sent to WordPress. pledgedrive grabbed the newly submitted comment and checked it for donation information via ” add_action(’comment_post’, ‘pdproject_comenttesting’); ”
- If donation information was added to the comment the information was INSERTed into the database setting it as “unconfirmed”. This was to grab the user’s name, email address, comment, etc.
- The comment was displayed to the user for a preview
- The trick was that if the comment was “approved” it was actually a POST to Paypal (not to WordPress), if the comment was rejected the POST was to Wordpress and the newly INSERTed row was deleted.
- The user goes off to Paypal to make the payment
- Paypal would post back to WordPress to ipn/ipn.php in the plugin directory. This module received the call and did an UPDATE to the corresponding entry that matched on the POST variable item_number1 (i.e $_POST[’item_number1′] ) marking it as “confirmed”
The pledgedrive did other actions but this is the main meat of it. The two big pieces in here are that (1) there was a hack in the theme to POST to paypal vs. WordPress and (2) the “preview” page is crucial because it allowed WordPress to grab the data BEFORE it was sent out to paypal (e.g. User submits data –> WordPress –> Stored in Database –> Preview to user –> Paypal). Realistically we’ll have to do something similar.
Now how do we modify it to work in the new form and be a true plugin (i.e. no hardcoding)? Somewhat in order of importance.. sorta.
- Build a site URI to accept (bulk of the work)
- A URI that is passed to a function (I have no idea how to do this)
- The function would do the following
- Accepts/validate/Stores POST or GET data (incoming donation request)
- Does an INSERT to the DB if all of the required fields are passed in
- Returns an HTTP 304 redirect to a paypal URL filled with a GET request ex.
https://www.paypal.com/cgi-bin/webscr?cmd=_xclick-subscriptions&business=mybiz%40gmail%2ecom&item_name=DonationToMybiz&no_shipping=1&no_note=1¤cy_code=USD&bn=PP%2dSubscriptionsBF&charset=UTF%2d8&a3=25%2e00&p3=1&t3=M&src=1&sra=1 - The 304 redirect would include a unique transaction identifier (stored in WordPress DB)
- User is then at Paypal and away from the grasp of the module
- Flow…..
- User –[POST/GET]–>WP Plugin
- WP Plugin –[304 Redirect–>User
- User –[GET]–>Paypal
Only an extremely geeky-techy-savvy user would see this happening…otherwise its “behind the scenes” and only delays the transaction by a few seconds.
- Modify ipn.php to adapt to new MySQL structure
- ipn.php accepts the POST back from Paypal
- Matches up the POST back from Paypal with an existing transaction UPDATEs the transaction and set confirmation to 1 (for A-OK).
- if nothing matches it should create a new transaction item with confirmed = 1 and set as Anonymous (paypal email address are never shown).
- Add in Transaction history log to the Plugin configuration area? Or to the options?
- The transaction history log is simply a SELECT * from pd_pledges.
- Columns shown would include Name, paypal email, amount, confirmed (t/f), subscription/donation, edit/remove options
- The transaction history log is also a list of who will be displayed on the “Sponsors list”.
- Already done via the pledgedrive module function pledgeprive_contriblist()
- function needs to be modified so that it pulls ALL unexpired contributions currently it limits pledges pulled to a specific post id. Additionally the joins need to be removed (since the tables don’t exist any longer)
- Add in paypal API functions (note paypal API calls are different than the calls above; Paypal API calls require an API key and certificate to be installed by the user vs. only needing an email address).
- 3 new fields are needed for the API key (user, api Key, api certificate) in the Plugin configuration settings
- the API call allows for the use of the NVP Paypal call TransactionSearch() which will return a listing of up to 100 transactions.
- Since each transaction is tagged as part of this website and performed through the module the transaction_search() call can limit pulled transaction to those only tagged as part of this website (since a users’ paypal account can be used for multiple purposes)
- A routine would loop through each item returned from that transaction_search() and compare against the local transaction (in pd_pledges).
- A subscription is considered expired if it is “canceled” or if no payment has been made for over 60 days.
- A donation is considered expired if it is over 30 days old
- A tinyint(1) (i.e. Boolean) column (expired) on the pd_pledge record is flipped to 1 to indicated expired
- Financial Gauge
- The widget will display the financial gauge from 0 to user’s requested amount
- Already implemented via DisplayGuage in pledgedrive module
- The gauge will reset on a set day every month based on a user defined variable in the plugin configuration settings. Ex if the user set the day to the 15th, the gauge would display options from May 15 to June 14th, June 15th - July 14th would be a new period.
- Cool feature. Gauge display BOTH donations AND subscriptions within the x day period in different colors. The Top of the Gauge would the SUM of the two but two colors would be overlayed to display the difference between subscriptions and donations. example if there were $400 in one-time donation and $500 in subscriptions the gauge would display $900 with $400 in red to demonstrate one-time donations and the top $500 in green to demonstrate subscriptions/recurring payments.
- Add in embed code
- 1,000 ways to do this.
A suggestion… scrap the code already written in pledgedrive since its heavily, heavily dependent on clientside javascript routines. Build the gauge using the GD Image library as a dynamic image. Cache the image on disk for an hour (rebuild the image every hour). The embed code would simply be a <img src=”"> with a <a href=”" to get back to the site or even a small <form> to provide an amount, etc. otherwise have someone build a little swf files that dynamically builds the gauge similar to the chip-in type module. Kinda slick but also its flash.. uggh.
This goes back to the #1 objective. The URI should accept both a GET or POST variable for its processing and if any information is missing it should simply prompt the user for it via a confirmation page otherwise accept the data and send the user over to paypal.
- 1,000 ways to do this.
What is completed (very little)
- Plugin can be activated/deactivated
- Plugin options are adjusted via the Plugin settings page (NOT the options area; it seemed more logical)
4 functions make up the current module
siabpp_conf
siabpp_widget($args)
siabpp_widget_register()
siabpp_config_page()
All new functions should follow the convention established (i.e. siabpp_ ).
The module has two functions
- Creates a widget to POST data to paypal (also future home of the gauge)
- add_action(’init’,’siabpp_widget_register’) //calls the siabpp_widget_register function after initialization
- register_sidebar_widget(’SIABPaypal’, ’siabpp_widget’); //called within siabpp_widget_register has to be called after initialization otherwise register_sidebar_widget() doesn’t exist and you get a “function not found” PHP error. Its the only reason for the siabpp_widget_register function
- siabpp_widget contains standard echos ($beforetitle, $aftertitle, etc.) and regular ‘ole HTML printed directly (not returned.. aahhh!)
- Administrative Configuration page
- add_action(’admin_menu’, ’siabpp_config_page’);
- siabpp_config_page() for the most part pretty straightforward. Standard HTML for the elements (*gasp*) and all items are Stored/updated view the PHP at the top of the function. To add a new configuration option it needs to be added to the array at the top ($key => $value == “FormElementName” => “Default Value”) AND the element added to the form in the HTML.
Whew! That was two days of pure…. um. joy? Ya, I’m not developing to Wordpress anytime soon. I really should get back to my userpoints module and finish that up before I head off to China.
Sorry I couldn’t get this done. I had no idea how difficult WordPress would turn out to be….
