/**
  * When a new order is inserted, add the subscriptions period to the order. 
  * 
  * It's important that the period is tied to the order so that changing the products
  * period does not change the past. 
  *
  * @since 1.0
  */
 public static function add_order_meta($order_id)
 {
     global $woocommerce;
     if (WC_Subscriptions_Order::order_contains_subscription($order_id)) {
         $order = new WC_Order($order_id);
         $order_subscription_periods = array();
         $order_subscription_intervals = array();
         $order_subscription_lengths = array();
         $order_subscription_trial_lengths = array();
         foreach ($order->get_items() as $item) {
             $period = WC_Subscriptions_Product::get_period($item['id']);
             if (!empty($period)) {
                 $order_subscription_periods[$item['id']] = $period;
             }
             $interval = WC_Subscriptions_Product::get_interval($item['id']);
             if (!empty($interval)) {
                 $order_subscription_intervals[$item['id']] = $interval;
             }
             $length = WC_Subscriptions_Product::get_length($item['id']);
             if (!empty($length)) {
                 $order_subscription_lengths[$item['id']] = $length;
             }
             $trial_length = WC_Subscriptions_Product::get_trial_length($item['id']);
             if (!empty($trial_length)) {
                 $order_subscription_trial_lengths[$item['id']] = $trial_length;
             }
         }
         update_post_meta($order_id, '_order_subscription_periods', $order_subscription_periods);
         update_post_meta($order_id, '_order_subscription_intervals', $order_subscription_intervals);
         update_post_meta($order_id, '_order_subscription_lengths', $order_subscription_lengths);
         update_post_meta($order_id, '_order_subscription_trial_lengths', $order_subscription_trial_lengths);
         // Store sign-up fee details
         foreach (WC_Subscriptions_Cart::get_sign_up_fee_fields() as $field_name) {
             update_post_meta($order_id, "_{$field_name}", $woocommerce->cart->{$field_name});
         }
         // Prepare sign up fee taxes to store in same format as order taxes
         $sign_up_fee_taxes = array();
         foreach (array_keys($woocommerce->cart->sign_up_fee_taxes) as $key) {
             $is_compound = $woocommerce->cart->tax->is_compound($key) ? 1 : 0;
             $sign_up_fee_taxes[] = array('label' => $woocommerce->cart->tax->get_rate_label($key), 'compound' => $is_compound, 'cart_tax' => number_format($woocommerce->cart->sign_up_fee_taxes[$key], 2, '.', ''));
         }
         update_post_meta($order_id, '_sign_up_fee_taxes', $sign_up_fee_taxes);
     }
 }
 /**
  * Removes a couple of notifications that are less relevant for Subscription orders.
  * 
  * @since 1.0
  */
 public static function maybe_remove_customer_processing_order($order_id)
 {
     if (WC_Subscriptions_Order::order_contains_subscription($order_id)) {
         remove_action('woocommerce_order_status_pending_to_processing_notification', array(self::$woocommerce_email, 'customer_processing_order'));
         remove_action('woocommerce_order_status_pending_to_on-hold_notification', array(self::$woocommerce_email, 'customer_processing_order'));
     }
 }
 /**
  * When a new order is inserted, add the subscriptions period to the order. 
  * 
  * It's important that the period is tied to the order so that changing the products
  * period does not change the past. 
  *
  * @since 1.0
  */
 public static function add_order_meta($order_id, $posted)
 {
     global $woocommerce;
     if (WC_Subscriptions_Order::order_contains_subscription($order_id)) {
         // This works because the 'new_order_item' runs before the 'woocommerce_checkout_update_order_meta' hook
         // Set the recurring totals so totals display correctly on order page
         update_post_meta($order_id, '_order_recurring_discount_cart', WC_Subscriptions_Cart::get_recurring_discount_cart());
         update_post_meta($order_id, '_order_recurring_discount_total', WC_Subscriptions_Cart::get_recurring_discount_total());
         update_post_meta($order_id, '_order_recurring_shipping_tax_total', WC_Subscriptions_Cart::get_recurring_shipping_tax_total());
         update_post_meta($order_id, '_order_recurring_tax_total', WC_Subscriptions_Cart::get_recurring_total_tax());
         update_post_meta($order_id, '_order_recurring_total', WC_Subscriptions_Cart::get_recurring_total());
         // Get recurring taxes into same format as _order_taxes
         $order_recurring_taxes = array();
         foreach (WC_Subscriptions_Cart::get_recurring_taxes() as $tax_key => $tax_amount) {
             $is_compound = $woocommerce->cart->tax->is_compound($tax_key) ? 1 : 0;
             if (isset($woocommerce->cart->taxes[$tax_key])) {
                 $cart_tax = $tax_amount;
                 $shipping_tax = 0;
             } else {
                 $cart_tax = 0;
                 $shipping_tax = $tax_amount;
             }
             $order_recurring_taxes[] = array('label' => $woocommerce->cart->tax->get_rate_label($tax_key), 'compound' => $is_compound, 'cart_tax' => woocommerce_format_total($cart_tax), 'shipping_tax' => woocommerce_format_total($shipping_tax));
         }
         update_post_meta($order_id, '_order_recurring_taxes', $order_recurring_taxes);
         $payment_gateways = $woocommerce->payment_gateways->payment_gateways();
         if (!$payment_gateways[$posted['payment_method']]->supports('subscriptions')) {
             update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true');
         }
     }
 }
 /**
  * Process the payment
  */
 function process_payment($order_id)
 {
     global $woocommerce;
     if (class_exists('WC_Subscriptions_Order') && WC_Subscriptions_Order::order_contains_subscription($order_id)) {
         $order = new WC_Order($order_id);
         $stripe_token = isset($_POST['stripe_token']) ? woocommerce_clean($_POST['stripe_token']) : '';
         // Use Stripe CURL API for payment
         try {
             $post_data = array();
             $customer_id = 0;
             // Check if paying via customer ID
             if (isset($_POST['stripe_customer_id']) && $_POST['stripe_customer_id'] !== 'new' && is_user_logged_in()) {
                 $customer_ids = get_user_meta(get_current_user_id(), '_stripe_customer_id', false);
                 if (isset($customer_ids[$_POST['stripe_customer_id']]['customer_id'])) {
                     $customer_id = $customer_ids[$_POST['stripe_customer_id']]['customer_id'];
                 } else {
                     throw new Exception(__('Invalid card.', 'wc_stripe'));
                 }
             } elseif (empty($stripe_token)) {
                 throw new Exception(__('Please make sure your card details have been entered correctly and that your browser supports JavaScript.', 'wc_stripe'));
             }
             if (method_exists('WC_Subscriptions_Order', 'get_total_initial_payment')) {
                 $initial_payment = WC_Subscriptions_Order::get_total_initial_payment($order);
             } else {
                 $initial_payment = WC_Subscriptions_Order::get_sign_up_fee($order) + WC_Subscriptions_Order::get_price_per_period($order);
             }
             $customer_response = $this->add_customer_to_order($order, $customer_id, $stripe_token);
             if ($initial_payment > 0) {
                 $payment_response = $this->process_subscription_payment($order, $initial_payment);
             }
             if (is_wp_error($customer_response)) {
                 throw new Exception($customer_response->get_error_message());
             } else {
                 if (isset($payment_response) && is_wp_error($payment_response)) {
                     throw new Exception($payment_response->get_error_message());
                 } else {
                     // Payment complete
                     $order->payment_complete();
                     // Remove cart
                     $woocommerce->cart->empty_cart();
                     // Activate subscriptions
                     WC_Subscriptions_Manager::activate_subscriptions_for_order($order);
                     // Store token
                     if ($stripe_token) {
                         update_post_meta($order->id, '_stripe_token', $stripe_token);
                     }
                     // Return thank you page redirect
                     return array('result' => 'success', 'redirect' => $this->get_return_url($order));
                 }
             }
         } catch (Exception $e) {
             $woocommerce->add_error(__('Error:', 'wc_stripe') . ' "' . $e->getMessage() . '"');
             return;
         }
     } else {
         return parent::process_payment($order_id);
     }
 }
