<?php
/**
 * Plugin Name: Authorize.net Payments for WooCommerce
 * Description: Accept credit cards and eChecks in WooCommerce with Authorize.net.
 * Version: 1.0.2
 * Author: Authorize.net
 * Author URI: https://www.authorize.net/
 * Developer: Authorize.net
 * Requires Plugins: woocommerce
 * Requires at least: 6.1
 * Tested up to: 6.9
 * Requires PHP: 8.0.0
 * WC requires at least: 7.6.0
 * WC tested up to: 10.4.3
 * Text Domain: authorize-net-payments-for-woocommerce
 * Domain Path: /languages
 *
 * License: GNU General Public License v2.0
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
 *
 * @package Authorize_Net_Payments_For_Woocommerce
 */

if (! defined('ABSPATH')) {
    exit;
}

require_once(plugin_dir_path(__FILE__) . '/includes/api/tokenization/class-anet-echeck-tokenization.php');
require_once(plugin_dir_path(__FILE__) . '/includes/admin/class-anet-loader.php');

/**
 * Currently plugin version.
 * Start at version 1.0.0 and use SemVer - https://semver.org
 * Rename this for your plugin and update it as you release new versions.
 */
define('ANET_PLUGIN_VERSION', '1.0.2');
/**
 *
 * Sends through sale and request for funds to be charged to cardholder's credit card Constant.
 */
define('ANET_TRANSACTION_TYPE_CHARGE', 'charge');
/**
 *
 * Sends through a request for funds to be "reserved" on the cardholder's credit card. 
 * A standard authorization is reserved for 2-5 days. 
 * Reservation times are determined by cardholder's bank.
 */
define('ANET_TRANSACTION_TYPE_AUTHORIZATION', 'authorization');
/**
 *
 * The production environment identifier Constant.
 */
define('ANET_ENVIRONMENT_PRODUCTION', 'production');
/**
 *
 * The test environment identifier Constant.
 */
define('ANET_ENVIRONMENT_TEST', 'test'); 
 /*
 * The test environment identifier Constant.
 */
define('ANET_ENVIRONMENT_TESTMODE', 'testMode'); 

 /*
 * The test environment identifier Constant.
 */
define('ANET_ENVIRONMENT_LIVEMODE', 'liveMode');
/**
 *
 * Accept Js domain for Test Mode.
 */
define('ANET_ACCEPT_TEST_DOMAIN', 'https://jstest.authorize.net/v1/Accept.js');
/**
 *
 * Accept Js domain for Production Mode.
 */
define('ANET_ACCEPT_PROD_DOMAIN', 'https://js.authorize.net/v1/Accept.js');
/**
 * Partner Solution ID for sandbox.
 */
define('ANET_SANDBOX_SOLUTION_ID', 'AAA198607');
/**
 * Partner Solution ID for production.
 */
define('ANET_PRODUCTION_SOLUTION_ID', 'AAA201052');
/**
 *
 * Credit Card gateway id.
 */
define('ANET_CREDIT_CARD_GATEWAY_ID', 'anet');
/**
 *
 * Echeck gateway id.
 */
define('ANET_ECHECK_GATEWAY_ID', 'anet_echeck');
/**
 *
 * Helper Credit card.
 */
define('ANET_PAYMENT_TYPE_CREDIT_CARD', 'creditcard');
/**
 *
 * Helper Echeck.
 */
define('ANET_PAYMENT_TYPE_ECHECK', 'echeck');
/**
 *
 * WooCommerce Order Status after Settlement.
 */
define('ANET_WOOCOMMERCE_ORDER_STATUS_PROCESSING', 'processing');
/**
 *
 * WooCommerce Order Status after Authorization.
 */
define('ANET_WOOCOMMERCE_ORDER_STATUS_ON_HOLD', 'on-hold');
/**
 *
 * WooCommerce Order Status after Auth Reversal.
 */
define('ANET_WOOCOMMERCE_ORDER_STATUS_CANCELLED', 'cancelled');
/**
 *
 * WooCommerce Order Status after Refund.
 */
define('ANET_WOOCOMMERCE_ORDER_STATUS_REFUNDED', 'refunded');
/**
 *
 * WooCommerce Order Status after Error.
 */
define('ANET_WOOCOMMERCE_ORDER_STATUS_FAILED', 'failed');
/**
 *
 * WooCommerce Default Order Status.
 */
define('ANET_WOOCOMMERCE_ORDER_STATUS_PENDING', 'pending');
/**
 *
 * WooCommerce Default Order Status Pending Payment.
 */
define('ANET_WOOCOMMERCE_ORDER_STATUS_PENDING_PAYMENT', 'pending_payment');
/**
 *
 * WooCommerce Completed Order Status.
 */
