dolibarr.idsconnect/class/idssupplier.class.php
data d91f9dbc9a IDS Connect v2.1 - WKE + WKS mit Sonepar live getestet
- WKE-Flow (Warenkorb empfangen): Sonepar-Integration komplett funktionsfähig
  inkl. PriceBasis-Handling, Namespace-Stripping, OCI-Unterstützung
- WKS-Flow (Warenkorb senden): Lieferantenbestellung → Shop mit vorausgefüllten
  Artikeln, IDS Connect 2.0 XML-Format
- Callback v2.0: NOLOGIN-Seite statt Redirect, 7 Datenquellen, Debug-Daten
- URL-Handling: user_base_url-Tracking für Cross-Domain-Szenarien
- Sicherheit: CSRF, HMAC-SHA256 Tokens, XXE-Schutz, PIN für WKS
- Mock-Server für lokale Tests
- Dokumentation mit Roadmap (fehlende Features, Möglichkeiten)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:37:15 +01:00

297 lines
8.4 KiB
PHP

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*/
/**
* \file idsconnect/class/idssupplier.class.php
* \ingroup idsconnect
* \brief Großhändler-Konfiguration für IDS Connect
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
/**
* Klasse für IDS Connect Großhändler-Konfiguration
*/
class IdsSupplier
{
/** @var DoliDB */
public $db;
/** @var int */
public $id;
/** @var string */
public $ref;
/** @var string */
public $label;
/** @var int Verknüpfter Dolibarr-Lieferant */
public $fk_soc;
/** @var string Shop-URL für IDS Connect */
public $ids_url;
/** @var string IDS-Version (2.0, 2.3, 2.5) */
public $ids_version = '2.5';
/** @var string Kundennummer beim Großhändler */
public $ids_customer_no;
/** @var string Benutzerkennung */
public $ids_username;
/** @var string Passwort (verschlüsselt in DB) */
public $ids_password;
/** @var int Testmodus (1=aktiv, 0=live) */
public $testmode = 1;
/** @var int Aktiv (1=ja, 0=nein) */
public $active = 1;
/** @var string */
public $note_public;
/** @var string */
public $note_private;
/** @var string */
public $date_creation;
/** @var int */
public $fk_user_creat;
/** @var int */
public $fk_user_modif;
/** @var int */
public $entity;
/** @var string */
public $error = '';
/** @var array */
public $errors = array();
const TABLE = 'idsconnect_supplier';
/**
* Constructor
*
* @param DoliDB $db Datenbank-Handler
*/
public function __construct($db)
{
$this->db = $db;
}
/**
* Großhändler anlegen
*
* @param User $user Benutzer der die Aktion ausführt
* @return int >0 bei Erfolg, <0 bei Fehler
*/
public function create($user)
{
global $conf;
$this->entity = $conf->entity;
$this->fk_user_creat = $user->id;
$this->date_creation = dol_now();
// Passwort verschlüsseln
$encrypted_password = dolEncrypt($this->ids_password);
$sql = "INSERT INTO ".$this->db->prefix().self::TABLE." (";
$sql .= "ref, label, fk_soc, ids_url, ids_version, ids_customer_no,";
$sql .= " ids_username, ids_password, testmode, active,";
$sql .= " note_public, note_private, date_creation, fk_user_creat, entity";
$sql .= ") VALUES (";
$sql .= "'".$this->db->escape($this->ref)."',";
$sql .= " '".$this->db->escape($this->label)."',";
$sql .= " ".($this->fk_soc > 0 ? ((int) $this->fk_soc) : "NULL").",";
$sql .= " '".$this->db->escape($this->ids_url)."',";
$sql .= " '".$this->db->escape($this->ids_version)."',";
$sql .= " '".$this->db->escape($this->ids_customer_no)."',";
$sql .= " '".$this->db->escape($this->ids_username)."',";
$sql .= " '".$this->db->escape($encrypted_password)."',";
$sql .= " ".((int) $this->testmode).",";
$sql .= " ".((int) $this->active).",";
$sql .= " ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "NULL").",";
$sql .= " ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL").",";
$sql .= " '".$this->db->idate($this->date_creation)."',";
$sql .= " ".((int) $this->fk_user_creat).",";
$sql .= " ".((int) $this->entity);
$sql .= ")";
$this->db->begin();
$resql = $this->db->query($sql);
if ($resql) {
$this->id = $this->db->last_insert_id($this->db->prefix().self::TABLE);
$this->db->commit();
return $this->id;
} else {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
}
}
/**
* Großhändler laden
*
* @param int $id ID
* @param string $ref Referenz
* @return int >0 bei Erfolg, 0 nicht gefunden, <0 bei Fehler
*/
public function fetch($id = 0, $ref = '')
{
global $conf;
$sql = "SELECT rowid, ref, label, fk_soc, ids_url, ids_version,";
$sql .= " ids_customer_no, ids_username, ids_password, testmode, active,";
$sql .= " note_public, note_private, date_creation, fk_user_creat, fk_user_modif, entity";
$sql .= " FROM ".$this->db->prefix().self::TABLE;
if ($id > 0) {
$sql .= " WHERE rowid = ".((int) $id);
} elseif ($ref) {
$sql .= " WHERE ref = '".$this->db->escape($ref)."'";
} else {
return -1;
}
$sql .= " AND entity IN (".getEntity('idsconnect').")";
$resql = $this->db->query($sql);
if ($resql) {
if ($this->db->num_rows($resql) > 0) {
$obj = $this->db->fetch_object($resql);
$this->id = $obj->rowid;
$this->ref = $obj->ref;
$this->label = $obj->label;
$this->fk_soc = $obj->fk_soc;
$this->ids_url = $obj->ids_url;
$this->ids_version = $obj->ids_version;
$this->ids_customer_no = $obj->ids_customer_no;
$this->ids_username = $obj->ids_username;
// Passwort entschlüsseln
$this->ids_password = dolDecrypt($obj->ids_password);
$this->testmode = $obj->testmode;
$this->active = $obj->active;
$this->note_public = $obj->note_public;
$this->note_private = $obj->note_private;
$this->date_creation = $this->db->jdate($obj->date_creation);
$this->fk_user_creat = $obj->fk_user_creat;
$this->fk_user_modif = $obj->fk_user_modif;
$this->entity = $obj->entity;
return 1;
}
return 0;
} else {
$this->error = $this->db->lasterror();
return -1;
}
}
/**
* Großhändler aktualisieren
*
* @param User $user Benutzer der die Aktion ausführt
* @return int >0 bei Erfolg, <0 bei Fehler
*/
public function update($user)
{
$encrypted_password = dolEncrypt($this->ids_password);
$sql = "UPDATE ".$this->db->prefix().self::TABLE." SET";
$sql .= " ref = '".$this->db->escape($this->ref)."',";
$sql .= " label = '".$this->db->escape($this->label)."',";
$sql .= " fk_soc = ".($this->fk_soc > 0 ? ((int) $this->fk_soc) : "NULL").",";
$sql .= " ids_url = '".$this->db->escape($this->ids_url)."',";
$sql .= " ids_version = '".$this->db->escape($this->ids_version)."',";
$sql .= " ids_customer_no = '".$this->db->escape($this->ids_customer_no)."',";
$sql .= " ids_username = '".$this->db->escape($this->ids_username)."',";
$sql .= " ids_password = '".$this->db->escape($encrypted_password)."',";
$sql .= " testmode = ".((int) $this->testmode).",";
$sql .= " active = ".((int) $this->active).",";
$sql .= " note_public = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "NULL").",";
$sql .= " note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL").",";
$sql .= " fk_user_modif = ".((int) $user->id);
$sql .= " WHERE rowid = ".((int) $this->id);
$this->db->begin();
$resql = $this->db->query($sql);
if ($resql) {
$this->db->commit();
return 1;
} else {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
}
}
/**
* Großhändler löschen
*
* @param User $user Benutzer
* @return int >0 bei Erfolg, <0 bei Fehler
*/
public function delete($user)
{
$this->db->begin();
// Zuerst Logs löschen
$sql = "DELETE FROM ".$this->db->prefix()."idsconnect_log WHERE fk_supplier = ".((int) $this->id);
$this->db->query($sql);
$sql = "DELETE FROM ".$this->db->prefix().self::TABLE." WHERE rowid = ".((int) $this->id);
$resql = $this->db->query($sql);
if ($resql) {
$this->db->commit();
return 1;
} else {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
}
}
/**
* Alle aktiven Großhändler laden
*
* @param int $activeonly Nur aktive (1) oder alle (0)
* @return array|int Array mit Objekten oder -1 bei Fehler
*/
public function fetchAll($activeonly = 1)
{
$list = array();
$sql = "SELECT rowid FROM ".$this->db->prefix().self::TABLE;
$sql .= " WHERE entity IN (".getEntity('idsconnect').")";
if ($activeonly) {
$sql .= " AND active = 1";
}
$sql .= " ORDER BY label ASC";
$resql = $this->db->query($sql);
if ($resql) {
while ($obj = $this->db->fetch_object($resql)) {
$supplier = new self($this->db);
$supplier->fetch($obj->rowid);
$list[] = $supplier;
}
return $list;
}
$this->error = $this->db->lasterror();
return -1;
}
/**
* Passwort maskiert zurückgeben (für Anzeige)
*
* @return string Maskiertes Passwort
*/
public function getMaskedPassword()
{
if (empty($this->ids_password)) {
return '';
}
$len = strlen($this->ids_password);
if ($len <= 4) {
return str_repeat('*', $len);
}
return substr($this->ids_password, 0, 2).str_repeat('*', $len - 4).substr($this->ids_password, -2);
}
}