Esempio n. 5
0
/**
 * Get the string key for a subscription used in Subscriptions prior to 2.0.
 *
 * Previously, a subscription key was made up of the ID of the order used to purchase the subscription, and
 * the product to which the subscription relates; however, in Subscriptions 2.0, subscriptions can actually
 * relate to multiple products (because they can contain multiple line items) and they also no longer need
 * to have an original order associated with them, to make manually adding subscriptions more accurate.
 *
 * Therefore, although the return value of this method is a string matching the key form used  inSubscriptions
 * prior to 2.0, the actual value represented is not a perfect analogue. Specifically,
 *  - if the subscription contains more than one product, only the ID of the first line item will be used in the ID
 *  - if the subscription does not contain any products, the key still be missing that component of the
 *  - if the subscription does not have an initial order, then the order ID used will be the WC_Subscription object's ID
 *
 * @param WC_Subscription $subscription An instance of WC_Subscription
 * @return string $subscription_key A subscription key in the deprecated form previously created by @see self::get_subscription_key()
 * @since 2.0
 */
function wcs_get_old_subscription_key(WC_Subscription $subscription)
{
    // Get an ID to use as the order ID
    $order_id = isset($subscription->order->id) ? $subscription->order->id : $subscription->id;
    // Get an ID to use as the product ID
    $subscription_items = $subscription->get_items();
    $first_item = reset($subscription_items);
    return $order_id . '_' . WC_Subscriptions_Order::get_items_product_id($first_item);
}
 /**
  * Process the payment
  *
  * @param  int $order_id
  * @return array
  */
 public function process_payment($order_id, $retry = true)
 {
     // Processing subscription
     if (class_exists('WC_Subscriptions_Order') && WC_Subscriptions_Order::order_contains_subscription($order_id)) {
         return $this->process_subscription($order_id, $retry);
         // Processing pre-order or standard ordre
     } else {
         return parent::process_payment($order_id, $retry);
     }
 }
 /**
  * For versions of WooCommerce prior to the existence of the woocommerce_available_gateways, 
  * hide available gateways with JavaScript.
  * 
  * @since 1.0
  */
 public static function gateway_scheduled_subscription_payment($user_id, $subscription_key)
 {
     $subscription = WC_Subscriptions_Manager::get_users_subscription($user_id, $subscription_key);
     $order = new WC_Order($subscription['order_id']);
     $amount_to_charge = WC_Subscriptions_Order::get_price_per_period($order, $subscription['product_id']);
     $outstanding_payments = WC_Subscriptions_Order::get_outstanding_balance($order, $subscription['product_id']);
     if ($outstanding_payments > 0) {
         $amount_to_charge += $outstanding_payments;
     }
     do_action('scheduled_subscription_payment_' . $order->payment_method, $amount_to_charge, $order, $subscription['product_id']);
 }
 /**
  * Change the status of a subscription and show a notice to the
  * user to say when the next payment will now be made on.
  *
  * @since  1.0.0
  * @access public
  * @static
  * @param  $subscription
  * @param  $order_id
  * @param  $product_id
  * @uses   WC_Subscriptions::add_notice
  */
 public static function change_users_subscription($subscription, $order_id, $product_id)
 {
     $subscription = !is_object($subscription) ? wcs_get_subscription($subscription) : $subscription;
     $current_next_subscription_payment = WC_Subscriptions_Order::get_next_payment_date($order_id, $product_id, $from_date = '');
     // Get the date of the current next subscription.
     $next_subscription_payment = WC_Subscriptions_Order::calculate_next_payment_date($order_id, $product_id, $type = 'mysql', $current_next_subscription_payment);
     WCSO_Subscriptions_Order::update_next_payment($order_id, $next_subscription_payment);
     // Update the next payment on the subscriptions order.
     $subscription->add_order_note(__('Subscription was skipped by the subscriber from their subscription page.', 'woocommerce-skip-one'));
     // translators: placeholder is next subscription payment
     WC_Subscriptions::add_notice(sprintf(__('You next payment subscription will now be on the %s.', 'woocommerce-skip-one'), $next_subscription_payment), 'success');
 }
 public function init()
 {
     global $wpdb;
     $subscriptions_meta_key = $wpdb->get_blog_prefix() . 'woocommerce_subscriptions';
     $order_items_table = $wpdb->get_blog_prefix() . 'woocommerce_order_items';
     $order_item_meta_table = $wpdb->get_blog_prefix() . 'woocommerce_order_itemmeta';
     // Get the IDs of all users who have a subscription
     $users_to_upgrade = get_users(array('meta_key' => $subscriptions_meta_key, 'fields' => 'ID', 'orderby' => 'ID'));
     $users_to_upgrade = array_filter($users_to_upgrade, __CLASS__ . '::is_user_upgraded');
     foreach ($users_to_upgrade as $user_to_upgrade) {
         // Can't use WC_Subscriptions_Manager::get_users_subscriptions() because it relies on the new structure
         $users_old_subscriptions = get_user_option($subscriptions_meta_key, $user_to_upgrade);
         foreach ($users_old_subscriptions as $subscription_key => $subscription) {
             if (!isset($subscription['order_id'])) {
                 // Subscription created incorrectly with v1.1.2
                 continue;
             }
             $order_item_id = WC_Subscriptions_Order::get_item_id_by_subscription_key($subscription_key);
             if (empty($order_item_id)) {
                 // Subscription created incorrectly with v1.1.2
                 continue;
             }
             if (!isset($subscription['trial_expiry_date'])) {
                 $subscription['trial_expiry_date'] = '';
             }
             // Set defaults
             $failed_payments = isset($subscription['failed_payments']) ? $subscription['failed_payments'] : 0;
             $completed_payments = isset($subscription['completed_payments']) ? $subscription['completed_payments'] : array();
             $suspension_count = isset($subscription['suspension_count']) ? $subscription['suspension_count'] : 0;
             $trial_expiry_date = isset($subscription['trial_expiry_date']) ? $subscription['trial_expiry_date'] : '';
             $wpdb->query($wpdb->prepare("INSERT INTO {$order_item_meta_table} (order_item_id, meta_key, meta_value)\n\t\t\t\t\t\tVALUES\n\t\t\t\t\t\t(%d,%s,%s),\n\t\t\t\t\t\t(%d,%s,%s),\n\t\t\t\t\t\t(%d,%s,%s),\n\t\t\t\t\t\t(%d,%s,%s),\n\t\t\t\t\t\t(%d,%s,%s),\n\t\t\t\t\t\t(%d,%s,%s),\n\t\t\t\t\t\t(%d,%s,%s),\n\t\t\t\t\t\t(%d,%s,%s)", $order_item_id, '_subscription_status', $subscription['status'], $order_item_id, '_subscription_start_date', $subscription['start_date'], $order_item_id, '_subscription_expiry_date', $subscription['expiry_date'], $order_item_id, '_subscription_end_date', $subscription['end_date'], $order_item_id, '_subscription_trial_expiry_date', $trial_expiry_date, $order_item_id, '_subscription_failed_payments', $failed_payments, $order_item_id, '_subscription_completed_payments', serialize($completed_payments), $order_item_id, '_subscription_suspension_count', $suspension_count));
         }
         update_option('wcs_1_4_last_upgraded_user_id', $user_to_upgrade);
         self::$last_upgraded_user_id = $user_to_upgrade;
     }
     // Add an underscore prefix to usermeta key to deprecate, but not delete, subscriptions in user meta
     $wpdb->update($wpdb->usermeta, array('meta_key' => '_' . $subscriptions_meta_key), array('meta_key' => $subscriptions_meta_key));
     // Now set the recurring shipping & payment method on all subscription orders
     $wpdb->query("INSERT INTO {$wpdb->postmeta} (`post_id`, `meta_key`, `meta_value`)\n\t\t\tSELECT `post_id`, CONCAT('_recurring',`meta_key`), `meta_value`\n\t\t\tFROM {$wpdb->postmeta}\n\t\t\tWHERE `meta_key` IN ('_shipping_method','_shipping_method_title','_payment_method','_payment_method_title')\n\t\t\tAND `post_id` IN (\n\t\t\t\tSELECT `post_id` FROM {$wpdb->postmeta} WHERE `meta_key` = '_order_recurring_total'\n\t\t\t)");
     // Set the recurring shipping total on all subscription orders
     $wpdb->query("INSERT INTO {$wpdb->postmeta} (`post_id`, `meta_key`, `meta_value`)\n\t\t\tSELECT `post_id`, '_order_recurring_shipping_total', `meta_value`\n\t\t\tFROM {$wpdb->postmeta}\n\t\t\tWHERE `meta_key` = '_order_shipping'\n\t\t\tAND `post_id` IN (\n\t\t\t\tSELECT `post_id` FROM {$wpdb->postmeta} WHERE `meta_key` = '_order_recurring_total'\n\t\t\t)");
     // Get the ID of all orders for a subscription with a free trial and no sign-up fee
     $order_ids = $wpdb->get_col("SELECT order_items.order_id FROM {$order_items_table} AS order_items\n\t\t\t\tLEFT JOIN {$order_item_meta_table} AS itemmeta USING (order_item_id)\n\t\t\t\tLEFT JOIN {$order_item_meta_table} AS itemmeta2 USING (order_item_id)\n\t\t\tWHERE itemmeta.meta_key = '_subscription_trial_length'\n\t\t\tAND itemmeta.meta_value > 0\n\t\t\tAND itemmeta2.meta_key = '_subscription_sign_up_fee'\n\t\t\tAND itemmeta2.meta_value > 0");
     $order_ids = implode(',', array_map('absint', array_unique($order_ids)));
     // Now set the order totals to $0 (can't use $wpdb->update as it only allows joining WHERE clauses with AND)
     if (!empty($order_ids)) {
         $wpdb->query("UPDATE {$wpdb->postmeta}\n\t\t\t\tSET `meta_value` = 0\n\t\t\t\tWHERE `meta_key` IN ( '_order_total', '_order_tax', '_order_shipping_tax', '_order_shipping', '_order_discount', '_cart_discount' )\n\t\t\t\tAND `post_id` IN ( {$order_ids} )");
         // Now set the line totals to $0
         $wpdb->query("UPDATE {$order_item_meta_table}\n\t\t\t\t SET `meta_value` = 0\n\t\t\t\t WHERE `meta_key` IN ( '_line_subtotal', '_line_subtotal_tax', '_line_total', '_line_tax', 'tax_amount', 'shipping_tax_amount' )\n\t\t\t\t AND `order_item_id` IN (\n\t\t\t\t\tSELECT `order_item_id` FROM {$order_items_table}\n\t\t\t\t\tWHERE `order_item_type` IN ('tax','line_item')\n\t\t\t\t\tAND `order_id` IN ( {$order_ids} )\n\t\t\t\t)");
     }
     update_option('wcs_1_4_upgraded_order_ids', explode(',', $order_ids));
 }
 /**
  * Process the subscription.
  *
  * @param WC_Order $order
  *
  * @return array
  */
 protected function process_subscription($order_id)
 {
     try {
         $order = new WC_Order($order_id);
         if (!isset($_POST['iugu_token'])) {
             if ('yes' == $this->debug) {
                 $this->log->add($this->id, 'Error doing the subscription for order ' . $order->get_order_number() . ': Missing the "iugu_token".');
             }
             $error_msg = __('Please make sure your card details have been entered correctly and that your browser supports JavaScript.', 'iugu-woocommerce');
             throw new Exception($error_msg);
         }
         // Create customer payment method.
         $payment_method_id = $this->api->create_customer_payment_method($order, $_POST['iugu_token']);
         if (!$payment_method_id) {
             if ('yes' == $this->debug) {
                 $this->log->add($this->id, 'Invalid customer method ID for order ' . $order->get_order_number());
             }
             $error_msg = __('An error occurred while trying to save your data. Please contact us for get help.', 'iugu-woocommerce');
             throw new Exception($error_msg);
         }
         // Save the payment method ID in order data.
         update_post_meta($order->id, '_iugu_customer_payment_method_id', $payment_method_id);
         // Try to do an initial payment.
         $initial_payment = WC_Subscriptions_Order::get_total_initial_payment($order);
         if ($initial_payment > 0) {
             $payment_response = $this->process_subscription_payment($order, $initial_payment);
         }
         if (isset($payment_response) && is_wp_error($payment_response)) {
             throw new Exception($payment_response->get_error_message());
         } else {
             // Remove cart
             $this->api->empty_card();
             // Return thank you page redirect
             return array('result' => 'success', 'redirect' => $this->get_return_url($order));
         }
     } catch (Exception $e) {
         $this->api->add_error('<strong>' . esc_attr($this->title) . '</strong>: ' . $e->getMessage());
         return array('result' => 'fail', 'redirect' => '');
     }
 }
 /**
  * Process the subscription.
  *
  * @param WC_Order $order
  *
  * @return array
  */
 protected function process_subscription($order_id)
 {
     try {
         $order = new WC_Order($order_id);
         // Try to do an initial payment.
         $initial_payment = WC_Subscriptions_Order::get_total_initial_payment($order);
         if ($initial_payment > 0) {
             $payment_response = $this->process_subscription_payment($order, $initial_payment);
         }
         if (isset($payment_response) && is_wp_error($payment_response)) {
             throw new Exception($payment_response->get_error_message());
         } else {
             // Remove cart
             $this->api->empty_card();
             // Return thank you page redirect
             return array('result' => 'success', 'redirect' => $this->get_return_url($order));
         }
     } catch (Exception $e) {
         $this->api->add_error('<strong>' . esc_attr($this->title) . '</strong>: ' . $e->getMessage());
         return array('result' => 'fail', 'redirect' => '');
     }
 }
 public function request_access_code($order, $method = 'ProcessPayment', $trx_type = 'Purchase')
 {
     $customer_ip = get_post_meta($order->id, '_customer_ip_address', true);
     // Check if order is for a subscription, if it is check for fee and charge that
     if (class_exists('WC_Subscriptions_Order') && WC_Subscriptions_Order::order_contains_subscription($order->id)) {
         if (0 == WC_Subscriptions_Order::get_total_initial_payment($order)) {
             $method = 'CreateTokenCustomer';
         } else {
             $method = 'TokenPayment';
         }
         $trx_type = 'Recurring';
         $order_total = WC_Subscriptions_Order::get_total_initial_payment($order) * 100;
     } else {
         $order_total = $order->get_total() * 100.0;
     }
     // set up request object
     $request = array('Method' => $method, 'TransactionType' => $trx_type, 'RedirectUrl' => str_replace('https:', 'http:', add_query_arg(array('wc-api' => 'WC_Gateway_EWAY', 'order_id' => $order->id, 'order_key' => $order->order_key, 'sig_key' => md5($order->order_key . 'WOO' . $order->id)), home_url('/'))), 'IPAddress' => $customer_ip, 'DeviceID' => '0b38ae7c3c5b466f8b234a8955f62bdd', 'PartnerID' => '0b38ae7c3c5b466f8b234a8955f62bdd', 'Payment' => array('TotalAmount' => $order_total, 'CurrencyCode' => get_woocommerce_currency(), 'InvoiceDescription' => apply_filters('woocommerce_eway_description', '', $order), 'InvoiceNumber' => ltrim($order->get_order_number(), _x('#', 'hash before order number', 'woocommerce')), 'InvoiceReference' => $order->id), 'Customer' => array('FirstName' => $order->billing_first_name, 'LastName' => $order->billing_last_name, 'CompanyName' => substr($order->billing_company, 0, 50), 'Street1' => $order->billing_address_1, 'Street2' => $order->billing_address_2, 'City' => $order->billing_city, 'State' => $order->billing_state, 'PostalCode' => $order->billing_postcode, 'Country' => $order->billing_country, 'Email' => $order->billing_email, 'Phone' => $order->billing_phone));
     // Add customer ID if logged in
     if (is_user_logged_in()) {
         $request['Options'][] = array('customerID' => get_current_user_id());
     }
     return $this->perform_request('/CreateAccessCode.json', json_encode($request));
 }
 /**
  * Set the subscription prices to be used in calculating totals by @see WC_Subscriptions_Cart::calculate_subscription_totals()
  *
  * @since 1.4
  */
 public static function maybe_set_apporitioned_totals($total)
 {
     global $woocommerce;
     if (false === self::cart_contains_subscription_switch()) {
         return $total;
     }
     // Maybe charge an initial amount to account for upgrading from a cheaper subscription
     $apportion_recurring_price = get_option(WC_Subscriptions_Admin::$option_prefix . '_apportion_recurring_price', 'no');
     $apportion_sign_up_fee = get_option(WC_Subscriptions_Admin::$option_prefix . '_apportion_sign_up_fee', 'no');
     $apportion_length = get_option(WC_Subscriptions_Admin::$option_prefix . '_apportion_length', 'no');
     foreach ($woocommerce->cart->get_cart() as $cart_item_key => $cart_item) {
         if (!isset($cart_item['subscription_switch']['subscription_key'])) {
             continue;
         }
         $old_subscription_key = $cart_item['subscription_switch']['subscription_key'];
         $item_data = $cart_item['data'];
         $product_id = empty($cart_item['variation_id']) ? $cart_item['product_id'] : $cart_item['variation_id'];
         $product = get_product($product_id);
         // Set the date on which the first payment for the new subscription should be charged
         $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp'] = $cart_item['subscription_switch']['next_payment_timestamp'];
         $is_virtual_product = 'no' != $item_data->virtual ? true : false;
         // Add any extra sign up fees required to switch to the new subscription
         if ('yes' == $apportion_sign_up_fee) {
             $old_subscription = WC_Subscriptions_Manager::get_subscription($old_subscription_key);
             $sign_up_fee_due = $product->subscription_sign_up_fee;
             if (self::order_contains_subscription_switch($old_subscription['order_id'])) {
                 $old_order = new WC_Order($old_subscription['order_id']);
                 $sign_up_fee_paid = $old_order->get_total();
             } else {
                 $sign_up_fee_paid = WC_Subscriptions_Order::get_item_sign_up_fee($old_subscription['order_id'], $old_subscription['product_id']);
             }
             $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_sign_up_fee = max($sign_up_fee_due - $sign_up_fee_paid, 0);
         } elseif ('no' == $apportion_sign_up_fee) {
             // $0 the initial sign-up fee
             $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_sign_up_fee = 0;
         }
         // Now lets see if we should add an apportioned amount to the sign-up fee (for upgrades) or extend the next payment date (for downgrades)
         if ('yes' == $apportion_recurring_price || 'virtual' == $apportion_recurring_price && $is_virtual_product) {
             // Get the current subscription
             $old_subscription = isset($old_subscription) ? $old_subscription : WC_Subscriptions_Manager::get_subscription($old_subscription_key);
             // Get the current subscription's original order
             $old_order = isset($old_order) ? $old_order : new WC_Order($old_subscription['order_id']);
             // Get the current subscription's last payment date
             $last_payment_timestamp = WC_Subscriptions_Manager::get_last_payment_date($old_subscription_key, get_current_user_id(), 'timestamp');
             $days_since_last_payment = round((gmdate('U') - $last_payment_timestamp) / (60 * 60 * 24));
             // Get the current subscription's next payment date
             $next_payment_timestamp = $cart_item['subscription_switch']['next_payment_timestamp'];
             $days_until_next_payment = round(($next_payment_timestamp - gmdate('U')) / (60 * 60 * 24));
             // Find the number of days between the two
             $days_in_old_cycle = $days_until_next_payment + $days_since_last_payment;
             // Find the $price per day for the old subscription's recurring total
             $old_recurring_total = WC_Subscriptions_Order::get_item_recurring_amount($old_subscription['order_id'], $old_subscription['product_id']);
             $old_price_per_day = $old_recurring_total / $days_in_old_cycle;
             // Find the price per day for the new subscription's recurring total
             // If the subscription uses the same billing interval & cycle as the old subscription,
             if ($item_data->subscription_period == $old_subscription['period'] && $item_data->subscription_period_interval == $old_subscription['interval']) {
                 $days_in_new_cycle = $days_in_old_cycle;
                 // Use $days_in_old_cycle to make sure they're consistent
                 $new_price_per_day = $product->subscription_price / $days_in_old_cycle;
             } else {
                 // We need to figure out the price per day for the new subscription based on its billing schedule
                 switch ($item_data->subscription_period) {
                     case 'day':
                         $days_in_new_cycle = $item_data->subscription_period_interval;
                         break;
                     case 'week':
                         $days_in_new_cycle = $item_data->subscription_period_interval * 7;
                         break;
                     case 'month':
                         $days_in_new_cycle = $item_data->subscription_period_interval * 30.4375;
                         // Average days per month over 4 year period
                         break;
                     case 'year':
                         $days_in_new_cycle = $item_data->subscription_period_interval * 365.25;
                         // Average days per year over 4 year period
                         break;
                 }
                 $new_price_per_day = $product->subscription_price / $days_in_new_cycle;
             }
             // If the customer is upgrading, we may need to add a gap payment to the sign-up fee or to reduce the pre-paid period (or both)
             if ($old_price_per_day < $new_price_per_day) {
                 // The new subscription may be more expensive, but it's also on a shorter billing cycle, so reduce the next pre-paid term
                 if ($days_in_old_cycle > $days_in_new_cycle) {
                     // Find out how many days at the new price per day the customer would receive for the total amount already paid
                     // (e.g. if the customer paid $10 / month previously, and was switching to a $5 / week subscription, she has pre-paid 14 days at the new price)
                     $pre_paid_days = 0;
                     do {
                         $pre_paid_days++;
                         $new_total_paid = $pre_paid_days * $new_price_per_day;
                     } while ($new_total_paid < $old_recurring_total);
                     // If the total amount the customer has paid entitles her to more days at the new price than she has received, there is no gap payment, just shorten the pre-paid term the appropriate number of days
                     if ($days_since_last_payment < $pre_paid_days) {
                         $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp'] = $last_payment_timestamp + $pre_paid_days * 60 * 60 * 24;
                         // If the total amount the customer has paid entitles her to the same or less days at the new price then start the new subscription from today
                     } else {
                         $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp'] = 0;
                     }
                 } else {
                     $extra_to_pay = $days_until_next_payment * ($new_price_per_day - $old_price_per_day);
                     $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_sign_up_fee += round($extra_to_pay, 2);
                 }
                 $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['upgraded_or_downgraded'] = 'upgraded';
                 // If the customer is downgrading, we need to extend the next payment date for n more days
             } elseif ($old_price_per_day > $new_price_per_day && $new_price_per_day > 0) {
                 $old_total_paid = $old_price_per_day * $days_until_next_payment;
                 $new_total_paid = $new_price_per_day;
                 // Find how many more days at the new lower price it takes to exceed the amount already paid
                 for ($days_to_add = 1; $new_total_paid <= $old_total_paid; $days_to_add++) {
                     $new_total_paid = $days_to_add * $new_price_per_day;
                 }
                 $days_to_add -= $days_until_next_payment;
                 $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp'] = $next_payment_timestamp + $days_to_add * 60 * 60 * 24;
                 $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['upgraded_or_downgraded'] = 'downgraded';
             }
             // The old price per day == the new price per day, no need to change anything
         }
         // Finally, if we need to make sure the initial total doesn't include any recurring amount, we can by spoofing a free trial
         if (0 != $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp']) {
             $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_trial_length = 1;
         }
         if ('yes' == $apportion_length || 'virtual' == $apportion_length && $is_virtual_product) {
             // Maybe charge an initial amount to account for upgrading from a cheaper subscription
             $base_length = WC_Subscriptions_Product::get_length($product_id);
             $completed_payments = WC_Subscriptions_Manager::get_subscriptions_completed_payment_count($old_subscription_key);
             $length_remaining = $base_length - $completed_payments;
             // Default to the base length if more payments have already been made than this subscription requires
             if ($length_remaining < 0) {
                 $length_remaining = $base_length;
             }
             $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_length = $length_remaining;
         }
     }
     return $total;
 }
