Adding a Custom Payment Gateway to RSVPMaker

RSVPMaker now supports two payment methods, PayPal and Stripe, but I recently got a request from someone wanting to add an additional custom payment gateway. Now you can by using the hook ‘rsvpmaker_cash_or_custom’.

I’ve always tried to keep RSVPMaker developer-friendly for those who want to extend it. If you come up with something cool that ought to be part of the standard distribution, I hope you will consider contributing it to the project.

The new Default Payment Gateway heading on the settings page now includes 3 options: PayPal, Stripe, and Cash or Custom. The Cash or Custom setting can also be used by anyone who wants to display pricing on the website even if they will tell people to pay by cash or some other means, rather than paying online.

In the case where you are implementing a custom payment gateway, you would write a routine something like this.

add_action('rsvpmaker_cash_or_custom','my_cash_or_custom',10,6);

function my_cash_or_custom($charge,$invoice_id,$rsvp_id,$details,$profile,$post)
{
	echo '<h1>Variables Passed to My Custom Function</h1>';
	echo '<h3>Charge</h3>';
	echo '<p>'.$charge."</p>\n";
	echo '<h3>Invoice ID #</h3>';
	echo '<p>'.$invoice_id."</p>\n";
	echo "<p><em>Tracking # for payments</em></p>";
	echo '<h3>RSVP ID #</h3>';
	echo "<p><em>Unique ID for main database record for registration</em></p>";
	echo '<p>'.$rsvp_id."</p>\n";
	echo '<h3>Details</h3>';
	echo "<p><em>Details about the transaction</em></p>";
	echo '<pre>'.var_export($details,true)."</pre>\n";
	echo '<h3>Profile</h3>';
	echo "<p><em>Details about the person</em></p>";
	echo '<pre>'.var_export($profile,true)."</pre>\n";
	echo '<h3>Post</h3>';
	echo '<pre>'.var_export($post,true)."</pre>\n";	
}

Normally, what you would do in this space is output the payment button or other user interface code for the payment gateway functionality you are adding. This sample function just dumps all the data you get to work with related to the pricing and the information the user submitted about themselves, such as the email address for a confirmation message.

Want to add a custom payment method?

You would then take responsibility for handling the user’s submission. Ideally, you want to capture confirmation of the completed transaction and log the payment as complete in the RSVP report. Here is the function call.

rsvpmaker_custom_payment('blockchain',$amount,$rsvp_id,$event, $transaction_id);

In this example:

‘blockchain’ is the label for my custom payment method
$amount is the amount paid in this transaction
$rsvp_id is the ID for the event registration
$event is the post id ($post->ID)
$transaction_id is an optional transaction identifier, intended for an ID # you got back from the payment service

Here is what you get to work with (the output of the test function shown above, with an example user entry).

Charge

300

Invoice ID #

rsvp126102

Tracking # for payments

RSVP ID #

Unique ID for main database record for registration

5

Details

Details about the transaction

array (
  'email' => 'david@carrcommunications.com',
  'first' => 'David',
  'last' => 'Carr',
  'phone' => '',
  'phone_type' => 'Work Phone',
  'payingfor' => '2 Special Seating @ 150.00',
  'total' => 300,
  'pricechoice' => 1,
  'id' => '5',
  'yesno' => '1',
  'event' => '4337',
  'owed' => '0.00',
  'amountpaid' => '0.00',
  'master_rsvp' => '0',
  'guestof' => NULL,
  'note' => '',
  'participants' => '2',
  'user_id' => '1',
  'timestamp' => '2017-10-16 17:24:05',
)

Profile

Details about the person

array (
  'email' => 'david@carrcommunications.com',
  'first' => 'David',
  'last' => 'Carr',
  'phone' => '',
  'phone_type' => 'Work Phone',
  'payingfor' => '2 Special Seating @ 150.00',
  'total' => 300,
  'pricechoice' => 1,
  'id' => '5',
  'yesno' => '1',
  'event' => '4337',
  'owed' => '0.00',
  'amountpaid' => '0.00',
  'master_rsvp' => '0',
  'guestof' => NULL,
  'note' => '',
  'participants' => '2',
  'user_id' => '1',
  'timestamp' => '2017-10-16 17:24:05',
)

