PageRenderTime 61ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/class.xmodpaybox.inc

https://github.com/jcplat/console-seolan
PHP | 1105 lines | 613 code | 44 blank | 448 comment | 93 complexity | 9fbb9db3458d8bd7dbf21c8ad1717e61 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * \file class.xmodpaybox.inc
  4. * \name XModPaybox
  5. * \author Vladimir Monari
  6. * \version 1.0
  7. * \date 1 Septembre 2013
  8. */
  9. /**
  10. * \brief Classe XModPaybox.
  11. * Classe de gestion des transactions Paybox.
  12. * \version 1.0
  13. */
  14. class XModPaybox extends XModMonetique{
  15. // Options spécifiques au module
  16. public $rang = NULL; ///< Rang du site, fournis par la banque.
  17. public $identifiant = NULL; ///< Identifiant, fournis par la banque.
  18. public $keyFile = NULL; ///< Fichier contenant la clé permettant de verifiée la signature.
  19. public $formMethode = 'POST'; ///< méthode de soumission.
  20. public $formFirstUrl = NULL; ///< url de soumission principale.
  21. public $form2NdUrl = NULL; ///< url de soumission secondaire.
  22. public $formUrlPreProd = NULL; ///< url de soumission de pré-production.
  23. /// Gestion des paramètres de retour (C'est le maximum d'infos que paybox nous retourne).
  24. private $champsRetour = array(
  25. "P_M" => "M", // Montant de la transaction
  26. "P_R" => "R", // Référence commande (Passée par PBX_CMD)
  27. "P_A" => "A", // Numéro d'autorisation
  28. "P_T" => "T", // Identifiant de la transaction
  29. "P_Q" => "Q", // Heure du traitement de la transaction
  30. "P_W" => "W", // Date du traitement de la transaction
  31. "P_B" => "B", // Numéro d'abonnement (fournis par Paybox Service)
  32. "P_P" => "P", // Type de paiement
  33. "P_C" => "C", // Type de carte
  34. "P_S" => "S", // Numéro de transaction
  35. "P_Y" => "Y", // Code pays de la banque éméttrice de la carte
  36. "P_E" => "E", // Code erreure de la transaction
  37. "P_F" => "F", // Etat d'authentification 3D secure
  38. "P_G" => "G", // Garantie de paiement 3D secure
  39. "P_O" => "O", // Enrolement du porteur 3D secure
  40. "P_D" => "D", // Date de fin de validitée
  41. "P_U" => "U", // Référence donner par Paybox Direct Plus
  42. "P_I" => "I", // Code pays de l'IP du client
  43. "P_N" => "N", // 6 premier numéros de carte
  44. "P_J" => "J", // 2 derniers numéros de carte
  45. "P_H" => "H", // Empreinte de la carte
  46. "P_Z" => "Z", // Index lors de l'utilisation de paiement mixtes
  47. "P_K" => "K" // Signature du message
  48. );
  49. private $cardsTypePaybox = array(
  50. /* Tous */
  51. 'AMEX' => 'AMEX',
  52. 'AURORE' => 'AURORE-MULTI',
  53. 'BUYSTER' => 'BUYSTER',
  54. 'CB' => 'CB', ///< On accepte les CB par défaut
  55. 'COFINOGA' => 'COFINOGA',
  56. 'E-CARTEBLEUE' => 'E-CARTEBLEUE',
  57. 'MASTERCARD' => 'MASTERCARD', ///< On accepte les MASTERCARD par défaut
  58. 'JCB' => 'JCB',
  59. 'MAESTRO' => 'MAESTRO',
  60. 'ONEY' => 'ONEY',
  61. 'ONEY_SANDBOX' => 'ONEY_SANDBOX',
  62. 'PAYPAL' => 'PAYPAL',
  63. 'PAYPAL_SB' => 'PAYPAL_SB',
  64. 'PAYSAFECARD' => 'PAYSAFECARD',
  65. 'VISA' => 'VISA', ///< On accepte les VISA par défaut
  66. 'VISA_ELECTRON' => 'VISA_ELECTRON',
  67. 'COF3XCB' => 'COF3XCB',
  68. 'COF3XCB_SB' => 'COF3XCB_SB',
  69. );
  70. // Variables relatives à la signature
  71. public $hashKey = NULL; ///< Signature de l'envoi en banque
  72. public $algoHash = NULL; ///< Algorithme de hachage
  73. /// Tableaux permettant la séléction de l'algorithme dans la console
  74. public $libelleHash = array('Sha512','RIPEMD160','Sha256','Sha384','Sha224','MDC2');
  75. public $codeHash = array('Sha512','RIPEMD160','Sha256','Sha384','Sha224','MDC2');
  76. // Urls de serveurs PPPS (Serveur à serveur)
  77. public $urlPPPStest = NULL; ///< Url d'appel pour le mode TEST.
  78. public $urlPPPS1 = NULL; ///< Url principale d'appel pour le mode PRODUCTION.
  79. public $urlPPPS2 = NULL; ///< Url secondaire d'appel pour le mode PRODUCTION.
  80. public $clePPPS = NULL; ///< Clé de vérification pour le dial de serveur à serveur (PPPS).
  81. public $defaultTemplate = "xmodmonetique/xmodmonetique-paybox-basic-form.html"; ///< Template Paybox par défaut.
  82. /// Constructeur standard d'un module console.
  83. function __construct($ar=null){
  84. parent::__construct($ar);
  85. }
  86. /* Fonctions de paiement version HMAC */
  87. /**
  88. * \brief Méthode de génération des données de paiement.
  89. * Cette fonction permet de générer les données d'un paiement Paybox.
  90. * \param MOrderInfos $order : Objet des données issues de la commande.
  91. * \param MCustomerInfos $customer : Objet des données issues du client.
  92. * \param MShopInfos $shop : Objet comportant les paramètres de la boutique.
  93. * \param MTransaction $transaction : La transaction en cours de paramètrage.
  94. * \return Array :
  95. * - MTransaction $transaction : La transaction contenant tous les paramètres d'appel.
  96. * - Array $payboxForm : Contient le formulaire envoyé en banque.
  97. * - String $template : Le template correspondant correspondant un module de traitement (TZR_SHARE_DIR.$this->defaultTemplate).
  98. * - String $tplentry : L'entrée smarty du template : 'pbf'.
  99. * \note
  100. * - Initialise les paramètres d'appel.
  101. * - Crée le formulaire à envoyer en banque.
  102. * - Recherche le serveur Paybox disponible. \link XModPaybox::serveurDispo() \endlink
  103. * - Retourne la transaction en cours, le formulaire envoyé en banque ainsi que le template et son entrée
  104. * \note
  105. * Définition des types de cartes proposés:
  106. * - $params['PBX_TYPEPAIEMENT'] = 'CARTE';
  107. * - $params['PBX_TYPECARTE'] = 'NOM DE LA CARTE VOULUE';
  108. */
  109. protected function webPaymentHandling(MTransaction $transaction){
  110. // Initialisation des paramètres d'appel
  111. $callParms = $this->payboxForm($transaction);
  112. $transaction->callParms = $callParms;
  113. $transaction->callParms['method'] = $this->formMethode;
  114. $transaction->callParms['url'] = $this->serveurDispo();
  115. // Création du formulaire à envoyer en banque
  116. foreach ($callParms as $key => $value) {
  117. $payboxForm['fields'] .= '<input type="hidden" name="'.$key.'" value="'.$value.'" />';
  118. }
  119. // Méthode POST par défaut pour soumettre le formulaire
  120. $payboxForm['method'] = $transaction->callParms['method'];
  121. // Recherche du serveur disponible
  122. $payboxForm['url'] = $transaction->callParms['url'];
  123. // Retourne la transaction en cours, le formulaire envoyé en banque ainsi que le template et son entrée
  124. return array($transaction, $payboxForm, TZR_SHARE_DIR.$this->defaultTemplate, 'pbf');
  125. }
  126. /**
  127. * \brief Méthode de génération du formulaire de paiement.
  128. * Cette fonction permet de générer le formulaire de paiement Paybox.
  129. * \param MOrderInfos $order : Objet des données issues de la commande.
  130. * \param MCustomerInfos $customer : Objet des données issues du client.
  131. * \param MShopInfos $shop : Objet comportant les paramètres de la boutique.
  132. * \param MTransaction $transaction : La transaction en cours de paramètrage.
  133. * \return Array :
  134. * - Array $payboxForm : Contient le formulaire envoyé en banque.
  135. * \note
  136. * - Mise en forme du montant (centimes). \link XModMonetique::formatOrderAmount($amount); \endlink
  137. * - Paiement en euros par défaut.
  138. * - Si $order->options['noCapture'] est valorisé à true alors on ne fait qu'une demande d'autorisation, sinon capture par défaut.
  139. * - Gestion du paiement multiple si la commande indique plusieurs échéances. \link MOrderInfos::$options \endlink
  140. * - Gestion du mode TEST ou PRODUCTION.
  141. * - Gestion des abonnement.
  142. * - Gestion des délais de capture.
  143. * - Génération de la signature.
  144. */
  145. private function payboxForm($transaction){
  146. $params = array();
  147. // Limite le choix au paiement par carte
  148. $params['PBX_TYPEPAIEMENT'] = 'CARTE';
  149. // Identifiant du site fournis par la banque
  150. $params['PBX_SITE'] = $this->siteId;
  151. // Rang du site fournis par la banque
  152. $params['PBX_RANG'] = $this->rang;
  153. // Identifiant du commerçant
  154. $params['PBX_IDENTIFIANT'] = $this->identifiant;
  155. // Mise en forme du montant (centimes)
  156. $params['PBX_TOTAL'] = $this->formatOrderAmount($transaction->amount);
  157. // Paiement en euros par défaut
  158. $params['PBX_DEVISE'] = $this->defaultCurrencyCode;
  159. // Si $order->options['noCapture'] est valorisé à true alors on ne fait qu'une demande d'autorisation
  160. if( $transaction->captureMode == self::AUTHORIZATION_ONLY){
  161. $params['PBX_AUTOSEULE'] = 'O';
  162. }
  163. // Sinon capture par défaut
  164. else{
  165. $params['PBX_AUTOSEULE'] = 'N';
  166. }
  167. // Gestion du paiement multiple si la commande indique plusieurs échéances
  168. if($transaction->nbDeadLine > 1){
  169. // Préparation des paramètres de multi paiement
  170. /* Calcule du montant des prochain prélévement */
  171. // On divise le montant total en centimes par le nombre d'écheances
  172. $montantDivise = $this->formatOrderAmount($transaction->amount) / $transaction->nbDeadLine;
  173. // On récupère la partie entière qui sera le montant des futurs prélévement
  174. $montantDivise = explode('.', $montantDivise);
  175. // Montant des prochains prélèvements en centimes (0 = montant identique au paiement initial précisé dans PBX_TOTAL).
  176. $montant =sprintf('%010d',$montantDivise[0]);
  177. // Calcule de la fréquence des prélévement ( $order->options['frequencyDuplicate'] est en jours)
  178. $frequenceDivise = $transaction->frequencyDuplicate /30;
  179. // On récupère la partie entière qui sera le nombre de mois entre chaque prélévement
  180. $frequenceDivise = explode('.', $frequenceDivise);
  181. // Fréquence des prélèvements en mois
  182. $frequencyDuplicate = sprintf('%02d',$frequenceDivise[0]);
  183. // Nombre de jours entre la demande d'autorisation et le prélévement effectif
  184. $delais = sprintf('%03d', $transaction->captureDelay);
  185. // Nombre de prélèvements (0 = toujours)
  186. $pbx_nbpaie = sprintf('%02d',$transaction->nbDeadLine);
  187. // Mise en forme des paramètre d'appel de multi-paiement
  188. $params['PBX_CMD'] = $transaction->orderReference.'PBX_2MONT'.$montant.'PBX_NBPAIE'.$pbx_nbpaie.'PBX_FREQ'.$frequencyDuplicate.'PBX_QUAND'.$transaction->captureDay.'PBX_DELAIS'.$delais;
  189. }
  190. // Sinon paiement unique
  191. else{
  192. // Paiement en une fois si seulement la référence est renseigné dans 'PBX_CMD'
  193. $params['PBX_CMD'] = $transaction->orderReference;
  194. }
  195. $params['PBX_PORTEUR'] = $transaction->customerEmail;
  196. $params['PBX_EFFECTUE'] = $this->urlPayed;
  197. $params['PBX_REFUSE'] = $this->urlCancelled;
  198. $params['PBX_ANNULE'] = $this->urlCancelled;
  199. // Gestion du mode TEST ou PRODUCTION
  200. $params['PBX_REPONDRE_A'] = $this->urlAutoResponse;
  201. $params['PBX_TIME'] = date("c");
  202. $params['PBX_HASH'] = $this->algoHash; ///< Algorithme utilisé pour le calcul de la clé
  203. $params['PBX_RUF1'] = $this->formMethode;
  204. // Si la commande nécéssite l'abonnement du client
  205. if (isset($transaction->refAbonneBoutique) && $transaction->enrollement == true) {
  206. $params['PBX_REFABONNE'] = $transaction->refAbonneBoutique;
  207. }
  208. // Si la commande indique que la capture doit être différé
  209. if(isset($transaction->captureDelay)){
  210. $params['DIFF'] = $transaction->captureDelay;///< Nombre de jours pour la capture différée
  211. }else{
  212. $params['DIFF'] = 0;
  213. }
  214. // variables attendus en retour (Toutes celles fournis par paybox)
  215. $retour = '';
  216. foreach ($this->champsRetour as $key => $value) {
  217. $retour .= $key.":".$value.";";
  218. }
  219. $retour = substr($retour,0,strlen($retour)-1); ///< Suppression du dernier ';'
  220. $params['PBX_RETOUR'] = $retour;
  221. // Concatenation des champs du formulaire pour générer la signature
  222. $contenu_signature = "";
  223. foreach ($params as $key=>$value) {
  224. $contenu_signature .= $key."=".$value."&";
  225. }
  226. $contenu_signature = substr($contenu_signature,0,strlen($contenu_signature)-1); ///< Suppression du dernier '&'
  227. /// La clé est en ASCII, On la transforme en binaire
  228. $binKey = pack("H*", $this->hashKey);
  229. /* On calcule l’empreinte (à renseigner dans le paramètre PBX_HMAC) grâce à la fonction hash_hmac et la clé binaire.
  230. * On envoie via la variable PBX_HASH l'algorithme de hachage qui a été utilisé. */
  231. $key = hash_hmac($this->algoHash, $contenu_signature, $binKey);
  232. // La chaîne sera envoyée en majuscules, d'où l'utilisation de strtoupper()
  233. $signature = strtoupper($key);
  234. $params['PBX_HMAC'] = $signature;
  235. return $params;
  236. }
  237. /**
  238. * \brief Méthode de traitement du retour banque paybox.
  239. * Méthode de traitement du retour banque paybox, afin de transamettre des paramètres standards à \link XModMonetique::autoresponse() \endlink
  240. * \return MTransaction $transaction : La transaction concernée par le retour automatique.
  241. * \note
  242. * - Récupère de toutes les valeurs attendu par PayBox, présentes dans $_REQUEST.
  243. * - Mémorise les paramètres de retour de la transaction sous une forme normalisée pour faciliter le traitement en aval et dans Xmodmonetique. \link XModPaybox::formatParams(& $transaction); \endlink
  244. * - Vérifie la signature de la reponse. \link XModPaybox::verificationSignature($retour, $signature); \endlink
  245. * - Affecte le status de la transaction.
  246. * - Récupère l'oid de la transaction grâce à la référence commande. \link XModmonetique::getIdTransactionWithOrderRef($orderReference); \endlink
  247. * - Incrémente le nombre de retour.
  248. */
  249. protected function webPaymentUnFoldReponse() {
  250. // Récupération de toutes les valeurs retournés par PayBox et présentes dans $_REQUEST
  251. $params = array_intersect_key($_REQUEST, $this->champsRetour);
  252. // Mémorisation des paramètres de retour de la transaction sous une forme normalisé pour faciliter le traitement en aval et dans Xmodmonetique
  253. $formatedReturn = $this->formatParams($params);
  254. $transaction = new MTransaction();
  255. foreach($formatedReturn as $k => $v){
  256. $transaction->{$k} = $v;
  257. }
  258. $transaction->responseParms = $params;
  259. // Vérification de la signature
  260. $errcode = $this->verificationSignature($formatedReturn['stringToVerify'], $formatedReturn['signature']);
  261. // Si la signature est invalide
  262. if ($errcode != 1) {
  263. $transaction->status = self::INVALID; ///< Définition de status invalide
  264. $transaction->statusComplement = 'Error à la vérification de la signature, risque de fraude. Chaine à vérifierPréc : '.$formatedReturn['stringToVerify'].' Signature = '.$formatedReturn['signature'].' Code d\'erreur : '.$errcode;
  265. $transaction->autoResponseMode = self::RESPONSE_NONE;
  266. $this->xset->procEdit(array('_options'=>array('local'=>1),
  267. 'oid'=>$transaction->oid,
  268. 'responseParms'=>$transaction->responseParms,
  269. 'status'=>$transaction->status,
  270. 'dateTimeIn'=>date('Y-m-d H:i:s'),
  271. 'statusComplement'=>$transaction->statusComplement,
  272. 'responseStatus'=>'NA'
  273. ));
  274. XLogs::critical(get_class($this)."::webPaymentUnFoldReponse $transaction->statusComplement. ", print_r($transaction, true));
  275. throw new Exception(get_class($this).'::webPaymentUnFoldReponse : '.$transaction->statusComplement);
  276. }
  277. // Vérification de la coherence de la réponse (Le numéro d'autorisation ne peut être XXXXXX si l'identifiant de la boutique n'est pas celui de test)
  278. if (($formatedReturn['N_A'] == 'XXXXXX') && ($this->siteId != '1999888')) {
  279. $transaction->status =self::ERROR;
  280. $transaction->statusComplement = 'PAYBOX RETOUR: Reception d\'une autorisation de test, alors que PBX_SITE n\'est pas celui de test!';
  281. $transactionResponse->autoResponseMode = self::RESPONSE_NONE;
  282. $this->xset->procEdit(array('_options'=>array('local'=>1),
  283. 'oid'=>$transaction->oid,
  284. 'responseParms'=>$transaction->responseParms,
  285. 'status'=>$transaction->status,
  286. 'dateTimeIn'=>date('Y-m-d H:i:s'),
  287. 'statusComplement'=>$transaction->statusComplement,
  288. 'nbReturn'=>$transaction->nbReturn,
  289. 'responseStatus'=>'NA'
  290. ));
  291. XLogs::critical(get_class($this)."::webPaymentUnFoldReponse $transaction->statusComplement. ", print_r($transaction, true));
  292. throw new Exception(get_class($this).'::webPaymentUnFoldReponse : '.$$transaction->statusComplement);
  293. throw new Exception(get_class($this).' ::webPaymentUnFoldReponse : Error message : '.$transaction->statusComplement);
  294. }
  295. return $transaction;
  296. }
  297. /* Appel de serveur à serveur (PPPS) */
  298. /* Fonctions de remboursement d'un abonné */
  299. /**
  300. * \brief Méthode de traitement d'un remboursement Paybox.
  301. * \param MTransaction &$transaction : La nouvelle transaction correspondant au remboursement.
  302. * Doit contenir dans responseParms les paramètre de retour de la transaction à l'origine du remboursement.
  303. * \return MTransaction $transaction : La transaction concernée par le remboursement après l'appel banque.
  304. * \note
  305. * - Mémorise les paramètres nécéssaire au remboursement.
  306. * - Ré-initialise les champs de retour
  307. * - Création du formulaire de remboursement (Mise à jour de l'attribut $transaction->callParms) \link XModPaybox::refundPayboxForm (&$transaction, $paramsRetourOrigin); \endlink
  308. * - Mémorise les paramètres d'appel.
  309. * - Prépare le formulaire curl. \link XModPaybox::XModPaybox::prepareCurlForm ($payboxParams) \endlink
  310. * - Envoi le formulaire curl. \link XModPaybox::sendCurlForm ($payboxForm, &$transaction) \endlink
  311. * - Traite le retour curl. \link XModPaybox::handlingCurlReturn (&$transaction) \endlink
  312. */
  313. protected function refundHandling($transaction){
  314. // Mémorisation des paramètres nécéssaire au remboursement
  315. list($paramsRetourOrigin, $amountOri) = $this->getResponseParmsOrigin($transaction);
  316. if($amountOri < $transaction->amount){
  317. throw new Exception(get_class($this).'::refundHandling : Le montant du remboursement ne peut être supérieur au montant d\'origine : '.$transaction->amount.' > '.$amountOri);
  318. }
  319. // Création du formulaire de remboursement (Mise à jour de l'attribut $transaction->callParms)
  320. $transaction->callParms = $this->refundPayboxForm($paramsRetourOrigin, $transaction);
  321. // Mémorisation des paramètres d'appel
  322. $appel['oid'] = $transaction->oid ;
  323. $appel['callParms'] = $transaction->callParms;
  324. $appel['options'] =array('callParms'=>array('raw'=>true,'toxml'=>true));
  325. $this->xset->procEdit($appel);
  326. // Préparation du formulaire de remboursement
  327. $payboxForm = $this->prepareCurlForm($transaction->callParms);
  328. // Envoi du formulaire et mise à jour du retour dans $transaction
  329. $this->sendCurlForm($payboxForm, $transaction);
  330. XLogs::critical(get_class($this).'::refundHandling', print_r($transaction,true));
  331. // Traitement de la réponse contenu dans $transaction
  332. $this->handlingCurlReturn($transaction);
  333. return $transaction;
  334. }
  335. private function getResponseParmsOrigin($transaction){
  336. $rs = selectQuery('select responseParms, amount from '.$this->xset->getTable().' where `KOID`="'.$transaction->transOri.'"');
  337. $res = null;
  338. if($rs->rowCount()==1){
  339. $res = $rs->fetch();
  340. $params = XSystem::xml2array($res['responseParms']);
  341. return array($params, $res['amount']);
  342. }else{
  343. XLogs::critical(get_class($this).'::getResponseParmsOrigin', 'responseParms, amount de la transaction d\'origine ayant pour KOID '.$transaction->transOri.' non trouvé!');
  344. throw new Exception(get_class($this).'::getResponseParmsOrigin : responseParms, amount de la transaction d\'origine ayant pour KOID '.$transaction->transOri.' non trouvé!');
  345. }
  346. }
  347. /**
  348. * \brief Méthode de génération du formulaire de remboursement qui sera envoyé à la banque.
  349. * \param MTransaction &$transaction : La transaction correspondant au remboursement.
  350. * \param MTransaction $paramsRetourOrigin : Les paramètres de retour de la transaction à l'origine du remboursement.
  351. * \return MTransaction $transaction : La transaction concernée par le remboursement après la mise à jour du formulaire, mémorisé dans $transaction->callParms.
  352. */
  353. private function refundPayboxForm($paramsRetourOrigin, $transaction){
  354. $callParms = array();
  355. // Construction du formulaire
  356. $callParms['DATEQ'] = date('dmY');
  357. $callParms['TYPE'] = 14;
  358. $callParms['NUMQUESTION'] = date('His');
  359. $callParms['MONTANT'] = $this->formatOrderAmount($transaction->amount);
  360. $callParms['REFERENCE'] = $transaction->orderReference;
  361. $callParms['SITE'] = $this->siteId;
  362. $callParms['RANG'] = $this->rang;
  363. $callParms['VERSION'] = '00104';
  364. $callParms['CLE'] = $this->clePPPS;
  365. $callParms['IDENTIFIANT'] = $this->identifiant;
  366. $callParms['DEVISE'] = $this->defaultCurrencyCode;
  367. $callParms['NUMAPPEL'] = $paramsRetourOrigin['P_T'];
  368. $callParms['NUMTRANS'] = $paramsRetourOrigin['P_S'];
  369. return $callParms;
  370. }
  371. /**
  372. * \brief Méthode de ré-émissions des remboursement en attente (serveur non disponible lors de l'appel).
  373. * \param MTransaction &$transaction : La transaction correspondant au remboursement qui sera mise à jour pendant la ré-émission.
  374. * \return MTransaction $transaction : La transaction concernée par le remboursement après sa ré-émission.
  375. * \see
  376. * - Prépare le formulaire curl. \link XModPaybox::XModPaybox::prepareCurlForm ($payboxParams) \endlink
  377. * - Envoi le formulaire curl. \link XModPaybox::sendCurlForm ($payboxForm, &$transaction) \endlink
  378. * - Traite le retour curl. \link XModPaybox::handlingCurlReturn (&$transaction) \endlink
  379. */
  380. protected function refundReplay($transaction){
  381. /// Mise à jour du numéro de question
  382. $transaction->callParms['NUMQUESTION'] = date('Hisd');
  383. /// Préparation du formulaire de remboursement
  384. $payboxForm = $this->prepareCurlForm( $transaction->callParms);
  385. /// Envoi du formulaire et mise à jour du retour dans $transaction
  386. $this->sendCurlForm($payboxForm, $transaction);
  387. /// Traitement de la réponse contenu dans $transaction
  388. $this->handlingCurlReturn($transaction);
  389. return $transaction;
  390. }
  391. /* Fonctions de débit forcé d'un abonné */
  392. /**
  393. * \brief Méthode de traitement d'une duplication Paybox.
  394. * \param MTransaction &$transaction : La nouvelle transaction correspondant à la duplication.
  395. * \return MTransaction $transaction : La transaction concernée par la duplication après l'appel banque.
  396. * \note
  397. * - Création du formulaire envoyé pour le débit (Mise à jour de l'attribut $transaction->callParms).
  398. * - Mémorise les paramètres d'appel.
  399. * - Prépare le formulaire curl. \link XModPaybox::XModPaybox::prepareCurlForm ($payboxParams) \endlink
  400. * - Envoi le formulaire curl. \link XModPaybox::sendCurlForm ($payboxForm, &$transaction) \endlink
  401. * - Traite le retour curl. \link XModPaybox::handlingCurlReturn (&$transaction) \endlink
  402. */
  403. protected function duplicateHandling($transaction ){
  404. $transaction->callParms = $this->duplicatePayboxForm($transaction);
  405. // Mémorisation des paramètres d'appel
  406. $appel['oid'] = $transaction->oid;
  407. $appel['callParms'] = $transaction->callParms ;
  408. $appel['options'] =array('callParms'=>array('raw'=>true,'toxml'=>true));
  409. $this->xset->procEdit($appel);
  410. // Préparation du formulaire de remboursement
  411. $payboxForm = $this->prepareCurlForm($transaction->callParms);
  412. // Envoi du formulaire et mise à jour du retour dans $transaction
  413. $this->sendCurlForm($payboxForm, $transaction);
  414. // Traitement de la réponse contenu dans $transaction
  415. $this->handlingCurlReturn($transaction);
  416. return $transaction;
  417. }
  418. /**
  419. * \brief Méthode de génération du formulaire de remboursement qui sera envoyé à la banque.
  420. * \param MTransaction &$transaction : La transaction correspondant au remboursement.
  421. * \param MTransaction $paramsRetourOrigin : Les paramètres de retour de la transaction à l'origine du remboursement.
  422. * \return MTransaction $transaction : La transaction concernée par le remboursement après la mise à jour du formulaire, mémorisé dans $transaction->callParms.
  423. */
  424. private function duplicatePayboxForm($transaction){
  425. $callParms =array();
  426. $callParms = array();
  427. $callParms ['DATEQ'] = date('dmY');
  428. $callParms['TYPE'] = '00053';
  429. $callParms['NUMQUESTION'] = date('Hisd');
  430. $callParms['MONTANT'] = $transaction->amount;
  431. $callParms['SITE'] = $this->siteId;
  432. $callParms['RANG'] = $this->rang;
  433. $callParms['REFERENCE'] = $transaction->orderReference;
  434. $callParms['REFABONNE'] = $transaction->refAbonneBoutique;
  435. $callParms['VERSION'] = '00104';
  436. $callParms['CLE'] = $this->clePPPS;
  437. $callParms['IDENTIFIANT'] = $this->identifiant;
  438. $callParms['DEVISE'] = $this->defaultCurrencyCode;
  439. $callParms['PORTEUR'] = $transaction->porteur;
  440. $callParms['DATEVAL'] = $transaction->dateVal;
  441. $callParms['CVV'] = $transaction->cvv;
  442. return $callParms;
  443. }
  444. /**
  445. * \brief Méthode de ré-émissions des duplications en attente (serveur non disponible lors de l'appel).
  446. * \param MTransaction &$transaction : La transaction correspondant à la duplication qui sera mise à jour pendant la ré-émission.
  447. * \return MTransaction $transaction : La transaction concernée par la duplication après sa ré-émission.
  448. * \see
  449. * - Prépare le formulaire curl. \link XModPaybox::XModPaybox::prepareCurlForm ($payboxParams) \endlink
  450. * - Envoi le formulaire curl. \link XModPaybox::sendCurlForm ($payboxForm, &$transaction) \endlink
  451. * - Traite le retour curl. \link XModPaybox::handlingCurlReturn (&$transaction) \endlink
  452. */
  453. protected function duplicateReplay($transaction){
  454. // Mise à jour du numéro de question (doit être unique chaque jours)
  455. $transaction->callParms['NUMQUESTION'] = date('Hisd');
  456. // Préparation du formulaire de remboursement
  457. $payboxForm = $this->prepareCurlForm( $transaction->callParms);
  458. // Envoi du formulaire et mise à jour du retour dans $transaction
  459. $this->sendCurlForm($payboxForm, $transaction);
  460. // Traitement de la réponse contenu dans $transaction
  461. $this->handlingCurlReturn($transaction);
  462. return $transaction;
  463. }
  464. /* Fonctions utilitaires */
  465. /**
  466. * \brief Méthode qui retourne une url d'appel disponible pour un paiement web PayBox.
  467. * \exception:
  468. * Si aucun serveur n'est disponible.
  469. * \return String $serveurOK : L'url du serveur disponible.
  470. * \note
  471. * - Gère le mode TEST et PRODUCTION.
  472. * - Test la disponibilité du serveur.
  473. * - Test la disponibilité des services. (Selon la documentation).
  474. */
  475. private function serveurDispo (){
  476. // Si la boutique est en production
  477. if (!$this->testMode(true)) {
  478. // On récupère les urls d'appel
  479. $serveurs = array($formFirstUrl,$form2NdUrl);
  480. $serveurOK = "";
  481. // Pour tous les serveurs de production
  482. foreach ($serveurs as $serveur) {
  483. // On applique la procédure indiquée dans la documentation PayBox
  484. $doc = new DOMDocument();
  485. $doc->loadHTMLFile($serveur.'load.html');
  486. $server_status = "";
  487. $element = $doc->getElementById('server_status');
  488. // On récupère la réponse du serveur
  489. if ($element) {
  490. $server_status = $element->textContent;
  491. }
  492. // Si le serveur est prêt et les services opérationnels
  493. if ($server_status == "OK") {
  494. $serveurOK = $serveur;
  495. break;
  496. }
  497. // Le serveur est disponible mais les services ne le sont pas.
  498. else{
  499. XLogs::critical('::serveurDispo : ', 'Le serveur '.$serveur.' est disponible mais les services ne le sont pas.');
  500. }
  501. }
  502. if (!$serveurOK) {
  503. throw new Exception('Serveur payBox de production indisponible à l\'adresse: '.$serveur ,10);
  504. }
  505. }
  506. // Si la boutique est en TEST
  507. else{
  508. // On applique la procédure indiquée dans la documentation PayBox
  509. $serveur = $this->formUrlPreProd;
  510. $doc = new DOMDocument();
  511. $posDernierSlash = strrpos ($serveur,"/");
  512. $url = substr ($serveur, 0, $posDernierSlash);
  513. $doc->loadHTMLFile($url.'load.html');
  514. // Si le serveur est disponible
  515. if (!empty($doc)) {
  516. $serveurOK = $serveur;
  517. }
  518. // Si le serveur est indisponible
  519. else if (!$serveurOK) {
  520. throw new Exception('Serveur payBox de test indisponible à l\'adresse: '.$this->formUrlPreProd,10);
  521. }
  522. }
  523. // Url du serveur disponible
  524. return $serveurOK;
  525. }
  526. /**
  527. * \brief Fonction de vérication de la signature Paybox.
  528. * \param String $retour : La reponse du serveur Paybox.
  529. * \param String $signature : La signature attachée à la réponse Paybox.
  530. * \return Int $returnValue : 1 si valide, 0 si invalide et -1 si erreur.
  531. * \note
  532. * - Charge la clé de vérification Paybox. \link XModPaybox::loadKey \endlink
  533. * - Log en critical si le chargement de la clé échoue.
  534. * \todo Vérifier s'il ne faut vraiment pas de clé privée.
  535. */
  536. private function verificationSignature($retour, $signature) {
  537. // Chargement de la clé
  538. $key = $this->loadKey($this->keyFile);
  539. // Si le chargement de la clé échoue
  540. if( !$key ){
  541. XLogs::critical(get_class($this), '::verificationSignature chargement de la clé échoué '.$this->keyFile);
  542. return -1;
  543. }
  544. // Retour = 1 si valide, 0 si invalide, -1 si erreur
  545. $returnValue = openssl_verify($retour, $signature, $key );
  546. openssl_free_key($key);
  547. return $returnValue;
  548. }
  549. /**
  550. * \brief Fonction de récupération de la clé de décryptage (chargement de la clé publique par défaut).
  551. * \param String $keyFile : Le chemin du fichier de la clé.
  552. * \param Bool $pub : Valorisé à True (par défaut, charge la clé publique).
  553. * \param String $pass : Le mot de passe permettant d'accéder à la clé privée.
  554. * \return String $key : La clé ou False.
  555. */
  556. private function loadKey( $keyFile, $pub=true, $pass='' ) {
  557. // Vérifie que le fichier contenant la clé existe
  558. $filedata = file_get_contents($keyFile);
  559. if( !$filedata ) {
  560. return false;
  561. }
  562. // Récuperation de la clé publique
  563. if( $pub ){
  564. $key = openssl_pkey_get_public( $filedata );
  565. }
  566. // ou de la clé privée
  567. else {
  568. $key = openssl_pkey_get_private( array( $filedata, $pass ));
  569. }
  570. // renvoi cle ( ou erreur )
  571. return $key;
  572. }
  573. /**
  574. * \brief Mise en forme des paramètres de retour en vue de mémorisation.
  575. * Transforme les paramètres Paybox en paramètres mémorisable par XModMonetique.
  576. * \param MTransaction &$transaction : La transaction en cours.
  577. * \return MTransaction &$transaction: La transaction avec ses paramètres renseignés.
  578. * \note
  579. * - $transaction->retour permettra de vérifier la signature.
  580. * - Pour tous les paramètres reçus:
  581. * - La première structure conditionnelle permet d'extraire les champs retour, mémorisés pour la vérification de la signature.
  582. * - Dans la suite de la boucle, dans la seconde structure conditionnelle, on met en forme les paramètres reçus dans $transaction.
  583. * - Mise en forme du retour pour le calcul de la signature.
  584. */
  585. private function formatParams($params) {
  586. $formatedReturn = array();
  587. $formatedReturn['stringToVerify'] = null;
  588. // Extraction des paramètres reçus
  589. // $transaction->retour permettra de vérifier la signature
  590. // $transaction contiendra les informations retournés à XModMonetique
  591. foreach ($params as $key => $value) {
  592. // La première structure conditionnelle permet d'extraire les champs retour, mémorisés pour la vérification de la signature
  593. if ((!strcmp($key,'P_K') == 0) && (!strcmp($key,'P_C') == 0) ) {
  594. $formatedReturn['stringToVerify'] .= $key."=".urlencode($params[$key])."&";
  595. }
  596. // Récupération de la signature (elle n'est pas intégré au calcul de vérification)
  597. else if (strcmp($key,'P_K') == 0) {
  598. // Contrairement à la documentation PayBox, on ne urldecode pas la signature (La console le fait implicitement)
  599. $formatedReturn['signature'] = base64_decode($params[$key]);
  600. }
  601. else if (strcmp($key,'P_C') == 0) {
  602. // Type de carte utilisée
  603. // Pas d'url encodage des types de cartes pour la vérification de signature
  604. $formatedReturn['stringToVerify'] .= $key."=". $params[$key]."&";
  605. }
  606. /* Dans la suite de la boucle on met en forme les paramètres reçus dans $transaction */
  607. // On mémorise déjà le montant retourné
  608. if (strcmp($key,'P_M') == 0) {
  609. $formatedReturn['amount'] = $params[$key]/100;
  610. }
  611. // Mémorisation du code réponse retourné par la banque
  612. if (strcmp($key,'P_E') == 0) {
  613. $formatedReturn['responseCode'] = substr($params[$key],3);
  614. }
  615. // Récupération de la référence (Le cas paiement multiple est géré)
  616. if (strcmp($key,'P_R') == 0) {
  617. $refInfos = explode("PBX_2MONT", $params[$key]);
  618. // Contient la référence de la commande
  619. $formatedReturn['orderReference'] = $refInfos[0];
  620. if(!empty($refInfos[1])){
  621. // Contient les infos de paiement multiple si c'est la cas
  622. $moreInfos = $refInfos[1];
  623. $formatedReturn['nbDeadLine'] = $this->extractMultiPayement($moreInfos);
  624. }
  625. else{
  626. $formatedReturn['nbDeadLine'] = '1';
  627. }
  628. }
  629. // Numéro d'appel de la transaction (retourné par la banque)
  630. if (strcmp($key,'P_T') == 0){
  631. $formatedReturn['numAppel'] = $params[$key];
  632. }
  633. // Numéro d'autorisation (retourné par la banque)
  634. if (strcmp($key,'P_A') == 0){
  635. $formatedReturn['authId'] = $params[$key];
  636. }
  637. // Numéro de transaction (retourné par la banque)
  638. if (strcmp($key,'P_S') == 0){
  639. $formatedReturn['numTrans'] = $params[$key];
  640. }
  641. // P_N Contient les 4 premiers numéros de carte
  642. if (strcmp($key,'P_N') == 0){
  643. $formatedReturn['numCarte'] =$params[$key];
  644. }
  645. // P_J contient les 2 derniers numéros de carte
  646. if (strcmp($key,'P_J') == 0){
  647. $formatedReturn['numCarte'] = $formatedReturn['numCarte'].'XXXXXXXX'.$params[$key];
  648. $formatedReturn['numCarte'] = chunk_split($formatedReturn['numCarte'], 4, ' ');
  649. }
  650. // P_U Contient les informations nécéssaires à la duplication d'une transaction
  651. if(strcmp($key,'P_U') == 0){
  652. $infos = explode(' ', $params[$key]);
  653. // Mémorisation du porteur (crypté par PayBox)
  654. $formatedReturn['porteur'] = $infos[0];
  655. $anneeVal = substr($infos[1], 0, 2);
  656. $moisVal = substr($infos[1], 2, 4);
  657. // Mémorisation de la date de validitée
  658. $formatedReturn['dateVal'] = $moisVal.$anneeVal;
  659. // Mémorisation du code cvv de la carte
  660. $formatedReturn['cvv'] = $infos[2];
  661. }
  662. // Référence de l'abonné (dans le cadre d'un paiement multiple )
  663. if (strcmp($key,'P_B') == 0){
  664. $formatedReturn['refAbonne'] = $params[$key];
  665. }
  666. // Identifiant de la transaction (retourné par la banque)
  667. if(strcmp($key,'P_T') == 0){
  668. $formatedReturn['transId'] = $params[$key];
  669. }
  670. }
  671. // Mise en forme du retour pour le calcul de la signature
  672. // On enlève le dernier '&'
  673. $formatedReturn['stringToVerify'] = substr($formatedReturn['stringToVerify'] ,0,strlen($formatedReturn['stringToVerify'] )-1);
  674. // On remplace les espaces par des + pour pouvoir vérifier la signature
  675. $formatedReturn['stringToVerify'] = str_replace (' ', '+', $formatedReturn['stringToVerify'] );
  676. // Récupération de l'oid de la transaction grâce à la référence commande
  677. $formatedReturn['oid'] = $this->getIdTransactionWithOrderRef($formatedReturn['orderReference']);
  678. return $formatedReturn;
  679. }
  680. protected function getNbretour($transactionOid){
  681. $rs = selectQuery('select nbReturn from '.$this->xset->getTable().' where `KOID`="'.$transactionOid.'"');
  682. $nbReturn = null;
  683. if($rs->rowCount()==1){
  684. $nbReturn = $rs->fetch(PDO::FETCH_COLUMN);
  685. }
  686. else{
  687. XLogs::critical(get_class($this).' ::getNbretour :', 'Transaction ayant pour KOID : '.$transactionOid.' non trouvé!');
  688. }
  689. return $nbReturn;
  690. }
  691. /**
  692. * \brief Méthode extrait les paramètres de multi-paiement contenue dans la reponse Paybox.
  693. * \param String $moreInfos : Contient les informations à extraire.
  694. * \return $nbDeadLine.
  695. */
  696. private function extractMultiPayement($moreInfos){
  697. $infos = explode('PBX_NBPAIE', $moreInfos);
  698. $nbDeadLine = $infos[1];
  699. $nbDeadLine = substr($nbDeadLine, 0,2);
  700. return $nbDeadLine;
  701. }
  702. /**
  703. * \brief Méthode qui génére un numero de question Paybox unique pour la journée.
  704. * \todo A implémenter.
  705. */
  706. private function genNumRequest(){
  707. }
  708. /**
  709. * \brief Méthode qui test le serveur disponible pour un dial PPPS (De serveur à serveur).
  710. * Transforme les paramètres Paybox en paramètres mémorisable par XModMonetique.
  711. * \param String $url : L'url à tester.
  712. * \param Int $timeout :
  713. * - Le temps maximum d'exécution de la fonction CURL.
  714. * - Le nombre de secondes à attendre durant la tentative de connexion.
  715. * \param Int $maxredirs : Le nombre maximal de redirections HTTP à suivre. Utilisez cette option avec l'option CURLOPT_FOLLOWLOCATION.
  716. * \return Bool $test : True si returnValue = 200 (message : ok -> Requête traitée avec succès), False sinon.
  717. * \note
  718. * - Vérifie que l'url apellée est bien en HTTPS.
  719. * - Initialise la ressources CURL.
  720. * - Execute la requête.
  721. * - Si le serveur n'emet aucune reponse c'est qu'il est indisponible :
  722. * - Fermeture de la session.
  723. * - Retourne False.
  724. * - Sinon vérifie le code HTTP reçu et retourne le résultat.
  725. */
  726. private function urlPPPSdispo($url, $timeout = 10, $maxredirs = 10)
  727. {
  728. $returnValue = FALSE;
  729. // On vérifie que l'url apellée est bien en HTTPS
  730. if (strpos($url, 'https://') === 0) {
  731. // Initialisation de la ressource curl
  732. $ch = curl_init($url);
  733. // Le temps maximum d'exécution de la fonction CURL.
  734. curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  735. // Le nombre de secondes à attendre durant la tentative de connexion.
  736. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  737. // TRUE pour que le corps du transfert ne soit pas inclus dans la value de retour. La méthode de demande est définie à HEAD.
  738. curl_setopt($ch, CURLOPT_NOBODY, TRUE);
  739. // TRUE pour suivre toutes les en-têtes "Location: " que le serveur envoie dans les en-têtes HTTP (notez que cette fonction est récursive et que PHP suivra toutes les en-têtes "Location: " qu'il trouvera à moins que CURLOPT_MAXREDIRS ne soit définie).
  740. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
  741. // Le nombre maximal de redirections HTTP à suivre. Utilisez cette option avec l'option CURLOPT_FOLLOWLOCATION.
  742. curl_setopt($ch, CURLOPT_MAXREDIRS, $maxredirs);
  743. // TRUE pour afficher tous les événements. Écrit la sortie sur STDERR ou dans le fichier spécifié en utilisant CURLOPT_STDERR. False pour le contraire
  744. curl_setopt($ch, CURLOPT_VERBOSE, false);
  745. // TRUE pour sortir les informations de certification SSL vers STDERR pour les transferts sécurisés.
  746. curl_setopt($ch, CURLOPT_CERTINFO, false);
  747. // CURL doit vérifier le certificat. Par défaut depuis curl 7.1
  748. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
  749. // 2 pour vérifier l'existence d'un key commun et vérifier qu'il correspond avec le key d'hôte fourni. En environnement de production, la value de cette option doit être conservée à 2 (value par défaut).
  750. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
  751. // La version de SSL (2 ou 3) à utiliser.
  752. curl_setopt($ch, CURLOPT_SSLVERSION, 3);
  753. // La réponse du serveur sera dans $result
  754. $result = curl_exec ($ch);
  755. // Si le serveur n'emet aucune reponse c'est qu'il est indisponible
  756. if($result === false){
  757. XLogs::critical('Error curl: ', curl_error($ch));
  758. // Fermeture de la session
  759. curl_close ($ch);
  760. return false;
  761. }
  762. // Sinon si le serveur à donné une réponse:
  763. else{
  764. $returnValue = curl_getinfo($ch, CURLINFO_HTTP_CODE); // Retourne le dernier code HTTP reçu
  765. }
  766. // Fermeture de la ressource curl
  767. curl_close($ch);
  768. }else{
  769. XLogs::critical('L\'url PPPS', 'doit être HTTPS');
  770. }
  771. // Retourne true si returnValue = 200 (message : ok -> Requête traitée avec succès), False sinon.
  772. return ($returnValue == 200);
  773. }
  774. /**
  775. * \brief Fonction de préparation du formulaire Curls à envoyer à Paybox.
  776. * Concatène les champs du formulaire Paybox à soumettre.
  777. * \param Array $payboxParams : Le tableau contenant les paramètres à envoyer.
  778. * \return Sring $payboxForm : La chaine contenant la requête à envoyer.
  779. */
  780. private function prepareCurlForm($payboxParams){
  781. $payboxForm ='';
  782. foreach($payboxParams as $key => $value){
  783. $payboxForm .= $key.'='.$value.'&';
  784. }
  785. // On enlève le dernier '&'
  786. $payboxForm = substr($payboxForm,0,strlen($payboxForm)-1);
  787. return $payboxForm;
  788. }
  789. /**
  790. * \brief Fonction d'émission d'une requête à Paybox.
  791. * Envoi une requête CURL à Paybox.
  792. * \param String $payboxForm : La chaine contenant les paramètres de la transaction.
  793. * \param MTransaction &$transaction : La transaction en cours qui va être mise à jour.
  794. * \return MTransaction &$transaction : La transaction passé en paramètre et mise à jour.
  795. * \note
  796. * - Recherche du serveur disponible (Gestion des mode tests et production).
  797. * - Si l'url du serveur est accéssible :
  798. * - Initialisation d'une session CURL.
  799. * - La réponse du serveur sera dans $result.
  800. * - Les erreur (s'il y en a) seront dans $error.
  801. * - S'il y a une erreur de certificat, $testSSL est valorisé à SSL.
  802. * - S'il n'y pas d'erreur et que le résultat n'est pas faux:
  803. * - Traitement du retour.
  804. * - S'il y a une erreur SSL :
  805. * - $transaction->dial = 'erreurSSL';
  806. * - $transaction->responseParms = $error;
  807. * - Sinon :
  808. * - $transaction->responseParms = $result.$error;
  809. * - $transaction->dial = 'ko';
  810. * \note complémentaire:
  811. * - Test pour générer une erreur de certificat:
  812. * - curl_setopt($ch, CURLOPT_CAPATH, 'test');
  813. */
  814. private function sendCurlForm($payboxForm, &$transaction){
  815. // Recherche du serveur disponible
  816. if($this->testMode(true)){
  817. $url = $this->urlPPPStest;
  818. $urlDispo = $this->urlPPPSdispo($url);
  819. }
  820. else{
  821. $url = $this->$urlPPPS1;
  822. $urlDispo = $this->urlPPPSdispo($url);
  823. if (!$urlDispo){
  824. $url = $this->$urlPPPS2;
  825. $urlDispo = $this->urlPPPSdispo($url);
  826. }
  827. }
  828. if($urlDispo){
  829. // Initialisation d'une session CURL
  830. $ch = curl_init($url);
  831. // Définition de la méthode POST
  832. curl_setopt($ch, CURLOPT_POST, 1);
  833. // Insertion des champs du formulaire
  834. curl_setopt($ch, CURLOPT_POSTFIELDS, $payboxForm);
  835. // Définit que le retour doit être mis dans une variable
  836. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  837. // TRUE pour afficher tous les événements. Écrit la sortie sur STDERR ou dans le fichier spécifié en utilisant CURLOPT_STDERR. False pour le contraire
  838. curl_setopt($ch, CURLOPT_VERBOSE, false);
  839. // TRUE pour sortir les informations de certification SSL vers STDERR pour les transferts sécurisés.
  840. curl_setopt($ch, CURLOPT_CERTINFO, false);
  841. // CURL doit vérifier le certificat. Par défaut depuis curl 7.1
  842. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
  843. // 2 pour vérifier l'existence d'un key commun et vérifier qu'il correspond avec le key d'hôte fourni. En environnement de production, la value de cette option doit être conservée à 2 (value par défaut).
  844. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
  845. // La version de SSL (2 ou 3) à utiliser.
  846. curl_setopt($ch, CURLOPT_SSLVERSION, 3);
  847. // La réponse du serveur sera dans $result
  848. $result = curl_exec ($ch);
  849. // Les erreur (s'il y en a) seront dans $error
  850. $error = curl_error($ch);
  851. // S'il y a une erreur de certificat, $testSSL est valorisé à SSL
  852. $testSSL = substr(curl_error($ch),0 , 3);
  853. // S'il n'y pas d'erreur et que le résultat n'est pas faux
  854. if ( ($error == 0) && ($result !== false) ) {
  855. // Traitement du retour
  856. $champs = explode('&', $result);
  857. $transaction->statusComplement = '';
  858. foreach($champs as $kv){
  859. $keyVal = explode('=', $kv);
  860. if(!empty($keyVal[1])){
  861. $transaction->responseParms[$keyVal[0]] = $keyVal[1];
  862. }
  863. }
  864. // Fermeture de la session
  865. curl_close ($ch);
  866. $transaction->dial = 'ok';
  867. }
  868. else if ($testSSL == 'SSL') {
  869. XLogs::critical('Error curl SSL: ', curl_error($ch));
  870. // Fermeture de la session
  871. curl_close ($ch);
  872. $transaction->dial = 'erreurSSL';
  873. $transaction->responseParms = $error;
  874. }
  875. else{
  876. XLogs::critical('Error curl: ', curl_error($ch));
  877. // Fermeture de la session
  878. curl_close ($ch);
  879. $transaction->responseParms = $result.$error;
  880. $transaction->dial = 'ko';
  881. }
  882. }
  883. }
  884. /* Fonctions de traitement du retour Curl */
  885. /**
  886. * \brief Méthode de traitement d'un retour curl Paybox.
  887. * \param MTransaction &$transaction : La transaction à emettre.
  888. * \return MTransaction $transaction : La transaction émise, mise à jour.
  889. * \note
  890. * - Extraction du code réponse (retourné par la banque et déffinisant le status de la transaction).
  891. * - Extraction du commentaire (encodage en utf8, pour une insertion correcte en base).
  892. * - Si le dial de serveur à serveur s'est déroulé correctement et que la transaction en un succés:
  893. * - Mise à jour du status SUCCESS.
  894. * - Mémorisation du commentaire dans la complément de status.
  895. * - Si le dial de serveur à serveur s'est déroulé correctement et que la transaction n'est pas un succés:
  896. * - Mise à jour du status ERROR.
  897. * - Mémorisation du type d'erreur dans la complément de status.
  898. * - Si le dial de serveur à serveur indique une erreur de certificat HTTPS:
  899. * - $transaction->status = ERROR.
  900. * - Il n'y a pas de code bancaire correspondant.
  901. * - Mémorisation du message d'erreur retourné par curl dans le statusComplement.
  902. * - Si le dial n'est pas un succés (Error Curl):
  903. * - $transaction->status = WAITTING (La transaction sera à rejouée).
  904. * - Dans ce cas reponseParms contient $result.$erreur (retourné par curl).
  905. * - Si le dial n'a pas du tout abouti (Serveur indisponible):
  906. * - Mise à jour du status WAITTING (La transaction sera à rejouée).
  907. * - Dans tous les autres cas (La transaction est en erreur).
  908. * - $transaction->status = ERROR.
  909. * - On log les paramètres de cette transaction qui est en erreur.
  910. */
  911. private function handlingCurlReturn(&$transaction){
  912. XLogs::critical(get_class($this).'::handlingCurlReturn', print_r($transaction,true));
  913. // Extraction du code réponse (retourné par la banque et déffinisant le status de la transaction)
  914. $transaction->responseCode = $transaction->responseParms['CODEREPONSE'];
  915. // Extraction du commentaire (encodage en utf8, pour une insertion correcte en base)
  916. $transaction->responseParms['COMMENTAIRE'] = utf8_encode($transaction->responseParms['COMMENTAIRE']);
  917. // Si le dial de serveur à serveur s'est déroulé correctement et que la transaction en un succés
  918. if(( $transaction->responseCode == '00000') && ($transaction->dial == 'ok')) {
  919. // Mise à jour du status SUCCESS
  920. $transaction->status = self::SUCCESS;
  921. // Mémorisation du commentaire dans la complément de status
  922. $transaction->statusComplement = $transaction->responseParms['COMMENTAIRE'];
  923. }
  924. // Si le dial de serveur à serveur s'est déroulé correctement et que la transaction n'est pas un succés
  925. else if ($transaction->dial == 'ok') {
  926. // Mise à jour du status ERROR
  927. $transaction->status = self::ERROR;
  928. XLogs::critical(get_class($this).'::handlingCurlReturn', substr($transaction->responseCode,2,1));
  929. // Mémorisation du type d'erreur dans la complément de status
  930. if(substr($transaction->responseCode,2,1) != '1'){
  931. $transaction->statusComplement = $this->getErrorCodePPS(substr($transaction->responseCode,3));
  932. }
  933. else{
  934. $transaction->statusComplement = $this->getErrorCode(substr($transaction->responseCode,3));
  935. }
  936. }
  937. // Si le dial de serveur à serveur indique une erreur de certificat HTTPS
  938. else if ($transaction->dial == 'erreurSSL') {
  939. /// \todo Choisir les messsages d'erreur (Pour l'instant ERROR)
  940. $transaction->status = self::ERROR;
  941. // Il n'y a pas de code bancaire correspondant
  942. $transaction->responseCode ='';
  943. // Mémorisation du message d'erreur retourné par curl dans le statusComplement
  944. $transaction->statusComplement = $retour;
  945. }
  946. // Si le dial n'est pas un succés (Error Curl)
  947. else if ($transaction->dial == 'ko') {
  948. $transaction->status = self::WAITTING;
  949. // Dans ce cas reponseParms contient $result.$erreur (retourné par curl)
  950. $transaction->statusComplement = $transaction->responseParms;
  951. }
  952. // Si le dial n'a pas du tout abouti (Serveur indisponible)
  953. else if(empty($transaction->dial )){
  954. // Mise à jour du status WAITTING (La transaction sera à rejouée)
  955. $transaction->status = self::WAITTING;
  956. $transaction->statusComplement = 'Serveur PPPS indisponible';
  957. XLogs::critical('Serveur PPPS', 'Indisponible à :'.date('H:i:s d-m-y'));
  958. XLogs::critical('Error curl', $transaction->responseParms);
  959. }
  960. // Dans tous les autres cas (La transaction est en erreur)
  961. else{
  962. $transaction->status = self::ERROR;
  963. $transaction->responseCode ='XXXXX';
  964. $transaction->statusComplement = 'Error inconnue :'.$transaction->responseParms;
  965. // On log les paramètres de cette transaction qui est en erreur
  966. XLogs::critical('::handlingCurlReturn Error inconnue : ', $transaction->responseParms);
  967. XLogs::critical('::handlingCurlReturn', print_r($transaction, true) );
  968. }
  969. }
  970. /**
  971. * \brief Fonction qui retourne le libellé d'une erreur à partir de son code.
  972. * \param Int $errorCode…

Large files files are truncated, but you can click here to view the full file