define('ANET_WOOCOMMERCE_ORDER_STATUS_COMPLETED', 'completed');
/**
 *
 * Sandbox Fraud Detection Suite Status.
 */
define('ANET_SANDBOX_STATUS_FDS', 'FDSPendingReview');
/**
 *
 * Sandbox Authorized Status.
 */
define('ANET_SANDBOX_STATUS_AUTHORIZED', 'Ok');
/**
 *
 * WooCommerce Domain.
 */
define('ANET_WOOCOMMERCE', 'woocommerce');
/**
 *
 * Used to set the cron job minutes.
 */
define('ANET_CRON_JOB_TIME', 15);
/**
 *
 * Used to set the priority parameter for add_action() method.
 */
define('ANET_ACTION_HOOK_DEFAULT_PRIORITY', 10);
/**
 * Integer value constant.
 *
 */
define('ANET_VAL_ZERO', 0);
/**
 * Integer value constant.
 *
 */
define('ANET_VAL_ONE', 1);
/**
 * Integer value constant.
 *
 */
define('ANET_VAL_TWO', 2);
/**
 * Integer value constant.
 *
 */
define('ANET_VAL_THREE', 3);
/**
 * Integer value constant.
 *
 */
define('ANET_VAL_TWENTY', 20);
/**
 * Integer value constant.
 *
 */
define('ANET_VAL_FOUR', 4);
/**
 * Integer value constant.
 *
 */
define('ANET_VAL_NINE', 9);
/**
 * Integer saving card checkbox value constant.
 *
 */
define('ANET_SAVING_CARD_VAL_ONE', '1');
/**
 *
 * YES Constant.
 */
define('ANET_YES', 'yes');
/**
 *
 * No Constant.
 */
define('ANET_NO', 'no');
/**
 *
 * Space constant.
 */
define('ANET_SPACE', ' ');
/**
 *
 * Hyphen constant.
 */
define('ANET_HYPHEN', '-');
/**
 *
 * Underscore constant.
 */
define('ANET_UNDERSCORE', '_');
/**
 *
 * Slash constant.
 */
define('ANET_SLASH', '/');
/**
 *
 * Colon slash constant.
 */
define('ANET_COLON_SLASH', '://');
/**
 *
 * Colon constant.
 */
define('ANET_COLON', ':');
/**
 *
 * Greater than or equal to constant.
 */
define('ANET_GREATER_THAN_EQUAL_TO', '>=');
/**
 *
 * Greater than or equal to constant.
 */
define('ANET_LESSER_THAN_EQUAL_TO', '<=');
/**
 *
 * WooCommerce MyAccount Payment method endpoint.
 */
define('ANET_PAYMENT_METHODS', 'payment-methods');
/**
 *
 * WooCommerce MyAccount Payment method endpoint.
 */
define('ANET_ADD_PAYMENT_METHODS', 'add-payment-method');
/**
 *
 * String.
 */
define('ANET_STRING_ERROR', 'error');
/**
 *
 * Authorize transaction type.
 */
define('ANET_TRANSACTION_TYPE_AUTHORIZE', 'authOnlyTransaction');
/**
 *
 * Charge transaction type.
 */
define('ANET_TRANSACTION_TYPE_AUTH_CAPTURE', 'authCaptureTransaction');
/**
 *
 * Capture transaction type.
 */
define('ANET_TRANSACTION_TYPE_CAPTURE', 'priorAuthCaptureTransaction');
/**
 *
 * Refund transaction type.
 */
define('ANET_TRANSACTION_TYPE_REFUND', 'refundTransaction');
/**
 *
 * Void transaction type.
 */
define('ANET_TRANSACTION_TYPE_VOID', 'voidTransaction');
/**
 *
 * String.
 */
define('ANET_ASTRA_THEME', 'Astra');
/**
 * Undefined value constant.
 *
 */
define('ANET_VAL_UNDEFINED', 'undefined');
/**
 * Subscription plugin version.
 */
define('ANET_SUBSCRIPTION_VERSION', '2.2.0');
/**
 * Echeck Account Type Checking.
 */
define('ANET_ECHECK_ACCOUNT_TYPE_CHECKING', 'checking');
/**
 * Echeck Account Type Savings
 */
define('ANET_ECHECK_ACCOUNT_TYPE_SAVINGS', 'savings');
/**
 * Source Type Opaque Data.
 */
define('ANET_SOURCE_TYPE_OPAQUE_DATA', 'opaque_data');
/**
 * Source Type Stored Token.
 */
define('ANET_SOURCE_TYPE_STORED_TOKEN', 'stored_token');
/**
 * WooCommerce Underscore String Constant.
 */