Post

WP_Post::__set_state(array(
   'ID' => 4337,
   'post_author' => '3',
   'post_date' => '2017-10-16 13:13:35',
   'post_date_gmt' => '2017-10-16 17:13:35',
   'post_content' => '',
   'post_title' => 'Replication Test',
   'post_excerpt' => '',
   'post_status' => 'publish',
   'comment_status' => 'closed',
   'ping_status' => 'closed',
   'post_password' => '',
   'post_name' => 'replication-test-2018-03-12-190000',
   'to_ping' => '',
   'pinged' => '',
   'post_modified' => '2017-10-16 17:21:00',
   'post_modified_gmt' => '2017-10-16 21:21:00',
   'post_content_filtered' => '',
   'post_parent' => 0,
   'guid' => 'http://classicsarefun.com/?rsvpmaker=replication-test-2018-03-12-190000',
   'menu_order' => 0,
   'post_type' => 'rsvpmaker',
   'post_mime_type' => '',
   'comment_count' => '0',
   'filter' => 'raw',
))

Creating an Events Registration Landing Page with RSVPMaker

Improvements for RSVPMaker often arrive when I see the need for them in my own projects, and recently I found myself creating a landing page for a series of workshops at Online Presenters. This is a Toastmasters club I founded, which focuses on helping members develop skills for webinars and online meetings, presentations, and trainings of all sorts.

landing page example
Online Presenters Landing Page

Because the workshop series is intended as a recruiting tool, I wanted our promotions (including some paid Facebook ads) to direct visitors to a page with a clear call to action — RSVP Now! — with no distractions that might tempt them to click away to another page or blog post. That meant the regular page sidebar and the menu at the top of the page had to go. Continue reading “Creating an Events Registration Landing Page with RSVPMaker”

Cutting Prices for Events Website Hosting

I’ve updated my pricing on two easy ways to get access to a WordPress website with RSVPMaker events management already integrated, lowering the price of entry to $75 from $99. Hosting your site with Carr Communications Inc., creator of RSVPMaker, makes sense if event management is one of the main purposes of your site. We can offer closer support, including PayPal setup, if you host your website with us.

Subdomain Hosting

For $75 per year, you get a website at an address like seminar.rsvpmaker.com. We handle the web hosting and technical details, but you get access to all the standard WordPress features, plus the event management capabilities of RSVPMaker. This fee includes assistance setting up the site to allow you to accept event payments via PayPal.

In addition to posting your events, you can promote them through the blog and build out other pages for details like speaker bios and your event agenda.

Sign Up Now

Subdomain Label
Administrator’s email address


Independent Website Hosting

Price: $175 per year for hosting of your own independent website, plus configuration assistance and RSVPMaker support. This gives you greater freedom to configure your site however you want and make your own decisions about adding themes and plugins, without being limited to those available on RSVPMaker.com.

Sign Up Now

Domain Name


Note: Hosting fee does not include domain registration or copywriting, consulting, and design services. It does include setup and proper configuration of WordPress site and RSVPMaker, as well as updating of all code so you always have the most recent, most secure, and most functional versions.

As with hosting anywhere else, the customer gets FTP access to the server and can perform their own additional customizations. Includes 5 GB disk space. Data center services provided by LiquidWeb, comparable to standard shared hosting plan.

How RSVPMaker Looks Up Prior Event Registrations

The latest updates to RSVPMaker were inspired in part by this post on the WordPress.org support forum for the plugin.

Users within my organization tend to forget that they’ve registered for an event and wind up RSVP’ing multiple times. How can I restrict duplicate entries with an error message that says that they’ve already RSVP’d to an event?

