/**
  * Bootstraps the class and hooks required actions & filters.
  *
  * @since 1.0
  */
 public static function init()
 {
     // Generate an order to keep a record of each subscription payment
     add_action('processed_subscription_payment', __CLASS__ . '::generate_paid_renewal_order', 10, 2);
     add_action('processed_subscription_payment_failure', __CLASS__ . '::generate_failed_payment_renewal_order', 10, 2);
     // If a subscription requires manual payment, generate an order to accept the payment
     add_action('scheduled_subscription_payment', __CLASS__ . '::maybe_generate_manual_renewal_order', 10, 2);
     // Make sure *manual* payment on a renewal order is correctly processed
     add_action('woocommerce_payment_complete', __CLASS__ . '::maybe_record_renewal_order_payment', 10, 1);
     // Make sure *manual* payment on renewal orders is correctly processed for gateways that do not call WC_Order::payment_complete()
     add_action('woocommerce_order_status_on-hold_to_processing', __CLASS__ . '::maybe_record_renewal_order_payment', 10, 1);
     add_action('woocommerce_order_status_on-hold_to_completed', __CLASS__ . '::maybe_record_renewal_order_payment', 10, 1);
     // Make sure payment on renewal orders is correctly processed when the *automatic* payment had previously failed
     add_action('woocommerce_order_status_failed_to_processing', __CLASS__ . '::process_failed_renewal_order_payment', 10, 1);
     add_action('woocommerce_order_status_failed_to_completed', __CLASS__ . '::process_failed_renewal_order_payment', 10, 1);
     add_action('woocommerce_order_status_failed', __CLASS__ . '::maybe_record_renewal_order_payment_failure', 10, 1);
     // Check if a user is requesting to create a renewal order for a subscription
     add_action('wp_loaded', __CLASS__ . '::maybe_create_renewal_order_for_user', 100);
     // Used to detect if payment on failed order is being made from 'My Account'
     add_action('before_woocommerce_pay', __CLASS__ . '::before_woocommerce_pay', 10);
     // To handle virtual/non-downloaded that require store manager approval
     add_action('woocommerce_payment_complete', __CLASS__ . '::maybe_process_failed_renewal_order_payment', 10, 1);
     add_action('woocommerce_order_status_on-hold_to_processing', __CLASS__ . '::maybe_process_failed_renewal_order_payment', 10, 1);
     add_action('woocommerce_order_status_on-hold_to_completed', __CLASS__ . '::maybe_process_failed_renewal_order_payment', 10, 1);
     // Add a renewal orders section to the Related Orders meta box
     add_action('woocommerce_subscriptions_related_orders_meta_box', __CLASS__ . '::renewal_orders_meta_box_section', 10, 2);
     // Allow renewal of limited subscriptions
     add_filter('woocommerce_subscription_is_purchasable', __CLASS__ . '::is_purchasable', 12, 2);
     add_filter('woocommerce_subscription_variation_is_purchasable', __CLASS__ . '::is_purchasable', 12, 2);
     add_action('woocommerce_payment_complete', __CLASS__ . '::trigger_renewal_payment_complete', 10);
     add_filter('woocommerce_get_checkout_payment_url', __CLASS__ . '::get_checkout_payment_url', 10, 2);
     add_filter('woocommerce_product_addons_adjust_price', __CLASS__ . '::product_addons_adjust_price', 10, 2);
     // The notice displayed when a subscription product has been deleted and the custoemr attempts to manually renew or make a renewal payment for a failed recurring payment for that product/subscription
     self::$product_deleted_error_message = apply_filters('woocommerce_subscriptions_renew_deleted_product_error_message', __('That product has been deleted and can no longer be renewed. Please choose a new product or contact us for assistance.', 'woocommerce-subscriptions'));
 }
 /**
  * When creating an order at checkout, if the order is for renewing a subscription from a failed
  * payment, hijack the order creation to make a renewal order - not a vanilla WooCommerce order.
  *
  * @since 1.3
  */
 public static function filter_woocommerce_create_order($order_id, $checkout_object)
 {
     global $woocommerce;
     $cart_item = WC_Subscriptions_Cart::cart_contains_subscription_renewal();
     if ($cart_item && 'child' == $cart_item['subscription_renewal']['role']) {
         $product_id = $cart_item['product_id'];
         $failed_order_id = $cart_item['subscription_renewal']['failed_order'];
         $original_order_id = $cart_item['subscription_renewal']['original_order'];
         $role = $cart_item['subscription_renewal']['role'];
         remove_action('woocommerce_subscriptions_renewal_order_created', 'WC_Subscriptions_Renewal_Order::maybe_send_customer_renewal_order_email', 10, 1);
         $renewal_order_args = array('new_order_role' => $role, 'checkout_renewal' => true, 'failed_order_id' => $failed_order_id);
         $order_id = WC_Subscriptions_Renewal_Order::generate_renewal_order($original_order_id, $product_id, $renewal_order_args);
         if ($checkout_object->posted['payment_method']) {
             $available_gateways = $woocommerce->payment_gateways->get_available_payment_gateways();
             if (isset($available_gateways[$checkout_object->posted['payment_method']])) {
                 $payment_method = $available_gateways[$checkout_object->posted['payment_method']];
                 $payment_method->validate_fields();
                 update_post_meta($order_id, '_payment_method', $payment_method->id);
                 update_post_meta($order_id, '_payment_method_title', $payment_method->get_title());
             }
         }
         if ($checkout_object->posted['shipping_method']) {
             $available_shipping_methods = $woocommerce->shipping->get_available_shipping_methods();
             if (isset($available_shipping_methods[$checkout_object->posted['shipping_method']])) {
                 $shipping_method = $available_shipping_methods[$checkout_object->posted['shipping_method']];
                 update_post_meta($order_id, '_shipping_method', $shipping_method->id);
                 update_post_meta($order_id, '_shipping_method_title', $shipping_method->label);
             }
         }
         if (isset($failed_order_id)) {
             $failed_order = new WC_Order($failed_order_id);
             if ($failed_order->status == 'failed') {
                 update_post_meta($failed_order_id, '_failed_order_replaced_by', $order_id);
             }
         }
     }
     return $order_id;
 }
