ik heb een webwinkeltje gemaakt maar er zit een vreemde bug in.
Wanneer ik het zelf test werkt alles perfect, wanneer een klant een bestelling doet dan worden de NAW gegevens en de bestelde producten niet goed doorgevoerd.
Ik heb de code wel 100 keer nagekeken en getest maar alles werkt perfect elke keer als ik het test. In verschillende browsers en op verschillende computers.
<?php
/*
Code om transactiegegevens van ING te ontvangen
*/
// Gegevens uit de inputstream trekken
$response = file_get_contents('php://input');
// Gegevens in een bruikbaar object zetten
$xml = simplexml_load_string($response);
// Transactiestatus bekijken
if($xml->status == "Success")
{
require_once('includes/class.phpmailer.php');
// Transactie verwerken
// Order id is: $xml->purchaseID
$query = mysql_query('SELECT * FROM site_bestellingen
WHERE
orderid = "'.mysql_real_escape_string($xml->purchaseID).'"');
$fetch = mysql_fetch_assoc($query);
$email = '<h1>Bestelling geplaatst</h1>
<p>Klant heeft gekozen voor <strong>iDeal overschrijving</strong>, deze is dus al voldaan!</p>
<p><strong>De volgende klantgegevens zijn genoteerd:</strong><br />
voornaam: '.$fetch['voornaam'].'<br />
achternaam: '.$fetch['achternaam'].'<br />
straat: '.$fetch['straat'].'<br />
postcode: '.$fetch['postcode'].'<br />
plaats: '.$fetch['plaats'].'<br />
e-mail: '.$fetch['email'].'<br />
telefoon nummer: '.$fetch['telefoonnummer'].'<br />
</p>
<br />
<h2>De volgende producten zijn besteld</h2><br /><br />'.$fetch['bestelling'].'</br ><br />';
$email .= 'uw order id is: <strong>'.$xml->purchaseID.'</strong>';
$mail = new PHPMailer();
$mail->From = 'no-reply@mijnsite.nl';
$mail->FromName = 'mijnsite';
$mail->AddAddress('info@mijnsite.nl', 'mijnsite');
$mail->AddReplyTo('no-reply@mijnsite.nl', 'mijnsite');
$mail->IsHTML(true);
$mail->Subject = 'Bestelling geplaatst op mijnsite '.date("d-m-Y H:i:s", mktime()).'.';
$mail->Body = $email;
$mail->Send();
/* EMAIL FOR CUSTOMER
* THIS EMAIL NOTIFIES THE CUSTOMER ABOUT
THE ORDER AND THE PRODUCTS THAT HAVE
* BEEN ORDERED BY THE CUSTOMER
*/
$email = '<h1>Bestelling geplaatst</h1>
<p><strong>Wij hebben de volgende gegevens genoteerd:</strong><br />
voornaam: '.$fetch['voornaam'].'<br />
achternaam: '.$fetch['achternaam'].'<br />
straat: '.$fetch['straat'].'<br />
postcode: '.$fetch['postcode'].'<br />
plaats: '.$fetch['plaats'].'<br />
e-mail: '.$fetch['email'].'<br />
telefoon nummer: '.$fetch['telefoonnummer'].'<br /><br />
<strong>betaalmethode:</strong> iDeal<br /><br />
</p>
<br />
<h2>U heeft de volgende producten besteld</h2><br /><br />'.$fetch['bestelling'].'<br /><br />';
$email .= 'uw order id is: <strong>'.$xml->purchaseID.'</strong><br /><br />Indien u onverhoopt een fout heeft ontdekt in uw bestelling, neemt u dan svp contact met ons op.';
$mail = new PHPMailer();
$mail->From = 'no-reply@mijnsite.nl';
$mail->FromName = 'mijnsite';
$mail->AddAddress($_SESSION['email'], $_SESSION['voornaam'].' '.$_SESSION['achternaam']);
$mail->AddReplyTo('no-reply@mijnsite.nl', 'mijnsite');
$mail->IsHTML(true);
$mail->Subject = 'Bestelling geplaatst op mijnsite '.date("d-m-Y H:i:s", mktime()).'.';
$mail->Body = $email;
$mail->Send();
mysql_query('UPDATE site_bestellingen
SET
temp = 0
WHERE
orderid = "'.mysql_real_escape_string($xml->purchaseID).'"');
unset($_SESSION['basket']);
echo 'Uw betaling is succesvol ontvangen, wij danken u voor uw bestelling!';
} else {
// Cancelled
// Meestal doe je dan niks, maar voor het geval dat maar een else toegevoegd
// Je zou evt wel de order kunnen annuleren
echo 'Uw betaling is <strong>niet</strong> voldaan, u kunt nu verder winkelen!';
}
/* Eventueel zijn er nog de variablen:
$xml->createDateTimeStamp - aanmaakdatum transactie
$xml->transactionID - transactie Id vanuit de bank
*/
?>
<h2>U heeft de volgende producten besteld</h2><br /><br />'.$fetch['bestelling'].'<br /><br />';
$email.='uw order id is: <strong>'.$xml->purchaseID.'</strong><br /><br />Indien u onverhoopt een fout heeft ontdekt in uw bestelling, neemt u dan svp contact met ons op.';
$xml->transactionID - transactie Id vanuit de bank
*/
?>
Wanneer iemand betaald heeft via iDeal krijg ik netjes een email alleen staan er GEEN NAW gegevens in of wat voor andere tekst dan ook (uit de database). Dus er staan geen naam, adres, woonplaats, welke artikelen besteld zijn en zo voort.
Heeft iemand enig idee wat er fout zou kunnen zijn?
Vermoedelijk gaat je sessie verloren als je naar de externe site gaat (van ING in dit geval).
Dus wat je dan doet:
- Sla de gegevens op in de database met de transactie id voor het betalen.
- Na het betalen roep je de gegevens op uit de database op basis van de transactie id.
dit is dus precies wat ik gedaan heb. Je ziet in de query al dat ik de tabel selecteer met de bijbehorende transactie id ;)
Thomas - 08/07/2014 16:28 (laatste wijziging 08/07/2014 16:32)
Moderator
Citaat:
Wanneer ik het zelf test werkt alles perfect, wanneer een klant een bestelling doet dan worden de NAW gegevens en de bestelde producten niet goed doorgevoerd.
- is de applicatie die je test in beide gevallen hetzelfde? daarmee bedoel ik: test je in beide gevallen op dezelfde (web)server of test jij op je dev/test-omgeving en de klant ergens anders; oftewel testen jullie beiden echt hetzelfde?
- wat bedoel je met "de NAW gegevens en de bestelde gegeven worden niet goed doorgevoerd"; worden deze niet goed opgeslagen? waar gaat het precies fout? waaruit blijkt dat het fout gaat? welke foutmelding(en) krijg je? Een eerste stap die je bij dit soort problemen kunt zetten is het isoleren van het probleem - dit kun je bijvoorbeeld doen door het dumpen van data (naar output) op specifieke punten in je code, vaak kun je dan snel zien waar het mis gaat.
Citaat:
Ik heb de code wel 100 keer nagekeken en getest maar alles werkt perfect elke keer als ik het test. In verschillende browsers en op verschillende computers.
De browsers zijn dan waarschijnlijk niet het probleem (maar ik zou dit niet uitsluiten zolang je de oorzaak niet gevonden hebt).
Omdat je niet kunt aangeven waar het precies misgaat, kan ik ook niet echt de vinger op de zere plek leggen. Wel kan ik een aantal pointers geven:
- ik neem aan dat je ook ergens je sessies expliciet start met session_start()?
- let op bij het gebruik van isset. Als <waarde> in isset(<waarde>) een van de volgende waarden heeft: het cijfer 0, de lege string '', de boolean false, dan retourneert isset(<waarde>) false; misschien kun je beter controleren op array_key_exists of wat meer controles uitvoeren bij het invoeren van gegevens
- ik zie dat je short open tags gebruikt (<?= ... yadda ... ?>); wordt dit overal ondersteund? heb je de HTML-output van je formulier wel eens bekeken om te zien of alle waarden er goed in zitten?
- wordt simplexml overal ondersteund?
- heb je (voorbeeld)data van de klant waar het niet werkt? is deze "case" na te bootsen? misschien kun je eens meekijken bij de klant met behulp van remote desktop programma's zoals teamviewer
- (security) je gebruikt wel (deels) input escaping, maar geen output filtering (bij het afdrukken van data). wellicht is het verstandig om overal waar je data afdrukt gebruik te maken van htmlspecialchars(), zorg hierbij dat je de goede character set toepast (ik neem aan dat dit UTF-8 is?)
Ik ga dadelijk even alles na lopen, hartelijk dank voor de goede suggesties! ik laat het jullie straks (later op de avond) even weten
Overigens test ik op de zelfde server, dus alles zou het zelfde moeten zijn. Meerdere computers, meerdere locaties en meerdere browsers gebruikt maar altijd goed, tot dat een klant (onbekende) iets besteld op de webwinkel en dan word er na een iDeal betaling geen NAW gegevens uit de database gehaald en opgeslagen. Het is net alsof iDeal het niet goed terug geeft of zo iets maar dit zou wel zo moeten zijn.
Ik loop alles nog even na en laat het weten hier ;)
Thomas - 08/07/2014 16:43 (laatste wijziging 08/07/2014 16:51)
Moderator
Wordt de bestelling wel weggeschreven?
Je controleert in het tweede fragment namelijk niet of er resultaten zijn, je fetcht meteen een resultaat... wat er wellicht niet is (regel 19 t/m 22).
Daarnaast zou dit met simplexml te maken kunnen hebben. Je kunt volgens mij niet simpelweg de waardes van nodes als string gebruiken, tenzij je deze typecast dacht ik. Anyway, debug je query eens en kijk wat de waarde van $xml->purchaseID is...
EDIT: ik maak hier ook uit op dat error_reporting uit staat? Op een productie-omgeving is dit natuurlijk handig, maar heb je geen eigen errorhandler? Daarnaast zou je op IP-basis error_reporting aan kunnen zetten, zodat JIJ wel (potentiële) fouten ziet, maar je klanten niet.
- let op bij het gebruik van isset. Als <waarde> in isset(<waarde>) een van de volgende waarden heeft: het cijfer 0, de lege string '', de boolean false, dan retourneert isset(<waarde>) false; misschien kun je beter controleren op array_key_exists of wat meer controles uitvoeren bij het invoeren van gegevens
? Volgens mij niet. Dat is empty.
Empty geeft bij de lege string, integer 0, string 0 en false de boolean 'false' terug.
Isset geeft bij bovenstaande true terug.
Thomas - 09/07/2014 14:32 (laatste wijziging 09/07/2014 14:56)
Moderator
Oh, dan was het isset() met null. Ik had dit moeten testen.
Anyhoo, het was om uit te sluiten dat het om zo'n (onzinnige) reden op een of andere manier niet zou werken.
Dit euvel zou toch eenvoudig op te lossen moeten zijn met gebruikmaking van bovenstaande hints in combinatie met het inbouwen van wat momenten waarop informatie gedumpt wordt.
EDIT: En (@topicstarter) als je inderdaad vermoed dat je "sessie verloren gaat", dump je sessie-id eens of houd je sessie-cookie in de gaten en kijk of de hash daarvan verandert (dit is je sessie-id) voor en na betalen.
Dank jullie voor jullie goede antwoorden, toch weer het e.e.a. uit kunnen leren. Ga dit onthouden voor toekomstige dingen dankjewel!
Tot op heden nog niet opgelost (volledig) echter weet ik nu wel waar het probleem zit. Dit is op de pagina waarnaar iDeal de gebruiker terug stuurt. Onderstaand de code:
<?php
/*
Code om transactiegegevens van ING te ontvangen
*/
// Gegevens uit de inputstream trekken
$response = file_get_contents('php://input');
// Gegevens in een bruikbaar object zetten
$xml = simplexml_load_string($response);
// Transactiestatus bekijken, als deze correct is database updaten en email naar beheerder
// en de klant versturen zodat deze op de hoogte zijn van een succesvolle bestelling
if($xml->status == "Success")
{
require_once('includes/class.phpmailer.php');
// Transactie verwerken
// Order id is: $xml->purchaseID
$query = mysql_query('SELECT * FROM site_bestellingen
WHERE
orderid = "'.mysql_real_escape_string($xml->purchaseID).'"');
$fetch = mysql_fetch_assoc($query);
$email = '<h1>Bestelling geplaatst</h1>
<p>Klant heeft gekozen voor <strong>iDeal overschrijving</strong>, deze is dus al voldaan!</p>
<p><strong>De volgende klantgegevens zijn genoteerd:</strong><br />
voornaam: '.$fetch['voornaam'].'<br />
achternaam: '.$fetch['achternaam'].'<br />
straat: '.$fetch['straat'].'<br />
postcode: '.$fetch['postcode'].'<br />
plaats: '.$fetch['plaats'].'<br />
e-mail: '.$fetch['email'].'<br />
telefoon nummer: '.$fetch['telefoonnummer'].'<br />
</p>
<br />
<h2>De volgende producten zijn besteld</h2><br /><br />'.$fetch['bestelling'].'</br ><br />';
$email .= 'uw order id is: <strong>'.$xml->purchaseID.'</strong>';
$mail = new PHPMailer();
$mail->From = '';
$mail->FromName = '';
$mail->AddAddress('', '');
$mail->AddReplyTo('', '');
$mail->IsHTML(true);
$mail->Subject = 'Bestelling geplaatst op '.date("d-m-Y H:i:s", mktime()).'.';
$mail->Body = $email;
$mail->Send();
/* EMAIL FOR CUSTOMER
* THIS EMAIL NOTIFIES THE CUSTOMER ABOUT
THE ORDER AND THE PRODUCTS THAT HAVE
* BEEN ORDERED BY THE CUSTOMER
*/
$email = '<h1>Bestelling geplaatst</h1>
<p><strong>Wij hebben de volgende gegevens genoteerd:</strong><br />
voornaam: '.$fetch['voornaam'].'<br />
achternaam: '.$fetch['achternaam'].'<br />
straat: '.$fetch['straat'].'<br />
postcode: '.$fetch['postcode'].'<br />
plaats: '.$fetch['plaats'].'<br />
e-mail: '.$fetch['email'].'<br />
telefoon nummer: '.$fetch['telefoonnummer'].'<br /><br />
<strong>betaalmethode:</strong> iDeal<br /><br />
</p>
<br />
<h2>U heeft de volgende producten besteld</h2><br /><br />'.$fetch['bestelling'].'<br /><br />';
$email .= 'uw order id is: <strong>'.$xml->purchaseID.'</strong><br /><br />Indien u onverhoopt een fout heeft ontdekt in uw bestelling, neemt u dan svp contact met ons op.';
$mail = new PHPMailer();
$mail->From = '';
$mail->FromName = '';
$mail->AddAddress($_SESSION['email'], $_SESSION['voornaam'].' '.$_SESSION['achternaam']);
$mail->AddReplyTo('', '');
$mail->IsHTML(true);
$mail->Subject = 'Bestelling geplaatst op '.date("d-m-Y H:i:s", mktime()).'.';
$mail->Body = $email;
$mail->Send();
mysql_query('UPDATE site_bestellingen
SET
temp = 0
WHERE
orderid = "'.mysql_real_escape_string($xml->purchaseID).'"');
unset($_SESSION['basket']);
echo 'Uw betaling is succesvol ontvangen, wij danken u voor uw bestelling!';
} else {
// Cancelled
// Meestal doe je dan niks, maar voor het geval dat maar een else toegevoegd
// Je zou evt wel de order kunnen annuleren
echo 'Uw betaling is <strong>niet</strong> voldaan, u kunt nu verder winkelen!';
}
/* Eventueel zijn er nog de variablen:
$xml->createDateTimeStamp - aanmaakdatum transactie
$xml->transactionID - transactie Id vanuit de bank
*/
?>
<h2>U heeft de volgende producten besteld</h2><br /><br />'.$fetch['bestelling'].'<br /><br />';
$email.='uw order id is: <strong>'.$xml->purchaseID.'</strong><br /><br />Indien u onverhoopt een fout heeft ontdekt in uw bestelling, neemt u dan svp contact met ons op.';
$xml->transactionID - transactie Id vanuit de bank
*/
?>
Volgens mijn is de fout dat er geen of een incorrecte transactie id word terug gegeven vanuit iDeal.
Op de vorige pagina (dus voordat je de betaling doet) sla ik de order al op in de database met een tijdelijke (temp) status met de waarde 1. Dit wilt zeggen dat er een bestelling gedaan is maar nog niet betaald.
Na de iDeal betaling word de status niet geupdate naar 0 zoals in de code staat. Dus of iDeal stuurt niet door naar deze pagina (wat me sterk lijkt want het staat aangegeven, zie onderstaande code) of de transactie id klopt niet.
Iemand enig idee? weet ook niet goed hoe ik dit kan testen zonder elke keer een bestelling te doen en via iDeal te betalen wat me dus elke keer geld kost en regelwerk haha
Thomas - 18/07/2014 10:59 (laatste wijziging 20/07/2014 16:17)
Moderator
Ik denk dat je probleem de omgang met simpleXML is. Alle data waaraan je refereert in $xml zijn objecten. Als je de waarde van zo'n object afdrukt vindt een impliciete typecast plaats, waardoor je de string-waarde van het object terugkrijgt en het lijkt alsof alles klopt.
De oplossing ligt (waarschijnlijk) in het typecasten van de XML-waarden.
<?php
header('Content-Type: text/html; charset=UTF-8');
$test = '<root>
<item><value>hoi</value></item>
<item><value>12</value></item>
</root>';
$xml = simplexml_load_string($test);
var_dump($xml);
// drukt braaf string af (impliciete typecast)
echo $xml->item[0]->value;
// als je de waarde toekent aan een variabele, is dit (nog steeds) een object
$value = $xml->item[0]->value;
var_dump($value);
var_dump($xml->item[0]->value);
// wat je zou moeten doen is een typecast
$value = (string) $xml->item[0]->value;
var_dump($value);
if ((string) $xml->item[0]->value == 'hoi') {
echo 'succes!';
}
?>
EDIT: hmm, een vergelijking met == is best coulant, het vergelijken van een object met een string werkt haha. Maar goed, mogelijk zit hier ergens het probleem. Daarnaast kan het geen kwaad om deze waarden eens te dumpen.
Ook controleer je (nog steeds?) niet of je SELECT query resultaten heeft...
EDIT 2: verder weet ik niet of de keuze die je hebt gemaakt voor purchaseID (timestamp) een verstandige is. Dit zou toch uniek moeten identificeren voor wie de aankoop is? Wat nu als er twee of meer personen op hetzelfde moment een aankoop doen?
Daarnaast: je maakt geen gebruik van transacties, dit is misschien voor dit soort zaken het overwegen waard.
Tevens: quotes om nummers in queries ...
Ook: je hebt geen terugkoppeling als een query fout gaat, niet eens een "or die". Je kunt dus niet goed nagaan of een query om een of andere reden fout gaat? Vooral niet als je op je productieomgeving de weergave van fouten enzo uitzet...
Gesponsorde links
Je moet ingelogd zijn om een reactie te kunnen posten.