One of the new ways I am trying to address this is with a JavaScript / AJAX powered lookup of any prior RSVPs associated with the user’s email address. As they start to type their email address into the form, they will see prompts to update any matching record, and as they type more of their email address the list of possible matches should narrow until there is only one (or none if they had not previously RSVP’ed using that email address).

Looking up matching RSVPs by email address.

A user can follow the link in that prompt to update their previous registration, if necessary. Or they may just need to be reminded that a registration for them is already on file.

This mechanism is actually a fallback. The standard email confirmation message includes an Update RSVP link users can follow to update their record. However, that only works if they go back and find the confirmation message.

Similarly, when you invite people using the MailChimp integration, their email address is embedded in the RSVP Now button. The idea there was always to save them some typing by looking up profile data from any previous RSVPs so they would not have to type it in again. (In the process of updating this code, I fixed a few bugs that were preventing this process from working properly).

If someone responds to the invitation, forgetting that they previously registered, RSVPMaker will ask them if they want to update their previous response. Similarly, if RSVPMaker detects a cookie associated with a previous response to the same event, it asks if they want to update that response rather than entering a new one.

update rsvp prompt
Update RSVP? prompt

What is the scenario where the user would NOT want to update the previous RSVP? There are scenarios where the user wants to enter multiple independent RSVPs under the same email address. Maybe an administrative assistant is registering several executives but wants all the confirmations to come to his or her email address. Another example is a couple that shares an email address, where the husband’s RSVP should not overwrite the wife’s or vice versa. My preference would be that one person enter an RSVP with one or more other people indicated as guests, but it doesn’t always work that way in practice.

Security Considerations

There are a few potential security concerns with this scenario. The high security option would be to require users to login with a password before completing the RSVP form, and their identity would be tied to that login. RSVPMaker supports making logins required, but in many cases the more important goal is to make it as easy as possible for people to register without having a pre-assigned password.

If any information gathered on the form is sensitive, I recommend tagging it as private. You can see that with the tagging of the phone # and related fields in the default form:

The form builder utility (the popup you get when you click the “Generate form” button) also allows you to mark fields as private. If data has been recorded for that field, the message “Private data on file” is displayed instead of the private content. In other words, this prevents people from using your email address to look up your phone number or other information designated as private.

However, a mischievous or malicious user could use the lookup by email function to alter someone else’s RSVP response. I haven’t seen this be a problem, but it’s not impossible.

Design Considerations

In the AJAX-powered email lookup example shown above, the data entry field for email appears before those for first and last name. The idea is to get them to enter their email address first. If we match it to a record, we want to do that before they have reentered a lot of the same information.

I’ve made this the new default form layout for new users, but established users of RSVPMaker may need to tweak their RSVP form code. The form builder now includes an option to specify that the email field should come first.

Creating Custom WordPress Websites (and Site Networks) for Event Management

Over the past several years, I have used WordPress and my RSVPMaker plugin to create a series of membership-based websites that revolve around signing up to attend events or in some cases fill specific volunteer roles at events (range safety officer at a rifle range, speakers and evaluators for Toastmasters clubs).

This is a progress report on my most ambitious project to date in this category, shared partly so anyone trying to create something similar will consider hiring me as a consultant. But I’ll also share some tips I hope will be useful to other developers.

As part of my WordPress for Toastmasters project, I took advantage of the multisite support in the WordPress software to allow officers in these public speaking sites to create a free website as a subdomain of toastmost.org (mysite.toastmost.org, yoursite.toastmost.org, etc.). Although the software for managing meeting agendas is available as open source, many leaders in Toastmasters would like to take advantage of the software without being responsible for setting up an independent website and installing WordPress plugins.