Ejemplo n.º 3
0
 /**
  * Registers the "Renewal Orders" meta box for the "Edit Order" page.
  */
 public static function add_related_orders_meta_box()
 {
     global $current_screen, $post_id;
     // Only display the meta box if an order relates to a subscription
     if ('shop_order' == $current_screen->id && (WC_Subscriptions_Renewal_Order::is_renewal($post_id, array('order_role' => 'child')) || WC_Subscriptions_Order::order_contains_subscription($post_id))) {
         add_meta_box('subscription_renewal_orders', __('Related Subscription Orders', WC_Subscriptions::$text_domain), __CLASS__ . '::related_orders_meta_box', 'shop_order');
     }
 }
 /**
  * Adjust renew membership URL for subscription-based memberships
  *
  * @since 1.0.0
  * @param string $url Renew membership URL
  * @param WC_Memberships_User_Membership $user_membership
  * @return string Modified renew URL
  */
 public function renew_membership_url($url, WC_Memberships_User_Membership $user_membership)
 {
     if ($this->has_membership_plan_subscription($user_membership->get_plan_id())) {
         // note that we must also check if order contains a subscription since users
         // can be manually-assigned to memberships and not have an associated subscription
         // 2.0 onwards
         if ($this->is_subscriptions_gte_2_0()) {
             if (wcs_order_contains_subscription($user_membership->get_order())) {
                 $url = wcs_get_users_resubscribe_link($this->get_user_membership_subscription_id($user_membership->get_id()));
             }
         } else {
             if (WC_Subscriptions_Order::order_contains_subscription($user_membership->get_order())) {
                 $subscription_key = $this->get_user_membership_subscription_key($user_membership->get_id());
                 $url = WC_Subscriptions_Renewal_Order::get_users_renewal_link($subscription_key);
             }
         }
     }
     return $url;
 }
 /**
  * Check if a payment is being made on a failed renewal order from 'My Account'. If so,
  * redirect the order into a cart/checkout payment flow.
  *
  * @since 1.3
  */
 public static function before_woocommerce_pay()
 {
     global $woocommerce;
     if (isset($_GET['pay_for_order']) && isset($_GET['order']) && isset($_GET['order_id'])) {
         // Pay for existing order
         $order_key = urldecode($_GET['order']);
         $order_id = absint($_GET['order_id']);
         $order = new WC_Order($order_id);
         $failed_order_replaced_by = get_post_meta($order_id, '_failed_order_replaced_by', true);
         if (is_numeric($failed_order_replaced_by)) {
             $woocommerce->add_error(sprintf(__('Sorry, this failed order has already been paid. See order %s.', WC_Subscriptions::$text_domain), $failed_order_replaced_by));
             wp_safe_redirect(get_permalink(woocommerce_get_page_id('myaccount')));
             exit;
         }
         if ($order->id == $order_id && $order->order_key == $order_key && in_array($order->status, array('pending', 'failed')) && WC_Subscriptions_Renewal_Order::is_renewal($order)) {
             // If order being paid is a parent order, get the original order, else query parent_order
             if (WC_Subscriptions_Renewal_Order::is_renewal($order_id, array('order_role' => 'parent'))) {
                 $role = 'parent';
                 $original_order = new WC_Order($order->order_custom_fields['_original_order'][0]);
             } elseif (WC_Subscriptions_Renewal_Order::is_renewal($order_id, array('order_role' => 'child'))) {
                 $role = 'child';
                 $original_order = WC_Subscriptions_Renewal_Order::get_parent_order($order_id);
             }
             $order_items = WC_Subscriptions_Order::get_recurring_items($original_order);
             $first_order_item = reset($order_items);
             $product_id = WC_Subscriptions_Order::get_items_product_id($first_order_item);
             $product = get_product($product_id);
             // Make sure we don't actually need the variation ID
             if ($product->is_type(array('variable-subscription'))) {
                 $item = WC_Subscriptions_Order::get_item_by_product_id($original_order, $product_id);
                 $variation_id = $item['variation_id'];
                 $variation = get_product($variation_id);
                 $variation_data = $variation->get_variation_attributes();
             } elseif ($product->is_type(array('subscription_variation'))) {
                 // Handle existing renewal orders incorrectly using variation_id as the product_id
                 $product_id = $product->id;
                 $variation_id = $product->get_variation_id();
                 $variation_data = $product->get_variation_attributes();
             } else {
                 $variation_id = '';
                 $variation_data = array();
             }
             $woocommerce->cart->empty_cart(true);
             $woocommerce->cart->add_to_cart($product_id, 1, $variation_id, $variation_data, array('subscription_renewal' => array('original_order' => $original_order->id, 'failed_order' => $order_id, 'role' => $role)));
             wp_safe_redirect($woocommerce->cart->get_checkout_url());
             exit;
         }
     }
 }
 /**
  * When creating an order at checkout, if the order is for renewing a subscription from a failed
  * payment, hijack the order creation to make a renewal order - not a vanilla WooCommerce order.
  *
  * @since 1.3
  */
 public static function filter_woocommerce_create_order($order_id, $checkout_object)
 {
     global $woocommerce;
     $cart_item = WC_Subscriptions_Cart::cart_contains_subscription_renewal();
     if ($cart_item && 'child' == $cart_item['subscription_renewal']['role']) {
         $product_id = $cart_item['product_id'];
         $failed_order_id = $cart_item['subscription_renewal']['failed_order'];
         $original_order_id = $cart_item['subscription_renewal']['original_order'];
         $role = $cart_item['subscription_renewal']['role'];
         $renewal_order_args = array('new_order_role' => $role, 'checkout_renewal' => true, 'failed_order_id' => $failed_order_id);
         $renewal_order_id = WC_Subscriptions_Renewal_Order::generate_renewal_order($original_order_id, $product_id, $renewal_order_args);
         $original_order = new WC_Order($original_order_id);
         $customer_id = $original_order->customer_user;
         // Save posted billing address fields to both renewal and original order
         if ($checkout_object->checkout_fields['billing']) {
             foreach ($checkout_object->checkout_fields['billing'] as $key => $field) {
                 update_post_meta($renewal_order_id, '_' . $key, $checkout_object->posted[$key]);
                 update_post_meta($original_order->id, '_' . $key, $checkout_object->posted[$key]);
                 // User
                 if ($customer_id && !empty($checkout_object->posted[$key])) {
                     update_user_meta($customer_id, $key, $checkout_object->posted[$key]);
                     // Special fields
                     switch ($key) {
                         case "billing_email":
                             if (!email_exists($checkout_object->posted[$key])) {
                                 wp_update_user(array('ID' => $customer_id, 'user_email' => $checkout_object->posted[$key]));
                             }
                             break;
                         case "billing_first_name":
                             wp_update_user(array('ID' => $customer_id, 'first_name' => $checkout_object->posted[$key]));
                             break;
                         case "billing_last_name":
                             wp_update_user(array('ID' => $customer_id, 'last_name' => $checkout_object->posted[$key]));
                             break;
                     }
                 }
             }
         }
         // Save posted shipping address fields to both renewal and original order
         if ($checkout_object->checkout_fields['shipping'] && ($woocommerce->cart->needs_shipping() || get_option('woocommerce_require_shipping_address') == 'yes')) {
             foreach ($checkout_object->checkout_fields['shipping'] as $key => $field) {
                 $postvalue = false;
                 if (isset($checkout_object->posted['shiptobilling']) && $checkout_object->posted['shiptobilling'] || isset($checkout_object->posted['ship_to_different_address']) && $checkout_object->posted['ship_to_different_address']) {
                     if (isset($checkout_object->posted[str_replace('shipping_', 'billing_', $key)])) {
                         $postvalue = $checkout_object->posted[str_replace('shipping_', 'billing_', $key)];
                         update_post_meta($renewal_order_id, '_' . $key, $postvalue);
                         update_post_meta($original_order->id, '_' . $key, $postvalue);
                     }
                 } elseif (isset($checkout_object->posted[$key])) {
                     $postvalue = $checkout_object->posted[$key];
                     update_post_meta($renewal_order_id, '_' . $key, $postvalue);
                     update_post_meta($original_order->id, '_' . $key, $postvalue);
                 }
                 // User
                 if ($postvalue && $customer_id) {
                     update_user_meta($customer_id, $key, $postvalue);
                 }
             }
         }
         if ($checkout_object->posted['payment_method']) {
             $available_gateways = $woocommerce->payment_gateways->get_available_payment_gateways();
             if (isset($available_gateways[$checkout_object->posted['payment_method']])) {
                 $payment_method = $available_gateways[$checkout_object->posted['payment_method']];
                 $payment_method->validate_fields();
                 update_post_meta($renewal_order_id, '_payment_method', $payment_method->id);
                 update_post_meta($renewal_order_id, '_payment_method_title', $payment_method->get_title());
             }
         }
         // Set the shipping method for WC < 2.1
         if ($checkout_object->posted['shipping_method'] && method_exists($woocommerce->shipping, 'get_available_shipping_methods')) {
             $available_shipping_methods = $woocommerce->shipping->get_available_shipping_methods();
             if (isset($available_shipping_methods[$checkout_object->posted['shipping_method']])) {
                 $shipping_method = $available_shipping_methods[$checkout_object->posted['shipping_method']];
                 update_post_meta($renewal_order_id, '_shipping_method', $shipping_method->id);
                 update_post_meta($renewal_order_id, '_shipping_method_title', $shipping_method->label);
             }
         }
         if (isset($failed_order_id)) {
             $failed_order = new WC_Order($failed_order_id);
             if ($failed_order->status == 'failed') {
                 update_post_meta($failed_order_id, '_failed_order_replaced_by', $renewal_order_id);
             }
         }
         // Store fees, any new fees on this order should be applied now
         foreach ($woocommerce->cart->get_fees() as $fee) {
             $item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $fee->name, 'order_item_type' => 'fee'));
             if ($fee->taxable) {
                 woocommerce_add_order_item_meta($item_id, '_tax_class', $fee->tax_class);
             } else {
                 woocommerce_add_order_item_meta($item_id, '_tax_class', '0');
             }
             woocommerce_add_order_item_meta($item_id, '_line_total', woocommerce_format_decimal($fee->amount));
             woocommerce_add_order_item_meta($item_id, '_line_tax', woocommerce_format_decimal($fee->tax));
         }
         // Store tax rows
         foreach (array_keys($woocommerce->cart->taxes + $woocommerce->cart->shipping_taxes) as $key) {
             $item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => WC_Tax::get_rate_code($key), 'order_item_type' => 'tax'));
             // Add line item meta
             if ($item_id) {
                 woocommerce_add_order_item_meta($item_id, 'rate_id', $key);
                 woocommerce_add_order_item_meta($item_id, 'label', WC_Tax::get_rate_label($key));
                 woocommerce_add_order_item_meta($item_id, 'compound', absint(WC_Tax::is_compound($key) ? 1 : 0));
                 woocommerce_add_order_item_meta($item_id, 'tax_amount', woocommerce_format_decimal(isset($woocommerce->cart->taxes[$key]) ? $woocommerce->cart->taxes[$key] : 0));
                 woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_format_decimal(isset($woocommerce->cart->shipping_taxes[$key]) ? $woocommerce->cart->shipping_taxes[$key] : 0));
             }
         }
         // Store shipping for all packages on this order (as this can differ between each order), WC 2.1
         if (method_exists($woocommerce->shipping, 'get_packages')) {
             $packages = $woocommerce->shipping->get_packages();
             foreach ($packages as $i => $package) {
                 if (isset($package['rates'][$checkout_object->shipping_methods[$i]])) {
                     $method = $package['rates'][$checkout_object->shipping_methods[$i]];
                     $item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $method->label, 'order_item_type' => 'shipping'));
                     if ($item_id) {
                         woocommerce_add_order_item_meta($item_id, 'method_id', $method->id);
                         woocommerce_add_order_item_meta($item_id, 'cost', woocommerce_format_decimal($method->cost));
                         do_action('woocommerce_add_shipping_order_item', $renewal_order_id, $item_id, $i);
                     }
                 }
             }
         }
         update_post_meta($renewal_order_id, '_order_shipping', WC_Subscriptions::format_total($woocommerce->cart->shipping_total));
         update_post_meta($renewal_order_id, '_cart_discount', WC_Subscriptions::format_total($woocommerce->cart->get_cart_discount_total()));
         update_post_meta($renewal_order_id, '_order_tax', WC_Subscriptions::format_total($woocommerce->cart->tax_total));
         update_post_meta($renewal_order_id, '_order_shipping_tax', WC_Subscriptions::format_total($woocommerce->cart->shipping_tax_total));
         update_post_meta($renewal_order_id, '_order_total', WC_Subscriptions::format_total($woocommerce->cart->total));
         // WC < 2.3, set deprecated after tax discount total
         if (WC_Subscriptions::is_woocommerce_pre('2.3')) {
             update_post_meta($renewal_order_id, '_order_discount', WC_Subscriptions::format_total($woocommerce->cart->get_total_discount()));
         }
         update_post_meta($renewal_order_id, '_order_currency', get_woocommerce_currency());
         update_post_meta($renewal_order_id, '_prices_include_tax', get_option('woocommerce_prices_include_tax'));
         update_post_meta($renewal_order_id, '_customer_ip_address', isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);
         update_post_meta($renewal_order_id, '_customer_user_agent', isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '');
         update_post_meta($renewal_order_id, '_checkout_renewal', 'yes');
         // Return the new order's ID to prevent WC creating an order
         $order_id = $renewal_order_id;
     }
     return $order_id;
 }
 /**
  * Check if a payment is being made on a failed renewal order from 'My Account'. If so,
  * redirect the order into a cart/checkout payment flow.
  *
  * @since 1.3
  */
 public static function before_woocommerce_pay()
 {
     global $woocommerce, $wp;
     if (isset($_GET['pay_for_order']) && (isset($_GET['order']) && isset($_GET['order_id']) || isset($_GET['key']) && isset($wp->query_vars['order-pay']))) {
         // Pay for existing order
         $order_key = isset($_GET['key']) ? $_GET['key'] : $_GET['order'];
         // WC 2.1 compatibility
         $order_id = isset($wp->query_vars['order-pay']) ? $wp->query_vars['order-pay'] : absint($_GET['order_id']);
         $order = new WC_Order($order_id);
         $failed_order_replaced_by = get_post_meta($order_id, '_failed_order_replaced_by', true);
         if (is_numeric($failed_order_replaced_by)) {
             WC_Subscriptions::add_notice(sprintf(__('Sorry, this failed order has already been paid. See order %s.', 'woocommerce-subscriptions'), $failed_order_replaced_by), 'error');
             wp_safe_redirect(get_permalink(woocommerce_get_page_id('myaccount')));
             exit;
         }
         if ($order->id == $order_id && $order->order_key == $order_key && in_array($order->status, array('pending', 'failed')) && WC_Subscriptions_Renewal_Order::is_renewal($order)) {
             // If order being paid is a parent order, get the original order, else query parent_order
             if (WC_Subscriptions_Renewal_Order::is_renewal($order_id, array('order_role' => 'parent'))) {
                 $role = 'parent';
                 $original_order = new WC_Order(WC_Subscriptions_Order::get_meta($order, 'original_order', false));
             } elseif (WC_Subscriptions_Renewal_Order::is_renewal($order_id, array('order_role' => 'child'))) {
                 $role = 'child';
                 $original_order = WC_Subscriptions_Renewal_Order::get_parent_order($order_id);
             }
             $order_items = WC_Subscriptions_Order::get_recurring_items($original_order);
             $first_order_item = reset($order_items);
             $product_id = WC_Subscriptions_Order::get_items_product_id($first_order_item);
             $product = get_product($product_id);
             $variation_id = '';
             $variation_data = array();
             // Display error message for deleted products
             if (false === $product) {
                 WC_Subscriptions::add_notice(self::$product_deleted_error_message, 'error');
                 // Make sure we don't actually need the variation ID
             } elseif ($product->is_type(array('variable-subscription'))) {
                 $item = WC_Subscriptions_Order::get_item_by_product_id($original_order, $product_id);
                 $variation_id = $item['variation_id'];
                 $variation = get_product($variation_id);
                 // Display error message for deleted product variations
                 if (false === $variation) {
                     WC_Subscriptions::add_notice(self::$product_deleted_error_message, 'error');
                     $variation_data = array();
                 } else {
                     $variation_data = $variation->get_variation_attributes();
                 }
             } elseif ($product->is_type(array('subscription_variation'))) {
                 // Handle existing renewal orders incorrectly using variation_id as the product_id
                 $product_id = $product->id;
                 $variation_id = $product->get_variation_id();
                 $variation_data = $product->get_variation_attributes();
             }
             $woocommerce->cart->empty_cart(true);
             $woocommerce->cart->add_to_cart($product_id, 1, $variation_id, $variation_data, array('subscription_renewal' => array('original_order' => $original_order->id, 'failed_order' => $order_id, 'role' => $role)));
             wp_safe_redirect($woocommerce->cart->get_checkout_url());
             exit;
         }
     }
 }
 /**
  * Override the default PayPal standard args in WooCommerce for subscription purchases when
  * automatic payments are enabled and when the recurring order totals is over $0.00 (because
  * PayPal doesn't support subscriptions with a $0 recurring total, we need to circumvent it and
  * manage it entirely ourselves.)
  *
  * Based on the HTML Variables documented here: https://developer.paypal.com/webapps/developer/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/#id08A6HI00JQU
  *
  * @since 1.0
  */
 public static function paypal_standard_subscription_args($paypal_args)
 {
     extract(self::get_order_id_and_key($paypal_args));
     $order = new WC_Order($order_id);
     if ($cart_item = WC_Subscriptions_Cart::cart_contains_failed_renewal_order_payment() || false !== WC_Subscriptions_Renewal_Order::get_failed_order_replaced_by($order_id)) {
         $renewal_order = $order;
         $order = WC_Subscriptions_Renewal_Order::get_parent_order($renewal_order);
         $order_contains_failed_renewal = true;
     } else {
         $order_contains_failed_renewal = false;
     }
     if ($order_contains_failed_renewal || WC_Subscriptions_Order::order_contains_subscription($order) && WC_Subscriptions_Order::get_recurring_total($order) > 0 && 'yes' !== get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) {
         // Only one subscription allowed in the cart when PayPal Standard is active
         $product = $order->get_product_from_item(array_pop(WC_Subscriptions_Order::get_recurring_items($order)));
         // It's a subscription
         $paypal_args['cmd'] = '_xclick-subscriptions';
         if (count($order->get_items()) > 1) {
             foreach ($order->get_items() as $item) {
                 if ($item['qty'] > 1) {
                     $item_names[] = $item['qty'] . ' x ' . self::paypal_item_name($item['name']);
                 } elseif ($item['qty'] > 0) {
                     $item_names[] = self::paypal_item_name($item['name']);
                 }
             }
             $paypal_args['item_name'] = self::paypal_item_name(sprintf(__('Order %s', 'woocommerce-subscriptions'), $order->get_order_number() . " - " . implode(', ', $item_names)));
         } else {
             $paypal_args['item_name'] = self::paypal_item_name($product->get_title());
         }
         $unconverted_periods = array('billing_period' => WC_Subscriptions_Order::get_subscription_period($order), 'trial_period' => WC_Subscriptions_Order::get_subscription_trial_period($order));
         $converted_periods = array();
         // Convert period strings into PayPay's format
         foreach ($unconverted_periods as $key => $period) {
             switch (strtolower($period)) {
                 case 'day':
                     $converted_periods[$key] = 'D';
                     break;
                 case 'week':
                     $converted_periods[$key] = 'W';
                     break;
                 case 'year':
                     $converted_periods[$key] = 'Y';
                     break;
                 case 'month':
                 default:
                     $converted_periods[$key] = 'M';
                     break;
             }
         }
         $price_per_period = WC_Subscriptions_Order::get_recurring_total($order);
         $subscription_interval = WC_Subscriptions_Order::get_subscription_interval($order);
         $subscription_length = WC_Subscriptions_Order::get_subscription_length($order);
         $subscription_installments = $subscription_length / $subscription_interval;
         $is_payment_change = WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment;
         $is_switch_order = WC_Subscriptions_Switcher::order_contains_subscription_switch($order->id);
         $is_synced_subscription = WC_Subscriptions_Synchroniser::order_contains_synced_subscription($order->id);
         $sign_up_fee = $is_payment_change ? 0 : WC_Subscriptions_Order::get_sign_up_fee($order);
         $initial_payment = $is_payment_change ? 0 : WC_Subscriptions_Order::get_total_initial_payment($order);
         if ($is_payment_change) {
             // Add a nonce to the order ID to avoid "This invoice has already been paid" error when changing payment method to PayPal when it was previously PayPal
             $paypal_args['invoice'] = $paypal_args['invoice'] . '-wcscpm-' . wp_create_nonce();
         } elseif ($order_contains_failed_renewal) {
             // Set the invoice details to the original order's invoice but also append a special string and this renewal orders ID so that we can match it up as a failed renewal order payment later
             $paypal_args['invoice'] = self::$invoice_prefix . ltrim($order->get_order_number(), '#') . '-wcsfrp-' . $renewal_order->id;
             $paypal_args['custom'] = serialize(array($order->id, $order->order_key));
         }
         if ($order_contains_failed_renewal) {
             $sign_up_fee = 0;
             $initial_payment = $renewal_order->get_total();
             // Initial payment can be left in case the customer is purchased other products with the payment
             $subscription_trial_length = 0;
             $subscription_installments = max($subscription_installments - WC_Subscriptions_Manager::get_subscriptions_completed_payment_count(WC_Subscriptions_Manager::get_subscription_key($order_id, $product->id)), 0);
             // If we're changing the payment date or switching subs, we need to set the trial period to the next payment date & installments to be the number of installments left
         } elseif ($is_payment_change || $is_switch_order || $is_synced_subscription) {
             $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order_id, $product->id);
             // Give a free trial until the next payment date
             if ($is_switch_order) {
                 $next_payment_timestamp = get_post_meta($order->id, '_switched_subscription_first_payment_timestamp', true);
             } elseif ($is_synced_subscription) {
                 $next_payment_timestamp = WC_Subscriptions_Synchroniser::calculate_first_payment_date($product, 'timestamp');
             } else {
                 $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $order->user_id, 'timestamp');
             }
             // When the subscription is on hold
             if ($next_payment_timestamp != false && !empty($next_payment_timestamp)) {
                 $trial_until = self::calculate_trial_periods_until($next_payment_timestamp);
                 $subscription_trial_length = $trial_until['first_trial_length'];
                 $converted_periods['trial_period'] = $trial_until['first_trial_period'];
                 $second_trial_length = $trial_until['second_trial_length'];
                 $second_trial_period = $trial_until['second_trial_period'];
             } else {
                 $subscription_trial_length = 0;
             }
             // If is a payment change, we need to account for completed payments on the number of installments owing
             if ($is_payment_change && $subscription_length > 0) {
                 $subscription_installments -= WC_Subscriptions_Manager::get_subscriptions_completed_payment_count($subscription_key);
             }
         } else {
             $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order);
         }
         if ($subscription_trial_length > 0) {
             // Specify a free trial period
             if ($is_switch_order || $is_synced_subscription || $initial_payment != $sign_up_fee) {
                 $paypal_args['a1'] = $initial_payment > 0 ? $initial_payment : 0;
             } else {
                 $paypal_args['a1'] = $sign_up_fee > 0 ? $sign_up_fee : 0;
                 // Maybe add the sign up fee to the free trial period
             }
             // Trial period length
             $paypal_args['p1'] = $subscription_trial_length;
             // Trial period
             $paypal_args['t1'] = $converted_periods['trial_period'];
             // We need to use a second trial period before we have more than 90 days until the next payment
             if (isset($second_trial_length) && $second_trial_length > 0) {
                 $paypal_args['a2'] = 0.01;
                 // Alas, although it's undocumented, PayPal appears to require a non-zero value in order to allow a second trial period
                 $paypal_args['p2'] = $second_trial_length;
                 $paypal_args['t2'] = $second_trial_period;
             }
         } elseif ($sign_up_fee > 0 || $initial_payment != $price_per_period) {
             // No trial period, so charge sign up fee and per period price for the first period
             if ($subscription_installments == 1) {
                 $param_number = 3;
             } else {
                 $param_number = 1;
             }
             $paypal_args['a' . $param_number] = $initial_payment;
             // Sign Up interval
             $paypal_args['p' . $param_number] = $subscription_interval;
             // Sign Up unit of duration
             $paypal_args['t' . $param_number] = $converted_periods['billing_period'];
         }
         // We have a recurring payment
         if (!isset($param_number) || $param_number == 1) {
             // Subscription price
             $paypal_args['a3'] = $price_per_period;
             // Subscription duration
             $paypal_args['p3'] = $subscription_interval;
             // Subscription period
             $paypal_args['t3'] = $converted_periods['billing_period'];
         }
         // Recurring payments
         if ($subscription_installments == 1 || $sign_up_fee > 0 && $subscription_trial_length == 0 && $subscription_installments == 2) {
             // Non-recurring payments
             $paypal_args['src'] = 0;
         } else {
             $paypal_args['src'] = 1;
             if ($subscription_installments > 0) {
                 if ($sign_up_fee > 0 && $subscription_trial_length == 0) {
                     // An initial period is being used to charge a sign-up fee
                     $subscription_installments--;
                 }
                 $paypal_args['srt'] = $subscription_installments;
             }
         }
         // Don't reattempt failed payments, instead let Subscriptions handle the failed payment
         $paypal_args['sra'] = 0;
         // Force return URL so that order description & instructions display
         $paypal_args['rm'] = 2;
     }
     return $paypal_args;
 }
            ?>
