Work on SEPA Stripe Payments

This commit is contained in:
Laurent Destailleur 2023-02-24 23:15:54 +01:00
parent d49caabe51
commit 62c6178269
7 changed files with 199 additions and 333 deletions

View File

@ -325,7 +325,7 @@ if ($object->id > 0) {
$sql .= " WHERE fk_facture = ".((int) $object->id);
}
$sql .= " AND pfd.traite = 0";
$sql .= " AND pfd.ext_payment_id IS NULL";
$sql .= " AND pfd.type = 'ban'";
$sql .= " ORDER BY pfd.date_demande DESC";
$resql = $db->query($sql);
@ -700,7 +700,7 @@ if ($object->id > 0) {
$sql .= " WHERE fk_facture = ".((int) $object->id);
}
$sql .= " AND pfd.traite = 0";
$sql .= " AND pfd.ext_payment_id IS NULL";
$sql .= " AND pfd.type = 'ban'";
$resql = $db->query($sql);
if ($resql) {
@ -817,7 +817,8 @@ if ($object->id > 0) {
print '</tr>';
$sql = "SELECT pfd.rowid, pfd.traite, pfd.date_demande as date_demande,";
$sql .= " pfd.date_traite as date_traite, pfd.amount,";
$sql .= " pfd.date_traite as date_traite, pfd.amount, pfd.fk_prelevement_bons,";
$sql .= " pb.ref, pb.date_trans, pb.method_trans, pb.credite, pb.date_credit, pb.datec, pb.statut as status,";
$sql .= " u.rowid as user_id, u.email, u.lastname, u.firstname, u.login, u.statut as user_status";
$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pfd";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on pfd.fk_user_demande = u.rowid";
@ -828,7 +829,7 @@ if ($object->id > 0) {
$sql .= " WHERE fk_facture = ".((int) $object->id);
}
$sql .= " AND pfd.traite = 0";
$sql .= " AND pfd.ext_payment_id IS NULL";
$sql .= " AND pfd.type = 'ban'";
$sql .= " ORDER BY pfd.date_demande DESC";
$resql = $db->query($sql);
@ -868,19 +869,36 @@ if ($object->id > 0) {
print '<td class="center"><span class="opacitymedium">'.$langs->trans("OrderWaiting").'</span></td>';
// Link to make payment now
print '<td>';
print '<td class="center">';
if ($obj->fk_prelevement_bons > 0) {
$withdrawreceipt = new BonPrelevement($db);
$withdrawreceipt->id = $obj->fk_prelevement_bons;
$withdrawreceipt->ref = $obj->ref;
$withdrawreceipt->date_trans = $db->jdate($obj->date_trans);
$withdrawreceipt->date_credit = $db->jdate($obj->date_credit);
$withdrawreceipt->date_creation = $db->jdate($obj->datec);
$withdrawreceipt->statut = $obj->status;
$withdrawreceipt->status = $obj->status;
//$withdrawreceipt->credite = $db->jdate($obj->credite);
print $withdrawreceipt->getNomUrl(1);
}
if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT)) {
$langs->load("stripe");
if ($obj->fk_prelevement_bons > 0) {
print ' &nbsp; ';
}
print '<a href="'.$_SERVER["PHP_SELF"].'?action=sepastripepayment&paymentservice=stripesepa&token='.newToken().'&did='.$obj->rowid.'&id='.$object->id.'&type='.urlencode($type).'">'.img_picto('', 'stripe', 'class="pictofixedwidth"').$langs->trans("RequestDirectDebitWithStripe").'</a>';
}
print '</td>';
//
print '<td align="center">-</td>';
print '<td class="center">-</td>';
// Actions
print '<td class="right">';
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=delete&token='.newToken().'&did='.$obj->rowid.'&type='.$type.'">';
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=delete&token='.newToken().'&did='.$obj->rowid.'&type='.urlencode($type).'">';
print img_delete();
print '</a></td>';
@ -897,7 +915,7 @@ if ($object->id > 0) {
// Past requests
$sql = "SELECT pfd.rowid, pfd.traite, pfd.date_demande, pfd.date_traite, pfd.fk_prelevement_bons, pfd.amount,";
$sql .= " pb.ref,";
$sql .= " pb.ref, pb.date_trans, pb.method_trans, pb.credite, pb.date_credit, pb.datec, pb.statut as status,";
$sql .= " u.rowid as user_id, u.email, u.lastname, u.firstname, u.login, u.statut as user_status";
$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pfd";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on pfd.fk_user_demande = u.rowid";
@ -908,7 +926,7 @@ if ($object->id > 0) {
$sql .= " WHERE fk_facture = ".((int) $object->id);
}
$sql .= " AND pfd.traite = 1";
$sql .= " AND pfd.ext_payment_id IS NULL";
$sql .= " AND pfd.type = 'ban'";
$sql .= " ORDER BY pfd.date_demande DESC";
$result = $db->query($sql);
@ -944,7 +962,7 @@ if ($object->id > 0) {
print '<td class="center"><span class="amount">'.price($obj->amount).'</span></td>';
// Date process
print '<td class="center">'.dol_print_date($db->jdate($obj->date_traite), 'day')."</td>\n";
print '<td class="center">'.dol_print_date($db->jdate($obj->date_traite), 'dayhour', 'tzuserrel')."</td>\n";
// Link to payment request done
print '<td class="center">';
@ -952,6 +970,13 @@ if ($object->id > 0) {
$withdrawreceipt = new BonPrelevement($db);
$withdrawreceipt->id = $obj->fk_prelevement_bons;
$withdrawreceipt->ref = $obj->ref;
$withdrawreceipt->date_trans = $db->jdate($obj->date_trans);
$withdrawreceipt->date_credit = $db->jdate($obj->date_credit);
$withdrawreceipt->date_creation = $db->jdate($obj->datec);
$withdrawreceipt->statut = $obj->status;
$withdrawreceipt->status = $obj->status;
//$withdrawreceipt->credite = $db->jdate($obj->credite);
print $withdrawreceipt->getNomUrl(1);
}
print "</td>\n";

View File

@ -128,9 +128,7 @@ class BonPrelevement extends CommonObject
$this->factures = array();
$this->methodes_trans = array();
$this->methodes_trans[0] = "Internet";
$this->methodes_trans = array(0 => 'Internet', 2 => 'Email', 3 => 'Api');
$this->fetched = 0;
}
@ -509,7 +507,7 @@ class BonPrelevement extends CommonObject
*
* @param User $user id of user
* @param int $date date of action
* @param string $method method of transmision to bank
* @param string $method method of transmision to bank (0=Internet, 1=Api...)
* @return int >0 if OK, <0 if KO
*/
public function set_infotrans($user, $date, $method)
@ -737,7 +735,11 @@ class BonPrelevement extends CommonObject
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Create a direct debit order or a credit transfer order
* Create a BAN payment order:
* - Select waiting requests from prelevement_demande (or use $did if provided)
* - Check BAN values
* - Then create a direct debit order or a credit transfer order
* - Link the order with the prelevement_demande lines
* TODO delete params banque and agence when not necessary
*
* @param int $banque dolibarr mysoc bank
@ -747,7 +749,7 @@ class BonPrelevement extends CommonObject
* @param string $executiondate Date to execute the transfer
* @param int $notrigger Disable triggers
* @param string $type 'direct-debit' or 'bank-transfer'
* @param int $did ID of payment request
* @param int $did ID of an existing payment request. If $did is defined, no entry
* @return int <0 if KO, No of invoice included into file if OK
*/
public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit', $did = 0)
@ -755,7 +757,7 @@ class BonPrelevement extends CommonObject
// phpcs:enable
global $conf, $langs, $user;
dol_syslog(__METHOD__."::Bank=".$banque." Office=".$agence." mode=".$mode." format=".$format, LOG_DEBUG);
dol_syslog(__METHOD__." Bank=".$banque." Office=".$agence." mode=".$mode." format=".$format, LOG_DEBUG);
require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php";
require_once DOL_DOCUMENT_ROOT."/societe/class/societe.class.php";
@ -815,7 +817,7 @@ class BonPrelevement extends CommonObject
if ($did > 0) {
$sql .= " AND pfd.rowid = ".((int) $did);
}
dol_syslog(__METHOD__."::Read invoices,", LOG_DEBUG);
dol_syslog(__METHOD__." Read invoices,", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
@ -827,17 +829,17 @@ class BonPrelevement extends CommonObject
$factures[$i] = $row; // All fields
if ($row[7] == 0) {
$error++;
dol_syslog(__METHOD__."::Read invoices error Found a null invoice", LOG_ERR);
dol_syslog(__METHOD__." Read invoices error Found a null invoice", LOG_ERR);
$this->invoice_in_error[$row[0]] = "Error for invoice id ".$row[0].", found a null amount";
break;
}
$i++;
}
$this->db->free($resql);
dol_syslog(__METHOD__."::Read invoices, ".$i." invoices to withdraw", LOG_DEBUG);
dol_syslog(__METHOD__." Read invoices, ".$i." invoices to withdraw", LOG_DEBUG);
} else {
$error++;
dol_syslog(__METHOD__."::Read invoices error ".$this->db->error(), LOG_ERR);
dol_syslog(__METHOD__." Read invoices error ".$this->db->error(), LOG_ERR);
}
}
@ -847,7 +849,7 @@ class BonPrelevement extends CommonObject
// Check BAN
$i = 0;
dol_syslog(__METHOD__."::Check BAN", LOG_DEBUG);
dol_syslog(__METHOD__." Check BAN", LOG_DEBUG);
if (count($factures) > 0) {
foreach ($factures as $key => $fac) {
@ -878,19 +880,19 @@ class BonPrelevement extends CommonObject
$i++;
//dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
} else {
dol_syslog(__METHOD__."::Check BAN Error on default bank number IBAN/BIC for thirdparty reported by verif() ".$tmpinvoice->socid." ".$soc->name, LOG_WARNING);
dol_syslog(__METHOD__." Check BAN Error on default bank number IBAN/BIC for thirdparty reported by verif() ".$tmpinvoice->socid." ".$soc->name, LOG_WARNING);
$this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
$this->thirdparty_in_error[$soc->id] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
}
} else {
dol_syslog(__METHOD__."::Check BAN Failed to read company", LOG_WARNING);
dol_syslog(__METHOD__." Check BAN Failed to read company", LOG_WARNING);
}
} else {
dol_syslog(__METHOD__."::Check BAN Failed to read invoice", LOG_WARNING);
dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
}
}
} else {
dol_syslog(__METHOD__."::Check BAN No invoice to process", LOG_WARNING);
dol_syslog(__METHOD__." Check BAN No invoice to process", LOG_WARNING);
}
}
@ -934,13 +936,14 @@ class BonPrelevement extends CommonObject
if (!$error) {
$ref = substr($year, -2).$month;
// Get next free nuber for the ref of bon
$sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons";
$sql .= " WHERE ref LIKE '_".$this->db->escape($ref)."%'";
$sql .= " AND entity = ".((int) $conf->entity);
$sql .= " ORDER BY ref DESC LIMIT 1";
dol_syslog(get_class($this)."::create", LOG_DEBUG);
dol_syslog(get_class($this)." get next free number", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
@ -964,7 +967,7 @@ class BonPrelevement extends CommonObject
$this->filename = $dir.'/'.$ref.'.xml';
// Create withdraw receipt in database
// Create withdraw order in database
$sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_bons (";
$sql .= "ref, entity, datec, type";
$sql .= ") VALUES (";
@ -981,11 +984,11 @@ class BonPrelevement extends CommonObject
$this->ref = $ref;
} else {
$error++;
dol_syslog(__METHOD__."::Create withdraw receipt ".$this->db->lasterror(), LOG_ERR);
dol_syslog(__METHOD__." Create withdraw receipt ".$this->db->lasterror(), LOG_ERR);
}
} else {
$error++;
dol_syslog(__METHOD__."::Get last withdraw receipt ".$this->db->lasterror(), LOG_ERR);
dol_syslog(__METHOD__." Get last withdraw receipt ".$this->db->lasterror(), LOG_ERR);
}
}
@ -996,9 +999,7 @@ class BonPrelevement extends CommonObject
$fact = new FactureFournisseur($this->db);
}
/*
* Create withdrawal receipt in database
*/
// Add lines for the bon
if (count($factures_prev) > 0) {
foreach ($factures_prev as $fac) { // Add a link in database for each invoice
// Fetch invoice
@ -1009,7 +1010,7 @@ class BonPrelevement extends CommonObject
}
/*
* Add standing order. This add record into llx_prelevement_lignes
* Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
*
* $fac[0] : invoice_id
* $fac[1] : ???
@ -1037,7 +1038,7 @@ class BonPrelevement extends CommonObject
if (!$resql) {
$error++;
$this->errors[] = $this->db->lasterror();
dol_syslog(__METHOD__."::Update Error=".$this->db->lasterror(), LOG_ERR);
dol_syslog(__METHOD__." Update Error=".$this->db->lasterror(), LOG_ERR);
}
}
}
@ -1048,7 +1049,7 @@ class BonPrelevement extends CommonObject
* Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
*/
dol_syslog(__METHOD__."::Init direct debit or credit transfer file for ".count($factures_prev)." invoices", LOG_DEBUG);
dol_syslog(__METHOD__." Init direct debit or credit transfer file for ".count($factures_prev)." invoices", LOG_DEBUG);
if (count($factures_prev) > 0) {
$this->date_echeance = $datetimeprev;
@ -1085,7 +1086,7 @@ class BonPrelevement extends CommonObject
$error++;
}
}
dol_syslog(__METHOD__."::End withdraw receipt, file ".$this->filename, LOG_DEBUG);
dol_syslog(__METHOD__." Bank order file has been generated under filename ".$this->filename, LOG_DEBUG);
}
//var_dump($this->total);exit;
@ -1101,7 +1102,7 @@ class BonPrelevement extends CommonObject
$resql = $this->db->query($sql);
if (!$resql) {
$error++;
dol_syslog(__METHOD__."::Error update total: ".$this->db->error(), LOG_ERR);
dol_syslog(__METHOD__." Error update total: ".$this->db->error(), LOG_ERR);
}
}
@ -1226,12 +1227,15 @@ class BonPrelevement extends CommonObject
$labeltoshow = 'PaymentByBankTransfer';
}
$label = '<u>'.$langs->trans($labeltoshow).'</u>';
$label = img_picto('', $this->picto).' <u>'.$langs->trans($labeltoshow).'</u> '.$this->getLibStatut(5);
$label .= '<br>';
$label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
if (isset($this->statut)) {
$label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
if (isset($this->date_trans)) {
$label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
}
/*if (isset($this->date_credit)) {
$label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
}*/
$url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
if (!empty($this->type) && $this->type == 'bank-transfer') {

View File

@ -789,7 +789,7 @@ abstract class CommonInvoice extends CommonObject
} else {
$sql .= " WHERE fk_facture = ".((int) $this->id);
}
$sql .= " AND ext_payment_id IS NULL"; // To exclude record done for some online payments
$sql .= " AND type = 'ban'"; // To exclude record done for some online payments
$sql .= " AND traite = 0";
dol_syslog(get_class($this)."::demande_prelevement", LOG_DEBUG);
@ -819,7 +819,7 @@ abstract class CommonInvoice extends CommonObject
} else {
$sql .= 'fk_facture, ';
}
$sql .= ' amount, date_demande, fk_user_demande, code_banque, code_guichet, number, cle_rib, sourcetype, entity)';
$sql .= ' amount, date_demande, fk_user_demande, code_banque, code_guichet, number, cle_rib, sourcetype, type, entity)';
$sql .= " VALUES (".((int) $this->id);
$sql .= ", ".((float) price2num($amount));
$sql .= ", '".$this->db->idate($now)."'";
@ -829,6 +829,7 @@ abstract class CommonInvoice extends CommonObject
$sql .= ", '".$this->db->escape($bac->number)."'";
$sql .= ", '".$this->db->escape($bac->cle_rib)."'";
$sql .= ", '".$this->db->escape($sourcetype)."'";
$sql .= ", 'ban'";
$sql .= ", ".((int) $conf->entity);
$sql .= ")";
@ -876,11 +877,11 @@ abstract class CommonInvoice extends CommonObject
/**
* Create a withdrawal request, from a prelevement_demande, to Stripe for a direct debit order or a credit transfer order.
* Use the remain to pay excluding all existing open direct debit requests.
* Create a payment order for a prelevement_demande
* Then send the payment order to Stripe (for a direct debit order or a credit transfer order).
*
* @param User $fuser User asking the direct debit transfer
* @param int $did ID of payment request
* @param int $did ID of unitary payment request to pay
* @param string $type 'direct-debit' or 'bank-transfer'
* @param string $sourcetype Source ('facture' or 'supplier_invoice')
* @return int <0 if KO, >0 if OK
@ -896,11 +897,12 @@ abstract class CommonInvoice extends CommonObject
$error = 0;
dol_syslog(get_class($this)."::makeStripeSepaRequest 0", LOG_DEBUG);
dol_syslog(get_class($this)."::makeStripeSepaRequest start", LOG_DEBUG);
if ($this->statut > self::STATUS_DRAFT && $this->paye == 0) {
// Get the default payment mode for BAN payment
require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
$bac = new CompanyBankAccount($this->db);
$bac = new CompanyBankAccount($this->db); // table societe_rib
$result = $bac->fetch(0, $this->socid, 1, 'ban');
if ($result <= 0 || empty($bac->id)) {
$this->error = $langs->trans("ThirdpartyHasNoDefaultBanAccount");
@ -909,13 +911,14 @@ abstract class CommonInvoice extends CommonObject
return -1;
}
$sql = "SELECT rowid, date_demande, amount, fk_facture, fk_facture_fourn";
// Load the request to process
$sql = "SELECT rowid, date_demande, amount, fk_facture, fk_facture_fourn, fk_prelevement_bons";
$sql .= " FROM ".$this->db->prefix()."prelevement_demande";
$sql .= " WHERE rowid = ".((int) $did);
$sql .= " AND fk_facture = ".((int) $this->id); // Add a protection to not pay another invoice than current one
$sql .= " AND traite = 0"; // Add a protection to not process twice
dol_syslog(get_class($this)."::makeStripeSepaRequest 1", LOG_DEBUG);
dol_syslog(get_class($this)."::makeStripeSepaRequest load requests to process", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$obj = $this->db->fetch_object($resql);
@ -924,30 +927,16 @@ abstract class CommonInvoice extends CommonObject
return -2;
}
//
// amount to pay
$amount = $obj->amount;
$now = dol_now();
$totalpaye = $this->getSommePaiement();
$totalcreditnotes = $this->getSumCreditNotesUsed();
$totaldeposits = $this->getSumDepositsUsed();
//print "totalpaye=".$totalpaye." totalcreditnotes=".$totalcreditnotes." totaldeposts=".$totaldeposits;
// We can also use bcadd to avoid pb with floating points
// For example print 239.2 - 229.3 - 9.9; does not return 0.
//$resteapayer=bcadd($this->total_ttc,$totalpaye,$conf->global->MAIN_MAX_DECIMALS_TOT);
//$resteapayer=bcadd($resteapayer,$totalavoir,$conf->global->MAIN_MAX_DECIMALS_TOT);
$amounttocheck = price2num($this->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits, 'MT');
// TODO We can compare $amount and $amounttocheck
if (is_numeric($amount) && $amount != 0) {
require_once DOL_DOCUMENT_ROOT.'/societe/class/companypaymentmode.class.php';
$companypaymentmode = new CompanyPaymentMode($this->db);
$companypaymentmode = new CompanyPaymentMode($this->db); // table societe_rib
$companypaymentmode->fetch($bac->id);
// Start code for Stripe
// TODO This must come from a parameter ? or the method may not work as expected when used from a batch ?
$service = 'StripeTest';
$servicestatus = 0;
if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) {
@ -955,26 +944,27 @@ abstract class CommonInvoice extends CommonObject
$servicestatus = 1;
}
dol_syslog("makeStripeSepaRequest amount = ".$amount." service=" . $service . " servicestatus=" . $servicestatus . " thirdparty_id=" . $this->socid . " companypaymentmode=" . $companypaymentmode->id);
dol_syslog("makeStripeSepaRequest amount = ".$amount." service=" . $service . " servicestatus=" . $servicestatus . " thirdparty_id=" . $this->socid." did=".$did);
$this->stripechargedone = 0;
$this->stripechargeerror = 0;
$now = dol_now();
$currency = $conf->currency;
global $stripearrayofkeysbyenv;
global $savstripearrayofkeysbyenv;
$errorforinvoice = 0; // We reset the $errorforinvoice at each invoice loop
$this->fetch_thirdparty();
dol_syslog("--- Process invoice thirdparty_id=" . $this->id . ", thirdparty_name=" . $this->thirdparty->name . " id=" . $this->id . ", ref=" . $this->ref . ", datef=" . dol_print_date($this->date, 'dayhourlog'), LOG_DEBUG);
dol_syslog("--- Process payment request thirdparty_id=" . $this->thirdparty->id . ", thirdparty_name=" . $this->thirdparty->name . " ban id=" . $bac->id, LOG_DEBUG);
$alreadypayed = $this->getSommePaiement();
$amount_credit_notes_included = $this->getSumCreditNotesUsed();
$amounttopay = $this->total_ttc - $alreadypayed - $amount_credit_notes_included;
//$alreadypayed = $this->getSommePaiement();
//$amount_credit_notes_included = $this->getSumCreditNotesUsed();
//$amounttopay = $this->total_ttc - $alreadypayed - $amount_credit_notes_included;
$amounttopay = $amount;
// Correct the amount according to unit of currency
// See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
@ -984,7 +974,41 @@ abstract class CommonInvoice extends CommonObject
$amountstripe = $amountstripe * 100;
}
if ($amountstripe > 0) {
$this->db->begin();
// Create a prelevement_bon
$bon = new BonPrelevement($this->db);
if (empty($obj->fk_prelevement_bons)) {
// This create record into llx_prelevment_bons and update link with llx_prelevement_demande
$nbinvoices = $bon->create(0, 0, 'real', 'ALL', '', 0, 'direct-debit', $did);
if ($nbinvoices <= 0) {
$error++;
$errorforinvoice++;
dol_syslog("Error on BonPrelevement creation", LOG_ERR);
$this->errors[] = "Error on BonPrelevement creation";
}
/*
if (!$error) {
// Update the direct debit payment request of the processed request to save the id of the prelevement_bon
$sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande SET";
$sql .= " fk_prelevement_bons = ".((int) $bon->id);
$sql .= " WHERE rowid = ".((int) $did);
$result = $this->db->query($sql);
if ($result < 0) {
$error++;
$this->errors[] = "Error on updateing fk_prelevement_bons to ".$bon->id;
}
}
*/
} else {
$error++;
$errorforinvoice++;
dol_syslog("Error Line already part of a bank payment order", LOG_ERR);
$this->errors[] = "The line is already included into a bank payment order. Delete the bank payment order first.";
}
if (!$error && $amountstripe > 0) {
try {
//var_dump($companypaymentmode);
dol_syslog("We will try to pay with companypaymentmodeid=" . $companypaymentmode->id . " stripe_card_ref=" . $companypaymentmode->stripe_card_ref . " mode=" . $companypaymentmode->status, LOG_DEBUG);
@ -996,94 +1020,26 @@ abstract class CommonInvoice extends CommonObject
// So it inits or erases the $stripearrayofkeysbyenv
$stripe = new Stripe($this->db);
if (empty($savstripearrayofkeysbyenv)) {
$savstripearrayofkeysbyenv = $stripearrayofkeysbyenv;
}
dol_syslog("makeStripeSepaRequest Current Stripe environment is " . $stripearrayofkeysbyenv[$servicestatus]['publishable_key']);
dol_syslog("makeStripeSepaRequest Current Saved Stripe environment is " . $savstripearrayofkeysbyenv[$servicestatus]['publishable_key']);
$foundalternativestripeaccount = '';
// Force stripe to another value (by default this value is empty)
if (!empty($thirdparty->array_options['options_stripeaccount'])) {
dol_syslog("makeStripeSepaRequest The thirdparty id=" . $thirdparty->id . " has a dedicated Stripe Account, so we switch to it.");
$tmparray = explode('@', $thirdparty->array_options['options_stripeaccount']);
if (!empty($tmparray[1])) {
$tmparray2 = explode(':', $tmparray[1]);
if (!empty($tmparray2[3])) {
$stripearrayofkeysbyenv = [
0 => [
"publishable_key" => $tmparray2[0],
"secret_key" => $tmparray2[1]
],
1 => [
"publishable_key" => $tmparray2[2],
"secret_key" => $tmparray2[3]
]
];
$stripearrayofkeys = $stripearrayofkeysbyenv[$servicestatus];
\Stripe\Stripe::setApiKey($stripearrayofkeys['secret_key']);
$foundalternativestripeaccount = $tmparray[0]; // Store the customer id
dol_syslog("We use now customer=" . $foundalternativestripeaccount . " publishable_key=" . $stripearrayofkeys['publishable_key'], LOG_DEBUG);
}
}
if (!$foundalternativestripeaccount) {
$stripearrayofkeysbyenv = $savstripearrayofkeysbyenv;
$stripearrayofkeys = $savstripearrayofkeysbyenv[$servicestatus];
\Stripe\Stripe::setApiKey($stripearrayofkeys['secret_key']);
dol_syslog("We found a bad value for Stripe Account for thirdparty id=" . $thirdparty->id . ", so we ignore it and keep using the global one, so " . $stripearrayofkeys['publishable_key'], LOG_WARNING);
}
} else {
$stripearrayofkeysbyenv = $savstripearrayofkeysbyenv;
$stripearrayofkeys = $savstripearrayofkeysbyenv[$servicestatus];
\Stripe\Stripe::setApiKey($stripearrayofkeys['secret_key']);
dol_syslog("The thirdparty id=" . $thirdparty->id . " has no dedicated Stripe Account, so we use global one, so " . json_encode($stripearrayofkeys), LOG_DEBUG);
}
$stripearrayofkeys = $stripearrayofkeysbyenv[$servicestatus];
\Stripe\Stripe::setApiKey($stripearrayofkeys['secret_key']);
dol_syslog("makeStripeSepaRequest get stripe connet account", LOG_DEBUG);
$stripeacc = $stripe->getStripeAccount($service, $this->socid); // Get Stripe OAuth connect account if it exists (no network access here)
dol_syslog("makeStripeSepaRequest get stripe connect account return " . json_encode($stripeacc), LOG_DEBUG);
if ($foundalternativestripeaccount) {
if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
$customer = \Stripe\Customer::retrieve(['id' => "$foundalternativestripeaccount", 'expand[]' => 'sources']);
} else {
$customer = \Stripe\Customer::retrieve(['id' => "$foundalternativestripeaccount", 'expand[]' => 'sources'], ["stripe_account" => $stripeacc]);
}
} else {
$customer = $stripe->customerStripe($thirdparty, $stripeacc, $servicestatus, 0);
if (empty($customer) && !empty($stripe->error)) {
$this->errors[] = $stripe->error;
}
/*if (!empty($customer) && empty($customer->sources)) {
$customer = null;
$this->errors[] = '\Stripe\Customer::retrieve did not returned the sources';
}*/
$customer = $stripe->customerStripe($thirdparty, $stripeacc, $servicestatus, 0);
if (empty($customer) && !empty($stripe->error)) {
$this->errors[] = $stripe->error;
}
// $nbhoursbetweentries = (empty($conf->global->SELLYOURSAAS_NBHOURSBETWEENTRIES) ? 49 : $conf->global->SELLYOURSAAS_NBHOURSBETWEENTRIES); // Must have more that 48 hours + 1 between each try (so 1 try every 3 daily batch)
// $nbdaysbeforeendoftries = (empty($conf->global->SELLYOURSAAS_NBDAYSBEFOREENDOFTRIES) ? 35 : $conf->global->SELLYOURSAAS_NBDAYSBEFOREENDOFTRIES);
$labeltouse = '';
$postactionmessages = [];
if ($resultthirdparty > 0 && !empty($customer)) {
if (!$error && !empty($this->array_options['options_delayautopayment']) && $this->array_options['options_delayautopayment'] > $now && empty($calledinmyaccountcontext)) {
$errmsg = 'Payment try was canceled (invoice qualified by the automatic payment was delayed after the ' . dol_print_date($this->array_options['options_delayautopayment'], 'day') . ')';
dol_syslog($errmsg, LOG_DEBUG);
$error++;
$errorforinvoice++;
$this->errors[] = $errmsg;
}
if (!$error) { // Payment was not canceled
$sepaMode = false;
$stripecard = null;
@ -1096,8 +1052,8 @@ abstract class CommonInvoice extends CommonObject
}
if ($stripecard) { // Can be src_... (for sepa) or pm_... (new card mode). Note that card_... (old card mode) should not happen here.
$FULLTAG = 'INV=' . $this->id . '-CUS=' . $thirdparty->id;
$description = 'Stripe payment from makeStripeSepaRequest: ' . $FULLTAG . ' ref=' . $this->ref;
$FULLTAG = 'DID='.$did.'-INV=' . $this->id . '-CUS=' . $thirdparty->id;
$description = 'Stripe payment from makeStripeSepaRequest: ' . $FULLTAG . ' did='.$did.' ref=' . $this->ref;
$stripefailurecode = '';
$stripefailuremessage = '';
@ -1107,7 +1063,7 @@ abstract class CommonInvoice extends CommonObject
dol_syslog("* Create payment on SEPA " . $stripecard->id . ", amounttopay=" . $amounttopay . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG);
// Create payment intent and charge payment (confirmnow = true)
$paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $this, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1);
$paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $this, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1, 1, $did);
$charge = new stdClass();
@ -1200,17 +1156,6 @@ abstract class CommonInvoice extends CommonObject
$object = $this;
// Send emails
$labeltouse = 'InvoicePaymentSuccess';
$sendemailtocustomer = 1;
if (empty($charge) || $charge->status == 'failed') {
$labeltouse = 'InvoicePaymentFailure';
if ($noemailtocustomeriferror) {
$sendemailtocustomer = 0;
} // $noemailtocustomeriferror is set when error already reported on myaccount screen
}
// Track an event
if (empty($charge) || $charge->status == 'failed') {
$actioncode = 'PAYMENT_STRIPE_KO';
@ -1227,12 +1172,6 @@ abstract class CommonInvoice extends CommonObject
dol_syslog("No direct debit payment method found for this stripe customer " . $customer->id, LOG_WARNING);
$this->errors[] = 'Failed to get direct debit payment method for stripe customer = ' . $customer->id;
$labeltouse = 'InvoicePaymentFailure';
$sendemailtocustomer = 1;
if ($noemailtocustomeriferror) {
$sendemailtocustomer = 0;
} // $noemailtocustomeriferror is set when error already reported on myaccount screen
$description = 'Failed to find or use the payment mode - no credit card defined for the customer account';
$stripefailurecode = 'BADPAYMENTMODE';
$stripefailuremessage = 'Failed to find or use the payment mode - no credit card defined for the customer account';
@ -1244,10 +1183,7 @@ abstract class CommonInvoice extends CommonObject
$extraparams = '';
}
} else {
// If error because payment was canceled for a logical reason, we do nothing (no email and no event added)
$labeltouse = '';
$sendemailtocustomer = 0;
// If error because payment was canceled for a logical reason, we do nothing (no event added)
$description = '';
$stripefailurecode = '';
$stripefailuremessage = '';
@ -1268,12 +1204,6 @@ abstract class CommonInvoice extends CommonObject
$error++;
$errorforinvoice++;
$labeltouse = 'InvoicePaymentFailure';
$sendemailtocustomer = 1;
if ($noemailtocustomeriferror) {
$sendemailtocustomer = 0;
} // $noemailtocustomeriferror is set when error already reported on myaccount screen
$description = 'Failed to find or use your payment mode (no payment mode for this customer id)';
$stripefailurecode = 'BADPAYMENTMODE';
$stripefailuremessage = 'Failed to find or use your payment mode (no payment mode for this customer id)';
@ -1285,121 +1215,8 @@ abstract class CommonInvoice extends CommonObject
$extraparams = '';
}
/*
// Send email + create action after
if ($sendemailtocustomer && $labeltouse) {
dol_syslog("* Send email with result of payment - " . $labeltouse);
// Set output language
$outputlangs = new Translate('', $conf);
$outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang);
$outputlangs->loadLangs(["main", "members", "bills"]);
// Get email content from templae
$arraydefaultmessage = null;
include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
$formmail = new FormMail($this->db);
if (!empty($labeltouse)) {
$arraydefaultmessage = $formmail->getEMailTemplate($this->db, 'facture_send', $user, $outputlangs, 0, 1, $labeltouse);
}
if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
$subject = $arraydefaultmessage->topic;
$msg = $arraydefaultmessage->content;
}
$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
//$substitutionarray['__SELLYOURSAAS_PAYMENT_ERROR_DESC__'] = $stripefailurecode . ' ' . $stripefailuremessage;
complete_substitutions_array($substitutionarray, $outputlangs, $object);
// Set the property ->ref_customer with ref_customer of contract so __REF_CLIENT__ will be replaced in email content
// Search contract linked to invoice
$foundcontract = null;
$this->fetchObjectLinked();
if (is_array($this->linkedObjects['contrat']) && count($this->linkedObjects['contrat']) > 0) {
//dol_sort_array($object->linkedObjects['facture'], 'date');
foreach ($this->linkedObjects['contrat'] as $idcontract => $contract) {
$substitutionarray['__CONTRACT_REF__'] = $contract->ref_customer;
$substitutionarray['__REFCLIENT__'] = $contract->ref_customer; // For backward compatibility
$substitutionarray['__REF_CLIENT__'] = $contract->ref_customer;
$foundcontract = $contract;
break;
}
}
dol_syslog('__DIRECTDOWNLOAD_URL_INVOICE__=' . $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__']);
//erics - erreur de réécriture de l'url de téléchargement direct de la facture ... le lien de base est le bon
//on cherche donc d'ou vien le pb ...
//$urlforsellyoursaasaccount = getRootUrlForAccount($foundcontract);
// if ($urlforsellyoursaasaccount) {
// $tmpforurl = preg_replace('/.*document.php/', '', $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__']);
// if ($tmpforurl) {
// dol_syslog('__DIRECTDOWNLOAD_URL_INVOICE__ cas 1, urlforsellyoursaasaccount=' . $urlforsellyoursaasaccount);
// // $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__'] = $urlforsellyoursaasaccount . '/source/document.php' . $tmpforurl;
// } else {
// dol_syslog('__DIRECTDOWNLOAD_URL_INVOICE__ cas 2, urlforsellyoursaasaccount=' . $urlforsellyoursaasaccount);
// // $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__'] = $urlforsellyoursaasaccount;
// }
// }
$subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs);
$texttosend = make_substitutions($msg, $substitutionarray, $outputlangs);
// Attach a file ?
$file = '';
$listofpaths = [];
$listofnames = [];
$listofmimes = [];
if (is_object($invoice)) {
$invoicediroutput = $conf->facture->dir_output;
//erics - choix du PDF a joindre aux mails
$fileparams = dol_most_recent_file($invoicediroutput . '/' . $this->ref, preg_quote($this->ref, '/') . '[^\-]+*.pdf');
$file = $fileparams['fullname'];
//$file = $invoicediroutput . '/' . $this->ref . '/' . $this->ref . '.pdf';
// $file = ''; // Disable attachment of invoice in emails
if ($file) {
$listofpaths = [$file];
$listofnames = [basename($file)];
$listofmimes = [dol_mimetype($file)];
}
}
$from = "";//$conf->global->SELLYOURSAAS_NOREPLY_EMAIL;
$trackid = 'inv' . $this->id;
$moreinheader = 'X-Dolibarr-Info: makeStripeSepaRequest' . "\r\n";
// Send email (substitutionarray must be done just before this)
include_once DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php';
$mailfile = new CMailFile($subjecttosend, $this->thirdparty->email, $from, $texttosend, $listofpaths, $listofmimes, $listofnames, '', '', 0, -1, '', '', $trackid, $moreinheader);
if ($mailfile->sendfile()) {
$result = 1;
} else {
$this->error = $langs->trans("ErrorFailedToSendMail", $from, $this->thirdparty->email) . '. ' . $mailfile->error;
$result = -1;
}
if ($result < 0) {
$errmsg = $this->error;
$postactionmessages[] = $errmsg;
$ispostactionok = -1;
} else {
if ($file) {
$postactionmessages[] = 'Email sent to thirdparty (to ' . $this->thirdparty->email . ' with invoice document attached: ' . $file . ', language = ' . $outputlangs->defaultlang . ')';
} else {
$postactionmessages[] = 'Email sent to thirdparty (to ' . $this->thirdparty->email . ' without any attached document, language = ' . $outputlangs->defaultlang . ')';
}
}
}
*/
if ($description) {
dol_syslog("* Record event for payment result - " . $description);
dol_syslog("* Record event for credit transfer or direct debit request result - " . $description);
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
// Insert record of payment (success or error)
@ -1448,18 +1265,9 @@ abstract class CommonInvoice extends CommonObject
$this->errors[] = "Remain to pay is null for the invoice " . $this->id . " " . $this->ref . ". Why is the invoice not classified 'Paid' ?";
}
// TODO Create a prelevement_bon and set its status to sent instead of this
$bon = new BonPrelevement($this->db);
$nbinvoices = $bon->create(0, 0, 'real', 'ALL', '', 0, 'direct-debit', $did);
if ($nbinvoices <= 0) {
$error++;
$errorforinvoice++;
dol_syslog("Error on BonPrelevement creation", LOG_ERR);
$this->errors[] = "Error on BonPrelevement creation";
}
if (!$errorforinvoice) {
$result = $bon->set_infotrans($user, $now, 'internet');
// Set status of the order to "Transferred" with method 'api'
if (!$error && !$errorforinvoice) {
$result = $bon->set_infotrans($user, $now, 3);
if ($result < 0) {
$error++;
$errorforinvoice++;
@ -1468,19 +1276,14 @@ abstract class CommonInvoice extends CommonObject
}
}
if (!$errorforinvoice) {
$idtransferfile = $bon->id;
if (!$error && !$errorforinvoice) {
// Update the direct debit payment request of the processed invoice to save the id of the prelevement_bon
$sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande SET";
$sql .= " traite = 1,"; // TODO Remove this
$sql .= " date_traite = '".$this->db->idate(dol_now())."',"; // TODO Remove this
if ($idtransferfile > 0) {
$sql .= " fk_prelevement_bons = ".((int) $idtransferfile);
}
$sql .= " ext_payment_id = '".$this->db->escape($paymentintent->id)."',";
$sql .= " ext_payment_site = '".$this->db->escape($service)."'";
$sql .= " WHERE rowid = ".((int) $did);
dol_syslog(get_class($this)."::makeStripeSepaRequest", LOG_DEBUG);
dol_syslog(get_class($this)."::makeStripeSepaRequest update to save stripe paymentintent ids", LOG_DEBUG);
$resql = $this->db->query($sql);
if (!$resql) {
$this->error = $this->db->lasterror();
@ -1488,19 +1291,26 @@ abstract class CommonInvoice extends CommonObject
$error++;
}
}
if (!$error && !$errorforinvoice) {
$this->db->commit();
} else {
$this->db->rollback();
}
} else {
$this->error = 'WithdrawRequestErrorNilAmount';
dol_syslog(get_class($this).'::makeStripeSepaRequest WithdrawRequestErrorNilAmount');
$error++;
}
/*
if (!$error) {
// Force payment mode of invoice to withdraw
// Force payment mode of the invoice to withdraw
$payment_mode_id = dol_getIdFromCode($this->db, ($type == 'bank-transfer' ? 'VIR' : 'PRE'), 'c_paiement', 'code', 'id', 1);
if ($payment_mode_id > 0) {
$result = $this->setPaymentMethods($payment_mode_id);
}
}
}*/
if ($error) {
return -1;

View File

@ -84,3 +84,5 @@ ALTER TABLE llx_supplier_proposal ADD INDEX idx_supplier_proposal_fk_account(fk_
ALTER TABLE llx_ecm_files ADD COLUMN share_pass varchar(32) after share;
ALTER TABLE llx_prelevement_demande ADD COLUMN type varchar(12) DEFAULT '';
UPDATE llx_prelevement_demande SET type = 'ban' WHERE ext_payment_id IS NULL AND type = '';

View File

@ -36,6 +36,8 @@ create table llx_prelevement_demande
code_guichet varchar(6),
number varchar(255),
cle_rib varchar(5),
type varchar(12) DEFAULT '',
ext_payment_id varchar(255),
ext_payment_site varchar(128)
)ENGINE=innodb;

View File

@ -196,7 +196,6 @@ if ($event->type == 'payout.created') {
return -1;
}
} elseif ($event->type == 'payout.paid') {
global $conf;
$error = 0;
$result = dolibarr_set_const($db, $service."_NEXTPAYOUT", null, 'chaine', 0, '', $conf->entity);
if ($result) {
@ -298,6 +297,8 @@ if ($event->type == 'payout.created') {
$db->query($sql);
$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));
// TODO: create fees
// TODO: Redirect to paymentok.php

View File

@ -341,9 +341,10 @@ class Stripe extends CommonObject
* @param string $payment_method 'pm_....' (if known)
* @param string $off_session If we use an already known payment method to pay when customer is not available during the checkout flow.
* @param string $noidempotency_key Do not use the idempotency_key when creating the PaymentIntent
* @param int $did ID of an existing line into llx_prelevement_demande (Dolibarr intent). If provided, no new line will be created.
* @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found and failed to create
*/
public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false, $payment_method = null, $off_session = 0, $noidempotency_key = 1)
public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false, $payment_method = null, $off_session = 0, $noidempotency_key = 1, $did = 0)
{
global $conf, $user;
@ -530,29 +531,50 @@ class Stripe extends CommonObject
// Store the payment intent
if (is_object($object)) {
$paymentintentalreadyexists = 0;
// Check that payment intent $paymentintent->id is not already recorded.
$sql = "SELECT pi.rowid";
$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pi";
$sql .= " WHERE pi.entity IN (".getEntity('societe').")";
$sql .= " AND pi.ext_payment_site = '".$this->db->escape($service)."'";
$sql .= " AND pi.ext_payment_id = '".$this->db->escape($paymentintent->id)."'";
dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
if ($num) {
$obj = $this->db->fetch_object($resql);
if ($obj) {
$paymentintentalreadyexists++;
}
if ($did > 0) {
// If a payment request line provided, we do not need to recreate one, we just update it
dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
$sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande SET";
$sql .= " ext_payment_site = '".$this->db->escape($service)."',";
$sql .= " ext_payment_id = '".$this->db->escape($paymentintent->id)."'";
$sql .= " WHERE rowid = ".((int) $did);
$resql = $this->db->query($sql);
if ($resql) {
$paymentintentalreadyexists++;
} else {
$error++;
dol_print_error($this->db);
}
} else {
dol_print_error($this->db);
// Check that payment intent $paymentintent->id is not already recorded.
dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
$sql = "SELECT pi.rowid";
$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pi";
$sql .= " WHERE pi.entity IN (".getEntity('societe').")";
$sql .= " AND pi.ext_payment_site = '".$this->db->escape($service)."'";
$sql .= " AND pi.ext_payment_id = '".$this->db->escape($paymentintent->id)."'";
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
if ($num) {
$obj = $this->db->fetch_object($resql);
if ($obj) {
$paymentintentalreadyexists++;
}
}
} else {
$error++;
dol_print_error($this->db);
}
}
// If not, we create it.
if (!$paymentintentalreadyexists) {
if (!$error && !$paymentintentalreadyexists) {
$now = dol_now();
$sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site, amount)";
$sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $user->id).", '".$this->db->escape($paymentintent->id)."', ".((int) $object->id).", '".$this->db->escape($object->element)."', ".((int) $conf->entity).", '".$this->db->escape($service)."', ".((float) $amount).")";