/** * Updates other subscription sources. */ protected function save_source($order, $source) { parent::save_source($order, $source); // Also store it on the subscriptions being purchased or paid for in the order if (wcs_order_contains_subscription($order->id)) { $subscriptions = wcs_get_subscriptions_for_order($order->id); } elseif (wcs_order_contains_renewal($order->id)) { $subscriptions = wcs_get_subscriptions_for_renewal_order($order->id); } else { $subscriptions = array(); } foreach ($subscriptions as $subscription) { update_post_meta($subscription->id, '_stripe_customer_id', $source->customer); update_post_meta($subscription->id, '_stripe_card_id', $source->source); } }
/** * Setup the cart for paying for a delayed initial payment for a subscription. * * @since 2.0 */ public function maybe_setup_cart() { global $wp; if (isset($_GET['pay_for_order']) && isset($_GET['key']) && isset($wp->query_vars['order-pay'])) { // Pay for existing order $order_key = $_GET['key']; $order_id = isset($wp->query_vars['order-pay']) ? $wp->query_vars['order-pay'] : absint($_GET['order_id']); $order = wc_get_order($wp->query_vars['order-pay']); if ($order->order_key == $order_key && $order->has_status(array('pending', 'failed')) && !wcs_order_contains_renewal($order)) { $subscriptions = wcs_get_subscriptions_for_order($order, array('order_type' => 'parent')); if (get_current_user_id() !== $order->get_user_id()) { wc_add_notice(__('That doesn\'t appear to be your order.', 'woocommerce-subscriptions'), 'error'); wp_safe_redirect(get_permalink(wc_get_page_id('myaccount'))); exit; } elseif (!empty($subscriptions)) { // Setup cart with all the original order's line items $this->setup_cart($order, array()); WC()->session->set('order_awaiting_payment', $order_id); wp_safe_redirect(WC()->cart->get_checkout_url()); exit; } } } }
/** * 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 (wcs_order_contains_renewal($theorder->id)) { $available_emails = array('new_renewal_order', 'customer_processing_renewal_order', 'customer_completed_renewal_order', 'customer_renewal_invoice'); } return $available_emails; }
/** * Check if order contains subscriptions. * * @param int $order_id * @return bool */ protected function order_contains_subscription($order_id) { return function_exists('wcs_order_contains_subscription') && (wcs_order_contains_subscription($order_id) || wcs_order_contains_renewal($order_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 = '') { _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 the payment for a renewal order has previously failed and is then paid, we need to make sure the * subscription payment function is called. * * @param int $user_id The id of the user who purchased the subscription * @param string $subscription_key A subscription key of the form created by @see WC_Subscriptions_Manager::get_subscription_key() * @since 1.2 * @deprecated 2.0 */ public static function process_subscription_payment_on_child_order($order_id, $payment_status = 'completed') { _deprecated_function(__METHOD__, '2.0'); if (wcs_order_contains_renewal($order_id)) { $subscriptions = wcs_get_subscriptions_for_renewal_order($order_id); foreach ($subscriptions as $subscription) { if ('failed' == $payment_status) { $subscription->payment_failed(); } else { $subscription->payment_complete(); $subscription->update_status('active'); } } } }
/** * Records the initial payment against a subscription. * * This function is called when a gateway calls @see WC_Order::payment_complete() and payment * is completed on an order. It is also called when an orders status is changed to completed or * processing for those gateways which never call @see WC_Order::payment_complete(), like the * core WooCommerce Cheque and Bank Transfer gateways. * * It will also set the start date on the subscription to the time the payment is completed. * * @param WC_Order|int $order A WC_Order object or ID of a WC_Order order. * @since 1.1.2 * @deprecated 2.0 */ public static function maybe_record_order_payment($order) { _deprecated_function(__METHOD__, '2.0', __CLASS__ . 'maybe_record_subscription_payment::( $order, $old_status, $new_status )'); if (!wcs_order_contains_renewal($order)) { $subscriptions = wcs_get_subscriptions_for_order($order, array('order_type' => 'parent')); foreach ($subscriptions as $subscription_id => $subscription) { // No payments have been recorded yet if (0 == $subscription->get_completed_payment_count()) { $subscription->update_dates(array('start' => current_time('mysql', true))); $subscription->payment_complete(); } } } }
/** * When a failed renewal order is being paid for via checkout, make sure WC_Checkout::create_order() preserves its * status as 'failed' until it is paid. By default, it will always set it to 'pending', but we need it left as 'failed' * so that we can correctly identify the status change in @see self::maybe_change_subscription_status(). * * @param string Default order status for orders paid for via checkout. Default 'pending' * @since 2.0 */ public function maybe_preserve_order_status($order_status) { if (null !== WC()->session) { $order_id = absint(WC()->session->order_awaiting_payment); if ($order_id > 0 && ($order = wc_get_order($order_id)) && wcs_order_contains_renewal($order) && $order->has_status('failed')) { $order_status = 'failed'; } } return $order_status; }
/** * When a payment fails, either for the original purchase or a renewal payment, this function processes it. * * @since 2.0 */ public function payment_failed($new_status = 'on-hold') { // Make sure the last order's status is set to failed $last_order = $this->get_last_order('all', 'any'); if (false !== $last_order && false === $last_order->has_status('failed')) { remove_filter('woocommerce_order_status_changed', 'WC_Subscriptions_Renewal_Order::maybe_record_subscription_payment'); $last_order->update_status('failed'); add_filter('woocommerce_order_status_changed', 'WC_Subscriptions_Renewal_Order::maybe_record_subscription_payment', 10, 3); } // Log payment failure on order $this->add_order_note(__('Payment failed.', 'woocommerce-subscriptions')); // Allow a short circuit for plugins & payment gateways to force max failed payments exceeded if ('cancelled' == $new_status || apply_filters('woocommerce_subscription_max_failed_payments_exceeded', false, $this)) { $this->update_status('cancelled', __('Subscription Cancelled: maximum number of failed payments reached.', 'woocommerce-subscriptions')); } else { $this->update_status($new_status); } do_action('woocommerce_subscription_payment_failed', $this, $new_status); if (false !== $last_order && wcs_order_contains_renewal($last_order)) { do_action('woocommerce_subscription_renewal_payment_failed', $this); } }
/** * Check if the order has a subscription (either according to Subscriptions 1.5 or 2.0) * * @param string $order_id The ID of the order to check * @return mixed Either 1 (Subscriptions 1.5), 2 (Subscriptions 2) or false (no order) */ function order_has_subscription($order_id) { // Subscriptions not loaded if (!class_exists('WC_Subscriptions_Order')) return false; // Subscriptions v2.0 if (function_exists('wcs_order_contains_subscription')) { if (wcs_order_contains_subscription($order_id) || wcs_order_contains_renewal( $order_id ) || ( function_exists( 'wcs_is_subscription' ) && wcs_is_subscription( $order_id ))) { return 2; } else { return false; } } // Subscriptions v1.5 if (WC_Subscriptions_Order::order_contains_subscription($order_id)) { return 1; } return false; }
/** * Checks an order to see if it contains a subscription. * * @param mixed $order A WC_Order object or the ID of the order which the subscription was purchased in. * @param array|string $order_type Can include 'parent', 'renewal', 'resubscribe' and/or 'switch'. Defaults to 'parent'. * @return bool True if the order contains a subscription that belongs to any of the given order types, otherwise false. * @since 2.0 */ function wcs_order_contains_subscription($order, $order_type = array('parent', 'resubscribe', 'switch')) { // Accept either an array or string (to make it more convenient for singular types, like 'parent' or 'any') if (!is_array($order_type)) { $order_type = array($order_type); } if (!is_object($order)) { $order = new WC_Order($order); } $contains_subscription = false; $get_all = in_array('any', $order_type) ? true : false; if ((in_array('parent', $order_type) || $get_all) && count(wcs_get_subscriptions_for_order($order->id, array('order_type' => 'parent'))) > 0) { $contains_subscription = true; } elseif ((in_array('renewal', $order_type) || $get_all) && wcs_order_contains_renewal($order)) { $contains_subscription = true; } elseif ((in_array('resubscribe', $order_type) || $get_all) && wcs_order_contains_resubscribe($order)) { $contains_subscription = true; } elseif ((in_array('switch', $order_type) || $get_all) && wcs_order_contains_switch($order)) { $contains_subscription = true; } return $contains_subscription; }
/** * Process the payment * * @param int $order_id * @return array */ public function process_payment($order_id, $retry = true) { // Processing subscription if (function_exists('wcs_order_contains_subscription') && (wcs_order_contains_subscription($order_id) || wcs_is_subscription($order_id) || wcs_order_contains_renewal($order_id))) { return $this->process_subscription($order_id, $retry); // Processing pre-order } elseif (class_exists('WC_Pre_Orders_Order') && WC_Pre_Orders_Order::order_contains_pre_order($order_id)) { return $this->process_pre_order($order_id, $retry); // Processing regular product } else { return parent::process_payment($order_id, $retry); } }