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/broker-api.php
<?php
/**
 * broker-api.php – API für das Vermittler-/Reisebüro-Portal. Strikt broker-scoped:
 * nur eingeloggte Vermittler (is_broker), Daten immer auf den eigenen Account begrenzt.
 *
 *  action=events    GET                          -> { ok, events:[{title,begin,end}] }  (kommende, aktive)
 *  action=products  GET                          -> { ok, products:[{id,title,net,gross}] } (Zusatzleistungen)
 *  action=quote     POST type,begin,end,products[] -> { ok, quote:{...} }                 (Preis/Provision-Vorschau)
 *  action=create    POST <Buchungsfelder>        -> { ok, invoice_id, booking_id, booking_no }
 */
require_once( __DIR__ . '/includes/config.inc.php' );
@ini_set( 'display_errors', '0' );
error_reporting( 0 );
ob_start();

function ba_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_broker' ) || ! is_broker() ) {
    http_response_code( 403 );
    ba_json( array( 'ok' => false, 'error' => 'forbidden' ) );
}

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

/* ---------------- Events (Schiffe/Termine) ---------------- */
if ( $action === 'events' ) {
    $rows = $db->rawQuery(
        "SELECT event_calendar_title AS title,
                DATE_FORMAT(event_calendar_begin, '%Y-%m-%d') AS begin,
                DATE_FORMAT(event_calendar_end,   '%Y-%m-%d') AS end
         FROM pacim_events
         WHERE event_calendar_active = 1
           AND event_calendar_begin >= CURDATE() - INTERVAL 1 DAY
         ORDER BY event_calendar_begin ASC
         LIMIT 400"
    );
    ba_json( array( 'ok' => true, 'events' => $rows ? $rows : array() ) );
}

/* ---------------- Zusatzleistungen ---------------- */
if ( $action === 'products' ) {
    $year = (int) date( 'Y' );
    // bookbare Zusatzleistungen (ohne reine Parkplatzprodukte 1/2 und ohne 0-Preis-Platzhalter)
    $rows = $db->rawQuery(
        "SELECT p.product_id AS id, p.product_title AS title,
                COALESCE((SELECT pp.price FROM pacim_product_prices pp WHERE pp.product_id=p.product_id AND pp.year=? LIMIT 1), p.product_price) AS net
         FROM pacim_products p
         WHERE p.product_id NOT IN (1,2)
         ORDER BY p.product_id",
        array( $year )
    );
    $out = array();
    foreach ( (array) $rows as $r ) {
        $net = (float) $r['net'];
        if ( $net <= 0 ) continue; // Platzhalter/0-Preis-Produkte ausblenden
        $out[] = array( 'id' => (int) $r['id'], 'title' => $r['title'], 'net' => round( $net, 2 ), 'gross' => round( $net * 1.19, 2 ) );
    }
    ba_json( array( 'ok' => true, 'products' => $out ) );
}

/* ---------------- Preis-/Provisionsvorschau ---------------- */
if ( $action === 'quote' ) {
    $q = bookingservice::quote( array(
        'type'     => (int) ( $_POST['type'] ?? 1 ),
        'begin'    => (string) ( $_POST['begin'] ?? '' ),
        'end'      => (string) ( $_POST['end'] ?? '' ),
        'products' => isset( $_POST['products'] ) ? (array) $_POST['products'] : array(),
        'brokerId' => $brokerId,
    ) );
    ba_json( array( 'ok' => true, 'quote' => $q ) );
}

/* ---------------- Buchung anlegen ---------------- */
if ( $action === 'create' ) {
    $res = bookingservice::create( array(
        'brokerId' => $brokerId,
        'customer' => array(
            'gender'    => (int) ( $_POST['customer_gender'] ?? 1 ),
            'firstname' => (string) ( $_POST['customer_firstname'] ?? '' ),
            'lastname'  => (string) ( $_POST['customer_lastname'] ?? '' ),
            'street'    => (string) ( $_POST['customer_street'] ?? '' ),
            'zipcode'   => (string) ( $_POST['customer_zipcode'] ?? '' ),
            'city'      => (string) ( $_POST['customer_city'] ?? '' ),
            'country'   => (string) ( $_POST['customer_country'] ?? 'Deutschland' ),
            'phone'     => (string) ( $_POST['customer_phone'] ?? '' ),
            'email'     => (string) ( $_POST['customer_email'] ?? '' ),
        ),
        'plate'    => (string) ( $_POST['plate'] ?? '' ),
        'event'    => (string) ( $_POST['event'] ?? '' ),
        'begin'    => (string) ( $_POST['begin'] ?? '' ),
        'end'      => (string) ( $_POST['end'] ?? '' ),
        'type'     => (int) ( $_POST['type'] ?? 1 ),
        'products' => isset( $_POST['products'] ) ? (array) $_POST['products'] : array(),
        'guests'   => (int) ( $_POST['guests'] ?? 0 ),
        'hint'     => (string) ( $_POST['hint'] ?? '' ), // Partner-Hinweis zur Buchung (Freitext)
    ) );
    ba_json( $res );
}

