If you’ve worked with WP Simple Pay, you know it is a great plugin to quickly integrate Stripe payment forms on a WordPress website. The ease of use of this plugin is impressive, but the flexibility it offers is even more incredible.
Let’s see how we can register our own custom form field in WP Simple Pay Pro 3.6.
The plugin code is freely available for download on Github. Just clone the repo in your wp-content/plugins
folder and activate the plugin in your WordPress site admin.
Intro
WP Simple Pay Pro is a very flexible plugin: thanks to many well-thought actions and filters scattered around its code, we can easily modify the core behavior of this plugin.
In our tutorial, we will register a new type of payment form field in order to give a visitor the ability to pick a WooCommerce product from a list.
Once a product is selected, the form price will automatically be updated to the product price, so it can be bought by using Stripe.
Demo
First, let’s see the end result of what we’re about to create ⬇️
How to develop a new custom field in a WP Simple Pay payment form?
Requirements
We are using WP Simple Pay Pro version 3.6.7. This tutorial may not work with the lite (free) version of the plugin.
Register a new set of fields
First thing first: let’s see how we can add a new WooCommerce group in the Choose a field dropdown when adding a field to a new payment form in the backend.
By default, WP Simple Pay creates 4 groups: payment, customer, standard and custom. But by using the 'simpay_custom_field_group_labels'
field, we can add our own group in order to add our own field in it.
<?php
/**
* Register a new Custom Form Fields group
*
* @param array $groups
* @return array
*/
function register_woocommerce_fields_group( $groups ) {
$groups['woocommerce'] = _x( 'WooCommerce', 'custom field group', 'simpay-wc-product' );
return $groups;
}
add_filter( 'simpay_custom_field_group_labels', __NAMESPACE__ . '\\register_woocommerce_fields_group' );
With that code, we alter the original $groups
variable to add a new custom woocommerce
key. Its value is simply the readable title of the new group displayed to the admin user in the select dropdown.
Add our own custom field in the form settings
Now that we have the parent, let’s have a child! The simpay_custom_field_options
filter gives us a way to tell WP Simple Pay to add a custom Product Dropdown option in the field selection dropdown.
<?php
/**
* Register our new Product Dropdown form field type
*
* @param array $fields
* @return array $fields
*/
function register_wc_product_dropdown_field( $fields ) {
$fields['wc-product'] = [
'label' => esc_html__( 'Product Dropdown', 'simpay-wc-product' ),
'type' => 'wc-product',
'category' => 'woocommerce',
'active' => true,
'repeatable' => true,
];
return $fields;
}
add_filter( 'simpay_custom_field_options', __NAMESPACE__ . '\register_wc_product_dropdown_field' );
The $fields
associative array consists of multiple keyed items, each item following a specific structure:
- the
label
key defines the label displayed to the user in the dropdown. It’s also displayed at the top of the settings section for each field of this type. - the
type
key indicates a unique key that will be used across other dynamic hooks we’ll use below. In our case, we’re usingwc-product
. - the
category
is a reference to the group we’ve just created. Here, we’re adding a new option in our new WooCommerce group, but you can use the default values:payment
customer
standard
custom
active
gives you the ability to disable the field. For example, you could dynamically disable a field based on some site-wide logic. This key accepts a boolean value.- finally, the
repeatable
setting is helpful if you’re only allowing one instance of your custom field per payment form. Once a field has been created, the option is grayed-out to the user and it’s impossible to add a second field of the same type. This setting is also expecting a boolean.
Output our field settings
To define our new field settings used by the admin user in the backend, we need to proceed in two steps.
Provide a template path to WP Simple Pay
Once the user selects and adds a new field in a form, WP Simple Pay will load a set of setting fields to customize its properties. The plugin is using a template file for each field type: this template file provides the HTML markup for the setting fields.
To let WPSP know the location of our settings template file, we can use the 'simpay_admin_{$type}_field_template'
dynamic filter. The $type
refers to what we defined previously in the simpay_custom_field_options
filter: in our case, we’ll be using the simpay_admin_wc-product_field_template
filter name because we registered the wc-product
field type above.
<?php
/**
* Display the new field type admin settings
*
* @param string $template
* @return string $template
*/
function display_wc_product_dropdown_settings( $template ) {
$template = SWCP_DIR . '/views/field-settings.php';
return $template;
}
add_filter( 'simpay_admin_wc-product_field_template', __NAMESPACE__ . '\display_wc_product_dropdown_settings' );
The plugin is expecting the path of the PHP file in charge of outputting the field settings markup.
Create the template responsible of outputting the field settings
Now that Simple Pay knows which file to use, let’s write the HTML markup for our custom field settings.
Look at the wp-simple-pay-pro-3/includes/pro/admin/metaboxes/views/custom-fields/*.php
to see how settings fields are registered. You can easily duplicate a file and adapt it to your needs to follow the same convention the plugin is using.
To do that, we will:
- follow the existing plugin fields markup, to keep the same CSS classes and stylings
- use the
simpay_print_field()
to output the input HTML code. It’s a helper function provided by the plugin that will greatly help us output our input fields.
The full template file code is visible here: we will only discuss the key part of it.
Data available in the template file
We have access to a $counter
variable provided by WPSP. This is a unique integer linked to a new field instance added in the form. With it, we can generate unique ID and name attributes for each setting field that we create.
More importantly, we have also access to a $field
variable in this template file. This variable gives us access to the current field data and it looks like that:
The shape of this array will depend on the settings you will register for your custom fields. A couple of keys are natively provided by the plugin such as:
order
(the field position in the entire form fields set),uid
(a numeric unique identifier),id
(a string following thesimpay_{$form_id}_{$field_type}_{$uid}
pattern).
Displaying setting fields
The full template file code is visible here: we are only mentioning some key parts of it.
Each setting is displayed in a <tr class="simpay-panel-field">
container.
We can use the simpay_print_field()
function to generate the markup for any type of input/checkbox/select/radio/textarea.
These fields will host any specific setting for our new payment form custom field.
<?php simpay_print_field( [
'type' => 'standard',
'subtype' => 'text',
'name' => "_simpay_custom_field[wc-product][{$counter}][label]",
'id' => "simpay-wc-product-label-{$counter}",
'value' => isset( $field['label'] ) ? $field['label'] : '',
'class' => [ 'simpay-field-text', 'simpay-label-input' ],
'attributes' => [ 'data-field-key' => $counter ],
'description' => simpay_form_field_label_description(),
] );
A very important parameter of this function is the name
parameter. You have to follow the plugin convention in order to:
- automatically save your field data when saving the form,
- let the plugin populate the
$field
array (previously described) with a new key => value pair for each setting field you create
The name should follow this structure: _simpay_custom_field[{$type}][{$counter}][{$setting_key}]
. For instance, to register the label setting field, we’re using a _simpay_custom_field[wc-product][{$counter}][label]
name attribute value.
To decide which input type will be generated, we pass a type
parameter (with an optional subtype
parameter for the standard
input field). You can pass a value of:
checkbox
to display a set of checkboxes. The values and labels of the checkboxes are passed via an array in aoptions
parameter.editor
to display a WYSIWYGradio
to ouput radio buttons. The values and labels of the radio options are passed via an array in aoptions
parameter.select
to output a select dropdown. The select options are passed via an array in aoptions
parameter.standard
for a normal text input field. Thesubtype
parameter can take any value and will let you customize the<input type>
attribute to force an e-mail, telephone, number value…
Products selection setting field
<?php simpay_print_field( [
'type' => 'select',
'name' => "_simpay_custom_field[wc-product][{$counter}][products][]",
'id' => "simpay-wc-product-products-{$counter}",
'value' => isset( $field['products'] ) ? $field['products'] : '',
'class' => [ 'simpay-field-dropdown', 'simpay-field-text' ],
'attributes' => [
'data-field-key' => $counter,
'multiple' => true,
],
'options' => \SWCP\get_wc_products(),
'description' => esc_html__( 'Select the products that are available for sale in this form.', 'swcp' ),
] ); ?>
For our field to work, the admin needs to pick a selection of WooCommerce products to populate the select dropdown in the frontend.
Therefore, we’ve registered a 'type' => 'select'
setting field and we passed an array of products (in a $product_id => $product_name
format). Note that we also set the <select multiple>
attribute to be true, so that we can pick more than one products in the list.
On the frontend side, we will then be able to access a $field['products']
variable holding all the products IDs that have been selected in the backend for this field.
Default settings fields
Note that some settings fields are necessary for the default plugin behavior to work :
- the
Form Field Label
setting is not mandatory, but is a convention to let the user define the text label displayed before the payment form field, - the
Stripe Metadata Label
allows the user to set a different, more readable Stripe label for its form field, - the
Field ID
is a very important setting field: this is a<input type="hidden">
field and it stores the unique identifier generated by the plugin for this specific setting field instance.
Display the WooCommerce product selection field on the frontend
We’ve registered our new field and each field instance can now be customized with some settings fields. The last step is to output the field in a WPSP payment form.
The simpay_custom_field_html_for_non_native_fields
filter
By hooking into this filter, your custom function will receive 3 parameters:
$html
is the current payment form HTML markup. We will append some extra HTML code to this variable in order to output our own custom field markup.$field
is an array that contains all of our field settings (such as the field label, or the products list to be used to populate our dropdown).$form
is aSimplePay\Pro\Forms\Pro_Form
object and contains all the data relative to the payment form currently being displayed.
<?php
/**
* Output our custom field HTML in the form
*
* @param string $html
* @param object $form
* @return string $html
*/
function display_addon_checkbox_frontend_html( $html, $field, $form ) {
if ( 'wc-product' === $field['type'] ) {
$html .= output_wc_product_field_html( $field );
}
return $html;
}
add_filter( 'simpay_custom_field_html_for_non_native_fields', __NAMESPACE__ . '\display_addon_checkbox_frontend_html', 20, 3 );
Any payment form custom field will go through the simpay_custom_field_html_for_non_native_fields
to get its HTML markup generated.
So we have to compare the $field['type']
value and check if we’re dealing with one of our wc-product
field type. If that’s the case, we will pass the $field
to a custom output_wc_product_field_html()
function responsible of generating the final HTML markup for our field.
Generating the field markup in a payment form
Here is the last piece of the puzzle:
<?php
function output_wc_product_field_html( $item ) {
$html = '';
$id = isset( $item['id'] ) ? $item['id'] : '';
$meta_name = isset( $item['metadata'] ) && ! empty( $item['metadata'] ) ? $item['metadata'] : $id;
$label = isset( $item['label'] ) ? $item['label'] : '';
$name = 'simpay_field[' . esc_attr( $meta_name ) . ']';
if ( ! is_array( $item['products'] ) || empty( $item['products'] ) ) {
return sprintf(
'<div><p>%1$s</p></div>',
esc_html__( 'You need to select at least one product in the form settings.', 'simpay-wc-product' )
);
}
$id = simpay_dashify( $id );
$label = '<p><label for="' . esc_attr( simpay_dashify( $id ) ) . '">' . $label . '</label></p>';
$field = '<select name="' . $name . '" id="' . esc_attr( $id ) . '" class="simpay-amount-dropdown">';
foreach ( $item['products'] as $product_id ) {
$product = wc_get_product( (int) $product_id );
if ( $product ) {
$field .= sprintf(
'<option value="%1$d" data-amount="%4$s">%2$s (%3$s)</option>',
(int) $product->get_id(),
esc_html( $product->get_name() ),
$product->get_price_html(),
$product->get_price()
);
}
}
$field .= '</select>';
$html .= '<div class="simpay-form-control simpay-wc-product-container">';
$html .= '<div class="simpay-checkbox-wrap simpay-field-wrap">';
$html .= $label . $field;
$html .= '</div>';
$html .= '</div>';
return $html;
}
This custom function will analyze the $item
field array and outputs the HTML accordingly. In this function, you will receive all the field parameters and settings to conditionally generate the final input markup.
In our case, the products IDs available for sale are stored in the $item['products']
key. We use that key to output a single <option>
in the dropdown.
By using a simpay-amount-dropdown
class on our select dropdown, and by passing a data-amount
attribute to every single option (containing the product price amount), we benefit from a core plugin logic that will automagically update the payment form price-to-pay with the price of the product selected in the dropdown.
Conclusion
In 4 steps, we’ve successfully customized WP Simple Pay Pro to display our own custom WooCommerce product field. Feel free to clone the repo to use it as a foundation for your own payment form customizations!
If you’re feeling stuck or need help with developing a custom WordPress/WooCommerce integration with WP Simple Pay, let’s chat!