Files
AluxPay/aluxpay-payment-gateway/includes/class-aluxpay-payment-gateway.php

439 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* AluxPay Payment Gateway Class
*/
if (!defined('ABSPATH')) {
exit;
}
class WC_Aluxpay_Payment_Gateway extends WC_Payment_Gateway {
/**
* Reusable: HTML notice for Thank You page + HTML emails
*/
protected function get_generic_notice_html(): string {
// Keep inline styles for email clients; translate strings
$html .= '<h5>' . esc_html__( 'Important Note:', 'aluxpay-payment-gateway' ) . '</h5>';
$html .= '<p>' . esc_html__( "Because of the nature of our business and how our website integrates with PayPal, youll also receive a PayPal payment confirmation email. That email will display a generic product name instead of the specific item(s) you purchased.", 'aluxpay-payment-gateway' ) . '</p>';
$html .= '<p>' . esc_html__( 'Rest assured — your order is fully confirmed, and the webstore confirmation email contains the correct details of your purchase.', 'aluxpay-payment-gateway' ) . '</p>';
$html .= '<p>' . esc_html__( "If you have any questions or need assistance, please dont hesitate to contact our support team.", 'aluxpay-payment-gateway' ) . '</p>';
// For frontend we can allow basic tags; for email we echo directly.
$allowed = array(
'p' => array('style'=>true),
'h5' => array('style'=>true),
'strong' => array(),
);
return wp_kses( $html, $allowed );
}
/**
* Reusable: Plain-text version for plain emails
*/
protected function get_generic_notice_plain(): string {
$lines = array(
__( 'Important Note:', 'aluxpay-payment-gateway' ),
__( "Because of the nature of our business and how our website integrates with PayPal, youll also receive a PayPal payment confirmation email. That email will display a generic product name instead of the specific item(s) you purchased.", 'aluxpay-payment-gateway' ),
__( 'Rest assured — your order is fully confirmed, and the webstore confirmation email contains the correct details of your purchase.', 'aluxpay-payment-gateway' ),
'',
__( "If you have any questions or need assistance, please dont hesitate to contact our support team.", 'aluxpay-payment-gateway' ),
);
return implode( PHP_EOL, $lines ) . PHP_EOL;
}
/**
* Reusable: HTML notice for Failed Order emails
*/
protected function get_failed_notice_html(): string {
$html = '';
$html .= '<p><strong>' . esc_html__( 'Payment Failed', 'aluxpay-payment-gateway' ) . '</strong></p>';
$html .= '<p>' . esc_html__( 'Unfortunately, your payment could not be processed. This may have occurred for one of the following reasons:', 'aluxpay-payment-gateway' ) . '</p>';
$html .= '<ul style="margin-left: 20px;">';
$html .= '<li>' . esc_html__( 'Insufficient funds in your account', 'aluxpay-payment-gateway' ) . '</li>';
$html .= '<li>' . esc_html__( 'Payment was cancelled during the process', 'aluxpay-payment-gateway' ) . '</li>';
$html .= '<li>' . esc_html__( 'Payment method declined the transaction', 'aluxpay-payment-gateway' ) . '</li>';
$html .= '<li>' . esc_html__( 'Technical issue during payment processing', 'aluxpay-payment-gateway' ) . '</li>';
$html .= '</ul>';
$html .= '<p>' . esc_html__( 'Your order has not been completed and no charges have been made to your account.', 'aluxpay-payment-gateway' ) . '</p>';
$html .= '<h5>' . esc_html__( 'What to do next:', 'aluxpay-payment-gateway' ) . '</h5>';
$html .= '<p>' . esc_html__( 'You can try placing your order again by visiting our website. If you continue to experience issues, please contact us for assistance.', 'aluxpay-payment-gateway' ) . '</p>';
$html .= '<p>' . esc_html__( 'We apologize for any inconvenience this may have caused.', 'aluxpay-payment-gateway' ) . '</p>';
$allowed = array(
'p' => array('style'=>true),
'h5' => array('style'=>true),
'ul' => array('style'=>true),
'li' => array(),
'strong' => array(),
);
return wp_kses( $html, $allowed );
}
/**
* Reusable: Plain-text version for Failed Order emails
*/
protected function get_failed_notice_plain(): string {
$lines = array(
__( 'Payment Failed', 'aluxpay-payment-gateway' ),
'',
__( 'Unfortunately, your payment could not be processed. This may have occurred for one of the following reasons:', 'aluxpay-payment-gateway' ),
'',
'- ' . __( 'Insufficient funds in your account', 'aluxpay-payment-gateway' ),
'- ' . __( 'Payment was cancelled during the process', 'aluxpay-payment-gateway' ),
'- ' . __( 'Payment method declined the transaction', 'aluxpay-payment-gateway' ),
'- ' . __( 'Technical issue during payment processing', 'aluxpay-payment-gateway' ),
'',
__( 'Your order has not been completed and no charges have been made to your account.', 'aluxpay-payment-gateway' ),
'',
__( 'What to do next:', 'aluxpay-payment-gateway' ),
__( 'You can try placing your order again by visiting our website. If you continue to experience issues, please contact us for assistance.', 'aluxpay-payment-gateway' ),
'',
__( 'We apologize for any inconvenience this may have caused.', 'aluxpay-payment-gateway' ),
);
return implode( PHP_EOL, $lines ) . PHP_EOL;
}
/**
* Constructor
*/
public function __construct() {
$this->id = 'aluxpay_payment_gateway';
$this->icon = ''; // URL to icon (optional)
$this->method_title = __('AluxPay Payment Gateway', 'aluxpay-payment-gateway');
$this->method_description = __('Redirects customers to a standalone payment website for secure PayPal payments.', 'aluxpay-payment-gateway');
$this->has_fields = false;
// Load the settings
$this->init_form_fields();
$this->init_settings();
// Define user set variables
$this->title = $this->get_option('title');
$this->description = $this->get_option('description');
$this->payment_url = $this->get_option('payment_url');
$this->enabled = $this->get_option('enabled');
$this->testmode = 'yes' === $this->get_option('testmode');
$this->debug = 'yes' === $this->get_option('debug', 'no');
// Logs
if ($this->debug) {
$this->log = wc_get_logger();
}
// Actions
add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options'));
add_action('woocommerce_api_' . $this->id, array($this, 'webhook_handler'));
add_action('woocommerce_thankyou_' . $this->id, array($this, 'thankyou_page'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_checkout_styles'));
// Customer Emails - Success
add_action('woocommerce_email_before_order_table', array($this, 'email_instructions'), 10, 3);
// Customer Emails - Failed Orders
add_action('woocommerce_email_before_order_table', array($this, 'failed_email_instructions'), 10, 3);
}
// SVG icons on checkout
public function get_icon() {
$icons = array(
'discover' => array(
'file' => 'discover.svg',
'alt' => 'Discover'
),
'amex' => array(
'file' => 'american-express.svg',
'alt' => 'American Express'
),
'visa' => array(
'file' => 'visa.svg',
'alt' => 'Visa'
),
'mastercard' => array(
'file' => 'mastercard-alt.svg',
'alt' => 'Mastercard'
),
'paypal' => array(
'file' => 'paypal.svg',
'alt' => 'PayPal'
),
);
$icons_html = '<span class="aluxpay-payment-icons">';
foreach ($icons as $key => $icon) {
// Use the constant defined in main plugin file
$icon_url = ALUXPAY_PLUGIN_URL . 'assets/images/' . $icon['file'];
$icons_html .= sprintf(
'<img src="%s" alt="%s" class="aluxpay-icon aluxpay-icon-%s" />',
esc_url($icon_url),
esc_attr($icon['alt']),
esc_attr($key)
);
}
$icons_html .= '</span>';
return $icons_html;
}
/**
* Enqueue checkout styles
*/
public function enqueue_checkout_styles() {
if (is_checkout()) {
wp_enqueue_style(
'aluxpay-checkout',
ALUXPAY_PLUGIN_URL . 'assets/css/checkout.css',
array(),
'1.0.1'
);
}
}
/**
* Initialize Gateway Settings Form Fields
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __('Enable/Disable', 'aluxpay-payment-gateway'),
'label' => __('Enable AluxPay Payment Gateway', 'aluxpay-payment-gateway'),
'type' => 'checkbox',
'description' => '',
'default' => 'no'
),
'title' => array(
'title' => __('Title', 'aluxpay-payment-gateway'),
'type' => 'text',
'description' => __('This controls the title which the user sees during checkout.', 'aluxpay-payment-gateway'),
'default' => __(' PayPal or Credit/Debit Card Payment ', 'aluxpay-payment-gateway'),
'desc_tip' => true,
),
'description' => array(
'title' => __('Description', 'aluxpay-payment-gateway'),
'type' => 'textarea',
'description' => __('Payment method description that the customer will see on your checkout.', 'aluxpay-payment-gateway'),
'default' => __('You will be redirected to complete payment securely with PayPal or Credit Card.', 'aluxpay-payment-gateway'),
'desc_tip' => true,
),
'payment_url' => array(
'title' => __('Payment Website URL', 'aluxpay-payment-gateway'),
'type' => 'text',
'description' => __('The URL of your standalone payment website (e.g., https://payment.yoursite.com)', 'aluxpay-payment-gateway'),
'default' => 'http://localhost:5173/payment',
'desc_tip' => true,
),
'testmode' => array(
'title' => __('Test mode', 'aluxpay-payment-gateway'),
'label' => __('Enable Test Mode', 'aluxpay-payment-gateway'),
'type' => 'checkbox',
'description' => __('Place the payment gateway in test mode using test API keys.', 'aluxpay-payment-gateway'),
'default' => 'yes',
'desc_tip' => true,
),
'debug' => array(
'title' => __('Debug log', 'aluxpay-payment-gateway'),
'label' => __('Enable logging', 'aluxpay-payment-gateway'),
'type' => 'checkbox',
'description' => sprintf(__('Log events inside %s Note: this may log personal information. We recommend using this for debugging purposes only.', 'aluxpay-payment-gateway'), '<code>' . WC_Log_Handler_File::get_log_file_path($this->id) . '</code>'),
'default' => 'no',
),
);
}
/**
* Process the payment and return the result
*/
public function process_payment($order_id) {
$order = wc_get_order($order_id);
if ($this->debug) {
$this->log->info('Processing payment for order #' . $order_id, array('source' => $this->id));
}
// Mark as pending payment
$order->update_status('pending', __('Awaiting payment via AluxPay Payment Gateway.', 'aluxpay-payment-gateway'));
// Reduce stock levels
wc_reduce_stock_levels($order_id);
// Remove cart
WC()->cart->empty_cart();
// Build redirect URL with order parameters
$redirect_url = $this->get_payment_redirect_url($order);
if ($this->debug) {
$this->log->info('Redirecting to: ' . $redirect_url, array('source' => $this->id));
}
// Return redirect
return array(
'result' => 'success',
'redirect' => $redirect_url
);
}
/**
* Build payment redirect URL
*/
private function get_payment_redirect_url($order) {
// Build the base URL
$base_url = $this->payment_url;
// Build parameters array - NO special characters
$params = array(
'wc_order_id' => $order->get_id(),
'total' => $order->get_total(),
'currency' => $order->get_currency(),
'description' => 'Order ' . $order->get_id(), // ← No # symbol
'customer_email' => $order->get_billing_email(),
'return_url' => urlencode($this->get_return_url($order)),
'cancel_url' => urlencode(wc_get_checkout_url()),
'_wpnonce' => wp_create_nonce('cpg_payment_' . $order->get_id()),
);
return add_query_arg($params, $base_url);
}
/**
* Webhook handler for payment updates
*/
public function webhook_handler() {
if ($this->debug) {
$this->log->info('Webhook received', array('source' => $this->id));
}
// Get the raw POST data
$raw_post = file_get_contents('php://input');
$decoded = json_decode($raw_post);
if (!$decoded || !isset($decoded->order_id) || !isset($decoded->transaction_id)) {
if ($this->debug) {
$this->log->error('Invalid webhook data received', array('source' => $this->id));
}
status_header(400);
die('Invalid data');
}
$order_id = absint($decoded->order_id);
$transaction_id = sanitize_text_field($decoded->transaction_id);
$status = sanitize_text_field($decoded->status);
$order = wc_get_order($order_id);
if (!$order) {
if ($this->debug) {
$this->log->error('Order not found: ' . $order_id, array('source' => $this->id));
}
status_header(404);
die('Order not found');
}
// Process based on status
if ($status === 'completed' || $status === 'COMPLETED') {
// Payment complete
$order->payment_complete($transaction_id);
// Add order note
$order->add_order_note(
sprintf(__('Payment completed via AluxPay Payment Gateway. Transaction ID: %s', 'aluxpay-payment-gateway'), $transaction_id)
);
if ($this->debug) {
$this->log->info('Payment completed for order #' . $order_id . ' Transaction ID: ' . $transaction_id, array('source' => $this->id));
}
status_header(200);
die('Success');
} else {
// Payment failed
$order->update_status('failed', __('Payment failed or was declined.', 'aluxpay-payment-gateway'));
if ($this->debug) {
$this->log->warning('Payment failed for order #' . $order_id, array('source' => $this->id));
}
status_header(200);
die('Marked as failed');
}
}
/**
* Output for the order received page
*/
public function thankyou_page($order_id) {
/**if ($this->description) {
echo wpautop(wptexturize($this->description));
}*/
$order = wc_get_order($order_id);
if ($order && $order->get_status() === 'processing') {
echo $this->get_generic_notice_html();
}
}
/**
* Add content to the WC emails for successful orders
*/
public function email_instructions($order, $sent_to_admin, $plain_text = false) {
/** if ($this->description && !$sent_to_admin && $this->id === $order->get_payment_method()) {
* echo wpautop(wptexturize($this->description)) . PHP_EOL;
*} */
if ( $sent_to_admin ) return; // customers only
if ( ! $order instanceof WC_Order ) return;
if ( $order->get_payment_method() !== $this->id ) return;
// Only show for completed/processing orders
if ( ! in_array( $order->get_status(), array( 'processing' ) ) ) return;
// Pick the right format for the email renderer
if ( $plain_text ) {
echo $this->get_generic_notice_plain();
} else {
echo $this->get_generic_notice_html();
}
}
/**
* Add content to the WC emails for failed orders
*/
public function failed_email_instructions($order, $sent_to_admin, $plain_text = false) {
if ( $sent_to_admin ) return; // customers only
if ( ! $order instanceof WC_Order ) return;
if ( $order->get_payment_method() !== $this->id ) return;
// Only show for failed orders
if ( $order->get_status() !== 'failed' ) return;
// Pick the right format for the email renderer
if ( $plain_text ) {
echo $this->get_failed_notice_plain();
} else {
echo $this->get_failed_notice_html();
}
}
}