-
Notifications
You must be signed in to change notification settings - Fork 193
Payment Gateway API
1 - Creating Your Initial Gateway Class (Applicable to Both Option-Based Editor and Visual Form Builder)
The first step in creating your gateway integration is to extend the PaymentGateway class and implement the required methods.
You can refer to the example below for guidance:
Once your gateway class is set up, the next step is to register it on the Give payment gateway list.
You can achieve this by using the following code snippet:
add_action(
'givewp_register_payment_gateway',
function (PaymentGatewayRegister $registrar) {
$registrar->registerGateway(ExampleGatewayOnsiteClass::class);
}
);
To enable your gateway integration to work with the Give donation forms, you need to implement the enqueueScript() method within your gateway class. This method should load the script containing your gateway's frontend logic.
Refer to the following examples for guidance:
These scripts contain the frontend logic for your gateway and render fields using React.
However, you must not load your own version of React to avoid compatibility issues. Instead, your JavaScript file should be compiled using @wordpress/scripts
to exclude dependencies like React and rely on WordPress to provide them.
To learn how to compile your JavaScript/TypeScript (JS/TSX) files using WP Scripts, refer to the following example:
For a practical example of implementing the enqueueScript()
method, check out this more realistic (using a file compiled with WP Scripts) sample:
The main distinction between onsite and offsite gateway scripts is as follows:
- Onsite Gateway Script: Loads input fields that donors need to complete before submitting the form.
- Offsite Gateway Script: Renders helper text to inform donors they will be redirected outside the site.
In some gateway integrations, it’s necessary to pass API public keys or other data from the backend to the frontend. To achieve this, implement the formSettings() method in your gateway class.
Here’s an example:
Once the data is passed, you can retrieve it in the initialize() method of the JavaScript gateway object, as shown here:
For most onsite gateway integrations, you'll need to send data such as gateway required inputs, tokens, or other inputs from the frontend to the backend.
Here’s how to achieve this:
- In the beforeCreatePayment() method of the JavaScript gateway object, return the fields you need to send to the backend.
See the example below: - Access this data in the $gatewayData parameter of the createPayment() method within your gateway class.
Here’s a sample implementation:
To integrate your gateway with Give's legacy donation forms, implement the getLegacyFormFieldMarkup() method in your gateway class.
Below are examples for both offsite and onsite gateways:
Offsite gateways typically do not require donor inputs on the donation form since this is handled on the gateway page.
For these, you only need to add helper text markup:
For onsite gateways, you’ll need to include input fields that donors complete before submitting the form.
Use this approach:
WordPress best practices recommend using the wp_enqueue_script() function to load scripts within your plugin. This ensures your scripts are added in an optimized and manageable way. You can use this function to load the scripts that will manipulate donor input fields when necessary.
However, if you prefer to load your gateway scripts only when it is selected in the gateway list for legacy donation forms, you can handle this directly within the getLegacyFormFieldMarkup() method.
For example:
public function getLegacyFormFieldMarkup(int $formId, array $args): string
{
ob_start();
?>
<div>
<input type='text' name='gatewayData[example-gateway-id]' placeholder='Example gateway field' />
</div>
<script type="text/javascript" src="https://example.com/example-gateway-script.js" charset="utf-8"></script>
<?php
return ob_get_clean();
}
Sometimes, you need to pass API public keys or other settings from the backend to the frontend.
Here are two approaches:
If you are using wp_enqueue_script() to load your gateway script, you can use wp_localize_script() to pass data.
For example:
wp_enqueue_script('my-gateway-script-js', MY_GATEWAY_PLUGIN_URL . '/assets/js/my-gateway-script.js');
wp_localize_script('my-gateway-script-js', 'gatewayData', [
'clientKey' => get_option('my-gateway-clientKey'),
]);
In your JavaScript file, you can then access the data via the global gatewayData object:
console.log(window.gatewayData.clientKey);
If you prefer embedding data directly in the getLegacyFormFieldMarkup() method, you can use this approach:
public function getLegacyFormFieldMarkup(int $formId, array $args): string
{
ob_start();
$clientKey = get_option('my-gateway-clientKey');
?>
<div>
<input type='text' name='gatewayData[example-gateway-id]' placeholder='Example gateway field' />
</div>
<script type="text/javascript" src="https://example.com/example-gateway-script.js" charset="utf-8"></script>
<script type="text/javascript">
function readyHandler() {
let clientKey = "<?php echo esc_js($clientKey); ?>";
console.log(clientKey);
}
if (document.readyState !== 'loading') {
readyHandler();
} else {
document.addEventListener('DOMContentLoaded', readyHandler);
}
</script>
<?php
return ob_get_clean();
}
For most onsite gateway integrations, you need to send data (e.g., card details, tokens) from the frontend to the backend.
In the previous step, you added custom input fields to legacy forms. Now, you can retrieve these fields on the backend using the $_POST global variable.
add_filter(sprintf('givewp_create_payment_gateway_data_%s', MyGateway::id()), function ($gatewayData) {
// If this $gatewayData is empty, means the donation was made with a legacy donation form (Option-Based Form Editor)
if (empty($gatewayData)) {
$gatewayData['example-gateway-id'] = give_clean($_POST['example-gateway-id']);
}
return $gatewayData;
});
Once the data is available in the $gatewayData parameter, you can access it in the createPayment() method of your gateway class.
See this example:
Recurring Donations: for recurring donations, use the same logic above but use the givewp_create_subscription_gateway_data_$s filter.
4 - Adding Support for Recurring Donations (Applicable to Both Option-Based Editor and Visual Form Builder)
To add support for recurring donations in your gateway integration, follow these steps:
Create a custom subscription module by extending the SubscriptionModule class and implementing the required methods.
Refer to this example:
Attach your custom subscription module to the corresponding gateway using the following filter:
add_filter(sprintf('givewp_gateway_%s_subscription_module', MyGateway::id()), function () {
return ExampleGatewayOnsiteSubscriptionModuleClass::class;
});
5 - Listening for Webhook Notifications Sent by Gateways (Applicable to Both Option-Based Editor and Visual Form Builder)
Many gateways do not provide immediate responses for API interactions. It is common for transactions to initially have a status like "pending" or "processing." When the gateway updates the transaction status to "complete" on their end, a webhook notification is sent to the website where Give is installed. This notification includes a payload with the updated status information.
Webhook notifications are particularly important for subscriptions. Not only can the initial transaction and subscription statuses be sent later, but renewal notifications are also sent each time the gateway processes a recurring charge.
To properly handle these webhook notifications, your gateway integration needs to:
- Update donation and subscription statuses based on the notification payload.
- Add a new renewal record for subscriptions if the notification indicates a renewal event.
Set up a route in your gateway class to handle webhook notifications from the gateway.
See this example:
Set up a method with the same name as the route. This method will receive the webhook notification and handle its payload.
Example:
In this example, the webhook notification is passed to a WebhookNotificationHandler class, which processes the notification based on its payload.
For more details, see:
You may wonder: how does the gateway know the URL (route) to send webhook notifications?
To provide the correct URL, add a method like this in your gateway class:
public static function webhookUrl(): string
{
$instance = new static();
return $instance->generateGatewayRouteUrl($instance->routeMethods[0]);
}
The generated URL will look like this:
https://example.com?give-listener=give-gateway&give-gateway-id=my-gateway&give-gateway-method=webhookNotificationsListener
Once you have the webhook URL, you have two options depending on how the gateway operates:
-
Automate Webhook Creation:
Use the gateway's API to automatically register the webhook. The gateway will then use the specified URL to send notifications. -
Manual Configuration:
Display the webhook URL in your gateway settings interface. Instruct users to copy and paste this URL into the webhook settings on the gateway dashboard. Many gateways provide an interface where users can:- Create new webhooks.
- Select which events or notifications should be sent to the specified URL.
By following these steps, you ensure that your gateway integration effectively listens for and processes webhook notifications for transactions and subscriptions.
6 - Redirecting Users to an Offsite Gateway and Back to Confirmation or Cancellation Pages (Applicable to Both Option-Based Editor and Visual Form Builder)
Offsite gateways require special handling because the workflow can sometimes be confusing. Here's the typical process for integrating an offsite gateway:
- The createPayment() method redirects donors to the offsite gateway's UI, where they can complete or cancel the donation.
- Depending on the donor's action, the gateway redirects them back to either a confirmation page or a cancellation page.
- Upon redirection, the donation status must be updated to reflect the donor's action (e.g., "completed" or "canceled").
- Additionally, the gateway may send webhook notifications later to update the transaction status.
Offsite gateways typically require specific parameters to manage the donation process and redirect users.
These include:
- returnUrl**:** The URL for redirecting users after a successful donation.
- cancelUrl**:** The URL for redirecting users after a cancellation.
- webhookUrl**:** The URL for sending transaction status updates (covered in the previous section).
To provide these parameters, you must retrieve and send them within the createPayment() method of your gateway class.
Here’s an example:
The returnUrl and cancelUrl should be generated using secure routes instead of regular ones.
See this example for defining secure routes:
Then, create methods for these routes, like in these examples:
When the gateway redirects the user back to your site (either to the confirmation or cancellation route), these methods will:
- Receive data sent by the offsite gateway to the Give installation.
- Update the donation status based on the donor's action.
If you’d like to see this offsite gateway workflow in action, check out the demo video here:
Processing a refund for a transaction is straightforward. In your gateway class, you need to implement the refundDonation() method.
This method should:
- Call the appropriate gateway API responsible for handling refunds.
- Throw an exception if any error occurs during the process.
If no exceptions are thrown, Give will assume the refund was successful and automatically update the donation status to refunded.
Here’s an example implementation:
This Wiki is focused on GiveWP development. For help using our WordPress plugin, head over to our website where you'll find Plugin Documentation and Support.