From 74ee34634e73f549539ecdfa8fe47bf6cdbb4fe9 Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 26 Jun 2026 14:26:06 -0400 Subject: [PATCH] Refactor PayPal refund process by introducing a modular approach for refund context and rendering. This update consolidates refund logic into dedicated functions in `inc_fx_paypal.php`, enhancing maintainability and clarity. The `commandes.php` file is updated to utilize these new functions, improving the overall structure and readability of the refund handling code. --- superadm/commandes.php | 207 +++---------------------------- superadm/php/inc_fx_paypal.php | 220 +++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 190 deletions(-) diff --git a/superadm/commandes.php b/superadm/commandes.php index 6f245e6..a554aa4 100644 --- a/superadm/commandes.php +++ b/superadm/commandes.php @@ -399,10 +399,7 @@ include('inc_header.php'); require_once $_SERVER["DOCUMENT_ROOT"] . "/superadm/php/inc_fx_paypal.php"; // Jeton anti double clic / re-soumission -if (empty($_SESSION['refund_token'])) { - $_SESSION['refund_token'] = bin2hex(random_bytes(16)); -} -$refundToken = $_SESSION['refund_token']; +$refundToken = fxRefundEnsureToken(); // Récupération des infos commande (présentes dans ton contexte) $CAPTURE_ID = $recCommandes["TransactionID"] ?? null; @@ -414,194 +411,24 @@ if (!isset($CAPTURE_ID) || !is_string($CAPTURE_ID) || $CAPTURE_ID === '') { return; } -// Charger ta classe PayPal -require_once '../paypal_advanced/PaypalCheckout.class.php'; -$paypal = new PayPalCheckout(); // adapte si nécessaire - -// Préparation -$errors = []; -$successMsg = null; - -// Devise par défaut si jamais les détails PayPal n’en donnent pas -$currencyUI = 'CAD'; - -// ====== Calculs initiaux côté serveur ====== - -// Solde dispo promoteur (ton helper existant) -$solde_dispo_ms1 = statut_payement($recCommandes["eve_id"]); - -// Récupérer les détails PayPal de la capture -$paypaldetails = $paypal->paypaldetails($CAPTURE_ID); - -// Harmoniser avec tes remboursements locaux si besoin -$paypaldetails = reconcileRefundsWithLocal($paypaldetails); -//print_rsl($paypaldetails); -// Déterminer le max remboursable PayPal -$max_remboursement_paypal = 0.0; -//print_rsl($paypaldetails); - // 1) S'il existe au moins un refund → on prend remaining (même si c’est 0) - if (isset($paypaldetails['refunds']['totals']['remaining'])) { - $max_remboursement_paypal = (float)$paypaldetails['refunds']['totals']['remaining']; - } -// 2) Sinon → fallback : montant total capturé - else { - if (!empty($paypaldetails['details']['amount']['value'])) { - $max_remboursement_paypal = (float)$paypaldetails['details']['amount']['value']; - } elseif (!empty($paypaldetails['delails']['amount']['value'])) { - $max_remboursement_paypal = (float)$paypaldetails['delails']['amount']['value']; - } - } - -// Déterminer la devise d’affichage si fournie par PayPal -if (!empty($paypaldetails['refunds']['totals']['currency'])) { - $currencyUI = (string)$paypaldetails['refunds']['totals']['currency']; -} elseif (!empty($paypaldetails['details']['amount']['currency_code'])) { - $currencyUI = (string)$paypaldetails['details']['amount']['currency_code']; -} elseif (!empty($paypaldetails['delails']['amount']['currency_code'])) { - $currencyUI = (string)$paypaldetails['delails']['amount']['currency_code']; -} - -// Frais MS1 (selon ta structure) -$frais_ms1 = (float)($recCommandes['fra_total'] ?? 0); - -// Max remboursable à l’écran (ta logique actuelle) -$maxUI = $max_remboursement_paypal - $frais_ms1; - -// maxblock = limite stricte d’input côté front, selon ton choix actuel -if ($max_remboursement_paypal < $solde_dispo_ms1) { - $maxblock = $max_remboursement_paypal; -} else { - $maxblock = 0; - $maxUI = 0; -} -// ******************** variable info -//print_rsl($recCommandes); - echosl( "no_commande : ".$recCommandes["no_commande"]); - echosl( "rem_ajoute_par : ".$_SESSION["usa_info"]["com_prenom"]." ".$_SESSION["usa_info"]["com_nom"]); - echosl( "eve_id : ".$recCommandes["eve_id"]) ; - echosl( "Montant remboursable : " . number_format($max_remboursement_paypal, 2) . " " . ($result['refunds']['totals']['currency'] ?? $result['delails']['amount']['currency_code'] ?? '')); - - - - echo("solde dispo ms1 :"); - echosl($solde_dispo_ms1); - echo("frais ms1 :"); - $frais_ms1=$recCommandes['fra_total']; - echosl($frais_ms1); - echo("max Remboursement :"); - - // $maxUI le max Remboursement si on veux pas renbourcer les frais ms1 - // $maxUI=$max_remboursement_paypal-$frais_ms1; - // $maxUI le max Remboursement - $maxUI=$max_remboursement_paypal; - echosl($maxUI); - $maxproposer = max(0, $maxUI - $frais_ms1); -// Helpers UI +// Contexte de remboursement mutualisé (calculs + détails PayPal) +$refundCtx = fxRefundComputeContext($recCommandes); +$paypaldetails = $refundCtx['paypaldetails']; +// Infos debug (Super Admin) +echosl("no_commande : " . $recCommandes["no_commande"]); +echosl("rem_ajoute_par : " . ($_SESSION["usa_info"]["com_prenom"] ?? '') . " " . ($_SESSION["usa_info"]["com_nom"] ?? '')); +echosl("eve_id : " . $recCommandes["eve_id"]); +echosl("Montant remboursable : " . number_format($refundCtx['max_paypal'], 2) . " " . $refundCtx['currency']); +echo("solde dispo ms1 :"); +echosl($refundCtx['solde_dispo']); +echo("frais ms1 :"); +echosl($refundCtx['frais_ms1']); +echo("max Remboursement :"); +echosl($refundCtx['maxUI']); +// Formulaire de remboursement (rendu mutualisé : voir inc_fx_paypal.php) +echo fxRenderRefundForm($recCommandes, $refundToken, $refundCtx, $vDomaine); ?> - - - - - Remboursement PayPal - - - - -
-
Remboursement PayPal (Checkout)
- - - - - 0): ?> -
-
Capture:
-
Max remboursable (affiché):
-
- -
- - - - "> - "> - -
- - -
- -
- - -
- -
- -
-
- -
- Aucun montant remboursable pour cette capture. -
- -
- - - - - diff --git a/superadm/php/inc_fx_paypal.php b/superadm/php/inc_fx_paypal.php index 1fc71cd..890799b 100644 --- a/superadm/php/inc_fx_paypal.php +++ b/superadm/php/inc_fx_paypal.php @@ -785,3 +785,223 @@ $qryInsert = $GLOBALS['db']->fxQuery($sqlInsert); // $stmt->execute([$capture_ } function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } + +/* ================================================================== + * Remboursement PayPal - briques mutualisees (Super Admin + fiche gestion) + * + * IMPORTANT : ces fonctions ne dependent QUE de ce fichier + * (statut_payement, reconcileRefundsWithLocal, money2, h) + de la classe + * PaypalCheckout. Elles n'incluent JAMAIS superadm/php/inc_functions.php + * (le « U »), afin d'eviter tout conflit "Cannot redeclare" avec + * php/inc_fonctions.php (le « O ») charge dans le contexte /compte. + * ================================================================== */ + +/** + * Garantit la presence d'un jeton anti double-clic en session. + * @return string le jeton + */ +function fxRefundEnsureToken(): string +{ + if (session_status() === PHP_SESSION_NONE) { + session_start(); + } + if (empty($_SESSION['refund_token'])) { + $_SESSION['refund_token'] = bin2hex(random_bytes(16)); + } + return $_SESSION['refund_token']; +} + +/** + * Calcule le contexte de remboursement d'une commande (capture PayPal). + * + * @param array $recCommandes Ligne commande (TransactionID, eve_id, no_commande, fra_total...) + * @return array { + * ok:bool, capture_id:string, currency:string, paypaldetails:array, + * max_paypal:float, solde_dispo:float, frais_ms1:float, + * maxUI:float, maxblock:float, maxproposer:float + * } + */ +function fxRefundComputeContext(array $recCommandes): array +{ + $out = [ + 'ok' => false, + 'capture_id' => '', + 'currency' => 'CAD', + 'paypaldetails' => [], + 'max_paypal' => 0.0, + 'solde_dispo' => 0.0, + 'frais_ms1' => 0.0, + 'maxUI' => 0.0, + 'maxblock' => 0.0, + 'maxproposer' => 0.0, + ]; + + $captureId = $recCommandes['TransactionID'] ?? null; + if (!is_string($captureId) || $captureId === '') { + return $out; // pas de capture PayPal exploitable + } + $out['capture_id'] = $captureId; + + require_once $_SERVER['DOCUMENT_ROOT'] . '/paypal_advanced/PaypalCheckout.class.php'; + $paypal = new PayPalCheckout(); + + // Solde disponible promoteur (helper de ce fichier) + $out['solde_dispo'] = (float) statut_payement($recCommandes['eve_id'] ?? 0); + + // Details PayPal de la capture + reconciliation locale + $paypaldetails = $paypal->paypaldetails($captureId); + $paypaldetails = reconcileRefundsWithLocal($paypaldetails); + $out['paypaldetails'] = $paypaldetails; + + // Max remboursable PayPal : remaining si dispo, sinon montant capture (tolere "delails") + $maxPaypal = 0.0; + if (isset($paypaldetails['refunds']['totals']['remaining'])) { + $maxPaypal = (float) $paypaldetails['refunds']['totals']['remaining']; + } elseif (!empty($paypaldetails['details']['amount']['value'])) { + $maxPaypal = (float) $paypaldetails['details']['amount']['value']; + } elseif (!empty($paypaldetails['delails']['amount']['value'])) { + $maxPaypal = (float) $paypaldetails['delails']['amount']['value']; + } + $out['max_paypal'] = $maxPaypal; + + // Devise d'affichage + if (!empty($paypaldetails['refunds']['totals']['currency'])) { + $out['currency'] = (string) $paypaldetails['refunds']['totals']['currency']; + } elseif (!empty($paypaldetails['details']['amount']['currency_code'])) { + $out['currency'] = (string) $paypaldetails['details']['amount']['currency_code']; + } elseif (!empty($paypaldetails['delails']['amount']['currency_code'])) { + $out['currency'] = (string) $paypaldetails['delails']['amount']['currency_code']; + } + + // Frais ms1 + $out['frais_ms1'] = (float) ($recCommandes['fra_total'] ?? 0); + + // Plafonds (fidele a l'ecran Super Admin actuel) : + // - maxUI affiche = max remboursable PayPal + // - maxblock (input max) = max_paypal si max_paypal < solde dispo, sinon 0 + // - valeur proposee = max(0, maxUI - frais ms1) + $out['maxUI'] = $maxPaypal; + $out['maxblock'] = ($maxPaypal < $out['solde_dispo']) ? $maxPaypal : 0.0; + $out['maxproposer'] = max(0.0, $out['maxUI'] - $out['frais_ms1']); + $out['ok'] = true; + + return $out; +} + +/** + * Rend le formulaire de remboursement PayPal (carte + script AJAX). + * Fragment HTML autonome (pas de /), reutilisable partout. + * + * @param array $recCommandes Ligne commande + * @param string $refundToken Jeton anti double-clic + * @param array $ctx Resultat de fxRefundComputeContext() + * @param string $vDomaine Domaine de base (pour l'URL AJAX par defaut) + * @param string|null $ajaxUrl URL de l'endpoint (def: $vDomaine.'/superadm/ajax_refund.php') + * @return string HTML + */ +function fxRenderRefundForm(array $recCommandes, string $refundToken, array $ctx, string $vDomaine, ?string $ajaxUrl = null): string +{ + if ($ajaxUrl === null) { + $ajaxUrl = $vDomaine . '/superadm/ajax_refund.php'; + } + + $captureId = (string) ($ctx['capture_id'] ?? ''); + $currencyUI = (string) ($ctx['currency'] ?? 'CAD'); + $maxUI = (float) ($ctx['maxUI'] ?? 0); + $maxblock = (float) ($ctx['maxblock'] ?? 0); + $maxproposer = (float) ($ctx['maxproposer'] ?? 0); + + ob_start(); + ?> +
+
Remboursement PayPal (Checkout)
+ + + + + 0): ?> +
+
Capture:
+
Max remboursable (affiché):
+
+ +
+ + + + + + +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+ Aucun montant remboursable pour cette capture. +
+ +
+ + +