[RESOLU] Problème de redirection sur google chrome

Petit nouveau ! | 5 Messages

03 avr. 2015, 15:33

Bonjour,

je me permets de poster mon problème ici car je ne sais plus quoi faire.

Je précise d'emblée que je ne suis pas dév, je fais des études en système et réseau, et n'ai donc que des connaissances basiques en ce qui concerne la programmation. J'ai néanmoins déjà développé en php donc je comprendrai vos explications (enfin en théorie).

Depuis 3semaines je dois déboguer un site d'assistance informatique. Ce site permet à un client de mon entreprise d'acheter des tickets lui octroyant une assistance de la part de l'un de nos techniciens.

Juste après la validation du paiement s'affiche une page indiquant que l'utilisateur va être redirigé vers une page résumant son achat, avec la possibilité de forcer cette redirection en cliquant sur un lien.
Après la redirection, que l'on clique sur le lien ou que l'on attende la redirection automatique, les numéros des tickets voulus par l'utilisateur lui sont envoyés par courriel.

Le problème est que, lorsque l'on achète en utilisant google chrome, si on clique sur le lien pour forcer la redirection, les tickets sont générés en double, et deux courriels sont envoyés à l'utilisateur ...

En regardant le contenu du fichier access.log, j'ai remarqué que la page était appelée 2x lorsque l'on clique sur le lien pour forcer la redirection, et une seule fois sinon, j'en déduis que le problème est là, mais n'ai aucune idée de la façon dont je pourrais le résoudre ...

Le module de paiement du crédit agricole est utilisé par le site.

Il est installé sur un serveur WAMP.

Voici les fichiers en rapport avec le paiement :

paiement.php :
<?php 
	// LANCEMENT DU SYSTEME DE SESSION
	session_start();
 
 //Envoi du mail contenant les informations tapées avant le paiement
$destinataire = '[email protected]';
$headers2  = 'MIME-Version: 1.0' . "\r\n";
$headers2 .= 'From:monentreprise <[email protected]>' . "\r\n" .
			'Reply-To:[email protected]' . "\r\n" .
			'Content-type: text/html; charset= utf8\n'.
			'X-Mailer:PHP/'.phpversion();
$sujet = 'Contact monentreprise';
		$noinfo='non renseigné';
		$memail = $_POST["email"];
		$mtitre = $_POST["titre"];
		$mprenom = $_POST["prenom"];
		$mnom = $_POST["nom"];
		$mtelephone = $_POST["telephone"];
		if (isset($_POST['societe'])) { $msociete = $_POST['societe'];} else { $msociete = $noinfo; }
		if (isset($_POST['rue-1'])) { $mrue1 = $_POST['rue-1'];} else { $mrue1 = $noinfo; }
		if (isset($_POST['rue-2'])) { $mrue2 = $_POST['rue-2'];} else { $mrue2 = $noinfo; }
		if (isset($_POST['rue-3'])) { $mrue3 = $_POST['rue-3'];} else { $mrue3 = $noinfo; }
		if (isset($_POST['code-postal'])) { $mcodepostal = $_POST['code-postal'];} else { $mcodepostal = $noinfo; }
		if (isset($_POST['ville'])) { $mville = $_POST['ville'];} else { $mville = $noinfo; }
		if (isset($_POST['pays'])) { $mpays = $_POST['pays'];} else { $mpays = $noinfo; }
		if (isset($_POST['siret'])) { $msiret = $_POST['siret'];} else { $msiret = $noinfo; }
		if (isset($_POST['tva'])) { $mtva = $_POST['tva'];} else { $mtva = $noinfo; }
		$madresse=$mrue1." ".$mrue2." ".$mrue3;
 
$msg ="Voici les informations que le client a saisies dans le formulaire de commande de tickets, indépendamment de la finalisation du paiement :<br/><br/>- Champs obligatoires - <br/>Titre : ".$mtitre."<br/>Prénom : ".$mprenom."<br/>Nom : ".$mnom."<br/>Adresse mail : ".$memail."<br/>Numéro de téléphone : ".$mtelephone."<br/>";
 
if (!empty($msociete)) {
$msg .="<br/>- Concernant la facture - <br/>Société : ".$msociete."<br/>Adresse : ".$madresse."<br/>Code postal :  ".$mcodepostal."<br/>Ville : ".$mville."<br/>Pays : ".$mpays."<br/>SIRET : ".$msiret."<br/>Numéro de TVA intracommunautaire : ".$mtva."<br/>";
}
else{}
 
//a quoi sert ce if ? Il est execute tout le temps pour rien apparemment ...
 if(mail($destinataire,$sujet,$msg,$headers2)){}else{}
 
// Vérifie si un une varaible existe dans _POST et si elle n'est pas vide
 
function checkPostIndex( $index_name ) {
	$state = false;
	if( is_string($index_name) ) {
		if( isset($_POST[$index_name]) ) {
			$state = !empty($_POST[$index_name]);
		}
	} else if ( is_array($index_name)) {
		$loop_state = true;
		foreach ($index_name as $value) {
			if( !checkPostIndex($value) ) {
				$loop_state = false;
			}
		}
		$state = $loop_state;
	}
	return $state;
}
/**
 * Fonction permettant de tester les paramètres requis envoyés pas la page d'achat
 */
function checkPaymentParameters() {
	$nombre_tickets = intval($_POST["nombre-tickets"]);
	$email = $_POST["email"];
	$email_confirmation = $_POST["email-confirmation"];
	$state = true; 
	if( $nombre_tickets < 0 ) {
		$state = false;
		$error = 1;
	} else if ( !filter_var($email ,FILTER_VALIDATE_EMAIL) ) {
		$state = false;
		$error = 2;
	} else if ( strtolower(trim($email)) != strtolower(trim($email_confirmation)) ) {
		$state = false;
		$error = 3;
	}
	if( $state == false ) {
		header("location: /index.php?erreur=".$error );
		exit(0);
	}
	return $state;	
}
/**
 * Fonction permettant de tester les paramètres optionnels envoyés pas la page d'achat
 */