Although WordPress was originally created for bloggers, it can be extended with plugins to add functionality such as event management. It also includes a fairly sophisticated user security system (occasionally hacked but quickly patched) including necessary functions like a process for users to reset their passwords when they forget them. I use this as the basis for a membership website in which you must be logged in to view members-only content and certain functions are reserved for site editors or administrators. Most of these functions are well documented on the WordPress developer reference site. For example, the function is_user_logged_in() tells me if a website visitor has authenticated as a user. For WordPress multisite, I need is_user_member_of_blog() to determine if the user is not only logged in but a member of the blog currently being displayed.

If the documentation doesn’t answer all your questions about how a function works, you can download the source code from wordpress.org and go spelunking through functions until you get a better idea of what exactly is going on. I’ve had to do that occasionally for functions in both WordPress and popular add-ons like BuddyPress (for example, to figure out why BuddyPress seemed to behave differently in a multisite environment). Meanwhile, I’m working on fleshing out RSVPMaker’s own developer documentation (see: Developer Functions for Extending RSVPMaker).

WordPress provides a default user interface for allowing members to register for an account and create a site on a multisite network. In my case, this was something else I needed to customize, so each new site would be initialized with a theme reflecting the branding and trademark disclaimers required by Toastmasters International, along with some starter text for a home page and starter templates for meeting events.

A network of WordPress multisite events websites.

In addition, before they can register as users and create a site, I require them to sign up for the MailChimp mailing list for the project. RSVPMaker includes an API integration with MailChimp, including the ability to verify that an email address is subscribed to a mailing list. So I have them sign up for the list used for project announcements and include instructions for creating a site as part of the confirmation message. The link they follow to the signup form includes their email address as a query parameter. Before displaying the signup form for creating an account, I use the API to verify their subscription.

Requiring that they sign up for the MailChimp mailing list also serves to filter out hackers and spammers, who typically won’t go to the trouble of signing up for the email list and verifying their subscription with MailChimp. Why bother, when there are so many easier targets on the web?

There are other, more general purpose membership management plugins available, but the great glory of creating something custom is it can be exactly what you want and need.

If you would like help creating custom events websites, I am available as a consultant. Drop me a note at david@rsvpmaker.com.

Developer Functions for Extending RSVPMaker

If you are creating a custom events website for which RSVPMaker is the foundation but you want to add your own flourishes, you should be aware of several utilities functions.

I created these for my own selfish purposes. As someone who customizes events for specific purposes, I have gradually gotten to the point where I don’t want to deal with the internal complexities of my own plugin. And from studying the APIs of other software I’ve had occasion to modify or extend, I’ve started to figure out what that ought to look like for RSVPMaker.

Here are a few basic functions that are useful if you are trying to get events data out of the system and display it in some custom manner, for example in a widget or a shortcode different from the ones RSVPMaker includes.

To get a listing of future events use get_future_events:

$events = get_future_events();

The variable $events will be an array of objects, each of which represents an event post. The event post objects include all the usual blog post fields such as post_title, post_author, post_content, with the additional fields datetime (the SQL timestamp for the date and time of the event) and date (date formatted as Month Day, Year as in July 6, 2017). You can add where and limit parameters to the query. You then loop through the results like in this example using a shortcode.

function rsvpmaker_utilities_test () {
$output = '';
$events = get_future_events('post_author=1',10);
foreach($events as $event)
  {
	$output .= sprintf('%s %s',get_permalink($event->ID), $event->post_title,$event->date);
  } return $output;
}
add_shortcode('rsvpmaker_utilities_test','rsvpmaker_utilities_test');

The full function signature is

get_future_events ($where = '', $limit='', 
$output = OBJECT, $offset_hours = 0)

Changing the $output parameter from OBJECT, the default, to ARRAY_A, would give you an associative array for each event. The fourth parameter, $offset_hours is used to prevent events from expiring off the list the moment their start time is past. I’ve come across a number of situations where it’s preferable to have an event displayed several hours past the start time, for example so people who are arriving late or are in the middle of the meeting can still look up details such as the agenda or location.

There is also get_past_events function, which works almost the same way (no $offset_hours parameter) but lists past events starting with the most recent and counting backwards.

