SubtleForms uses WordPress filters and actions, all namespaced with subtleforms/. These are the ones most add-ons need.
subtleforms/payments/quote
Filter the computed order before it is shown or charged. The quote contains currency, items, subtotal, discount, coupon, tax_rate, tax and total.
add_filter( 'subtleforms/payments/quote', function ( array $quote, array $schema, array $payload ) {
// Add a handling fee to every order over 100.
if ( $quote['subtotal'] > 100 ) {
$quote['items'][] = array( 'key' => 'handling', 'label' => 'Handling', 'quantity' => 1, 'amount' => 5.0 );
$quote['total'] += 5.0;
}
return $quote;
}, 10, 3 );
If you change line items, keep total consistent with them, because the total is what gets charged.
subtleforms/payments/validate_coupon
The last word on whether a coupon applies. Receives the coupon array or a WP_Error, the form ID and the order subtotal. Return the coupon to accept it or a WP_Error to refuse it.
add_filter( 'subtleforms/payments/validate_coupon', function ( $coupon, int $form_id, float $subtotal ) {
if ( is_wp_error( $coupon ) ) {
return $coupon;
}
if ( 'MEMBERS' === $coupon['code'] && ! is_user_logged_in() ) {
return new WP_Error( 'members_only', __( 'Log in to use this coupon.', 'my-plugin' ) );
}
return $coupon;
}, 10, 3 );
subtleforms/payment/verify
Gateways use this filter to confirm the visitor’s payment. Return an array with status (authorized, paid or pending), gateway and transaction_id, or a WP_Error to reject the submission. Returning null means no gateway handled it, and the entry is stored as payment pending.
add_filter( 'subtleforms/payment/verify', function ( $result, array $quote, array $payload, int $form_id, $schema ) {
if ( null !== $result || empty( $payload['_payment']['my_gateway_token'] ) ) {
return $result;
}
$auth = my_gateway_authorize( $payload['_payment']['my_gateway_token'], $quote['total'], $quote['currency'] );
if ( ! $auth['ok'] ) {
return new WP_Error( 'payment_declined', $auth['message'] );
}
return array( 'status' => 'authorized', 'gateway' => 'my_gateway', 'transaction_id' => $auth['id'] );
}, 10, 5 );
subtleforms/payment/capture
Runs after the entry has been stored. Capture an authorised payment here and return the updated payment array, or a WP_Error if the capture failed.
add_filter( 'subtleforms/payment/capture', function ( array $payment, int $submission_id ) {
if ( 'my_gateway' !== ( $payment['gateway'] ?? '' ) || 'authorized' !== $payment['status'] ) {
return $payment;
}
$capture = my_gateway_capture( $payment['transaction_id'] );
if ( ! $capture['ok'] ) {
return new WP_Error( 'capture_failed', $capture['message'] );
}
$payment['status'] = 'paid';
return $payment;
}, 10, 2 );
subtleforms/payment/void
Fires when the submission failed after the gateway authorised the payment. Release the hold here so the visitor is not charged.
add_action( 'subtleforms/payment/void', function ( array $payment ) {
if ( 'my_gateway' === ( $payment['gateway'] ?? '' ) ) {
my_gateway_release( $payment['transaction_id'] );
}
} );
subtleforms/frontend/enqueued
Fires after the public form assets are enqueued, so add-ons such as a payment gateway can load their own scripts alongside. Receives the plugin settings object, or null.
add_action( 'subtleforms/frontend/enqueued', function ( $settings ) {
wp_enqueue_script( 'my-gateway', plugins_url( 'gateway.js', __FILE__ ), array( 'subtleforms-frontend' ), '1.0.0', true );
} );
subtleforms/fields/register
Register a custom field type. Receives the field registry. Each type is described by a FieldDefinition, and a type can only be registered once.
use SubtleForms\Fields\FieldDefinition;
add_action( 'subtleforms/fields/register', function ( $registry ) {
$registry->register(
new FieldDefinition(
type: 'vat_number',
label: __( 'VAT number', 'my-plugin' ),
category: 'basic',
icon: 'dashicons-id',
kind: 'input',
baseAttributes: array(),
fieldSpecificAttributes: array( 'placeholder' => '' ),
inspectorControls: array(
array( 'type' => 'text', 'name' => 'label', 'label' => __( 'Label', 'my-plugin' ) ),
)
)
);
} );
Hooks marked with a version in the source are stable from that version on. If you need a hook that does not exist yet, email support@subtleforms.com.