namespace, '/account/affiliate', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [$this, 'get_dashboard'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route($this->namespace, '/account/affiliate/apply', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [$this, 'apply_affiliate'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route($this->namespace, '/account/affiliate/referrals', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [$this, 'get_referrals'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route($this->namespace, '/account/affiliate/payouts', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [$this, 'get_payouts'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route($this->namespace, '/account/affiliate/payment-details', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [$this, 'get_payment_details'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route($this->namespace, '/account/affiliate/payment-details', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [$this, 'update_payment_details'], 'permission_callback' => [$this, 'check_permission'], ]); } public function check_permission() { return is_user_logged_in(); } public function get_dashboard(WP_REST_Request $request) { global $wpdb; $user_id = get_current_user_id(); $table = $wpdb->prefix . 'woonoow_affiliates'; $affiliate = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE user_id = %d", $user_id), ARRAY_A); if (!$affiliate) { return new \WP_Error('not_found', 'Affiliate profile not found', ['status' => 404]); } // Get global default rate $global_rate = (float) get_option('woonoow_affiliate_default_rate', 10); // Use custom rate if set, otherwise global $effective_rate = !empty($affiliate['custom_commission_rate']) ? (float) $affiliate['custom_commission_rate'] : $global_rate; $affiliate['global_commission_rate'] = $global_rate; $affiliate['commission_rate'] = $effective_rate; return rest_ensure_response($affiliate); } public function apply_affiliate(WP_REST_Request $request) { global $wpdb; $user_id = get_current_user_id(); $table = $wpdb->prefix . 'woonoow_affiliates'; // Check if already applied $exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM $table WHERE user_id = %d", $user_id)); if ($exists) { return new \WP_Error('exists', 'You have already applied.', ['status' => 400]); } // Generate simple code $user = wp_get_current_user(); $referral_code = strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $user->user_login)) . wp_generate_password(4, false); $auto_approve = get_option('woonoow_affiliate_auto_approve', false); $status = $auto_approve ? 'active' : 'pending'; $wpdb->insert($table, [ 'user_id' => $user_id, 'referral_code' => $referral_code, 'commission_rate' => get_option('woonoow_affiliate_default_rate', 10), // 10% default 'status' => $status ]); // Trigger email notification for admin $admin_email = get_option('admin_email'); do_action('woonoow/email/trigger', 'affiliate_application_received', $admin_email, [ 'affiliate_name' => $user->display_name, 'customer_email' => $user->user_email ]); if ($auto_approve) { do_action('woonoow/email/trigger', 'affiliate_application_approved', $user->user_email, [ 'affiliate_name' => $user->display_name, 'customer_email' => $user->user_email, 'referral_code' => $referral_code ]); } return rest_ensure_response(['success' => true, 'status' => $status, 'referral_code' => $referral_code]); } public function get_referrals(WP_REST_Request $request) { global $wpdb; $user_id = get_current_user_id(); $affiliates_table = $wpdb->prefix . 'woonoow_affiliates'; $referrals_table = $wpdb->prefix . 'woonoow_referrals'; $affiliate = $wpdb->get_row($wpdb->prepare("SELECT id FROM $affiliates_table WHERE user_id = %d", $user_id)); if (!$affiliate) { return rest_ensure_response([]); } $referrals = $wpdb->get_results($wpdb->prepare( "SELECT r.*, COALESCE(NULLIF(r.cancelled_reason, ''), NULL) as cancelled_reason, COALESCE(r.approved_at, r.created_at) as approved_at FROM $referrals_table r WHERE r.affiliate_id = %d ORDER BY r.created_at DESC", $affiliate->id ), ARRAY_A); return rest_ensure_response($referrals); } public function get_payouts(WP_REST_Request $request) { global $wpdb; $user_id = get_current_user_id(); $affiliates_table = $wpdb->prefix . 'woonoow_affiliates'; $payouts_table = $wpdb->prefix . 'woonoow_affiliate_payouts'; $affiliate = $wpdb->get_row($wpdb->prepare("SELECT id FROM $affiliates_table WHERE user_id = %d", $user_id)); if (!$affiliate) { return rest_ensure_response([]); } $payouts = $wpdb->get_results($wpdb->prepare( "SELECT id, amount, currency, method, status, notes, created_at, completed_at FROM $payouts_table WHERE affiliate_id = %d ORDER BY created_at DESC", $affiliate->id ), ARRAY_A); return rest_ensure_response($payouts); } public function get_payment_details(WP_REST_Request $request) { global $wpdb; $user_id = get_current_user_id(); $table = $wpdb->prefix . 'woonoow_affiliates'; $affiliate = $wpdb->get_row($wpdb->prepare( "SELECT payment_method, payment_details FROM $table WHERE user_id = %d", $user_id )); if (!$affiliate) { return new \WP_Error('not_found', 'Affiliate not found', ['status' => 404]); } $payment_details = $affiliate->payment_details ? json_decode($affiliate->payment_details, true) : []; return rest_ensure_response([ 'payment_method' => $affiliate->payment_method ?: '', 'payment_details' => $payment_details ?: new \stdClass() ]); } public function update_payment_details(WP_REST_Request $request) { global $wpdb; $user_id = get_current_user_id(); $table = $wpdb->prefix . 'woonoow_affiliates'; // Get allowed payment methods from settings $settings = get_option('woonoow_module_affiliate_settings', []); $allowed_methods = $settings['woonoow_affiliate_payment_methods'] ?? ['bank_transfer']; $payment_method = sanitize_text_field($request->get_param('payment_method') ?: ''); $payment_details_raw = $request->get_param('payment_details') ?: []; // Validate payment method is allowed if (!in_array($payment_method, $allowed_methods)) { return new \WP_Error( 'invalid_payment_method', 'This payment method is not available. Please contact admin.', ['status' => 400] ); } // Sanitize payment details based on method $sanitized_details = self::sanitize_payment_details($payment_method, $payment_details_raw); $result = $wpdb->update( $table, [ 'payment_method' => $payment_method, 'payment_details' => json_encode($sanitized_details) ], ['user_id' => $user_id] ); if ($result === false) { return new \WP_Error('update_failed', 'Failed to update payment details', ['status' => 500]); } return rest_ensure_response([ 'success' => true, 'payment_method' => $payment_method, 'payment_details' => $sanitized_details ]); } /** * Sanitize payment details based on payment method */ private static function sanitize_payment_details($method, $details) { $sanitized = []; switch ($method) { case 'bank_transfer': $sanitized['bank_name'] = sanitize_text_field($details['bank_name'] ?? ''); $sanitized['account_number'] = sanitize_text_field($details['account_number'] ?? ''); $sanitized['account_holder'] = sanitize_text_field($details['account_holder'] ?? ''); $sanitized['swift_code'] = sanitize_text_field($details['swift_code'] ?? ''); $sanitized['bank_address'] = sanitize_text_field($details['bank_address'] ?? ''); break; case 'paypal': case 'wise': case 'skrill': case 'payoneer': $sanitized['email'] = sanitize_email($details['email'] ?? ''); $sanitized['name'] = sanitize_text_field($details['name'] ?? ''); break; case 'custom': $sanitized['notes'] = sanitize_textarea_field($details['notes'] ?? ''); break; } return $sanitized; } }