Here’s an example that would pull in all the past events since the start of 2017.

$events = get_past_events("datetime > '2017-01-01' "); 

You can retrieve a single event using get_rsvp_event. It accepts 2 parameters, $where and $output (defaults to OBJECT)

$event = get_rsvp_event('datetime > CURDATE');

or

$event = get_rsvp_event('ID=3');

Here are a few others that might come in handy.

Use get_events_by_template to retrieve all the events associated with a specific template, in ascending date order by default and as row objects by default.

//showing defaults
get_events_by_template($template_id, $order = 'ASC', $output = OBJECT);
//example
$template_31_events = get_events_by_template(31);

Count of future events (no parameters)

$count = count_future_events ();

Get the date associated with an event, based on ID, with get_rsvp_date. SQL date will be returned. To format, you might use strtotime as in this example.

global $post;
$timestamp = get_rsvp_date($post->ID);
$t = strtotime($timestamp);
echo date('F jS, Y',$t);

Because a single event can span multiple dates, there is also a get_rsvp_dates function that returns an array of timestamps. This is also the version you would have to use if you also want to retrieve the event duration. Look at the rsvp_date_block function in rsvpmaker-pluggable.php for an example of how RSVPMaker uses this internally to display the date or dates at the top of an event post.

To test whether an event is in the future, use:

is_rsvpmaker_future($event_id, $offset_hours)

The $event_id is the post ID, while $offset_hours (default = 0) is the number of hours past the start time where this will return true. For example, you wouldn’t necessarily want it to evaluate to false for an all-day event.

To retrieve the same values you would get from the rsvpmaker_upcoming shortcode (or the comparable Gutenberg block), you can use:

rsvpmaker_upcoming_data($atts)

This returns an array of rows that you can feed into your own display function.