function checkOptionalParameters()  {
	$parameters = array (
		getPost("societe"),
		getPost("rue-1"),
		getPost("code-postal"),
		getPost("ville"),
		getPost("pays")
	);
	/** 
	 * Paramètres pas forcément requis pour le moment :
	 *	getPost("rue-2"),
	 *	getPost("rue-3"),
	 *  getPost("siret"),
	 *  getPost("tva"),
	 */
 
	foreach ($parameters as $key => $value) {
		if( empty($value) ) return false;
	}
	return true;
}	
function getPost($index, $default_value = false) {
	if( isset($_POST[$index]) ) {
		if( !empty( $_POST[$index] ) ) {
			return $_POST[$index];
		}
	}
	return $default_value;
}
 
	// parametres que la page PHP doit récupérer obligatoirement poru fonctionenr correctement
	$parametres_post = array( 
		"titre", 
		"prenom", 
		"nom", 
		"telephone", 
		"email", 
		"email-confirmation", 
		"nombre-tickets" 
	);
	// Vérification des paramètres 
	if ( checkPostIndex( $parametres_post ) ) {
 
		// Vérification supplémentaires : 
		$xml=simplexml_load_file("configuration.xml");
		$prix_ticket = (string)$xml->ticket->prix;
		// on utilise pas la variable accessible depuis $_POST (elle pourra être utilisée, mais par défaut il est préférable de récupérer cette info depuis le serveur web)
		$nombre_tickets = (string)$xml->ticket->quantite;
		$tva = (int)$xml->ticket->tva;
 
		// récupération des paramètres envoyés par la page d'achat
		$email = $_POST["email"];
		$email_confirmation = $_POST["email-confirmation"];
 
		$titre = $_POST["titre"];
		$prenom = $_POST["prenom"];
		$nom = $_POST["nom"];
		$telephone = $_POST["telephone"];
 
		// Vérifications supplémentaires (champs mail valide? nombre de ticket valide? )
		if( checkPaymentParameters() ) {
 
			$recevoirFacture = getPost("recevoir-facture");
			if( $recevoirFacture != null ) {
				if( !checkOptionalParameters() ) {
					header("location: /index.php?erreur=0");
					die(0);
				}
				// Informations à enregistrer en session si tout est valide :
				$_SESSION["societe"] = getPost("societe");
				$_SESSION["rue-1"] = getPost("rue-1");
				$_SESSION["rue-2"] = getPost("rue-2");
				$_SESSION["rue-3"] = getPost("rue-3");
				$_SESSION["code-postal"] = getPost("code-postal");
				$_SESSION["ville"] = getPost("ville");
				$_SESSION["pays"] = getPost("pays");
				$_SESSION["siret"] = getPost("siret");
				$_SESSION["num-tva"] = getPost("tva");
			}
 
			// Indique si la case à cocher pour obtenir une facture par courrier est cochée
			$_SESSION["recevoir-facture"] = ( getPost("recevoir-facture") != null );
 
			// Les paramètres sont correctes, enregistrement de tout en session pour réutilisation et lancement du module e-transaction
			// Client :
			$_SESSION["titre"] = $titre;
			$_SESSION["prenom"] = $prenom;
			$_SESSION["nom"] = $nom;
			$_SESSION["telephone"] = $telephone;
			$_SESSION['email'] = $email;
			// Prix et quantité
			$_SESSION['prix-ticket'] = $prix_ticket;
			$_SESSION['nombre-tickets'] = $nombre_tickets;
			$_SESSION['tva'] = $tva;
 
			// Les variables pour le paiement sont correctes :
			// Mode d'appel
			$PBX_MODE       = '4';    //pour lancement paiement par exécution
			//$PBX_MODE        = '1';    //pour lancement paiement par URL
			//identification
			$PBX_SITE       = '1177593';
			$PBX_RANG       = '01';
			$PBX_IDENTIFIANT= '229341201';
			//gestion de la page de connection : paramétrage "invisible"
			$PBX_WAIT       = '0';
			$PBX_TXT        = "" ; //"<div style=\"margin: auto; height: 300px;border: 1px solid #646464; border-radius: 5px;\"><center><p><b>Redirection vers la page de paiement sécurisé en cours,<b><p><p>Veuillez patienter quelques instants ...</p></center></div>";
			$PBX_BOUTPI     = "nul";
			$PBX_BKGD       = "#f5f5f5";
 
			// PARTIE DYNAMIQUE
			//informations paiement (appel)
			// ATTENTION : PAIEMENT EN CENTIMES !!!
			// On garde seulement deux chiffres après la virgule dans le montant (les autres sont coupés) -> TVA prise en compte!
			$PBX_TOTAL      = (( $prix_ticket * $tva / 100 ) + $prix_ticket ) * $nombre_tickets * 100;
 
			// 978 => devise en €UROS
			$PBX_DEVISE     = '978';
			// Référence de commande
			// Référence type : NUMSQL du client + '-' + id unique
			$PBX_CMD        = "OA-".uniqid();
 
			// Email du porteur
			$PBX_PORTEUR    = $email;
 
			// RAPPEL DES LIENS VERS LES DIFFERENTES REPONSES POSSIBLES D'E-TRANSACTION
			//informations nécessaires aux traitements (réponse)
			/** 
			 * /////////////////////////////////////////////////////////////////////////////////////////////////
			 * //   INFORMATION CONCERNANT  PBX_RETOUR (ce que le programme e-transaction renvoie)            //
			 * /////////////////////////////////////////////////////////////////////////////////////////////////
			 * 
			 * - "M" => le Montant de la transaction (précisé dans PBX_TOTAL). 
			 * - "R" => votre Référence commande (précisée dans PBX_CMD) : espace URL encodé, 
			 * - "T" => un identifiant de Transaction (numéro d’appel séquentiel e-transactions), 
			 * - "A" => le numéro d’Autorisation (numéro remis par le centre d’autorisation) : URL encodé, 
			 * - "B" => le numéro d’aBonnement (numéro remis par e-transactions), 
			 * - "P" => le type de Paiement retenu (CARTE, …), 
			 * - "C" => le type de Carte retenu (CB, VISA, EUROCARD_MASTERCARD, AMEX, …), 
			 * - "S" => le numéro de la tranSaction (identifiant unique de la transaction), 
			 * - "Y" => le code paYs de la banque émettrice de la carte : norme ISO 3166 (code alphabétique), 
			 * - "E" => le code Erreur de la transaction ([voir page 22]), 
			 * - "D" => Date de fin de validité de la carte du porteur (Format AAMM), 
			 * - "" => Gestion des abonnements avec le traitement Gestion Automatisée des encaissements ([voir page 24) : URL encodé, 
			 * - "I" =>  Le code pays de l’adresse IP de l’internaute : norme ISO 3166 (code alphabétique) : URL encodé 
			 * - "" => Signature sur les variables de l’URL ([voir page Erreur ! Signet non défini.]) : URL encodé, 
			 * - "N" => 6 premiers chiffres (« bin6 ») du numéro de carte de l’acheteur : URL encodé, 
			 * - "H" => Empreinte de la carte, 
			 * - "G" => Garanti du paiement (O ou N). Programme 3-D Secure, 
			 * - "O" => EnrOlement du porteur/acheteur au programme 3-D Secure. Y:Porteur enrôlé, N:Porteur non enrôlé, U:Information non connue, 
			 * - "F" => Etat de l’authentiFication du porteur vis-à-vis du programme 3-D Secure. Y:Porteur authentifié, A:Authenatification du porteur forcée par la banque de l’acheteur, U:L’authentification du porteur n’a pas pu s’effectuer, N:Porteur non authentifié, 
			 * - "J" => : 2 derniers chiffres du numéro de carte du porteur, 
			 * - "W" => Date de traitement de la transaction sur la plateforme e-transactions (Format JJMMAAAA), 
			 * - "Z" => Index lors de l’utilisation des paiements mixtes (cartes cadeaux associées à un complément par carte CB/Visa/MasterCard/Amex), 
			 * - "Q" => Heure de traitement de la transaction (Format 24h / HH:MM:SS)
			 * 
			 * Exemple d'utilisation : $PBX_RETOUR = "montant:M;maref:R;auto:A;trans:T;abonnement:B ;paiement:P;carte:C;idtrans:S;pays:Y;erreur:E;validite:D;PPPS:U;IP:I;BIN6:N;digest:H;sign:K"
			 * Les adresses de redirections recevront avec cet exemple les variables suivants dans $_GET[] : montant, maref, auto, ...
			 */
 
			// ATTENTION !!! NE PAS DEPASSER 250 caractères !!!						    
			$PBX_RETOUR   = "montant:M;maref:R;auto:A;trans:T;paiement:P;carte:C;idtrans:S;erreur:E;validite:D;BIN6:N;digest:H;date:W;heure:Q;sign:K";
 
			// ADRESSES DE REDIRECTIONS 
			// AFIN DE 'SECURISER' LA VERIFICATION DU PAIEMENT EN PHP, le staut correspond à une chaine de caractères aléatoires,
			// LES DIFFERENTS status possible seront stockés en session 
			// Explication : E-TRANSACTION renvoie en GET toutes les donénes conernant le paiement, il est donc possible qu'un pirate copie l'url, 
			// 				 et la modifie pour par exemple acheter gratuitement en modifiant un paiement refusé en accepté 
 
			/** 
			 * Détail de la solution de sécurité :
			 * - 4 chaines de caractères aléatoires sont générées et associées à un status (valide, refuse, annule, erreur)
			 * - Les valeurs des status sont stockées en session pour qu'on puisse identifier les status depuis la page de verification de paiement 
			 * - les urls de redirection après paiement sont générées avec le status correspondant
			 *
			 * Quand la page de vérification reçoit une réponse d'E-Transaction, elle vérifie si les status sont présents en session 
			 * (sinon, aucun paiement n'est à l'origine de cette url, c'est soit un rechargement de page, soit une attaque d'un pirate!) 
			 * 
			 * Afin d'améliorer encore la sécurité, les données sont supprimmées de la session une fois récupérées 
			 * (pour éviter qu'un pirate puisse analyser l'URL correctement, et qu'il ne trouve pas la chaine de caractères correspondant au status valide par exemple)
			 */
 
			// SUCCES
			$PBX_EFFECTUE = "http://www.monsite.fr/paiement_fini.php?status=succes";
			// REFUS
			$PBX_REFUSE   = "http://www.monsite.fr/paiement_fini.php?status=refus";
			// ANNULATION
			$PBX_ANNULE   = "http://www.monsite.fr/paiement_fini.php?status=annule";
			// ERREUR DE PARAMETRAGE
			$PBX_ERREUR   = "http://www.monsite.fr/paiement_fini.php?status=erreur";
 
			//construction de la chaîne de paramètres à envoyer lors de l'exécution du module de paiement
			$PBX = 'PBX_MODE="'.$PBX_MODE.'" ';
			$PBX .= 'PBX_SITE="'.$PBX_SITE.'" ';
			$PBX .= 'PBX_RANG="'.$PBX_RANG.'" ';
			$PBX .= 'PBX_IDENTIFIANT="'.$PBX_IDENTIFIANT.'" ';
			$PBX .= 'PBX_WAIT="'.$PBX_WAIT.'" ';
			$PBX .= 'PBX_TXT="'.$PBX_TXT.'" ';
			$PBX .= 'PBX_BOUTPI="'.$PBX_BOUTPI.'" ';
			$PBX .= 'PBX_BKGD="'.$PBX_BKGD.'" ';
			$PBX .= 'PBX_TOTAL="'.$PBX_TOTAL.'" ';
			$PBX .= 'PBX_DEVISE="'.$PBX_DEVISE.'" ';
			$PBX .= 'PBX_CMD="'.$PBX_CMD.'" ';
			$PBX .= 'PBX_PORTEUR="'.$PBX_PORTEUR.'" ';
			$PBX .= 'PBX_EFFECTUE="'.$PBX_EFFECTUE.'" ';
			$PBX .= 'PBX_REFUSE="'.$PBX_REFUSE.'" ';
			$PBX .= 'PBX_ANNULE="'.$PBX_ANNULE.'" ';
			$PBX .= 'PBX_ERREUR="'.$PBX_ERREUR.'" ';
			$PBX .= 'PBX_RETOUR="'.$PBX_RETOUR.'" ';
			$return = null;
 
			// echo shell_exec("\"modulev2.exe\" ".$PBX);
			echo shell_exec("\"./bin/modulev2.exe\" ".$PBX);
			die(1);
		} else {
			// Rediriger vers la page de paiement, avec les erreurs asociées
			header("location: /index.php?erreur=".$erreur_number.";");
			exit();
		}
	} else {
		header("location: /index.php?erreur=0");
		exit(0);
	}
