403Webshell
Server IP : 202.61.199.114  /  Your IP : 216.73.217.139
Web Server : nginx/1.22.1
System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64
User : web20 ( 1018)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/seaside.pacim.de/web/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/seaside.pacim.de/web/partner-api.php
<?php
/**
 * partner-api.php – Admin-Verwaltung des Partnerprogramms (Vermittler/Reisebüros).
 * Nur Admins (is_admin). Verwaltet pacim_users(level=BROKER_LEVEL) + pacim_broker,
 * den globalen Provisions-Default und liefert Übersichten der vermittelten Buchungen.
 *
 *  action=brokers      GET                 -> { ok, default, brokers:[{...,bookings,commission_sum}] }
 *  action=get          GET  id             -> { ok, broker:{user+broker} }
 *  action=save         POST <felder>       -> { ok, id }    (anlegen/bearbeiten; pw optional)
 *  action=default-save POST commission     -> { ok }
 *  action=bookings     GET  [broker]       -> { ok, bookings:[...], totals:{gross,commission} }
 */
require_once( __DIR__ . '/includes/config.inc.php' );
@ini_set( 'display_errors', '0' );
error_reporting( 0 );
ob_start();

function pa_json( $a ) { while ( ob_get_level() > 0 ) ob_end_clean(); header( 'Content-Type: application/json; charset=utf-8' ); echo json_encode( $a ); exit(); }

if ( ! function_exists( 'is_admin' ) || ! is_admin() ) { http_response_code( 403 ); pa_json( array( 'ok' => false, 'error' => 'forbidden' ) ); }

$action = isset( $_GET['action'] ) ? $_GET['action'] : ( isset( $_POST['action'] ) ? $_POST['action'] : '' );
$db     = new MysqliDb( MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB );
$LVL    = (int) BROKER_LEVEL;

/* ---------------- Vermittler-Liste + Statistik ---------------- */
if ( $action === 'brokers' ) {
    $rows = $db->rawQuery(
        "SELECT u.user_id, u.user_firstname, u.user_lastname, u.user_email,
                br.broker_company, br.broker_commission, br.broker_commission_addon, br.broker_payment_mode, br.broker_active, br.broker_pending,
                br.broker_phone, DATE_FORMAT(br.broker_created,'%d.%m.%Y') AS applied,
                (SELECT COUNT(*) FROM pacim_invoice i WHERE i.invoice_broker = u.user_id) AS bookings,
                (SELECT COALESCE(SUM(" . broker_commission_sql( 'i' ) . "),0)
                 FROM pacim_invoice i WHERE i.invoice_broker = u.user_id AND i.invoice_status != 3) AS commission_sum
         FROM pacim_users u
         LEFT JOIN pacim_broker br ON br.broker_id = u.user_id
         WHERE u.user_level = $LVL
         ORDER BY u.user_lastname, u.user_firstname",
        null
    );
    $out = array();
    foreach ( (array) $rows as $r ) {
        $out[] = array(
            'id' => (int) $r['user_id'],
            'name' => trim( $r['user_firstname'] . ' ' . $r['user_lastname'] ),
            'email' => $r['user_email'],
            'company' => $r['broker_company'],
            'commission' => ( $r['broker_commission'] === null ) ? null : (float) $r['broker_commission'],
            'commission_addon' => ( $r['broker_commission_addon'] === null ) ? null : (float) $r['broker_commission_addon'],
            'payment_mode' => $r['broker_payment_mode'] ?: 'payout',
            'active' => (int) $r['broker_active'],
            'pending' => (int) $r['broker_pending'],
            'phone' => $r['broker_phone'],
            'applied' => $r['applied'],
            'bookings' => (int) $r['bookings'],
            'commission_sum' => round( (float) $r['commission_sum'], 2 ),
            'effective_rate' => broker_commission_rate( (int) $r['user_id'] ),
            'effective_addon_rate' => broker_commission_addon_rate( (int) $r['user_id'] ),
        );
    }
    pa_json( array( 'ok' => true, 'default' => (float) pacim_setting( 'broker_commission_default', 0 ), 'default_addon' => (float) pacim_setting( 'broker_commission_addon_default', 0 ), 'addon_enabled' => broker_addon_enabled(), 'terms' => broker_terms_text(), 'brokers' => $out ) );
}