Esempio n. 14
0
    /**
     * Callback for the [subscriptions] shortcode that displays subscription names for a particular user.
     *
     * @param array $attributes Shortcode attributes.
     * @return string
     */
    public static function do_subscriptions_shortcode($attributes)
    {
        $attributes = wp_parse_args($attributes, array('user_id' => 0, 'status' => 'active'));
        $status = $attributes['status'];
        $subscriptions = WC_Subscriptions_Manager::get_users_subscriptions($attributes['user_id']);
        if (empty($subscriptions)) {
            return '<ul class="user-subscriptions no-user-subscriptions">
						<li>No subscriptions found.</li>
					</ul>';
        }
        $list = '<ul class="user-subscriptions">';
        foreach ($subscriptions as $subscription) {
            if ($subscription['status'] == $status || $status == 'all') {
                $list .= sprintf('<li>%s</li>', WC_Subscriptions_Order::get_item_name($subscription['order_id'], $subscription['product_id']));
            }
        }
        $list .= '</ul>';
        return $list;
    }
 /**
  * If a gateway doesn't manage payment schedules, then we should suspend the subscription until it is paid (i.e. for manual payments
  * or token gateways like Stripe). If the gateway does manage the scheduling, then we shouldn't suspend the subscription because a 
  * gateway may use batch processing on the time payments are charged and a subscription could end up being incorrectly suspended.
  *
  * @param $user_id int The id of the user whose subscription should be put on-hold.
  * @param $subscription_key string A subscription key of the form created by @see self::get_subscription_key()
  * @since 1.2.5
  */
 public static function maybe_put_subscription_on_hold($user_id, $subscription_key)
 {
     global $woocommerce;
     $subscription = self::get_users_subscription($user_id, $subscription_key);
     if (empty($subscription) || $subscription['status'] == 'on-hold') {
         return false;
     }
     $order = new WC_Order($subscription['order_id']);
     $payment_gateways = $woocommerce->payment_gateways->payment_gateways();
     $order_uses_manual_payments = WC_Subscriptions_Order::requires_manual_renewal($order) ? true : false;
     // If the subscription is using manual payments, the gateway isn't active or it manages scheduled payments
     if ($order_uses_manual_payments || !isset($payment_gateways[$order->payment_method]) || !$payment_gateways[$order->payment_method]->supports('gateway_scheduled_payments')) {
         self::put_subscription_on_hold($user_id, $subscription_key);
     }
 }