Le contenu de paiement_fini.php :
<?php
	// Lancement du système de session
	session_start();
 
	/**
	 *  FONCTIONS UTTILES AUX TRAITEMENTS
	 */
	function checkPostIndex( $index_name ) {
		$state = false;
		if( is_string($index_name) ) {
			if( isset($_POST[$index_name]) ) {
				$state = !empty($_POST[$index_name]);
			}
		} else if ( is_array($index_name)) {
			$loop_state = true;
			foreach ($index_name as $value) {
				if( !checkPostIndex($value) ) {
					$loop_state = false;
				}
			}
			$state = $loop_state;
		}
		return $state;
	}
	function getSession($index, $default_value = null) {
		if( isset($_SESSION[$index]) ) {
			if( !empty($_SESSION[$index]) ) {
				return $_SESSION[$index];
			}
		}
		return $default_value;
	}
 
 
	/**
	 * 
	 * Traitement
	 * 
	 */
 
	$data = $_GET;
 
	// Récupération des donénes en session
	// Civilité :
	$titre = getSession("titre", "");
	$prenom = getSession("prenom", "");
	$nom = getSession("nom", "");
	$telephone = getSession("telephone", "");
 
	// Récupération de l'email
	$adresseMail = getSession("email"); 
	$prixTicket = getSession("prix-ticket");
	$nombreTickets = getSession("nombre-tickets"); 
	$tva = getSession("tva"); 
 
	// Valeur par défaut si cette variable n'existe pas en session => false
	$recevoirFacture = getSession("recevoir-facture", false);
	// Test à supprimer !
	//$recevoirFacture = true;
 
	// Variables utiles pour le template 
	$etat_mail = false;
	$etat = 'erreur';
	$tickets = array();
 
	// Vérification des données d'E-Transaction
	$PBX_RETOUR   = "montant=M&maref=R&auto=A&trans=T&paiement=P&carte=C&idtrans=S&erreur=E&validite=D&BIN6=N&digest=H&date=W&heure=Q&sign=K";
 
	// 15 éléments en tout
	$array_to_find = array('=M', '=R', '=A', '=T', '=P', '=C', '=S', '=E', '=D', '=N', '=H', '=W', '=Q', '=K');
	$array_to_replace = array(
		'='.(isset($data['montant'])? $data['montant']:''),
		'='.(isset($data['maref'])? $data['maref']:''),
		'='.(isset($data['auto'])? $data['auto']:''),
		'='.(isset($data['trans'])? $data['trans']:''),
		'='.(isset($data['paiement'])? $data['paiement']:''),
		'='.(isset($data['carte'])? $data['carte']:''),
		'='.(isset($data['idtrans'])? $data['idtrans']:''),
		'='.(isset($data['erreur'])? $data['erreur']:''),
		'='.(isset($data['validite'])? $data['validite']:''),
		'='.(isset($data['BIN6'])? $data['BIN6']:''),
		'='.(isset($data['digest'])? $data['digest']:''),
		'='.(isset($data['date'])? $data['date']:''),
		'='.(isset($data['heure'])? $data['heure']:''),
		'='.(isset($_GET['sign'])? $_GET['sign']:'')
	);
 
	$PBX_RETOUR = explode('&sign=', str_replace($array_to_find, $array_to_replace, $PBX_RETOUR) );
	// 		1.	Récupérer le contenu de la donnée du type “K” (ici, c'est 'sign')
	// 		2.	“URL décodée” cette signature,
	// 		3.	Décodée en base 64 le résultat de l’étape précédente,
	$sealed = base64_decode(
        str_replace(" ", "+", urldecode(
            // Valeur de 'sign'
            $PBX_RETOUR[1]
        ))
    );
 
	// 		4.	Décrypter avec la clé publique d'e-transactions le résultat de l’étape précédente,
	$newsource = "";
    $fp =       fopen ("./bin/pubkey.pem","r");
    $pub_key =  fread($fp,8192);
    fclose($fp);
    openssl_get_publickey($pub_key);
    openssl_public_decrypt($sealed, $newsource, $pub_key);
	// 		5.	Calculer une empreinte SHA-1 avec les autres données de la variable "PBX_RETOUR",
	$empreinte = sha1($PBX_RETOUR[0],true);
	// 		6.	L’empreinte calculée dans l’étape précédente doit être égale au résultat de l’étape 4
	// A cause d'un bug, je vérifie seulement que la valeur de l'empreinte se trouve bien dans la la valeur de la newsource (qui contient queleques caractères en plus)
	// Si >= 0, ALORS LES CLEFS CORRESPONDENT -> c'est bon !
 
	if( strpos($newsource, $empreinte) >= 0 && $adresseMail != null && $prixTicket != null && $nombreTickets != null ) {
		if( in_array( $data['status'], array('erreur', 'succes', 'annule', 'refus') ) ) {
			$etat = $data['status'];
			// Si le paiement est effectué avec succès, faire appel au webservice adéquat.
			if( $etat == 'succes' ) {
				// CHARGEMENT DES CONFIGURATIONS
				$xml=simplexml_load_file("configuration.xml");
				// URL DU WEBSERVICE
				$webservice_url = (string)$xml->webservice->url;
				// Email recevant les erreurs apparues lors de la procédure de paiement
				$erreurMail = (string)$xml->mail->erreur;
				// Email recevant en copie les récapitulatifs d'achat
				$copieMail = (string)$xml->mail->copie;
				// Email expédiant les messages
				$expediteurMail = (string)$xml->mail->expediteur;
				// Email recevant la demande de facture par courrier
				$factureMail = (string)$xml->mail->facture;
				//
				$replyMail = (string)$xml->mail->repondre;
				// Fermeture du fichier xml
				$xml = null;
 
				// Cette variable permet de savoir si le webservice n'est pas accessible ou si le nombre de tickets 
				$erreur_interne = false;
				$detail_erreur = "";
 
				$client = null;
				try {
					// génération des tickets,
				    $client = new SoapClient($webservice_url);
				} catch (Exception $e) {
					// oups! le webservice est indisponible à l'adresse spécifiée
					$erreur_interne = true;
				}
 
				// Si le webservice est bien disponible :
				if( $erreur_interne == false ) {
				    // Variables par défaut
					$etat_achat = false;  
 
				    $tickets = array();
				    for ($i=0; $i < $nombreTickets; $i++) { 
				    	$reponse = $client->GenererTicket(array("nombre_tickets" => 1));
					    foreach ( $reponse->GenererTicketResult->ArrayOfString as $key => $ticket) {
					    	/** 
					    	 * Pour récupérer les valeurs d'un ticket : $ticket[ chiffre ]
					    	 * 0 => ID du ticket
					    	 * 1 => Num ticket
					    	 * 2 => Date génération du ticket 
					    	 * 3 => Date péremption du ticket
					    	 * 4 => Utilisé ?
					    	 * 5 => Date utilisation
					    	 * 6 => notes
					    	 * 7 => int_appel
					    	 * 8 => int_client
					    	 */
					    	$tickets[$i] = $ticket;
					    	// Formatage de la date
					    	$date_peremption = DateTime::createFromFormat('d/m/Y H:i:s', $tickets[$i][3]);
					    	$tickets[$i][3] = $date_peremption->format('d/m/Y');
					    }
				    }
 
				    // Vérification, y-a-t-il  le bon compte de tickets ?
				    if( count($tickets) > 0 ) {
				    	if( count($tickets) != $nombreTickets ) {
					    	$erreur_interne = true;
					    	$detail_erreur = "<p>Nombre de tickets générés invalide( ".$nombreTickets." achetés, ".count($tickets)." générés). Voici la liste de tickets générés :</p>";
					    	$detail_erreur .= "<ul>";
					    	foreach ($tickets as $key => $t) {
						    	$contenu_mail .= "<li> Ticket n°".$t[1]." (id du ticket: ".$t[0].", généré le ".$t[2]." )</li>";
						    }
					    	$detail_erreur .= "</ul>";
					    }
 
				    	// SI OUI :
				    	// Envoi d'un mail récapitulant les tickets achetés
					    $contenu_mail = "<ul style=\"list-style-type: none;\">";
					    foreach ($tickets as $key => $t) {
					    	$contenu_mail .= "<li> Ticket n°".$t[1]."</li>";
					    }
					    $contenu_mail .= "</ul><p>Limite de validité :  Vos tickets sont à utiliser impérativement avant le ".$tickets[0][3]."</p>";
						// Info :
						// L'adresse mail est récupérée au début de ce fichier .php
						$headers  = 'MIME-Version: 1.0' . "\n"; // Version MIME
					    $headers .= 'Content-type: text/html; charset="UTF-8"'."\n"; // l'en-tete Content-type pour le format HTML
					    $headers .= 'From: "monentreprise"<'.$expediteurMail.'>'."\n"; // Expediteur
					    $headers .= 'Reply-To: '.$replyMail."\n"; // reply to 
					    $headers .= 'To: '.$adresseMail."\n"; // Destinataire
					    $headers .= 'Bcc: '.$copieMail."\n"; // Destinataire en copie 
 
					    // Contenu du message
						$message ="<body style='font-size:10.0pt;font-family:\"Arial\",\"sans-serif\"'>
								    <p>Bonjour,</p>
								    <p>Merci d’avoir choisi monentreprise pour la résolution de vos problèmes informatiques !</p>
								    <p>
								   		Nous vous confirmons votre achat de tickets d'assistance sur notre site <a href=\"http://www.monsite.fr\">www.monsite.fr</a>.
								   		Vous trouverez ci-dessous le récapitulatif de votre achat pour un montant de ".($data['montant'] / 100)." € TTC :
								   	</p>".$contenu_mail."
									<p>
										Pour utiliser ces tickets, il vous suffit de nous contacter au 01.01.01.01.01 ou par mail :
										<a href=\"mailto: [email protected]\">[email protected]</a>.
									</p>
								   	<p>
								   		Horaires d’ouverture de votre hotline dédiée :<br />
								   		Du Lundi au Vendredi, de 8h00 à 12h30 et de 14h00 à 18h00 (17h00 le Vendredi).
								   	</p>
								   	<p>Si vous avez demandé une facture, celle-ci sera envoyée sous 72h par email.</p>
								   	<p>monentreprise<br />
								    test<br />
								    <a href='http://www.monsite.fr/' alt='site monentreprise'>www.monsite.fr</a></p>
								    <img src='http://www.monsite.fr/images/logo-monentreprise.png' alt='logo'/>
								    </body>";
						$etat_mail = mail($adresseMail, "monentreprise - confirmation d'achat", $message, $headers);
				    } 
 
				} else {
					$detail_erreur = "<p>WebService indisponible. veuillez vérifier que l'url ".$webservice_url." est bien disponible.<br/>";
					$detail_erreur .= "Attention! Les tickets du client n'ont pas été générés (".$nombreTickets." achetés)</p>";
				}
 
				// Si une erreur est survenue lors de la génération des tickets, envoi d'un mail à l'adresse [email protected]
				if( $erreur_interne == true ) {
					$etat = 'erreur_interne';
					// L'adresse mail est récupérée au début de ce fichier .php
					$headers  = 'MIME-Version: 1.0' . "\n"; // Version MIME
				    $headers .= 'Content-type: text/html; charset="UTF-8"'."\n"; // l'en-tete Content-type pour le format HTML
				    $headers .= 'From: "monentreprise"<'.$expediteurMail.'>'."\n"; // Expediteur
				    $headers .= 'Reply-To: '.$replyMail."\n"; // reply to 
				    $headers .= 'To: '.$erreurMail."\n"; // Destinataire
				    //Reply-To:
				    // Contenu du message
					$message ="<body style='font-size:10.0pt;font-family:\"Arial\",\"sans-serif\"'>
							    <p>Bonjour,</p>
							    <p>
							   		Une erreur est survenue lors de la génération des tickets d'assitances d'un client (adresse mail: ".$adresseMail.").
							   		Détail de l'erreur :
							   	</p>
								".$detail_erreur."
								<br />
							   	<p>
							   		Le site
							   	</p>
							    </body>";
					$etat_mail = mail($erreur_mail, "Confirmation d'inscription", $message, $headers);
			    }
 
			    if( $recevoirFacture === true ) {
					// Récupération des informations sur le client depuis la session :
					$societe = getSession("societe");
					$rue1 =  getSession("rue-1");
					$rue2 =  getSession("rue-2");
					$rue3 =  getSession("rue-3");
 
					$codePostal = getSession("code-postal");
					$ville = getSession("ville");
					$pays = getSession("pays");
 
					$siret = getSession("siret", "non renseigné");
					$numTva = getSession("num-tva", "non renseigné");							
 
					// Info :
					// L'adresse mail est récupérée au début de ce fichier .php
					$headers  = 'MIME-Version: 1.0' . "\n"; // Version MIME
				    $headers .= 'Content-type: text/html; charset="UTF-8"'."\n"; // l'en-tete Content-type pour le format HTML
				    $headers .= 'From: "monentreprise"<'.$expediteurMail.'>'."\n"; // Expediteur
				    $headers .= 'Reply-To: '.$replyMail."\n"; // reply to 
				    $headers .= 'To: '.$factureMail."\n"; // Destinataire
 
				    // Contenu du message
					$message ="<body style='font-size:10.0pt;font-family:\"Arial\",\"sans-serif\"'>
							    <p>Bonjour, </p> ".
							    "<p>
							    	".$titre." ".ucfirst($prenom)." ".ucfirst($nom)." souhaite recevoir une facture concernant son achat de tickets d'assistance.
							    </p>
							    <p>
							   		<b><u>Information sur le client :</u></b>
							   	</p>
							   	<dl>
							   		<dt>Téléphone</dt>
							   		<dd>".$telephone."</dd>
							   		<dt>Société</dt>
							   		<dd>".$societe."</dd>
									<dd>Num. SIRET : ".$siret."<br />Num. TVA : ".$numTva."</dd>
									<dt>Adresse</dt>
									<dd>".$rue1."<br/>".$rue2."<br/>".$rue3."</dd>
									<dd>".$codePostal." ".ucfirst($ville).", ".ucfirst($pays)."</dd>
									<dt> Adresse mail </dt>
									<dd>".$adresseMail."</dd>
							   	</dl>
							   	<br />
							   	<p>
							   		<b><u>Informations sur la commande :</u></b>
							   	</p>
							   	<dl>
							   		<dt>Montant</dt>
							   		<dd> ".($data['montant'] / 100)." € TTC</dd>
							   		<dt>Numéro de transaction Crédit Agricole: </dt>
							   		<dd>".$data['idtrans']."</dd>
							   		<dt>Identifiant de la commande </dt>
							   		<dd>".$data['maref']."</dd>
							   	</dl>
							   	<p>monentreprise<br />
							    adresse<br />
							    <a href='http://www.monsite.fr/' alt='site monentreprise'>www.monsite.fr</a></p>
							    <img src='http://www.monsite.fr/images/logo-monentreprise.png' alt='logo'/>
							    </body>";
					$etat_mail = mail($factureMail, "monentreprise - Demande de facture", $message, $headers);
				}
 
				// NETTOYAGE DE LA SESSION
			    session_unset();
			    session_destroy();
			}
		} else {
			$etat = 'erreur';
		}
	} else {
		header("location: /index.php?erreur=4");
		exit();
	}
	// Titre à envoyer dans le template
	$titre = "Confirmation de paiement";
	// Chargement du haut de page
	require("./template/header.php");
 
	// appel du template
	require("./template/page_paiement_fini.php");
 
	// Chargement du haut de page
	require("./template/footer.php");