/* ---------------- Einen Vermittler laden ---------------- */
if ( $action === 'get' ) {
    $id = (int) ( $_GET['id'] ?? 0 );
    $u = $db->rawQueryOne( "SELECT user_id, user_firstname, user_lastname, user_email, user_level FROM pacim_users WHERE user_id = ? AND user_level = $LVL", array( $id ) );
    if ( ! $u ) pa_json( array( 'ok' => false, 'error' => 'not_found' ) );
    $b = broker_record( $id );
    pa_json( array( 'ok' => true, 'broker' => array( 'user' => $u, 'broker' => $b ? $b : new stdClass() ) ) );
}

/* ---------------- Anlegen / Bearbeiten ---------------- */
if ( $action === 'save' ) {
    $id        = (int) ( $_POST['id'] ?? 0 );
    $email     = trim( (string) ( $_POST['email'] ?? '' ) );
    $firstname = trim( (string) ( $_POST['firstname'] ?? '' ) );
    $lastname  = trim( (string) ( $_POST['lastname'] ?? '' ) );
    $password  = (string) ( $_POST['password'] ?? '' );
    if ( $lastname === '' && trim( (string)($_POST['company'] ?? '') ) === '' ) pa_json( array( 'ok' => false, 'error' => 'Bitte Name oder Firma angeben.' ) );
    if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) pa_json( array( 'ok' => false, 'error' => 'Bitte eine gültige E-Mail angeben.' ) );

    // E-Mail-Eindeutigkeit
    $ex = $db->rawQueryOne( 'SELECT user_id FROM pacim_users WHERE user_email = ?' . ( $id ? ' AND user_id <> ' . $id : '' ), array( $email ) );
    if ( $ex ) pa_json( array( 'ok' => false, 'error' => 'E-Mail ist bereits vergeben.' ) );

    $now = date( 'Y-m-d H:i:s' );
    $commission = ( isset( $_POST['commission'] ) && $_POST['commission'] !== '' ) ? (float) str_replace( ',', '.', $_POST['commission'] ) : null;
    $commissionAddon = ( isset( $_POST['commission_addon'] ) && $_POST['commission_addon'] !== '' ) ? (float) str_replace( ',', '.', $_POST['commission_addon'] ) : null;
    $payMode = in_array( ( $_POST['payment_mode'] ?? 'payout' ), array( 'payout', 'collect' ), true ) ? $_POST['payment_mode'] : 'payout';
    $active  = ! empty( $_POST['active'] ) ? 1 : 0;

    if ( ! $id ) {
        // anlegen
        if ( strlen( $password ) < 6 ) pa_json( array( 'ok' => false, 'error' => 'Bitte ein Passwort (min. 6 Zeichen) vergeben.' ) );
        $id = $db->insert( 'pacim_users', array(
            'user_firstname' => $firstname, 'user_lastname' => $lastname, 'user_email' => $email,
            'user_password' => password_hash( $password, PASSWORD_DEFAULT ), 'user_level' => $LVL,
            'user_created' => $now, 'user_updated' => $now,
        ) );
        if ( ! $id ) pa_json( array( 'ok' => false, 'error' => 'Konto konnte nicht angelegt werden.' ) );
    } else {
        $db->where( 'user_id', $id );
        $upd = array( 'user_firstname' => $firstname, 'user_lastname' => $lastname, 'user_email' => $email, 'user_level' => $LVL, 'user_updated' => $now );
        if ( $password !== '' ) { if ( strlen( $password ) < 6 ) pa_json( array( 'ok' => false, 'error' => 'Passwort zu kurz (min. 6 Zeichen).' ) ); $upd['user_password'] = password_hash( $password, PASSWORD_DEFAULT ); }
        $db->update( 'pacim_users', $upd );
    }

    // pacim_broker upsert
    $bf = array(
        'broker_company'    => trim( (string) ( $_POST['company'] ?? '' ) ),
        'broker_street'     => trim( (string) ( $_POST['street'] ?? '' ) ),
        'broker_zipcode'    => trim( (string) ( $_POST['zipcode'] ?? '' ) ),
        'broker_city'       => trim( (string) ( $_POST['city'] ?? '' ) ),
        'broker_country'    => trim( (string) ( $_POST['country'] ?? '' ) ),
        'broker_phone'      => trim( (string) ( $_POST['phone'] ?? '' ) ),
        'broker_taxid'      => trim( (string) ( $_POST['taxid'] ?? '' ) ),
        'broker_commission' => $commission,
        'broker_commission_addon' => $commissionAddon,
        'broker_payment_mode' => $payMode,
        'broker_active'     => $active,
        'broker_pending'    => 0,   // Admin-Bearbeitung beendet den Anfrage-Status
        'broker_updated'    => $now,
    );
    if ( broker_record( $id ) ) { $db->where( 'broker_id', $id ); $db->update( 'pacim_broker', $bf ); }
    else { $bf['broker_id'] = $id; $bf['broker_created'] = $now; $db->insert( 'pacim_broker', $bf ); }

    pa_json( array( 'ok' => true, 'id' => (int) $id ) );
}