$atts is an array of the same attributes you would use with the shortcode. Examples: $atts[‘posts_per_page’] (default: 10) or $atts[‘days’] (days worth of results to include (default: 365). The stricter of the two limits will be applied.

To check whether an event is based on a template, this function will return either the ID of the template or false if there is none.

has_template($post_id)

Can I Help?

If you would like help creating custom events websites, I am available as a consultant. Drop me a note at david@rsvpmaker.com. Some of the customizations I’ve worked on over the past couple of years include:

  • Signups for volunteer roles at a rifle range, with a reporting back end to show which roles are filled versus open for each shift.
  • A network of membership-based event websites for a nonprofit organization (Toastmasters), set up as subdomains using WordPress multisite. Chapter officers can sign up to get a free site, using a custom user and site registration process. They can then manage their own events and create accounts for their own members. They can collect event registrations via RSVPMaker but also sign members up to fill specific roles using the WordPress for Toastmasters extensions.
  • In a couple of cases, I’ve made signing up for MailChimp a prerequisite for creating a user account. The MailChimp confirmation message directs people back to a website page with a coded url that includes their email address. Before the signup form will display, their subscription must be verified via the MailChimp API.

Toward a Proper API

Going back to 2010, RSVPMaker has included a mechanism for developers to override pluggable functions with their own versions. The functions documented above represent the beginnings of a cleaner API.

Gathering Different or Additional Information About Guests

This small feature update came in response to a request from a user who was planning an event for which parents will register their themselves and their children. The event organizers need some additional information about the children, such as grade level.

RSVPMaker already allowed you to set up a registration form where some fields included on the main form will not necessarily be displayed on the guest form. Now you can specify that a field should be displayed only on the main form, on both the main form and guest form, or only on the guest form (not the main form).

Here’s what that looks like with the RSVPMaker form builder:

Guest-only setup

If you edit the shortcode directly, you would make it:


The guestfield attribute set to 1 means “also display on guest form” whereas setting it to 2 means “only display on guest form.”

Additional field on guest form
Host and guest (parent and child in this example) on the RSVP Report.

See the demo.

How Do You Use RSVPMaker? Share Your Story in a Guest Blog or Video

Sample Event

After years of working to improve RSVPMaker, answering questions about it, and troubleshooting problems, I want to hear from those of you who have made it work for you in your business or nonprofit.

Can I get you to share your story in a guest post on the RSVPMaker blog? I would also be interested in connecting with you in an online video meeting to interview you about your story. This can be your opportunity to ask questions or tell me about improvements you would like to see at the same time.

What do you say?

David F. Carr, versatile and inventive writer, editor, and web consultant
Author, Social Collaboration for Dummies

See my work on Forbes, connect with me on TwitterLinkedIn, or Facebook
Appointment scheduling: https://calendly.com/davidfcarr

RSVPMaker is Now on GitHub

This is an invitation to developers with ideas about how to make RSVPMaker better. The code is now on GitHub:

https://github.com/davidfcarr/rsvpmaker

While I have received occasional code contributions over the years, I hope this will make it easier to collaborate with others who have great ideas or who have stronger skills in some areas than I do. Even if you don’t have code to contribute, there is an Issues section where you can record wish list items.

I’m relatively new to using GitHub, so I welcome advice on how to use the platform effectively.

RSVPMaker on GitHub

Customization for Notification Emails

Added by popular request: a new way of modifying the notification and confirmation messages RSVPMaker sends when someone submits the form for an event.

The default is still that a notification goes to the event organizer (or whatever email address or addresses you supplied) saying something like “RSVP YES for The Big Event on May 1” and the attendee gets a version that says “Confirming RSVP YES for The Big Event on May 1.” By default, the confirmation message also includes a button people can click to update their RSVP.

Now, if you want to use “Registration” rather than RSVP in the subject line, or you want to leave off the “Update RSVP” button (some people have told me they don’t want to make it too easy for people to back out), you can make those changes. (See also: How to Change the RSVP Now! Button.)

The notifications editor opens up possibilities for adding personality to these transactional messages. It also simplifies the process of localization, since “RSVP” is not universally understood across languages and cultures.

Sample form, showing customized subject line
Confirmation message with a customized headline

The information you record here should be generic enough to apply to all your events. You still get the option to add a per-event confirmation message, which will be included as long as your template includes the [rsvpmessage] placeholder (one of several documented on the page for the template editor). By default, the confirmation message is just “Thank you!” but I’ve also used RSVPMaker to register people for webinars where that message includes detailed instructions for accessing the online event. For a terrestrial event, it might be driving directions.

The Notification Templates screen is distinct from the Email Template screen, which you use to define one or more templates for the layout of your HTML email, for example to specify a background color. Notification messages use the default template defined on that screen.

While RSVPMaker is intended to be useful out of the box, I continue to look for ways to let you make it your own.

P.S. for Developers

If you create extensions to RSVPMaker, there are filters and actions you can tap to extend this feature as well.

The default array of variables used for these templates is defined like this:

$template_forms['notification'] = array('subject' => 'RSVP [rsvpyesno] for Customization for Notification Emails on ','body' => "Just signed up:\n\n[rsvpdetails]");
$template_forms['confirmation'] = array('subject' => 'Confirming RSVP [rsvpyesno] for Customization for Notification Emails on ','body' => "[rsvpmessage]\n\n[rsvpdetails]\n\nIf you wish to change your registration, you can do so using the button below. [rsvpupdate]");

You can add to it with a filter like

add_filter('rsvpmaker_notification_template_forms','my_forms');

Your filter would be passed an array and return your modified version with additional entries in the same format.

The sample forms use data pulled from a simple key / value array, where entries look like

$sample_data = array('rsvpyesno' => 'YES','rsvp_title' => $post->post_title);

The filter for that is ‘rsvpmaker_notification_sample_data’.

Finally, there is a ‘rsvpmaker_notification_templates_doc’ action you can use to add to the documentation at the bottom of the page.

As part of my WordPress for Toastmasters project, I plan to use this same template utility for confirmation and reminder messages for specific meeting roles.