?>

Voici également le contenu du fichier page_paiement_fini.php :
<div class="intromentions">
 
<?php
	/**
	 * Variables utilisables :
	 * - 	$tickets : un talbeau de tickets 
	 * 		chaque ticket contient :
	  		 * 0 => ID du ticket
	    	 * 1 => Num ticket
	    	 * 2 => Date génération du ticket 
	    	 * 3 => Date péremption du ticket
	    	 * 4 => Utilisé ?
	    	 * 5 => Date utilisation
	    	 * 6 => notes
	    	 * 7 => int_appel
	    	 * 8 => int_client
	 * -	$etat : peut contenir : 'erreur', 'succes', 'annule', 'refus' 
	 		* Si $etat == 'succes', alors la variable $etat_mail peut contenir : true, false ( Mail envoyé, ou non envoyé) 
	 * 
	 * Plus de détail sur la syntaxe PHP : http://www.php.net/manual/fr/language.basic-syntax.phpmode.php
	 * 
	 */
?>
<?php if($etat == 'erreur'): ?>
	<h1>Oups!</h1>
	<p>
		Une erreur est survenue lors du paiement. Veuillez recommencer le paiement une nouvelle fois.
	</p>
	<center><a href="../index.php">retour à la page d'achat</a><center>
<?php elseif($etat == 'erreur_interne'): ?>
	<h1>Oups!</h1>
	<p>
		Votre paiement a bien été pris en compte, mais une erreur est survenue lors de la création de votre commande. Nos collaborateurs ont été prévenus, et travaille le plus vite possible sur la résolution de votre problème.
		Nous vous contacterons par mail dans les plus brefs délais afin de vous tenir informé sur la résolution de cet incident.
		<br />
		Veuillez nous excuser pour ce désagrément.
	</p>
	<center><a href="../index.php">retour à la page d'achat</a><center>
