From 23a4933326a3c1fd89fae60bfc235711c7e560a2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 21 Apr 2025 22:59:25 +0200 Subject: [PATCH 1/8] More info for tracking payment bug --- htdocs/compta/paiement/list.php | 48 +++++++++++++++++++++++++++++++-- htdocs/langs/en_US/bills.lang | 2 ++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/paiement/list.php b/htdocs/compta/paiement/list.php index fd5c5b20799..11afdf10d2d 100644 --- a/htdocs/compta/paiement/list.php +++ b/htdocs/compta/paiement/list.php @@ -120,6 +120,8 @@ $arrayfields = array( 'p.num_paiement' => array('label' => "Numero", 'checked' => 1, 'position' => 70, 'tooltip' => "ChequeOrTransferNumber"), 'p.amount' => array('label' => "Amount", 'checked' => 1, 'position' => 80), 'p.note' => array('label' => "Comment", 'checked' => -1, 'position' => 85), + 'p.ext_payment_id' => array('label' => "ExtPaymentID", 'checked' => -1, 'position' => 87), + 'p.ext_payment_site' => array('label' => "ExtPaymentSite", 'checked' => -1, 'position' => 88), 'p.statut' => array('label' => "Status", 'checked' => 1, 'position' => 90, 'enabled' => (getDolGlobalString('BILL_ADD_PAYMENT_VALIDATION'))), ); $arrayfields = dol_sort_array($arrayfields, 'position'); @@ -214,7 +216,7 @@ if (GETPOST("orphelins", "alpha")) { $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; } else { - $sql = "SELECT p.rowid, p.ref, p.datep, p.fk_bank, p.statut, p.num_paiement as num_payment, p.amount, p.note as note_private"; + $sql = "SELECT p.rowid, p.ref, p.datep, p.fk_bank, p.statut, p.num_paiement as num_payment, p.amount, p.note as note_private, p.ext_payment_id, p.ext_payment_site"; $sql .= ", c.code as paiement_code"; $sql .= ", ba.rowid as bid, ba.ref as bref, ba.label as blabel, ba.number, ba.account_number as account_number, ba.fk_accountancy_journal as accountancy_journal"; $sql .= ", s.rowid as socid, s.nom as name, s.email"; @@ -300,7 +302,7 @@ if (GETPOST("orphelins", "alpha")) { $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; - $sql .= " GROUP BY p.rowid, p.ref, p.datep, p.fk_bank, p.statut, p.num_paiement, p.amount, p.note"; + $sql .= " GROUP BY p.rowid, p.ref, p.datep, p.fk_bank, p.statut, p.num_paiement, p.amount, p.note, p.ext_payment_id, p.ext_payment_site"; $sql .= ", c.code"; $sql .= ", ba.rowid, ba.ref, ba.label, ba.number, ba.account_number, ba.fk_accountancy_journal"; $sql .= ", s.rowid, s.nom, s.email"; @@ -515,6 +517,20 @@ if (!empty($arrayfields['p.note']['checked'])) { print ''; } +// Filter: ext_payment_id +if (!empty($arrayfields['p.ext_payment_id']['checked'])) { + print ''; + //print ''; + print ''; +} + +// Filter: ext_payment_site +if (!empty($arrayfields['p.ext_payment_site']['checked'])) { + print ''; + //print ''; + print ''; +} + // Filter: Status (only placeholder) if (!empty($arrayfields['p.statut']['checked'])) { print ''; @@ -588,6 +604,14 @@ if (!empty($arrayfields['p.note']['checked'])) { print_liste_field_titre($arrayfields['p.note']['label'], $_SERVER["PHP_SELF"], "p.note", '', $param, '', $sortfield, $sortorder); $totalarray['nbfield']++; } +if (!empty($arrayfields['p.ext_payment_id']['checked'])) { + print_liste_field_titre($arrayfields['p.ext_payment_id']['label'], $_SERVER["PHP_SELF"], "p.ext_payment_id", '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['p.ext_payment_site']['checked'])) { + print_liste_field_titre($arrayfields['p.ext_payment_site']['label'], $_SERVER["PHP_SELF"], "p.ext_payment_site", '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} if (!empty($arrayfields['p.statut']['checked'])) { print_liste_field_titre($arrayfields['p.statut']['label'], $_SERVER["PHP_SELF"], "p.statut", '', $param, 'class="right"', $sortfield, $sortorder); $totalarray['nbfield']++; @@ -798,6 +822,26 @@ while ($i < $imaxinloop) { } } + // ext_payment_id + if (!empty($arrayfields['p.ext_payment_id']['checked'])) { + print ''; + print dolPrintHTML($objp->ext_payment_id).''; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // ext_payment_site + if (!empty($arrayfields['p.ext_payment_site']['checked'])) { + print ''; + print dolPrintHTML($objp->ext_payment_site).''; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status if (!empty($arrayfields['p.statut']['checked'])) { print ''; diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index ab1165bfac2..3039dffe4e4 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -679,3 +679,5 @@ PaymentMadeForSeveralInvoices=Payment made for several invoices SituationInvoiceProgressCurrent=Invoice progress CumulativeProgression=Cumulative progress INVOICE_ADD_EPC_QR_CODEPay=Scan this QR code to pay with a smartphone supporting payment with EPC QR code. +ExtPaymentID=External payment ID +ExtPaymentSite=External payment Site From cebfdbd69afa0865ade5bd922122734db8c4ffba Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 21 Apr 2025 23:33:30 +0200 Subject: [PATCH 2/8] Add log to help debug payment --- htdocs/public/stripe/ipn.php | 46 +++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index e04053634d7..aa4a2698d30 100644 --- a/htdocs/public/stripe/ipn.php +++ b/htdocs/public/stripe/ipn.php @@ -150,6 +150,7 @@ if (isModEnabled('multicompany') && !empty($conf->stripeconnect->enabled) && is_ $sql .= " WHERE service = '".$db->escape($service)."' and tokenstring LIKE '%".$db->escape($db->escapeforlike($event->account))."%'"; dol_syslog(get_class($db)."::fetch", LOG_DEBUG); + dol_syslog(get_class($db)."::fetch", LOG_DEBUG, 0, '_payment'); $result = $db->query($sql); if ($result) { if ($db->num_rows($result)) { @@ -176,10 +177,14 @@ if (getDolGlobalString('MAIN_APPLICATION_TITLE')) { top_httphead(); dol_syslog("***** Stripe IPN was called with event->type=".$event->type." service=".$service); +dol_syslog("***** Stripe IPN was called with event->type=".$event->type." service=".$service, 0, '_payment'); if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_PAYOUT')) { // When a payout is created by Stripe to transfer money to your account + dol_syslog("object = ".var_export($event->data, true)); + dol_syslog("object = ".var_export($event->data, true), 0, '_payment'); + $error = 0; $result = dolibarr_set_const($db, $service."_NEXTPAYOUT", date('Y-m-d H:i:s', $event->data->object->arrival_date), 'chaine', 0, '', $conf->entity); @@ -223,6 +228,9 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P } } elseif ($event->type == 'payout.paid' && getDolGlobalString('STRIPE_AUTO_RECORD_PAYOUT')) { // When a payout to transfer money to your account is completely done + dol_syslog("object = ".var_export($event->data, true)); + dol_syslog("object = ".var_export($event->data, true), 0, '_payment'); + $error = 0; $result = dolibarr_set_const($db, $service."_NEXTPAYOUT", 0, 'chaine', 0, '', $conf->entity); if ($result) { @@ -337,8 +345,9 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $db->commit(); } elseif ($event->type == 'payment_intent.succeeded') { // Called when making payment with PaymentIntent method ($conf->global->STRIPE_USE_NEW_CHECKOUT is on). + dol_syslog("object = ".var_export($event->data, true)); + dol_syslog("object = ".var_export($event->data, true), 0, '_payment'); - //dol_syslog("object = ".var_export($event->data, true)); include_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php'; global $stripearrayofkeysbyenv; $error = 0; @@ -356,6 +365,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $payment_amountInDolibarr = 0; dol_syslog("Try to find a payment in database for the payment_intent id = ".$TRANSACTIONID); + dol_syslog("Try to find a payment in database for the payment_intent id = ".$TRANSACTIONID, 0, '_payment'); $sql = "SELECT pi.rowid, pi.fk_facture, pi.fk_prelevement_bons, pi.amount, pi.type, pi.traite"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pi"; @@ -377,8 +387,10 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $paymentTypeCodeInDolibarr = $obj->type; dol_syslog("Found a request in database to pay with direct debit generated (pdid = ".$pdid." directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.")"); + dol_syslog("Found a request in database to pay with direct debit generated (pdid = ".$pdid." directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.")", 0, '_payment'); } else { dol_syslog("Found a request in database not yet generated (pdid = ".$pdid." directdebitorcreditransfer_id=".$directdebitorcreditransfer_id."). Was the order deleted after being sent ?", LOG_WARNING); + dol_syslog("Found a request in database not yet generated (pdid = ".$pdid." directdebitorcreditransfer_id=".$directdebitorcreditransfer_id."). Was the order deleted after being sent ?", LOG_WARNING, 0, '_payment'); } } if ($obj->type == 'card' || empty($obj->type)) { @@ -390,12 +402,15 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $paymentTypeCodeInDolibarr = empty($obj->type) ? 'card' : $obj->type; dol_syslog("Found a request in database to pay with card (pdid = ".$pdid."). We should fix status traite to 1"); + dol_syslog("Found a request in database to pay with card (pdid = ".$pdid."). We should fix status traite to 1", 0, '_payment'); } else { dol_syslog("Found a request in database to pay with card (pdid = ".$pdid.") already set to traite=1. Nothing to fix."); + dol_syslog("Found a request in database to pay with card (pdid = ".$pdid.") already set to traite=1. Nothing to fix.", 0, '_payment'); } } } else { dol_syslog("Payment intent ".$TRANSACTIONID." not found into database, so ignored."); + dol_syslog("Payment intent ".$TRANSACTIONID." not found into database, so ignored.", 0, '_payment'); http_response_code(200); print "Payment intent ".$TRANSACTIONID." not found into database, so ignored."; return 1; @@ -412,6 +427,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $stripeacc = $stripearrayofkeysbyenv[$servicestatus]['secret_key']; dol_syslog("Get the Stripe payment object for the payment method id = ".json_encode($paymentmethodstripeid)); + dol_syslog("Get the Stripe payment object for the payment method id = ".json_encode($paymentmethodstripeid), 0, '_payment'); $s = new \Stripe\StripeClient($stripeacc); @@ -434,6 +450,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P // TODO Set traite to 1 dol_syslog("TODO update flag traite to 1"); + dol_syslog("TODO update flag traite to 1", 0, '_payment'); } elseif ($paymentTypeCode == "PRE" && $paymentTypeCodeInDolibarr == 'ban') { // Case payment type in Stripe and into prelevement_demande are both BAN. // For this case, payment on invoice (not yet recorded) must be done and direct debit order must be closed. @@ -480,6 +497,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P if ($db->num_rows($result)) { $ispaymentdone = 1; dol_syslog('* Payment for ext_payment_id '.$paiement->ext_payment_id.' already done. We do not recreate the payment'); + dol_syslog('* Payment for ext_payment_id '.$paiement->ext_payment_id.' already done. We do not recreate the payment', 0, '_payment'); } } @@ -487,6 +505,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P if (!$error && !$ispaymentdone) { dol_syslog('* Record payment type PRE for invoice id ' . $invoice_id . '. It includes closing of invoice and regenerating document.'); + dol_syslog('* Record payment type PRE for invoice id ' . $invoice_id . '. It includes closing of invoice and regenerating document.', 0, '_payment'); // This include closing invoices to 'paid' (and trigger including unsuspending) and regenerating document $paiement_id = $paiement->create($user, 1); @@ -496,10 +515,12 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $error++; dol_syslog("Failed to create the payment for invoice id " . $invoice_id); + dol_syslog("Failed to create the payment for invoice id " . $invoice_id, 0, '_payment'); } else { $postactionmessages[] = 'Payment created'; dol_syslog("The payment has been created for invoice id " . $invoice_id); + dol_syslog("The payment has been created for invoice id " . $invoice_id, 0, '_payment'); } } @@ -516,10 +537,12 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $ispaymentdone = 1; $obj = $db->fetch_object($result); dol_syslog('* Payment already linked to bank record '.$obj->fk_bank.' . We do not recreate the link'); + dol_syslog('* Payment already linked to bank record '.$obj->fk_bank.' . We do not recreate the link', 0, '_payment'); } } if (!$ispaymentdone) { dol_syslog('* Add payment to bank'); + dol_syslog('* Add payment to bank', 0, '_payment'); // The bank used is the one defined into Stripe setup $paymentmethod = 'stripe'; @@ -561,8 +584,10 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $obj = $db->fetch_object($result); $idbon = $obj->idbon; dol_syslog('* Prelevement must be set to credited'); + dol_syslog('* Prelevement must be set to credited', 0, '_payment'); } else { dol_syslog('* Prelevement not found or already credited'); + dol_syslog('* Prelevement not found or already credited', 0, '_payment'); } } else { $postactionmessages[] = $db->lasterror(); @@ -611,13 +636,16 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P } } else { dol_syslog("The payment mode of this payment is ".$paymentTypeCode." in Stripe and ".$paymentTypeCodeInDolibarr." in Dolibarr. This case is not managed by the IPN"); + dol_syslog("The payment mode of this payment is ".$paymentTypeCode." in Stripe and ".$paymentTypeCodeInDolibarr." in Dolibarr. This case is not managed by the IPN", 0, '_payment'); } } else { dol_syslog("Nothing to do in database because we don't know paymentTypeIdInDolibarr"); + dol_syslog("Nothing to do in database because we don't know paymentTypeIdInDolibarr", 0, '_payment'); } } elseif ($event->type == 'payment_intent.payment_failed') { // When a try to take payment has failed. Useful for asynchronous SEPA payment that fails. dol_syslog("A try to make a payment has failed"); + dol_syslog("A try to make a payment has failed", 0, '_payment'); $object = $event->data->object; $ipaddress = $object->metadata->ipaddress; @@ -663,6 +691,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P } dol_syslog("objpayid=".$objpayid." objpaymentmodetype=".$objpaymentmodetype." objerrcode=".$objerrcode); + dol_syslog("objpayid=".$objpayid." objpaymentmodetype=".$objpaymentmodetype." objerrcode=".$objerrcode, 0, '_payment'); // If this is a differed payment for SEPA, add a line into agenda events if ($objpaymentmodetype == 'sepa_debit') { @@ -698,6 +727,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $result = $actioncomm->create($user); if ($result <= 0) { dol_syslog($actioncomm->error, LOG_ERR); + dol_syslog($actioncomm->error, LOG_ERR, 0, '_payment'); $error++; } @@ -712,6 +742,9 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P } elseif ($event->type == 'checkout.session.completed') { // Called when making payment with new Checkout method ($conf->global->STRIPE_USE_NEW_CHECKOUT is on). // TODO: create fees } elseif ($event->type == 'payment_method.attached') { + dol_syslog("object = ".var_export($event->data, true)); + dol_syslog("object = ".var_export($event->data, true), 0, '_payment'); + // When we link a payment method with a customer on Stripe side require_once DOL_DOCUMENT_ROOT.'/societe/class/companypaymentmode.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societeaccount.class.php'; @@ -761,6 +794,9 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P } } } elseif ($event->type == 'payment_method.updated') { + dol_syslog("object = ".var_export($event->data, true)); + dol_syslog("object = ".var_export($event->data, true), 0, '_payment'); + // When we update a payment method on Stripe side require_once DOL_DOCUMENT_ROOT.'/societe/class/companypaymentmode.class.php'; $companypaymentmode = new CompanyPaymentMode($db); @@ -809,9 +845,11 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P } elseif ($event->type == 'charge.dispute.closed') { // When a dispute to cancel a SEPA payment is finished dol_syslog("object = ".var_export($event->data, true)); + dol_syslog("object = ".var_export($event->data, true), 0, '_payment'); } elseif ($event->type == 'charge.dispute.funds_withdrawn') { // When a dispute/withdraw to cancel a SEPA payment is done dol_syslog("object = ".var_export($event->data, true)); + dol_syslog("object = ".var_export($event->data, true), 0, '_payment'); global $stripearrayofkeysbyenv; $error = 0; @@ -834,6 +872,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $payment_amountInDolibarr = 0; dol_syslog("Try to find the payment in database for the payment_intent id = ".$TRANSACTIONID); + dol_syslog("Try to find the payment in database for the payment_intent id = ".$TRANSACTIONID, 0, '_payment'); $sql = "SELECT pi.rowid, pi.fk_facture, pi.fk_prelevement_bons, pi.amount, pi.type, pi.traite"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pi"; @@ -853,6 +892,7 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $paymentTypeCodeInDolibarr = $obj->type; dol_syslog("Found the payment intent for ban in database (pdid = ".$pdid." directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.")"); + dol_syslog("Found the payment intent for ban in database (pdid = ".$pdid." directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.")", 0, '_payment'); } if ($obj->type == 'card' || empty($obj->type)) { // This is a card payment. @@ -862,9 +902,11 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $paymentTypeCodeInDolibarr = empty($obj->type) ? 'card' : $obj->type; dol_syslog("Found the payment intent for card in database (pdid = ".$pdid." directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.")"); + dol_syslog("Found the payment intent for card in database (pdid = ".$pdid." directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.")", 0, '_payment'); } } else { dol_syslog("Payment intent ".$TRANSACTIONID." not found into database, so ignored."); + dol_syslog("Payment intent ".$TRANSACTIONID." not found into database, so ignored.", 0, '_payment'); http_response_code(200); print "Payment intent ".$TRANSACTIONID." not found into database, so ignored."; return 1; @@ -876,11 +918,13 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P } dol_syslog("objinvoiceid=".$invoice_id); + dol_syslog("objinvoiceid=".$invoice_id, 0, '_payment'); $tmpinvoice = new Facture($db); $tmpinvoice->fetch($invoice_id); $tmpinvoice->fetch_thirdparty(); dol_syslog("The payment disputed is ".$amountdispute." and the invoice is ".$payment_amountInDolibarr); + dol_syslog("The payment disputed is ".$amountdispute." and the invoice is ".$payment_amountInDolibarr, 0, '_payment'); if ($amountdispute != $payment_amountInDolibarr) { http_response_code(500); From 03c2da65fe34ad54d10c1c59abc77df63e9445a2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 21 Apr 2025 23:58:26 +0200 Subject: [PATCH 3/8] Add log to help debug payment --- htdocs/public/payment/newpayment.php | 46 +++++++++++++++------------- htdocs/public/payment/paymentok.php | 2 +- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index ceb5d6cb984..70211ed33dc 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -370,6 +370,7 @@ if (getDolGlobalString('PAYMENT_SECURITY_TOKEN')) { $valid = false; // PAYMENT_SECURITY_ACCEPT_ANY_TOKEN is for backward compatibility } else { dol_syslog("Warning: PAYMENT_SECURITY_ACCEPT_ANY_TOKEN is on", LOG_WARNING); + dol_syslog("Warning: PAYMENT_SECURITY_ACCEPT_ANY_TOKEN is on", LOG_WARNING, 0, '_payment'); } } @@ -446,6 +447,7 @@ if ($action == 'dopayment') { // Test on permission not required here (anonymous if (empty($mesg)) { dol_syslog("newpayment.php call paypal api and do redirect", LOG_DEBUG); + dol_syslog("newpayment.php call paypal api and do redirect", LOG_DEBUG, 0, '_payment'); // Other $PAYPAL_API_DEVISE = "USD"; @@ -455,27 +457,29 @@ if ($action == 'dopayment') { // Test on permission not required here (anonymous // Show var initialized by inclusion of paypal lib at start of this file dol_syslog("Submit Paypal form", LOG_DEBUG); - dol_syslog("PAYPAL_API_USER: $PAYPAL_API_USER", LOG_DEBUG); - dol_syslog("PAYPAL_API_PASSWORD: ".preg_replace('/./', '*', $PAYPAL_API_PASSWORD), LOG_DEBUG); // No password into log files - dol_syslog("PAYPAL_API_SIGNATURE: $PAYPAL_API_SIGNATURE", LOG_DEBUG); - dol_syslog("PAYPAL_API_SANDBOX: $PAYPAL_API_SANDBOX", LOG_DEBUG); - dol_syslog("PAYPAL_API_OK: $PAYPAL_API_OK", LOG_DEBUG); - dol_syslog("PAYPAL_API_KO: $PAYPAL_API_KO", LOG_DEBUG); - dol_syslog("PAYPAL_API_PRICE: $PAYPAL_API_PRICE", LOG_DEBUG); - dol_syslog("PAYPAL_API_DEVISE: $PAYPAL_API_DEVISE", LOG_DEBUG); - // All those fields may be empty when making a payment for a free amount for example - dol_syslog("shipToName: $shipToName", LOG_DEBUG); - dol_syslog("shipToStreet: $shipToStreet", LOG_DEBUG); - dol_syslog("shipToCity: $shipToCity", LOG_DEBUG); - dol_syslog("shipToState: $shipToState", LOG_DEBUG); - dol_syslog("shipToCountryCode: $shipToCountryCode", LOG_DEBUG); - dol_syslog("shipToZip: $shipToZip", LOG_DEBUG); - dol_syslog("shipToStreet2: $shipToStreet2", LOG_DEBUG); - dol_syslog("phoneNum: $phoneNum", LOG_DEBUG); - dol_syslog("email: $email", LOG_DEBUG); - dol_syslog("desc: $desc", LOG_DEBUG); + dol_syslog("Submit Paypal form", LOG_DEBUG, 0, '_payment'); - dol_syslog("SCRIPT_URI: ".(empty($_SERVER["SCRIPT_URI"]) ? '' : $_SERVER["SCRIPT_URI"]), LOG_DEBUG); // If defined script uri must match domain of PAYPAL_API_OK and PAYPAL_API_KO + dol_syslog("PAYPAL_API_USER: $PAYPAL_API_USER", LOG_DEBUG, 0, '_payment'); + dol_syslog("PAYPAL_API_PASSWORD: ".preg_replace('/./', '*', $PAYPAL_API_PASSWORD), LOG_DEBUG, 0, '_payment'); // No password into log files + dol_syslog("PAYPAL_API_SIGNATURE: $PAYPAL_API_SIGNATURE", LOG_DEBUG, 0, '_payment'); + dol_syslog("PAYPAL_API_SANDBOX: $PAYPAL_API_SANDBOX", LOG_DEBUG, 0, '_payment'); + dol_syslog("PAYPAL_API_OK: $PAYPAL_API_OK", LOG_DEBUG, 0, '_payment'); + dol_syslog("PAYPAL_API_KO: $PAYPAL_API_KO", LOG_DEBUG, 0, '_payment'); + dol_syslog("PAYPAL_API_PRICE: $PAYPAL_API_PRICE", LOG_DEBUG, 0, '_payment'); + dol_syslog("PAYPAL_API_DEVISE: $PAYPAL_API_DEVISE", LOG_DEBUG, 0, '_payment'); + // All those fields may be empty when making a payment for a free amount for example + dol_syslog("shipToName: $shipToName", LOG_DEBUG, 0, '_payment'); + dol_syslog("shipToStreet: $shipToStreet", LOG_DEBUG, 0, '_payment'); + dol_syslog("shipToCity: $shipToCity", LOG_DEBUG, 0, '_payment'); + dol_syslog("shipToState: $shipToState", LOG_DEBUG, 0, '_payment'); + dol_syslog("shipToCountryCode: $shipToCountryCode", LOG_DEBUG, 0, '_payment'); + dol_syslog("shipToZip: $shipToZip", LOG_DEBUG, 0, '_payment'); + dol_syslog("shipToStreet2: $shipToStreet2", LOG_DEBUG, 0, '_payment'); + dol_syslog("phoneNum: $phoneNum", LOG_DEBUG, 0, '_payment'); + dol_syslog("email: $email", LOG_DEBUG, 0, '_payment'); + dol_syslog("desc: $desc", LOG_DEBUG, 0, '_payment'); + + dol_syslog("SCRIPT_URI: ".(empty($_SERVER["SCRIPT_URI"]) ? '' : $_SERVER["SCRIPT_URI"]), LOG_DEBUG, 0, '_payment'); // If defined script uri must match domain of PAYPAL_API_OK and PAYPAL_API_KO // A redirect is added if API call successful $mesg = print_paypal_redirect($PAYPAL_API_PRICE, $PAYPAL_API_DEVISE, $PAYPAL_PAYMENT_TYPE, $PAYPAL_API_OK, $PAYPAL_API_KO, $FULLTAG); @@ -511,7 +515,7 @@ if ($action == 'dopayment') { // Test on permission not required here (anonymous } if (empty($mesg)) { - dol_syslog("newpayment.php call paybox api and do redirect", LOG_DEBUG); + dol_syslog("newpayment.php call paybox api and do redirect", LOG_DEBUG, 0, '_payment'); include_once DOL_DOCUMENT_ROOT.'/paybox/lib/paybox.lib.php'; print_paybox_redirect((float) $PRICE, $conf->currency, $email, $urlok, $urlko, $FULLTAG); diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 7ee00438afc..0b81db356ec 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -134,7 +134,7 @@ dol_syslog("***** paymentok.php is called paymentmethod=".$paymentmethod." FULLT $reg_ws = array(); $ws = preg_match('/WS=([^\.]+)/', $FULLTAG, $reg_ws) ? $reg_ws[1] : 0; if ($ws) { - dol_syslog("Paymentok.php page is invoked from a website with ref ".$ws.". It performs actions and then redirects back to this website. A page with ref paymentok must be created for this website.", LOG_DEBUG, 0, '_payment'); + dol_syslog("paymentok.php page is invoked from a website with ref ".$ws.". It performs actions and then redirects back to this website. A page with ref paymentok must be created for this website.", LOG_DEBUG, 0, '_payment'); } $validpaymentmethod = getValidOnlinePaymentMethods($paymentmethod); From 8b4561bc3c85fc7ec13923187fb6404d7545682a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Apr 2025 00:21:46 +0200 Subject: [PATCH 4/8] Fix transactions --- htdocs/public/payment/paymentok.php | 32 ++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 0b81db356ec..617541714f7 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -1064,6 +1064,8 @@ if ($ispaymentok) { // 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 (isModEnabled('invoice')) { if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { + $db->begin(); + include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; $invoice = new Facture($db); $result = $invoice->createFromOrder($object, $user); @@ -1152,15 +1154,16 @@ if ($ispaymentok) { $error++; } } - - if (!$error) { - $db->commit(); - } else { - $db->rollback(); - } } else { $postactionmessages[] = 'Failed to create invoice form order ' . $tmptag['ORD'] . '.'; $ispostactionok = -1; + $error++; + } + + if (!$error) { + $db->commit(); + } else { + $db->rollback(); } } else { $postactionmessages[] = 'Failed to get a valid value for "amount paid" (' . $FinalPaymentAmt . ') or "payment type id" (' . $paymentTypeId . ') to record the payment of order ' . $tmptag['ORD'] . '. May be payment was already recorded.'; @@ -1680,6 +1683,8 @@ if ($ispaymentok) { $error++; setEventMessages(null, $thirdparty->errors, "errors"); } else { + // TODO Move the send of email out of the db transaction + // Sending mail require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; @@ -1786,6 +1791,8 @@ if ($ispaymentok) { // 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 (isModEnabled('invoice')) { if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { + $db->begin(); + include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; $invoice = new Facture($db); $result = $invoice->createFromContract($object, $user, array((int) $contract_lines)); @@ -1864,12 +1871,6 @@ if ($ispaymentok) { $error++; } } - - if (!$error) { - $db->commit(); - } else { - $db->rollback(); - } } else { $msg = 'Failed to create invoice form contract ' . $tmptag['CON']; if (!empty($tmptag['COL'])) { @@ -1877,6 +1878,13 @@ if ($ispaymentok) { } $postactionmessages[] = $msg; $ispostactionok = -1; + $error++; + } + + if (!$error) { + $db->commit(); + } else { + $db->rollback(); } } else { $postactionmessages[] = 'Failed to get a valid value for "amount paid" (' . $FinalPaymentAmt . ') or "payment type id" (' . $paymentTypeId . ') to record the payment of contract ' . $tmptag['CON'] .'. Maybe payment was already recorded.'; From 656a4f36e3e0dedc4e1d1b2fd423ff6cf560477f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Apr 2025 01:42:28 +0200 Subject: [PATCH 5/8] Fix add protection to avoid bypass in paymentok --- htdocs/public/payment/newpayment.php | 30 +++++++++++++++++++------ htdocs/public/payment/paymentko.php | 12 +++++----- htdocs/public/payment/paymentok.php | 33 +++++++++++++++++++--------- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 70211ed33dc..c0712da4f2b 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -68,6 +68,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societeaccount.class.php'; @@ -132,7 +133,7 @@ if (!$action) { $thirdparty = null; // Init for static analysis -$istrpecu = null; // Init for static analysis +$stripecu = null; // Init for static analysis $paymentintent = null; // Init for static analysis // Load data required later for actions and view @@ -796,7 +797,7 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r $stripe = new Stripe($db); $stripeacc = $stripe->getStripeAccount($service); - // We go here if $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is set. + // We go here if getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') is set. // In such a case, payment is always ok when we call the "charge" action. $paymentintent_id = GETPOST("paymentintent_id", "alpha"); @@ -824,16 +825,23 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r dol_syslog($errormessage, LOG_WARNING, 0, '_payment'); setEventMessages($paymentintent->status, null, 'errors'); $action = ''; + + $randomseckey = getRandomPassword(true, null, 20); + $_SESSION['paymentkosessionkey'] = $randomseckey; // key between newpayment.php to paymentko.php + + $urlko .= '&paymentkosessionkey='.urlencode($randomseckey); } else { - // TODO We can also record the payment mode into llx_societe_rib with stripe $paymentintent->payment_method + // 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, '_payment'); + // dol_syslog("Create payment_method for ".$paymentintent->payment_method, LOG_DEBUG, 0, '_payment'); // 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 retrieved from the POST. - if (!empty($paymentintent->currency) && !empty($paymentintent->amount)) { + $amount = $paymentintent->amount; + $currency = ''; + + if (!empty($paymentintent->currency)) { $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 @@ -842,6 +850,13 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r $amount /= 100; } } + + dol_syslog("StatusOfRetrievedIntent is succeeded for amount = ".$amount." currency = ".$currency, LOG_DEBUG, 0, '_payment'); + + $randomseckey = getRandomPassword(true, null, 20); + $_SESSION['paymentoksessionkey'] = $randomseckey; // key between newpayment.php to paymentok.php + + $urlok .= '&paymentoksessionkey='.urlencode($randomseckey); } } @@ -858,7 +873,8 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r $_SESSION['errormessage'] = $errormessage; dol_syslog("Action charge stripe STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION=".getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')." ip=".$remoteip, LOG_DEBUG, 0, '_payment'); - dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." FinalPaymentAmt=".$_SESSION["FinalPaymentAmt"]." currencyCodeType=".$_SESSION["currencyCodeType"]." payerID=".$_SESSION['payerID']." TRANSACTIONID=".$_SESSION['TRANSACTIONID'], LOG_DEBUG, 0, '_payment'); + dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." paymentsessionkey=".$_SESSION["paymentsessionkey"], LOG_DEBUG, 0, '_payment'); + dol_syslog("FinalPaymentAmt=".$_SESSION["FinalPaymentAmt"]." currencyCodeType=".$_SESSION["currencyCodeType"]." payerID=".$_SESSION['payerID']." TRANSACTIONID=".$_SESSION['TRANSACTIONID'], LOG_DEBUG, 0, '_payment'); dol_syslog("FULLTAG=".$FULLTAG, LOG_DEBUG, 0, '_payment'); dol_syslog("error=".$error." errormessage=".$errormessage, LOG_DEBUG, 0, '_payment'); dol_syslog("_SERVER[SERVER_NAME] = ".(empty($_SERVER["SERVER_NAME"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_NAME"])), LOG_DEBUG, 0, '_payment'); diff --git a/htdocs/public/payment/paymentko.php b/htdocs/public/payment/paymentko.php index 3cd0ecd04a6..c1f0176e3ab 100644 --- a/htdocs/public/payment/paymentko.php +++ b/htdocs/public/payment/paymentko.php @@ -163,7 +163,6 @@ if ($ws) { // None - /* * View */ @@ -178,6 +177,7 @@ foreach ($_POST as $k => $v) { } dol_syslog("POST=".$tracepost, LOG_DEBUG, 0, '_payment'); +dol_syslog("paymentkosessionkey=".GETPOST('paymentkosessionkey')." SESSION['paymentkosessionkey']=".$_SESSION['paymentkosessionkey'], LOG_DEBUG, 0, '_payment'); // Set $appli for emails title $appli = $mysoc->name; @@ -348,15 +348,15 @@ $db->close(); // If option to do a redirect somewhere else is defined. if (!empty($doactionsthenredirect)) { - $randomseckey = getRandomPassword(true, null, 20); - $_SESSION['paymentsessionkey'] = $randomseckey; - // Redirect to an error page + $randomseckey = getRandomPassword(true, null, 20); + $_SESSION['paymentkosessionkey'] = $randomseckey; // key between paymentok.php to another page like a paymentko of the website. + // Paymentko page must be created for the specific website if (!defined('USEDOLIBARRSERVER') && !empty($ws_virtuelhost)) { - $ext_urlko = $ws_virtuelhost . '/paymentko.php?paymentsessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; + $ext_urlko = $ws_virtuelhost . '/paymentko.php?paymentkosessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; } else { - $ext_urlko = DOL_URL_ROOT.'/public/website/index.php?paymentsessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentko&fulltag='.$FULLTAG; + $ext_urlko = DOL_URL_ROOT.'/public/website/index.php?paymentkosessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentko&fulltag='.$FULLTAG; } dol_syslog("Now do a redirect using Location : ".$ext_urlko, LOG_DEBUG, 0, '_payment'); diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 617541714f7..f866f20826b 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -181,9 +181,15 @@ if ($ws) { } } +/* + * Actions + */ + +// None + /* - * Actions and view + * View */ $now = dol_now(); @@ -199,14 +205,17 @@ foreach ($_POST as $k => $v) { } } dol_syslog("POST=".$tracepost, LOG_DEBUG, 0, '_payment'); + $tracesession = ""; foreach ($_SESSION as $k => $v) { - if (is_scalar($k) && is_scalar($v)) { + if (is_scalar($k) && is_scalar($v) && in_array($k, array('currencyCodeType', 'errormessage', 'FinalPaymentAmt', 'ipaddress', 'onlinetoken', 'payerID', 'paymentType', 'TRANSACTIONID', 'paymentoksessionkey', 'paymentkosessionkey'))) { $tracesession .= "$k - $v\n"; } } dol_syslog("SESSION=".$tracesession, LOG_DEBUG, 0, '_payment'); +dol_syslog("paymentoksessionkey=".GETPOST('paymentoksessionkey')." SESSION['paymentoksessionkey']=".$_SESSION['paymentoksessionkey'], LOG_DEBUG, 0, '_payment'); + $head = ''; if (getDolGlobalString('ONLINE_PAYMENT_CSS_URL')) { $head = ''."\n"; @@ -370,7 +379,8 @@ if (isModEnabled('paybox')) { // For Stripe if (isModEnabled('stripe')) { if ($paymentmethod === 'stripe') { - // TODO Add a check to validate that payment is ok. We can request Stripe with payment_intent and payment_intent_client_secret + // TODO Add a check to validate that payment is ok. + // We can request Stripe with payment_intent and payment_intent_client_secret the sameway we do in newpayment after comment "// Get here amount and currency used for payment". $ispaymentok = true; // We call this page only if payment is ok on payment system } } @@ -2162,16 +2172,16 @@ $db->close(); // If option to do a redirect somewhere else. if (!empty($doactionsthenredirect)) { - $randomseckey = getRandomPassword(true, null, 20); - $_SESSION['paymentsessionkey'] = $randomseckey; - if ($ispaymentok) { // Redirect to a success page + $randomseckey = getRandomPassword(true, null, 20); + $_SESSION['paymentoksessionkey'] = $randomseckey; // key between paymentok.php to another page like a paymentok of the website. + // Paymentok page must be created for the specific website if (!defined('USEDOLIBARRSERVER') && !empty($ws_virtuelhost)) { - $ext_urlok = $ws_virtuelhost . '/paymentok.php?paymentsessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; + $ext_urlok = $ws_virtuelhost . '/paymentok.php?paymentoksessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; } else { - $ext_urlok = DOL_URL_ROOT.'/public/website/index.php?paymentsessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentok&fulltag='.$FULLTAG; + $ext_urlok = DOL_URL_ROOT.'/public/website/index.php?paymentoksessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentok&fulltag='.$FULLTAG; } dol_syslog("Now do a redirect using a Location: ".$ext_urlok, LOG_DEBUG, 0, '_payment'); @@ -2179,11 +2189,14 @@ if (!empty($doactionsthenredirect)) { exit; } else { // Redirect to an error page + $randomseckey = getRandomPassword(true, null, 20); + $_SESSION['paymentkosessionkey'] = $randomseckey; // key between paymentok.php to another page like a paymentko of the website. + // Paymentko page must be created for the specific website if (!defined('USEDOLIBARRSERVER') && !empty($ws_virtuelhost)) { - $ext_urlko = $ws_virtuelhost . '/paymentko.php?paymentsessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; + $ext_urlko = $ws_virtuelhost . '/paymentko.php?paymentkosessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; } else { - $ext_urlko = DOL_URL_ROOT.'/public/website/index.php?paymentsessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentko&fulltag='.$FULLTAG; + $ext_urlko = DOL_URL_ROOT.'/public/website/index.php?paymentkosessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentko&fulltag='.$FULLTAG; } dol_syslog("Now do a redirect using a Location:".$ext_urlko, LOG_DEBUG, 0, '_payment'); From aab39489f2e8adc55d4d5ebfea0bd490f571ded6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Apr 2025 02:02:20 +0200 Subject: [PATCH 6/8] Fix add protection to avoid bypass in paymentok --- htdocs/public/payment/newpayment.php | 12 ++++++++++++ htdocs/public/payment/paymentok.php | 10 +++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index c0712da4f2b..8c1f4c9ea59 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -783,6 +783,18 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r setEventMessages($e->getMessage(), null, 'errors'); $action = ''; } + + if ($error) { + $randomseckey = getRandomPassword(true, null, 20); + $_SESSION['paymentkosessionkey'] = $randomseckey; // key between newpayment.php to paymentko.php + + $urlko .= '&paymentkosessionkey='.urlencode($randomseckey); + } else { + $randomseckey = getRandomPassword(true, null, 20); + $_SESSION['paymentoksessionkey'] = $randomseckey; // key between newpayment.php to paymentok.php + + $urlok .= '&paymentoksessionkey='.urlencode($randomseckey); + } } // When using the PaymentIntent API architecture (mode set on by default into conf.class.php) diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index f866f20826b..376ee9afafd 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -379,9 +379,13 @@ if (isModEnabled('paybox')) { // For Stripe if (isModEnabled('stripe')) { if ($paymentmethod === 'stripe') { - // TODO Add a check to validate that payment is ok. - // We can request Stripe with payment_intent and payment_intent_client_secret the sameway we do in newpayment after comment "// Get here amount and currency used for payment". - $ispaymentok = true; // We call this page only if payment is ok on payment system + // Check we are coming from the newpaymentpage + if (GETPOST('paymentoksessionkey') == $_SESSION['paymentoksessionkey']) { + // We can also request Stripe with payment_intent and payment_intent_client_secret the sameway we do in newpayment after comment "// Get here amount and currency used for payment". + $ispaymentok = true; // We call this page only if payment is ok on payment system + } else { + $ispaymentok = false; // We call this page only if payment is ok on payment system + } } } From 0c2dcefcfb10a99f215559870eb125deaebd248c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Apr 2025 02:19:27 +0200 Subject: [PATCH 7/8] Fix log --- htdocs/public/payment/newpayment.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 8c1f4c9ea59..effff8e5846 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -885,7 +885,7 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r $_SESSION['errormessage'] = $errormessage; dol_syslog("Action charge stripe STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION=".getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')." ip=".$remoteip, LOG_DEBUG, 0, '_payment'); - dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." paymentsessionkey=".$_SESSION["paymentsessionkey"], LOG_DEBUG, 0, '_payment'); + dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." paymentoksessionkey=".$_SESSION["paymentoksessionkey"]." paymentkosessionkey=".$_SESSION["paymentkosessionkey"], LOG_DEBUG, 0, '_payment'); dol_syslog("FinalPaymentAmt=".$_SESSION["FinalPaymentAmt"]." currencyCodeType=".$_SESSION["currencyCodeType"]." payerID=".$_SESSION['payerID']." TRANSACTIONID=".$_SESSION['TRANSACTIONID'], LOG_DEBUG, 0, '_payment'); dol_syslog("FULLTAG=".$FULLTAG, LOG_DEBUG, 0, '_payment'); dol_syslog("error=".$error." errormessage=".$errormessage, LOG_DEBUG, 0, '_payment'); From 99b1bcf4d0b2ffeca80eec697ac14578673b3c6a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Apr 2025 03:09:36 +0200 Subject: [PATCH 8/8] Debug v22 on param sessionkey --- htdocs/public/payment/newpayment.php | 18 +++++++++--------- htdocs/public/payment/paymentko.php | 6 +++--- htdocs/public/payment/paymentok.php | 14 +++++++------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index effff8e5846..e7d6c4b929b 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -786,14 +786,14 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r if ($error) { $randomseckey = getRandomPassword(true, null, 20); - $_SESSION['paymentkosessionkey'] = $randomseckey; // key between newpayment.php to paymentko.php + $_SESSION['paymentkosessioncode'] = $randomseckey; // key between newpayment.php to paymentko.php - $urlko .= '&paymentkosessionkey='.urlencode($randomseckey); + $urlko .= '&paymentkosessioncode='.urlencode($randomseckey); } else { $randomseckey = getRandomPassword(true, null, 20); - $_SESSION['paymentoksessionkey'] = $randomseckey; // key between newpayment.php to paymentok.php + $_SESSION['paymentoksessioncode'] = $randomseckey; // key between newpayment.php to paymentok.php - $urlok .= '&paymentoksessionkey='.urlencode($randomseckey); + $urlok .= '&paymentoksessioncode='.urlencode($randomseckey); } } @@ -839,9 +839,9 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r $action = ''; $randomseckey = getRandomPassword(true, null, 20); - $_SESSION['paymentkosessionkey'] = $randomseckey; // key between newpayment.php to paymentko.php + $_SESSION['paymentkosessioncode'] = $randomseckey; // key between newpayment.php to paymentko.php - $urlko .= '&paymentkosessionkey='.urlencode($randomseckey); + $urlko .= '&paymentkosessioncode='.urlencode($randomseckey); } else { // 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. @@ -866,9 +866,9 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r dol_syslog("StatusOfRetrievedIntent is succeeded for amount = ".$amount." currency = ".$currency, LOG_DEBUG, 0, '_payment'); $randomseckey = getRandomPassword(true, null, 20); - $_SESSION['paymentoksessionkey'] = $randomseckey; // key between newpayment.php to paymentok.php + $_SESSION['paymentoksessioncode'] = $randomseckey; // key between newpayment.php to paymentok.php - $urlok .= '&paymentoksessionkey='.urlencode($randomseckey); + $urlok .= '&paymentoksessioncode='.urlencode($randomseckey); } } @@ -885,7 +885,7 @@ if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not r $_SESSION['errormessage'] = $errormessage; dol_syslog("Action charge stripe STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION=".getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')." ip=".$remoteip, LOG_DEBUG, 0, '_payment'); - dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." paymentoksessionkey=".$_SESSION["paymentoksessionkey"]." paymentkosessionkey=".$_SESSION["paymentkosessionkey"], LOG_DEBUG, 0, '_payment'); + dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." paymentoksessioncode=".$_SESSION["paymentoksessioncode"]." paymentkosessioncode=".$_SESSION["paymentkosessioncode"], LOG_DEBUG, 0, '_payment'); dol_syslog("FinalPaymentAmt=".$_SESSION["FinalPaymentAmt"]." currencyCodeType=".$_SESSION["currencyCodeType"]." payerID=".$_SESSION['payerID']." TRANSACTIONID=".$_SESSION['TRANSACTIONID'], LOG_DEBUG, 0, '_payment'); dol_syslog("FULLTAG=".$FULLTAG, LOG_DEBUG, 0, '_payment'); dol_syslog("error=".$error." errormessage=".$errormessage, LOG_DEBUG, 0, '_payment'); diff --git a/htdocs/public/payment/paymentko.php b/htdocs/public/payment/paymentko.php index c1f0176e3ab..9ccb7c79eb0 100644 --- a/htdocs/public/payment/paymentko.php +++ b/htdocs/public/payment/paymentko.php @@ -177,7 +177,7 @@ foreach ($_POST as $k => $v) { } dol_syslog("POST=".$tracepost, LOG_DEBUG, 0, '_payment'); -dol_syslog("paymentkosessionkey=".GETPOST('paymentkosessionkey')." SESSION['paymentkosessionkey']=".$_SESSION['paymentkosessionkey'], LOG_DEBUG, 0, '_payment'); +dol_syslog("paymentkosessioncode=".GETPOST('paymentkosessioncode')." SESSION['paymentkosessioncode']=".$_SESSION['paymentkosessioncode'], LOG_DEBUG, 0, '_payment'); // Set $appli for emails title $appli = $mysoc->name; @@ -354,9 +354,9 @@ if (!empty($doactionsthenredirect)) { // Paymentko page must be created for the specific website if (!defined('USEDOLIBARRSERVER') && !empty($ws_virtuelhost)) { - $ext_urlko = $ws_virtuelhost . '/paymentko.php?paymentkosessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; + $ext_urlko = $ws_virtuelhost . '/paymentko.php?paymentkosessioncode='.urlencode($randomseckey).'&fulltag='.$FULLTAG; } else { - $ext_urlko = DOL_URL_ROOT.'/public/website/index.php?paymentkosessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentko&fulltag='.$FULLTAG; + $ext_urlko = DOL_URL_ROOT.'/public/website/index.php?paymentkosessioncode='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentko&fulltag='.$FULLTAG; } dol_syslog("Now do a redirect using Location : ".$ext_urlko, LOG_DEBUG, 0, '_payment'); diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 376ee9afafd..9bf6518dad1 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -214,7 +214,7 @@ foreach ($_SESSION as $k => $v) { } dol_syslog("SESSION=".$tracesession, LOG_DEBUG, 0, '_payment'); -dol_syslog("paymentoksessionkey=".GETPOST('paymentoksessionkey')." SESSION['paymentoksessionkey']=".$_SESSION['paymentoksessionkey'], LOG_DEBUG, 0, '_payment'); +dol_syslog("paymentoksessioncode=".GETPOST('paymentoksessioncode')." SESSION['paymentoksessioncode']=".$_SESSION['paymentoksessioncode'], LOG_DEBUG, 0, '_payment'); $head = ''; if (getDolGlobalString('ONLINE_PAYMENT_CSS_URL')) { @@ -2179,13 +2179,13 @@ if (!empty($doactionsthenredirect)) { if ($ispaymentok) { // Redirect to a success page $randomseckey = getRandomPassword(true, null, 20); - $_SESSION['paymentoksessionkey'] = $randomseckey; // key between paymentok.php to another page like a paymentok of the website. + $_SESSION['paymentoksessioncode'] = $randomseckey; // key between paymentok.php to another page like a paymentok of the website. // Paymentok page must be created for the specific website if (!defined('USEDOLIBARRSERVER') && !empty($ws_virtuelhost)) { - $ext_urlok = $ws_virtuelhost . '/paymentok.php?paymentoksessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; + $ext_urlok = $ws_virtuelhost . '/paymentok.php?paymentoksessioncode='.urlencode($randomseckey).'&fulltag='.$FULLTAG; } else { - $ext_urlok = DOL_URL_ROOT.'/public/website/index.php?paymentoksessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentok&fulltag='.$FULLTAG; + $ext_urlok = DOL_URL_ROOT.'/public/website/index.php?paymentoksessioncode='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentok&fulltag='.$FULLTAG; } dol_syslog("Now do a redirect using a Location: ".$ext_urlok, LOG_DEBUG, 0, '_payment'); @@ -2194,13 +2194,13 @@ if (!empty($doactionsthenredirect)) { } else { // Redirect to an error page $randomseckey = getRandomPassword(true, null, 20); - $_SESSION['paymentkosessionkey'] = $randomseckey; // key between paymentok.php to another page like a paymentko of the website. + $_SESSION['paymentkosessioncode'] = $randomseckey; // key between paymentok.php to another page like a paymentko of the website. // Paymentko page must be created for the specific website if (!defined('USEDOLIBARRSERVER') && !empty($ws_virtuelhost)) { - $ext_urlko = $ws_virtuelhost . '/paymentko.php?paymentkosessionkey='.urlencode($randomseckey).'&fulltag='.$FULLTAG; + $ext_urlko = $ws_virtuelhost . '/paymentko.php?paymentkosessioncode='.urlencode($randomseckey).'&fulltag='.$FULLTAG; } else { - $ext_urlko = DOL_URL_ROOT.'/public/website/index.php?paymentkosessionkey='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentko&fulltag='.$FULLTAG; + $ext_urlko = DOL_URL_ROOT.'/public/website/index.php?paymentkosessioncode='.urlencode($randomseckey).'&website='.urlencode($ws).'&pageref=paymentko&fulltag='.$FULLTAG; } dol_syslog("Now do a redirect using a Location:".$ext_urlko, LOG_DEBUG, 0, '_payment');