/* ---------------- Globalen Default speichern ---------------- */
if ( $action === 'default-save' ) {
    $v = (float) str_replace( ',', '.', (string) ( $_POST['commission'] ?? '' ) );
    if ( $v < 0 || $v > 100 ) pa_json( array( 'ok' => false, 'error' => 'Parkplatz-Provision: Wert zwischen 0 und 100.' ) );
    settings::set( 'broker_commission_default', number_format( $v, 2, '.', '' ) );
    if ( isset( $_POST['commission_addon'] ) && $_POST['commission_addon'] !== '' ) {
        $va = (float) str_replace( ',', '.', (string) $_POST['commission_addon'] );
        if ( $va < 0 || $va > 100 ) pa_json( array( 'ok' => false, 'error' => 'Zusatzprodukt-Provision: Wert zwischen 0 und 100.' ) );
        settings::set( 'broker_commission_addon_default', number_format( $va, 2, '.', '' ) );
    }
    pa_json( array( 'ok' => true, 'default' => $v ) );
}

/* ---------------- Teilnahmebedingungen speichern ---------------- */
if ( $action === 'terms-save' ) {
    $t = trim( (string) ( $_POST['terms'] ?? '' ) );
    settings::set( 'broker_terms', $t );
    pa_json( array( 'ok' => true ) );
}

/* ---------------- Anfrage freischalten ---------------- */
if ( $action === 'approve' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    $u = $db->rawQueryOne( "SELECT user_id FROM pacim_users WHERE user_id = ? AND user_level = $LVL", array( $id ) );
    if ( ! $u ) pa_json( array( 'ok' => false, 'error' => 'not_found' ) );
    $db->where( 'broker_id', $id );
    $db->update( 'pacim_broker', array( 'broker_active' => 1, 'broker_pending' => 0, 'broker_updated' => date( 'Y-m-d H:i:s' ) ) );
    // Regel-Engine: Ereignis „Partner freigeschaltet" (Fallback: partner_approved). No-Op solange SMTP nicht aktiv.
    // Echte Partner-Platzhalter (partner_*) mergen, sonst blieben die Beispielwerte aus context(0) stehen.
    if ( class_exists( 'mailrules' ) ) {
        $bu = $db->rawQueryOne( "SELECT user_email, user_firstname, user_lastname FROM pacim_users WHERE user_id = ?", array( $id ) );
        if ( $bu ) {
            $pctx = class_exists( 'mailrenderer' ) ? mailrenderer::partnerPlaceholders( (int) $id ) : array();
            $pctx = array_merge( $pctx, array(
                'customer_firstname' => $bu['user_firstname'], 'customer_lastname' => $bu['user_lastname'], 'salutation' => trim( $bu['user_firstname'] . ' ' . $bu['user_lastname'] ),
            ) );
            // broker_id → Dedupe „eine Freischaltungsmail je Partner" (message_broker, kollidiert nicht mit customer_id).
            mailrules::evaluateEvent( 'partner_approved', array( 'to' => $bu['user_email'], 'broker_id' => (int) $id, 'ctx' => $pctx ), 'partner_approved' );
        }
    }
    pa_json( array( 'ok' => true, 'id' => $id ) );
}

/* ---------------- Anfrage ablehnen (löscht den angefragten Account) ---------------- */
if ( $action === 'reject' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    // Nur noch offene Anfragen dürfen gelöscht werden – niemals aktive Vermittler.
    $b = $db->rawQueryOne( "SELECT broker_id, broker_pending, broker_active FROM pacim_broker WHERE broker_id = ?", array( $id ) );
    if ( ! $b || (int) $b['broker_pending'] !== 1 || (int) $b['broker_active'] === 1 ) pa_json( array( 'ok' => false, 'error' => 'Nur offene Anfragen können abgelehnt werden.' ) );
    // Sicherheitsnetz: keine Buchungen vorhanden?
    $cnt = $db->rawQueryOne( "SELECT COUNT(*) AS c FROM pacim_invoice WHERE invoice_broker = ?", array( $id ) );
    if ( $cnt && (int) $cnt['c'] > 0 ) pa_json( array( 'ok' => false, 'error' => 'Vermittler hat bereits Buchungen – Ablehnung nicht möglich.' ) );
    $db->where( 'broker_id', $id ); $db->delete( 'pacim_broker' );
    $db->where( 'user_id', $id ); $db->where( 'user_level', $LVL ); $db->delete( 'pacim_users' );
    pa_json( array( 'ok' => true, 'id' => $id ) );
}