<?php elseif($etat == 'annule'): ?>
	<h1>Achat annulé</h1>
	<p>
		Vous avez annulé le paiement.
	</p>
	<center><a href="../index.php">retour à la page d'achat</a><center>
<?php elseif($etat == 'refus'): ?>
	<h1>Paiement refusé</h1>
	<p>
		Votre achat a été refusé par le service de paiement. Si c'est une erreur, veuillez recommencer le paiement une nouvelle fois.
	</p>
	<center><a href="../index.php">retour à la page d'achat</a><center>
<?php elseif($etat == 'succes'): ?>
	<h1>Paiement effectué !</h1>
	<p>
		Nous confirmons votre achat de <?php echo(count($tickets)); ?> tickets.
		<br />
		Voici les numéros de tickets qui sont mis à votre disposition :
		<?php if( $etat_mail == false ): ?>(Une erreur est survenue lors de l'envoie des tickets par mail, veuillez bien prendre note des informations ci-dessous !)<?php endif; ?>
	</p>
	<div class="ticketsleft">
		<ul>
		<?php foreach($tickets as $t): ?>
		<?php
			/** 
	    	 * Pour récupérer les valeurs d'un ticket : $t[ chiffre ]
	    	 * 0 => ID du ticket
	    	 * 1 => Num ticket
	    	 * 2 => Date génération du ticket 
	    	 * 3 => Date péremption du ticket
	    	 * 4 => Utilisé ?
	    	 * 5 => Date utilisation
	    	 * 6 => notes
	    	 * 7 => int_appel
	    	 * 8 => int_client
	    	 */
		?>
			<li> Ticket n°<?php echo($t[1]);  ?></li>
		<?php endforeach; ?>
		<?php // Si dessous , on utilise [0][3] car tous les tickets ont la même date de péremption, donc afficher celle du premier ticket est valable ?>
		</ul> <br />
	</div>
		<div class="information" style="font-weight:bold;">Attention ! Vos tickets sont à utiliser impérativement avant le : <?php echo( $tickets[0][3]); ?> </div>
 
	<p>Pour utiliser ces tickets, il vous suffit de nous contacter au 01 01 01 01 01 ou par mail : <a href="mailto:[email protected]">[email protected]</a>. <br />
	Nous vous rappelons nos horaires d'ouverture : <br />
	Du Lundi au Vendredi, de 8h00 à 12h30 et de 14h à 18h (17h le Vendredi). <br />
	Si vous avez demandé une facture, celle-ci sera envoyée sous 72h par email.</p>
	<br/>
 
<?php endif; ?>
Voici également le contenu du fichier header.php :
<!DOCTYPE html> 
<!--[if lte IE 9]><html class="ie ie9" lang="fr"><![endif]-->
 
 
 
<html lang="fr">
	<head>
		<title>monentreprise - <?php echo $titre; ?></title>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="description" content="Vous avez besoin d\'une assistance informatique pour un problème ou une panne informatique ? Accès internet, virus, installation de logiciel ou encore souci d\'imprimante, nos techniciens vous dépannent à distance, par téléphone ou télémaintenance." />
		<link rel="icon" href="images/favicon_monentreprise.ico" type="image/x-icon">
		<link rel="stylesheet" type="text/css" href="CSS/style.css" media="screen"/>
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		  <link rel="stylesheet" type="text/css" media="all" href="css/bootstrap-glyphicons.css">
		<link rel="stylesheet" type="text/css" href="CSS/mobile.css" media="screen and (max-width: 320px)">
		<link rel="stylesheet" type="text/css" href="CSS/mobile.css" media="screen and (max-width: 480px)">
		<link rel="stylesheet" type="text/css" href="CSS/mobile.css" media="screen and (max-width: 600px) and (orientation: landscape)">
		<link rel="stylesheet" type="text/css" href="CSS/mobile.css" media="screen and (max-width: 800px)">
 
 
		<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
 
  ga('create', 'UA-53033808-1', 'auto');
  ga('send', 'pageview');
 
</script>
		  <script type="text/javascript" src="js/modernizr-1.5.min.js"></script>
		  <script language="javascript" type="text/javascript" src="js/jquery.js"></script>
		    <script type="text/javascript" src="js/jquery.easing-sooper.js"></script>
  <script type="text/javascript" src="js/jquery.sooperfish.js"></script>
  <script type="text/javascript">
 
    $(document).ready(function() {
      $('ul.sf-menu').sooperfish();
	  					document.getElementById("container").style.height = document.getElementById("foot").offsetTop+120+"px";
 
    });
 
function disablelink() {
if (window.matchMedia("(min-width: 800px)").matches) {
document.location.href="quelques-exemples.php" 
 
  /* La largeur minimum de l'affichage est 600 px inclus */
} else {
return false;
}
}
 
 
 
  </script>
 
 
	</head>
 
	<body>
		<div id="container">
				<a id="hautpage"></a>
			<div id="head">
				<a href="index.php">
					<img class="logo" src="images/logo-monentreprise.png" alt="Dépannage informatique"/>
				</a>
			</div>
			<nav>
					<ul class="sf-menu" id="nav">
 
						<li><a style="line-height:10pt;margin-top:8px;" href="depannage-informatique.php">Comment  ça marche ?</a>  </li>
 
						<li><a style="line-height:10pt;" href="pourquoi-nous-choisir.php">Pourquoi <br /> monentreprise ?</a>  </li>
 
						<li style="cursor:pointer;" ><a style="line-height:10pt; margin-top:8px;" onclick="disablelink()" >Quelques Exemples</a>
							<ul>
								<li><a href="quelques-exemples.php?categorie=internet" >Internet</a></li>
								<li><a href="quelques-exemples.php?categorie=logiciels">Logiciels</a></li>
								<li><a href="quelques-exemples.php?categorie=protection">Protection</a></li>
								<li><a href="quelques-exemples.php?categorie=peripheriques">Périphériques</a></li>
								<li><a href="quelques-exemples.php?categorie=outils">Outils Système</a></li>
								<li><a href="quelques-exemples.php?categorie=office">Microsoft Office</a></li>
							</ul>
						</li>
 
						<li><a style="line-height:10pt; margin-top:8px;"  href="avis-clients.php">Témoignages clients</a></li>
						<li ><a style="line-height:10pt;   margin-top:8px;"  href="contact.php">Nous contacter</a>  </li>
			  </ul>
			  </nav>
Pardon d'avoir mis le contenu des fichiers "en vrac", mais ne sachant pas où peut se situer mon problème, je préfère tout montrer plutôt que de cacher la partie qui pourrait contenir l'erreur.

J'espère que vous pourrez m'aider, merci d'avance pour le temps que vous me consacrerez !

P.S :
- je n'ai pas écrit le code, je ne fais qu'essayer de le déboguer. (pardonnez donc à mon prédécesseur ses fautes d'orthographe, je les corrigerai dès que j'aurai réglé le problème de tickets ^^)
- les adresses électroniques et du site ne sont pas celles d'origine, mais elles sont bonnes, donc le problème ne vient pas de là (du moins pas de l'orthographe de celles-ci).

