Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into

develop
This commit is contained in:
Laurent Destailleur 2025-04-22 03:57:47 +02:00
commit 5e064f32e2
6 changed files with 208 additions and 61 deletions

View file

@ -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 '</td>';
}
// Filter: ext_payment_id
if (!empty($arrayfields['p.ext_payment_id']['checked'])) {
print '<td class="liste_titre">';
//print '<input class="flat maxwidth150" type="text" name="search_ext_payment_id" value="'.dol_escape_htmltag($search_ext_payment_id).'">';
print '</td>';
}
// Filter: ext_payment_site
if (!empty($arrayfields['p.ext_payment_site']['checked'])) {
print '<td class="liste_titre">';
//print '<input class="flat maxwidth150" type="text" name="search_ext_payment_site" value="'.dol_escape_htmltag($search_payment_site).'">';
print '</td>';
}
// Filter: Status (only placeholder)
if (!empty($arrayfields['p.statut']['checked'])) {
print '<td class="liste_titre right">';
@ -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 '<td class="tdoverflowmax200" title="'.dolPrintHTMLForAttribute($objp->ext_payment_id).'">';
print dolPrintHTML($objp->ext_payment_id).'</span>';
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}
// ext_payment_site
if (!empty($arrayfields['p.ext_payment_site']['checked'])) {
print '<td class="tdoverflowmax200" title="'.dolPrintHTMLForAttribute($objp->ext_payment_site).'">';
print dolPrintHTML($objp->ext_payment_site).'</span>';
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}
// Status
if (!empty($arrayfields['p.statut']['checked'])) {
print '<td class="right">';

View file

@ -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

View file

@ -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');

View file

@ -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');

View file

@ -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 = '<link rel="stylesheet" type="text/css" href="' . getDolGlobalString('ONLINE_PAYMENT_CSS_URL').'?lang='.$langs->defaultlang.'">'."\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');

View file

@ -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);