# Gateway Template

The Gateway Template gives you a starting point for building your own POS-only payment gateway. It produces a working WordPress plugin with a single PHP file that you can install and customise to fit your needs.

## Features[​](#features "Direct link to Features")

#### Minimal Code

A single PHP file with just the essentials — easy to read and modify

#### POS Only

Disabled on web checkout by default, enabled through WCPOS settings

#### Automated Setup

A shell script handles all the placeholder replacement for you

#### GitHub Releases

Push a version bump and GitHub Actions builds a downloadable ZIP

## Getting Started[​](#getting-started "Direct link to Getting Started")

1

#### Clone the Template Repository

```
git clone https://github.com/wcpos/woocommerce-gateway-template.git

cd woocommerce-gateway-template
```

Or click the **Use this template** button on the [GitHub repository](https://github.com/wcpos/woocommerce-gateway-template) to create your own copy.

2

#### Run the Setup Script

```
./create-gateway.sh
```

The script asks for a few details — your gateway name, a short description, and your GitHub username — then generates a ready-to-use plugin in a directory of your choice.

3

#### Install the Plugin

You have two options:

**Option A — Copy the folder directly** (if you have server access): Copy the generated gateway folder into your site's `wp-content/plugins/` directory.

**Option B — Zip and upload** (easiest for most people):

1. Compress the generated folder into a `.zip` file
2. In WordPress, go to **Plugins > Add New > Upload Plugin**
3. Choose the zip file and click **Install Now**

4

#### Enable in WCPOS

1. Go to **WP Admin > POS > Settings > Checkout**
2. Find your new gateway in the list and enable it

note

The gateway is disabled on the regular web checkout by default. WCPOS controls which gateways appear in the POS through its own settings.

## Manual Setup[​](#manual-setup "Direct link to Manual Setup")

If you prefer not to use the script, you can replace the placeholders yourself. Open each file in a text editor and find-and-replace the following:

| Placeholder                       | What to enter                                | Example                            |
| --------------------------------- | -------------------------------------------- | ---------------------------------- |
| `{{GATEWAY_NAME}}`                | Your gateway's display name                  | Cash Payment                       |
| `{{GATEWAY_SLUG}}`                | A URL-safe identifier (lowercase, hyphens)   | cash-payment                       |
| `{{GATEWAY_DESCRIPTION}}`         | Short description of the gateway             | Accept cash payments in WCPOS      |
| `{{GATEWAY_DEFAULT_DESCRIPTION}}` | Text shown to the cashier at checkout        | Pay with cash at the point of sale |
| `{{GITHUB_USERNAME}}`             | Your GitHub username                         | kilbot                             |
| `{{REPO_NAME}}`                   | Your repository name                         | cash-payment-gateway               |
| `{{AUTHOR_NAME}}`                 | Your name                                    | kilbot                             |
| `{{GATEWAY_ID}}`                  | Slug with underscores instead of hyphens     | cash\_payment                      |
| `{{GATEWAY_CLASS_NAME}}`          | Each word capitalised, joined by underscores | Cash\_Payment                      |
| `{{GATEWAY_FUNCTION_PREFIX}}`     | Same as Gateway ID                           | cash\_payment                      |

Then rename `wcpos-{{GATEWAY_SLUG}}.php` to match your slug (e.g., `wcpos-cash-payment.php`).

tip

The setup script derives `GATEWAY_ID`, `GATEWAY_CLASS_NAME`, and `GATEWAY_FUNCTION_PREFIX` automatically from the name and slug, so you only need to think about these when doing manual setup.

## How It Works[​](#how-it-works "Direct link to How It Works")

The generated plugin registers a WooCommerce payment gateway class. Here are the key things to know:

* **`$this->enabled = 'no'`** — The gateway is hidden from web checkout. WCPOS enables it in the POS based on your POS settings.
* **`process_payment()`** — Calls `$order->payment_complete()`, which marks the order as paid and handles stock reduction automatically.
* **`init_form_fields()`** — Defines the Title and Description fields that appear in WooCommerce settings.

## Customising Your Gateway[​](#customising-your-gateway "Direct link to Customising Your Gateway")

### Adding Payment Fields[​](#adding-payment-fields "Direct link to Adding Payment Fields")

If your gateway needs input from the cashier (for example, a reference number), override the `payment_fields()` method:

```
public function payment_fields() {

    if ( $this->description ) {

        echo wpautop( wptexturize( $this->description ) );

    }



    woocommerce_form_field( 'my_gateway_reference', array(

        'type'        => 'text',

        'label'       => __( 'Reference Number', 'your-text-domain' ),

        'required'    => true,

    ) );

}
```

You can then read the submitted value in `process_payment()` via `$_POST['my_gateway_reference']`. Remember to sanitise any input with `sanitize_text_field()`.

### Changing Payment Behaviour[​](#changing-payment-behaviour "Direct link to Changing Payment Behaviour")

The default template marks orders as paid immediately. If your workflow requires payment later (like an invoice), replace `payment_complete()` with a status update:

```
public function process_payment( $order_id ) {

    $order = wc_get_order( $order_id );



    // Set to pending — the customer will pay later.

    $order->update_status( 'pending', __( 'Awaiting payment', 'your-text-domain' ) );



    // Stock must be reduced manually when not using payment_complete().

    wc_reduce_stock_levels( $order_id );



    return array(

        'result'   => 'success',

        'redirect' => $this->get_return_url( $order ),

    );

}
```

## Making Changes and Updating[​](#making-changes-and-updating "Direct link to Making Changes and Updating")

After installing your gateway, you can keep editing the plugin file to adjust the payment logic. To install an updated version:

1. Edit `wcpos-your-slug.php` in the generated folder
2. Update the `Version:` number in the plugin header (e.g., `0.1.0` to `0.2.0`)
3. Zip the folder and upload it again through **Plugins > Add New > Upload Plugin**, or replace the folder directly in `wp-content/plugins/`

tip

WordPress will ask if you want to replace the existing plugin when you upload a zip with the same plugin name — click **Replace current with uploaded** to update.

### Automated Releases with GitHub[​](#automated-releases-with-github "Direct link to Automated Releases with GitHub")

If you push your gateway to a GitHub repository, the template includes a GitHub Actions workflow that creates releases automatically:

1. Update the `Version:` number in the plugin header
2. Commit and push to the `main` branch
3. GitHub Actions detects the version change and creates a new release with a downloadable ZIP

Other users can then download the ZIP from your repository's **Releases** page and install it like any WordPress plugin.

## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting")

Gateway doesn't appear in the POS

* Check that the plugin is activated in **WP Admin > Plugins**
* Go to **WP Admin > POS > Settings > Checkout** and make sure the gateway is enabled
* Verify that WooCommerce is installed and active

Gateway shows up on the web checkout

* Make sure `$this->enabled = 'no';` is set in the gateway constructor
* WCPOS overrides this setting for POS requests, so the gateway should only appear in the POS

Orders stay in 'Processing' instead of 'Completed'

* WooCommerce sets the order status based on product types. Orders containing physical products stay in "Processing" — this is normal WooCommerce behaviour. Only orders with exclusively virtual or downloadable products are marked "Completed" automatically.

## Requirements[​](#requirements "Direct link to Requirements")

WCPOS

<!-- -->

: Pro version required for POS checkout

WordPress

<!-- -->

: WordPress with WooCommerce installed

PHP

<!-- -->

: Basic PHP knowledge for customising the gateway

## Resources[​](#resources "Direct link to Resources")

* **GitHub**: [woocommerce-gateway-template](https://github.com/wcpos/woocommerce-gateway-template)
* **WooCommerce Payment Gateway API**: [WC\_Payment\_Gateway docs](https://woocommerce.github.io/code-reference/classes/WC-Payment-Gateway.html)

### Example Gateways[​](#example-gateways "Direct link to Example Gateways")

These existing gateways were built with the same approach and are good references:

* **[Email Invoice](/payment/gateways/email-invoice.md)** — Sends an invoice email so the customer can pay later
* **[Web Checkout](/payment/gateways/web-checkout.md)** — Redirects to the web store for payment
