<?php
class WC_Accelebit_Gateway extends WC_Payment_Gateway
{
private string $api_url = 'https://api.gateway.accelebit.com';
public function __construct()
{
$this->id = 'accelebit';
$this->method_title = 'Accelebit';
$this->method_description = 'Accept card payments via Accelebit Payments API';
$this->has_fields = true;
$this->supports = ['products', 'refunds'];
$this->init_form_fields();
$this->init_settings();
$this->title = $this->get_option('title', 'Credit / Debit Card');
$this->description = $this->get_option('description', 'Pay securely with your card.');
$this->enabled = $this->get_option('enabled');
add_action(
'woocommerce_update_options_payment_gateways_' . $this->id,
[$this, 'process_admin_options']
);
}
public function init_form_fields(): void
{
$this->form_fields = [
'enabled' => [
'title' => 'Enable/Disable',
'type' => 'checkbox',
'label' => 'Enable Accelebit Payments',
'default' => 'no',
],
'title' => [
'title' => 'Title',
'type' => 'text',
'default' => 'Credit / Debit Card',
],
'description' => [
'title' => 'Description',
'type' => 'textarea',
'default' => 'Pay securely with your card.',
],
'secret_key' => [
'title' => 'Secret Key',
'type' => 'password',
'description' => 'Your Accelebit secret key (starts with smtgw_sk_)',
],
'webhook_secret' => [
'title' => 'Webhook Secret',
'type' => 'password',
'description' => 'Used to verify incoming webhook signatures',
],
];
}
public function payment_fields(): void
{
if ($this->description) {
echo '<p>' . esc_html($this->description) . '</p>';
}
?>
<fieldset>
<p class="form-row form-row-wide">
<label for="accelebit-card-number">Card Number <span class="required">*</span></label>
<input id="accelebit-card-number" name="accelebit_card_number"
type="text" autocomplete="cc-number" maxlength="19" />
</p>
<p class="form-row form-row-first">
<label for="accelebit-expiry-month">Expiry Month <span class="required">*</span></label>
<input id="accelebit-expiry-month" name="accelebit_expiry_month"
type="text" autocomplete="cc-exp-month" maxlength="2" placeholder="MM" />
</p>
<p class="form-row form-row-last">
<label for="accelebit-expiry-year">Expiry Year <span class="required">*</span></label>
<input id="accelebit-expiry-year" name="accelebit_expiry_year"
type="text" autocomplete="cc-exp-year" maxlength="2" placeholder="YY" />
</p>
<p class="form-row form-row-first">
<label for="accelebit-cvv">CVV <span class="required">*</span></label>
<input id="accelebit-cvv" name="accelebit_cvv"
type="text" autocomplete="cc-csc" maxlength="4" />
</p>
<p class="form-row form-row-last">
<label for="accelebit-holder">Cardholder Name <span class="required">*</span></label>
<input id="accelebit-holder" name="accelebit_holder_name"
type="text" autocomplete="cc-name" />
</p>
</fieldset>
<?php
}
public function process_payment($order_id): array
{
$order = wc_get_order($order_id);
$payload = [
'amount' => $order->get_total(),
'currency' => $order->get_currency(),
'paymentMethod' => 'card',
'customerId' => (string) $order->get_customer_id() ?: $order->get_billing_email(),
'card' => [
'number' => sanitize_text_field($_POST['accelebit_card_number']),
'expiryMonth' => sanitize_text_field($_POST['accelebit_expiry_month']),
'expiryYear' => sanitize_text_field($_POST['accelebit_expiry_year']),
'cvv' => sanitize_text_field($_POST['accelebit_cvv']),
'holderName' => sanitize_text_field($_POST['accelebit_holder_name']),
],
'billing' => [
'firstName' => $order->get_billing_first_name(),
'lastName' => $order->get_billing_last_name(),
'email' => $order->get_billing_email(),
'phone' => $order->get_billing_phone(),
'country' => $order->get_billing_country(),
'address' => $order->get_billing_address_1(),
'addressLine2' => $order->get_billing_address_2() ?: null,
'city' => $order->get_billing_city(),
'postalCode' => $order->get_billing_postcode(),
'state' => $order->get_billing_state() ?: null,
],
'returnUrl' => $this->get_return_url($order),
'merchantRef' => (string) $order_id,
];
$response = wp_remote_post($this->api_url . '/v1/payments', [
'headers' => [
'Content-Type' => 'application/json',
'X-API-Key' => $this->get_option('secret_key'),
'Idempotency-Key' => 'woo_' . $order_id . '_' . time(),
],
'body' => wp_json_encode($payload),
'timeout' => 30,
]);
if (is_wp_error($response)) {
wc_add_notice('Payment failed. Please try again.', 'error');
return ['result' => 'fail'];
}
$body = json_decode(wp_remote_retrieve_body($response), true);
// 3DS redirect required
if (!empty($body['data']['threeDsRequired'])) {
$order->update_meta_data('_accelebit_payment_id', $body['data']['id']);
$order->save();
return [
'result' => 'success',
'redirect' => $body['data']['threeDsData']['redirectUrl'],
];
}
// Payment captured
if (($body['data']['status'] ?? '') === 'captured') {
$order->payment_complete($body['data']['id']);
$order->add_order_note('Accelebit payment captured: ' . $body['data']['id']);
return [
'result' => 'success',
'redirect' => $this->get_return_url($order),
];
}
// Payment failed
$error_msg = $body['error']['message'] ?? 'Payment was declined.';
wc_add_notice($error_msg, 'error');
$order->update_status('failed', 'Accelebit: ' . $error_msg);
return ['result' => 'fail'];
}
public function process_refund($order_id, $amount = null, $reason = ''): bool
{
$order = wc_get_order($order_id);
$payment_id = $order->get_transaction_id();
if (!$payment_id) {
return false;
}
$response = wp_remote_post($this->api_url . '/v1/refunds', [
'headers' => [
'Content-Type' => 'application/json',
'X-API-Key' => $this->get_option('secret_key'),
'Idempotency-Key' => 'woo_refund_' . $order_id . '_' . time(),
],
'body' => wp_json_encode([
'transactionId' => $payment_id,
'amount' => number_format((float) $amount, 2, '.', ''),
'currency' => $order->get_currency(),
'reason' => $reason ?: 'Refund from WooCommerce',
]),
'timeout' => 30,
]);
if (is_wp_error($response)) {
return false;
}
$body = json_decode(wp_remote_retrieve_body($response), true);
$status = wp_remote_retrieve_response_code($response);
if ($status === 201) {
$order->add_order_note(
sprintf('Accelebit refund created: %s', $body['data']['id'] ?? 'unknown')
);
return true;
}
return false;
}
}