*/ class PaymentController extends BasePaymentModuleController { protected static $resultCodes = [ '00' => ' Transaction acceptée', '02' => ' Demande d’autorisation par téléphone à la banque à cause d’un dépassement du plafond d’autorisation sur la carte, si vous êtes autorisé à forcer les transactions', '03' => ' Contrat commerçant invalide', '05' => ' Autorisation refusée', '11' => ' Utilisé dans le cas d\'un contrôle différé. Le PAN est en opposition', '12' => ' Transaction invalide, vérifier les paramètres transférés dans la requête', '14' => ' Coordonnées du moyen de paiement invalides (ex: n° de carte ou cryptogramme visuel de la carte) ou vérification AVS échouée', '17' => ' Annulation de l’acheteur', '30' => ' Erreur de format', '34' => ' Suspicion de fraude (seal erroné)', '54' => ' Date de validité du moyen de paiement dépassée', '75' => ' Nombre de tentatives de saisie des coordonnées du moyen de paiement sous Sips Paypage dépassé', '90' => ' Service temporairement indisponible', '94' => ' Transaction dupliquée : la référence de transaction est déjà utilisé', '97' => ' Délai expiré, transaction refusée', '99' => ' Problème temporaire du serveur de paiement.', ]; /** * Traitement de la réponse manuelle. La réponse manuelle est l'URL vers laquelle le client est * redirigé une fois le paiement effectué (ou annulé). * * La validation de commande est efectuée dans le traitement de la réponse automatique (le callback de la banque). */ public function processManualResponse(): void { $this->getLog()->addInfo( $this->getTranslator()->trans( "Mercanet manual response processing.", [], Mercanet::MODULE_DOMAIN ) ); $paymentResponse = new MercanetApi(Mercanet::getConfigValue('secretKey')); $paymentResponse->setResponse($_POST); $this->getLog()->addInfo( $this->getTranslator()->trans( 'Response parameters : %resp', ['%resp' => print_r($paymentResponse->getDataString(), true)], Mercanet::MODULE_DOMAIN ) ); $order = OrderQuery::create() ->filterById($paymentResponse->getParam('ORDERID')) ->filterByPaymentModuleId(Mercanet::getModuleId()) ->findOne(); if ($paymentResponse->isValid() && $paymentResponse->isSuccessful()) { $this->redirectToSuccessPage($order->getId()); } $resultCode = $paymentResponse->getParam('RESPONSECODE'); // Annulation de la commande if ((int) $resultCode === 17) { $this->processUserCancel($order->getId()); } $message = self::$resultCodes[$resultCode] ?? 'Raison inconnue'; $this->redirectToFailurePage($order->getId(), $message); } /** * @return \Symfony\Component\HttpFoundation\Response * @throws \Exception */ public function processMercanetRequest() { $this->getLog()->addInfo( $this->getTranslator()->trans( "Mercanet automatic response processing.", [], Mercanet::MODULE_DOMAIN ) ); $paymentResponse = new MercanetApi(Mercanet::getConfigValue('secretKey')); $paymentResponse->setResponse($_POST); $this->getLog()->addInfo( $this->getTranslator()->trans( 'Response parameters : %resp', ['%resp' => print_r($paymentResponse->getDataString(), true)], Mercanet::MODULE_DOMAIN ) ); if ($paymentResponse->isValid()) { if (null !== $order = OrderQuery::create() ->filterById($paymentResponse->getParam('ORDERID')) ->filterByPaymentModuleId(Mercanet::getModuleId()) ->findOne()) { if ($paymentResponse->isSuccessful()) { $this->confirmPayment($order->getId()); $this->getLog()->addInfo( $this->getTranslator()->trans( 'Order ID %id is confirmed, transaction référence "%trans"', [ '%id' => $order->getId(), '%trans' => $paymentResponse->getParam('TRANSACTIONREFERENCE') ], Mercanet::MODULE_DOMAIN ) ); } else { $this->getLog()->addError( $this->getTranslator()->trans( 'Cannot validate order. Response code is %resp', ['%resp' => $paymentResponse->getParam('RESPONSECODE')], Mercanet::MODULE_DOMAIN ) ); // Cancel order. $event = (new OrderEvent($order)) ->setStatus(OrderStatusQuery::getCancelledStatus()->getId()); $this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event); $this->getLog()->addError( $this->getTranslator()->trans('Order was canceled.', [], Mercanet::MODULE_DOMAIN) ); } } else { $this->getLog()->addError( $this->getTranslator()->trans( 'Cannot find an order for transaction référence "%trans"', ['%trans' => $paymentResponse->getParam('TRANSACTIONREFERENCE')], Mercanet::MODULE_DOMAIN ) ); } } else { $this->getTranslator()->trans( 'Got invalid response from Mercanet', [ ], Mercanet::MODULE_DOMAIN ); } $this->getLog()->addInfo( $this->getTranslator()->trans( "Automatic response processing terminated.", [], Mercanet::MODULE_DOMAIN ) ); return new Response('OK'); } /* * @param $orderId int the order ID * @return \Thelia\Core\HttpFoundation\Response */ public function processUserCancel($orderId): void { $this->getLog()->addInfo( $this->getTranslator()->trans( 'User canceled payment of order %id', ['%id' => $orderId], Mercanet::MODULE_DOMAIN ) ); try { if (null !== $order = OrderQuery::create()->findPk($orderId)) { $currentCustomerId = $this->getSecurityContext()->getCustomerUser()->getId(); $orderCustomerId = $order->getCustomerId(); if ($orderCustomerId !== $currentCustomerId) { throw new TheliaProcessException( sprintf( "User ID %d is trying to cancel order ID %d ordered by user ID %d", $currentCustomerId, $orderId, $orderCustomerId ) ); } $event = new OrderEvent($order); $event->setStatus(OrderStatusQuery::getCancelledStatus()->getId()); $this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event); } } catch (\Exception $ex) { $this->getLog()->addError("Error occurred while canceling order ID $orderId: " . $ex->getMessage()); } $this->redirectToFailurePage( $orderId, $this->getTranslator()->trans('you cancel the payment', [], Mercanet::MODULE_DOMAIN) ); } /** * Return a module identifier used to calculate the name of the log file, * and in the log messages. * * @return string the module code */ protected function getModuleCode() { return 'Mercanet'; } }