/* ---------------- Vermittelte Buchungen (alle / je Vermittler) ---------------- */
if ( $action === 'bookings' ) {
    $broker = (int) ( $_GET['broker'] ?? 0 );
    $where  = 'd.invoice_broker IS NOT NULL AND d.invoice_broker > 0' . ( $broker ? ' AND d.invoice_broker = ' . $broker : '' );
    $rows = $db->rawQuery(
        "SELECT d.invoice_id, b.booking_no, b.booking_event, b.booking_serial,
                DATE_FORMAT(b.booking_begin,'%d.%m.%Y') AS begin, DATE_FORMAT(b.booking_end,'%d.%m.%Y') AS end,
                MIN(b.booking_begin) AS begin_raw,
                DATE_FORMAT(d.invoice_datetime,'%d.%m.%Y') AS created,
                TRIM(CONCAT(COALESCE(c.customer_lastname,''),', ',COALESCE(c.customer_firstname,''))) AS customer,
                d.invoice_no, d.invoice_payment, d.invoice_status, d.invoice_broker, d.invoice_broker_commission AS rate,
                COALESCE(d.invoice_broker_commission_addon, d.invoice_broker_commission) AS rate_addon,
                TRIM(CONCAT(COALESCE(u.user_firstname,''),' ',COALESCE(u.user_lastname,''))) AS broker_name,
                (SELECT SUM(p.invoice_pos_price*p.invoice_pos_quantity*1.19) FROM pacim_invoice_pos p WHERE p.invoice_id=d.invoice_id) AS gross,
                " . broker_commission_sql( 'd' ) . " AS commission
         FROM pacim_invoice d
         JOIN pacim_booking b ON b.booking_invoice = d.invoice_id
         LEFT JOIN pacim_customer c ON c.customer_id = b.booking_customer
         LEFT JOIN pacim_users u ON u.user_id = d.invoice_broker
         WHERE $where
         GROUP BY d.invoice_id
         ORDER BY d.invoice_datetime DESC, d.invoice_id DESC",
        null
    );
    $out = array(); $tg = 0.0; $tc = 0.0;
    $sumReleased = 0.0; $sumPending = 0.0; $cntReleased = 0; $cntPending = 0; $cntCancelled = 0;
    foreach ( (array) $rows as $r ) {
        $gross = (float) $r['gross']; $rate = (float) $r['rate'];
        $status = broker_commission_status( $r['begin_raw'], $r['invoice_status'] ); // released | pending | cancelled
        $storno = ( $status === 'cancelled' );
        $comm = $storno ? 0.0 : round( (float) $r['commission'], 2 );
        $tg += $gross; $tc += $comm;
        if ( $status === 'released' ) { $sumReleased += $comm; $cntReleased++; }
        elseif ( $status === 'pending' ) { $sumPending += $comm; $cntPending++; }
        else { $cntCancelled++; }
        $out[] = array(
            'invoice_id' => (int) $r['invoice_id'], 'broker_id' => (int) $r['invoice_broker'], 'broker' => $r['broker_name'],
            'booking_no' => $r['booking_no'], 'event' => $r['booking_event'], 'plate' => $r['booking_serial'],
            'customer' => $r['customer'], 'begin' => $r['begin'], 'end' => $r['end'], 'created' => $r['created'],
            'gross' => round( $gross, 2 ), 'rate' => $rate, 'addon_rate' => (float) $r['rate_addon'], 'commission' => $comm,
            'paid' => ( (int) $r['invoice_payment'] > 0 && (int) $r['invoice_payment'] != 4 ), 'storno' => $storno, 'status' => $status,
        );
    }
    pa_json( array( 'ok' => true, 'bookings' => $out,
        'totals' => array( 'gross' => round($tg,2), 'commission' => round($tc,2), 'count' => count($out),
            'released' => round($sumReleased,2), 'pending' => round($sumPending,2),
            'cnt_released' => $cntReleased, 'cnt_pending' => $cntPending, 'cnt_cancelled' => $cntCancelled ) ) );
}

http_response_code( 400 );
pa_json( array( 'ok' => false, 'error' => 'unknown_action' ) );

Youez - 2016 - github.com/yon3zu
LinuXploit