WooCommerce
A native WC_Payment_Gateway plugin: settings screen, hosted-checkout redirect, and a signed return handler, built on a small PHP client that mirrors the real BoomPay SDK.
WooCommerce has a real extension point for this: WC_Payment_Gateway. The plugin below registers as a proper gateway choice at checkout, redirects to BoomPay's hosted page on process_payment(), and verifies the signed return through a custom woocommerce_api_* route — the same mechanism WooCommerce has used for offsite gateways for years.
Architecture
Customer checks out
Shopper selects "Pay with Boomcoin" and places the order.
process_payment() runs
The gateway calls BoomPay’s client to create an intent for the order total, then returns a redirect result.
WooCommerce redirects
The shopper's browser is sent to the BoomPay-hosted link to approve payment.
Signed return
BoomPay sends the shopper back to a woocommerce_api_wc_gateway_boompay route with paymentIntentId and X-Boom-Signature.
Order completes
The handler verifies the signature, confirms via getPayment(), and calls payment_complete().
Plugin files
Three files: a thin REST client mirroring the real SDK’s contract, the gateway class itself, and a bootstrap file that registers it.
<?php
/**
* Plugin Name: BoomPay for WooCommerce
* Description: Accept Boomcoin (BMC) payments through BoomPay's hosted checkout.
* Version: 1.0.0
* Requires Plugins: woocommerce
*/
defined('ABSPATH') || exit;
add_action('plugins_loaded', function () {
if (!class_exists('WC_Payment_Gateway')) {
return; // WooCommerce isn't active.
}
require_once __DIR__ . '/includes/class-boompay-client.php';
require_once __DIR__ . '/includes/class-wc-boompay-gateway.php';
});
add_filter('woocommerce_payment_gateways', function ($gateways) {
$gateways[] = 'WC_Gateway_BoomPay';
return $gateways;
});
<?php
defined('ABSPATH') || exit;
/**
* Minimal HTTP client mirroring the official boom-pay-sdk (Node) contract:
* same two REST endpoints, same x-api-key header, same HMAC-SHA1 signature
* scheme. There is no official PHP SDK, so this is built from reading the
* real SDK's source rather than guessing at one. See the API Reference page.
*/
class BoomPay_Client {
const SANDBOX_BASE = 'https://sapi.boom.market';
const LIVE_BASE = 'https://api.boom.market';
private $api_key;
private $base_url;
public function __construct($api_key, $sandbox = false) {
$this->api_key = $api_key;
$this->base_url = $sandbox ? self::SANDBOX_BASE : self::LIVE_BASE;
}
public function create_intent($amount, $success_url, $failure_url, $label, $metadata = array()) {
return $this->request('POST', '/v1/boompay/paymentIntent', array(
'amount' => $amount,
'successUrl' => $success_url,
'failureUrl' => $failure_url,
'label' => $label,
'metadata' => $metadata,
));
}
public function get_payment($id) {
return $this->request('GET', '/v1/boompay/paymentIntent/' . rawurlencode($id));
}
/**
* signature = base64( HMAC-SHA1( key = apiKey, message = paymentIntentId ) )
* "+" can arrive as a space after URL-decoding, so restore it before comparing.
*/
public function verify_signature($payment_intent_id, $signature) {
$expected = base64_encode(hash_hmac('sha1', $payment_intent_id, $this->api_key, true));
$received = str_replace(' ', '+', (string) $signature);
return hash_equals($expected, $received);
}
private function request($method, $path, $body = null) {
$args = array(
'method' => $method,
'timeout' => 30,
'headers' => array(
'x-api-key' => $this->api_key,
'Content-Type' => 'application/json',
),
);
if (null !== $body) {
$args['body'] = wp_json_encode($body);
}
$response = wp_remote_request($this->base_url . $path, $args);
if (is_wp_error($response)) {
throw new Exception('BoomPay request failed: ' . $response->get_error_message());
}
$code = wp_remote_retrieve_response_code($response);
$data = json_decode(wp_remote_retrieve_body($response), true);
if ($code < 200 || $code >= 300) {
$message = isset($data['message']) ? $data['message'] : 'Unknown BoomPay API error';
throw new Exception("BoomPay API error ({$code}): {$message}");
}
return $data;
}
}
<?php
defined('ABSPATH') || exit;
class WC_Gateway_BoomPay extends WC_Payment_Gateway {
private $sandbox;
private $client;
public function __construct() {
$this->id = 'boompay';
$this->has_fields = false;
$this->method_title = 'BoomPay (Boomcoin)';
$this->method_description = "Accept Boomcoin (BMC) payments through BoomPay's hosted checkout.";
$this->init_form_fields();
$this->init_settings();
$this->title = $this->get_option('title');
$this->description = $this->get_option('description');
$this->enabled = $this->get_option('enabled');
$this->sandbox = 'yes' === $this->get_option('sandbox');
$api_key = $this->sandbox
? $this->get_option('sandbox_api_key')
: $this->get_option('api_key');
$this->client = new BoomPay_Client($api_key, $this->sandbox);
add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options'));
add_action('woocommerce_api_wc_gateway_boompay', array($this, 'handle_return'));
}
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => 'Enable/Disable',
'type' => 'checkbox',
'label' => 'Enable BoomPay',
'default' => 'no',
),
'title' => array(
'title' => 'Title',
'type' => 'text',
'default' => 'Pay with Boomcoin',
),
'description' => array(
'title' => 'Description',
'type' => 'textarea',
'default' => 'You will be redirected to BoomPay to pay from your Boom wallet.',
),
'sandbox' => array(
'title' => 'Sandbox mode',
'type' => 'checkbox',
'label' => 'Enable sandbox / test mode',
'default' => 'yes',
),
'api_key' => array(
'title' => 'Live API key',
'type' => 'password',
),
'sandbox_api_key' => array(
'title' => 'Sandbox API key',
'type' => 'password',
),
);
}
public function process_payment($order_id) {
$order = wc_get_order($order_id);
$return_url = WC()->api_request_url('WC_Gateway_BoomPay');
try {
$intent = $this->client->create_intent(
$this->to_bmc($order->get_total(), $order->get_currency()),
add_query_arg(array('boompay_status' => 'success', 'order_id' => $order_id), $return_url),
add_query_arg(array('boompay_status' => 'failure', 'order_id' => $order_id), $return_url),
sprintf('Order #%s', $order->get_order_number()),
array('order_id' => $order_id, 'order_key' => $order->get_order_key())
);
} catch (Exception $e) {
wc_add_notice('BoomPay error: ' . $e->getMessage(), 'error');
return array('result' => 'failure');
}
$order->update_meta_data('_boompay_intent_id', $intent['id']);
$order->update_status('on-hold', 'Awaiting BoomPay payment.');
$order->save();
return array(
'result' => 'success',
'redirect' => $intent['link'],
);
}
public function handle_return() {
$order_id = isset($_GET['order_id']) ? absint($_GET['order_id']) : 0;
$intent_id = isset($_GET['paymentIntentId']) ? sanitize_text_field($_GET['paymentIntentId']) : '';
$signature = isset($_GET['X-Boom-Signature']) ? sanitize_text_field(wp_unslash($_GET['X-Boom-Signature'])) : '';
$order = wc_get_order($order_id);
if (!$order || !$this->client->verify_signature($intent_id, $signature)) {
wp_die('BoomPay signature verification failed.', 'BoomPay', array('response' => 403));
}
$payment = $this->client->get_payment($intent_id);
$status = isset($_GET['boompay_status']) ? $_GET['boompay_status'] : '';
if (!empty($payment['paidAt']) && 'success' === $status) {
$order->payment_complete($intent_id);
$order->add_order_note('Paid via BoomPay. Intent: ' . $intent_id);
wp_safe_redirect($this->get_return_url($order));
} else {
$order->update_status('failed', 'BoomPay payment failed or was cancelled.');
wp_safe_redirect(wc_get_checkout_url());
}
exit;
}
/**
* BoomPay settles in BMC and has no FX endpoint (see API Reference > Currency).
* Replace this with your own fiat -> BMC rate source before going live.
*/
private function to_bmc($total, $currency) {
return (float) $total;
}
}
Install
Zip the three files above preserving the includes/ folder, then upload via Plugins → Add New → Upload Plugin, or drop the folder into wp-content/plugins/boompay-for-woocommerce/ over SFTP. Activate it, then go to WooCommerce → Settings → Payments → BoomPay (Boomcoin) to configure it.
Leave Sandbox mode checked and fill in a sandbox API key first. Switch it off and add your live key only once you’ve completed a full test order end to end.
Testing in sandbox
With sandbox mode on, place a test order and choose BoomPay at checkout. You’ll be redirected to BoomPay’s sandbox-hosted page (served from sapi.boom.market); approve it from a Boom wallet configured for testing, and confirm the order lands in WooCommerce → Orders as Processing with an order note recording the intent id. Cancel a second test payment to confirm the order correctly moves to Failed instead.
Go-live checklist
- Replace the sandbox API key with a live one and uncheck sandbox mode.
- Implement
to_bmc()with a real fiat→BMC conversion rate — the placeholder in this plugin passes your store currency total through unchanged, which is only correct if your store already prices in BMC. - Confirm your site serves the return URL over HTTPS; BoomPay’s own hosted page is HTTPS-only, and mixed content will break the redirect back.
- Run one real, small-value live payment before announcing the option to customers.