/** * Add a 'new-payment-method' handler to the @see WC_Subscriptions_Manager::can_subscription_be_changed_to() function * to determine whether the recurring payment method on a subscription can be changed. * * For the recurring payment method to be changeable, the subscription must be active, have future (automatic) payments * and use a payment gateway which allows the subscription to be cancelled. * * @param bool $subscription_can_be_changed Flag of whether the subscription can be changed to * @param string $new_status_or_meta The status or meta data you want to change th subscription to. Can be 'active', 'on-hold', 'cancelled', 'expired', 'trash', 'deleted', 'failed', 'new-payment-date' or some other value attached to the 'woocommerce_can_subscription_be_changed_to' filter. * @param object $args Set of values used in @see WC_Subscriptions_Manager::can_subscription_be_changed_to() for determining if a subscription can be changes, include: * 'subscription_key' string A subscription key of the form created by @see WC_Subscriptions_Manager::get_subscription_key() * 'subscription' array Subscription of the form returned by @see WC_Subscriptions_Manager::get_subscription() * 'user_id' int The ID of the subscriber. * 'order' WC_Order The order which recorded the successful payment (to make up for the failed automatic payment). * 'payment_gateway' WC_Payment_Gateway The subscription's recurring payment gateway * 'order_uses_manual_payments' bool A boolean flag indicating whether the subscription requires manual renewal payment. * @since 1.4 */ public static function can_subscription_be_changed_to($subscription_can_be_changed, $new_status_or_meta, $args) { global $woocommerce; if ('new-payment-method' === $new_status_or_meta) { $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($args->subscription_key, '', 'timestamp'); // Check if any payment gateway supports recurring payment method changes $one_gateway_supports_changes = false; foreach ($woocommerce->payment_gateways->get_available_payment_gateways() as $gateway) { if ($gateway->supports('subscription_payment_method_change')) { $one_gateway_supports_changes = true; break; } } if ($one_gateway_supports_changes && 0 !== $next_payment_timestamp && false === $args->order_uses_manual_payments && $args->payment_gateway->supports('subscription_cancellation') && 'active' == $args->subscription['status']) { $subscription_can_be_changed = true; } else { $subscription_can_be_changed = false; } } return $subscription_can_be_changed; }
?> </td> <td class="subscription-status" style="text-align:left; white-space:nowrap;" data-title="<?php _e('Status', 'woocommerce-subscriptions'); ?> "> <?php echo WC_Subscriptions_Manager::get_status_to_display($subscription_details['status'], $subscription_key, $user_id); ?> </td> <td class="subscription-next-payment" data-title="<?php _e('Next Payment', 'woocommerce-subscriptions'); ?> "> <?php $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $user_id, 'timestamp'); ?> <?php if ($next_payment_timestamp == 0) { ?> - <?php } else { ?> <?php $time_diff = $next_payment_timestamp - gmdate('U'); ?> <?php if ($time_diff > 0 && $time_diff < 7 * 24 * 60 * 60) { ?> <?php
/** * When a subscription switch is added to the cart, store a record of pertinent meta about the switch. * * @since 1.4 */ public static function set_switch_details_in_cart($cart_item_data, $product_id, $variation_id) { if (!isset($_GET['switch-subscription'])) { return $cart_item_data; } $subscription = WC_Subscriptions_Manager::get_subscription($_GET['switch-subscription']); $product = get_product($subscription['product_id']); $child_products = 0 !== $product->post->post_parent ? get_product($product->post->post_parent)->get_children() : array(); if ($product_id != $subscription['product_id'] && !in_array($subscription['product_id'], $child_products)) { return $cart_item_data; } $cart_item_data['subscription_switch'] = array('subscription_key' => $_GET['switch-subscription'], 'next_payment_timestamp' => WC_Subscriptions_Manager::get_next_payment_date($_GET['switch-subscription'], get_current_user_id(), 'timestamp'), 'upgraded_or_downgraded' => ''); return $cart_item_data; }
/** * 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 }
/** * Display subscription columns in my memberships section * * @since 1.0.0 * @param WC_Memberships_User_Membership $user_membership */ public function output_subscription_columns(WC_Memberships_User_Membership $user_membership) { $subscription = $this->get_user_membership_subscription($user_membership->get_id()); if (!$this->is_subscriptions_gte_2_0()) { $subscription_key = $this->get_user_membership_subscription_key($user_membership->get_id()); } if ($subscription && in_array($user_membership->get_status(), array('active', 'free_trial'))) { $next_payment = $this->is_subscriptions_gte_2_0() ? $subscription->get_time('next_payment') : WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $user_membership->get_user_id(), 'timestamp'); } ?> <td class="membership-membership-next-bill-on" data-title="<?php esc_attr_e('Next Bill On', WC_Memberships::TEXT_DOMAIN); ?> "> <?php if ($subscription && !empty($next_payment)) { ?> <?php echo date_i18n(get_option('date_format'), $next_payment); ?> <?php } else { ?> <?php _e('N/A', WC_Memberships::TEXT_DOMAIN); ?> <?php } ?> </td> <?php }
/** * Takes a subscription product's ID and the order it was purchased in and returns the date on * which the next payment is due. * * A convenience wrapper for @see WC_Subscriptions_Manager::get_next_payment_date() to get the next * payment date for a subscription when all you have is the order and product. * * @param mixed $order A WC_Order object or the ID of the order which the subscription was purchased in. * @param int $product_id The product/post ID of the subscription * @param mixed $deprecated Never used. * @return mixed If no more payments are due, returns 0, otherwise it returns the MySQL formatted date/time string for the next payment date. * @version 1.2 * @since 1.0 */ public static function get_next_payment_date($order, $product_id, $deprecated = null) { if (null != $deprecated) { // We want to calculate a date _deprecated_argument(__CLASS__ . '::' . __FUNCTION__, '1.2'); $next_payment_date = self::calculate_next_payment_date($order, $product_id, 'mysql', $deprecated); } else { if (!is_object($order)) { $order = new WC_Order($order); } $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order->id, $product_id); $next_payment_date = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $order->user_id, 'mysql'); } return $next_payment_date; }
/** * Change the send date of the email for 'before_renewal' and 'before_expire' triggers * @param array $insert * @param FUE_Email $email * @return array */ public function modify_insert_send_date($insert, $email) { if ($email->type != 'subscription') { return $insert; } $order_id = $insert['order_id']; $order = WC_FUE_Compatibility::wc_get_order($order_id); if (!WC_Subscriptions_Order::order_contains_subscription($order)) { return $insert; } $subs_key = WC_Subscriptions_Manager::get_subscription_key($order_id); if ($email->trigger == 'subs_before_renewal') { $renewal_date = WC_Subscriptions_Manager::get_next_payment_date($subs_key); if (!$renewal_date) { // return false to tell FUE to skip importing this email/order return false; } // convert to local time $local_renewal_date = get_date_from_gmt($renewal_date, 'U'); $add = FUE_Sending_Scheduler::get_time_to_add($email->interval, $email->duration); $insert['send_on'] = $local_renewal_date - $add; } elseif ($email->trigger == 'subs_before_expire') { $expiry_date = WC_Subscriptions_Manager::get_subscription_expiration_date($subs_key); if (!$expiry_date) { return false; } // convert to local time $expiry_timestamp = get_date_from_gmt($expiry_date, 'U'); $add = FUE_Sending_Scheduler::get_time_to_add($email->interval, $email->duration); $insert['send_on'] = $expiry_timestamp - $add; } // Add the subscription key if it is not present in the meta if (!isset($insert['meta']) || empty($insert['meta']['subs_key'])) { $insert['meta']['subs_key'] = $subs_key; } return $insert; }
/** * Override the default PayPal standard args in WooCommerce for subscription purchases. * * 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)); if (WC_Subscriptions_Order::order_contains_subscription($order_id) && 'yes' !== get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) { $order = new WC_Order($order_id); $order_items = $order->get_items(); // Only one subscription allowed in the cart when PayPal Standard is active $product = $order->get_product_from_item(array_pop($order_items)); // 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 ' . $item['name']; } else { if ($item['qty'] > 0) { $item_names[] = $item['name']; } } } $paypal_args['item_name'] = sprintf(__('Order %s', WC_Subscriptions::$text_domain), $order->get_order_number()); } else { $paypal_args['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); $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(); // Set a flag on the order if changing from PayPal *to* PayPal to prevent incorrectly cancelling the subscription if ('paypal' == $order->recurring_payment_method) { add_post_meta($order_id, '_wcs_changing_payment_from_paypal_to_paypal', 'true', true); } } // 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 if ($is_payment_change || $is_switch_order) { $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order_id, $product->id); // Give a free trial until the next payment date $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) { $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']; } // 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) { $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 (WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment && $second_trial_length > 0) { $paypal_args['a2'] = 0; $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; }
/** * When a subscription switch is added to the cart, store a record of pertinent meta about the switch. * * @since 1.4 */ public static function set_switch_details_in_cart($cart_item_data, $product_id, $variation_id) { global $woocommerce; if (!isset($_GET['switch-subscription'])) { return $cart_item_data; } $subscription = WC_Subscriptions_Manager::get_subscription($_GET['switch-subscription']); // Requesting a switch for someone elses subscription if (!WC_Subscriptions_Manager::user_owns_subscription($_GET['switch-subscription'])) { WC_Subscriptions::add_notice(__('You can not switch this subscription. It appears you do not own the subscription.', 'woocommerce-subscriptions'), 'error'); $woocommerce->cart->empty_cart(true); wp_redirect(get_permalink($subscription['product_id'])); exit; } // Else it's a valid switch $product = get_product($subscription['product_id']); $child_products = 0 !== $product->post->post_parent ? get_product($product->post->post_parent)->get_children() : array(); if ($product_id != $subscription['product_id'] && !in_array($subscription['product_id'], $child_products)) { return $cart_item_data; } $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($_GET['switch-subscription'], get_current_user_id(), 'timestamp'); // If there are no more payments due on the subscription, because we're in the last billing period, we need to use the subscription's expiration date, not next payment date if (false == $next_payment_timestamp && WC_Subscriptions_Manager::get_subscriptions_completed_payment_count($_GET['switch-subscription']) >= WC_Subscriptions_Order::get_subscription_length($subscription['order_id'], $subscription['product_id'])) { $next_payment_timestamp = WC_Subscriptions_Manager::get_subscription_expiration_date($_GET['switch-subscription'], get_current_user_id(), 'timestamp'); } $cart_item_data['subscription_switch'] = array('subscription_key' => $_GET['switch-subscription'], 'next_payment_timestamp' => $next_payment_timestamp, 'upgraded_or_downgraded' => ''); return $cart_item_data; }
/** * 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; }
/** * 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; }
function blendercloud_api($atts) { $user_data = array('shop_id' => '0', 'cloud_access' => 0, 'expiration_date' => '1970-01-01 00:00:00'); $last_expiration_date = new DateTime('1970-01-01 00:00:00'); // map blenderid to userid $args = array('search' => $_GET['blenderid'], 'search_columns' => array('user_login')); $user_query = new WP_User_Query($args); // Get the results from the query, returning the first user $users = $user_query->get_results(); if (!empty($users)) { $user_id = $users[0]->ID; $user_data['shop_id'] = $user_id; // process simple products (prepaid subscriptions) $order_ids = bo_get_all_user_orders($user_id, 'completed'); foreach ($order_ids as $order_id) { $order = new WC_Order($order_id); $order_date = $order->order_date; $items = $order->get_items(); foreach ($items as $item) { $tmp = bo_empty_subscription_line(); $product_id = $item['product_id']; $product = get_product($product_id); $sku = $product->get_sku(); $expiry_date = new DateTime($order_date); $tmp['sku'] = $sku; switch ($sku) { case 'cloud-prepaid-3': case 'cloud-prepaid-3-renewal': $expiry_date->modify('+3 month'); break; case 'cloud-prepaid-18': $expiry_date->modify('+18 month'); break; default: continue 2; // skip to next product } $tmp['expiration_date'] = $expiry_date->format('Y-m-d H:i:s'); $tmp['subscription_status'] = 'prepaid'; $now = new DateTime("now"); if ($expiry_date > $now) { $tmp['cloud_access'] = 1; } if ($expiry_date > $last_expiration_date) { $last_expiration_date = $expiry_date; } $user_data['subscriptions'][] = $tmp; } } // process recurring subscriptions $subscriptions = WC_Subscriptions_Manager::get_users_subscriptions($user_id); if (!empty($subscriptions)) { // iterate over all subscriptions. foreach ($subscriptions as $subscription_details) { if ($subscription_details['status'] != 'trash') { $order_id = $subscription_details['order_id']; $product_id = $subscription_details['product_id']; $order = new WC_Order($order_id); // print_r($order); // $next_payment_date = WC_Subscriptions_Manager::get_next_payment_date( $subscription_key, $user_id, 'mysql' ); $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order_id, $product_id); if ($subscription_details['expiry_date'] == 0 && !in_array($subscription_details['status'], array('cancelled', 'switched'))) { $end_time = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $user_id, 'mysql'); $end_timestamp = strtotime($end_time); } else { if (in_array($subscription_details['status'], array('cancelled', 'switched'))) { $end_of_prepaid_term = wc_next_scheduled_action('scheduled_subscription_end_of_prepaid_term', array('user_id' => (int) $user_id, 'subscription_key' => $subscription_key)); if (false === $end_of_prepaid_term) { $end_timestamp = strtotime($subscription_details['end_date']); } else { $end_timestamp = $end_of_prepaid_term; } } else { $end_timestamp = strtotime($subscription_details['expiry_date']); } } // if( $users[0]->data->user_email == '*****@*****.**' ) { // print_r($subscription_details); // } if ($subscription_details['status'] == 'cancelled') { $end_timestamp = strtotime($subscription_details['trial_expiry_date']); } if ($subscription_details['status'] == 'on-hold') { $end_timestamp = strtotime($subscription_details['last_payment_date']); } $end_time = date("Y-m-d H:i:s", $end_timestamp); $product = get_product($product_id); $sku = $product->get_sku(); $tmp = bo_empty_subscription_line(); $tmp['expiration_date'] = $end_time; $tmp['subscription_status'] = $subscription_details['status']; $expiry_date = new DateTime($end_time); if ($expiry_date > $last_expiration_date) { $last_expiration_date = $expiry_date; } $now = new DateTime("now"); $tmp['cloud_access'] = $expiry_date > $now ? 1 : 0; $tmp['sku'] = $sku; // if order is refunded, stop access if ($order->status == 'refunded') { $tmp['expiration_date'] = $end_time; $tmp['subscription_status'] = 'refunded'; $tmp['cloud_access'] = 0; } switch ($sku) { case 'cloud-subscription-1-renewal': case 'cloud-subscription-3': //$tmp['failed_payments'] = $subscription['failed_payments']; break; case 'cloud-subscription-team': // purchased team size $variation_id = $subscription_details['variation_id']; // find variation info from order to pass on # of seats $order = new WC_Order($order_id); $items = $order->get_items(); $team_members = 0; foreach ($items as $item) { // does product variation id match the current subscription? if ($item['item_meta']['_variation_id'][0] == $variation_id) { $team_members = $item['item_meta']['pa_team-size'][0]; } } $tmp['team_members'] = $team_members; break; } $user_data['subscriptions'][] = $tmp; } } } } // add one grace day to expiration $last_expiration_date->add(DateInterval::createfromdatestring('+1 day')); $user_data['expiration_date'] = $last_expiration_date->format('Y-m-d H:i:s'); $now = new DateTime("now"); if ($last_expiration_date > $now) { $user_data['cloud_access'] = 1; } //echo "<pre>";print_r($user_data); echo json_encode($user_data, JSON_PRETTY_PRINT); die; }
function woo_ce_get_subscription_next_payment( $subscription_key = '', $user_id = 0 ) { $next_payment = '-'; // Check that get_next_payment_date() exists within the WC_Subscriptions_Manager class if( method_exists( 'WC_Subscriptions_Manager', 'get_next_payment_date' ) ) { // Check that $subscription_key and $user_id aren't empty if( $subscription_key && !empty( $user_id ) ) { if( $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date( $subscription_key, $user_id, 'timestamp' ) ) { // Date formatting for Next Payment is provided by WooCommerce Subscriptions $time_diff = $next_payment_timestamp - gmdate( 'U' ); if( $time_diff > 0 && $time_diff < 7 * 24 * 60 * 60 ) $next_payment = sprintf( __( 'In %s', 'woocommerce-subscriptions' ), human_time_diff( $next_payment_timestamp ) ); else $next_payment = date_i18n( woocommerce_date_format(), $next_payment_timestamp ); } } } return $next_payment; }