id = sanitize_key( $id ); $this->method_title = esc_html( $title ); $this->method_description = esc_html( $description ); $this->init_form_fields(); $this->init_settings(); $this->title = sanitize_text_field( $this->get_option( 'title' ) ); $this->description = sanitize_textarea_field( $this->get_option( 'description' ) ); $this->enabled = sanitize_text_field( $this->get_option( 'enabled' ) ); $this->order_status = sanitize_text_field( $this->get_option( 'order_status' ) ); $this->instructions = sanitize_textarea_field( $this->get_option( 'instructions' ) ); $this->allowed_users = $this->get_option( 'allowed_users', array() ); add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); add_action( 'woocommerce_email_before_order_table', array( $this, 'add_instructions_to_email' ), 10, 4 ); add_action( 'woocommerce_thankyou', array( $this, 'display_instructions_on_thankyou_page' ) ); } public function init_form_fields() { include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); $all_statuses = wc_get_order_statuses(); $allowed_statuses = array(); if ( is_plugin_active( 'aisp-order-tools/aisp-order-tools.php' ) ) { $allowed_statuses['wc-pending'] = $all_statuses['wc-pending']; } $allowed_statuses['wc-on-hold'] = $all_statuses['wc-on-hold']; $allowed_statuses['wc-processing'] = $all_statuses['wc-processing']; $this->form_fields = array( 'enabled' => array( 'title' => esc_html__( 'Enable/Disable', 'aisp-custom-payment-manager' ), 'type' => 'checkbox', 'label' => esc_html__( 'Enable this payment method', 'aisp-custom-payment-manager' ), 'default' => 'yes', ), 'title' => array( 'title' => esc_html__( 'Title', 'aisp-custom-payment-manager' ), 'type' => 'text', 'description' => esc_html__( 'The title displayed to customers.', 'aisp-custom-payment-manager' ), 'default' => esc_html__( 'Custom Payment', 'aisp-custom-payment-manager' ), ), 'description' => array( 'title' => esc_html__( 'Description', 'aisp-custom-payment-manager' ), 'type' => 'textarea', 'description' => esc_html__( 'The description displayed to customers.', 'aisp-custom-payment-manager' ), 'default' => esc_html__( 'Pay using this custom method.', 'aisp-custom-payment-manager' ), ), 'order_status' => array( 'title' => esc_html__( 'Order Status', 'aisp-custom-payment-manager' ), 'type' => 'select', 'description' => esc_html__( 'Set the order status after payment.', 'aisp-custom-payment-manager' ), 'options' => $allowed_statuses, 'default' => 'wc-on-hold', ), 'instructions' => array( 'title' => esc_html__( 'Instructions', 'aisp-custom-payment-manager' ), 'type' => 'textarea', 'description' => esc_html__( 'Instructions included in the email and thank-you page.', 'aisp-custom-payment-manager' ), 'default' => '', ), 'allowed_users' => array( 'title' => esc_html__( 'Allowed Users', 'aisp-custom-payment-manager' ), 'type' => 'multiselect', 'description' => esc_html__( 'Search and select users allowed to use this payment method. Leave empty to allow all users.', 'aisp-custom-payment-manager' ), 'options' => $this->get_user_list(), 'default' => array(), 'class' => 'wc-customer-search', ), ); } /** * Build the user list for the admin multiselect. * * Only loads users already saved in the setting, keeping the initial * page load fast regardless of site size. New users are found via the * AJAX search powered by wc-customer-search / Select2, which queries * the WooCommerce customer search endpoint automatically. * * @return array $user_id => display_name pairs. */ private function get_user_list() { $saved = $this->get_option( 'allowed_users', array() ); $list = array(); if ( empty( $saved ) ) { return $list; } $users = get_users( array( 'include' => array_map( 'intval', $saved ), 'fields' => array( 'ID', 'display_name' ), ) ); foreach ( $users as $user ) { $list[ $user->ID ] = esc_html( $user->display_name ); } return $list; } public function is_available() { if ( 'yes' !== $this->enabled ) { return false; } if ( empty( $this->allowed_users ) ) { return true; } return in_array( get_current_user_id(), array_map( 'intval', $this->allowed_users ), true ); } public function process_payment( $order_id ) { $order = wc_get_order( $order_id ); if ( ! $order ) { return array( 'result' => 'fail' ); } $order->update_status( $this->order_status, 'Awaiting payment confirmation.' ); return array( 'result' => 'success', 'redirect' => $this->get_return_url( $order ), ); } /** * Map an order status slug to its corresponding WooCommerce customer email ID. * * This ensures instructions are injected into the correct email regardless * of which order status is configured for this gateway. * * @param string $order_status e.g. 'wc-on-hold', 'wc-processing'. * @return string|null WooCommerce email ID, or null if not mapped. */ private function get_email_id_for_status( $order_status ) { $map = array( 'wc-pending' => 'customer_pending_order', 'wc-on-hold' => 'customer_on_hold_order', 'wc-processing' => 'customer_processing_order', ); return isset( $map[ $order_status ] ) ? $map[ $order_status ] : null; } public function add_instructions_to_email( $order, $sent_to_admin, $plain_text, $email ) { $expected_email_id = $this->get_email_id_for_status( $this->order_status ); if ( ! $expected_email_id || ! isset( $email->id ) || $email->id !== $expected_email_id ) { return; } if ( $order->get_payment_method() !== $this->id ) { return; } if ( ! $this->instructions ) { return; } if ( $plain_text ) { echo esc_html__( 'Payment Instructions', 'aisp-custom-payment-manager' ) . ":\n"; echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) ); } else { echo '