define('ANET_WOOCOMMERCE_UNDERSCORE', 'woocommerce_');
/**
 * Settings Underscore String Constant.
 */
define('ANET_UNDERSCORE_SETTINGS', '_settings');
/**
 *
 * Registers the activation hook for our plugin.
 */
register_activation_hook(__FILE__, 'anet_activate');
/**
 *
 * Registers the deactivation hook for our plugin.
 */
register_deactivation_hook(__FILE__, 'anet_deactivate');
/**
 * The code that runs during plugin activation.
 * This action is documented in includes/class-anet-activator.php
 */
function anet_activate()
{
    require_once plugin_dir_path(__FILE__) . 'includes/class-anet-activator.php';
    Anet_Activator::activate();
}
/**
 * The code that runs during plugin deactivation.
 * This action is documented in includes/class-anet-deactivator.php
 */
function anet_deactivate()
{
    require_once plugin_dir_path(__FILE__) . 'includes/class-anet-deactivator.php';
    Anet_Deactivator::deactivate();
}
/**
 * Hpos compatibility.
 *
 * @return boolean
 */
function anet_hpos_compatibility()
{
    if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
            'custom_order_tables',
            __FILE__,
            true
        );
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
            'cart_checkout_blocks',
            __FILE__,
            true
        );
    }
}
/**
 * Handles hpos compatibility.
 *
 * @return boolean
 */