Petit nouveau ! | 5 Messages

07 avr. 2015, 10:49

Bonjour,

Je pense que le problème se situe au niveau du module de paiement du Crédit Agricole, en effet c'est ce dernier qui appelle le fichier paiement_fini.php. Cependant, comme il s'agit de code propriétaire je n'y ai pas accès.

Quelqu'un connaitrait un moyen détourné de corriger ce problème ?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

07 avr. 2015, 11:41

Bonjour,

Le Crédit Agricole te fournit des références de payement qui te permettent d'identifier de façon unique un paiement.
Mon conseil serait que tu conserves en base de données (ou dans un fichier texte à défaut), la trace des références de paiement traitées associées aux références des tickets que tu auras généré.

Et à chaque fois que tu reçois une confirmation de paiement, ton script doit vérifier que cette référence de paiement n'a pas déjà été traitée.
Quand tout le reste a échoué, lisez le mode d'emploi...

Petit nouveau ! | 5 Messages

08 avr. 2015, 12:01

Bonjour,

Merci pour ta réponse !

J'ai suivi ton conseil et ai créé les trois fonctions suivantes dans le fichier paiement_fini.php (au début du fichier) :
//cree un acces a une bdd
function open_bdd($bdd_host, $bdd_name, $bdd_login, $bdd_passwd) {
	try
	{
		$bdd= new PDO('mysql:host='.$bdd_host.';dbname='.$bdd_name.';charset=utf8', $bdd_login, $bdd_passwd);
	}
	catch (Exception $e)
	{
		die('Erreur : ' . $e->getMessage());
	}
	return $bdd;
}
	
