/** * Takes a subscription key and calculates the date on which the subscription is scheduled to expire * or 0 if it will never expire. * * @param $subscription_key string A subscription key of the form created by @see self::get_subscription_key() * @param $user_id int The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance. * @param $type string (optional) The format for the Either 'mysql' or 'timestamp'. * @since 1.1 */ public static function calculate_trial_expiration_date($subscription_key, $user_id = '', $type = 'mysql') { $subscription = self::get_subscription($subscription_key, $user_id); if (empty($subscription)) { $expiration_date = 0; } else { $order = new WC_Order($subscription['order_id']); $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order, $subscription['product_id']); $subscription_trial_period = WC_Subscriptions_Order::get_subscription_trial_period($order, $subscription['product_id']); if ($subscription_trial_length > 0) { if (isset($subscription['start_date']) && !empty($subscription['start_date'])) { $start_date = $subscription['start_date']; } elseif (!empty($order->order_date)) { $start_date = get_gmt_from_date($order->order_date); } else { $start_date = gmdate('Y-m-d H:i:s'); } if ('month' == $subscription_trial_period) { $expiration_date = WC_Subscriptions::add_months(strtotime($start_date), $subscription_trial_length); } else { // Safe to just add the billing periods $expiration_date = strtotime("+ {$subscription_trial_length} {$subscription_trial_period}", strtotime($start_date)); } } else { $expiration_date = 0; } } $expiration_date = 'mysql' == $type && 0 != $expiration_date ? date('Y-m-d H:i:s', $expiration_date) : $expiration_date; return apply_filters('woocommerce_subscription_calculated_trial_expiration_date', $expiration_date, $subscription_key, $user_id); }
/** * Filters WC_Subscriptions_Order::get_sign_up_fee() to make sure the sign-up fee for a subscription product * that is synchronised is returned correctly. * * @param float The initial sign-up fee charged when the subscription product in the order was first purchased, if any. * @param mixed $order A WC_Order object or the ID of the order which the subscription was purchased in. * @param int $product_id The post ID of the subscription WC_Product object purchased in the order. Defaults to the ID of the first product purchased in the order. * @return float The initial sign-up fee charged when the subscription product in the order was first purchased, if any. * @since 1.5.3 */ public static function get_sign_up_fee($sign_up_fee, $order, $product_id, $non_subscription_total) { if (self::order_contains_synced_subscription($order->id) && WC_Subscriptions_Order::get_subscription_trial_length($order) < 1) { $sign_up_fee = max(WC_Subscriptions_Order::get_total_initial_payment($order) - $non_subscription_total, 0); } return $sign_up_fee; }
/** * Takes a subscription key and calculates the date on which the subscription is scheduled to expire * or 0 if it will never expire. * * @param $subscription_key string A subscription key of the form created by @see self::get_subscription_key() * @param $user_id int The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance. * @param $type string (optional) The format for the Either 'mysql' or 'timestamp'. * @since 1.1 */ public static function calculate_subscription_expiration_date($subscription_key, $user_id = '', $type = 'mysql') { $subscription = self::get_subscription($subscription_key, $user_id); if (empty($subscription)) { $expiration_date = 0; } else { $order = new WC_Order($subscription['order_id']); $subscription_period = WC_Subscriptions_Order::get_subscription_period($order, $subscription['product_id']); $subscription_length = WC_Subscriptions_Order::get_subscription_length($order, $subscription['product_id']); $subscription_interval = WC_Subscriptions_Order::get_subscription_interval($order, $subscription['product_id']); $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order, $subscription['product_id']); $subscription_trial_period = WC_Subscriptions_Order::get_subscription_trial_period($order, $subscription['product_id']); if ($subscription_length > 0) { if (isset($subscription['start_date']) && !empty($subscription['start_date'])) { $start_date = $subscription['start_date']; } elseif (!empty($order->order_date)) { $start_date = $order->order_date - get_option('gmt_offset') * 3600; } else { date('Y-m-d H:i:s'); } $expiration_date = strtotime("+ {$subscription_trial_length} {$subscription_trial_period}s", strtotime($start_date)); $expiration_date = strtotime("+ {$subscription_length} {$subscription_period}s", $expiration_date); } else { $expiration_date = 0; } } $expiration_date = 'mysql' == $type && 0 != $expiration_date ? date('Y-m-d H:i:s', $expiration_date) : $expiration_date; return apply_filters('woocommerce_subscription_calculated_expiration_date', $expiration_date, $subscription_key, $user_id); }
/** * 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; }
/** * Filters WC_Subscriptions_Order::get_sign_up_fee() to make sure the sign-up fee for a subscription product * that is synchronised is returned correctly. * * @param float The initial sign-up fee charged when the subscription product in the order was first purchased, if any. * @param mixed $order A WC_Order object or the ID of the order which the subscription was purchased in. * @param int $product_id The post ID of the subscription WC_Product object purchased in the order. Defaults to the ID of the first product purchased in the order. * @return float The initial sign-up fee charged when the subscription product in the order was first purchased, if any. * @since 1.5.3 * @deprecated 2.0 */ public static function get_sign_up_fee($sign_up_fee, $order, $product_id, $non_subscription_total) { _deprecated_function(__METHOD__, '2.0', __CLASS__ . '::get_synced_sign_up_fee'); if ('shop_order' == get_post_type($order) && self::order_contains_synced_subscription($order->id) && WC_Subscriptions_Order::get_subscription_trial_length($order) < 1) { $sign_up_fee = max(WC_Subscriptions_Order::get_total_initial_payment($order) - $non_subscription_total, 0); } return $sign_up_fee; }
/** * Calculate the timestamp for the next payment * * @param WC_Order $order * @param int $product_id * * @return mixed|void */ private static function calculate_next_payment_timestamp($order, $product_id) { $type = 'timestamp'; $from_date = ''; $from_date_arg = $from_date; $subscription = WC_Subscriptions_Manager::get_subscription(WC_Subscriptions_Manager::get_subscription_key($order->id, $product_id)); $subscription_period = WC_Subscriptions_Order::get_subscription_period($order, $product_id); $subscription_interval = WC_Subscriptions_Order::get_subscription_interval($order, $product_id); $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order, $product_id); $subscription_trial_period = WC_Subscriptions_Order::get_subscription_trial_period($order, $product_id); $trial_end_time = !empty($subscription['trial_expiry_date']) ? $subscription['trial_expiry_date'] : WC_Subscriptions_Product::get_trial_expiration_date($product_id, get_gmt_from_date($order->order_date)); $trial_end_time = strtotime($trial_end_time); // If the subscription has a free trial period, and we're still in the free trial period, the next payment is due at the end of the free trial if ($subscription_trial_length > 0 && $trial_end_time > gmdate('U') + 60 * 60 * 23 + 120) { // Make sure trial expiry is more than 23+ hours in the future to account for trial expiration dates incorrectly stored in non-UTC/GMT timezone (and also for any potential changes to the site's timezone) $next_payment_timestamp = $trial_end_time; // The next payment date is {interval} billing periods from the from date } else { // We have a timestamp if (!empty($from_date) && is_numeric($from_date)) { $from_date = date('Y-m-d H:i:s', $from_date); } if (empty($from_date)) { if (!empty($subscription['completed_payments'])) { $from_date = array_pop($subscription['completed_payments']); $add_failed_payments = true; } else { if (!empty($subscription['start_date'])) { $from_date = $subscription['start_date']; $add_failed_payments = true; } else { $from_date = gmdate('Y-m-d H:i:s'); $add_failed_payments = false; } } $failed_payment_count = WC_Subscriptions_Order::get_failed_payment_count($order, $product_id); // Maybe take into account any failed payments if (true === $add_failed_payments && $failed_payment_count > 0) { $failed_payment_periods = $failed_payment_count * $subscription_interval; $from_timestamp = strtotime($from_date); if ('month' == $subscription_period) { $from_date = date('Y-m-d H:i:s', WC_Subscriptions::add_months($from_timestamp, $failed_payment_periods)); } else { // Safe to just add the billing periods $from_date = date('Y-m-d H:i:s', strtotime("+ {$failed_payment_periods} {$subscription_period}", $from_timestamp)); } } } $from_timestamp = strtotime($from_date); if ('month' == $subscription_period) { // Workaround potential PHP issue $next_payment_timestamp = WC_Subscriptions::add_months($from_timestamp, $subscription_interval); } else { $next_payment_timestamp = strtotime("+ {$subscription_interval} {$subscription_period}", $from_timestamp); } // Make sure the next payment is in the future $i = 1; while ($next_payment_timestamp < gmdate('U') && $i < 30) { if ('month' == $subscription_period) { $next_payment_timestamp = WC_Subscriptions::add_months($next_payment_timestamp, $subscription_interval); } else { // Safe to just add the billing periods $next_payment_timestamp = strtotime("+ {$subscription_interval} {$subscription_period}", $next_payment_timestamp); } $i = $i + 1; } } // If the subscription has an expiry date and the next billing period comes after the expiration, return 0 if (isset($subscription['expiry_date']) && 0 != $subscription['expiry_date'] && $next_payment_timestamp + 120 > strtotime($subscription['expiry_date'])) { $next_payment_timestamp = 0; } $next_payment = 'mysql' == $type && 0 != $next_payment_timestamp ? date('Y-m-d H:i:s', $next_payment_timestamp) : $next_payment_timestamp; return apply_filters('woocommerce_subscriptions_calculated_next_payment_date', $next_payment, $order, $product_id, $type, $from_date, $from_date_arg); }
/** * 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; }
/** * Override the default PayPal standard args in WooCommerce for subscription purchases. * * @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)) { $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($order_items[0]); // 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(); } // Subscription unit of duration switch (strtolower(WC_Subscriptions_Order::get_subscription_period($order))) { case 'day': $subscription_period = 'D'; break; case 'week': $subscription_period = 'W'; break; case 'year': $subscription_period = 'Y'; break; case 'month': default: $subscription_period = 'M'; break; } $sign_up_fee = WC_Subscriptions_Order::get_sign_up_fee($order); $price_per_period = WC_Subscriptions_Order::get_price_per_period($order); $subscription_interval = WC_Subscriptions_Order::get_subscription_interval($order); $subscription_length = WC_Subscriptions_Order::get_subscription_length($order); $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order); if ($subscription_trial_length > 0) { // Specify a free trial period $paypal_args['a1'] = $sign_up_fee > 0 ? $sign_up_fee : 0; // Add the sign up fee to the free trial period // Sign Up interval $paypal_args['p1'] = $subscription_trial_length; // Sign Up unit of duration $paypal_args['t1'] = $subscription_period; } elseif ($sign_up_fee > 0) { // No trial period, so charge sign up fee and per period price for the first period if ($subscription_length == 1) { $param_number = 3; } else { $param_number = 1; } $paypal_args['a' . $param_number] = $price_per_period + $sign_up_fee; // Sign Up interval $paypal_args['p' . $param_number] = $subscription_interval; // Sign Up unit of duration $paypal_args['t' . $param_number] = $subscription_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'] = $subscription_period; } // Recurring payments if ($subscription_length == 1 || $sign_up_fee > 0 && $subscription_trial_length == 0 && $subscription_length == 2) { // Non-recurring payments $paypal_args['src'] = 0; } else { $paypal_args['src'] = 1; if ($subscription_length > 0) { if ($sign_up_fee > 0 && $subscription_trial_length == 0) { // An initial period is being used to charge a sign-up fee $subscription_length--; } $paypal_args['srt'] = $subscription_length / $subscription_interval; } } // Force return URL so that order description & instructions display $paypal_args['rm'] = 2; } return $paypal_args; }
/** * Override the default PayPal standard args in WooCommerce for subscription purchases. * * @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; } } $sign_up_fee = WC_Subscriptions_Order::get_sign_up_fee($order); $initial_payment = WC_Subscriptions_Order::get_total_initial_payment($order); $price_per_period = WC_Subscriptions_Order::get_recurring_total($order); $subscription_interval = WC_Subscriptions_Order::get_subscription_interval($order); $subscription_installments = WC_Subscriptions_Order::get_subscription_length($order) / $subscription_interval; $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order); if ($subscription_trial_length > 0) { // Specify a free trial period $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']; } 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; } } // Force return URL so that order description & instructions display $paypal_args['rm'] = 2; } return $paypal_args; }
/** * notify handler * @since 2.2.0 */ function notify_handler() { global $woocommerce; $redirect = get_permalink(woocommerce_get_page_id('cart')); if (isset($_GET['stripeListener']) && $_GET['stripeListener'] == 'stripe') { if ($this->debug == 'yes') { $this->log->add('stripe', __('Post form: ', 'woocommerce') . print_r($_POST, true)); } if ($woocommerce->verify_nonce('stripe_payment_submit')) { $order_id = $this->get_request('order'); $order = new WC_Order($order_id); if ($order->order_key != $_REQUEST['key']) { $woocommerce->add_error(__('Order key do not match!', 'woocommerce')); wp_redirect($redirect); //redirect page exit; } $order_items = $order->get_items(); $product = $order->get_product_from_item(array_pop($order_items)); $this->product_type = $product->product_type; $params = $this->get_params($order); if ($this->debug == 'yes') { $this->log->add('stripe', __('Post paramaters: ', 'woocommerce') . print_r($params, true)); } $request = new stripe_request($this->get_config()); $response = ''; if ('subscription' == $product->product_type || 'subscription_variation' == $product->product_type) { if ($this->debug == 'yes') { $this->log->add('stripe', 'Starting subscription ... '); } $sign_up_fee = WC_Subscriptions_Order::get_sign_up_fee($order); $price_per_period = WC_Subscriptions_Order::get_price_per_period($order); $subscription_interval = WC_Subscriptions_Order::get_subscription_interval($order); $subscription_length = WC_Subscriptions_Order::get_subscription_length($order); $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order); // Subscription unit of duration switch (strtolower(WC_Subscriptions_Order::get_subscription_period($order))) { case 'year': $subscription_period = 'year'; break; case 'month': default: $subscription_period = 'month'; break; } // add more param $sparams = array(); $plan_name = get_post($product->id)->post_title; //$plan_id = $product->id; $plan_id = $order_id; $response = $request->send($plan_id, 'retrieve'); if (!$response->success()) { //create plan if not exists if ($this->debug == 'yes') { $this->log->add('stripe', sprintf(__('Create plan id: %s', 'woocommerce'), $plan_id)); } $response = $request->send(array('amount' => number_format($price_per_period, 2, '.', '') * 100, 'interval' => $subscription_period, "currency" => $params['currency'], "id" => $plan_id, 'name' => $plan_name, 'trial_period_days' => $subscription_trial_length), 'plan'); } if ($response->success()) { if ($this->debug == 'yes') { $this->log->add('stripe', print_r($response, true)); } $response = $request->send(array("card" => $params['card'], "plan" => $plan_id, "email" => $order->billing_email), 'customer'); if ($this->debug == 'yes') { $this->log->add('stripe', 'Customer create: ' . print_r($response->results, true)); } if ($response->success() && $sign_up_fee > 0) { $response = $request->send(array("customer" => $response->results->id, "amount" => number_format($sign_up_fee, 2, '.', '') * 100, "currency" => $params['currency'], "description" => __("Sign-up Fee", 'woocommerce'))); if ($this->debug == 'yes') { $this->log->add('stripe', 'Sign-up fee response: ' . print_r($response->results, true)); } } } else { //error if ($this->debug == 'yes') { $this->log->add('stripe', __('Error can not create plan', 'woocommerce')); } $woocommerce->add_error(__('Error can not create plan', 'woocommerce')); } } else { $response = $request->send($params); } //response result if ($response->success()) { $order->add_order_note(__('Stripe payment completed', 'woocommerce') . ' (Transaction ID: ' . $response->get_transaction_id() . ')'); $order->payment_complete(); $woocommerce->cart->empty_cart(); $redirect = add_query_arg('key', $order->order_key, add_query_arg('order', $order_id, get_permalink(woocommerce_get_page_id('thanks')))); } else { if ($this->debug == 'yes') { $this->log->add('stripe', 'Error: ' . $response->get_error(), true); } $woocommerce->add_error(__('Payment error', 'woocommerce') . ': ' . $response->get_error() . ''); } } wp_redirect($redirect); //redirect page exit; } }