function anet_handle_hpos_compatibility()
{
    $status = false;
    if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
        if (class_exists(\Automattic\WooCommerce\Utilities\OrderUtil::class)) {
            if (\Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled()) {
                $status = true;
            }
        }
    }
    return $status;
}
class Anet_Payments_For_Woocommerce
{
    public function __construct()
    {
        $loader = new Anet_Loader();
        add_action('plugins_loaded', array($this, 'init'));
        add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($loader, 'plugin_action_links'), 11);
        add_filter('woocommerce_payment_gateways', array($this, 'add_gateways'));
        add_action('woocommerce_blocks_loaded', array($this, 'anet_block_support_for_gateway'));
        add_action('before_woocommerce_init', 'anet_hpos_compatibility');
    }
    public function wp_kama_woocommerce_pre_delete_object_type_filter($check, $token)
    {
        // woocommerce_pre_delete_data fires for ALL WC data objects (coupons, orders, webhooks, etc.), not just payment tokens.
        // Bail early if this isn't a WC_Payment_Token to avoid a fatal on get_gateway_id().
        if (! ($token instanceof \WC_Payment_Token)) {
            return $check;
        }
        if (ANET_CREDIT_CARD_GATEWAY_ID === $token->get_gateway_id() || ANET_ECHECK_GATEWAY_ID === $token->get_gateway_id()) {
            $core_tokens = \WC_Payment_Tokens::get_customer_tokens($token->get_user_id(), $token->get_gateway_id());
            $is_delete    = $token->is_default() && ANET_VAL_ONE < count($core_tokens);
            if ($is_delete) {
                wc_add_notice(esc_html__('Please set another card to default and try deleting the card again.', 'authorize-net-payments-for-woocommerce'), ANET_STRING_ERROR);
                wp_safe_redirect(wc_get_account_endpoint_url(ANET_PAYMENT_METHODS));
                exit();
            }
            $response = self::delete_token($token->get_id(), $token);
            if ($response) {
                return null;
            } else {
                wc_add_notice(esc_html__('Card deletion failed. Please try again.', 'authorize-net-payments-for-woocommerce'), ANET_STRING_ERROR);
                wp_safe_redirect(wc_get_account_endpoint_url(ANET_PAYMENT_METHODS));
                exit();
            }
        } else {
            return $check;
        }
    }
    public function delete_token($token_id, $token)
    {
        $response = false;
        $gateway_id = $token->get_gateway_id();
        $user_id = $token->get_user_id();
        $token_info = $token->get_meta('token_information');
        if (!empty($token_info['customer_profile_id']) && !empty($token_info['payment_profile_id'])) {
            if (ANET_CREDIT_CARD_GATEWAY_ID === $gateway_id) {
                $tokenize = new Anet_Credit_Card_Tokenization();
                $response = $tokenize->delete_profile(
                    $user_id,
                    $token_info['customer_profile_id'],
                    $token_info['payment_profile_id']
                );
            } elseif (ANET_ECHECK_GATEWAY_ID === $gateway_id) {
                $tokenize = new Anet_ECheck_Tokenization();
                $response = $tokenize->delete_profile(
                    $user_id,
                    $token_info['customer_profile_id'],
                    $token_info['payment_profile_id']
                );
            }
        }
        return $response;
    }
    public function is_wc_subscriptions_activated()
    {
        return class_exists('WC_Subscriptions') && class_exists('WC_Subscription') && version_compare(WC_Subscriptions::$version, ANET_SUBSCRIPTION_VERSION, ANET_GREATER_THAN_EQUAL_TO);
    }
    public function init_gateways()
    {
        require_once(plugin_dir_path(__FILE__) . '/includes/gateway/class-anet-credit-card-gateway.php');
        require_once(plugin_dir_path(__FILE__) . '/includes/gateway/class-anet-echeck-gateway.php');
        require_once plugin_dir_path(__FILE__) . '/includes/class-anet-subscriptions.php';
        if (! class_exists('WC_Payment_Gateway')) {
            return;
        }
        add_action('woocommerce_init', function () {
            if (class_exists('Anet_Credit_Card_Gateway')) {
                $anet_gateway = new Anet_Credit_Card_Gateway();
                $anet_gateway->define_hooks(); // Register hooks separately.
            }
        });
        add_action('woocommerce_init', function () {
            if (class_exists('Anet_ECheck_Gateway')) {
                $anet_gateway_echeck = new Anet_ECheck_Gateway();
                $anet_gateway_echeck->define_hooks(); // Register hooks separately.
            }
        });
        $subscriptions = new Anet_Subscriptions();
        if ($this->is_wc_subscriptions_activated()) {
            $subscriptions->add_subscription_actions();
        }
    }
    public function init()
    {
        if (! class_exists('Anet_Credit_Card_Api')) {
            require_once(dirname(__FILE__) . '/includes/api/payments/class-anet-credit-card-api.php');
        }
        if (! class_exists('Anet_ECheck_Api')) {
            require_once(dirname(__FILE__) . '/includes/api/payments/class-anet-echeck-api.php');
        }
        // Init the gateway itself.
        $this->init_gateways();
        // required files.
        require_once(dirname(__FILE__) . '/includes/class-anet-logger.php');
        require_once(dirname(__FILE__) . '/vendor/autoload.php');
        require_once(dirname(__FILE__) . '/includes/api/payments/class-anet-credit-card-api.php');
        require_once(dirname(__FILE__) . '/includes/api/payments/class-anet-echeck-api.php');
        require_once(dirname(__FILE__) . '/includes/helper/class-anet-setting-helper.php');
        require_once(dirname(__FILE__) . '/includes/helper/class-anet-api-helper.php');
        $anet_wc_version = defined('WC_VERSION') ? WC_VERSION : null;
        if (version_compare($anet_wc_version, "8.1.0", ANET_GREATER_THAN_EQUAL_TO)) {
            add_filter('woocommerce_pre_delete_data', array($this, 'wp_kama_woocommerce_pre_delete_object_type_filter'), ANET_ACTION_HOOK_DEFAULT_PRIORITY, ANET_VAL_THREE);
        } else {
            add_action('woocommerce_payment_token_deleted', function ($id, $token) {
                $token = $token->get_token();
            }, ANET_ACTION_HOOK_DEFAULT_PRIORITY, ANET_VAL_TWO);
        }
        if (!class_exists('Anet_Capture')) {
            include_once(dirname(__FILE__) . '/includes/admin/class-anet-capture.php');
        }
        $anet_capture = new Anet_Capture();
        $anet_capture->add_capture_button_to_admin_page();
        if (!class_exists('Anet_Refund_Void_Api')) {
            require_once(plugin_dir_path(__FILE__) . '/includes/api/payments/class-anet-refund-void-api.php');
        }
    }
    /**
     * Add the gateways to WooCommerce.
     *
     */
    public function add_gateways($methods)
    {
        $methods = array_merge($methods, ['Anet_Credit_Card_Gateway', 'Anet_ECheck_Gateway']);
        return $methods;
    }
    /**
     * Woocommerce block support for the gateway.
     *
     * @return void
     */
    public function anet_block_support_for_gateway()
    {
        if (class_exists('Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType')) {
            require_once plugin_dir_path(__FILE__) . 'includes/class-anet-credit-card-block.php';
            require_once plugin_dir_path(__FILE__) . 'includes/class-anet-echeck-block.php'; // Include the eCheck block class.
            add_action(
                'woocommerce_blocks_payment_method_type_registration',
                function (Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry $payment_method_registry) {
                    $payment_method_registry->register(new Anet_Credit_Card_Block());
                    $payment_method_registry->register(new Anet_ECheck_Block()); // Register the eCheck block.
                }
            );
        }
    }
}
// Initialize the plugin.
global $anet_gateway;
$anet_gateway = new Anet_Payments_For_Woocommerce();