">
					<?php 
        }
        ?>
						<?php 
        echo WC_Subscriptions_Order::get_item_name($subscription_details['order_id'], $subscription_details['product_id']);
        ?>
					<?php 
        if (false !== $product) {
            ?>
					</a>
					<?php 
        }
        ?>
					<?php 
        $order_item = WC_Subscriptions_Order::get_item_by_product_id($order, $subscription_details['product_id']);
        ?>
					<?php 
        if (WC_Subscriptions::is_woocommerce_pre('2.4')) {
            ?>
						<?php 
            $item_meta = new WC_Order_Item_Meta($order_item['item_meta'], $product);
            ?>
					<?php 
        } else {
            ?>
						<?php 
            $item_meta = new WC_Order_Item_Meta($order_item, $product);
            ?>
					<?php 
        }
 /**
  * If requesting a payment method change, replace the woocommerce_pay_shortcode() with a change payment form.
  *
  * @since 1.4
  */
 public static function maybe_replace_pay_shortcode()
 {
     global $woocommerce;
     if (!self::$is_request_to_change_payment) {
         return;
     }
     ob_clean();
     do_action('before_woocommerce_pay');
     echo '<div class="woocommerce">';
     if (!empty(self::$woocommerce_errors)) {
         foreach (self::$woocommerce_errors as $error) {
             $woocommerce->add_error($error);
         }
     }
     if (!empty(self::$woocommerce_messages)) {
         foreach (self::$woocommerce_messages as $message) {
             $woocommerce->add_message($message);
         }
     }
     $subscription_key = $_GET['change_payment_method'];
     $subscription = WC_Subscriptions_Manager::get_subscription($subscription_key);
     if (wp_verify_nonce($_GET['_wpnonce'], __FILE__) === false) {
         $woocommerce->add_error(__('There was an error with your request. Please try again.', WC_Subscriptions::$text_domain));
         $woocommerce->show_messages();
     } elseif (!WC_Subscriptions_Manager::user_owns_subscription($subscription_key)) {
         $woocommerce->add_error(__('That doesn\'t appear to be one of your subscriptions.', WC_Subscriptions::$text_domain));
         $woocommerce->show_messages();
     } elseif (empty($subscription)) {
         $woocommerce->add_error(__('Invalid subscription.', WC_Subscriptions::$text_domain));
         $woocommerce->show_messages();
     } elseif (!WC_Subscriptions_Manager::can_subscription_be_changed_to('new-payment-method', $subscription_key, get_current_user_id())) {
         $woocommerce->add_error(__('The payment method can not be changed for that subscription.', WC_Subscriptions::$text_domain));
         $woocommerce->show_messages();
     } else {
         $order = new WC_Order($subscription['order_id']);
         $order_id = absint($_GET['order_id']);
         $order_key = urldecode($_GET['order']);
         $product_id = $subscription['product_id'];
         $next_payment_timestamp = WC_Subscriptions_Order::get_next_payment_timestamp($order, $product_id);
         if (!empty($next_payment_timestamp)) {
             $next_payment_string = sprintf(__(' Next payment is due %s.', WC_Subscriptions::$text_domain), date_i18n(woocommerce_date_format(), $next_payment_timestamp));
         } else {
             $next_payment_string = '';
         }
         $woocommerce->add_message(sprintf(__('Choose a new payment method.%s', WC_Subscriptions::$text_domain), $next_payment_string));
         $woocommerce->show_messages();
         if ($order->order_key == $order_key) {
             // Set customer location to order location
             if ($order->billing_country) {
                 $woocommerce->customer->set_country($order->billing_country);
             }
             if ($order->billing_state) {
                 $woocommerce->customer->set_state($order->billing_state);
             }
             if ($order->billing_postcode) {
                 $woocommerce->customer->set_postcode($order->billing_postcode);
             }
             // Show form
             WC_Subscriptions_Order::$recurring_only_price_strings = true;
             woocommerce_get_template('checkout/form-change-payment-method.php', array('order' => $order, 'subscription_key' => $subscription_key), '', plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/');
             WC_Subscriptions_Order::$recurring_only_price_strings = false;
         } else {
             $woocommerce->add_error(__('Invalid order.', WC_Subscriptions::$text_domain));
             $woocommerce->show_messages();
         }
     }
 }
 /**
  * Output a hidden element in the order status of the orders list table to provide information about whether
  * the order displayed in that row contains a subscription or not.
  * 
  * @param $column String The string of the current column.
  * @since 1.1
  */
 public static function contains_subscription_hidden_field($order_id)
 {
     $has_subscription = WC_Subscriptions_Order::order_contains_subscription($order_id) ? 'true' : 'false';
     echo '<input type="hidden" name="contains_subscription" value="' . $has_subscription . '">';
 }
 /**
  * Checks if a subscription requires manual payment because the payment gateway used to purchase the subscription
  * did not support automatic payments at the time of the subscription sign up.
  *
  * @param $subscription_key string A subscription key of the form created by @see self::get_subscription_key()
  * @param $user_id int The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
  * @return bool | null True if the subscription exists and requires manual payments, false if the subscription uses automatic payments, null if the subscription doesn't exist.
  * @since 1.2
  */
 public static function requires_manual_renewal($subscription_key, $user_id = '')
 {
     $subscription = self::get_subscription($subscription_key, $user_id);
     if (isset($subscription['order_id'])) {
         $requires_manual_renewals = WC_Subscriptions_Order::requires_manual_renewal($subscription['order_id']);
     } else {
         $requires_manual_renewals = null;
     }
     return $requires_manual_renewals;
 }
 public function process_payment($order_id)
 {
     global $woocommerce, $wpdb;
     $this->client = $this->getCurrentClient();
     // retrieve client
     $this->order_id = $order_id;
     $this->order_desc = $_SERVER['HTTP_HOST'] . ': ' . __('Order #', 'paymill') . $this->order_id . __(', Customer-ID #', 'paymill') . get_current_user_id();
     $this->order = new WC_Order($this->order_id);
     // load subscription class
     $this->subscriptions = new paymill_subscriptions('woocommerce');
     $this->offers = $this->subscriptions->offerGetList();
     // get the totals for pre authorization
     $this->getTotals();
     /*
     				$GLOBALS['paymill_loader']->paymill_errors->setError($this->totalProducts,'paymill');
     				$GLOBALS['paymill_loader']->paymill_errors->setError($this->totalSub,'paymill');
     				if($GLOBALS['paymill_loader']->paymill_errors->status()){
     					$GLOBALS['paymill_loader']->paymill_errors->getErrors();
     					return false;
     				}
     				
     				die('end');
     */
     // create payment object and preauthorization
     require_once PAYMILL_DIR . 'lib/integration/payment.inc.php';
     $this->paymentClass = new paymill_payment($this->clientClass->getCurrentClientID(), $this->totalProducts + $this->totalSub, get_woocommerce_currency());
     // create payment object, as it should be used for next processing instead of the token.
     if ($GLOBALS['paymill_loader']->paymill_errors->status()) {
         $GLOBALS['paymill_loader']->paymill_errors->getErrors();
         return false;
     }
     // process subscriptions & products
     if ($this->processSubscriptions() && $this->processProducts()) {
         // success
         if (method_exists($this->order, 'payment_complete')) {
             // if order contains subscription, mark payment complete later when webhook triggers succeeded payment
             if (class_exists('WC_Subscriptions_Order') && WC_Subscriptions_Order::order_contains_subscription($this->order)) {
                 $this->order->update_status('on-hold', __('Awaiting payment confirmation from Paymill.', 'paymill'));
             } else {
                 $this->order->payment_complete();
             }
         }
         // Reduce stock levels
         /*if(method_exists($this->order, 'reduce_order_stock')){
         			$this->order->reduce_order_stock();
         		}*/
         // Remove cart
         $woocommerce->cart->empty_cart();
         // Return thankyou redirect
         return array('result' => 'success', 'redirect' => $this->get_return_url($this->order));
     } else {
         if ($GLOBALS['paymill_loader']->paymill_errors->status()) {
             $GLOBALS['paymill_loader']->paymill_errors->getErrors();
         }
         return false;
     }
 }
Esempio n. 21
0
 function wc_subs_exporter_create_csv($export)
 {
     global $wc_subs_exporter;
     if (!$export->status) {
         return false;
     }
     if (empty($export->subscriptions)) {
         return false;
     }
     $subscription_statuses = wc_subs_exporter_get_subscription_statuses();
     $fields = array(__('Order Id', 'wc-subs-exporter'), __('Order Status', 'wc-subs-exporter'), __('Subscription Status', 'wc-subs-exporter'), __('Subscription Description', 'wc-subs-exporter'), __('Subscription Start Date', 'wc-subs-exporter'), __('Subscription Expiration Date', 'wc-subs-exporter'), __('Subscription Last Payment', 'wc-subs-exporter'), __('Email', 'wc-subs-exporter'), __('Billing First Name', 'wc-subs-exporter'), __('Billing Last Name', 'wc-subs-exporter'), __('Billing Address 1', 'wc-subs-exporter'), __('Billing Address 2', 'wc-subs-exporter'), __('Billing City', 'wc-subs-exporter'), __('Billing State', 'wc-subs-exporter'), __('Billing Zip', 'wc-subs-exporter'), __('Billing Country', 'wc-subs-exporter'), __('Shipping First Name', 'wc-subs-exporter'), __('Shipping Last Name', 'wc-subs-exporter'), __('Shipping Address 1', 'wc-subs-exporter'), __('Shipping Address 2', 'wc-subs-exporter'), __('Shipping City', 'wc-subs-exporter'), __('Shipping State', 'wc-subs-exporter'), __('Shipping Zip', 'wc-subs-exporter'), __('Shipping Country', 'wc-subs-exporter'), __('Product SKU', 'wc-subs-exporter'), __('Product Description', 'wc-subs-exporter'), __('Quantity', 'wc-subs-exporter'), __('Date Ordered', 'wc-subs-exporter'), __('Coupon Code Used', 'wc-subs-exporter'));
     $csv = '';
     if ($export->bom) {
         $csv .= chr(239) . chr(187) . chr(191) . '';
     }
     foreach ($fields as $field) {
         $csv .= wc_subs_exporter_escape_csv_value($field, $export->delimiter, $export->escape_formatting) . $export->delimiter;
     }
     $csv = substr($csv, 0, -strlen($export->delimiter)) . "\n";
     $processed_rows = 0;
     foreach ($export->subscriptions as $user => $user_subscriptions) {
         foreach ($user_subscriptions as $key => $subscription) {
             $order = new WC_Order($subscription['order_id']);
             $order_item = WC_Subscriptions_Order::get_item_by_product_id($order, $subscription['product_id']);
             $product = $order->get_product_from_item($order_item);
             if (empty($product)) {
                 continue;
             }
             $product_sku = $product->get_sku();
             $product_title = WC_Subscriptions_Order::get_item_name($subscription['order_id'], $subscription['product_id']);
             if (isset($product->variation_data)) {
                 $product_description = woocommerce_get_formatted_variation($product->variation_data, true);
             } else {
                 $product_description = $product_title;
             }
             $coupon_code_used = '';
             $coupons = $order->get_items(array('coupon'));
             foreach ($coupons as $item_id => $item) {
                 $coupon_code_used .= $item['name'] . ' ';
             }
             $start_date = substr($subscription['start_date'], 0, 10);
             if ($subscription['expiry_date']) {
                 $end_date = substr($subscription['expiry_date'], 0, 10);
             } else {
                 $end_date = '0000-00-00';
             }
             if ($order->user_id > 0) {
                 $user_info = get_userdata($order->user_id);
             }
             if (array_key_exists('completed_payments', $subscription) && is_array($subscription['completed_payments'])) {
                 $recent_payment = substr(end($subscription['completed_payments']), 0, 10);
             } else {
                 $recent_payment = '';
             }
             $order_date = substr($order->completed_date, 0, 10);
             $csv .= wc_subs_exporter_escape_csv_value($order->id, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->status, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($subscription_statuses[$subscription['status']], $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($product_title, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($start_date, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($end_date, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($recent_payment, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($user_info->user_email, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->billing_first_name, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->billing_last_name, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->billing_address_1, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->billing_address_2, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->billing_city, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->billing_state, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->billing_postcode, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->billing_country, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->shipping_first_name, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->shipping_last_name, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->shipping_address_1, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->shipping_address_2, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->shipping_city, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->shipping_state, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->shipping_postcode, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order->shipping_country, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($product_sku, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($product_description, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value(1, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value($order_date, $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= wc_subs_exporter_escape_csv_value(trim($coupon_code_used), $export->delimiter, $export->escape_formatting) . $export->delimiter;
             $csv .= "\n";
         }
     }
     if (!$csv) {
         return false;
     } else {
         if (isset($wc_subs_exporter['debug']) && $wc_subs_exporter['debug']) {
             $wc_subs_exporter['debug_log'] = $csv;
         } else {
             return $csv;
         }
     }
 }
 /**
  * When a subscription payment hook is fired, reschedule the hook to run again on the
  * time/date of the next payment (if any).
  * 
  * WP-Cron's built in wp_schedule_event() function can not be used because the recurrence
  * must be a timestamp, which creates inaccurate schedules for month and year billing periods.
  * 
  * @since 1.0
  */
 public static function reschedule_subscription_payment($user_id, $subscription_key)
 {
     $subscription = self::get_users_subscription($user_id, $subscription_key);
     // Don't reschedule for cancelled or expired subscriptions
     if (!in_array($subscription['status'], array('expired', 'cancelled', 'failed', 'suspended'))) {
         $next_billing_timestamp = strtotime(WC_Subscriptions_Order::get_next_payment_date($subscription['order_id'], $subscription['product_id']));
         // If the next billing date is before the expiration date, reschedule the 'scheduled_subscription_payment' hook
         if ($subscription['expiry_date'] == 0 || $next_billing_timestamp < strtotime($subscription['expiry_date'])) {
             wp_schedule_single_event($next_billing_timestamp, 'scheduled_subscription_payment', array('user_id' => (int) $user_id, 'subscription_key' => $subscription_key));
             do_action('rescheduled_subscription_payment', $user_id, $subscription_key);
         }
     }
 }
 /**
  * Keep a record of an order's dates if we're marking it as completed during a request to change the payment method.
  *
  * @since 1.4
  */
 public static function store_original_order_dates($new_order_status, $order_id)
 {
     if (self::$is_request_to_change_payment) {
         $order = new WC_Order($order_id);
         $post = get_post($order_id);
         self::$original_order_dates = array('_paid_date' => WC_Subscriptions_Order::get_meta($order, 'paid_date'), '_completed_date' => WC_Subscriptions_Order::get_meta($order, 'completed_date'), 'post_date' => $order->order_date, 'post_date_gmt' => $post->post_date_gmt);
     }
     return $new_order_status;
 }
 /**
  * Process an initial subscription payment if the order contains a
  * subscription, otherwise use the parent::process_payment() method
  *
  * @since  1.4
  * @param int $order_id the order identifier
  * @return array
  */
 public function process_payment($order_id)
 {
     require_once 'class-wc-realex-api.php';
     // processing subscription (which means we are ineligible for 3DSecure for now)
     if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0() ? wcs_order_contains_subscription($order_id) : WC_Subscriptions_Order::order_contains_subscription($order_id)) {
         $order = wc_get_order($order_id);
         // redirect to payment page for payment if 3D secure is enabled
         if ($this->get_threedsecure()->is_3dsecure_available() && !SV_WC_Helper::get_post('woocommerce_pay_page')) {
             // empty cart before redirecting from Checkout page
             WC()->cart->empty_cart();
             // redirect to payment page to continue payment
             return array('result' => 'success', 'redirect' => $order->get_checkout_payment_url(true));
         }
         $order->payment_total = SV_WC_Helper::number_format(SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0() ? $order->get_total() : WC_Subscriptions_Order::get_total_initial_payment($order));
         // 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
         $result = $this->authorize($realex_client, $order);
         // subscription with initial payment, everything is now taken care of
         if (is_array($result)) {
             // for Subscriptions 2.0.x, save payment token to subscription object
             if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) {
                 // a single order can contain multiple subscriptions
                 foreach (wcs_get_subscriptions_for_order($order->id) as $subscription) {
                     // payment token
                     update_post_meta($subscription->id, '_realex_cardref', get_post_meta($order->id, '_realex_cardref', true));
                 }
             }
             return $result;
         }
         // otherwise there was no initial payment, so we mark the order as complete, etc
         if ($order->payment_total == 0) {
             // mark order as having received payment
             $order->payment_complete();
             WC()->cart->empty_cart();
             return array('result' => 'success', 'redirect' => $this->get_return_url($order));
         }
     } else {
         // processing regular product
         return parent::process_payment($order_id);
     }
 }
 /**
  * Process the payment
  *
  * If order contains subscriptions, use this class's process_subscription. If not, use the main class's process_payment function
  *
  * @param  int $order_id
  *
  * @return array
  *
  * @since 0.6.0
  */
 public function process_payment($order_id)
 {
     // Processing subscription
     if (class_exists('WC_Subscriptions_Order') && WC_Subscriptions_Order::order_contains_subscription($order_id)) {
         return $this->process_subscription($order_id);
         // Processing regular product
     } else {
         return parent::process_payment($order_id);
     }
 }
 /**
  * Get, sort and filter subscriptions for display.
  *
  * @uses $this->_column_headers
  * @uses $this->items
  * @uses $this->get_columns()
  * @uses $this->get_sortable_columns()
  * @uses $this->get_pagenum()
  * @uses $this->set_pagination_args()
  * @since 1.0
  */
 function prepare_items()
 {
     $screen = get_current_screen();
     $per_page = $this->get_items_per_page($screen->get_option('per_page', 'option'), 10);
     $this->get_column_info();
     $this->process_actions();
     if (isset($_REQUEST['s'])) {
         $subscriptions_grouped_by_user = WC_Subscriptions_Manager::search_subscriptions($_REQUEST['s']);
     } elseif (isset($_GET['_customer_user']) || isset($_GET['_product_id'])) {
         if (isset($_GET['_customer_user']) && !empty($_GET['_customer_user'])) {
             $subscriptions_grouped_by_user = array($_GET['_customer_user'] => WC_Subscriptions_Manager::get_users_subscriptions($_GET['_customer_user']));
         } else {
             $subscriptions_grouped_by_user = WC_Subscriptions_Manager::get_all_users_subscriptions();
         }
         if (isset($_GET['_product_id']) && !empty($_GET['_product_id'])) {
             foreach ($subscriptions_grouped_by_user as $user_id => $subscriptions) {
                 foreach ($subscriptions as $subscription_key => $subscription) {
                     if ($subscription['product_id'] == intval($_GET['_product_id'])) {
                         continue;
                     }
                     $order_item = WC_Subscriptions_Order::get_item_by_product_id($subscription['order_id'], $subscription['product_id']);
                     if (isset($order_item['variation_id']) && $order_item['variation_id'] == intval($_GET['_product_id'])) {
                         continue;
                     }
                     unset($subscriptions_grouped_by_user[$user_id][$subscription_key]);
                 }
             }
         }
     } else {
         $subscriptions_grouped_by_user = WC_Subscriptions_Manager::get_all_users_subscriptions();
     }
     $status_to_show = isset($_GET['status']) ? $_GET['status'] : 'all';
     // Reformat the subscriptions grouped by user to be usable by each row
     $subscriptions = array();
     $this->statuses = array();
     foreach ($subscriptions_grouped_by_user as $user_id => $users_subscriptions) {
         foreach ($users_subscriptions as $subscription_key => $subscription) {
             $this->statuses[$subscription['status']] = isset($this->statuses[$subscription['status']]) ? $this->statuses[$subscription['status']] + 1 : 1;
             $all_subscriptions[$subscription_key] = $subscription + array('user_id' => $user_id, 'subscription_key' => $subscription_key);
             if ($status_to_show == $subscription['status'] || $status_to_show == 'all' && $subscription['status'] != 'trash') {
                 $subscriptions[$subscription_key] = $subscription + array('user_id' => $user_id, 'subscription_key' => $subscription_key);
             }
         }
     }
     // If we have a request for a status that does not exist, default to all subscriptions
     if (!isset($this->statuses[$status_to_show])) {
         if ($status_to_show != 'all') {
             $status_to_show = $_GET['status'] = 'all';
             foreach ($all_subscriptions as $subscription_key => $subscription) {
                 if ($all_subscriptions[$subscription_key]['status'] != 'trash') {
                     $subscriptions = $subscriptions + array($subscription_key => $subscription);
                 }
             }
         } else {
             $_GET['status'] = 'all';
         }
     }
     ksort($this->statuses);
     $this->statuses = array('all' => array_sum($this->statuses)) + $this->statuses;
     if (isset($this->statuses['trash'])) {
         $this->statuses['all'] = $this->statuses['all'] - $this->statuses['trash'];
     }
     usort($subscriptions, array(&$this, 'sort_subscriptions'));
     // Add sorted & sliced data to the items property to be used by the rest of the class
     $this->items = array_slice($subscriptions, ($this->get_pagenum() - 1) * $per_page, $per_page);
     $total_items = count($subscriptions);
     $this->set_pagination_args(array('total_items' => $total_items, 'per_page' => $per_page, 'total_pages' => ceil($total_items / $per_page)));
 }
 /**
  * For subscription renewal via cart, preivously adjust item price by original order discount
  *
  * No longer required as of 1.3.5 as totals are calculated correctly internally.
  *
  * @since 1.3
  */
 public static function get_discounted_price_for_renewal($price, $values, $cart)
 {
     $cart_item = self::cart_contains_subscription_renewal();
     if ($cart_item) {
         $original_order_id = $cart_item['subscription_renewal']['original_order'];
         $price -= WC_Subscriptions_Order::get_meta($original_order_id, '_order_recurring_discount_cart', 0);
     }
     return $price;
 }
?>
</th>
			<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php 
_e('Start Date', 'woocommerce-subscriptions');
?>
</th>
			<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php 
_e('End Date', 'woocommerce-subscriptions');
?>
</th>
		</tr>
	</thead>
	<tbody>
	<?php 
foreach ($order->get_items() as $item) {
    if (WC_Subscriptions_Order::is_item_subscription($order, $item)) {
        ?>
			<tr>
				<td scope="row" style="text-align:left; border: 1px solid #eee;"><?php 
        echo $item['name'];
        ?>
</td>
				<td scope="row" style="text-align:left; border: 1px solid #eee;"><?php 
        echo date_i18n(woocommerce_date_format(), strtotime($item['subscription_start_date']));
        ?>
</td>
				<td scope="row" style="text-align:left; border: 1px solid #eee;"><?php 
        echo !empty($item['subscription_expiry_date']) ? date_i18n(woocommerce_date_format(), strtotime($item['subscription_expiry_date'])) : __('When Cancelled', 'woocommerce-subscriptions');
        ?>
			</tr>
			<?php 
_e('Subscription', 'woocommerce-subscriptions');
?>
</th>
			<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php 
_e('Start Date', 'woocommerce-subscriptions');
?>
</th>
			<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php 
_e('End Date', 'woocommerce-subscriptions');
?>
</th>
		</tr>
	</thead>
	<tbody>
	<?php 
foreach (WC_Subscriptions_Order::get_recurring_items($order) as $item) {
    ?>
			<tr>
				<td scope="row" style="text-align:left; border: 1px solid #eee;"><?php 
    echo $item['name'];
    ?>
</td>
				<td scope="row" style="text-align:left; border: 1px solid #eee;"><?php 
    echo date_i18n(woocommerce_date_format(), strtotime($item['subscription_start_date']));
    ?>
</td>
				<td scope="row" style="text-align:left; border: 1px solid #eee;"><?php 
    echo !empty($item['subscription_expiry_date']) ? date_i18n(woocommerce_date_format(), strtotime($item['subscription_expiry_date'])) : __('When Cancelled', 'woocommerce-subscriptions');
    ?>
			</tr>
	<?php 
function wpcomm_renewal_meta_update($order_meta, $order_id)
{
    global $wpdb, $woocommerce;
    // Send me an email if this hook works
    error_log("woocommerce_subscriptions_renewal_order_created hook fired", 1, "*****@*****.**", "Subject: woocommerce_subscriptions_renewal_order_created");
    if (!is_object($order)) {
        $order = new WC_Order($order);
    }
    // Get the values we need from the WC_Order object
    $order_id = $order->id;
    $item = $order->get_items();
    $product_id = WC_Subscriptions_Order::get_items_product_id($item[0]);
    // These arrays contain the details for each possible product, in order. They
    // are used to change the order to the correct values
    $quarterly_product_ids = array(2949, 2945, 2767, 2793, 2795, 2796, 2798, 2799, 2800, 2805, 2806, 2815, 2816, 2817);
    $quarterly_product_names = array("One Day Renewal for Testing No Virtual Downloadable", "One Day Renewal for Testing", "0-3 MONTHS ELEPHANT (QUARTERLY)", "3-6 MONTHS HIPPO (QUARTERLY)", "6-9 MONTHS GIRAFFE (QUARTERLY)", "9-12 MONTHS PANDA (QUARTERLY)", "12-15 MONTHS ZEBRA (QUARTERLY)", "15-18 MONTHS RABBIT (QUARTERLY)", "18-21 MONTHS MONKEY (QUARTERLY)", "21-24 MONTHS FROG (QUARTERLY)", "24-27 MONTHS KANGAROO (QUARTERLY)", "27-30 MONTHS BEAR (QUARTERLY)", "30-33 MONTHS TIGER (QUARTERLY)", "33-36 MONTHS CROCODILE (QUARTERLY)");
    // Not sure yet if SKUs are needed
    $quarterly_product_skus = array("test sku one", "test sku two", "0-3-elephant-q", "3-6-hippo-q", "6-9-giraffe-q", "9-12-panda-q", "12-15-zebra-q", "15-18-rabbit-q", "18-21-monkey-q", "21-24-frog-q", "24-24-kangaroo-q", "27-30-bear-q", "30-33-tiger-q", "33-36-crocodile-q");
    $yearly_product_names = array();
    $yearly_product_ids = array();
    // Get the position of the current id, and then assign the next product
    // to $incremented_item_id and $incremented_item_name
    $product_id_index = array_search($product_id, $quarterly_product_ids);
    if ($product_id_index === False) {
        $product_id_index = array_search($product_id, $yearly_product_ids);
    }
    $incremented_item_id = $quarterly_product_ids[$product_id_index + 1];
    $incremented_item_name = $quarterly_product_names[$product_id_index + 1];
    $incremented_item_sku = $quarterly_product_skus[$product_id_index + 1];
    // Apply the updates to the order
    $order_meta["_product_id"] = $incremented_item_id;
    $order_meta["_product_name"] = $incremented_item_name;
    $order_meta["_sku"] = $incremented_item_sku;
    return $order_meta;
}