Bonjour,

j'ai un petit problème car les utilisateurs peuvent modifier le code source des champs caché en l'occurence le prix de l'article, dans mon fichier ipn.php je fait un SELECT pour comparé ce que le client achète à ma base de données, donc le nom et le prix, mais c'est de la que j'ai un problème ça passe quand même si je modifie le code source du montant.

pourriez vous me donner un petit coup de pouce s'il vous plaît.

voici le code de mon fichier ipn.php

<?php

$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
  $keyval = explode ('=', $keyval);
  if (count($keyval) == 2)
     $myPost$keyval[0]] = urldecode($keyval[1]);
}
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
   $get_magic_quotes_exists = true;
} 
foreach ($myPost as $key => $value) {        
   if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { 
        $value = urlencode(stripslashes($value)); 
   } else {
        $value = urlencode($value);
   }
   $req .= "&$key=$value";
}

$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path 
// of the certificate as shown below.
// curl_setopt($ch, CURLOPT_CAINFO, dirname( __FILE__ ) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
    // error_log("Got " . curl_error($ch) . " when processing IPN data");
    curl_close($ch);
    exit;
}
curl_close($ch); 

// STEP 3: Inspect IPN validation result and act accordingly
include("gestion/pont.php");
$email_account = "sell_1353771010_biz@yahoo.fr";
if (strcmp ($res, "VERIFIED") == 0) {
    $item_name = $_POST'item_name'];
    $item_number = $_POST'quantity'];
    $payment_status = $_POST'payment_status'];
    $payment_amount = $_POST'amount'];
    $payment_currency = $_POST'mc_currency'];
    $txn_id = $_POST'txn_id'];
    $receiver_email = $_POST'receiver_email'];
    $payer_email = $_POST'payer_email'];
    $custom = $_POST'custom'];

        if ( $payment_status == "Completed") {

               if ( $email_account == $receiver_email) {
                    file_put_contents('log.txt', print_r($_POST,true)); 

                    $requete="SELECT * FROM album WHERE nom_album=$item_name AND prix_album=$payment_amount";
                    $exe=mysql_query($requete);                 
                    $nb_art=mysql_num_rows($exe);                   

                        if($nb_art != $item_name){                          

                            $paymentok="attente";
                            $data= serialize($_POST);
                            $date_aujourdhui=date("Y-m-d");                 

                            $sql="UPDATE commande SET 
                            datepaiement='$date_aujourdhui',
                            statutcmd='$paymentok',
                            data='$data'
                            WHERE idcmd=$custom";
                            $exe=mysql_query($sql) or die (mysql_error());          
                            file_put_contents('log.txt', 'Le paiement ne correspond à aucun album de la boutique');             

                            }else{                      

                                $paymentok="valide";
                                $data= serialize($_POST);
                                $date_aujourdhui=date("Y-m-d");                 

                                $sql="UPDATE commande SET 
                                datepaiement='$date_aujourdhui',
                                statutcmd='$paymentok',
                                data='$data'
                                WHERE idcmd=$custom";
                                $exe=mysql_query($sql) or die (mysql_error());
                                file_put_contents('log.txt', 'Le paiement à bien été confirmé');            

                            }   

               }else{

                    file_put_contents('log1.txt', 'probleme de l\'adresse email marchand'); 

                   }

        }

} else if (strcmp ($res, "INVALID") == 0) {
    // log for manual investigation
}
?>

Voilà j'aimerais compter le nombre d'article que le client à prix et comparé avec mon SELECT si c'est different du prix 'ERREUR' sinon le paiement c'est bien déroulé.

Merci d'avance à ceux et celle qui se pencheront sur mon problème.

8 réponses


Peux-tu reformuler ta question ^^. Quand tu parles du prix erreur, de quel prix tu parles ?

barbas
Auteur

en fait tu peux par exemple en inspectant le code modifier la valeur du prix et donc payer 0.1 € au lieu de 30€ par exemple et j'aimerais via mon fichier ipn.php vérifier que le montant que je reçois n'as pas été modifier par un petit malin.

c'est pour ça je fait un SELECT dans ma base de données pour comparé mes articles envoyé a ceux vraiment disponible dans ma base.
Mais cela ne fonctionne pas, même si on change via le code le prix ça passe quand même, ma condition ne doit pas être bonne.

Mon formulaire d'envois pour paypal.