//cette fonction permet de verifier que la transaction na pas encore ete effectuee, et renvoie TRUE si elle existe
function test_unique($idtransaction, $bdd) {
	$param_req = array(
		'idtransaction' => $idtransaction,
	);

	$liste_id = $bdd->prepare('SELECT idtrans FROM transactions WHERE idtrans = :idtransaction');
	$liste_id->execute($param_req);
	
	if (empty($liste_id)) {
		$trans_unique = true;
	} else {
		$trans_unique = false;
	}
	
	$liste_id->closeCursor();
		
	return $trans_unique;
}

//Cette fonction ajoute ID de la transaction à la base de données si celui-ci nexiste pas deja
function store_idtrans ($id_transaction, $date, $ref, $bdd) {
	
	$param_req = array(
		'idtransaction' => $id_transaction,
		'date' 		 => $date,
		'ref' 			 => $ref,
	);
		
	$id_add = $bdd->prepare('INSERT INTO transaction(idtrans, date, ref) VALUES(:idtransaction, :date, :ref)');
	$id_add->execute($param_req);
	//TODO - ajouter a la bdd ID passe en parametre
}
J'entrepose les informations de connexion dans le fichier XML déjà existant.

J'appelle les fonctions susmentionnées juste après avoir récupéré les informations de connexion, de cette manière :
// CHARGEMENT DES CONFIGURATIONS
$xml=simplexml_load_file("configuration.xml");

