From 27ae8f61bd28c463c9fb75c68a04206d31c216ff Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Nov 2021 19:04:39 +0100 Subject: [PATCH] FIX Check on Stripe REAL amount currency before validating membership --- htdocs/public/payment/newpayment.php | 16 +++++++++++- htdocs/public/payment/paymentok.php | 37 +++++++++------------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index bb58936d78d..27bf780de62 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -768,9 +768,23 @@ if ($action == 'charge' && !empty($conf->stripe->enabled)) { setEventMessages($paymentintent->status, null, 'errors'); $action = ''; } else { - // TODO We can alse record the payment mode into llx_societe_rib with stripe $paymentintent->payment_method + // TODO We can also record the payment mode into llx_societe_rib with stripe $paymentintent->payment_method // Note that with other old Stripe architecture (using Charge API), the payment mode was not recorded, so it is not mandatory to do it here. //dol_syslog("Create payment_method for ".$paymentintent->payment_method, LOG_DEBUG, 0, '_stripe'); + + // Get here amount and currency used for payment and force value into $amount and $currency so the real amount is saved into session instead + // of the amount and currency retreived from the POST. + if (!empty($paymentintent->currency) && !empty($paymentintent->amount)) { + $currency = strtoupper($paymentintent->currency); + $amount = $paymentintent->amount; + + // Correct the amount according to unit of currency + // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support + $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); + if (!in_array($currency, $arrayzerounitcurrency)) { + $amount = $amount / 100; + } + } } } diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index c8222c4c4aa..c822bfcdf96 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -343,6 +343,9 @@ if (empty($FinalPaymentAmt)) { if (empty($paymentType)) { $paymentType = $_SESSION["paymentType"]; } +if (empty($currencyCodeType)) { + $currencyCodeType = $_SESSION['currencyCodeType']; +} $fulltag = $FULLTAG; $tmptag = dolExplodeIntoArray($fulltag, '.', '='); @@ -403,15 +406,12 @@ if ($ispaymentok) { $paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; } if (empty($paymentTypeId)) { - $paymentType = $_SESSION["paymentType"]; if (empty($paymentType)) { $paymentType = 'CB'; } $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); } - $currencyCodeType = $_SESSION['currencyCodeType']; - dol_syslog("FinalPaymentAmt=".$FinalPaymentAmt." paymentTypeId=".$paymentTypeId." currencyCodeType=".$currencyCodeType, LOG_DEBUG, 0, '_payment'); // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) @@ -435,13 +435,19 @@ if ($ispaymentok) { $errmsg = 'Value of FinalPayment ('.$FinalPaymentAmt.') differs from value expected for membership ('.$amountexpected.'). May be a hack to try to pay a different amount ?'; $postactionmessages[] = $errmsg; $ispostactionok = -1; - dol_syslog("Failed to validate member: ".$errmsg, LOG_ERR, 0, '_payment'); + dol_syslog("Failed to validate member (bad amount check): ".$errmsg, LOG_ERR, 0, '_payment'); } } } // Security protection: - // TODO check that currency is same ? + if ($currencyCodeType && $currencyCodeType != $conf->currency) { // Check that currency is the good one + $error++; + $errmsg = 'Value of currencyCodeType ('.$currencyCodeType.') differs from value expected for membership ('.$conf->currency.'). May be a hack to try to pay a different amount ?'; + $postactionmessages[] = $errmsg; + $ispostactionok = -1; + dol_syslog("Failed to validate member (bad currency check): ".$errmsg, LOG_ERR, 0, '_payment'); + } if (! $error) { // We validate the member (no effect if it is already validated) @@ -766,15 +772,12 @@ if ($ispaymentok) { $paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; } if (empty($paymentTypeId)) { - $paymentType = $_SESSION["paymentType"]; if (empty($paymentType)) { $paymentType = 'CB'; } $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); } - $currencyCodeType = $_SESSION['currencyCodeType']; - // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { $db->begin(); @@ -866,13 +869,10 @@ if ($ispaymentok) { if ($paymentmethod == 'paypal') $paymentTypeId = $conf->global->PAYPAL_PAYMENT_MODE_FOR_PAYMENTS; if ($paymentmethod == 'stripe') $paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; if (empty($paymentTypeId)) { - $paymentType = $_SESSION["paymentType"]; if (empty($paymentType)) $paymentType = 'CB'; $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); } - $currencyCodeType = $_SESSION['currencyCodeType']; - // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) if (!empty($conf->facture->enabled)) { if (!empty($FinalPaymentAmt) && $paymentTypeId > 0 ) { @@ -964,8 +964,6 @@ if ($ispaymentok) { $don = new Don($db); $result = $don->fetch((int) $tmptag['DON']); if ($result) { - $FinalPaymentAmt = $_SESSION["FinalPaymentAmt"]; - $paymentTypeId = 0; if ($paymentmethod == 'paybox') { $paymentTypeId = $conf->global->PAYBOX_PAYMENT_MODE_FOR_PAYMENTS; @@ -977,15 +975,12 @@ if ($ispaymentok) { $paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; } if (empty($paymentTypeId)) { - $paymentType = $_SESSION["paymentType"]; if (empty($paymentType)) { $paymentType = 'CB'; } $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); } - $currencyCodeType = $_SESSION['currencyCodeType']; - // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { $db->begin(); @@ -1074,8 +1069,6 @@ if ($ispaymentok) { $object = new Facture($db); $result = $object->fetch($ref); if ($result) { - $FinalPaymentAmt = $_SESSION["FinalPaymentAmt"]; - $paymentTypeId = 0; if ($paymentmethod == 'paybox') { $paymentTypeId = $conf->global->PAYBOX_PAYMENT_MODE_FOR_PAYMENTS; @@ -1087,15 +1080,12 @@ if ($ispaymentok) { $paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; } if (empty($paymentTypeId)) { - $paymentType = $_SESSION["paymentType"]; if (empty($paymentType)) { $paymentType = 'CB'; } $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); } - $currencyCodeType = $_SESSION['currencyCodeType']; - // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { $resultvalidate = $object->validate($user); @@ -1271,15 +1261,12 @@ if ($ispaymentok) { $paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; } if (empty($paymentTypeId)) { - $paymentType = $_SESSION["paymentType"]; if (empty($paymentType)) { $paymentType = 'CB'; } $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); } - $currencyCodeType = $_SESSION['currencyCodeType']; - // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { $resultvalidate = $object->validate($user); @@ -1687,7 +1674,7 @@ if ($ispaymentok) { print "\n\n"; -print "\n"; +print "\n"; htmlPrintOnlinePaymentFooter($mysoc, $langs, 0, $suffix);