cart->is_empty()) { WC()->cart->empty_cart(); } $_SESSION["addOns"] = []; $_SESSION["one-time"] = []; return $passed; }, 20, 3); add_filter('woocommerce_checkout_fields', function ($fields) { // $fields['order']['order_comments']['placeholder'] = 'My new placeholder'; return $fields; }); }); // WooCommerce Fee Stuff // first, wordpress doesn't use sessions, so let's enable those add_action('init', function () { if (!session_id()) { session_start(); } }); // and clean up sessions on logout add_action('wp_logout', function () { session_destroy(); }); /** * Allow only one coupon per order in WooCommerce. */ add_filter('woocommerce_apply_individual_use_coupon', 'only_one_coupon_allowed', 10, 2); function only_one_coupon_allowed($apply, $coupon) { // Check if a coupon is already applied if (WC()->cart->has_discount()) { // Remove other applied coupons except the current one WC()->cart->empty_discounts(); WC()->cart->apply_coupon($coupon->get_code()); return false; // Do not apply the new coupon } return $apply; } add_filter('woocommerce_add_error', 'customize_coupon_error_message', 10, 1); function customize_coupon_error_message($error) { // Check if the error message is related to a coupon already applied if (strpos($error, 'Coupon code already applied!') !== false) { return ''; } return $error; } function get_current_shipping_comment() { // Get the chosen shipping methods from the cart $chosen_shipping_methods = WC()->session->get('chosen_shipping_methods'); if (empty($chosen_shipping_methods)) { return null; } foreach ($chosen_shipping_methods as $chosen_method) { $method_parts = explode(':', $chosen_method); // Split method ID and instance ID $shipping_method_id = $method_parts[0]; $instance_id = isset($method_parts[1]) ? $method_parts[1] : ''; // Build the option name for the instance-specific settings $option_name = 'woocommerce_' . $shipping_method_id . '_' . $instance_id . '_settings'; $instance_settings = get_option($option_name); // Check if `shipping_comment` exists if (!empty($instance_settings) && isset($instance_settings['shipping_comment'])) { return $instance_settings['shipping_comment']; // Return the first found Salesforce ID } } return null; // No `shipping_comment` found } /** * Generates a cart summary with accurate total calculation and full details * * @param bool $showCheckoutButton Whether to show the checkout button * @return string Rendered cart summary */ function generateCartSummary($showCheckoutButton = true) { global $product; // Ensure WooCommerce calculates all totals WC()->cart->calculate_totals(); $cartItem = getFirstCartItem(); $parentName = $cartItem['data']->get_parent_data()['title']; $product = getProductDetails($cartItem["product_id"]); $ratePlan = getRatePlan(); $rateMultiplier = ($ratePlan === 'Annually') ? 12 : (($ratePlan === 'Semi-Annually') ? 6 : 1); // Base product pricing $basePrice = $cartItem['data']->get_regular_price(); $isSmartwatch = ($parentName === "Smartwatch"); // Setup fee setup $setupFeeName = $isSmartwatch ? "Device Fee" : "Setup Fee"; $setupFee = $isSmartwatch ? 159.00 : 99.95; $isAarpMember = WC()->session->get('aarp_discount') === true; $activationDiscount = 0; if ($isAarpMember && !$isSmartwatch) { $discountedMonthlyRate = round($base_price * 0.85, 2); $setupFee = 99.95; $activationDiscount = 50.00; } else { $discountedMonthlyRate = $base_price; } // Apply AARP discount if eligible $discountedMonthlyRate = $isAarpMember ? round($basePrice * 0.85, 2) : $basePrice; $variable_price = round($discountedMonthlyRate * $rateMultiplier, 2); // Setup Fee & Activation Discount //$setupFee = 99.95; $activationDiscount = ($isAarpMember && $parentName !== 'Smartwatch') ? 50.00 : 0; // Professional Install Check and Cost $professionalInstallLabel = $_SESSION['one-time']['Professional Install']['label'] ?? ''; $professionalInstallCost = $_SESSION['one-time']['Professional Install']['price'] ?? 0; // Add-ons and their total price calculation $totalAddonPrice = 0; $adjustedAddons = []; $addonLabels = []; if (isset($_SESSION['addOns']) && is_array($_SESSION['addOns'])) { foreach ($_SESSION['addOns'] as $addOn) { $addOnLabel = $addOn['label']; $addOnPrice = ($addOnLabel === 'Key Lockbox' && $ratePlan === 'Annually') ? 0 : $addOn['price'] * $rateMultiplier; if (!in_array($addOnLabel, $addonLabels)) { $adjustedAddons[] = ['name' => $addOnLabel, 'price' => $addOnPrice]; $addonLabels[] = $addOnLabel; $totalAddonPrice += $addOnPrice; } } } // Determine if free shipping applies $defaultShippingCost = 29.95; $freeShippingApplied = $isAarpMember || ($ratePlan === 'Annually' || $ratePlan === 'Semi-Annually') || $professionalInstallCost > 0; $finalShippingCost = $freeShippingApplied ? 0 : $defaultShippingCost; // Calculate total cart value $totalCart = round($variable_price + $setupFee + $professionalInstallCost + $totalAddonPrice + $finalShippingCost - $activationDiscount, 2); // Retrieve applied coupons $couponSummary = []; $couponDescription = []; foreach (WC()->cart->get_applied_coupons() as $coupon_code) { $coupon = new WC_Coupon($coupon_code); $couponSummary[] = $coupon_code; $couponDescription[] = $coupon->get_description(); } // Render with original structure and components return site()->render("cart_summary", array_merge($product, [ "variation" => $ratePlan, 'variable_price' => $variable_price, 'addonPrice' => $totalAddonPrice, 'adjustedAddons' => $adjustedAddons, 'fallDetectionLabel' => getAddonLabel('Fall Detection'), 'fallDetectionPrice' => getAddonPrice('Fall Detection') * $rateMultiplier, 'protectionPlan' => getAddonLabel('Protection Plan'), 'protectionPlanprice' => getAddonPrice('Protection Plan') * $rateMultiplier, 'keyLockboxlabel' => getAddonLabel('Key Lockbox'), 'keylockboxprice' => ($ratePlan === 'Annually') ? 0 : getAddonPrice('Key Lockbox') * $rateMultiplier, 'one-time' => $professionalInstallLabel, 'pro-one-time' => $professionalInstallCost, 'setupFeeName' => $setupFeeName, 'activationFeeAmount' => $setupFee, 'activationDiscount' => $activationDiscount > 0 ? -$activationDiscount : null, 'defaultShipping' => $defaultShippingCost, 'freeShipping' => $freeShippingApplied ? $defaultShippingCost : null, 'totalDue' => $totalCart, 'couponList' => implode(', ', $couponSummary), 'couponDescription' => implode('
', array_filter($couponDescription)), 'showCheckoutButton' => $showCheckoutButton, ])); } /** * Add custom fees to WooCommerce order based on cart items and conditions. * * @param WC_Order $order WooCommerce order object. * @param array $data Additional data for the order. */ function add_custom_meta_to_order($order, $data) { $existingFees = array_map(function ($fee) { return sanitize_title($fee->get_name()); }, $order->get_items('fee')); $cartItem = getFirstCartItem(); if (!$cartItem) return; $parentName = $cartItem['data']->get_parent_data()['title']; $isSmartwatch = ($parentName === "Smartwatch"); // Determine fee name and amount $feeName = $isSmartwatch ? "Device Fee" : "Setup Fee"; $feeAmount = $isSmartwatch ? 159.00 : 99.95; // Add Device/Setup Fee if (!in_array(sanitize_title($feeName), $existingFees)) { $feeItem = new WC_Order_Item_Fee(); $feeItem->set_name($feeName); $feeItem->set_total($feeAmount); $order->add_item($feeItem); } // Professional Install Fee $proInstall = $_SESSION["one-time"]["Professional Install"] ?? null; if ($proInstall && !in_array(sanitize_title("Professional Install"), $existingFees)) { $installFeeItem = new WC_Order_Item_Fee(); $installFeeItem->set_name("Professional Install"); $installFeeItem->set_total(99.00); // Specific fee amount $order->add_item($installFeeItem); } // Recalculate order totals after adding fees $order->calculate_totals(); } add_action('woocommerce_checkout_create_order', 'add_custom_meta_to_order', 20, 2); /** * Retrieves the default title and cost for the "Shipping" flat rate method from WooCommerce settings. * * @return array|null Array containing 'title' and 'cost' if found, or null if not found. */ function get_default_shipping_info() { $zones = WC_Shipping_Zones::get_zones(); $shipping_info = [ 'title' => null, 'cost' => null, ]; // Iterate over each zone to find the 'flat_rate' method titled 'Shipping' foreach ($zones as $zone) { foreach ($zone['shipping_methods'] as $method) { if ($method->id === 'flat_rate' && $method->title === 'Shipping') { $shipping_info['title'] = $method->title; // Try to retrieve the cost directly from the method's instance options if (method_exists($method, 'get_instance_option')) { $cost = $method->get_instance_option('cost'); if (!empty($cost)) { $shipping_info['cost'] = $cost; error_log("Shipping Method Title: {$shipping_info['title']}"); error_log("Shipping Method Default Cost: {$shipping_info['cost']}"); } } // Fallback if cost retrieval fails $shipping_info['cost'] = 'N/A'; error_log("Shipping Method Cost not found using get_instance_option; using fallback 'N/A'."); return $shipping_info; } } } return null; } /** * Calculate the variable price based on the rate plan * * @param float $basePrice The base price of the product * @param string|null $ratePlan The rate plan (e.g., "Monthly", "Semi-Annually", "Annually") * @return float The adjusted price based on the rate plan */ function calculateVariablePrice($basePrice, $ratePlan) { if (!is_numeric($basePrice)) { return 0; // Prevent non-numeric value issues } switch ($ratePlan) { case 'Annually': return $basePrice * 12; // Annual plan = monthly price * 12 case 'Semi-Annually': return $basePrice * 6; // Semi-annual plan = monthly price * 6 case 'Monthly': default: return $basePrice; // Monthly plan = base price } } /** * Get the first item in the cart */ function getFirstCartItem() { foreach (WC()->cart->get_cart() as $item) { return $item; } } /** * Retrieve product details based on ID */ function getProductDetails($productId) { // Ensure regular price is fetched correctly return site()->getPost($productId, [ "title", "thumbnail", "acf.activation_fee", "acf.fee_type", "meta._regular_price", // This field might not be necessary anymore "shipCoupon", "shipCouponName", "defaultShipping", "shippingName", "couponList", "couponTotal", "activationFeeName", "activationFeeAmount", "defaultshippingTitle", "defaultshippingCost", ]); } /** * Calculate the monthly costs of the cart */ function calculateMonthlyCosts($cartContents) { $total = 0; foreach ($cartContents as $item) { $total += $item['data']->get_regular_price(); } return $total; } /** * Retrieve the rate plan from the cart item's variation attributes * * @return string|null The rate plan, or null if not found */ function getRatePlan() { $cart = WC()->cart; foreach ($cart->get_cart() as $cart_item) { if (isset($cart_item['variation']['attribute_rate-plan'])) { return $cart_item['variation']['attribute_rate-plan']; } } return null; // Return null if no rate plan is found } /** * Retrieve applied coupons and their details */ function getAppliedCoupons() { $appliedCoupons = WC()->cart->get_applied_coupons(); $couponDetails = [ 'coupon_title' => '', 'coupon_amount' => 0, 'couponSummary' => '', 'coupon_description' => '' ]; foreach ($appliedCoupons as $couponCode) { $coupon = new WC_Coupon($couponCode); $couponDetails['coupon_title'] = $coupon->get_code(); $couponDetails['coupon_amount'] += $coupon->get_amount(); $couponDetails['coupon_description'] = $coupon->get_description(); } return $couponDetails; } /** * Calculate the total cart value based on product, monthly costs, and applied coupons */ function calculateTotalCart($basePrice, $activationFee, $finalShippingCost, $ratePlan) { // Define multipliers based on the rate plan $rateMultiplier = 1; if ($ratePlan === "Annually") { $rateMultiplier = 12; } elseif ($ratePlan === "Semi-Annually") { $rateMultiplier = 6; } $variablePrice = $basePrice * $rateMultiplier; $totalCart = $variablePrice + $activationFee + $finalShippingCost; return $totalCart; } /** * Get the label for a specific add-on */ function getAddonLabel($label) { return $_SESSION["addOns"][$label]["label"]; } /** * Get the price for a specific add-on */ function getAddonPrice($label) { return $_SESSION["addOns"][$label]["price"]; } /** * Calculate the total price for all add-ons */ function calculateAddonPrices() { // Check if addOns is set and is an array if (!isset($_SESSION["addOns"]) || !is_array($_SESSION["addOns"])) { //error_log("Warning: \$_SESSION['addOns'] is not set or is not an array."); return 0; // Return default price if addOns is missing or invalid } // Calculate total price from add-ons $addonPrices = 0; foreach ($_SESSION["addOns"] as $addOn) { // Ensure each addOn has a price if (isset($addOn["price"])) { $addonPrices += $addOn["price"]; } else { //error_log("Warning: Add-on missing 'price' key."); } } return $addonPrices; } /** * Retrieve the selected shipping type */ function getShippingType() { $shippingMethodId = WC()->session->get('chosen_shipping_methods')[0]; return get_title_shipping_method_from_method_id($shippingMethodId); } /** * Get the cost of shipping, providing free shipping for annual or semi-annual plans * * @param string|null $ratePlan The selected rate plan * @return float Shipping cost */ function getShippingCost($ratePlan = null) { // Check for Professional Install add-on in the session or cart $proInstallSelected = isset($_SESSION["one-time"]["Professional Install"]); // Apply free shipping for annual and semi-annual rate plans or if Professional Install is selected if ($ratePlan === 'Annually' || $ratePlan === 'Semi-Annually' || $proInstallSelected) { WC()->session->set('chosen_shipping_methods', ['free_shipping']); return 0.00; } $packages = WC()->shipping->get_packages(); // Check if we have shipping packages if (!empty($packages)) { // Get the chosen shipping method ID $chosen_method = WC()->session->get('chosen_shipping_methods')[0] ?? ''; // Get the first package (there might be multiple in some setups) $package = $packages[0]; // Check if the shipping method exists in the package rates if (isset($package['rates'][$chosen_method])) { return $package['rates'][$chosen_method]->cost; } } // Fallback shipping price if none is found return 29.95; } /** * Get the discount applied through shipping coupons */ function getShippingDiscount() { return WC()->cart->get_coupon_discount_totals()['shipping'] ?? 0; } /** * Get the free shipping name, if any */ function getFreeShippingName() { foreach (WC()->cart->get_applied_coupons() as $couponCode) { $coupon = new WC_Coupon($couponCode); if ($coupon->get_free_shipping()) { return "Free Shipping"; } } return ""; } /** * Get the cost of professional install */ function getProfessionalInstallCost() { return $_SESSION["one-time"]["Professional Install"]["price"] ?? 99.00; } function get_title_shipping_method_from_method_id( $method_rate_id = '' ){ if( ! empty( $method_rate_id ) ){ $method_key_id = str_replace( ':', '_', $method_rate_id ); $option_name = 'woocommerce_'.$method_key_id.'_settings'; return get_option( $option_name, true )['title']; } else { return false; } } function add_administration_fees() { WC()->cart->add_fee( 'Processing Fee', 2.5 ); } /** * custom woocommerce order fields */ $additionalWooFields = [ "subscriber_first_name" => [ "type" => "text", "label" => "", "placeholder" => "First Name", "required" => true, ], "subscriber_last_name" => [ "type" => "text", "label" => "", "placeholder" => "Last Name", "required" => true, ], "subscriber_address_1" => [ "type" => "text", "label" => "", "placeholder" => "Address 1", "required" => true, ], "subscriber_address_2" => [ "type" => "text", "label" => "", "placeholder" => "Address 2 (Apt, Suite, etc.)", ], "subscriber_zip" => [ "type" => "text", "label" => "", "placeholder" => "Zip Code", "required" => true, ], "subscriber_city" => [ "type" => "text", "label" => "", "placeholder" => "City", "required" => true, ], "subscriber_state" => [ "type" => "text", "label" => "", "placeholder" => "State", "required" => true, ], "subscriber_email" => [ "type" => "text", "label" => "", "placeholder" => "Email Address", ], "subscriber_phone" => [ "type" => "text", "label" => "", "placeholder" => "Phone Number", ], "caregiver_relation" => [ "type" => "select", "label" => "Relation", "options" => [ "Brother" => "Brother", "Daughter" => "Daughter", "Father" => "Father", "Friend" => "Friend", "Granddaughter" => "Granddaughter", "Grandson" => "Grandson", "In-law" => "In-law", "Mother" => "Mother", "Neighbor" => "Neighbor", "Relative" => "Relative", "Sister" => "Sister", "Son" => "Son", "Spouse" => "Spouse", "Other" => "Other", ], "required" => true, ], "caregiver_first_name" => [ "type" => "text", "label" => "", "placeholder" => "First Name", "required" => true, ], "caregiver_last_name" => [ "type" => "text", "label" => "", "placeholder" => "Last Name", "required" => true, ], "caregiver_email" => [ "type" => "text", "label" => "", "placeholder" => "Email Address", ], "caregiver_phone" => [ "type" => "text", "label" => "", "placeholder" => "Phone Number", ], "card_number" => [ "type" => "number", "label" => "Credit Card", "required" => true, ], "ccv" => [ "type" => "number", "label" => "CCV", "required" => true, ], "expiration_month" => [ "type" => "number", "label" => "Expiration Month", "required" => true, "attrs" => ["min" => 1, "max" => 12, "step" => 1] ], "expiration_year" => [ "type" => "number", "label" => "Expiration Year", "required" => true, "attrs" => ["min" => 2022, "max" => 2032, "step" => 1] ], "SESSpromoid" => [ "type" => "hidden", "label" => "Promotion ID", ], "SESSpromotion_description" => [ "type" => "hidden", "label" => "Promotion Description", ], "SESScoupon_code" => [ "type" => "hidden", "label" => "Coupon Code", ], ]; add_action('woocommerce_before_checkout_billing_form', function ($checkout) use ($additionalWooFields) { $dto = []; foreach ($additionalWooFields as $key => $field) { ob_start(); $customAttributes = ["v-model" => $key]; if ($field["attrs"]) { $customAttributes = array_merge($customAttributes, $field["attrs"]); } woocommerce_form_field($key, [ 'type' => $field["type"], 'class' => $field["classes"] ?? ['my-field-class orm-row-wide'], 'input_class' => $field["input_classes"] ?? [], 'label_class' => $field["label_classes"] ?? [], 'label' => $field["label"] ?? $key, 'required' => $field["placeholder"] ?? false, 'placeholder' => $field["placeholder"] ?? "", 'options' => $field["options"] ?? [], 'custom_attributes' => $customAttributes, ], $checkout->get_value($key)); $fieldHTML = ob_get_contents(); ob_end_clean(); $dto[$key] = $fieldHTML; } echo site()->render("checkout-step-1", $dto); }); function showCardFields() { global $additionalWooFields; $dto = []; foreach ($additionalWooFields as $key => $field) { if (!in_array($key, ["card_number", "ccv", "expiration_month", "expiration_year"])) { continue; } ob_start(); $customAttributes = ["v-model" => $key]; if ($field["attrs"]) { $customAttributes = array_merge($customAttributes, $field["attrs"]); } woocommerce_form_field($key, [ 'type' => $field["type"], 'class' => $field["classes"] ?? ['my-field-class orm-row-wide'], 'input_class' => $field["input_classes"] ?? [], 'label_class' => $field["label_classes"] ?? [], 'label' => $field["label"] ?? $key, 'required' => $field["placeholder"] ?? false, 'placeholder' => $field["placeholder"] ?? "", 'options' => $field["options"] ?? [], 'custom_attributes' => $customAttributes, ], null); $fieldHTML = ob_get_contents(); ob_end_clean(); $dto[$key] = $fieldHTML; } echo site()->render("card-fields", $dto); } add_action('woocommerce_checkout_update_order_meta', function ($orderID) use ($additionalWooFields) { foreach ($additionalWooFields as $key => $field) { if (isset($_POST[$key])) { $value = esc_attr($_POST[$key]); if ($key === "card_number") { $parts = str_split($value); $output = ""; for ($i = 0; $i < count($parts); $i++) { if ($i < count($parts) - 4) { $output .= "*"; } else { $output .= $parts[$i]; } } $value = $output; } update_post_meta($orderID, $key, $value); } } }); add_action('woocommerce_admin_order_data_after_shipping_address', function ($order) use ($additionalWooFields) { $dto = [ "subscriber-data" => [], "caregiver-data" => [], ]; foreach ($additionalWooFields as $key => $field) { $meta = get_post_meta($order->get_id(), $key, true); $dataType = (substr($key, 0, 10) === "subscriber") ? "subscriber-data" : "caregiver-data"; $dto[$dataType][] = [ "label" => $field["label"] ? $field["label"] : $field["placeholder"], "value" => $meta ?: "", ]; } echo site()->render("order_details_in_admin", $dto); }); add_filter( 'woocommerce_order_shipping_to_display_shipped_via', '__return_false' ); /** * Update order emails to include all the extra stuff */ add_filter('woocommerce_email_order_meta_fields', function ($fields, $sent_to_admin, $order) use ($additionalWooFields) { foreach ($additionalWooFields as $key => $value) { $fields[$key] = [ 'label' => strlen($value["label"]) ? $value["label"] : $value["placeholder"], 'value' => get_post_meta($order->get_id(), $key, true), ]; } if (count($order->get_coupon_codes())) { $fields["applied_coupons"] = [ "label" => "Applied Coupons", "value" => implode(", ", $order->get_coupon_codes()), ]; } return $fields; }, 10, 3); // Apply Rate Multiplier and AARP Discount to Each Cart Item add_action('woocommerce_before_calculate_totals', 'apply_multiplier_and_discount_to_cart_items', 10, 1); function apply_multiplier_and_discount_to_cart_items($cart) { // Exit if in the admin area or cart is empty if (is_admin() || !did_action('woocommerce_before_calculate_totals') || $cart->is_empty()) { return; } // Determine the rate plan and AARP discount status $rate_plan = getRatePlan(); $is_aarp_discount = WC()->session->get('aarp_discount') === true; // Define the rate multiplier based on the rate plan $rate_multiplier = 1; if ($rate_plan === 'Annually') { $rate_multiplier = 12; } elseif ($rate_plan === 'Semi-Annually') { $rate_multiplier = 6; } // Loop through each cart item and adjust the price based on the rate multiplier and AARP discount foreach ($cart->get_cart() as $cart_item) { $base_price = $cart_item['data']->get_regular_price(); // Calculate the discounted monthly rate, rounding to two decimal places $discounted_monthly_rate = $is_aarp_discount ? round($base_price * 0.85, 2) : $base_price; // Calculate the final adjusted price by multiplying the monthly rate by the rate multiplier $adjusted_price = $discounted_monthly_rate * $rate_multiplier; // Set the adjusted price $cart_item['data']->set_price(round($adjusted_price, 2)); } } // Apply Setup Fee, AARP Discount, Conditional Free Shipping, and Add-ons in Cart add_action('woocommerce_cart_calculate_fees', 'apply_custom_fees_and_discounts'); function apply_custom_fees_and_discounts() { // Clear previous fees to prevent duplication WC()->cart->fees_api()->remove_all_fees(); // Fetch rate plan and AARP status $ratePlan = getRatePlan(); $isAarpMember = WC()->session->get('aarp_discount') === true; // Set up rate multiplier based on the rate plan $rateMultiplier = ($ratePlan === 'Annually') ? 12 : (($ratePlan === 'Semi-Annually') ? 6 : 1); // Retrieve the first cart item $cartItem = getFirstCartItem(); if (!$cartItem) return; $parentName = $cartItem['data']->get_parent_data()['title']; $basePrice = $cartItem['data']->get_regular_price(); $isSmartwatch = ($parentName === 'Smartwatch'); // Calculate setup fee $setupFee = $isSmartwatch ? 159.00 : 99.95; // Calculate discounted price for AARP members $discountedPrice = $isAarpMember ? round($basePrice * 0.85, 2) : $basePrice; $totalDiscountedPrice = $discountedPrice * $rateMultiplier; // Apply Setup Fee WC()->cart->add_fee($isSmartwatch ? 'Device Fee' : 'Setup Fee', $setupFee); // Apply activation discount if applicable $activationDiscount = ($isAarpMember && !$isSmartwatch) ? 50.00 : 0; if ($activationDiscount > 0) { WC()->cart->add_fee('Free Activation', -$activationDiscount); } // Calculate and add add-ons fees if (isset($_SESSION["addOns"]) && is_array($_SESSION["addOns"])) { foreach ($_SESSION["addOns"] as $addOn) { $addOnLabel = $addOn["label"]; $addOnPrice = ($addOnLabel === "Key Lockbox" && $ratePlan === "Annually") ? 0 : $addOn["price"] * $rateMultiplier; WC()->cart->add_fee($addOnLabel, $addOnPrice); } } // Free shipping logic for AARP members, eligible rate plans, or Professional Install $hasProfessionalInstall = isset($_SESSION["one-time"]["Professional Install"]); $packages = WC()->shipping()->get_packages(); if (!empty($packages) && !empty($packages[0]['rates'])) { if (($ratePlan === 'Annually' || $ratePlan === 'Semi-Annually' || $isAarpMember || $hasProfessionalInstall) && isset($packages[0]['rates']['free_shipping:1'])) { WC()->session->set('chosen_shipping_methods', ['free_shipping:1']); } elseif ($ratePlan === 'Monthly' && isset($packages[0]['rates']['flat_rate:2'])) { WC()->session->set('chosen_shipping_methods', ['flat_rate:2']); } } } // Force WooCommerce to recalculate totals after adjusting line items add_action('woocommerce_checkout_create_order', 'force_recalculate_order_totals', 20, 1); function force_recalculate_order_totals($order) { $order->calculate_totals(); } add_action('woocommerce_checkout_update_order_meta', 'save_card_details_to_order_meta'); function save_card_details_to_order_meta($order_id) { if (isset($_POST['card_number']) && !empty($_POST['card_number'])) { $card_number = sanitize_text_field($_POST['card_number']); update_post_meta($order_id, '_card_number', $card_number); $card_type = detect_card_type($card_number); if ($card_type) { update_post_meta($order_id, '_card_type', $card_type); } } if (isset($_POST['expiration_month']) && !empty($_POST['expiration_month'])) { $expiration_month = sanitize_text_field($_POST['expiration_month']); update_post_meta($order_id, '_expiration_month', $expiration_month); } if (isset($_POST['expiration_year']) && !empty($_POST['expiration_year'])) { $expiration_year = sanitize_text_field($_POST['expiration_year']); update_post_meta($order_id, '_expiration_year', $expiration_year); } } /** * Function to detect card type based on the card number. */ function detect_card_type($number) { $number = preg_replace('/\D/', '', $number); $patterns = [ 'Visa' => '/^4[0-9]{12}(?:[0-9]{3})?$/', 'MasterCard' => '/^5[1-5][0-9]{14}$/', 'American Express' => '/^3[47][0-9]{13}$/', 'Discover' => '/^6(?:011|5[0-9]{2})[0-9]{12}$/' ]; foreach ($patterns as $type => $pattern) { if (preg_match($pattern, $number)) { return $type; } } return null; } add_action('woocommerce_thankyou', function ($order_id) { $card_number = get_post_meta($order_id, '_card_number', true); //error_log("Card Number: " . $card_number); $order = wc_get_order($order_id); $order_data = []; foreach ($order->get_items() as $item) { $item_data = $item->get_data(); $formatted_meta_data = $item->get_formatted_meta_data('_', true); $order_data['items'][] = [ 'name' => $item->get_name(), 'product_id' => $item->get_product_id(), 'quantity' => $item->get_quantity(), 'subtotal' => $item->get_subtotal(), 'total' => $item->get_total(), ]; } $order_products = []; foreach ($order->get_items() as $item) { $product = $item->get_product(); $product_id = $product->get_id(); $product_sku = $product->get_sku(); $quantity = $item->get_quantity(); $rate_plan_id = null; $attributes = []; if ($product->is_type('variation')) { $parent_id = $product->get_parent_id(); // Get the parent variable product ID $attributes = $product->get_attributes(); // Get variation attributes //var_dump($attributes['rate-plan-sfid']); // Get Rate Plan ID custom field for the variation $rate_plan_id = get_post_meta($product_id, 'rate_plan_id', true); // Adjust if needed $variation_label = implode(', ', $attributes); } else { // For non-variation products, still fetch Rate Plan ID if it exists $rate_plan_id = get_post_meta($product_id, 'rate_plan_id', true); } } $fees_total = 0; foreach ($order->get_fees() as $fees) { $order_data['fees'][] = [ 'name' => $fees->get_name(), 'amount' => $fees->get_amount(), ]; $fees_total += $fees->get_amount(); } foreach ($order->get_coupon_codes() as $coupon_code) { $coupon = new WC_Coupon($coupon_code); $order_data['coupons'][] = [ 'code' => $coupon_code, 'discount_amount' => $coupon->get_amount(), 'remaining_usage' => ($coupon->get_usage_limit_per_user() - $coupon->get_usage_count()) ]; } // Shipping and Coupon Amount Calculation if ($order->get_shipping_total() == 0) { $shipping_label = 'Free Shipping'; $shipping_cost = 0; } else { $shipping_label = 'Shipping'; $shipping_cost = $order->get_shipping_total(); } $order_data['shipping'] = [ 'label' => $shipping_label, 'cost' => $shipping_cost ]; // Total and Subtotal Data $order_total = (float)$order->get_total(); $order_subtotal = (float)$order->get_subtotal(); $coupon_total = (float)$order->get_discount_total(); $order_data['totals'] = [ 'subtotal' => $order_subtotal, 'total' => $order_total, 'discount' => $coupon_total ]; // Send the order data to Salesforce with encryption $request_payload = createOrderRequest($order, $card_number); // Create a new instance of the SalesforceSync class and send the request $sf = new SalesforceSync(SalesforceSync::kACTION_ORDER_CREATE, $request_payload); // Send the request and log the response $response = $sf->sendRequest(); // Log the raw response from Salesforce for debugging //error_log('Salesforce Response (Raw): ' . print_r($response, true)); // Decode the response (assuming it is double-encoded JSON) $decoded_response = json_decode(json_decode($response)); // Check if there are errors in the decoded response and log them if (isset($decoded_response->ErrorList)) { $error_response = serialize($decoded_response->ErrorList); //error_log('Salesforce API Error: ' . $error_response); } else { // Log the successful response if no errors are present //error_log('Salesforce Response (Decoded): ' . print_r($decoded_response, true)); } // Render the order details on the thank-you page echo site()->render("thank-you-order-details", [ "setupFeePrice" => $fees_total, "setupFeeName" => isset($order_data['fees'][0]['name']) ? $order_data['fees'][0]['name'] : '', "couponCode" => isset($order_data['coupons'][0]['code']) ? $order_data['coupons'][0]['code'] : '', "couponAmount" => $coupon_total, "monthlyFee" => $order_subtotal, "shippingLabel" => $shipping_label, "shippingCost" => $shipping_cost, "freeshippingCost" => ($shipping_cost == 0) ? 'Free' : '', "items" => array_map(function ($i) { return [ "name" => $i['name'], "image" => wc_get_product($i['product_id'])->get_image([100, 100]), // Get product image ]; }, $order_data['items']), "total" => $order_total, "fees" => $order_data['fees'] ]); }); /** * Retrieve accessories data for a product. */ function getProductAccessories($product_id) { $accessories = get_field('accessories', $product_id); $formatted_accessories = []; if (!empty($accessories)) { foreach ($accessories as $accessory) { $formatted_accessories[] = [ "AccessoryID" => $accessory['salesforce_id'], "Quantity" => 1, "Price" => $accessory['price'] ]; } } return $formatted_accessories; } /** * Creates the payload for the order to send to Salesforce. */ function createOrderRequest($order) { $shipping_comment = get_current_shipping_comment(); // Retrieve card type from order meta $card_type = get_post_meta($order->get_id(), '_card_type', true); // Retrieve other payment information from the order if needed $card_number = get_post_meta($order->get_id(), '_card_number', true); $expiration_month = get_post_meta($order->get_id(), '_expiration_month', true); $expiration_year = get_post_meta($order->get_id(), '_expiration_year', true); // Create the expiration date in the required format (e.g., "MM/YYYY") $expiration_date = sprintf('%02d/%s', $expiration_month, $expiration_year); $header = createRequestHeader(); // Get billing and shipping information from the order $billing = $order->get_address('billing'); $shipping = $order->get_address('shipping'); $payment_type = "Credit Card"; $billing_phone = preg_replace('/(\d{3})(\d{3})(\d{4})/', '$1-$2-$3', $billing['phone']); $shipping_phone = !empty($shipping['phone']) ? preg_replace('/(\d{3})(\d{3})(\d{4})/', '$1-$2-$3', $shipping['phone']) : $billing_phone; // Prepare product items and accessories $order_products = []; foreach ($order->get_items() as $item) { $product = $item->get_product(); // Get the WC_Product object $product_id = $product->get_id(); $product_sku = $product->get_sku(); $quantity = $item->get_quantity(); $rate_plan_id = null; $attributes = []; $parent_id = $product->get_parent_id(); // Get the parent variable product ID $attributes = $product->get_attributes(); // Get variation attributes // Get Rate Plan ID custom field for the variation $rate_plan_id = get_post_meta($product_id, 'rate_plan_id', true); // Include additional variation details $variation_label = implode(', ', $attributes); // Fetch accessories related to this product $accessories = getProductAccessories($item->get_product_id()); //error_log( print_r($accessories, true) ); // Add variation or product details to the order products array $order_products[] = [ 'ProductID' => $product_sku, 'Quantity' => $item->get_quantity(), 'RatePlanID' => $attributes['rate-plan-sfid'], 'Accessories' => $accessories, 'PromotionID' => $promotion_id ]; } // Create the payload structure $orderRequest = [ "RequestHeader" => $header, "RequestBody" => [ "CustomerFirstName" => $billing['first_name'], "CustomerLastName" => $billing['last_name'], "CustomerEmail" => $billing['email'], "CustomerPhoneNumber" => $billing_phone, "GCLID" => "", "UserExperience" => null, "CustomField1" => "", "CustomField2" => "", "CustomField3" => "", "CustomField4" => "", "MarketingCampaign" => "ecom campaign", "ShippingID" => $shipping_comment, "PaymentInformation" => [ "PaymentType" => $payment_type, "CardholderName" => $billing['first_name'] . ' ' . $billing['last_name'], "CardType" => $card_type, "CardNumber" => $card_number, "ExpirationDate" => $expiration_date ], "ShippingInformation" => [ "FirstName" => $shipping['first_name'], "LastName" => $shipping['last_name'], "Phone" => $shipping_phone, "Street1" => $shipping['address_1'], "Street2" => $shipping['address_2'], "City" => $shipping['city'], "State" => $shipping['state'], "PostalCode" => $shipping['postcode'], "Country" => $shipping['country'] == 'US' ? 'United States' : $shipping['country'] ], "BillingInformation" => [ "FirstName" => $billing['first_name'], "LastName" => $billing['last_name'], "Phone" => $billing_phone, "Street1" => $billing['address_1'], "Street2" => $billing['address_2'], "City" => $billing['city'], "State" => $billing['state'], "PostalCode" => $billing['postcode'], "Country" => $billing['country'] == 'US' ? 'United States' : $billing['country'] ], "OrderProducts" => $order_products ], ]; return $orderRequest; } /** * Creates a request header with a unique ID. */ function createRequestHeader() { return [ "RequestID" => "Request_" . microtime(true) ]; } if (!class_exists("SalesforceSync")) { class SalesforceSync { const kACTION_ORDER_CREATE = "CreateOrder"; const kACTION_PROFILE_CREATE ="CreateProfile"; const kAPPEND_URL = "?brand=MedicalAlert"; private $url; private $content; private $method; public function __construct($action, $content, $method = "POST") { // Appending ?brand=MedicalAlert to the URL $environment_url = get_option('id_api_salesforce', true); $this->url = "{$environment_url}/{$action}" . self::kAPPEND_URL; $this->content = $content; $this->method = $method; } public function sendRequest() { $crypto = new SecuredContent(); $encoded_content = json_encode($crypto->encode_content(json_encode($this->content))); $request = curl_init($this->url); curl_setopt($request, CURLOPT_CUSTOMREQUEST, $this->method); curl_setopt($request, CURLOPT_RETURNTRANSFER, true); curl_setopt($request, CURLOPT_POSTFIELDS, $encoded_content); curl_setopt($request, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Content-Length: ' . strlen($encoded_content), ]); // Execute the request and retrieve the response $response = curl_exec($request); curl_close($request); // Decode the encrypted response return $crypto->decode_content($response); } } } // Ensure only one item in the cart add_filter('woocommerce_add_cart_item_data', 'restrict_cart_to_one_item', 10, 3); function restrict_cart_to_one_item($cart_item_data, $product_id, $variation_id) { global $woocommerce; if (!$woocommerce->cart->is_empty()) { unset($_SESSION["one-time"]); unset($_SESSION["addOns"]); $woocommerce->cart->empty_cart(); } return $cart_item_data; } add_filter('woocommerce_checkout_fields', 'customize_billing_fields'); function customize_billing_fields($fields) { unset($fields['billing']['billing_company']); $fields['billing']['billing_first_name']['label'] = ''; $fields['billing']['billing_last_name']['label'] = ''; $fields['billing']['billing_address_1']['label'] = ''; $fields['billing']['billing_address_2']['label'] = ''; $fields['billing']['billing_city']['label'] = ''; $fields['billing']['billing_postcode']['label'] = ''; $fields['billing']['billing_phone']['label'] = ''; $fields['billing']['billing_email']['label'] = ''; $fields['billing']['billing_state']['label'] = ''; $fields['billing']['billing_state']['placeholder'] = 'Select Your State'; $fields['billing']['billing_first_name']['placeholder'] = __('First Name', 'woocommerce'); $fields['billing']['billing_last_name']['placeholder'] = __('Last Name', 'woocommerce'); $fields['billing']['billing_address_1']['placeholder'] = __('Street address', 'woocommerce'); $fields['billing']['billing_address_2']['placeholder'] = __('Apartment, suite, unit etc. (optional)', 'woocommerce'); $fields['billing']['billing_city']['placeholder'] = __('City', 'woocommerce'); $fields['billing']['billing_postcode']['placeholder'] = __('Postcode / ZIP', 'woocommerce'); $fields['billing']['billing_phone']['placeholder'] = __('Phone', 'woocommerce'); $fields['billing']['billing_email']['placeholder'] = __('Email address', 'woocommerce'); return $fields; } add_action('woocommerce_init', 'woocommerce_shipping_instances_form_fields_filters'); function woocommerce_shipping_instances_form_fields_filters(){ foreach( WC()->shipping->get_shipping_methods() as $shipping_method ) { add_filter('woocommerce_shipping_instance_form_fields_' . $shipping_method->id, 'shipping_methods_additional_custom_field'); } } function shipping_methods_additional_custom_field( $settings ) { $settings['shipping_comment'] = array( 'title' => __('Salesforce ID', 'woocommerce'), 'type' => 'text', 'placeholder' => __( 'Enter any additional comments for this shipping method.', 'woocommerce' ), ); return $settings; } add_action( 'wp_footer', 'refresh_cart'); function refresh_cart() { ?> cart->get_applied_coupons())) { return; } WC()->cart->apply_coupon($couponcode); } });