//CHARGEMENT DES INFORMATIONS DE LA BASE DES TRANSACTIONS
//hote de la bdd
$bdd_host = (string)$xml->bdd->hote;
//nom de la base
$bdd_name = (string)$xml->bdd->nom;
//login de la base
$bdd_login = (string)$xml->bdd->login;
//mdp de la base
$bdd_passwd = (string)$xml->bdd->mdp;
// Fermeture du fichier xml
$xml = null;

//appel des fonctions de test
//recuperation des informations de transaction
//ces donnees sont recuperees dorigine dans le code
$ref = $data['maref'];
$date = $data['date'];
$idtrans = $data['idtrans'];
				
//test de lunicite de la transaction
$bdd = open_bdd($bdd_host, $bdd_name, $bdd_login, $bdd_passwd);
$trans_unique = test_unique($idtrans, $bdd);

//si ID unique on lajoute dans la base
if($trans_unique) {
	store_idtrans($idtrans, $date, $ref, $bdd);
}
Est-ce correct ?

Petit nouveau ! | 5 Messages

09 avr. 2015, 09:48

Bonjour,

J'ai enfin pu tester ma modification :

Il me dit qu'il a généré 0 ticket et m'indique une erreur au moment d'afficher la date d'achat.

L'erreur est la suivante :

( ! ) SCREAM: Error suppression ignored for
( ! ) Notice: Undefined offset: 0 in C:\Webpages\www.monsite.fr\template\page_paiement_fini.php on line 81
Call Stack
# Time Memory Function Location
1 0.0025 818088 {main}( ) ..\paiement_fini.php:0
2 0.0191 896096 require( 'C:\Webpages\www.monsite.fr\template\page_paiement_fini.php' ) ..\paiement_fini.php:412

Si je comprends bien un indice de tableau est incorrect ?

Il s'agit du tableau contenant les informations au sujet des tickets achetés, comme il n'en a généré aucun l'indice est à 0 et fait planter ? Qu'est-ce qui a pu provoquer la mise à 0 du nombre de tickets ? (En sachant qu'il en génère 3 normalement)

Petit nouveau ! | 5 Messages

10 avr. 2015, 15:47

J'ai enfin corrigé mon problème ! \o/

Deux choses faisaient planter le script :

certains noms de variables étaient incorrects et les noms des champs dans la requête INSERT INTO n'étaient pas entre apostrophes.

Merci @rthur pour ton aide, problème résolu !