diff --git a/htdocs/compta/paiement/list.php b/htdocs/compta/paiement/list.php index bd94294f2a6..b161d26b7f2 100644 --- a/htdocs/compta/paiement/list.php +++ b/htdocs/compta/paiement/list.php @@ -122,6 +122,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'); @@ -215,7 +217,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"; @@ -301,7 +303,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"; @@ -516,6 +518,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 ''; @@ -589,6 +605,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']++; @@ -799,6 +823,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 c78fe9d4036..6ecbf68776a 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -689,3 +689,5 @@ CumulativeProgression=Cumulative progress INVOICE_ADD_EPC_QR_CODEPay=Scan this QR code to pay with a smartphone supporting payment with EPC QR code. InputValueIsNotAnNumber=Input value is not a number LimitDepositInvoicePossibilityForConsistency=Limit deposit invoice type to keep consistencies between lines (from proposals or orders) +ExtPaymentID=External payment ID +ExtPaymentSite=External payment Site diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index a0d2fe0b05e..fc2e4fd980f 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -69,6 +69,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.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'; @@ -371,6 +372,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'); } } @@ -447,6 +449,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"; @@ -456,27 +459,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((float) $PAYPAL_API_PRICE, $PAYPAL_API_DEVISE, $PAYPAL_PAYMENT_TYPE, $PAYPAL_API_OK, $PAYPAL_API_KO, $FULLTAG); @@ -512,7 +517,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); @@ -779,6 +784,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['paymentkosessioncode'] = $randomseckey; // key between newpayment.php to paymentko.php + + $urlko .= '&paymentkosessioncode='.urlencode($randomseckey); + } else { + $randomseckey = getRandomPassword(true, null, 20); + $_SESSION['paymentoksessioncode'] = $randomseckey; // key between newpayment.php to paymentok.php + + $urlok .= '&paymentoksessioncode='.urlencode($randomseckey); + } } // When using the PaymentIntent API architecture (mode set on by default into conf.class.php) @@ -793,7 +810,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"); @@ -821,16 +838,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['paymentkosessioncode'] = $randomseckey; // key between newpayment.php to paymentko.php + + $urlko .= '&paymentkosessioncode='.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 @@ -839,6 +863,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['paymentoksessioncode'] = $randomseckey; // key between newpayment.php to paymentok.php + + $urlok .= '&paymentoksessioncode='.urlencode($randomseckey); } } @@ -855,7 +886,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"]." 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'); 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 872c1cda625..92a2075d261 100644 --- a/htdocs/public/payment/paymentko.php +++ b/htdocs/public/payment/paymentko.php @@ -166,7 +166,6 @@ if ($ws) { // None - /* * View */ @@ -181,6 +180,7 @@ foreach ($_POST as $k => $v) { } dol_syslog("POST=".$tracepost, 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; @@ -353,15 +353,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?paymentkosessioncode='.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?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 c9f5f05f453..31a957f75af 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -135,7 +135,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); @@ -182,9 +182,15 @@ if ($ws) { } } +/* + * Actions + */ + +// None + /* - * Actions and view + * View */ $now = dol_now(); @@ -200,14 +206,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("paymentoksessioncode=".GETPOST('paymentoksessioncode')." SESSION['paymentoksessioncode']=".$_SESSION['paymentoksessioncode'], LOG_DEBUG, 0, '_payment'); + $head = ''; if (getDolGlobalString('ONLINE_PAYMENT_CSS_URL')) { $head = ''."\n"; @@ -371,8 +380,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 - $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 + } } } @@ -1068,6 +1082,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); @@ -1156,15 +1172,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.'; @@ -1684,6 +1701,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'; @@ -1790,6 +1809,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)); @@ -1868,12 +1889,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'])) { @@ -1881,6 +1896,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.'; @@ -2159,16 +2181,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['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?paymentsessionkey='.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?paymentsessionkey='.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'); @@ -2176,11 +2198,14 @@ if (!empty($doactionsthenredirect)) { exit; } else { // Redirect to an error page + $randomseckey = getRandomPassword(true, null, 20); + $_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?paymentsessionkey='.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?paymentsessionkey='.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'); diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index f47bfb3a322..ea6ec3f5157 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. @@ -861,10 +901,12 @@ if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_P $payment_amountInDolibarr = $obj->amount; $paymentTypeCodeInDolibarr = empty($obj->type) ? 'card' : $obj->type; - dol_syslog("Found the payment intent for card in database (pdid = ".$pdid.")"); + 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);