0 wins). if ($author_id > 0 && function_exists('aksrt_get_user_vip_level')) { $level = (int) aksrt_get_user_vip_level($author_id); if ($level === 1 && (float) ($settings['ratio_vip1'] ?? 0) > 0) { $ratio = (float) $settings['ratio_vip1']; } elseif ($level >= 2 && (float) ($settings['ratio_vip2'] ?? 0) > 0) { $ratio = (float) $settings['ratio_vip2']; } } return max(0.0, min(100.0, $ratio)); } /** * Guard: has this order already been settled into revenue? */ private function already_settled(string $order_number): bool { if ($order_number === '' || !class_exists('AKSRT_DB_Migrator')) { return false; } global $wpdb; $table = AKSRT_DB_Migrator::table('revenue'); if ($table === '') { return false; } $count = (int) $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE order_number = %s AND type = %s", $order_number, 'order' )); return $count > 0; } /** * aksrt_order_paid listener: credit creators their share. * * @param string $order_number Paid order number. * @param array $order Order row (status=paid). */ public function handle_order_paid(string $order_number, array $order): void { if (!$this->is_enabled() || $order_number === '') { return; } if ($this->already_settled($order_number)) { return; } $buyer_id = (int) ($order['user_id'] ?? 0); $items = []; if (class_exists('AKSRT_Shop')) { $shop = AKSRT_Shop::get_instance(); if (method_exists($shop, 'get_order_items')) { $items = (array) $shop->get_order_items($order_number); } } if (!empty($items)) { $this->settle_shop_items($order_number, $buyer_id, $items); return; } $this->settle_non_shop_cash_order($order_number, $order, $buyer_id); } /** * @param list> $items */ private function settle_shop_items(string $order_number, int $buyer_id, array $items): void { $revenue = AKSRT_Revenue::get_instance(); foreach ($items as $item) { $product_id = (int) ($item['product_id'] ?? 0); $pay_price = (float) ($item['pay_price'] ?? $item['total_price'] ?? 0); if ($product_id <= 0 || $pay_price <= 0) { continue; } $author_id = (int) get_post_field('post_author', $product_id); if ($author_id <= 0 || $author_id === $buyer_id) { continue; } $ratio = $this->resolve_share_ratio($author_id); if ($ratio <= 0) { continue; } $amount = round($pay_price * $ratio / 100, 2); if ($amount <= 0) { continue; } $revenue->add($author_id, $amount, $order_number, 'order'); } } /** * Content / topic / plate_follow cash orders (no shop line items). */ private function settle_non_shop_cash_order(string $order_number, array $order, int $buyer_id): void { $meta = $this->decode_note($order); if (($meta['pay_modo'] ?? '') === 'points') { return; } $payment_method = sanitize_key((string) ($order['payment_method'] ?? '')); $currency = sanitize_key((string) ($order['currency'] ?? '')); if ($payment_method === 'points' || $currency === 'points') { return; } $base_amount = round((float) ($order['amount'] ?? $meta['payable'] ?? 0), 2); if ($base_amount <= 0) { return; } $product_type = sanitize_key((string) ($order['product_type'] ?? '')); $product_id = (int) ($order['product_id'] ?? 0); if ($product_id <= 0) { return; } $post = get_post($product_id); if (!($post instanceof WP_Post)) { return; } $is_plate = !empty($meta['plate_follow_pay']) || $product_type === AKSRT_Domain_Model::ORDER_PRODUCT_PLATE_FOLLOW; $is_topic = !empty($meta['topic_pay']) || ($product_type === AKSRT_Domain_Model::ORDER_PRODUCT_RESOURCE && $post->post_type === 'aksrt_forum_topic'); $is_content = !empty($meta['content_pay']) && $post->post_type === 'post'; // Resource without content_pay/topic_pay and not a known cash kind: skip. if (!$is_plate && !$is_topic && !$is_content) { return; } // Guard: plate must be plate CPT; topic must be topic CPT. if ($is_plate && $post->post_type !== 'aksrt_forum_plate') { return; } if ($is_topic && $post->post_type !== 'aksrt_forum_topic') { return; } $author_id = (int) $post->post_author; if ($author_id <= 0 || $author_id === $buyer_id) { return; } $ratio = $this->resolve_share_ratio($author_id); if ($ratio <= 0) { return; } $amount = round($base_amount * $ratio / 100, 2); if ($amount <= 0) { return; } // Re-check after shop-less path; shop path already returned. if ($this->already_settled($order_number)) { return; } AKSRT_Revenue::get_instance()->add($author_id, $amount, $order_number, 'order'); } /** * @param array $order * @return array */ private function decode_note(array $order): array { if (isset($order['meta_payload']) && is_array($order['meta_payload'])) { return $order['meta_payload']; } $note = (string) ($order['note'] ?? ''); if ($note === '') { return []; } $decoded = json_decode($note, true); return is_array($decoded) ? $decoded : []; } } }