#2008-01-11 UUID to generate security_key

本文介绍如何使用Ruby语言通过uuidtools库来实现UUID的随机生成。文章详细展示了如何安装uuidtools库,并提供了具体的代码示例来生成不同的UUID字符串。
How to

1 Install
On DOS command , type this

gem install uuidtools

2 require
Add to top line on application.rb
require 'uuidtools'

Let's create
key = UUID.random_create().to_s>> UUID.random_create().to_s
UUID.random_create().to_s
=> "003b9ae0-0485-11dc-a799-005056c00008"
>> UUID.random_create().to_s
UUID.random_create().to_s
=> "051f4890-0485-11dc-a799-005056c00008"
>> UUID.random_create().to_s
UUID.random_create().to_s
=> "06b48e90-0485-11dc-a799-005056c00008"
>> UUID.random_create().to_s
UUID.random_create().to_s
=> "081ef400-0485-11dc-a799-005056c00008"
<?php defined(&#39;ABSPATH&#39;) || exit; /** * Robust partial checkout to regular /checkout/ with durable cart snapshot * - Snapshot full cart before virtualizing selection for checkout * - Do not remove anything until order is created * - On success (thank-you), rebuild cart as (snapshot - purchased) * - On cancel/back (visit cart), restore snapshot * - Guest resilience: localStorage + rehydrate AJAX */ /* ------------------------------------------------- * Helpers * ------------------------------------------------- */ function pc_get_cart_uid() { if (is_user_logged_in()) { return &#39;user_&#39; . get_current_user_id(); } if (empty($_COOKIE[&#39;pc_cart_uid&#39;])) { $token = wp_generate_uuid4(); setcookie(&#39;pc_cart_uid&#39;, $token, time() + YEAR_IN_SECONDS, COOKIEPATH ?: &#39;/&#39;, &#39;&#39;, is_ssl(), false); $_COOKIE[&#39;pc_cart_uid&#39;] = $token; } return &#39;guest_&#39; . sanitize_text_field(wp_unslash($_COOKIE[&#39;pc_cart_uid&#39;])); } function pc_build_item_key($product_id, $variation_id = 0) { return (int)$product_id . &#39;|&#39; . (int)$variation_id; } function pc_snapshot_current_cart() { if (!WC()->cart) wc_load_cart(); $items = array(); foreach (WC()->cart->get_cart() as $ci_key => $ci) { $pid = isset($ci[&#39;product_id&#39;]) ? (int)$ci[&#39;product_id&#39;] : 0; $vid = isset($ci[&#39;variation_id&#39;]) ? (int)$ci[&#39;variation_id&#39;] : 0; $qty = isset($ci[&#39;quantity&#39;]) ? wc_stock_amount($ci[&#39;quantity&#39;]) : 0; $var = isset($ci[&#39;variation&#39;]) && is_array($ci[&#39;variation&#39;]) ? $ci[&#39;variation&#39;] : array(); if ($pid && $qty > 0) { $items[] = array( &#39;product_id&#39; => $pid, &#39;variation_id&#39; => $vid, &#39;variation&#39; => array_map(&#39;wc_clean&#39;, $var), &#39;quantity&#39; => $qty, ); } } return $items; } function pc_restore_cart_from_items($items) { if (!WC()->cart) wc_load_cart(); WC()->cart->empty_cart(); foreach ((array)$items as $it) { $pid = isset($it[&#39;product_id&#39;]) ? (int)$it[&#39;product_id&#39;] : 0; $vid = isset($it[&#39;variation_id&#39;]) ? (int)$it[&#39;variation_id&#39;] : 0; $qty = isset($it[&#39;quantity&#39;]) ? wc_stock_amount($it[&#39;quantity&#39;]) : 0; $var = isset($it[&#39;variation&#39;]) && is_array($it[&#39;variation&#39;]) ? array_map(&#39;wc_clean&#39;, $it[&#39;variation&#39;]) : array(); if ($pid && $qty > 0) { WC()->cart->add_to_cart($pid, $qty, $vid, $var); } } WC()->cart->calculate_totals(); } function pc_transient_key($token) { return &#39;pc_partial_payload_&#39; . sanitize_key($token); } /* ------------------------------------------------- * AJAX: Local rehydrate when Woo cart is empty * ------------------------------------------------- */ add_action(&#39;wp_ajax_pc_rehydrate_cart&#39;, &#39;pc_rehydrate_cart&#39;); add_action(&#39;wp_ajax_nopriv_pc_rehydrate_cart&#39;, &#39;pc_rehydrate_cart&#39;); function pc_rehydrate_cart() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $raw = isset($_POST[&#39;items&#39;]) ? wp_unslash($_POST[&#39;items&#39;]) : &#39;&#39;; $items = is_string($raw) ? json_decode($raw, true) : (array)$raw; if (!is_array($items)) { wp_send_json_error(array(&#39;message&#39; => &#39;Invalid items.&#39;), 400); } if (!WC()->cart) wc_load_cart(); if (!WC()->cart->is_empty()) { wp_send_json_success(array(&#39;message&#39; => &#39;Cart not empty.&#39;)); } foreach ($items as $it) { $pid = isset($it[&#39;product_id&#39;]) ? (int)$it[&#39;product_id&#39;] : 0; $vid = isset($it[&#39;variation_id&#39;]) ? (int)$it[&#39;variation_id&#39;] : 0; $qty = isset($it[&#39;quantity&#39;]) ? wc_stock_amount($it[&#39;quantity&#39;]) : 0; $var = isset($it[&#39;variation&#39;]) && is_array($it[&#39;variation&#39;]) ? array_map(&#39;wc_clean&#39;, $it[&#39;variation&#39;]) : array(); if ($pid && $qty > 0) { WC()->cart->add_to_cart($pid, $qty, $vid, $var); } } WC()->cart->calculate_totals(); wp_send_json_success(array(&#39;rehydrated&#39; => true)); } /* ------------------------------------------------- * AJAX: Update qty (per-row; no page reload) * ------------------------------------------------- */ add_action(&#39;wp_ajax_update_cart_item_qty&#39;, &#39;pc_update_cart_item_qty&#39;); add_action(&#39;wp_ajax_nopriv_update_cart_item_qty&#39;, &#39;pc_update_cart_item_qty&#39;); function pc_update_cart_item_qty() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $key = isset($_POST[&#39;cart_item_key&#39;]) ? wc_clean(wp_unslash($_POST[&#39;cart_item_key&#39;])) : &#39;&#39;; $qty = isset($_POST[&#39;qty&#39;]) ? wc_stock_amount($_POST[&#39;qty&#39;]) : null; if (!$key || $qty === null) { wp_send_json_error(array(&#39;message&#39; => &#39;Missing params.&#39;), 400); } if (!WC()->cart) wc_load_cart(); if ($qty <= 0) { $removed = WC()->cart->remove_cart_item($key); WC()->cart->calculate_totals(); wp_send_json_success(array(&#39;removed&#39; => (bool)$removed)); } else { $set = WC()->cart->set_quantity($key, $qty, true); WC()->cart->calculate_totals(); $cart_item = WC()->cart->get_cart_item($key); if (!$cart_item) { wp_send_json_error(array(&#39;message&#39; => &#39;Cart item not found after update.&#39;), 404); } $_product = $cart_item[&#39;data&#39;]; $subtotal_html = apply_filters( &#39;woocommerce_cart_item_subtotal&#39;, WC()->cart->get_product_subtotal($_product, $cart_item[&#39;quantity&#39;]), $cart_item, $key ); // Use line_total + line_tax (after totals) for checkbox data-price $line_total_incl_tax = (float)($cart_item[&#39;line_total&#39;] + $cart_item[&#39;line_tax&#39;]); wp_send_json_success(array( &#39;subtotal_html&#39; => $subtotal_html, &#39;line_total_incl_tax&#39; => $line_total_incl_tax, &#39;removed&#39; => false, )); } } /* ------------------------------------------------- * AJAX: Remove selected * ------------------------------------------------- */ add_action(&#39;wp_ajax_remove_selected_cart_items&#39;, &#39;pc_remove_selected_cart_items&#39;); add_action(&#39;wp_ajax_nopriv_remove_selected_cart_items&#39;, &#39;pc_remove_selected_cart_items&#39;); function pc_remove_selected_cart_items() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $keys = isset($_POST[&#39;selected_items&#39;]) ? (array) $_POST[&#39;selected_items&#39;] : array(); if (!WC()->cart) wc_load_cart(); foreach ($keys as $k) { $k = wc_clean(wp_unslash($k)); WC()->cart->remove_cart_item($k); } WC()->cart->calculate_totals(); wp_send_json_success(true); } /* ------------------------------------------------- * AJAX: Empty cart * ------------------------------------------------- */ add_action(&#39;wp_ajax_empty_cart&#39;, &#39;pc_empty_cart&#39;); add_action(&#39;wp_ajax_nopriv_empty_cart&#39;, &#39;pc_empty_cart&#39;); function pc_empty_cart() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); if (!WC()->cart) wc_load_cart(); WC()->cart->empty_cart(); wp_send_json_success(true); } /* ------------------------------------------------- * AJAX: Apply coupon * ------------------------------------------------- */ add_action(&#39;wp_ajax_apply_coupon&#39;, &#39;pc_apply_coupon&#39;); add_action(&#39;wp_ajax_nopriv_apply_coupon&#39;, &#39;pc_apply_coupon&#39;); function pc_apply_coupon() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $code = isset($_POST[&#39;coupon_code&#39;]) ? wc_format_coupon_code(wp_unslash($_POST[&#39;coupon_code&#39;])) : &#39;&#39;; if (!$code) { wp_send_json_error(array(&#39;message&#39; => __(&#39;请输入优惠券代码&#39;, &#39;woocommerce&#39;)), 400); } if (!WC()->cart) wc_load_cart(); $applied = WC()->cart->apply_coupon($code); WC()->cart->calculate_totals(); if (is_wp_error($applied)) { wp_send_json_error(array(&#39;message&#39; => $applied->get_error_message()), 400); } if (!$applied) { wp_send_json_error(array(&#39;message&#39; => __(&#39;优惠券应用失败&#39;, &#39;woocommerce&#39;)), 400); } wp_send_json_success(true); } /* ------------------------------------------------- * AJAX: Start partial checkout to regular checkout page * ------------------------------------------------- */ add_action(&#39;wp_ajax_create_direct_order&#39;, &#39;pc_create_direct_order&#39;); add_action(&#39;wp_ajax_nopriv_create_direct_order&#39;, &#39;pc_create_direct_order&#39;); function pc_create_direct_order() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $selected_keys = isset($_POST[&#39;selected_items&#39;]) ? (array) $_POST[&#39;selected_items&#39;] : array(); if (empty($selected_keys)) { wp_send_json_error(array(&#39;message&#39; => __(&#39;请选择要结算的商品&#39;, &#39;woocommerce&#39;)), 400); } if (!WC()->cart) wc_load_cart(); // Snapshot full cart $snapshot = pc_snapshot_current_cart(); // Build selected items from current cart based on cart_item_key list $selected = array(); foreach (WC()->cart->get_cart() as $ci_key => $ci) { if (!in_array($ci_key, $selected_keys, true)) { continue; } $pid = (int)$ci[&#39;product_id&#39;]; $vid = (int)$ci[&#39;variation_id&#39;]; $qty = wc_stock_amount($ci[&#39;quantity&#39;]); $var = isset($ci[&#39;variation&#39;]) && is_array($ci[&#39;variation&#39;]) ? array_map(&#39;wc_clean&#39;, $ci[&#39;variation&#39;]) : array(); if ($pid && $qty > 0) { $selected[] = array( &#39;product_id&#39; => $pid, &#39;variation_id&#39; => $vid, &#39;variation&#39; => $var, &#39;quantity&#39; => $qty, ); } } if (empty($selected)) { wp_send_json_error(array(&#39;message&#39; => __(&#39;没有可结算的商品&#39;, &#39;woocommerce&#39;)), 400); } $token = wp_generate_uuid4(); $payload = array( &#39;uid&#39; => pc_get_cart_uid(), &#39;snapshot&#39; => $snapshot, &#39;selected&#39; => $selected, &#39;created&#39; => time(), ); set_transient(pc_transient_key($token), $payload, 2 * DAY_IN_SECONDS); // Put token in session (used across checkout AJAX calls) if (method_exists(WC()->session, &#39;set&#39;)) { WC()->session->set(&#39;pc_partial_token&#39;, $token); } $checkout_url = add_query_arg(&#39;pc_token&#39;, rawurlencode($token), wc_get_checkout_url()); wp_send_json_success(array(&#39;checkout_url&#39; => $checkout_url)); } /* ------------------------------------------------- * Virtualize cart on checkout for token and rebuild after purchase * ------------------------------------------------- */ // Entering checkout with token: virtualize cart to selected items add_action(&#39;woocommerce_before_checkout_form&#39;, function() { if (!isset($_GET[&#39;pc_token&#39;])) return; $token = sanitize_text_field(wp_unslash($_GET[&#39;pc_token&#39;])); $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;selected&#39;])) return; if (!WC()->cart) wc_load_cart(); // Virtualize to selected items only pc_restore_cart_from_items($payload[&#39;selected&#39;]); // Persist token in session for all subsequent checkout AJAX calls if (method_exists(WC()->session, &#39;set&#39;)) { WC()->session->set(&#39;pc_partial_token&#39;, $token); } }, 1); // Safety: just-in-time re-virtualization before order processing add_action(&#39;woocommerce_before_checkout_process&#39;, function() { if (!method_exists(WC()->session, &#39;get&#39;)) return; $token = WC()->session->get(&#39;pc_partial_token&#39;); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;selected&#39;])) return; // Ensure cart still equals selected set pc_restore_cart_from_items($payload[&#39;selected&#39;]); }, 1); // Tag order with token add_action(&#39;woocommerce_checkout_create_order&#39;, function($order) { $token = null; if (isset($_GET[&#39;pc_token&#39;])) { $token = sanitize_text_field(wp_unslash($_GET[&#39;pc_token&#39;])); } elseif (method_exists(WC()->session, &#39;get&#39;)) { $token = WC()->session->get(&#39;pc_partial_token&#39;); } if ($token) { $order->update_meta_data(&#39;_pc_partial_token&#39;, $token); $order->update_meta_data(&#39;_pc_cart_snapshot&#39;, $token); } }, 10, 1); // Fixed: Only remove purchased items from cart add_action(&#39;woocommerce_thankyou&#39;, function($order_id) { $order = wc_get_order($order_id); if (!$order) return; $token = $order->get_meta(&#39;_pc_partial_token&#39;); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;snapshot&#39;])) { if (method_exists(WC()->session, &#39;set&#39;)) { WC()->session->set(&#39;pc_partial_token&#39;, null); } delete_transient(pc_transient_key($token)); return; } // 1. Restore FULL snapshot (all items) pc_restore_cart_from_items($payload[&#39;snapshot&#39;]); WC()->cart->calculate_totals(); // 2. Remove only the purchased (selected) items foreach ($payload[&#39;selected&#39;] as $selected_item) { $cart_item_key = pc_find_cart_item($selected_item[&#39;product_id&#39;], $selected_item[&#39;variation_id&#39;]); if ($cart_item_key) { WC()->cart->remove_cart_item($cart_item_key); } } // 3. Update cart totals WC()->cart->calculate_totals(); // Cleanup token if (method_exists(WC()->session, &#39;set&#39;)) { WC()->session->set(&#39;pc_partial_token&#39;, null); } delete_transient(pc_transient_key($token)); }, 20); // Helper: Find cart item by product and variation ID function pc_find_cart_item($product_id, $variation_id = 0) { if (!WC()->cart) wc_load_cart(); foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { $cart_pid = isset($cart_item[&#39;product_id&#39;]) ? (int)$cart_item[&#39;product_id&#39;] : 0; $cart_vid = isset($cart_item[&#39;variation_id&#39;]) ? (int)$cart_item[&#39;variation_id&#39;] : 0; if ($cart_pid == $product_id && $cart_vid == $variation_id) { return $cart_item_key; } } return false; } // Visiting cart with active token: restore full snapshot (cancel/back) add_action(&#39;woocommerce_before_cart&#39;, function() { if (!method_exists(WC()->session, &#39;get&#39;)) return; $token = WC()->session->get(&#39;pc_partial_token&#39;); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;snapshot&#39;])) return; // Restore full snapshot so cart page always shows everything pc_restore_cart_from_items($payload[&#39;snapshot&#39;]); }, 1); /* ------------------------------------------------- * Keep cart count accurate during checkout process * ------------------------------------------------- */ add_filter(&#39;woocommerce_cart_contents_count&#39;, function($count) { // Check if partial token exists if (!method_exists(WC()->session, &#39;get&#39;)) return $count; $token = WC()->session->get(&#39;pc_partial_token&#39;); if ($token) { $payload = get_transient(p You generated the functions.php halfway and havent generate code for cart.ophp yet. Please coninue from if ($token) { $payload = get_transient(p
09-05
Please double check if the combination of codes are correct Functions.php cart) wc_load_cart(); $items = array(); foreach (WC()->cart->get_cart() as $ci_key => $ci) { $pid = isset($ci[‘product_id’]) ? (int)$ci[‘product_id’] : 0; $vid = isset($ci[‘variation_id’]) ? (int)$ci[‘variation_id’] : 0; $qty = isset($ci[‘quantity’]) ? wc_stock_amount($ci[‘quantity’]) : 0; $var = isset($ci[‘variation’]) && is_array($ci[‘variation’]) ? $ci[‘variation’] : array(); if ($pid && $qty > 0) { $items[] = array( ‘product_id’ => $pid, ‘variation_id’ => $vid, ‘variation’ => array_map(‘wc_clean’, $var), ‘quantity’ => $qty, ); } } return $items; } /** 从快照恢复购物车 */ function pc_restore_cart_from_items($items) { if (!WC()->cart) wc_load_cart(); WC()->cart->empty_cart(); foreach ((array)$items as $it) { $pid = isset($it[‘product_id’]) ? (int)$it[‘product_id’] : 0; $vid = isset($it[‘variation_id’]) ? (int)$it[‘variation_id’] : 0; $qty = isset($it[‘quantity’]) ? wc_stock_amount($it[‘quantity’]) : 0; $var = isset($it[‘variation’]) && is_array($it[‘variation’]) ? array_map(‘wc_clean’, $it[‘variation’]) : array(); if ($pid && $qty > 0) { WC()->cart->add_to_cart($pid, $qty, $vid, $var); } } WC()->cart->calculate_totals(); } /** 生成瞬态键名 */ function pc_transient_key($token) { return ‘pc_partial_payload_’ . sanitize_key($token); } /* ------------------------------------------------- AJAX: 当购物车为空时恢复购物车 ------------------------------------------------- */ add_action(‘wp_ajax_pc_rehydrate_cart’, ‘pc_rehydrate_cart’); add_action(‘wp_ajax_nopriv_pc_rehydrate_cart’, ‘pc_rehydrate_cart’); function pc_rehydrate_cart() { check_ajax_referer(‘woocommerce-cart’, ‘security’); $raw = isset($_POST[‘items’]) ? wp_unslash($_POST[‘items’]) : ‘’; $items = is_string($raw) ? json_decode($raw, true) : (array)$raw; if (!is_array($items)) { wp_send_json_error(array(‘message’ => ‘无效的商品数据’), 400); } if (!WC()->cart) wc_load_cart(); if (!WC()->cart->is_empty()) { wp_send_json_success(array(‘message’ => ‘购物车非空’)); } foreach ($items as $it) { $pid = isset($it[‘product_id’]) ? (int)$it[‘product_id’] : 0; $vid = isset($it[‘variation_id’]) ? (int)$it[‘variation_id’] : 0; $qty = isset($it[‘quantity’]) ? wc_stock_amount($it[‘quantity’]) : 0; $var = isset($it[‘variation’]) && is_array($it[‘variation’]) ? array_map(‘wc_clean’, $it[‘variation’]) : array(); if ($pid && $qty > 0) { WC()->cart->add_to_cart($pid, $qty, $vid, $var); } } WC()->cart->calculate_totals(); wp_send_json_success(array(‘rehydrated’ => true)); } /* ------------------------------------------------- AJAX: 更新商品数量 (无需刷新页面) ------------------------------------------------- */ add_action(‘wp_ajax_update_cart_item_qty’, ‘pc_update_cart_item_qty’); add_action(‘wp_ajax_nopriv_update_cart_item_qty’, ‘pc_update_cart_item_qty’); function pc_update_cart_item_qty() { check_ajax_referer(‘woocommerce-cart’, ‘security’); $key = isset($_POST[‘cart_item_key’]) ? wc_clean(wp_unslash($_POST[‘cart_item_key’])) : ‘’; $qty = isset($_POST[‘qty’]) ? wc_stock_amount($_POST[‘qty’]) : null; if (!$key || $qty === null) { wp_send_json_error(array(‘message’ => ‘缺少参数’), 400); } if (!WC()->cart) wc_load_cart(); if ($qty <= 0) { $removed = WC()->cart->remove_cart_item($key); WC()->cart->calculate_totals(); wp_send_json_success(array(‘removed’ => (bool)$removed)); } else { $set = WC()->cart->set_quantity($key, $qty, true); WC()->cart->calculate_totals(); $cart_item = WC()->cart->get_cart_item($key); if (!$cart_item) { wp_send_json_error(array(‘message’ => ‘更新后找不到商品’), 404); } $_product = $cart_item[‘data’]; $subtotal_html = apply_filters(‘woocommerce_cart_item_subtotal’, WC()->cart->get_product_subtotal($_product, $cart_item[‘quantity’]), $cart_item, $key); $line_total_incl_tax = (float)($cart_item[‘line_total’] + $cart_item[‘line_tax’]); wp_send_json_success(array( ‘subtotal_html’ => $subtotal_html, ‘line_total_incl_tax’ => $line_total_incl_tax, ‘removed’ => false )); } } /* ------------------------------------------------- AJAX: 删除选中商品 ------------------------------------------------- */ add_action(‘wp_ajax_remove_selected_cart_items’, ‘pc_remove_selected_cart_items’); add_action(‘wp_ajax_nopriv_remove_selected_cart_items’, ‘pc_remove_selected_cart_items’); function pc_remove_selected_cart_items() { check_ajax_referer(‘woocommerce-cart’, ‘security’); $keys = isset($_POST[‘selected_items’]) ? (array) $_POST[‘selected_items’] : array(); if (!WC()->cart) wc_load_cart(); foreach ($keys as $k) { $k = wc_clean(wp_unslash($k)); WC()->cart->remove_cart_item($k); } WC()->cart->calculate_totals(); wp_send_json_success(true); } /* ------------------------------------------------- AJAX: 清空购物车 ------------------------------------------------- */ add_action(‘wp_ajax_empty_cart’, ‘pc_empty_cart’); add_action(‘wp_ajax_nopriv_empty_cart’, ‘pc_empty_cart’); function pc_empty_cart() { check_ajax_referer(‘woocommerce-cart’, ‘security’); if (!WC()->cart) wc_load_cart(); WC()->cart->empty_cart(); wp_send_json_success(true); } /* ------------------------------------------------- AJAX: 应用优惠券 ------------------------------------------------- */ add_action(‘wp_ajax_apply_coupon’, ‘pc_apply_coupon’); add_action(‘wp_ajax_nopriv_apply_coupon’, ‘pc_apply_coupon’); function pc_apply_coupon() { check_ajax_referer(‘woocommerce-cart’, ‘security’); $code = isset($_POST[‘coupon_code’]) ? wc_format_coupon_code(wp_unslash($_POST[‘coupon_code’])) : ‘’; if (!$code) { wp_send_json_error(array(‘message’ => __(‘请输入优惠券代码’, ‘woocommerce’)), 400); } if (!WC()->cart) wc_load_cart(); $applied = WC()->cart->apply_coupon($code); WC()->cart->calculate_totals(); if (is_wp_error($applied)) { wp_send_json_error(array(‘message’ => $applied->get_error_message()), 400); } if (!$applied) { wp_send_json_error(array(‘message’ => __(‘优惠券应用失败’, ‘woocommerce’)), 400); } wp_send_json_success(true); } /* ------------------------------------------------- AJAX: 创建部分结算订单 将快照和选中商品存储在瞬态中 将会话中的token标记 返回结账URL ------------------------------------------------- */ add_action(‘wp_ajax_create_direct_order’, ‘pc_create_direct_order’); add_action(‘wp_ajax_nopriv_create_direct_order’, ‘pc_create_direct_order’); function pc_create_direct_order() { check_ajax_referer(‘woocommerce-cart’, ‘security’); // 初始化会话 if (!WC()->session) { WC()->session = new WC_Session_Handler(); WC()->session->init(); } $selected_keys = isset($_POST[‘selected_items’]) ? (array) $_POST[‘selected_items’] : array(); if (empty($selected_keys)) { wp_send_json_error(array(‘message’ => __(‘请选择要结算的商品’, ‘woocommerce’)), 400); } if (!WC()->cart) wc_load_cart(); // 创建完整购物车快照 $snapshot = pc_snapshot_current_cart(); // 提取选中商品 $selected = array(); foreach (WC()->cart->get_cart() as $ci_key => $ci) { if (!in_array($ci_key, $selected_keys, true)) { continue; } $pid = isset($ci[‘product_id’]) ? (int)$ci[‘product_id’] : 0; $vid = isset($ci[‘variation_id’]) ? (int)$ci[‘variation_id’] : 0; $qty = isset($ci[‘quantity’]) ? wc_stock_amount($ci[‘quantity’]) : 0; $var = isset($ci[‘variation’]) && is_array($ci[‘variation’]) ? array_map(‘wc_clean’, $ci[‘variation’]) : array(); if ($pid && $qty > 0) { $selected[] = array( ‘product_id’ => $pid, ‘variation_id’ => $vid, ‘variation’ => $var, ‘quantity’ => $qty, ); } } if (empty($selected)) { wp_send_json_error(array(‘message’ => __(‘没有可结算的商品’, ‘woocommerce’)), 400); } $token = wp_generate_uuid4(); $payload = array( ‘uid’ => pc_get_cart_uid(), ‘snapshot’ => $snapshot, ‘selected’ => $selected, ‘created’ => time(), ); set_transient(pc_transient_key($token), $payload, 2 * DAY_IN_SECONDS); // 将token存入会话 if (method_exists(WC()->session, ‘set’)) { WC()->session->set(‘pc_partial_token’, $token); } $checkout_url = add_query_arg(‘pc_token’, rawurlencode($token), wc_get_checkout_url()); wp_send_json_success(array(‘checkout_url’ => $checkout_url)); } /* ------------------------------------------------- 结账流程处理 根据token虚拟化购物车 处理前确保重新虚拟化 订单标记token 感谢页重建购物车 返回购物车时恢复快照 ------------------------------------------------- */ // 进入结账页时虚拟化购物车 add_action(‘woocommerce_before_checkout_form’, ‘pc_virtualize_cart_on_checkout’, 1); function pc_virtualize_cart_on_checkout() { if (!isset($_GET[‘pc_token’])) return; $token = sanitize_text_field(wp_unslash($_GET[‘pc_token’])); $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[‘selected’])) return; if (!WC()->cart) wc_load_cart(); // 仅加载选中商品 pc_restore_cart_from_items($payload[‘selected’]); // 持久化token用于后续AJAX调用 if (method_exists(WC()->session, ‘set’)) { WC()->session->set(‘pc_partial_token’, $token); } } // 订单处理前再次确保虚拟化 add_action(‘woocommerce_before_checkout_process’, ‘pc_revirtualize_before_processing’, 1); function pc_revirtualize_before_processing() { if (!method_exists(WC()->session, ‘get’)) return; $token = WC()->session->get(‘pc_partial_token’); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[‘selected’])) return; pc_restore_cart_from_items($payload[‘selected’]); } // 订单标记token add_action(‘woocommerce_checkout_create_order’, ‘pc_tag_order_with_token’, 10, 1); function pc_tag_order_with_token($order) { $token = null; if (isset($_GET[‘pc_token’])) { $token = sanitize_text_field(wp_unslash($_GET[‘pc_token’])); } elseif (method_exists(WC()->session, ‘get’)) { $token = WC()->session->get(‘pc_partial_token’); } if ($token) { $order->update_meta_data(‘_pc_partial_token’, $token); } } // 感谢页重建购物车 add_action(‘woocommerce_thankyou’, ‘pc_rebuild_cart_on_thankyou’, 20); function pc_rebuild_cart_on_thankyou($order_id) { $order = wc_get_order($order_id); if (!$order) return; $token = $order->get_meta(‘_pc_partial_token’); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[‘snapshot’])) { // 清理会话token if (method_exists(WC()->session, ‘set’)) { WC()->session->set(‘pc_partial_token’, null); } delete_transient(pc_transient_key($token)); return; } // 创建已购商品映射表 $purchased = array(); foreach ($order->get_items() as $item) { $pid = (int)$item->get_product_id(); $vid = (int)$item->get_variation_id(); $qty = (int)$item->get_quantity(); $k = pc_build_item_key($pid, $vid); if (!isset($purchased[$k])) $purchased[$k] = 0; $purchased[$k] += $qty; } // 剩余商品 = 快照 - 已购 $remainder = array(); foreach ($payload[‘snapshot’] as $it) { $pid = isset($it[‘product_id’]) ? (int)$it[‘product_id’] : 0; $vid = isset($it[‘variation_id’]) ? (int)$it[‘variation_id’] : 0; $qty = isset($it[‘quantity’]) ? wc_stock_amount($it[‘quantity’]) : 0; $var = isset($it[‘variation’]) ? $it[‘variation’] : array(); $k = pc_build_item_key($pid, $vid); $take = isset($purchased[$k]) ? (int)$purchased[$k] : 0; $left = max(0, $qty - $take); if ($left > 0) { $remainder[] = array( ‘product_id’ => $pid, ‘variation_id’ => $vid, ‘variation’ => $var, ‘quantity’ => $left, ); $purchased[$k] = max(0, $take - $qty); } } // 重建剩余商品的购物车 pc_restore_cart_from_items($remainder); // 清理会话token if (method_exists(WC()->session, ‘set’)) { WC()->session->set(‘pc_partial_token’, null); } delete_transient(pc_transient_key($token)); } /* ------------------------------------------------- 支付取消处理 当订单取消时恢复原始购物车 ------------------------------------------------- */ add_action(‘woocommerce_cancelled_order’, ‘pc_restore_cart_on_cancellation’); function pc_restore_cart_on_cancellation($order_id) { $order = wc_get_order($order_id); if (!$order) return; $token = $order->get_meta(‘_pc_partial_token’); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[‘snapshot’])) { delete_transient(pc_transient_key($token)); return; } // 恢复完整购物车快照 pc_restore_cart_from_items($payload[‘snapshot’]); // 清理会话token if (method_exists(WC()->session, ‘set’)) { WC()->session->set(‘pc_partial_token’, null); } delete_transient(pc_transient_key($token)); } /* ------------------------------------------------- 跨标签页购物车同步 使用localStorage实现 ------------------------------------------------- */ add_action(‘wp_footer’, function() { if (!class_exists(‘WooCommerce’)) return; ?> session->get(‘original_cart’)) { $data[‘count’] = count($original); } return $data; }); /* ------------------------------------------------- 辅助函数:生成UUIDv4 ------------------------------------------------- */ if (!function_exists(‘wp_generate_uuid4’)) { function wp_generate_uuid4() { return sprintf(‘%04x%04x-%04x-%04x-%04x-%04x%04x%04x’, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) ); } } /* ------------------------------------------------- 会话初始化保障 ------------------------------------------------- */ add_action(‘woocommerce_init’, function() { if (!WC()->session) { WC()->session = new WC_Session_Handler(); WC()->session->init(); } }); Cart.php " method=“post”> <input type="hidden" id="selected_items" name="selected_items" value=""> do_action(‘woocommerce_before_cart’); // Provide tiny context for JS (invisible; no layout change) $pc_cart_is_empty = WC()->cart->is_empty(); function pc_uid_for_view() { if (is_user_logged_in()) return ‘user_’ . get_current_user_id(); if (empty($_COOKIE[‘pc_cart_uid’])) { $token = wp_generate_uuid4(); setcookie(‘pc_cart_uid’, $token, time() + YEAR_IN_SECONDS, COOKIEPATH ?: ‘/’, ‘’, is_ssl(), false); $COOKIE[‘pc_cart_uid’] = $token; } return &#39;guest’ . sanitize_text_field(wp_unslash($_COOKIE[‘pc_cart_uid’])); } $pc_uid = pc_uid_for_view(); ?> <div class="cart-page-section container" style="max-width: 1200px; margin: 0 auto;"> <form class="woocommerce-cart-form" action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post"> cart->get_cart() as $cart_item_key => $cart_item ) : ?> exists() && $cart_item[&#39;quantity&#39;] > 0 && apply_filters(&#39;woocommerce_cart_item_visible&#39;, true, $cart_item, $cart_item_key) ) : $product_permalink = apply_filters(&#39;woocommerce_cart_item_permalink&#39;, $_product->is_visible() ? $_product->get_permalink($cart_item) : &#39;&#39;, $cart_item, $cart_item_key); $line_total_value = (float) ($cart_item[&#39;line_total&#39;] + $cart_item[&#39;line_tax&#39;]); $variation_id = isset($cart_item[&#39;variation_id&#39;]) ? (int)$cart_item[&#39;variation_id&#39;] : 0; $variation_data = isset($cart_item[&#39;variation&#39;]) ? $cart_item[&#39;variation&#39;] : array(); $variation_json = wp_json_encode($variation_data); ?> <table class="shop_table shop_table_responsive cart woocommerce-cart-form__contents"> <thead> <tr> <th class="product-select" style="width: 8%;"> <input type="checkbox" id="select-all-items"> <label for="select-all-items" style="display: inline-block; margin-left: 5px; cursor: pointer;">全选</label> </th> <th class="product-info"></th> <th class="product-price"></th> <th class="product-quantity"></th> <th class="product-subtotal"></th> <th class="product-remove"></th> </tr> </thead> <tbody> <tr class="woocommerce-cart-form__cart-item <?php echo esc_attr( apply_filters(&#39;woocommerce_cart_item_class&#39;, &#39;cart_item&#39;, $cart_item, $cart_item_key) ); ?>" data-cart_item_key="<?php echo esc_attr($cart_item_key); ?>" data-product_id="<?php echo esc_attr($product_id); ?>" data-variation_id="<?php echo esc_attr($variation_id); ?>" data-variation="<?php echo esc_attr($variation_json); ?>"> <td class="product-select" data-title="<?php esc_attr_e(&#39;Select&#39;, &#39;woocommerce&#39;); ?>"> <input type="checkbox" class="item-checkbox" name="selected_items[]" value="<?php echo esc_attr($cart_item_key); ?>" data-price="<?php echo esc_attr($line_total_value); ?>"> </td> <td class="product-info" data-title="<?php esc_attr_e(&#39;Product&#39;, &#39;woocommerce&#39;); ?>"> <div class="product-image"> get_image(), $cart_item, $cart_item_key); if ( ! $product_permalink ) : echo $thumbnail; // PHPCS: XSS ok. else : printf(&#39;<a href="%s">%s</a>&#39;, esc_url($product_permalink), $thumbnail); // PHPCS: XSS ok. endif; ?> </div> <div class="product-name"> get_name(), $cart_item, $cart_item_key) . &#39; &#39; ); else : echo wp_kses_post( apply_filters(&#39;woocommerce_cart_item_name&#39;, sprintf(&#39;<a href="%s">%s</a>&#39;, esc_url($product_permalink), $_product->get_name()), $cart_item, $cart_item_key) ); endif; do_action(&#39;woocommerce_after_cart_item_name&#39;, $cart_item, $cart_item_key); echo wc_get_formatted_cart_item_data($cart_item); // PHPCS: XSS ok. ?> </div> </td> <td class="product-price" data-title="<?php esc_attr_e(&#39;Price&#39;, &#39;woocommerce&#39;); ?>"> cart->get_product_price($_product), $cart_item, $cart_item_key); // PHPCS: XSS ok. ?> </td> <td class="product-quantity" data-title="<?php esc_attr_e(&#39;Quantity&#39;, &#39;woocommerce&#39;); ?>"> is_sold_individually() ) : $product_quantity = sprintf(&#39;1 <input type="hidden" name="cart[%s][qty]" value="1">&#39;, $cart_item_key); else : $product_quantity = woocommerce_quantity_input( array( &#39;input_name&#39; => "cart[{$cart_item_key}][qty]", &#39;input_value&#39; => $cart_item[&#39;quantity&#39;], &#39;max_value&#39; => $_product->get_max_purchase_quantity(), &#39;min_value&#39; => &#39;0&#39;, &#39;product_name&#39; => $_product->get_name(), ), $_product, false ); endif; echo apply_filters(&#39;woocommerce_cart_item_quantity&#39;, $product_quantity, $cart_item_key, $cart_item); // PHPCS: XSS ok. ?> <small class="qty-status" style="display:none;margin-left:8px;color:#666;">保存中…</small> </td> <td class="product-subtotal" data-title="<?php esc_attr_e(&#39;Subtotal&#39;, &#39;woocommerce&#39;); ?>"> cart->get_product_subtotal($_product, $cart_item[&#39;quantity&#39;]), $cart_item, $cart_item_key); // PHPCS: XSS ok. ?> </td> <td class="product-remove" data-title="<?php esc_attr_e(&#39;操作&#39;, &#39;woocommerce&#39;); ?>"> ×&#39;, esc_url( wc_get_cart_remove_url($cart_item_key) ), esc_attr__(&#39;Remove this item&#39;, &#39;woocommerce&#39;), esc_attr($product_id), esc_attr($_product->get_sku()) ), $cart_item_key); ?> </td> </tr> </tbody> </table> </form> </div> <div class="cart-footer-actions sticky-footer" style="position: sticky; bottom: 0; background: white; padding: 15px; border-top: 1px solid #ddd; max-width: 1200px; margin: 0 auto;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> <div class="footer-left"> <input type="checkbox" id="footer-select-all"> <label for="footer-select-all" style="display: inline-block; margin-left: 5px; cursor: pointer;">全选</label> <button type="button" class="button" id="remove-selected-items">刪除選中的商品</button> <button type="button" class="button" id="clear-cart">清空購物車</button> </div> <div class="coupon-section"> <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="输入优惠券代码" style="padding: 8px; width: 200px; border: 1px solid #ddd; border-radius: 4px; margin-right: 5px;"> <button type="button" class="button" id="apply-coupon">应用优惠券</button> </div> </div> <div style="display: flex; justify-content: space-between; align-items: center;"> <div class="selected-summary" style="font-size: 16px; font-weight: bold;"> 已选商品: <span id="selected-count">0</span> 件,共计: <span id="selected-total">RM0.00</span> </div> <a href="<?php echo esc_url( wc_get_checkout_url() ); ?>" class="checkout-button button alt wc-forward" id="partial-checkout">结算</a> </div> </div> form-checkout.php session) return; // 从会话获取选中商品 $selected_keys = WC()->session->get(‘pc_selected_items’) ?: []; // 存储原始购物车 if(empty(WC()->session->get(‘original_cart’))) { WC()->session->set(‘original_cart’, WC()->cart->get_cart()); // 创建临时结账购物车 $checkout_cart = []; foreach(WC()->cart->get_cart() as $key => $item) { if(in_array($key, $selected_keys)) { $checkout_cart[$key] = $item; } } WC()->session->set(‘checkout_cart’, $checkout_cart); // 更新实际购物车 WC()->cart->empty_cart(); foreach($checkout_cart as $key => $item) { WC()->cart->add_to_cart( $item[‘product_id’], $item[‘quantity’], $item[‘variation_id’], $item[‘variation’] ); } } }, 5); if ( ! defined( ‘ABSPATH’ ) ) { exit; } //WC 3.5.0 if ( function_exists( ‘WC’ ) && version_compare( WC()->version, ‘3.5.0’, ‘<’ ) ) { wc_print_notices(); } do_action( ‘woocommerce_before_checkout_form’, $checkout ); // If checkout registration is disabled and not logged in, the user cannot checkout. if ( ! $checkout->is_registration_enabled() && $checkout->is_registration_required() && ! is_user_logged_in() ) { echo esc_html( apply_filters( ‘woocommerce_checkout_must_be_logged_in_message’, __( ‘You must be logged in to checkout.’, ‘woocommerce’ ) ) ); return; } // filter hook for include new pages inside the payment method $get_checkout_url = apply_filters( ‘woocommerce_get_checkout_url’, wc_get_checkout_url() ); ?> <form name="checkout" method="post" class="checkout woocommerce-checkout" action="<?php echo esc_url( $get_checkout_url ); ?>" enctype="multipart/form-data" aria-label="<?php echo esc_attr__( &#39;Checkout&#39;, &#39;woocommerce&#39; ); ?>"> get_checkout_fields() ) : ?> <div class="customer-details" id="customer_details"> </div> <div class="checkout-order-review"> <h3 id="order_review_heading"></h3> <div id="order_review" class="woocommerce-checkout-review-order"> </div> </div> </form> order-create.php session) return; $checkout_cart = WC()->session->get(‘checkout_cart’) ?: []; $original_cart = WC()->session->get(‘original_cart’) ?: []; // 从原始购物车移除已结算商品 foreach($checkout_cart as $key => $item) { if(isset($original_cart[$key])) { unset($original_cart[$key]); } } // 更新实际购物车 WC()->cart->empty_cart(); foreach($original_cart as $key => $item) { WC()->cart->add_to_cart( $item[‘product_id’], $item[‘quantity’], $item[‘variation_id’], $item[‘variation’], // 必须包含变体属性 $item[‘cart_item_data’] ); } // 清理session WC()->session->__unset(‘original_cart’); WC()->session->__unset(‘checkout_cart’); } payment-cancel.php session->get(‘original_cart’)) { WC()->cart->empty_cart(); foreach($original_cart as $key => $item) { WC()->cart->add_to_cart( $item[‘product_id’], $item[‘quantity’], $item[‘variation_id’], $item[‘variation’], $item[‘cart_item_data’] ); } } // 清理session WC()->session->__unset(‘original_cart’); WC()->session->__unset(‘checkout_cart’); // 重定向到购物车 wp_redirect(wc_get_cart_url()); exit; } } these are the full code for these file. If wrong, please give me the full code to be replaced with the current one.
09-03
<?php defined(&#39;ABSPATH&#39;) || exit; /** * Robust partial checkout to regular /checkout/ with durable cart snapshot * - Snapshot full cart before virtualizing selection for checkout * - Do not remove anything until order is created * - On success (thank-you), rebuild cart as (snapshot - purchased) * - On cancel/back (visit cart), restore snapshot * - Guest resilience: localStorage + rehydrate AJAX */ /* ------------------------------------------------- * Helpers * ------------------------------------------------- */ /** * 新增:购物车数量AJAX端点 */ add_action(&#39;wp_ajax_get_cart_count&#39;, &#39;pc_get_cart_count&#39;); add_action(&#39;wp_ajax_nopriv_get_cart_count&#39;, &#39;pc_get_cart_count&#39;); function pc_get_cart_count() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $count = WC()->cart->get_cart_contents_count(); wp_send_json_success(array(&#39;count&#39; => $count)); } function pc_get_cart_uid() { if (is_user_logged_in()) { return &#39;user_&#39; . get_current_user_id(); } if (empty($_COOKIE[&#39;pc_cart_uid&#39;])) { $token = wp_generate_uuid4(); setcookie(&#39;pc_cart_uid&#39;, $token, time() + YEAR_IN_SECONDS, COOKIEPATH ?: &#39;/&#39;, &#39;&#39;, is_ssl(), false); $_COOKIE[&#39;pc_cart_uid&#39;] = $token; } return &#39;guest_&#39; . sanitize_text_field(wp_unslash($_COOKIE[&#39;pc_cart_uid&#39;])); } function pc_build_item_key($product_id, $variation_id = 0) { return (int)$product_id . &#39;|&#39; . (int)$variation_id; } function pc_snapshot_current_cart() { if (!WC()->cart) wc_load_cart(); $items = array(); foreach (WC()->cart->get_cart() as $ci_key => $ci) { $pid = isset($ci[&#39;product_id&#39;]) ? (int)$ci[&#39;product_id&#39;] : 0; $vid = isset($ci[&#39;variation_id&#39;]) ? (int)$ci[&#39;variation_id&#39;] : 0; $qty = isset($ci[&#39;quantity&#39;]) ? wc_stock_amount($ci[&#39;quantity&#39;]) : 0; $var = isset($ci[&#39;variation&#39;]) && is_array($ci[&#39;variation&#39;]) ? $ci[&#39;variation&#39;] : array(); if ($pid && $qty > 0) { $items[] = array( &#39;product_id&#39; => $pid, &#39;variation_id&#39; => $vid, &#39;variation&#39; => array_map(&#39;wc_clean&#39;, $var), &#39;quantity&#39; => $qty, ); } } return $items; } function pc_restore_cart_from_items($items) { if (!WC()->cart) wc_load_cart(); WC()->cart->empty_cart(); foreach ((array)$items as $it) { $pid = isset($it[&#39;product_id&#39;]) ? (int)$it[&#39;product_id&#39;] : 0; $vid = isset($it[&#39;variation_id&#39;]) ? (int)$it[&#39;variation_id&#39;] : 0; $qty = isset($it[&#39;quantity&#39;]) ? wc_stock_amount($it[&#39;quantity&#39;]) : 0; $var = isset($it[&#39;variation&#39;]) && is_array($it[&#39;variation&#39;]) ? array_map(&#39;wc_clean&#39;, $it[&#39;variation&#39;]) : array(); if ($pid && $qty > 0) { WC()->cart->add_to_cart($pid, $qty, $vid, $var); } } WC()->cart->calculate_totals(); } // Fixed: Check WC() and session existence before method_exists add_action(&#39;wp_loaded&#39;, function() { if (!function_exists(&#39;WC&#39;) || !WC() || !property_exists(WC(), &#39;session&#39;)) { return; } if (!method_exists(WC()->session, &#39;get&#39;)) return; $token = WC()->session->get(&#39;pc_partial_token&#39;); if ($token && WC()->cart->is_empty()) { $payload = get_transient(pc_transient_key($token)); if (!empty($payload[&#39;snapshot&#39;])) { pc_restore_cart_from_items($payload[&#39;snapshot&#39;]); WC()->cart->calculate_totals(); } } }, 20); function pc_transient_key($token) { return &#39;pc_partial_payload_&#39; . sanitize_key($token); } /* ------------------------------------------------- * AJAX: Local rehydrate when Woo cart is empty * ------------------------------------------------- */ add_action(&#39;wp_ajax_pc_rehydrate_cart&#39;, &#39;pc_rehydrate_cart&#39;); add_action(&#39;wp_ajax_nopriv_pc_rehydrate_cart&#39;, &#39;pc_rehydrate_cart&#39;); function pc_rehydrate_cart() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $raw = isset($_POST[&#39;items&#39;]) ? wp_unslash($_POST[&#39;items&#39;]) : &#39;&#39;; $items = is_string($raw) ? json_decode($raw, true) : (array)$raw; if (!is_array($items)) { wp_send_json_error(array(&#39;message&#39; => &#39;Invalid items.&#39;), 400); } if (!WC()->cart) wc_load_cart(); if (!WC()->cart->is_empty()) { wp_send_json_success(array(&#39;message&#39; => &#39;Cart not empty.&#39;)); } foreach ($items as $it) { $pid = isset($it[&#39;product_id&#39;]) ? (int)$it[&#39;product_id&#39;] : 0; $vid = isset($it[&#39;variation_id&#39;]) ? (int)$it[&#39;variation_id&#39;] : 0; $qty = isset($it[&#39;quantity&#39;]) ? wc_stock_amount($it[&#39;quantity&#39;]) : 0; $var = isset($it[&#39;variation&#39;]) && is_array($it[&#39;variation&#39;]) ? array_map(&#39;wc_clean&#39;, $it[&#39;variation&#39;]) : array(); if ($pid && $qty > 0) { WC()->cart->add_to_cart($pid, $qty, $vid, $var); } } WC()->cart->calculate_totals(); wp_send_json_success(array(&#39;rehydrated&#39; => true)); } /* ------------------------------------------------- * AJAX: Update qty (per-row; no page reload) * ------------------------------------------------- */ add_action(&#39;wp_ajax_update_cart_item_qty&#39;, &#39;pc_update_cart_item_qty&#39;); add_action(&#39;wp_ajax_nopriv_update_cart_item_qty&#39;, &#39;pc_update_cart_item_qty&#39;); function pc_update_cart_item_qty() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $key = isset($_POST[&#39;cart_item_key&#39;]) ? wc_clean(wp_unslash($_POST[&#39;cart_item_key&#39;])) : &#39;&#39;; $qty = isset($_POST[&#39;qty&#39;]) ? wc_stock_amount($_POST[&#39;qty&#39;]) : null; if (!$key || $qty === null) { wp_send_json_error(array(&#39;message&#39; => &#39;Missing params.&#39;), 400); } if (!WC()->cart) wc_load_cart(); if ($qty <= 0) { $removed = WC()->cart->remove_cart_item($key); WC()->cart->calculate_totals(); wp_send_json_success(array(&#39;removed&#39; => (bool)$removed)); } else { $set = WC()->cart->set_quantity($key, $qty, true); WC()->cart->calculate_totals(); $cart_item = WC()->cart->get_cart_item($key); if (!$cart_item) { wp_send_json_error(array(&#39;message&#39; => &#39;Cart item not found after update.&#39;), 404); } $_product = $cart_item[&#39;data&#39;]; $subtotal_html = apply_filters( &#39;woocommerce_cart_item_subtotal&#39;, WC()->cart->get_product_subtotal($_product, $cart_item[&#39;quantity&#39;]), $cart_item, $key ); // Use line_total + line_tax (after totals) for checkbox data-price $line_total_incl_tax = (float)($cart_item[&#39;line_total&#39;] + $cart_item[&#39;line_tax&#39;]); wp_send_json_success(array( &#39;subtotal_html&#39; => $subtotal_html, &#39;line_total_incl_tax&#39; => $line_total_incl_tax, &#39;removed&#39; => false, )); } } /* ------------------------------------------------- * AJAX: Remove selected * ------------------------------------------------- */ add_action(&#39;wp_ajax_remove_selected_cart_items&#39;, &#39;pc_remove_selected_cart_items&#39;); add_action(&#39;wp_ajax_nopriv_remove_selected_cart_items&#39;, &#39;pc_remove_selected_cart_items&#39;); function pc_remove_selected_cart_items() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $keys = isset($_POST[&#39;selected_items&#39;]) ? (array) $_POST[&#39;selected_items&#39;] : array(); if (!WC()->cart) wc_load_cart(); foreach ($keys as $k) { $k = wc_clean(wp_unslash($k)); WC()->cart->remove_cart_item($k); } WC()->cart->calculate_totals(); wp_send_json_success(true); } /* ------------------------------------------------- * AJAX: Empty cart * ------------------------------------------------- */ add_action(&#39;wp_ajax_empty_cart&#39;, &#39;pc_empty_cart&#39;); add_action(&#39;wp_ajax_nopriv_empty_cart&#39;, &#39;pc_empty_cart&#39;); function pc_empty_cart() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); if (!WC()->cart) wc_load_cart(); WC()->cart->empty_cart(); wp_send_json_success(true); } /* ------------------------------------------------- * AJAX: Apply coupon * ------------------------------------------------- */ add_action(&#39;wp_ajax_apply_coupon&#39;, &#39;pc_apply_coupon&#39;); add_action(&#39;wp_ajax_nopriv_apply_coupon&#39;, &#39;pc_apply_coupon&#39;); function pc_apply_coupon() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $code = isset($_POST[&#39;coupon_code&#39;]) ? wc_format_coupon_code(wp_unslash($_POST[&#39;coupon_code&#39;])) : &#39;&#39;; if (!$code) { wp_send_json_error(array(&#39;message&#39; => __(&#39;请输入优惠券代码&#39;, &#39;woocommerce&#39;)), 400); } if (!WC()->cart) wc_load_cart(); $applied = WC()->cart->apply_coupon($code); WC()->cart->calculate_totals(); if (is_wp_error($applied)) { wp_send_json_error(array(&#39;message&#39; => $applied->get_error_message()), 400); } if (!$applied) { wp_send_json_error(array(&#39;message&#39; => __(&#39;优惠券应用失败&#39;, &#39;woocommerce&#39;)), 400); } wp_send_json_success(true); } /* ------------------------------------------------- * AJAX: Start partial checkout to regular checkout page * ------------------------------------------------- */ add_action(&#39;wp_ajax_create_direct_order&#39;, &#39;pc_create_direct_order&#39;); add_action(&#39;wp_ajax_nopriv_create_direct_order&#39;, &#39;pc_create_direct_order&#39;); function pc_create_direct_order() { check_ajax_referer(&#39;woocommerce-cart&#39;, &#39;security&#39;); $selected_keys = isset($_POST[&#39;selected_items&#39;]) ? (array) $_POST[&#39;selected_items&#39;] : array(); if (empty($selected_keys)) { wp_send_json_error(array(&#39;message&#39; => __(&#39;请选择要结算的商品&#39;, &#39;woocommerce&#39;)), 400); } if (!WC()->cart) wc_load_cart(); // Snapshot full cart $snapshot = pc_snapshot_current_cart(); // Build selected items from current cart based on cart_item_key list $selected = array(); foreach (WC()->cart->get_cart() as $ci_key => $ci) { if (!in_array($ci_key, $selected_keys, true)) { continue; } $pid = (int)$ci[&#39;product_id&#39;]; $vid = (int)$ci[&#39;variation_id&#39;]; $qty = wc_stock_amount($ci[&#39;quantity&#39;]); $var = isset($ci[&#39;variation&#39;]) && is_array($ci[&#39;variation&#39;]) ? array_map(&#39;wc_clean&#39;, $ci[&#39;variation&#39;]) : array(); if ($pid && $qty > 0) { $selected[] = array( &#39;product_id&#39; => $pid, &#39;variation_id&#39; => $vid, &#39;variation&#39; => $var, &#39;quantity&#39; => $qty, ); } } if (empty($selected)) { wp_send_json_error(array(&#39;message&#39; => __(&#39;没有可结算的商品&#39;, &#39;woocommerce&#39;)), 400); } $token = wp_generate_uuid4(); $payload = array( &#39;uid&#39; => pc_get_cart_uid(), &#39;snapshot&#39; => $snapshot, &#39;selected&#39; => $selected, &#39;created&#39; => time(), ); set_transient(pc_transient_key($token), $payload, 2 * DAY_IN_SECONDS); // Put token in session (used across checkout AJAX calls) if (method_exists(WC()->session, &#39;set&#39;)) { WC()->session->set(&#39;pc_partial_token&#39;, $token); } $checkout_url = add_query_arg(&#39;pc_token&#39;, rawurlencode($token), wc_get_checkout_url()); wp_send_json_success(array(&#39;checkout_url&#39; => $checkout_url)); } /* ------------------------------------------------- * Virtualize cart on checkout for token and rebuild after purchase * ------------------------------------------------- */ // Entering checkout with token: virtualize cart to selected items add_action(&#39;woocommerce_before_checkout_form&#39;, function() { if (!isset($_GET[&#39;pc_token&#39;])) return; $token = sanitize_text_field(wp_unslash($_GET[&#39;pc_token&#39;])); $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;selected&#39;])) return; if (!WC()->cart) wc_load_cart(); // Virtualize to selected items only pc_restore_cart_from_items($payload[&#39;selected&#39;]); // Persist token in session for all subsequent checkout AJAX calls if (method_exists(WC()->session, &#39;set&#39;)) { WC()->session->set(&#39;pc_partial_token&#39;, $token); } }, 1); // Safety: just-in-time re-virtualization before order processing add_action(&#39;woocommerce_before_checkout_process&#39;, function() { if (!method_exists(WC()->session, &#39;get&#39;)) return; $token = WC()->session->get(&#39;pc_partial_token&#39;); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;selected&#39;])) return; // Ensure cart still equals selected set pc_restore_cart_from_items($payload[&#39;selected&#39;]); }, 1); // Tag order with token add_action(&#39;woocommerce_checkout_create_order&#39;, function($order) { $token = null; if (isset($_GET[&#39;pc_token&#39;])) { $token = sanitize_text_field(wp_unslash($_GET[&#39;pc_token&#39;])); } elseif (method_exists(WC()->session, &#39;get&#39;)) { $token = WC()->session->get(&#39;pc_partial_token&#39;); } if ($token) { $order->update_meta_data(&#39;_pc_partial_token&#39;, $token); $order->update_meta_data(&#39;_pc_cart_snapshot&#39;, $token); } }, 10, 1); // Fixed: Only remove purchased items from cart add_action(&#39;woocommerce_thankyou&#39;, function($order_id) { $order = wc_get_order($order_id); if (!$order) return; $token = $order->get_meta(&#39;_pc_partial_token&#39;); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;snapshot&#39;])) { if (method_exists(WC()->session, &#39;set&#39;)) { WC()->session->set(&#39;pc_partial_token&#39;, null); } delete_transient(pc_transient_key($token)); return; } // 1. Restore FULL snapshot (all items) pc_restore_cart_from_items($payload[&#39;snapshot&#39;]); WC()->cart->calculate_totals(); // 2. Remove only the purchased (selected) items foreach ($payload[&#39;selected&#39;] as $selected_item) { $cart_item_key = pc_find_cart_item($selected_item[&#39;product_id&#39;], $selected_item[&#39;variation_id&#39;]); if ($cart_item_key) { WC()->cart->remove_cart_item($cart_item_key); } } // 3. Update cart totals WC()->cart->calculate_totals(); // Cleanup token if (method_exists(WC()->session, &#39;set&#39;)) { WC()->session->set(&#39;pc_partial_token&#39;, null); } delete_transient(pc_transient_key($token)); }, 20); // Helper: Find cart item by product and variation ID function pc_find_cart_item($product_id, $variation_id = 0) { if (!WC()->cart) wc_load_cart(); foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { $cart_pid = isset($cart_item[&#39;product_id&#39;]) ? (int)$cart_item[&#39;product_id&#39;] : 0; $cart_vid = isset($cart_item[&#39;variation_id&#39;]) ? (int)$cart_item[&#39;variation_id&#39;] : 0; if ($cart_pid == $product_id && $cart_vid == $variation_id) { return $cart_item_key; } } return false; } // Visiting cart with active token: restore full snapshot (cancel/back) add_action(&#39;woocommerce_before_cart&#39;, function() { if (!method_exists(WC()->session, &#39;get&#39;)) return; $token = WC()->session->get(&#39;pc_partial_token&#39;); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;snapshot&#39;])) return; // Restore full snapshot so cart page always shows everything pc_restore_cart_from_items($payload[&#39;snapshot&#39;]); }, 1); /* ------------------------------------------------- * Keep cart count accurate during checkout process * ------------------------------------------------- */ add_filter(&#39;woocommerce_cart_contents_count&#39;, function($count) { // Check if partial token exists if (!method_exists(WC()->session, &#39;get&#39;)) return $count; $token = WC()->session->get(&#39;pc_partial_token&#39;); if ($token) { $payload = get_transient(pc_transient_key($token)); // Always show full cart count even during checkout if (!empty($payload[&#39;snapshot&#39;])) { $snapshot_count = 0; foreach ($payload[&#39;snapshot&#39;] as $item) { $snapshot_count += (int)$item[&#39;quantity&#39;]; } return $snapshot_count; } } return $count; }); // Ensure cart item totals are accurate in header add_action(&#39;woocommerce_before_cart&#39;, function() { pc_maintain_cart_consistency(); }); add_action(&#39;woocommerce_before_checkout_form&#39;, function() { pc_maintain_cart_consistency(); }); function pc_maintain_cart_consistency() { if (!method_exists(WC()->session, &#39;get&#39;)) return; $token = WC()->session->get(&#39;pc_partial_token&#39;); if (!$token) return; $payload = get_transient(pc_transient_key($token)); if (empty($payload) || empty($payload[&#39;snapshot&#39;])) return; // Immediately restore full cart for consistent UI pc_restore_cart_from_items($payload[&#39;snapshot&#39;]); WC()->cart->calculate_totals(); } it says Your PHP code changes were not applied due to an error on line 86 of file wp-content/themes/woodmart-child/functions.php. Please fix and try saving again. Uncaught TypeError: method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given in wp-content/themes/woodmart-child/functions.php:86 Stack trace: #0 wp-content/themes/woodmart-child/functions.php(86): method_exists() #1 wp-includes/class-wp-hook.php(324): {closure}() #2 wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters() #3 wp-includes/plugin.php(517): WP_Hook->do_action() #4 wp-settings.php(749): do_action() #5 wp-config.php(105): require_once(&#39;/home/u18285596...&#39;) #6 wp-load.php(50): require_once(&#39;/home/u18285596...&#39;) #7 wp-admin/admin.php(35): require_once(&#39;/home/u18285596...&#39;) #8 wp-admin/theme-editor.php(10): require_once(&#39;/home/u18285596...&#39;) #9 {main} thrown Please regenerate the FULL CODE for me to be replaced with the current one in functions.php
09-06
基于遗传算法的新的异构分布式系统任务调度算法研究(Matlab代码实现)内容概要:本文档围绕基于遗传算法的异构分布式系统任务调度算法展开研究,重点介绍了一种结合遗传算法的新颖优化方法,并通过Matlab代码实现验证其在复杂调度问题中的有效性。文中还涵盖了多种智能优化算法在生产调度、经济调度、车间调度、无人机路径规划、微电网优化等领域的应用案例,展示了从理论建模到仿真实现的完整流程。此外,文档系统梳理了智能优化、机器学习、路径规划、电力系统管理等多个科研方向的技术体系与实际应用场景,强调“借力”工具与创新思维在科研中的重要性。; 适合人群:具备一定Matlab编程基础,从事智能优化、自动化、电力系统、控制工程等相关领域研究的研究生及科研人员,尤其适合正在开展调度优化、路径规划或算法改进类课题的研究者; 使用场景及目标:①学习遗传算法及其他智能优化算法(如粒子群、蜣螂优化、NSGA等)在任务调度中的设计与实现;②掌握Matlab/Simulink在科研仿真中的综合应用;③获取多领域(如微电网、无人机、车间调度)的算法复现与创新思路; 阅读建议:建议按目录顺序系统浏览,重点关注算法原理与代码实现的对应关系,结合提供的网盘资源下载完整代码进行调试与复现,同时注重从已有案例中提炼可迁移的科研方法与创新路径。
【微电网】【创新点】基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度研究(Matlab代码实现)内容概要:本文提出了一种基于非支配排序的蜣螂优化算法(NSDBO),用于求解微电网多目标优化调度问题。该方法结合非支配排序机制,提升了传统蜣螂优化算法在处理多目标问题时的收敛性和分布性,有效解决了微电网调度中经济成本、碳排放、能源利用率等多个相互冲突目标的优化难题。研究构建了包含风、光、储能等多种分布式能源的微电网模型,并通过Matlab代码实现算法仿真,验证了NSDBO在寻找帕累托最优解集方面的优越性能,相较于其他多目标优化算法表现出更强的搜索能力和稳定性。; 适合人群:具备一定电力系统或优化算法基础,从事新能源、微电网、智能优化等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于微电网能量管理系统的多目标优化调度设计;②作为新型智能优化算法的研究与改进基础,用于解决复杂的多目标工程优化问题;③帮助理解非支配排序机制在进化算法中的集成方法及其在实际系统中的仿真实现。; 阅读建议:建议读者结合Matlab代码深入理解算法实现细节,重点关注非支配排序、拥挤度计算和蜣螂行为模拟的结合方式,并可通过替换目标函数或系统参数进行扩展实验,以掌握算法的适应性与调参技巧。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值