Creating a Payment Gateway
Developers can extend the GetPaid_Payment_Gateway PHP class to create their own custom payment gateways. This class will take care of registering the payment gateway and provide a way of adding the admin settings fields and frontend payment fields.
GetPaid supports 4 different types of payment gateways:-
- Redirect - When a customer clicks on the pay now button, this payment gateway redirects them to the payment processor's website. For example, PayPal.
- iFrame based - The payment fields (e.g credit card forms) are loaded within the payment form in an iframe. For example, Square and Stripe.
- Embedded - The payment fields (e.g credit card forms) are added directly to the payment form. For example, Authorize.net AIM. These types of gateways may require the website to be PCI compliant.
- Offline - Money is collected offline and the invoice is manually marked as paid. For example, Bank Transfer.
Creating a simple payment gateway
Start by creating a PHP class that extends the GetPaid_Payment_Gateway class as shown...
<?php /** * Custom payment gateway * */ defined( 'ABSPATH' ) || exit; /** * Custom Payment Gateway class. * */ class My_Custom_Gateway extends GetPaid_Payment_Gateway { }
Next, use the getpaid_default_gateways filter hook to register the payment gateway as shown below.
/** * Registers the gateway. */ function register_my_custom_gateway( $gateways ){ $gateways['custom'] = 'My_Custom_Gateway'; return $gateways; } add_filter( 'getpaid_default_gateways', 'register_my_custom_gateway' );<br>
That's all.
However, before the gateway can be used to process payments and subscriptions, you need to implement a few required methods.
Required Methods
Most methods will be inherited from the GetPaid_Payment_Gateway class, but some are required in your custom gateway.
__construct()
This is where you set a unique id for the gateway and give it a name and description. In addition, you can also set the features that your gateway supports and add some hooks that are unique to the gateway.
Some of the properties that you can set here include:-
-
checkout_button_text - The label to show on a payment form's submit-button when this gateway is selected. If not set, the label set when editing a payment form will be used instead.
-
id - A unique id for your payment gateway.
-
order - The default priority of your payment gateway. Gateways with a lower priority appear first on payment forms. This can be changed by site admins.
-
title - The (frontend) name of the payment gateway. This is what customers will see. This can be changed by site admins.
-
description - The description of the payment gateway, shown on the frontend. This can be changed by site admins.
-
method_title - The actual name of the payment gateway, shown on the settings page.
-
countries - An array of countries that this payment gateway is allowed for. Do not set if the gateway is usable worldwide.
-
currencies - An array of currencies that this payment gateway is allowed for. Do not set if the gateway should be usable with any currency.
-
exclude_currencies - An array of currencies that this payment gateway is NOT allowed for. Do not set if the gateway should be usable with any currency.
-
max_amount - The maximum amount that this gateway can process in a single invoice.
-
view_transaction_url - The remote URL to view a transaction. '%s' will be replaced by the transaction ID of an invoice.
-
view_subscription_url - The remote URL to view a subscription. '%s' will be replaced by the remote subscription ID of a subscription.
-
supports - An array of features that this payment gateway supports. This includes sandbox, subscription, tokens and addons.
/** * Class constructor. */ public function __construct() { $this->id = 'custom'; $this->title = __( 'Custom', 'my-domain' ); // Frontend name $this->method_title = __( 'Custom Gateway', 'my-domain' ); // Admin name $this->description = __( 'Pay using my custom payment gateway', 'my-domain' ); $this->supports = array( 'subscription', 'sandbox', 'tokens', 'addons' ); // Add code that should always run whether or not the gateway is enabled (active). // Call the parent constructor. parent::__construct(); // Add code that should only run when the gateway is enabled (active). if ( $this->enabled ) { } }
admin_settings( $admin_settings )
When you register a payment gateway, GetPaid will automatically add settings that allow admins to enable/disable the payment gateway, change the name and description shown on payment forms, and if the gateway supports sandbox mode, enable/disable sandbox.
You can add an admin_settings() method to your gateway's class if you need to add more settings.
The example code below allows you to add an "API Key" settings field to your gateway's settings page.
public function admin_settings( $admin_settings ) { $admin_settings['custom_api_key'] = array( 'id' => 'custom_api_key', 'name' => __( 'API Key', 'my-domain' ), 'desc' => __( 'Enter the API Key used to process payments.', 'my-domain' ), 'type' => 'text', ); return $admin_settings; } <br>
payment_fields( $invoice_id, $form )
If you're creating an embedded or iframe-based payment gateway, you can extend the payment_fields() method to display the iframe or credit card form.
This method is passed an invoice id (or 0 if there is no invoice yet) and a payment form object.
You can then display your own payment fields or call the get_cc_form() method to display a pre-built credit card form. The example below shows how to display a quick credit card input form.
public function payment_fields( $invoice_id, $form ) { echo $this->get_cc_form() }
Some payment gateways allow you to tokenize a credit card so that you can use the token for future payments. If yours supports it, ensure to register support for tokens then replace the above code with this one instead.
public function payment_fields( $invoice_id, $form ) { // Let the user select a pre-saved payment token... echo $this->saved_payment_methods(); // ... or provide new credit card details. echo $this->new_payment_method_entry( $this->get_cc_form( true ) ); }
process_payment( $invoice, $submission_data, $submission )
$api_key = wpinv_get_option( 'custom_api_key' );
$cc_number = $submission_data['custom']['cc_number'];
if ( empty( $cc_number ) { wpinv_set_error( 'missing_cc', __( 'Please provide a valid credit card number', 'my-domain' ) ); wpinv_send_back_to_checkout( $invoice ); }
$currency = $invoice->get_currency()
$invoice_number = $invoice->get_number()
$invoice_total = $invoice->get_total(); $total_discount = $invoice->get_total_discount(); $total_tax = $invoice->$invoice->get_total_tax(); $subtotal = $invoice->get_subtotal();
$first_name = $invoice->get_first_name(); $last_name = $invoice->get_last_name(); $address = $invoice->get_address(); $city = $invoice->get_city(); $state = $invoice->get_state(); $zip = $invoice->get_zip(); $country = $invoice->get_country(); $customer_id = $invoice->get_customer_id();
// Process the payment here. // If successfuly, mark the invoice as paid... $invoice->mark_paid(); // ... then send to the success page. wpinv_send_to_success_page( array( 'invoice_key' => $invoice->get_key() ) );
// Mark the invoice as held... $invoice->set_status( 'wpi-onhold' ); // Add note. $invoice->add_note( __( 'Mark the invoice as paid when you receive offline payment', 'my-domain' ), false, false, true ); // ... then save it... $invoice->save(); // ... and redirect to the receipt page. wpinv_send_to_success_page( array( 'invoice_key' => $invoice->get_key() ) );
wp_redirect( 'https://my-payment-processor.com/process' );
verify_ipn()
This method is called when we receive an IPN request for your gateway. You can use it to process the request and process the invoice/subscription as needed.
Here are a few snippets that might be useful when it comes to IPNs:-
Getting an invoice object:-
$invoice = new WPInv_Invoice( $_POST['invoice_id'] ); if ( $invoice->exists() ) { // Process IPN. }
Getting your gateway's IPN URL:-
$ipn_url = wpinv_get_ipn_url( $this->id );
Working with subscriptions
If your payment gateway supports subscriptions, add it to the list of supported features. You can then use the following code snippets to work with subscriptions.
Checking if an invoice has an associated subscription:-
if ( $invoice->is_recurring() && $subscription = wpinv_get_subscription( $invoice ) ) { $period = $subscription->get_period(); $interval = (int) $subscription->get_frequency(); $max_bill_times = (int) $subscription->get_bill_times(); $initial_amount = (float) wpinv_sanitize_amount( $invoice->get_initial_total(), 2 ); $recurring_amount = (float) wpinv_sanitize_amount( $invoice->get_recurring_total(), 2 ); $subscription_item = $invoice->get_recurring( true ); // Process the subscription here. }
Activating an invoice's subscription:-
$duration = strtotime( $subscription->get_expiration() ) - strtotime( $subscription->get_date_created() ); $expiry = date( 'Y-m-d H:i:s', ( current_time( 'timestamp' ) + $duration ) ); $subscription->set_next_renewal_date( $expiry ); $subscription->set_date_created( current_time( 'mysql' ) ); $subscription->set_profile_id( /*THE REMOTE ID OF THE SUBSCRIPTION*/ ); $subscription->activate();
Renewing an invoice's subscription:-
// If this is the last renewal, complete the subscription. if ( $subscription->is_last_renewal() ) { return $subscription->complete(); } // Renew the subscription. $subscription->add_payment( array( 'transaction_id' => /*THE REMOTE ID OF THE RENEWAL PAYMENT*/, 'gateway' => $this->id ) ); $subscription->renew();