Dorokhov.codes
Creating a payment gateway
Types of payment gateway:
Type | Description |
---|---|
Form based | A user must click a button on a form that then redirects them to the payment processor on the gateway’s own website. |
iFrame based | A gateway payment system is loaded inside an iframe on your store. |
Direct | Payment fields are shown directly on the checkout page and the payment is made when ‘place order’ is pressed. |
Offline | No online payment is made. |
1. Creating a child class
There are 5 properties in a child class that are required to specify
(id
, icon
, has_fields
, method_title
, method_description
).
function init_your_gateway_class() {
class WC_Gateway_Your_Gateway extends WC_Payment_Gateway {
public function __construct() {
/**
* Unique ID of the gateway. Used in option names.
*/
$this->id = 'your_gateway';
/**
* If you want to show an image next to the gateway’s name
* on the frontend, enter a URL to an image.
*/
$this->icon = plugin_dir_url( __FILE__ ) . 'assets/images/logo.png';
/**
* Can be set to true if you want payment fields
* to show on the checkout (if doing a direct integration).
*/
$this->has_fields = false;
/**
* Title of the payment method shown on the admin page.
*/
$this->method_title = 'My payment gateway';
/**
* Description for the payment method shown on the admin page.
*/
$this->method_description = 'We are accepting credit cards.';
}
}
}
Initialize it after all the plugins are loaded:
add_action( 'plugins_loaded', 'init_your_gateway_class' );
As well as defining the class, we need to also tell WC that it exists.
We will do this by filtering woocommerce_payment_gateways
:
function add_your_gateway_class( $methods ) {
$methods[] = 'WC_Gateway_Your_Gateway';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_your_gateway_class' );
2. Specify options for admin page
All this I have described on the Settings API page.
The basic fields that we should include are enabled
, title
, and description
.
- Enabled will be a checkbox that allows the user to enable or disable the gateway on the checkout page.
- Title is different from the title we set in the constructor; this will be the title shown to customers at checkout and can be different from the admin title.
- Description will be shown under the title when the gateway is selected at checkout, and tells customers what to do next.
'enabled' => [
'title' => __( 'Enable/Disable', 'wc-gateway-offline' ),
'type' => 'checkbox',
'label' => __( 'Enable Offline Payment', 'wc-gateway-offline' ),
'default' => 'yes'
],
'title' => [
'title' => __( 'Title', 'wc-gateway-offline' ),
'type' => 'text',
'description' => __( 'This controls the title for the payment method the customer sees during checkout.', 'wc-gateway-offline' ),
'default' => __( 'Offline Payment', 'wc-gateway-offline' ),
'desc_tip' => true,
],
'description' => [
'title' => __( 'Description', 'wc-gateway-offline' ),
'type' => 'textarea',
'description' => __( 'Payment method description that the customer will see on your checkout.', 'wc-gateway-offline' ),
'default' => __( 'Please remit payment to Store Name upon pickup or delivery.', 'wc-gateway-offline' ),
'desc_tip' => true,
],
And then we should add the next calls to the constructor:
/**
* Initialise settings form fields.
*
* Add an array of fields to be displayed on the gateway's settings screen.
*/
$this->init_form_fields();
/**
* Init settings for gateways.
*/
$this->init_settings();
3. Processing payments
/**
* Process Payment.
*
* Process the payment. This should return the success
* and redirect in an array. e.g:
*
* return array(
* 'result' => 'success',
* 'redirect' => $this->get_return_url( $order )
* );
*
* @param int $order_id Order ID.
* @return array
*/
public function process_payment( $order_id )
{
$order = wc_get_order( $order_id );
// or: $order = new WC_Order( $order_id );
// Empty the cart:
WC()->cart->empty_cart();
// Error message if needed:
wc_add_notice( 'Something went wrong.', 'error' );
// Here we should specify the return url (thank you page or gateways' checkout page).
return [
'result' => 'success',
'redirect' => $this->get_return_url( $order ),
];
}
We shouldn’t use reduce_order_stock()
function:
/**
* Stock levels are updated via actions (`woocommerce_payment_complete` and in
* transitions between order statuses), so it’s no longer needed to manually
* call the methods reducing stock levels while processing the payment.
*/
$order->reduce_order_stock();
WC_Payment_Gateway
class has a method get_return_url()
for getting a URL for thank you page. Without a parameter
it will return a URL for a standard “thank you” page, but if we specify an order
argument, we will
get “thank you” page with all the details about the order.
After payment completing we should call:
$order->payment_complete();
If we are using an offline payment method, then we can do something like this:
// Mark as on-hold (we're awaiting the cheque)
$order->update_status('on-hold', __( 'Awaiting cheque payment', 'woocommerce' ));
If an error occurs
If payment fails, you should throw an error and return null:
wc_add_notice( __('Payment error:', 'woothemes') . $error_message, 'error' );
return;
3.1 Form request to the Gateway checkout page
// Receiving the order amount:
$order->get_total();
// Getting a current shop currency:
get_woocommerce_currency();
3.2 Redirect to Gateway checkout page
add_query_arg();