/** * Adds support for subscriptions by hooking in some necessary actions * * @since 4.1.0 */ public function add_support() { $this->get_gateway()->add_support(array('subscriptions', 'subscription_suspension', 'subscription_cancellation', 'subscription_reactivation', 'subscription_amount_changes', 'subscription_date_changes', 'multiple_subscriptions', 'subscription_payment_method_change_customer', 'subscription_payment_method_change_admin')); // 2.0.x hooks if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { // force tokenization when needed add_filter('wc_payment_gateway_' . $this->get_gateway()->get_id() . '_tokenization_forced', array($this, 'maybe_force_tokenization')); // save token/customer ID to subscription objects add_action('wc_payment_gateway_' . $this->get_gateway()->get_id() . '_add_transaction_data', array($this, 'save_payment_meta'), 10, 2); // process renewal payments add_action('woocommerce_scheduled_subscription_payment_' . $this->get_gateway()->get_id(), array($this, 'process_renewal_payment'), 10, 2); // update the customer/token ID on the subscription when updating a previously failing payment method add_action('woocommerce_subscription_failing_payment_method_updated_' . $this->get_gateway()->get_id(), array($this, 'update_failing_payment_method'), 10, 2); // display the current payment method used for a subscription in the "My Subscriptions" table add_filter('woocommerce_my_subscriptions_payment_method', array($this, 'maybe_render_payment_method'), 10, 3); // don't copy over order-specific meta to the WC_Subscription object during renewal processing add_filter('wcs_renewal_order_meta', array($this, 'do_not_copy_order_meta')); // remove order-specific meta from the Subscription object after the change payment method action add_filter('woocommerce_subscriptions_process_payment_for_change_method_via_pay_shortcode', array($this, 'remove_order_meta_from_change_payment'), 10, 2); // don't copy over order-specific meta to the new WC_Subscription object during upgrade to 2.0.x add_filter('wcs_upgrade_subscription_meta_to_copy', array($this, 'do_not_copy_order_meta_during_upgrade')); // allow concrete gateways to define additional order-specific meta keys to exclude if (is_callable(array($this->get_gateway(), 'subscriptions_get_excluded_order_meta_keys'))) { add_filter('wc_payment_gateway_' . $this->get_gateway()->get_id() . '_subscriptions_order_specific_meta_keys', array($this->get_gateway(), 'subscriptions_get_excluded_order_meta_keys')); } /* My Payment Methods */ add_filter('wc_' . $this->get_gateway()->get_plugin()->get_id() . '_my_payment_methods_table_headers', array($this, 'add_my_payment_methods_table_header'), 10, 2); add_filter('wc_' . $this->get_gateway()->get_plugin()->get_id() . '_my_payment_methods_table_body_row_data', array($this, 'add_my_payment_methods_table_body_row_data'), 10, 3); add_filter('wc_' . $this->get_gateway()->get_plugin()->get_id() . '_my_payment_methods_table_method_actions', array($this, 'disable_my_payment_methods_table_method_delete'), 10, 3); /* Admin Change Payment Method support */ // framework defaults - payment_token and customer_id add_filter('woocommerce_subscription_payment_meta', array($this, 'admin_add_payment_meta'), 9, 2); add_action('woocommerce_subscription_validate_payment_meta_' . $this->get_gateway()->get_id(), array($this, 'admin_validate_payment_meta'), 9); // allow concrete gateways to add/change defaults if (is_callable(array($this->get_gateway(), 'subscriptions_admin_add_payment_meta'))) { add_filter('woocommerce_subscription_payment_meta', array($this->get_gateway(), 'subscriptions_admin_add_payment_meta'), 10, 2); } // allow concrete gateways to perform additional validation if (is_callable(array($this->get_gateway(), 'subscriptions_admin_validate_payment_meta'))) { add_action('woocommerce_subscription_validate_payment_meta_' . $this->get_gateway()->get_id(), array($this->get_gateway(), 'subscriptions_admin_validate_payment_meta'), 10); } } else { // 1.5.x $this->add_support_1_5(); } }
/** * Process subscription renewal * * @since 1.4 * @param float $amount_to_charge subscription amount to charge, could include * multiple renewals if they've previously failed and the admin * has enabled it * @param WC_Order $order original order containing the subscription * @param int $product_id the ID of the subscription product */ public function process_renewal_payment($amount_to_charge, $order, $product_id = null) { require_once 'class-wc-realex-api.php'; $realex_subscription_count = 0; if (is_numeric($order->realex_subscription_count) && $order->realex_subscription_count) { $realex_subscription_count = $order->realex_subscription_count; } // increment the subscription count so we don't get order number clashes $realex_subscription_count++; update_post_meta($order->id, '_realex_subscription_count', $realex_subscription_count); // set custom class member used by the realex gateway $order->payment_total = SV_WC_Helper::number_format($amount_to_charge); // zero-dollar subscription renewal. weird, but apparently it happens -- only applicable to Subs 1.5.x if (!SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { if (0 == $order->payment_total) { // add order note $order->add_order_note(sprintf(__('%s0 Subscription Renewal Approved', 'woocommerce-gateway-realex'), get_woocommerce_currency_symbol())); // update subscription WC_Subscriptions_Manager::process_subscription_payments_on_order($order, $product_id); return; } } // This order is missing a tokenized card, lets see whether there's one available for the customer if (!get_post_meta($order->id, '_realex_cardref', true)) { $credit_cards = get_user_meta($order->get_user_id(), 'woocommerce_realex_cc', true); if (is_array($credit_cards)) { $card_ref = (object) current($credit_cards); $card_ref = $card_ref->ref; update_post_meta($order->id, '_realex_cardref', $card_ref); if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { foreach (wcs_get_subscriptions_for_renewal_order($order) as $subscription) { update_post_meta($subscription->id, '_realex_cardref', $card_ref); } } } } // create the realex api client $realex_client = new Realex_API($this->get_endpoint_url(), $this->get_realvault_endpoint_url(), $this->get_shared_secret()); // create the customer/cc tokens, and authorize the initial payment amount, if any $response = $this->authorize($realex_client, $order); if ($response && '00' == $response->result) { // add order note $order->add_order_note(sprintf(__('Credit Card Subscription Renewal Payment Approved (Payment Reference: %s) ', 'woocommerce-gateway-realex'), $response->pasref)); // update subscription if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { $order->payment_complete((string) $response->pasref); } else { WC_Subscriptions_Manager::process_subscription_payments_on_order($order, $product_id); } } else { // generate the result message $message = __('Credit Card Subscription Renewal Payment Failed', 'woocommerce-gateway-realex'); /* translators: Placeholders: %1$s - result, %2$s - result message */ if ($response) { $message .= sprintf(__(' (Result: %1$s - "%2$s").', 'woocommerce-gateway-realex'), $response->result, $response->message); } $order->add_order_note($message); // update subscription if (!SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { WC_Subscriptions_Manager::process_subscription_payment_failure_on_order($order, $product_id); } } }
/** * Setup main plugin class * * @since 3.0 * @see SV_WC_Plugin::__construct() */ public function __construct() { parent::__construct(self::PLUGIN_ID, self::VERSION, self::TEXT_DOMAIN); // load includes after WC is loaded add_action('sv_wc_framework_plugins_loaded', array($this, 'includes'), 11); // Subscriptions support if ($this->is_plugin_active('woocommerce-subscriptions.php')) { if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { // don't copy over FreshBooks invoice meta from the original order to the subscription (subscription objects should not have an invoice) add_filter('wcs_subscription_meta', array($this, 'subscriptions_remove_subscription_order_meta'), 10, 3); // don't copy over FreshBooks invoice meta to subscription object during upgrade from 1.5.x to 2.0 add_filter('wcs_upgrade_subscription_meta_to_copy', array($this, 'subscriptions_remove_subscription_order_meta_during_upgrade')); // don't copy over FreshBooks invoice meta from the subscription to the renewal order add_filter('wcs_renewal_order_meta', array($this, 'subscriptions_remove_renewal_order_meta')); } else { // remove the invoice data from new renewal orders for subscription renewals so a new invoice is created for each renewal order add_filter('woocommerce_subscriptions_renewal_order_meta_query', array($this, 'subscriptions_remove_renewal_order_meta_1_5'), 10, 4); } } // maybe disable API logging if ('on' !== get_option('wc_freshbooks_debug_mode')) { remove_action('wc_' . $this->get_id() . '_api_request_performed', array($this, 'log_api_request'), 10); } }
/** * Process bulk export * * Note this is hooked into `admin_init` as WC 2.1+ interferes with sending headers() from a sub-menu page * * @since 3.0 */ public function process_export() { if (!isset($_POST['wc_customer_order_csv_export_bulk_export']) || !isset($_POST['wc_customer_order_csv_export_type'])) { return; } // security check if (!wp_verify_nonce($_POST['_wpnonce'], __FILE__)) { wp_die(__('Action failed. Please refresh the page and retry.', 'woocommerce-customer-order-csv-export')); } $export_type = $_POST['wc_customer_order_csv_export_type']; $query_args = array('fields' => 'ids', 'post_type' => 'shop_order', 'post_status' => !empty($_POST['wc_customer_order_csv_export_statuses']) && 'orders' == $export_type ? $_POST['wc_customer_order_csv_export_statuses'] : 'any', 'posts_per_page' => empty($_POST['wc_customer_order_csv_export_limit']) ? -1 : absint($_POST['wc_customer_order_csv_export_limit']), 'offset' => empty($_POST['wc_customer_order_csv_export_offset']) ? 0 : absint($_POST['wc_customer_order_csv_export_offset']), 'date_query' => array(array('before' => empty($_POST['wc_customer_order_csv_export_end_date']) ? date('Y-m-d 23:59', current_time('timestamp')) : $_POST['wc_customer_order_csv_export_end_date'] . ' 23:59:59.99', 'after' => empty($_POST['wc_customer_order_csv_export_start_date']) ? date('Y-m-d 00:00', 0) : $_POST['wc_customer_order_csv_export_start_date'], 'inclusive' => true))); // allow offset to be used with "no" posts limit if ($query_args['offset'] > 0 && -1 === $query_args['posts_per_page']) { $query_args['posts_per_page'] = 999999999999.0; // a really large number {@link http://dev.mysql.com/doc/refman/5.7/en/select.html#idm140195560794688} } // set start/end date for customer exports as class variables which are used when performing get_users() in the CSV generator if ('customers' == $export_type) { $this->customer_export_start_date = str_replace(' 00:00', '', $query_args['date_query'][0]['after']); $this->customer_export_end_date = str_replace(' 23:59', '', $query_args['date_query'][0]['before']); } /** * Allow actors to change the WP_Query args used for selecting orders to export in the admin. * * @since 3.0.6 * @param array $query_args - WP_Query arguments * @param string $export_type - either `customers` or `orders` * @param \WC_Customer_Order_CSV_Export_Admin $this class instance */ $query_args = apply_filters('wc_customer_order_csv_export_admin_query_args', $query_args, $export_type, $this); // get order IDs $query = new WP_Query($query_args); $order_ids = $query->posts; // handle subscription & renewal order filtering if (wc_customer_order_csv_export()->is_plugin_active('woocommerce-subscriptions.php')) { $subscriptions = $renewals = array(); if (isset($_POST['wc_customer_order_csv_export_subscription_orders'])) { if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { $subscriptions = array_filter($order_ids, 'wcs_order_contains_subscription'); } else { $subscriptions = array_filter($order_ids, array('WC_Subscriptions_Order', 'order_contains_subscription')); } } if (isset($_POST['wc_customer_order_csv_export_subscription_renewals'])) { if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { $renewals = array_filter($order_ids, 'wcs_order_contains_renewal'); } else { $renewals = array_filter($order_ids, array('WC_Subscriptions_Renewal_Order', 'is_renewal')); } } if (!empty($subscriptions) || !empty($renewals)) { $order_ids = array_merge($subscriptions, $renewals); } } if (count($order_ids)) { $export = new WC_Customer_Order_CSV_Export_Handler($order_ids, $export_type); $export->download(); } else { $this->message_handler->add_message(sprintf(__('No %s found to export', 'woocommerce-customer-order-csv-export'), $export_type)); } }
/** * Setup main plugin class * * @since 3.0 * @return \WC_Customer_Order_CSV_Export */ public function __construct() { parent::__construct(self::PLUGIN_ID, self::VERSION); // required files $this->includes(); // Set orders as not-exported when created add_action('wp_insert_post', array($this, 'mark_order_not_exported'), 10, 2); // Admin if (is_admin()) { // handle single order CSV export download from order action button add_action('wp_ajax_wc_customer_order_csv_export_export_order', array($this, 'process_ajax_export_order')); if (!is_ajax()) { $this->admin_includes(); } } // Subscriptions support if ($this->is_plugin_active('woocommerce-subscriptions.php')) { if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) { // Prevent that new subscription renewal orders from being automatically marked as 'exported' add_filter('wcs_subscription_meta', array($this, 'subscriptions_remove_subscription_order_meta'), 10, 3); add_filter('wcs_upgrade_subscription_meta_to_copy', array($this, 'subscriptions_remove_subscription_order_meta_during_upgrade')); add_filter('wcs_renewal_order_meta', array($this, 'subscriptions_remove_renewal_order_meta')); } } // clear scheduled events on deactivation register_deactivation_hook($this->get_file(), array($this->get_cron_instance(), 'clear_scheduled_export')); }