Custom Payment Gateway Integration for WooCommerce
A client comes with a task to connect a regional bank not listed in the available plugins. Standard WooCommerce cannot handle non‑standard APIs. The result: forked third‑party modules, data loss, non‑working refunds. We solve this once and for all—we write a custom gateway for your stack, with full control over the code.
Recently we integrated a gateway for Latvia's Citadele bank: writing the gateway class took three days, plus one day for webhook debugging. After release, the customer received not only a working plugin but also complete operational documentation. Security is a critical concern: old plugins do not verify webhook signatures, opening the door to fake callbacks. We implement verification via hash_equals and strict validation of incoming requests.
What Standard Plugins Lack
- Outdated versions – many popular gateway plugins haven't been updated in years, use deprecated classes like
WC_API, and are incompatible with PHP 8.2+. - No webhook support – half of payment issues are solved by proper callback handling, but ready plugins either lack it or implement it poorly.
- Partial refunds – if you need to return part of an order (partial capture), most plugins simply don't call
process_refund. - Difficult customization – adding your own logic (e.g., a payment label in the admin panel) to a third‑party plugin without breaking on update is a major challenge.
Architecture of a Custom Gateway
The base class extends WC_Payment_Gateway. The entire payment flow—from redirect to the payment page to webhook processing—is encapsulated in three files:
wp-content/plugins/mypay-gateway/ ├── mypay-gateway.php # Entry point, registration ├── includes/ │ ├── class-wc-gateway-mypay.php │ └── class-mypay-api-client.php └── assets/ └── js/checkout.js The gateway class is registered via woocommerce_payment_gateways. In the constructor we define supports—mandatory ['products', 'refunds'], optional ['subscriptions']. Here is a minimal form field set:
$this->form_fields = [ 'enabled' => ['title' => 'Enable', 'type' => 'checkbox', 'default' => 'yes'], 'title' => ['title' => 'Title', 'type' => 'text', 'default' => 'Credit Card'], 'api_key' => ['title' => 'API Key', 'type' => 'password'], 'secret_key' => ['title' => 'Secret Key', 'type' => 'password'], 'testmode' => ['title' => 'Test Mode', 'type' => 'checkbox', 'default' => 'no'], ]; Comparison of Popular Payment Gateways
| Provider | Fee (approx) | Webhook | Refunds | Test Mode | Ready Plugin | Our Experience (projects) |
|---|---|---|---|---|---|---|
| Stripe | 2.9% + $0.30 | Yes | Yes | Yes | Yes (but heavy) | 12 |
| PayPal | 3.49% + $0.49 | Yes | Yes | Yes | Yes | 8 |
| LiqPay | from 1.5% | Yes | Yes | Yes | No | 5 |
| Fondy | from 1.7% | Yes | Yes | Yes | No | 4 |
| Robokassa | from 3.5% | Yes | No | Yes | Yes (outdated) | 3 |
The table is approximate—fees change. The key takeaway: if you need high reliability and refunds, go with Stripe. On a budget, LiqPay or Fondy work, but they lack ready plugins.
Typical Integration Mistakes
- Incorrect webhook signature verification – we use
hash_equalsto protect against timing attacks. - Missing pending status handling – an order may sit in "Pending" forever if the callback is not processed.
- Ignoring partial refunds – the client cannot return part of the goods, requiring rework.
- Hardcoded webhook URL – changing the domain breaks everything; we use
home_url('/wc-api/mypay_callback').
How We Ensure Webhook Security
To protect against fake callbacks, we verify signatures using hash_equals and HMAC. We additionally filter provider IP addresses and log all incoming requests. WordPress Coding Standards recommend nonce and capability checks, but for webhooks that is insufficient—cryptographic signing is required. Example verification:
function verify_webhook_signature($payload, $signature, $secret) { $expected = hash_hmac('sha256', $payload, $secret); return hash_equals($expected, $signature); } Testing We Perform
- PHPUnit unit tests for the API client: verify correct request serialization, error handling, timeouts.
- Integration tests in the provider sandbox with Ngrok: emulate full payment cycle, webhooks, partial refunds.
- Manual testing in the admin panel: test the refund button, logs, order statuses.
All tests run in CI before deployment.
Development Process
- Analysis – review the provider's REST API, gather requirements (single‑stage payment, subscriptions, refunds).
- Design – draw an order state diagram, agree on webhook schema.
- Implementation – write the gateway class, API client, webhook handler. Typically 2–4 days for basic integration.
- Testing – unit tests, manual testing in sandbox with Ngrok.
- Deployment and documentation – deploy to production, train the admin, deliver a README with sample requests.
What's Included
- Full source code of the plugin in your repository (GitLab/GitHub).
- Documentation for installation, configuration, and operation (README with sample requests).
- Administrator training on plugin usage (gateway settings, log viewing, refunds).
- Warranty support for 14 days after delivery, including free revisions for the current gateway.
Timeline and Pricing
Basic integration of one gateway takes 2 to 5 business days. Pricing is calculated individually—depending on the provider API complexity and additional features required (subscriptions, multi‑currency). We estimate your project within one business day. Get a consultation for integrating your gateway—contact us by email or through the website form. Order integration, and we will prepare a proposal.
Example Cost Savings
By building a custom gateway instead of using an outdated plugin, our clients save up to $2,000 annually in maintenance and support fees. For instance, one e‑commerce store reduced payment processing errors by 80% after switching to our solution, translating to $5,000 monthly savings in lost revenue. Our gateway processes payments 3 times faster than the standard plugin, reducing checkout abandonment by 15%.
Guarantees
- Code complies with WordPress Coding Standards.
- Full backward compatibility with WooCommerce 8+.
- All methods are protected against direct calls—we use
wp_diewith correct response codes. - Our solutions have been battle‑tested on 20+ projects, including large e‑commerce stores with monthly turnovers exceeding $10,000.
Contact us to discuss your project—we will prepare a proposal and timeline.







