=1 const META_PRICE = '_yoone_sub_price'; // decimal string const META_ALLOW_ONETIME = '_yoone_sub_allow_onetime'; // bool const META_MIN_QTY = '_yoone_sub_min_qty'; // int >=1(最小起订量,仅订阅模式下生效) const META_TIER_RULES = '_yoone_sub_tier_rules'; // string 逗号分隔“数量:折扣%”对,如 10:5,20:10 // 新增:多订阅计划(每个计划包含:id、label、period、price、discount_percent 可选) const META_PLANS = '_yoone_sub_plans'; // serialized array protected static $instance = null; /** * 单例 */ public static function instance() { if (null === self::$instance) self::$instance = new self(); return self::$instance; } private function __construct() { // 无需在此注册产品类型;订阅计划作为 simple/product 的增强配置存在 } /** * 获取产品的订阅配置(规范化)。 * * @param int|WC_Product $product 产品或产品ID * @return array{enabled:bool,period:string,qty_default:int,price:float,allow_onetime:bool} */ public static function get_config($product) { $product = is_numeric($product) ? wc_get_product($product) : $product; if (! $product) return self::defaults(); $pid = $product->get_id(); $enabled = (bool) get_post_meta($pid, self::META_ENABLED, true); $period = get_post_meta($pid, self::META_PERIOD, true); $qty = absint(get_post_meta($pid, self::META_QTY_DEFAULT, true)); $price = get_post_meta($pid, self::META_PRICE, true); $onetime = (bool) get_post_meta($pid, self::META_ALLOW_ONETIME, true); $min_qty = absint(get_post_meta($pid, self::META_MIN_QTY, true)); $tiers = get_post_meta($pid, self::META_TIER_RULES, true); $plans = get_post_meta($pid, self::META_PLANS, true); $period = in_array($period, array('month','year'), true) ? $period : 'month'; $qty = max(1, $qty); $price = is_numeric($price) ? floatval($price) : 0.0; // 0 表示按产品原价 // 规范化计划数组 if (! is_array($plans)) { $plans = array(); } else { $norm = array(); foreach ($plans as $p) { $norm[] = array( 'id' => isset($p['id']) ? sanitize_key($p['id']) : uniqid('plan_'), 'label' => isset($p['label']) ? sanitize_text_field($p['label']) : __('订阅计划', 'yoone-subscriptions'), 'period' => (isset($p['period']) && in_array($p['period'], array('month','year'), true)) ? $p['period'] : 'month', 'price' => isset($p['price']) && is_numeric($p['price']) ? floatval($p['price']) : 0.0, 'discount_percent' => isset($p['discount_percent']) && is_numeric($p['discount_percent']) ? floatval($p['discount_percent']) : 0.0, ); } $plans = $norm; } return array( 'enabled' => $enabled, 'period' => $period, 'qty_default' => $qty, 'price' => $price, 'allow_onetime' => $onetime, 'min_qty' => max(1, $min_qty), 'tier_rules' => is_string($tiers) ? $tiers : '', 'plans' => $plans, ); } /** * 默认配置 */ public static function defaults() { return array( 'enabled' => false, 'period' => 'month', 'qty_default' => 1, 'price' => 0.0, 'allow_onetime' => true, 'min_qty' => 1, 'tier_rules' => '', 'plans' => array(), ); } /** * 周期对应的系数(用于价格计算)。 * month=1, year=12。 */ public static function period_factor($period) { return $period === 'year' ? 12 : 1; } }