/* ---------------- Eigene Buchungen ---------------- */
if ( $action === 'bookings' ) {
    $rows = $db->rawQuery(
        "SELECT d.invoice_id, b.booking_id, b.booking_no, b.booking_event,
                DATE_FORMAT(b.booking_begin, '%d.%m.%Y') AS begin, DATE_FORMAT(b.booking_end, '%d.%m.%Y') AS end,
                b.booking_begin AS begin_raw, b.booking_type, b.booking_serial, b.booking_hint,
                TRIM(CONCAT(COALESCE(c.customer_lastname,''),', ',COALESCE(c.customer_firstname,''))) AS customer,
                d.invoice_no, d.invoice_payment, d.invoice_status, d.invoice_broker_commission,
                COALESCE(d.invoice_broker_commission_addon, d.invoice_broker_commission) AS rate_addon,
                DATE_FORMAT(d.invoice_datetime,'%d.%m.%Y') AS created,
                (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
         WHERE d.invoice_broker = ?
         GROUP BY d.invoice_id
         ORDER BY d.invoice_datetime DESC, d.invoice_id DESC",
        array( $brokerId )
    );
    $out = array();
    foreach ( (array) $rows as $r ) {
        $gross = (float) $r['gross'];
        $rate  = (float) $r['invoice_broker_commission'];
        $storno = ( (int) $r['invoice_status'] === 3 );
        $out[] = array(
            'invoice_id' => (int) $r['invoice_id'], 'booking_no' => $r['booking_no'], 'event' => $r['booking_event'],
            'begin' => $r['begin'], 'end' => $r['end'], 'begin_raw' => $r['begin_raw'],
            'type' => ( (int) $r['booking_type'] === 2 ? 'Außen' : 'Halle' ), 'plate' => $r['booking_serial'],
            'customer' => $r['customer'], 'created' => $r['created'], 'hint' => (string) ( $r['booking_hint'] ?? '' ),
            'gross' => round( $gross, 2 ), 'rate' => $rate, 'addon_rate' => (float) $r['rate_addon'], 'commission' => $storno ? 0.0 : round( (float) $r['commission'], 2 ),
            'paid' => ( (int) $r['invoice_payment'] > 0 && (int) $r['invoice_payment'] != 4 ),
            'storno' => $storno, 'cancelled' => $storno, 'status' => ( $storno ? 'cancelled' : 'active' ),
            'comm_status' => broker_commission_status( $r['begin_raw'], $r['invoice_status'] ),
        );
    }
    ba_json( array( 'ok' => true, 'bookings' => $out ) );
}

/* ---------------- Hinweis einer eigenen Buchung ändern ---------------- */
/* Partner darf NUR den Hinweis (booking_hint) seiner EIGENEN Buchungen anpassen. */
if ( $action === 'booking-hint' ) {
    $bid = (int) ( $_POST['booking_id'] ?? 0 );
    if ( $bid <= 0 ) ba_json( array( 'ok' => false, 'error' => 'booking_id fehlt.' ) );
    // Eigentum prüfen: Buchung muss zur Rechnung eines eigenen (invoice_broker = brokerId) Vorgangs gehören.
    $own = $db->rawQueryOne(
        "SELECT b.booking_id FROM pacim_booking b JOIN pacim_invoice d ON d.invoice_id = b.booking_invoice
          WHERE b.booking_id = ? AND d.invoice_broker = ? LIMIT 1", array( $bid, $brokerId ) );
    if ( ! $own ) ba_json( array( 'ok' => false, 'error' => 'Kein Zugriff auf diese Buchung.' ) );
    $db->where( 'booking_id', $bid );
    $db->update( 'pacim_booking', array( 'booking_hint' => trim( (string) ( $_POST['hint'] ?? '' ) ) ) );
    ba_json( array( 'ok' => true, 'booking_id' => $bid ) );
}

/* ---------------- Provisionsübersicht (Summen) ---------------- */
if ( $action === 'commission' ) {
    $rows = $db->rawQuery(
        "SELECT d.invoice_id, b.booking_no, b.booking_event, DATE_FORMAT(d.invoice_datetime,'%Y-%m') AS ym,
                DATE_FORMAT(d.invoice_datetime,'%d.%m.%Y') AS created, d.invoice_broker_commission AS rate, d.invoice_status,
                MIN(b.booking_begin) AS begin_raw,
                COALESCE(d.invoice_broker_commission_addon, d.invoice_broker_commission) AS rate_addon,
                (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
         WHERE d.invoice_broker = ?
         GROUP BY d.invoice_id ORDER BY d.invoice_datetime DESC",
        array( $brokerId )
    );
    $list = array(); $totalGross = 0.0; $totalComm = 0.0; $months = array();
    $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
        $comm = ( $status === 'cancelled' ) ? 0.0 : round( (float) $r['commission'], 2 );
        $list[] = array( 'booking_no' => $r['booking_no'], 'event' => $r['booking_event'], 'created' => $r['created'], 'gross' => round($gross,2), 'rate' => $rate, 'addon_rate' => (float) $r['rate_addon'], 'commission' => $comm, 'storno' => ($status==='cancelled'), 'status' => $status );
        $totalGross += $gross;
        if ( $status === 'released' ) { $sumReleased += $comm; $cntReleased++; }
        elseif ( $status === 'pending' ) { $sumPending += $comm; $cntPending++; }
        else { $cntCancelled++; }
        $totalComm = $sumReleased + $sumPending; // storniert zählt NICHT
        if ( $status !== 'cancelled' ) { if ( ! isset( $months[ $r['ym'] ] ) ) $months[ $r['ym'] ] = 0.0; $months[ $r['ym'] ] += $comm; }
    }
    ba_json( array( 'ok' => true, 'list' => $list, 'totalGross' => round($totalGross,2), 'totalCommission' => round($totalComm,2), 'count' => count($list), 'months' => $months, 'addon_enabled' => broker_addon_enabled(),
        'released' => round($sumReleased,2), 'pending' => round($sumPending,2), 'cnt_released' => $cntReleased, 'cnt_pending' => $cntPending, 'cnt_cancelled' => $cntCancelled ) );
}

/* ---------------- Stammdaten (lesen) ---------------- */
if ( $action === 'me' ) {
    $b = broker_record( $brokerId );
    $u = $db->rawQueryOne( 'SELECT user_firstname, user_lastname, user_email FROM pacim_users WHERE user_id = ?', array( $brokerId ) );
    ba_json( array( 'ok' => true,
        'user' => $u ? $u : array(),
        'broker' => $b ? $b : new stdClass(),
        'commission_rate' => broker_commission_rate( $brokerId ),
        'commission_addon_rate' => broker_commission_addon_rate( $brokerId ),
        'addon_enabled' => broker_addon_enabled(),
    ) );
}

/* ---------------- Persönliche Daten speichern ---------------- */
if ( $action === 'profile-save' ) {
    $now = date( 'Y-m-d H:i:s' );
    // pacim_users (Name)
    $db->where( 'user_id', $brokerId );
    $db->update( 'pacim_users', array(
        'user_firstname' => trim( (string) ( $_POST['firstname'] ?? '' ) ),
        'user_lastname'  => trim( (string) ( $_POST['lastname'] ?? '' ) ),
        'user_updated'   => $now,
    ) );
    // pacim_broker (Firma/Anschrift/Kontakt) – Upsert
    $fields = 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_updated' => $now,
    );
    if ( broker_record( $brokerId ) ) { $db->where( 'broker_id', $brokerId ); $db->update( 'pacim_broker', $fields ); }
    else { $fields['broker_id'] = $brokerId; $fields['broker_created'] = $now; $db->insert( 'pacim_broker', $fields ); }
    ba_json( array( 'ok' => true ) );
}

/* ---------------- Bankverbindung speichern ---------------- */
if ( $action === 'bank-save' ) {
    $now = date( 'Y-m-d H:i:s' );
    $fields = array(
        'broker_iban'           => strtoupper( preg_replace( '/\s+/', '', (string) ( $_POST['iban'] ?? '' ) ) ),
        'broker_bic'            => strtoupper( trim( (string) ( $_POST['bic'] ?? '' ) ) ),
        'broker_account_holder' => trim( (string) ( $_POST['account_holder'] ?? '' ) ),
        'broker_updated'        => $now,
    );
    if ( broker_record( $brokerId ) ) { $db->where( 'broker_id', $brokerId ); $db->update( 'pacim_broker', $fields ); }
    else { $fields['broker_id'] = $brokerId; $fields['broker_created'] = $now; $db->insert( 'pacim_broker', $fields ); }
    ba_json( array( 'ok' => true ) );
}

/* ---------------- API-Token (Partner-eigene Zugänge) ---------------- */
if ( $action === 'api-keys' ) {
    ba_json( array( 'ok' => true, 'keys' => apikeys::allForBroker( $brokerId ), 'scopes' => apikeys::partnerScopes() ) );
}

if ( $action === 'api-key-create' ) {
    $name = trim( (string) ( $_POST['name'] ?? '' ) );
    if ( $name === '' ) ba_json( array( 'ok' => false, 'error' => 'Bitte einen Namen/Zweck angeben.' ) );
    $res = apikeys::createForBroker( $name, $brokerId );
    ba_json( $res ); // enthält bei Erfolg den EINMALIGEN Klartext-Token
}

if ( $action === 'api-key-toggle' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    apikeys::setActiveForBroker( $id, $brokerId, ! empty( $_POST['active'] ) ? 1 : 0 );
    ba_json( array( 'ok' => true, 'active' => ! empty( $_POST['active'] ) ) );
}

if ( $action === 'api-key-delete' ) {
    apikeys::deleteForBroker( (int) ( $_POST['id'] ?? 0 ), $brokerId );
    ba_json( array( 'ok' => true ) );
}

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

Youez - 2016 - github.com/yon3zu
LinuXploit