Mit diesem Codeschnipsel wird das Guthaben der Seite geschützt
Etwas zum Hintergrund, warum dieses Schnipsel entstand: Mein Hoster hat ein Limit eingesetzt, welches die Datenbankabfragen in der Stunde begrenzt. Ich wurde über diese neue Einstellung nicht informiert, so das vollkommen überraschend massenweise Fehler auftraten. Die Datenbank "machte dicht" und nichts ging mehr.
Dann meldete ein User, dass bei der Auszahlung ein Fehler auftritt, der es ermöglicht, das Konto des Seitenbetreibers abzuräumen ....
Kontrolle ergab, das bei der Auszahlung die Schnittstelle zu Klamm, Cashcrawler etc. bedient wird und danach diese Auszahlung auf dem Userkonto verbucht wird. Wenn die Datenbank nun keine Abfragen mehr annimmt, wird über die Schnittstelle ausgezahlt, aber diese Auszahlung in der Datenbank der Seite nicht festgehalten.
Ein User bekam das auch sehr schnell mit und zahlte eine grosse Summe auf die Seite ein. Zum Glück hatte ich ja eine Info bekommen und habe dadurch verhindern können, dass dieser User mit dieser grösseren Summe noch mehr ergaunern konnte.
Nun habe ich eine Kontrolle eingebaut, welche evtl. Fehlermeldungen bei der Arbeit mit der Datenbank auswertet und entsprechend reagiert. In den letzten Tagen hat mir dieser Schnipsel schon eine Menge Stress erspart. Denn auch wenn der User, der davon betroffen ist, bereit ist zurückzuzahlen, ist es doch eine Unannehmlichkeit, die oft mit Stress verbunden ist.
Hier nun die Anleitung:
Als erstes müssen wir dafür sorgen, dass das Auszahlungsscript überhaupt merkt, das etwas bei der Arbeit mit der Datenbank schief läuft. Das VMS1 ist leider so aufgebaut, das keinerlei Fehlermeldungen an das aufrufende Script durchgegeben wird.
Sämtliche Datenbankabfragen werden in der functions.lib abgearbeitet. Diese befindet sich im Verzeichnis /lib. In der functions.lib ist eine Funktion db_query. Orginal sieht sie wie folgt aus:
PHP-Code:
function db_query($sql_tag) {
$sql_return = mysql_query($sql_tag);
return $sql_return;
}
Um evtl. Fehlermeldungen durchzureichen, muss diese Funktion so aussehen:
PHP-Code:
function db_query($sql_tag) {
global $sql_open;
$sql_return = mysql_query($sql_tag);
$fehler = mysql_errno($sql_open);
if($fehler){
$sql_return = $fehler;
}
return $sql_return;
}
Es wird nun geprüft, ob bei der Abarbeitung ein Fehler aufgetreten ist. Wenn ja, wird diese Meldung anstatt der normalen Ergebnismenge zurückgegeben.
Der nächste Punkt ist die auszahlen.php selbst. Diese liegt im Verzeichnis /content/konto
Ich das Orginalstück des Scriptes, der geändert werden muss:
PHP-Code:
if ($_POST['trans_menge'] <= $kontodaten['kontostand']) {
if ($schnittstelle['anfragen_user'] == 0 or $s_verbrauch < $schnittstelle['anfragen_user']) {
$buchungs_id = create_code(14);
@require_once ("lib/schittstellen/".$schnittstelle['schnittstelle'].".php");
@auszahlen ($schnittstelle['betreiber_id'],$schnittstelle['betreiber_passwort'],$_SESSION['uid'],$_POST['uid_passwort'],$schnittstelle['betreiber_kennung'],$_POST['trans_menge'],$schnittstelle['auszahltext'],'');
if ($schnittstelle['anfragen_user'] != 0) db_query("INSERT INTO ".$db_prefix."_schnittstelle_anfragen (zeit,uid) VALUES ('".$tag."','".$_SESSION['uid']."')");
if ($error) {
$auszahlmeldung = $trans_ausgabe;
} else {
kontobuchung ('-',$_POST['trans_menge'],$_SESSION['uid']);
buchungsliste ($buchungs_id,'-'.$_POST['trans_menge'],$schnittstelle['auszahltext'],$_SESSION['uid']);
$auszahlmeldung = 'Es wurden '.$_POST['trans_menge'].' '.$waehrung.' ausgezahlt';
}
} else {
$auszahlmeldung = 'Deine Schnittstellenanfragen sind verbraucht!!!';
}
} else {
$auszahlmeldung = 'Soviel Guthaben hast Du nicht!!!';
}
Und so sieht dieses Teil nun bei mir aus:
PHP-Code:
if ($_POST['trans_menge'] <= $kontodaten['kontostand']) {
if ($schnittstelle['anfragen_user'] == 0||(($schnittstelle['anfragen_user'] != 0) && (@$s_verbrauch < $schnittstelle['anfragen_user']))) {
$buchungs_id = create_code(14);
@require_once ("lib/schittstellen/".$schnittstelle['schnittstelle'].".php");
@auszahlen ($schnittstelle['betreiber_id'],$schnittstelle['betreiber_passwort'],$_SESSION['uid'],$_POST['uid_passwort'],$schnittstelle['betreiber_kennung'],$_POST['trans_menge'],$schnittstelle['auszahltext'],'');
if ($schnittstelle['anfragen_user'] != 0) db_query("INSERT INTO ".$db_prefix."_schnittstelle_anfragen (zeit,uid) VALUES ('".$tag."','".$_SESSION['uid']."')");
if ($error) {
$auszahlmeldung = $trans_ausgabe;
} else {
$fehler = db_query("UPDATE ".$db_prefix."_kontodaten SET `kontostand` = `kontostand` - ".$trans_menge." WHERE uid=".$_SESSION['uid']."");
$return=mysql_affected_rows($sql_open);
@mail("deinemail@addy.de","Userauszahlung ".$_SESSION['uid']." ".$_POST['trans_menge'],"Betroffene Datensaetze: ".$return." Fehler: ".$fehler." User: ".$_SESSION['uid']." Buchungsid: ".$buchungs_id." Menge: ".$_POST['trans_menge'], 'FROM: '.$seitenname.' <'.$betreibermail.'>');
if($fehler>1){
//rueckbuchung
@einzahlen ($schnittstelle['betreiber_id'],$schnittstelle['betreiber_passwort'],$_SESSION['uid'],$_POST['uid_passwort'],$schnittstelle['betreiber_kennung'],$_POST['trans_menge'],"Rückbuchung - miles4you.de",'');
$auszahlmeldung = "Bei der Auszahlung ist ein Fehler aufgetreten!";
}else{
buchungsliste ($buchungs_id,'-'.$_POST['trans_menge'],$schnittstelle['auszahltext'],$_SESSION['uid']);
$auszahlmeldung = 'Es wurden '.$_POST['trans_menge'].' '.$waehrung.' ausgezahlt';
}
}
} else {
$auszahlmeldung = 'Deine Schnittstellenanfragen sind verbraucht!';
}
} else {
$auszahlmeldung = 'Soviel Guthaben hast Du nicht!';
}
Wie funktioniert das nun?
Nachdem das Guthaben über die Schnittstelle ausgezahlt wurde, wird die Buchung auf dem Kundenkonto des Users durchgeführt. Nach dieser Buchung wird geprüft, ob ein Fehler aufgetreten ist. Das der Fehlercode (falls einer auftritt) übergeben wird, haben wir vorhin in der functions.lib eingebaut.
Nach der Abarbeitung wird die Anzahl der betroffenen Datensätze und ein evtl. Fehlercode von mysql ausgewertet.
Bei einer ordnungsgemässen Abarbeitung wird bei dieser Update-Anweisung die Zahl "1" zurückgegeben. Das bedeutet, das eine Zeile bei der Abarbeitung betroffen war. In dem Fall ist alles in Ordnung, es wird ein Eintrag in der Buchungsliste geschrieben, eine Meldung ausgegeben und fertig.
Wenn eine Zahl grösser 1 zurückgegeben wird, ist ein Fehler aufgetreten. In dem Fall wird das Guthaben, das nun schon über die Schnittstelle ausgezahlt wurde, zurückgebucht. Beim User wird eine Fehlermeldung ausgegeben und das Script ist zu Ende.
Der Befehl mysql_affected_rows fragt auch die Anzahl der betroffenen Datensätze ab, allerdings hat mir dieser Wert zur Identifizierung von sql-fehlern nicht ausgereicht
Für denjenigen, der sich mit sql etwas auskennt, ist es schon recht hilfreich, den genauen Fehlercode zu haben. Wem diese Information zuviel ist, kann sie auch in der Mailanweisung rausnehmen.
Falls du nur bei einem Fehler eine Mail erhalten möchtest, musst du die Mailanweisung eine Zeile tiefer, nach "if($fehler>1){" setzen.
So eine Mail bekomme ich nun, wenn die Abarbeitung richtig gelaufen ist:
Betroffene Datensaetze: 1 Fehler: 1 User: 12345 Buchungsid: mAUBf955biKEdt Menge: 2929
und so ein Fehler:
Betroffene Datensaetze: -1 Fehler: 1226 User: 12347 Buchungsid: MABxGvmk4bBT4T Menge: 3249
Und das auf dem Konto bei Cashcrawler.de:
25.03 22:39 Auszahlung - miles4you.de 12347 -3249
25.03 22:39 Rückbuchung - miles4you.de 12347 3249
Und mit dieser Rückbuchung ist mein Guthaben gerettet
Bei Fragen und Problemen helf ich gern weiter
plopp