<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_cart" />
<input type="hidden" name="upload" value="1" />
<input type="hidden" name="business" value="sell_1353771010_biz@yahoo.fr" />
<input name="lc" type="hidden" value="FR" />
<input name="return" type="hidden" value="http://www.lbrunet.com/disquaire/success.php" />
<input name="cancel_return" type="hidden" value="http://www.lbrunet.com/disquaire/cancel.php" />
<input name="notify_url" type="hidden" value="http://www.lbrunet.com/disquaire/ipn2.php" />
<input type="hidden" name="currency_code" value="EUR" />
<input type="hidden" name="charset" value="utf-8" />
<?php
    $total=0;
    $i=0;
    $item="item_name_"; 
    $amount="amount_";  
    $quantity="quantity_";  

    foreach ($_COOKIE'achat'] as $ref => $qte) {
    $requete="SELECT * FROM album WHERE id_album='$ref' ORDER BY id_album ASC LIMIT 0,1";
    $exec_requete=mysql_query($requete);
    while($ligne=mysql_fetch_array($exec_requete)){
    //$total+=$ligne"prix_album"]*$qte;
    /// OU /// c'est pareil

            $i=$i+1;

            $titre=$ligne"nom_album"];
            $titre=htmlentities($titre);

            $ref=$ligne"id_album"];

            $qte;

            $prix=$ligne"prix_album"];

            $prixligne=$prix*$qte;

            $total+=$prixligne; 

echo '<input type="hidden" name="'.$item.''.$i.'" value="'.$titre.'" />';
//echo '<input type="hidden" name="'.$item.''.$i.'" value="'.$titre.'-'.$ref.'" />';
echo '<input type="hidden" name="'.$amount.''.$i.'" value="'.$prix.'" />';
echo '<input type="hidden" name="'.$quantity.''.$i.'" value="'.$qte.'" />';         

// Suppression du cookie achat
//setcookie ("achat$ref]", "", time() - 3600);
// Suppression de la valeur du tableau $_COOKIE
//unset($_COOKIE'achat']);

    }
?>

<?php }?>
<input type="submit" name="btn" id="autre" value="Payer par CB ou PAYPAL" />
<input name="custom" type="hidden" value="<?php echo $idcmd?>" />
</form>

Personnellement dans ce genre situation je donnerais juste la référence du produit et je ferais tout en asynchrone pour pas que le client puissent affecter d'une quelconque manière le prix du produit ou encore sa transaction.

Le mieux c'est que tu donne un prix mais que tu reprends le prix du produit.

Par contre effectivement je vois un truc étrange :

$nb_art=mysql_num_rows($exe);                   
if($nb_art != $item_name){

Qu'est-ce que $item_name ?

Surtout pourquoi tu fais ce genre de comparaison entre un chiffre (nombre de ligne retourner par la requête dans notre cas 0 ou 1 avec un chaine de caractère (qui ma l'air le nom du produit).

Comment te dire ça aussi :

SELECT * FROM album WHERE nom_album=$item_name AND prix_album=$payment_amount

Cette requête ne sera jamais fiable à 10%.
Trouve un identifiant unique qui te permet de vraiment définir un produit. Surtout si tu as de thune en jeu. Les données non fiable peuvent être problématique.

barbas
Auteur

Salut, merci de t'attarder sur mon problème

j'ai bien un id sur mes articles = id_album dans ma table ALBUM ou

$ref

dans mon formulaire.

Mais je peux avoir plusieurs album dans le panier d'ou ma boucle des input, mais comment je peux donc faire pour tester la bonne correspondance des id et du prix avec ceux de ma base de donnée?

j'ai du me mélanger les pinceaux.

merci encore

Comment tu modifies ton codes de prix directement dans le formulaire ?

barbas
Auteur

avec firebug, je modifie le prix et j'envoie et ça passe comme dans le tuto de paiement Paypal réalisé par grafikart.

Je ne peux pas réécrire tout ton code. Mais essaie de le refaire, mets des commentaires.
Le but étant de créer un mécanisme qui permet de chercher les prix au moment de l'affichage de celui-ci et et au moment de payer.

Une règle d'or que t'a bien fait de vérifié ici : Ne jamais faire confiance au donnée que le client envoie.

Je pense que c'est la seule façon de ne pas te prendre la tête pour résoudre ce problème. Enfin ce que j'aurais fait.

Ou sinon reprend le prix et compare avec celui qui t'a renvoyé ? Compare grâce à la référence produit que tu m'as dite.

barbas
Auteur

ok, je vais repartir de zéro en comparant à la référence du produit avec son vrai prix.