" class="cancel" title="<?php 
            _e('Click to cancel this subscription', WC_Subscriptions::$text_domain);
            ?>
">(<?php 
            _e('Cancel', WC_Subscriptions::$text_domain);
            ?>
)</a>
				<?php 
        }
        ?>
				<?php 
        if (WC_Subscriptions_Renewal_Order::can_subscription_be_renewed($subscription_key, $user_id)) {
            ?>
				<a href="<?php 
            echo esc_url(WC_Subscriptions_Renewal_Order::get_users_renewal_link($subscription_key));
            ?>
" class="renew" title="<?php 
            _e('Click to renew this subscription', WC_Subscriptions::$text_domain);
            ?>
">(<?php 
            _e('Renew', WC_Subscriptions::$text_domain);
            ?>
)</a>
				<?php 
        }
        ?>
			</td>
			<td class="subscription-next-payment">
				<?php 
        $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $user_id, 'timestamp');
 /**
  * Outputs the content for each column.
  *
  * @param array $item A singular item (one full row's worth of data)
  * @param array $column_name The name/slug of the column to be processed
  * @return string Text or HTML to be placed inside the column <td>
  * @since 1.0
  */
 public function column_default($item, $column_name)
 {
     global $woocommerce;
     $current_gmt_time = gmdate('U');
     switch ($column_name) {
         case 'status':
             $actions = array();
             $action_url = add_query_arg(array('page' => $_REQUEST['page'], 'user' => $item['user_id'], 'subscription' => $item['subscription_key'], '_wpnonce' => wp_create_nonce($item['subscription_key'])));
             if (isset($_REQUEST['status'])) {
                 $action_url = add_query_arg(array('status' => $_REQUEST['status']), $action_url);
             }
             $order = new WC_Order($item['order_id']);
             $all_statuses = array('active' => __('Reactivate', WC_Subscriptions::$text_domain), 'on-hold' => __('Suspend', WC_Subscriptions::$text_domain), 'cancelled' => __('Cancel', WC_Subscriptions::$text_domain), 'trash' => __('Trash', WC_Subscriptions::$text_domain), 'deleted' => __('Delete Permanently', WC_Subscriptions::$text_domain));
             foreach ($all_statuses as $status => $label) {
                 if (WC_Subscriptions_Manager::can_subscription_be_changed_to($status, $item['subscription_key'], $item['user_id'])) {
                     $action = 'deleted' == $status ? 'delete' : $status;
                     // For built in CSS
                     $actions[$action] = sprintf('<a href="%s">%s</a>', add_query_arg('new_status', $status, $action_url), $label);
                 }
             }
             if ($item['status'] == 'pending') {
                 unset($actions['active']);
                 unset($actions['trash']);
             } elseif (!in_array($item['status'], array('cancelled', 'expired', 'suspended'))) {
                 unset($actions['trash']);
             }
             $actions = apply_filters('woocommerce_subscriptions_list_table_actions', $actions, $item);
             $column_content = sprintf('<mark class="%s">%s</mark> %s', sanitize_title($item[$column_name]), WC_Subscriptions_Manager::get_status_to_display($item[$column_name], $item['subscription_key'], $item['user_id']), $this->row_actions($actions));
             $column_content = apply_filters('woocommerce_subscriptions_list_table_column_status_content', $column_content, $item, $actions, $this);
             break;
         case 'title':
             //Return the title contents
             $column_content = sprintf('<a href="%s">%s</a>', get_edit_post_link($item['product_id']), WC_Subscriptions_Order::get_item_name($item['order_id'], $item['product_id']));
             $column_content .= sprintf('<input type="hidden" class="%1$s" name="%2$s[%3$s][%4$s][][%1$s]" value="%5$s" />', 'product_id', $this->_args['plural'], $item['user_id'], $item['subscription_key'], $item['product_id']);
             $order = new WC_Order($item['order_id']);
             $order_item = WC_Subscriptions_Order::get_item_by_product_id($order, $item['product_id']);
             $product = $order->get_product_from_item($order_item);
             if (isset($product->variation_data)) {
                 $column_content .= '<br />' . woocommerce_get_formatted_variation($product->variation_data, true);
             }
             break;
         case 'order_id':
             $order = new WC_Order($item[$column_name]);
             $column_content = sprintf('<a href="%1$s">%2$s</a>', get_edit_post_link($item[$column_name]), sprintf(__('Order %s', WC_Subscriptions::$text_domain), $order->get_order_number()));
             $column_content .= sprintf('<input type="hidden" class="%1$s" name="%2$s[%3$s][%4$s][][%1$s]" value="%5$s" />', $column_name, $this->_args['plural'], $item['user_id'], $item['subscription_key'], $item[$column_name]);
             break;
         case 'user':
             $user = get_user_by('id', $item['user_id']);
             $column_content = sprintf('<a href="%s">%s</a>', admin_url('user-edit.php?user_id=' . $user->ID), ucfirst($user->display_name));
             $column_content .= sprintf('<input type="hidden" class="%1$s" name="%2$s[%3$s][%4$s][][%1$s]" value="%5$s" />', 'user_id', $this->_args['plural'], $item['user_id'], $item['subscription_key'], $item['user_id']);
             break;
         case 'start_date':
         case 'expiry_date':
         case 'end_date':
             if ($column_name == 'expiry_date' && $item[$column_name] == 0) {
                 $column_content = __('Never', WC_Subscriptions::$text_domain);
             } else {
                 if ($column_name == 'end_date' && $item[$column_name] == 0) {
                     $column_content = __('Not yet ended', WC_Subscriptions::$text_domain);
                 } else {
                     $gmt_timestamp = strtotime($item[$column_name]);
                     $user_timestamp = $gmt_timestamp + get_option('gmt_offset') * 3600;
                     $column_content = sprintf('<time title="%s">%s</time>', esc_attr($gmt_timestamp), date_i18n(woocommerce_date_format(), $user_timestamp));
                 }
             }
             break;
         case 'trial_expiry_date':
             $trial_expiration = WC_Subscriptions_Manager::get_trial_expiration_date($item['subscription_key'], $item['user_id'], 'timestamp');
             if (empty($trial_expiration)) {
                 $column_content = '-';
             } else {
                 $column_content = sprintf('<time title="%s">%s</time>', esc_attr($trial_expiration), date_i18n(woocommerce_date_format(), $trial_expiration + get_option('gmt_offset') * 3600));
             }
             break;
         case 'last_payment_date':
             $last_payment_timestamp = strtotime($item['last_payment_date']);
             $time_diff = $current_gmt_time - $last_payment_timestamp;
             if ($time_diff > 0 && $time_diff < 7 * 24 * 60 * 60) {
                 $last_payment = sprintf(__('%s ago', WC_Subscriptions::$text_domain), human_time_diff($last_payment_timestamp, $current_gmt_time));
             } else {
                 $last_payment = date_i18n(woocommerce_date_format(), $last_payment_timestamp + get_option('gmt_offset') * 3600);
             }
             $column_content = sprintf('<time title="%s">%s</time>', esc_attr($last_payment_timestamp), $last_payment);
             break;
         case 'next_payment_date':
             $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($item['subscription_key'], $item['user_id'], 'timestamp');
             if ($next_payment_timestamp == 0) {
                 $column_content = '-';
             } else {
                 // Convert to site time
                 $time_diff = $next_payment_timestamp - $current_gmt_time;
                 if ($time_diff > 0 && $time_diff < 7 * 24 * 60 * 60) {
                     $next_payment = sprintf(__('In %s', WC_Subscriptions::$text_domain), human_time_diff($current_gmt_time, $next_payment_timestamp));
                 } else {
                     $next_payment = date_i18n(woocommerce_date_format(), $next_payment_timestamp + get_option('gmt_offset') * 3600);
                 }
                 $column_content = sprintf('<time class="next-payment-date" title="%s">%s</time>', esc_attr($next_payment_timestamp), $next_payment);
                 if (WC_Subscriptions_Manager::can_subscription_be_changed_to('new-payment-date', $item['subscription_key'], $item['user_id'])) {
                     $column_content .= '<div class="edit-date-div row-actions hide-if-no-js">';
                     $column_content .= '<img class="date-picker-icon" src="' . admin_url('images/date-button.gif') . '" title="Date Picker Icon"/>';
                     $column_content .= '<a href="#edit_timestamp" class="edit-timestamp" tabindex="4">' . __('Change', WC_Subscriptions::$text_domain) . '</a>';
                     $column_content .= '<div class="date-picker-div hide-if-js">';
                     $column_content .= WC_Subscriptions_Manager::touch_time(array('date' => date('Y-m-d', $next_payment_timestamp), 'echo' => false, 'multiple' => true, 'include_time' => false));
                     $column_content .= '</div>';
                     $column_content .= '</form>';
                 }
             }
             break;
         case 'renewal_order_count':
             $count = WC_Subscriptions_Renewal_Order::get_renewal_order_count($item['order_id']);
             $column_content = sprintf('<a href="%1$s">%2$d</a>', admin_url('edit.php?post_status=all&post_type=shop_order&_renewal_order_parent_id=' . absint($item['order_id'])), $count);
             break;
     }
     return $column_content;
 }
 /**
  * Check if a given order is a subscription renewal order
  * 
  * @param $order WC_Order | int The WC_Order object or ID of a WC_Order order.
  * @deprecated 1.2
  * @since 1.0
  */
 public static function is_renewal($order)
 {
     _deprecated_function(__CLASS__ . '::' . __FUNCTION__, '1.2', 'WC_Subscriptions_Renewal_Order::is_renewal( $order )');
     return WC_Subscriptions_Renewal_Order::is_renewal($order);
 }
 /**
  * Version 1.2 introduced child renewal orders to keep a record of each completed subscription
  * payment. Before 1.2, these orders did not exist, so this function creates them.
  *
  * @since 1.2
  */
 private static function generate_renewal_orders()
 {
     global $woocommerce, $wpdb;
     $subscriptions_grouped_by_user = WC_Subscriptions_Manager::get_all_users_subscriptions();
     // Don't send any order emails
     $email_actions = array('woocommerce_low_stock', 'woocommerce_no_stock', 'woocommerce_product_on_backorder', 'woocommerce_order_status_pending_to_processing', 'woocommerce_order_status_pending_to_completed', 'woocommerce_order_status_pending_to_on-hold', 'woocommerce_order_status_failed_to_processing', 'woocommerce_order_status_failed_to_completed', 'woocommerce_order_status_pending_to_processing', 'woocommerce_order_status_pending_to_on-hold', 'woocommerce_order_status_completed', 'woocommerce_new_customer_note');
     foreach ($email_actions as $action) {
         remove_action($action, array(&$woocommerce, 'send_transactional_email'));
     }
     remove_action('woocommerce_payment_complete', 'WC_Subscriptions_Renewal_Order::maybe_record_renewal_order_payment', 10, 1);
     foreach ($subscriptions_grouped_by_user as $user_id => $users_subscriptions) {
         foreach ($users_subscriptions as $subscription_key => $subscription) {
             $order_post = get_post($subscription['order_id']);
             if (isset($subscription['completed_payments']) && count($subscription['completed_payments']) > 0 && $order_post != null) {
                 foreach ($subscription['completed_payments'] as $payment_date) {
                     $existing_renewal_order = $wpdb->get_var($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_date_gmt = %s AND post_parent = %d AND post_type = 'shop_order'", $payment_date, $subscription['order_id']));
                     // If a renewal order exists on this date, don't generate another one
                     if (NULL !== $existing_renewal_order) {
                         continue;
                     }
                     $renewal_order_id = WC_Subscriptions_Renewal_Order::generate_renewal_order($subscription['order_id'], $subscription['product_id'], array('new_order_role' => 'child'));
                     if ($renewal_order_id) {
                         // Mark the order as paid
                         $renewal_order = new WC_Order($renewal_order_id);
                         $renewal_order->payment_complete();
                         // Avoid creating 100s "processing" orders
                         $renewal_order->update_status('completed');
                         // Set correct dates on the order
                         $renewal_order = array('ID' => $renewal_order_id, 'post_date' => $payment_date, 'post_date_gmt' => $payment_date);
                         wp_update_post($renewal_order);
                         update_post_meta($renewal_order_id, '_paid_date', $payment_date);
                         update_post_meta($renewal_order_id, '_completed_date', $payment_date);
                     }
                 }
             }
         }
     }
 }
Ejemplo n.º 13
0
function woo_ce_get_subscription_renewals( $order_id = 0 ) {

	$renewals = 0;
	// Check that get_renewal_order_count() exists within the WC_Subscriptions_Renewal_Order class
	if( method_exists( 'WC_Subscriptions_Renewal_Order', 'get_renewal_order_count' ) )
		$renewals = WC_Subscriptions_Renewal_Order::get_renewal_order_count( $order_id );
	return $renewals;

}
 /**
  * Registers the "Renewal Orders" meta box for the "Edit Order" page.
  */
 public static function add_meta_boxes()
 {
     global $current_screen, $post_id;
     // Only display the meta box if an order relates to a subscription
     if ('shop_order' == $current_screen->id) {
         $order_contains_subscription = WC_Subscriptions_Order::order_contains_subscription($post_id);
         if ($order_contains_subscription || WC_Subscriptions_Renewal_Order::is_renewal($post_id, array('order_role' => 'child'))) {
             add_meta_box('subscription_renewal_orders', __('Related Subscription Orders', 'woocommerce-subscriptions'), __CLASS__ . '::related_orders_meta_box', 'shop_order', 'normal', 'default');
         }
         if ($order_contains_subscription || 'add' == $current_screen->action) {
             if (!WC_Subscriptions::is_woocommerce_pre_2_2()) {
                 add_meta_box('woocommerce-order-totals', __('Recurring Totals', 'woocommerce-subscriptions'), __CLASS__ . '::recurring_totals_meta_box', 'shop_order', 'side', 'high');
             } else {
                 // WC 2.1 compatibility
                 add_filter('woocommerce_admin_order_totals_after_shipping', 'WC_Subscriptions_Order::recurring_order_totals_meta_box_section', 100, 1);
             }
         }
     }
 }
Ejemplo n.º 15
0
	<link itemprop="availability" href="http://schema.org/InStock">

	<?php 
    do_action('woocommerce_before_add_to_cart_form');
    ?>

	<?php 
    if (!$product->is_purchasable() && 0 != $user_id && 'no' != $product->limit_subscriptions && ('active' == $product->limit_subscriptions && WC_Subscriptions_Manager::user_has_subscription(0, $product->id, 'on-hold') || ($user_has_subscription = WC_Subscriptions_Manager::user_has_subscription($user_id, $product->id, $product->limit_subscriptions)))) {
        ?>
		<?php 
        if ('any' == $product->limit_subscriptions && $user_has_subscription && !WC_Subscriptions_Manager::user_has_subscription($user_id, $product->id, 'active') && !WC_Subscriptions_Manager::user_has_subscription($user_id, $product->id, 'on-hold')) {
            // customer has an inactive subscription, maybe offer the renewal button
            ?>
			<?php 
            $renewal_link = WC_Subscriptions_Renewal_Order::get_users_renewal_link_for_product($product->id);
            ?>
			<?php 
            if (!empty($renewal_link)) {
                ?>
				<a href="<?php 
                echo $renewal_link;
                ?>
" class="button product-renewal-link"><?php 
                _e('Renew', 'woocommerce-subscriptions');
                ?>
</a>
			<?php 
            }
            ?>
		<?php 
 /**
  * Check if a given order is a subscription renewal order
  *
  * @param WC_Order|int $order The WC_Order object or ID of a WC_Order order.
  * @deprecated 1.2
  * @since 1.0
  */
 public static function is_renewal($order)
 {
     _deprecated_function(__METHOD__, '1.2', 'WC_Subscriptions_Renewal_Order::is_renewal( $order )');
     return WC_Subscriptions_Renewal_Order::is_renewal($order);
 }
Ejemplo n.º 17
0
 /**
  * Returns the string key for a subscription purchased in an order specified by $order_id
  * 
  * @param order_id int The ID of the order in which the subscription was purchased. 
  * @param product_id int The ID of the subscription product.
  * @return string The key representing the given subscription.
  * @since 1.0
  */
 public static function get_subscription_key($order_id, $product_id = '')
 {
     // If we have a child renewal order, we need the parent order's ID
     if (WC_Subscriptions_Renewal_Order::is_renewal($order_id, array('order_role' => 'child'))) {
         $order_id = WC_Subscriptions_Renewal_Order::get_parent_order_id($order_id);
     }
     if (empty($product_id)) {
         $order = new WC_Order($order_id);
         $order_items = WC_Subscriptions_Order::get_recurring_items($order);
         $first_order_item = reset($order_items);
         $product_id = WC_Subscriptions_Order::get_items_product_id($first_order_item);
     }
     $subscription_key = $order_id . '_' . $product_id;
     return apply_filters('woocommerce_subscription_key', $subscription_key, $order_id, $product_id);
 }
 /**
  * Returns the string key for a subscription purchased in an order specified by $order_id
  * 
  * @param order_id int The ID of the order in which the subscription was purchased. 
  * @param product_id int The ID of the subscription product.
  * @return string The key representing the given subscription.
  * @since 1.0
  */
 public static function get_subscription_key($order_id, $product_id = '')
 {
     // If we have a child renewal order, we need the parent order's ID
     if (WC_Subscriptions_Renewal_Order::is_renewal($order_id, 'child')) {
         $order_id = WC_Subscriptions_Renewal_Order::get_parent_order_id($order_id);
     }
     if (empty($product_id)) {
         $order = new WC_Order($order_id);
         $order_items = $order->get_items();
         $product_id = $order_items[0]['id'];
     }
     $subscription_key = $order_id . '_' . $product_id;
     return apply_filters('woocommerce_subscription_key', $subscription_key, $order_id, $product_id);
 }
Ejemplo n.º 19
0
 /**
  * Activates a Klarna order for V2 API
  *
  * @since  2.0
  **/
 function activate_order($orderid)
 {
     $order = wc_get_order($orderid);
     if (get_post_meta($orderid, '_klarna_order_reservation', true) && get_post_meta($orderid, '_billing_country', true)) {
         // Check if this is a subscription order
         if (class_exists('WC_Subscriptions_Renewal_Order') && WC_Subscriptions_Renewal_Order::is_renewal($order)) {
             if (!get_post_meta($orderid, '_klarna_order_reservation_recurring', true)) {
                 return;
             }
         }
         $rno = get_post_meta($orderid, '_klarna_order_reservation', true);
         $country = get_post_meta($orderid, '_billing_country', true);
         $payment_method = get_post_meta($orderid, '_payment_method', true);
         $klarna = new Klarna();
         $this->configure_klarna($klarna, $country, $payment_method);
         try {
             $result = $klarna->activate($rno, null, KlarnaFlags::RSRV_SEND_BY_EMAIL);
             $risk = $result[0];
             // returns 'ok' or 'no_risk'
             $invNo = $result[1];
             // returns invoice number
             $order->add_order_note(sprintf(__('Klarna order activated. Invoice number %s - risk status %s.', 'woocommerce-gateway-klarna'), $invNo, $risk));
             update_post_meta($orderid, '_klarna_order_activated', time());
             update_post_meta($orderid, '_klarna_invoice_number', $invNo);
             update_post_meta($orderid, '_transaction_id', $invNo);
         } catch (Exception $e) {
             $order->add_order_note(sprintf(__('Klarna order activation failed. Error code %s. Error message %s', 'woocommerce-gateway-klarna'), $e->getCode(), utf8_encode($e->getMessage())));
         }
     }
 }
 /**
  * If no sort order set, default to title. If no sort order, default to descending.
  *
  * @since 1.0
  */
 function sort_subscriptions($a, $b)
 {
     $order_by = !empty($_REQUEST['orderby']) ? $_REQUEST['orderby'] : 'start_date';
     $order = !empty($_REQUEST['order']) ? $_REQUEST['order'] : 'desc';
     switch ($order_by) {
         case 'product_name':
             $product_name_a = get_the_title($a['product_id']);
             $product_name_b = get_the_title($b['product_id']);
             $result = strcasecmp($product_name_a, $product_name_b);
             break;
         case 'user':
             $user_a = get_user_by('id', $a['user_id']);
             $user_b = get_user_by('id', $b['user_id']);
             $result = strcasecmp($user_a->display_name, $user_b->display_name);
             break;
         case 'expiry_date':
             if ($order == 'asc') {
                 $result = self::sort_with_zero_at_end($a[$order_by], $b[$order_by]);
             } else {
                 $result = self::sort_with_zero_at_beginning($a[$order_by], $b[$order_by]);
             }
             break;
         case 'end_date':
             $result = self::sort_with_zero_at_end($a[$order_by], $b[$order_by]);
             // Display subscriptions that have not ended at the end of the list
             break;
         case 'next_payment_date':
             $next_payment_a = WC_Subscriptions_Manager::get_next_payment_date($a['subscription_key'], $a['user_id'], 'mysql');
             $next_payment_b = WC_Subscriptions_Manager::get_next_payment_date($b['subscription_key'], $b['user_id'], 'mysql');
             $result = self::sort_with_zero_at_end($next_payment_a, $next_payment_b);
             // Display subscriptions with no future payments at the end
             break;
         case 'last_payment_date':
             $last_payment_a = empty($a['completed_payments']) ? 0 : strtotime(array_pop($a['completed_payments']));
             $last_payment_b = empty($b['completed_payments']) ? 0 : strtotime(array_pop($b['completed_payments']));
             $result = self::sort_with_zero_at_end($last_payment_a, $last_payment_b);
             // Display subscriptions with no compelted payments at the end
             break;
         case 'trial_expiry_date':
             $trial_expiration_a = WC_Subscriptions_Manager::get_trial_expiration_date($a['subscription_key'], $a['user_id'], 'mysql');
             $trial_expiration_b = WC_Subscriptions_Manager::get_trial_expiration_date($b['subscription_key'], $b['user_id'], 'mysql');
             $result = self::sort_with_zero_at_end($trial_expiration_a, $trial_expiration_b);
             break;
         case 'renewal_order_count':
             $result = strcmp(WC_Subscriptions_Renewal_Order::get_renewal_order_count($a['order_id']), WC_Subscriptions_Renewal_Order::get_renewal_order_count($b['order_id']));
             break;
         case 'order_id':
             $result = strnatcmp($a[$order_by], $b[$order_by]);
             break;
         default:
             $result = strcmp($a[$order_by], $b[$order_by]);
             break;
     }
     return $order == 'asc' ? $result : -$result;
     // Send final sort direction to usort
 }
 /**
  * Loads the my-subscriptions.php template on the My Account page.
  *
  * @since 1.0
  */
 public static function get_my_subscriptions_template()
 {
     $subscriptions = WC_Subscriptions_Manager::get_users_subscriptions();
     $user_id = get_current_user_id();
     $all_actions = array();
     foreach ($subscriptions as $subscription_key => $subscription_details) {
         $actions = array();
         if ($subscription_details['status'] == 'trash') {
             unset($subscriptions[$subscription_key]);
             continue;
         }
         $admin_with_suspension_disallowed = current_user_can('manage_woocommerce') && 0 == get_option(WC_Subscriptions_Admin::$option_prefix . '_max_customer_suspensions', 0) ? true : false;
         if (WC_Subscriptions_Manager::can_subscription_be_changed_to('on-hold', $subscription_key, $user_id) && WC_Subscriptions_Manager::current_user_can_suspend_subscription($subscription_key) && !$admin_with_suspension_disallowed) {
             $actions['suspend'] = array('url' => WC_Subscriptions_Manager::get_users_change_status_link($subscription_key, 'on-hold'), 'name' => __('Suspend', 'woocommerce-subscriptions'));
         } elseif (WC_Subscriptions_Manager::can_subscription_be_changed_to('active', $subscription_key, $user_id) && !WC_Subscriptions_Manager::subscription_requires_payment($subscription_key, $user_id)) {
             $actions['reactivate'] = array('url' => WC_Subscriptions_Manager::get_users_change_status_link($subscription_key, 'active'), 'name' => __('Reactivate', 'woocommerce-subscriptions'));
         }
         if (WC_Subscriptions_Renewal_Order::can_subscription_be_renewed($subscription_key, $user_id)) {
             $actions['renew'] = array('url' => WC_Subscriptions_Renewal_Order::get_users_renewal_link($subscription_key), 'name' => __('Renew', 'woocommerce-subscriptions'));
         }
         $renewal_orders = WC_Subscriptions_Renewal_Order::get_renewal_orders($subscription_details['order_id'], 'ID');
         $last_order_id = end($renewal_orders);
         if ($last_order_id) {
             $renewal_order = new WC_Order($last_order_id);
             if (WC_Subscriptions_Manager::can_subscription_be_changed_to('active', $subscription_key, $user_id) && in_array($renewal_order->status, array('pending', 'failed')) && !is_numeric(get_post_meta($renewal_order->id, '_failed_order_replaced_by', true))) {
                 $actions['pay'] = array('url' => $renewal_order->get_checkout_payment_url(), 'name' => __('Pay', 'woocommerce-subscriptions'));
             }
         } else {
             // Check if the master order still needs to be paid
             $order = new WC_Order($subscription_details['order_id']);
             if ('pending' == $order->status && WC_Subscriptions_Manager::can_subscription_be_changed_to('active', $subscription_key, $user_id)) {
                 $actions['pay'] = array('url' => $order->get_checkout_payment_url(), 'name' => __('Pay', 'woocommerce-subscriptions'));
             }
         }
         if (WC_Subscriptions_Manager::can_subscription_be_changed_to('cancelled', $subscription_key, $user_id) && $subscription_details['interval'] != $subscription_details['length']) {
             $actions['cancel'] = array('url' => WC_Subscriptions_Manager::get_users_change_status_link($subscription_key, 'cancelled'), 'name' => __('Cancel', 'woocommerce-subscriptions'));
         }
         $all_actions[$subscription_key] = $actions;
     }
     $all_actions = apply_filters('woocommerce_my_account_my_subscriptions_actions', $all_actions, $subscriptions);
     woocommerce_get_template('myaccount/my-subscriptions.php', array('subscriptions' => $subscriptions, 'actions' => $all_actions, 'user_id' => $user_id), '', plugin_dir_path(__FILE__) . 'templates/');
 }
Ejemplo n.º 22
0
 /**
  * Outputs the contents of the "Renewal Orders" meta box.
  *
  * @param object $post Current post data.
  */
 public static function renewal_orders_meta_box($post)
 {
     $order = new WC_Order(absint($post->ID));
     if (WC_Subscriptions_Renewal_Order::is_renewal($order, array('order_role' => 'child'))) {
         $parent_id = WC_Subscriptions_Renewal_Order::get_parent_order_id($order);
     } else {
         if (WC_Subscriptions_Order::order_contains_subscription($order)) {
             $parent_id = $post->ID;
         }
     }
     //Find any renewal orders associated with this order.
     $items = get_posts(array('post_type' => $post->post_type, 'post_parent' => $parent_id, 'numberposts' => -1));
     if (WC_Subscriptions_Renewal_Order::is_renewal($order, array('order_role' => 'child'))) {
         $parent_order = new WC_Order($parent_id);
         printf('<p>%1$s <a href="%2$s">%3$s</a></p>', __('Initial Order:', WC_Subscriptions::$text_domain), get_edit_post_link($parent_id), $parent_order->get_order_number());
     }
     if (empty($items)) {
         printf(' <p class="renewal-subtitle">%s</p>', __('No renewal payments yet.', WC_Subscriptions::$text_domain));
     } else {
         printf('<p class="renewal-subtitle">%s</p>', __('Renewal Orders:', WC_Subscriptions::$text_domain));
         echo '<ul class="renewal-orders">';
         foreach ($items as $item) {
             $renewal_order = new WC_Order($item->ID);
             if ($item->ID == $post->ID) {
                 printf('<li><strong>%s</strong></li>', $renewal_order->get_order_number());
             } else {
                 printf('<li><a href="%1$s">%2$s</a></li>', get_edit_post_link($item->ID), $renewal_order->get_order_number());
             }
         }
         echo '</ul>';
     }
 }
 /**
  * If viewing a renewal order on the the Edit Order screen, set the available email actions for the order to use
  * renewal order emails, not core WooCommerce order emails.
  *
  * @param int $user_id The ID of the user who the subscription belongs to
  * @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
  * @return void
  */
 public static function renewal_order_emails_available($available_emails)
 {
     global $theorder;
     if (WC_Subscriptions_Renewal_Order::is_renewal($theorder->id, array('order_role' => 'child'))) {
         $available_emails = array('new_renewal_order', 'customer_processing_renewal_order', 'customer_completed_renewal_order', 'customer_renewal_invoice');
     }
     return $available_emails;
 }
 /**
  * Get PayPal Args for passing to PP
  *
  * Based on the HTML Variables documented here: https://developer.paypal.com/webapps/developer/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/#id08A6HI00JQU
  *
  * @param WC_Order $order
  * @return array
  */
 public static function get_paypal_args($paypal_args, $order)
 {
     $is_payment_change = WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment;
     $order_contains_failed_renewal = false;
     // Payment method changes act on the subscription not the original order
     if ($is_payment_change) {
         $subscriptions = array(wcs_get_subscription($order->id));
         $subscription = array_pop($subscriptions);
         $order = $subscription->order;
         // We need the subscription's total
         remove_filter('woocommerce_order_amount_total', 'WC_Subscriptions_Change_Payment_Gateway::maybe_zero_total', 11, 2);
     } else {
         // Otherwise the order is the $order
         if ($cart_item = wcs_cart_contains_failed_renewal_order_payment() || false !== WC_Subscriptions_Renewal_Order::get_failed_order_replaced_by($order->id)) {
             $subscriptions = wcs_get_subscriptions_for_renewal_order($order);
             $order_contains_failed_renewal = true;
         } else {
             $subscriptions = wcs_get_subscriptions_for_order($order);
         }
         // Only one subscription allowed per order with PayPal
         $subscription = array_pop($subscriptions);
     }
     if ($order_contains_failed_renewal || !empty($subscription) && $subscription->get_total() > 0 && 'yes' !== get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) {
         // It's a subscription
         $paypal_args['cmd'] = '_xclick-subscriptions';
         // Store the subscription ID in the args sent to PayPal so we can access them later
         $paypal_args['custom'] = wcs_json_encode(array('order_id' => $order->id, 'order_key' => $order->order_key, 'subscription_id' => $subscription->id, 'subscription_key' => $subscription->order_key));
         foreach ($subscription->get_items() as $item) {
             if ($item['qty'] > 1) {
                 $item_names[] = $item['qty'] . ' x ' . wcs_get_paypal_item_name($item['name']);
             } elseif ($item['qty'] > 0) {
                 $item_names[] = wcs_get_paypal_item_name($item['name']);
             }
         }
         // translators: 1$: subscription ID, 2$: order ID, 3$: names of items, comma separated
         $paypal_args['item_name'] = wcs_get_paypal_item_name(sprintf(_x('Subscription %1$s (Order %2$s) - %3$s', 'item name sent to paypal', 'woocommerce-subscriptions'), $subscription->get_order_number(), $order->get_order_number(), implode(', ', $item_names)));
         $unconverted_periods = array('billing_period' => $subscription->billing_period, 'trial_period' => $subscription->trial_period);
         $converted_periods = array();
         // Convert period strings into PayPay's format
         foreach ($unconverted_periods as $key => $period) {
             switch (strtolower($period)) {
                 case 'day':
                     $converted_periods[$key] = 'D';
                     break;
                 case 'week':
                     $converted_periods[$key] = 'W';
                     break;
                 case 'year':
                     $converted_periods[$key] = 'Y';
                     break;
                 case 'month':
                 default:
                     $converted_periods[$key] = 'M';
                     break;
             }
         }
         $price_per_period = $subscription->get_total();
         $subscription_interval = $subscription->billing_interval;
         $start_timestamp = $subscription->get_time('start');
         $trial_end_timestamp = $subscription->get_time('trial_end');
         $next_payment_timestamp = $subscription->get_time('next_payment');
         $is_synced_subscription = WC_Subscriptions_Synchroniser::subscription_contains_synced_product($subscription->id);
         if ($is_synced_subscription) {
             $length_from_timestamp = $next_payment_timestamp;
         } elseif ($trial_end_timestamp > 0) {
             $length_from_timestamp = $trial_end_timestamp;
         } else {
             $length_from_timestamp = $start_timestamp;
         }
         $subscription_length = wcs_estimate_periods_between($length_from_timestamp, $subscription->get_time('end'), $subscription->billing_period);
         $subscription_installments = $subscription_length / $subscription_interval;
         $initial_payment = $is_payment_change ? 0 : $order->get_total();
         if ($order_contains_failed_renewal || $is_payment_change) {
             if ($is_payment_change) {
                 // Add a nonce to the order ID to avoid "This invoice has already been paid" error when changing payment method to PayPal when it was previously PayPal
                 $suffix = '-wcscpm-' . wp_create_nonce();
             } else {
                 // Failed renewal order, append a descriptor and renewal order's ID
                 $suffix = '-wcsfrp-' . $order->id;
             }
             // Change the 'invoice' and the 'custom' values to be for the original order (if there is one)
             if (false === $subscription->order) {
                 // No original order so we need to use the subscriptions values instead
                 $order_number = ltrim($subscription->get_order_number(), _x('#', 'hash before the order number. Used as a character to remove from the actual order number', 'woocommerce-subscriptions')) . '-subscription';
                 $order_id_key = array('order_id' => $subscription->id, 'order_key' => $subscription->order_key);
             } else {
                 $order_number = ltrim($subscription->order->get_order_number(), _x('#', 'hash before the order number. Used as a character to remove from the actual order number', 'woocommerce-subscriptions'));
                 $order_id_key = array('order_id' => $subscription->order->id, 'order_key' => $subscription->order->order_key);
             }
             $order_details = false !== $subscription->order ? $subscription->order : $subscription;
             // Set the invoice details to the original order's invoice but also append a special string and this renewal orders ID so that we can match it up as a failed renewal order payment later
             $paypal_args['invoice'] = WCS_PayPal::get_option('invoice_prefix') . $order_number . $suffix;
             $paypal_args['custom'] = wcs_json_encode(array_merge($order_id_key, array('subscription_id' => $subscription->id, 'subscription_key' => $subscription->order_key)));
         }
         if ($order_contains_failed_renewal) {
             $subscription_trial_length = 0;
             $subscription_installments = max($subscription_installments - $subscription->get_completed_payment_count(), 0);
             // If we're changing the payment date or switching subs, we need to set the trial period to the next payment date & installments to be the number of installments left
         } elseif ($is_payment_change || $is_synced_subscription) {
             $next_payment_timestamp = $subscription->get_time('next_payment');
             // When the subscription is on hold
             if (false != $next_payment_timestamp && !empty($next_payment_timestamp)) {
                 $trial_until = wcs_calculate_paypal_trial_periods_until($next_payment_timestamp);
                 $subscription_trial_length = $trial_until['first_trial_length'];
                 $converted_periods['trial_period'] = $trial_until['first_trial_period'];
                 $second_trial_length = $trial_until['second_trial_length'];
                 $second_trial_period = $trial_until['second_trial_period'];
             } else {
                 $subscription_trial_length = 0;
             }
             // If this is a payment change, we need to account for completed payments on the number of installments owing
             if ($is_payment_change && $subscription_length > 0) {
                 $subscription_installments = max($subscription_installments - $subscription->get_completed_payment_count(), 0);
             }
         } else {
             $subscription_trial_length = wcs_estimate_periods_between($start_timestamp, $trial_end_timestamp, $subscription->trial_period);
         }
         if ($subscription_trial_length > 0) {
             // Specify a free trial period
             $paypal_args['a1'] = $initial_payment > 0 ? $initial_payment : 0;
             // Trial period length
             $paypal_args['p1'] = $subscription_trial_length;
             // Trial period
             $paypal_args['t1'] = $converted_periods['trial_period'];
             // We need to use a second trial period before we have more than 90 days until the next payment
             if (isset($second_trial_length) && $second_trial_length > 0) {
                 $paypal_args['a2'] = 0.01;
                 // Alas, although it's undocumented, PayPal appears to require a non-zero value in order to allow a second trial period
                 $paypal_args['p2'] = $second_trial_length;
                 $paypal_args['t2'] = $second_trial_period;
             }
         } elseif ($initial_payment != $price_per_period) {
             // No trial period, but initial amount includes a sign-up fee and/or other items, so charge it as a separate period
             if (1 == $subscription_installments) {
                 $param_number = 3;
             } else {
                 $param_number = 1;
             }
             $paypal_args['a' . $param_number] = $initial_payment;
             // Sign Up interval
             $paypal_args['p' . $param_number] = $subscription_interval;
             // Sign Up unit of duration
             $paypal_args['t' . $param_number] = $converted_periods['billing_period'];
         }
         // We have a recurring payment
         if (!isset($param_number) || 1 == $param_number) {
             // Subscription price
             $paypal_args['a3'] = $price_per_period;
             // Subscription duration
             $paypal_args['p3'] = $subscription_interval;
             // Subscription period
             $paypal_args['t3'] = $converted_periods['billing_period'];
         }
         // Recurring payments
         if (1 == $subscription_installments || $initial_payment != $price_per_period && 0 == $subscription_trial_length && 2 == $subscription_installments) {
             // Non-recurring payments
             $paypal_args['src'] = 0;
         } else {
             $paypal_args['src'] = 1;
             if ($subscription_installments > 0) {
                 // An initial period is being used to charge a sign-up fee
                 if ($initial_payment != $price_per_period && 0 == $subscription_trial_length) {
                     $subscription_installments--;
                 }
                 $paypal_args['srt'] = $subscription_installments;
             }
         }
         // Don't reattempt failed payments, instead let Subscriptions handle the failed payment
         $paypal_args['sra'] = 0;
         // Force return URL so that order description & instructions display
         $paypal_args['rm'] = 2;
         // Reattach the filter we removed earlier
         if ($is_payment_change) {
             add_filter('woocommerce_order_amount_total', 'WC_Subscriptions_Change_Payment_Gateway::maybe_zero_total', 11, 2);
         }
     }
     return $paypal_args;
 }
 /**
  * Returns the string key for a subscription purchased in an order specified by $order_id
  *
  * @param order_id int The ID of the order in which the subscription was purchased.
  * @param product_id int The ID of the subscription product.
  * @return string The key representing the given subscription.
  * @since 1.0
  */
 public static function get_subscription_key($order_id, $product_id = '')
 {
     _deprecated_function(__METHOD__, '2.0', 'wcs_get_old_subscription_key( WC_Subscription $subscription )');
     // If we have a child renewal order, we need the parent order's ID
     if (wcs_order_contains_renewal($order_id)) {
         $order_id = WC_Subscriptions_Renewal_Order::get_parent_order_id($order_id);
     }
     // Get the ID of the first order item in a subscription created by this order
     if (empty($product_id)) {
         $subscriptions = wcs_get_subscriptions_for_order($order_id, array('order_type' => 'parent'));
         foreach ($subscriptions as $subscription) {
             $subscription_items = $subscription->get_items();
             if (!empty($subscription_items)) {
                 break;
             }
         }
         if (!empty($subscription_items)) {
             $first_item = reset($subscription_items);
             $product_id = WC_Subscriptions_Order::get_items_product_id($first_item);
         } else {
             $product_id = '';
         }
     }
     $subscription_key = $order_id . '_' . $product_id;
     return apply_filters('woocommerce_subscription_key', $subscription_key, $order_id, $product_id);
 }
                if ('failed' == $payment_status) {
                    $subscription->payment_failed();
                } else {
                    $subscription->payment_complete();
                    $subscription->update_status('active');
                }
            }
        }
    }
    /**
     * Adds a renewal orders section to the Related Orders meta box displayed on subscription orders.
     *
     * @deprecated 2.0
     * @since 1.2
     */
    public static function renewal_orders_meta_box_section($order, $post)
    {
        _deprecated_function(__METHOD__, '2.0');
    }
    /**
     * Trigger a hook when a subscription suspended due to a failed renewal payment is reactivated
     *
     * @since 1.3
     */
    public static function trigger_processed_failed_renewal_order_payment_hook($user_id, $subscription_key)
    {
        _deprecated_function(__METHOD__, '2.0', __CLASS__ . '::maybe_record_subscription_payment( $order_id, $orders_old_status, $orders_new_status )');
    }
}
WC_Subscriptions_Renewal_Order::init();
Ejemplo n.º 27
0
 /**
  * Processing Order
  *
  * @param WC_Order|int $order The WC_Order object or ID of a WC_Order order.
  * @deprecated 1.2
  * @since 1.0
  */
 public static function send_customer_renewal_order_email($order)
 {
     _deprecated_function(__METHOD__, '1.2', 'WC_Subscriptions_Renewal_Order::send_customer_renewal_order_email( $order )');
     WC_Subscriptions_Renewal_Order::send_customer_renewal_order_email($order);
 }
 /**
  * Check if order contains subscriptions.
  *
  * @param  int $order_id
  * @return bool
  */
 protected function order_contains_subscription($order_id)
 {
     return class_exists('WC_Subscriptions_Order') && (WC_Subscriptions_Order::order_contains_subscription($order_id) || WC_Subscriptions_Renewal_Order::is_renewal($order_id));
 }