diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 782e16ec71b..c4ec203eb97 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -1,4 +1,6 @@ * Copyright (C) 2004 Eric Seigne * Copyright (C) 2004-2016 Laurent Destailleur @@ -138,7 +140,7 @@ if (empty($reshook)) { } } - // Payment with Direct Debit Stripe + // Make payment with Direct Debit Stripe if ($action == 'sepastripepayment' && $usercancreate) { $result = $object->makeStripeSepaRequest($user, GETPOST('did', 'int'), 'direct-debit', 'facture'); if ($result < 0) { @@ -153,7 +155,7 @@ if (empty($reshook)) { } } - // payments conditions + // Set payments conditions if ($action == 'setconditions' && $usercancreate) { $object->fetch($id); $object->cond_reglement_code = 0; // To clean property @@ -915,7 +917,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, pb.date_trans, pb.method_trans, pb.credite, pb.date_credit, pb.datec, pb.statut as status,"; + $sql .= " pb.ref, pb.date_trans, pb.method_trans, pb.credite, pb.date_credit, pb.datec, pb.statut as status, pb.fk_bank_account,"; $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"; @@ -929,16 +931,16 @@ if ($object->id > 0) { $sql .= " AND pfd.type = 'ban'"; $sql .= " ORDER BY pfd.date_demande DESC"; - $result = $db->query($sql); - if ($result) { - $num = $db->num_rows($result); + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); $numclosed = $num; $i = 0; $tmpuser = new User($db); while ($i < $num) { - $obj = $db->fetch_object($result); + $obj = $db->fetch_object($resql); $tmpuser->id = $obj->user_id; $tmpuser->login = $obj->login; @@ -975,9 +977,26 @@ if ($object->id > 0) { $withdrawreceipt->date_creation = $db->jdate($obj->datec); $withdrawreceipt->statut = $obj->status; $withdrawreceipt->status = $obj->status; + $withdrawreceipt->fk_bank_account = $obj->fk_bank_account; //$withdrawreceipt->credite = $db->jdate($obj->credite); print $withdrawreceipt->getNomUrl(1); + print ' '; + print $withdrawreceipt->getLibStatut(2); + + // Show the bank account + $fk_bank_account = $withdrawreceipt->fk_bank_account; + if (empty($fk_bank_account)) { + $fk_bank_account = ($object->type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT); + } + if ($fk_bank_account > 0) { + $bankaccount = new Account($db); + $result = $bankaccount->fetch($fk_bank_account); + if ($result > 0) { + print ' - '; + print $bankaccount->getNomUrl(1); + } + } } print "\n"; @@ -995,7 +1014,7 @@ if ($object->id > 0) { print ''.$langs->trans("None").''; } - $db->free($result); + $db->free($resql); } else { dol_print_error($db); } diff --git a/htdocs/compta/prelevement/card.php b/htdocs/compta/prelevement/card.php index 7ccac69b21a..675aeb965e7 100644 --- a/htdocs/compta/prelevement/card.php +++ b/htdocs/compta/prelevement/card.php @@ -215,7 +215,8 @@ if ($id > 0 || $ref) { $result = $acc->fetch($object->fk_bank_account); } else { // For backward compatibility $acc = new Account($db); - $result = $acc->fetch(($object->type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT)); + $fk_bank_account = ($object->type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT); + $result = $acc->fetch($fk_bank_account); } print ''; diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 70836cb50cf..64f359e4f7a 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -92,6 +92,7 @@ class BonPrelevement extends CommonObject public $user_credit; public $type; + public $fk_bank_account; // The bank the receipt is generated for const STATUS_DRAFT = 0; const STATUS_TRANSFERED = 1; @@ -299,6 +300,7 @@ class BonPrelevement extends CommonObject $sql .= ", p.date_credit as date_credit"; $sql .= ", p.fk_user_credit"; $sql .= ", p.type"; + $sql .= ", p.fk_bank_account"; $sql .= ", p.statut as status"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; $sql .= " WHERE p.entity IN (".getEntity('invoice').")"; @@ -328,6 +330,7 @@ class BonPrelevement extends CommonObject $this->user_credit = $obj->fk_user_credit; $this->type = $obj->type; + $this->fk_bank_account = $obj->fk_bank_account; $this->status = $obj->status; $this->statut = $obj->status; // For backward compatibility @@ -369,7 +372,7 @@ class BonPrelevement extends CommonObject $this->db->begin(); - $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_bons "; + $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_bons"; $sql .= " SET fk_user_credit = ".$user->id; $sql .= ", statut = ".self::STATUS_CREDITED; $sql .= ", date_credit = '".$this->db->idate($date)."'"; @@ -383,8 +386,12 @@ class BonPrelevement extends CommonObject $subject = $langs->trans("InfoCreditSubject", $this->ref); $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour')); - //Add payment of withdrawal into bank - $bankaccount = ($this->type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT); + // Add payment of withdrawal into bank + $fk_bank_account = $this->fk_bank_account; + if (empty($fk_bank_account)) { + $fk_bank_account = ($this->type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT); + } + $facs = array(); $amounts = array(); $amountsperthirdparty = array(); @@ -455,7 +462,7 @@ class BonPrelevement extends CommonObject $modeforaddpayment = 'payment'; } - $result = $paiement->addPaymentToBank($user, $modeforaddpayment, '(WithdrawalPayment)', $bankaccount, '', ''); + $result = $paiement->addPaymentToBank($user, $modeforaddpayment, '(WithdrawalPayment)', $fk_bank_account, '', ''); if ($result < 0) { $error++; $this->error = $paiement->error; @@ -742,17 +749,18 @@ class BonPrelevement extends CommonObject * - Link the order with the prelevement_demande lines * TODO delete params banque and agence when not necessary * - * @param int $banque dolibarr mysoc bank - * @param int $agence dolibarr mysoc bank office (guichet) - * @param string $mode real=do action, simu=test only - * @param string $format FRST, RCUR or ALL - * @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 an existing payment request. If $did is defined, no entry - * @return int <0 if KO, No of invoice included into file if OK + * @param int $banque dolibarr mysoc bank + * @param int $agence dolibarr mysoc bank office (guichet) + * @param string $mode real=do action, simu=test only + * @param string $format FRST, RCUR or ALL + * @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 an existing payment request. If $did is defined, no entry + * @param int $fk_bank_account Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0. + * @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) + public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit', $did = 0, $fk_bank_account = 0) { // phpcs:enable global $conf, $langs, $user; @@ -762,6 +770,7 @@ class BonPrelevement extends CommonObject require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php"; require_once DOL_DOCUMENT_ROOT."/societe/class/societe.class.php"; + // Check params if ($type != 'bank-transfer') { if (empty($format)) { $this->error = 'ErrorBadParametersForDirectDebitFileCreate'; @@ -769,6 +778,11 @@ class BonPrelevement extends CommonObject } } + // Clean params + if (empty($fk_bank_account)) { + $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT); + } + $error = 0; $datetimeprev = dol_now('gmt'); @@ -969,12 +983,13 @@ class BonPrelevement extends CommonObject // Create withdraw order in database $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_bons ("; - $sql .= "ref, entity, datec, type"; + $sql .= "ref, entity, datec, type, fk_bank_account"; $sql .= ") VALUES ("; $sql .= "'".$this->db->escape($ref)."'"; $sql .= ", ".((int) $conf->entity); $sql .= ", '".$this->db->idate($now)."'"; $sql .= ", '".($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order')."'"; + $sql .= ", ".((int) $fk_bank_account); $sql .= ")"; $resql = $this->db->query($sql); @@ -1055,12 +1070,8 @@ class BonPrelevement extends CommonObject $this->date_echeance = $datetimeprev; $this->reference_remise = $ref; - $id = $conf->global->PRELEVEMENT_ID_BANKACCOUNT; - if ($type == 'bank-transfer') { - $id = $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT; - } $account = new Account($this->db); - if ($account->fetch($id) > 0) { + if ($account->fetch($fk_bank_account) > 0) { $this->emetteur_code_banque = $account->code_banque; $this->emetteur_code_guichet = $account->code_guichet; $this->emetteur_numero_compte = $account->number; @@ -1382,16 +1393,22 @@ class BonPrelevement extends CommonObject * File is generated with name this->filename * * @param string $format FRST, RCUR or ALL - * @param string $executiondate Date to execute transfer + * @param int $executiondate Timestamp date to execute transfer * @param string $type 'direct-debit' or 'bank-transfer' + * @param int $fk_bank_account Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0. * @return int >=0 if OK, <0 if KO */ - public function generate($format = 'ALL', $executiondate = '', $type = 'direct-debit') + public function generate($format = 'ALL', $executiondate = 0, $type = 'direct-debit', $fk_bank_account = 0) { global $conf, $langs, $mysoc; //TODO: Optimize code to read lines in a single function + // Clean params + if (empty($fk_bank_account)) { + $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT); + } + $result = 0; dol_syslog(get_class($this)."::generate build file=".$this->filename." type=".$type); @@ -1486,7 +1503,7 @@ class BonPrelevement extends CommonObject // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf if ($result != -2) { - $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type); + $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account); } /** @@ -2041,31 +2058,36 @@ class BonPrelevement extends CommonObject * Write sender of request (me). * Note: The tag PmtInf is opened here but closed into caller * - * @param Conf $configuration conf - * @param int $ladate Date - * @param int $nombre 0 or 1 - * @param float $total Total - * @param string $CrLf End of line character - * @param string $format FRST or RCUR or ALL - * @param string $type 'direct-debit' or 'bank-transfer' - * @return string String with SEPA Sender + * @param Conf $configuration conf + * @param int $ladate Date + * @param int $nombre 0 or 1 + * @param float $total Total + * @param string $CrLf End of line character + * @param string $format FRST or RCUR or ALL + * @param string $type 'direct-debit' or 'bank-transfer' + * @param int $fk_bank_account Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0. + * @return string String with SEPA Sender * @see EnregEmetteur() */ - public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit') + public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0) { // phpcs:enable // SEPA INITIALISATION global $conf; + // Clean parameters $dateTime_YMD = dol_print_date($ladate, '%Y%m%d'); $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d'); $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S'); + // Clean params + if (empty($fk_bank_account)) { + $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT); + } + // Get data of bank account - //$id = $configuration->global->PRELEVEMENT_ID_BANKACCOUNT; - $id = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT); $account = new Account($this->db); - if ($account->fetch($id) > 0) { + if ($account->fetch($fk_bank_account) > 0) { $this->emetteur_code_banque = $account->code_banque; $this->emetteur_code_guichet = $account->code_guichet; $this->emetteur_numero_compte = $account->number; @@ -2081,8 +2103,7 @@ class BonPrelevement extends CommonObject // Get pending payments $sql = "SELECT rowid, ref"; - $sql .= " FROM"; - $sql .= " ".MAIN_DB_PREFIX."prelevement_bons as pb"; + $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as pb"; $sql .= " WHERE pb.rowid = ".((int) $this->id); $resql = $this->db->query($sql); @@ -2294,10 +2315,10 @@ class BonPrelevement extends CommonObject } /** - * Return status label of object + * Return status label of object * - * @param int $mode 0=Label, 1=Picto + label, 2=Picto, 3=Label + Picto - * @return string Label + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label */ public function getLibStatut($mode = 0) { diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 677b7c1017a..34eaf847f2c 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -900,7 +900,7 @@ abstract class CommonInvoice extends CommonObject 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 + // Get the default payment mode for BAN payment of the third party require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php'; $bac = new CompanyBankAccount($this->db); // table societe_rib $result = $bac->fetch(0, $this->socid, 1, 'ban'); @@ -974,295 +974,307 @@ abstract class CommonInvoice extends CommonObject $amountstripe = $amountstripe * 100; } + $fk_bank_account = getDolGlobalInt('STRIPE_BANK_ACCOUNT_FOR_PAYMENTS'); + if (!($fk_bank_account > 0)) { + $error++; + $errorforinvoice++; + dol_syslog("Error no bank account defined for Stripe payments", LOG_ERR); + $this->errors[] = "Error bank account for Stripe payments not defined into Stripe module"; + } + $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) { + if (!$error) { + 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, $fk_bank_account); + 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 on BonPrelevement creation", LOG_ERR); - $this->errors[] = "Error on BonPrelevement creation"; + 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) { - // 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); + if (!$error) { + if ($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); - $thirdparty = new Societe($this->db); - $resultthirdparty = $thirdparty->fetch($this->socid); + $thirdparty = new Societe($this->db); + $resultthirdparty = $thirdparty->fetch($this->socid); - include_once DOL_DOCUMENT_ROOT . '/stripe/class/stripe.class.php'; // This include the include of htdocs/stripe/config.php - // So it inits or erases the $stripearrayofkeysbyenv - $stripe = new Stripe($this->db); + include_once DOL_DOCUMENT_ROOT . '/stripe/class/stripe.class.php'; // This include the include of htdocs/stripe/config.php + // So it inits or erases the $stripearrayofkeysbyenv + $stripe = new Stripe($this->db); - dol_syslog("makeStripeSepaRequest Current Stripe environment is " . $stripearrayofkeysbyenv[$servicestatus]['publishable_key']); + dol_syslog("makeStripeSepaRequest Current Stripe environment is " . $stripearrayofkeysbyenv[$servicestatus]['publishable_key']); - $stripearrayofkeys = $stripearrayofkeysbyenv[$servicestatus]; - \Stripe\Stripe::setApiKey($stripearrayofkeys['secret_key']); + $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); + 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); - $customer = $stripe->customerStripe($thirdparty, $stripeacc, $servicestatus, 0); - if (empty($customer) && !empty($stripe->error)) { - $this->errors[] = $stripe->error; - } + $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); - $postactionmessages = []; + // $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); + $postactionmessages = []; - if ($resultthirdparty > 0 && !empty($customer)) { - if (!$error) { // Payment was not canceled - $sepaMode = false; - $stripecard = null; - if ($companypaymentmode->type == 'ban') { - $sepaMode = true; - // Check into societe_rib if a payment mode for Stripe and ban payment exists - // To make a Stripe SEPA payment request, we must have the payment mode source already saved into societe_rib and retreived with ->sepaStripe - // The payment mode source is created when we create the bank account on Stripe with paymentmodes.php?action=create - $stripecard = $stripe->sepaStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0); - } - - if ($stripecard) { // Can be src_... (for sepa) or pm_... (new card mode). Note that card_... (old card mode) should not happen here. - $FULLTAG = 'DID='.$did.'-INV=' . $this->id . '-CUS=' . $thirdparty->id; - $description = 'Stripe payment from makeStripeSepaRequest: ' . $FULLTAG . ' did='.$did.' ref=' . $this->ref; - - $stripefailurecode = ''; - $stripefailuremessage = ''; - $stripefailuredeclinecode = ''; - - // Using new SCA method - 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, 1, $did); - - $charge = new stdClass(); - - if ($paymentintent->status === 'succeeded' || $paymentintent->status === 'processing') { - $charge->status = 'ok'; - $charge->id = $paymentintent->id; - $charge->customer = $customer->id; - } elseif ($paymentintent->status === 'requires_action') { - //paymentintent->status may be => 'requires_action' (no error in such a case) - dol_syslog(var_export($paymentintent, true), LOG_DEBUG); - - $charge->status = 'failed'; - $charge->customer = $customer->id; - $charge->failure_code = $stripe->code; - $charge->failure_message = $stripe->error; - $charge->failure_declinecode = $stripe->declinecode; - $stripefailurecode = $stripe->code; - $stripefailuremessage = 'Action required. Contact the support at ';// . $conf->global->SELLYOURSAAS_MAIN_EMAIL; - $stripefailuredeclinecode = $stripe->declinecode; - } else { - dol_syslog(var_export($paymentintent, true), LOG_DEBUG); - - $charge->status = 'failed'; - $charge->customer = $customer->id; - $charge->failure_code = $stripe->code; - $charge->failure_message = $stripe->error; - $charge->failure_declinecode = $stripe->declinecode; - $stripefailurecode = $stripe->code; - $stripefailuremessage = $stripe->error; - $stripefailuredeclinecode = $stripe->declinecode; + if ($resultthirdparty > 0 && !empty($customer)) { + if (!$error) { // Payment was not canceled + $sepaMode = false; + $stripecard = null; + if ($companypaymentmode->type == 'ban') { + $sepaMode = true; + // Check into societe_rib if a payment mode for Stripe and ban payment exists + // To make a Stripe SEPA payment request, we must have the payment mode source already saved into societe_rib and retreived with ->sepaStripe + // The payment mode source is created when we create the bank account on Stripe with paymentmodes.php?action=create + $stripecard = $stripe->sepaStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0); } - //var_dump("stripefailurecode=".$stripefailurecode." stripefailuremessage=".$stripefailuremessage." stripefailuredeclinecode=".$stripefailuredeclinecode); - //exit; + if ($stripecard) { // Can be src_... (for sepa) or pm_... (new card mode). Note that card_... (old card mode) should not happen here. + $FULLTAG = 'DID='.$did.'-INV=' . $this->id . '-CUS=' . $thirdparty->id; + $description = 'Stripe payment from makeStripeSepaRequest: ' . $FULLTAG . ' did='.$did.' ref=' . $this->ref; + $stripefailurecode = ''; + $stripefailuremessage = ''; + $stripefailuredeclinecode = ''; - // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) - if (empty($charge) || $charge->status == 'failed') { - dol_syslog('Failed to charge payment mode ' . $stripecard->id . ' stripefailurecode=' . $stripefailurecode . ' stripefailuremessage=' . $stripefailuremessage . ' stripefailuredeclinecode=' . $stripefailuredeclinecode, LOG_WARNING); + // Using new SCA method + dol_syslog("* Create payment on SEPA " . $stripecard->id . ", amounttopay=" . $amounttopay . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG); - // Save a stripe payment was in error - $this->stripechargeerror++; + // 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, 1, $did); - $error++; - $errorforinvoice++; - $errmsg = $langs->trans("FailedToChargeCard"); - if (!empty($charge)) { - if ($stripefailuredeclinecode == 'authentication_required') { - $errauthenticationmessage = $langs->trans("ErrSCAAuthentication"); - $errmsg = $errauthenticationmessage; - } elseif (in_array($stripefailuredeclinecode, ['insufficient_funds', 'generic_decline'])) { - $errmsg .= ': ' . $charge->failure_code; - $errmsg .= ($charge->failure_message ? ' - ' : '') . ' ' . $charge->failure_message; - if (empty($stripefailurecode)) { - $stripefailurecode = $charge->failure_code; - } - if (empty($stripefailuremessage)) { - $stripefailuremessage = $charge->failure_message; - } - } else { - $errmsg .= ': failure_code=' . $charge->failure_code; - $errmsg .= ($charge->failure_message ? ' - ' : '') . ' failure_message=' . $charge->failure_message; - if (empty($stripefailurecode)) { - $stripefailurecode = $charge->failure_code; - } - if (empty($stripefailuremessage)) { - $stripefailuremessage = $charge->failure_message; - } - } + $charge = new stdClass(); + + if ($paymentintent->status === 'succeeded' || $paymentintent->status === 'processing') { + $charge->status = 'ok'; + $charge->id = $paymentintent->id; + $charge->customer = $customer->id; + } elseif ($paymentintent->status === 'requires_action') { + //paymentintent->status may be => 'requires_action' (no error in such a case) + dol_syslog(var_export($paymentintent, true), LOG_DEBUG); + + $charge->status = 'failed'; + $charge->customer = $customer->id; + $charge->failure_code = $stripe->code; + $charge->failure_message = $stripe->error; + $charge->failure_declinecode = $stripe->declinecode; + $stripefailurecode = $stripe->code; + $stripefailuremessage = 'Action required. Contact the support at ';// . $conf->global->SELLYOURSAAS_MAIN_EMAIL; + $stripefailuredeclinecode = $stripe->declinecode; } else { - $errmsg .= ': ' . $stripefailurecode . ' - ' . $stripefailuremessage; - $errmsg .= ($stripefailuredeclinecode ? ' - ' . $stripefailuredeclinecode : ''); + dol_syslog(var_export($paymentintent, true), LOG_DEBUG); + + $charge->status = 'failed'; + $charge->customer = $customer->id; + $charge->failure_code = $stripe->code; + $charge->failure_message = $stripe->error; + $charge->failure_declinecode = $stripe->declinecode; + $stripefailurecode = $stripe->code; + $stripefailuremessage = $stripe->error; + $stripefailuredeclinecode = $stripe->declinecode; } - $description = 'Stripe payment ERROR from makeStripeSepaRequest: ' . $FULLTAG; - $postactionmessages[] = $errmsg . ' (' . $stripearrayofkeys['publishable_key'] . ')'; - $this->errors[] = $errmsg; + //var_dump("stripefailurecode=".$stripefailurecode." stripefailuremessage=".$stripefailuremessage." stripefailuredeclinecode=".$stripefailuredeclinecode); + //exit; + + + // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) + if (empty($charge) || $charge->status == 'failed') { + dol_syslog('Failed to charge payment mode ' . $stripecard->id . ' stripefailurecode=' . $stripefailurecode . ' stripefailuremessage=' . $stripefailuremessage . ' stripefailuredeclinecode=' . $stripefailuredeclinecode, LOG_WARNING); + + // Save a stripe payment was in error + $this->stripechargeerror++; + + $error++; + $errorforinvoice++; + $errmsg = $langs->trans("FailedToChargeCard"); + if (!empty($charge)) { + if ($stripefailuredeclinecode == 'authentication_required') { + $errauthenticationmessage = $langs->trans("ErrSCAAuthentication"); + $errmsg = $errauthenticationmessage; + } elseif (in_array($stripefailuredeclinecode, ['insufficient_funds', 'generic_decline'])) { + $errmsg .= ': ' . $charge->failure_code; + $errmsg .= ($charge->failure_message ? ' - ' : '') . ' ' . $charge->failure_message; + if (empty($stripefailurecode)) { + $stripefailurecode = $charge->failure_code; + } + if (empty($stripefailuremessage)) { + $stripefailuremessage = $charge->failure_message; + } + } else { + $errmsg .= ': failure_code=' . $charge->failure_code; + $errmsg .= ($charge->failure_message ? ' - ' : '') . ' failure_message=' . $charge->failure_message; + if (empty($stripefailurecode)) { + $stripefailurecode = $charge->failure_code; + } + if (empty($stripefailuremessage)) { + $stripefailuremessage = $charge->failure_message; + } + } + } else { + $errmsg .= ': ' . $stripefailurecode . ' - ' . $stripefailuremessage; + $errmsg .= ($stripefailuredeclinecode ? ' - ' . $stripefailuredeclinecode : ''); + } + + $description = 'Stripe payment ERROR from makeStripeSepaRequest: ' . $FULLTAG; + $postactionmessages[] = $errmsg . ' (' . $stripearrayofkeys['publishable_key'] . ')'; + $this->errors[] = $errmsg; + } else { + dol_syslog('Successfuly request direct debit ' . $stripecard->id); + + $postactionmessages[] = 'Success to request direct debit (' . $charge->id . ' with ' . $stripearrayofkeys['publishable_key'] . ')'; + + // Save a stripe payment was done in realy life so later we will be able to force a commit on recorded payments + // even if in batch mode (method doTakePaymentStripe), we will always make all action in one transaction with a forced commit. + $this->stripechargedone++; + + // Default description used for label of event. Will be overwrite by another value later. + $description = 'Stripe payment request OK (' . $charge->id . ') from makeStripeSepaRequest: ' . $FULLTAG; + } + + $object = $this; + + // Track an event + if (empty($charge) || $charge->status == 'failed') { + $actioncode = 'PAYMENT_STRIPE_KO'; + $extraparams = $stripefailurecode; + $extraparams .= (($extraparams && $stripefailuremessage) ? ' - ' : '') . $stripefailuremessage; + $extraparams .= (($extraparams && $stripefailuredeclinecode) ? ' - ' : '') . $stripefailuredeclinecode; + } else { + $actioncode = 'PAYMENT_STRIPE_OK'; + $extraparams = ''; + } } else { - dol_syslog('Successfuly request direct debit ' . $stripecard->id); + $error++; + $errorforinvoice++; + 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; - $postactionmessages[] = 'Success to request direct debit (' . $charge->id . ' with ' . $stripearrayofkeys['publishable_key'] . ')'; + $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'; + $postactionmessages[] = $description . ' (' . $stripearrayofkeys['publishable_key'] . ')'; - // Save a stripe payment was done in realy life so later we will be able to force a commit on recorded payments - // even if in batch mode (method doTakePaymentStripe), we will always make all action in one transaction with a forced commit. - $this->stripechargedone++; + $object = $this; - // Default description used for label of event. Will be overwrite by another value later. - $description = 'Stripe payment request OK (' . $charge->id . ') from makeStripeSepaRequest: ' . $FULLTAG; - } - - $object = $this; - - // Track an event - if (empty($charge) || $charge->status == 'failed') { $actioncode = 'PAYMENT_STRIPE_KO'; - $extraparams = $stripefailurecode; - $extraparams .= (($extraparams && $stripefailuremessage) ? ' - ' : '') . $stripefailuremessage; - $extraparams .= (($extraparams && $stripefailuredeclinecode) ? ' - ' : '') . $stripefailuredeclinecode; - } else { - $actioncode = 'PAYMENT_STRIPE_OK'; $extraparams = ''; } } else { - $error++; - $errorforinvoice++; - 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; - - $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'; - $postactionmessages[] = $description . ' (' . $stripearrayofkeys['publishable_key'] . ')'; + // If error because payment was canceled for a logical reason, we do nothing (no event added) + $description = ''; + $stripefailurecode = ''; + $stripefailuremessage = ''; $object = $this; - $actioncode = 'PAYMENT_STRIPE_KO'; + $actioncode = ''; $extraparams = ''; } - } else { - // If error because payment was canceled for a logical reason, we do nothing (no event added) - $description = ''; - $stripefailurecode = ''; - $stripefailuremessage = ''; + } else { // Else of the if ($resultthirdparty > 0 && ! empty($customer)) { + if ($resultthirdparty <= 0) { + dol_syslog('SellYourSaasUtils Failed to load customer for thirdparty_id = ' . $thirdparty->id, LOG_WARNING); + $this->errors[] = 'Failed to load customer for thirdparty_id = ' . $thirdparty->id; + } else { // $customer stripe not found + dol_syslog('SellYourSaasUtils Failed to get Stripe customer id for thirdparty_id = ' . $thirdparty->id . " in mode " . $servicestatus . " in Stripe env " . $stripearrayofkeysbyenv[$servicestatus]['publishable_key'], LOG_WARNING); + $this->errors[] = 'Failed to get Stripe customer id for thirdparty_id = ' . $thirdparty->id . " in mode " . $servicestatus . " in Stripe env " . $stripearrayofkeysbyenv[$servicestatus]['publishable_key']; + } + $error++; + $errorforinvoice++; + + $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)'; + $postactionmessages = []; $object = $this; - $actioncode = ''; + $actioncode = 'PAYMENT_STRIPE_KO'; $extraparams = ''; } - } else { // Else of the if ($resultthirdparty > 0 && ! empty($customer)) { - if ($resultthirdparty <= 0) { - dol_syslog('SellYourSaasUtils Failed to load customer for thirdparty_id = ' . $thirdparty->id, LOG_WARNING); - $this->errors[] = 'Failed to load customer for thirdparty_id = ' . $thirdparty->id; - } else { // $customer stripe not found - dol_syslog('SellYourSaasUtils Failed to get Stripe customer id for thirdparty_id = ' . $thirdparty->id . " in mode " . $servicestatus . " in Stripe env " . $stripearrayofkeysbyenv[$servicestatus]['publishable_key'], LOG_WARNING); - $this->errors[] = 'Failed to get Stripe customer id for thirdparty_id = ' . $thirdparty->id . " in mode " . $servicestatus . " in Stripe env " . $stripearrayofkeysbyenv[$servicestatus]['publishable_key']; + + if ($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) + $actioncomm = new ActionComm($this->db); + + $actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...) + $actioncomm->code = 'AC_' . $actioncode; + $actioncomm->label = $description; + $actioncomm->note_private = join(",\n", $postactionmessages); + $actioncomm->fk_project = $this->fk_project; + $actioncomm->datep = $now; + $actioncomm->datef = $now; + $actioncomm->percentage = -1; // Not applicable + $actioncomm->socid = $thirdparty->id; + $actioncomm->contactid = 0; + $actioncomm->authorid = $user->id; // User saving action + $actioncomm->userownerid = $user->id; // Owner of action + // Fields when action is a real email (content is already into note) + /*$actioncomm->email_msgid = $object->email_msgid; + $actioncomm->email_from = $object->email_from; + $actioncomm->email_sender= $object->email_sender; + $actioncomm->email_to = $object->email_to; + $actioncomm->email_tocc = $object->email_tocc; + $actioncomm->email_tobcc = $object->email_tobcc; + $actioncomm->email_subject = $object->email_subject; + $actioncomm->errors_to = $object->errors_to;*/ + $actioncomm->fk_element = $this->id; + $actioncomm->elementtype = $this->element; + $actioncomm->extraparams = dol_trunc($extraparams, 250); + + $actioncomm->create($user); } + + $this->description = $description; + $this->postactionmessages = $postactionmessages; + } catch (Exception $e) { $error++; $errorforinvoice++; - - $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)'; - $postactionmessages = []; - - $object = $this; - - $actioncode = 'PAYMENT_STRIPE_KO'; - $extraparams = ''; + dol_syslog('Error ' . $e->getMessage(), LOG_ERR); + $this->errors[] = 'Error ' . $e->getMessage(); } - - if ($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) - $actioncomm = new ActionComm($this->db); - - $actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...) - $actioncomm->code = 'AC_' . $actioncode; - $actioncomm->label = $description; - $actioncomm->note_private = join(",\n", $postactionmessages); - $actioncomm->fk_project = $this->fk_project; - $actioncomm->datep = $now; - $actioncomm->datef = $now; - $actioncomm->percentage = -1; // Not applicable - $actioncomm->socid = $thirdparty->id; - $actioncomm->contactid = 0; - $actioncomm->authorid = $user->id; // User saving action - $actioncomm->userownerid = $user->id; // Owner of action - // Fields when action is a real email (content is already into note) - /*$actioncomm->email_msgid = $object->email_msgid; - $actioncomm->email_from = $object->email_from; - $actioncomm->email_sender= $object->email_sender; - $actioncomm->email_to = $object->email_to; - $actioncomm->email_tocc = $object->email_tocc; - $actioncomm->email_tobcc = $object->email_tobcc; - $actioncomm->email_subject = $object->email_subject; - $actioncomm->errors_to = $object->errors_to;*/ - $actioncomm->fk_element = $this->id; - $actioncomm->elementtype = $this->element; - $actioncomm->extraparams = dol_trunc($extraparams, 250); - - $actioncomm->create($user); - } - - $this->description = $description; - $this->postactionmessages = $postactionmessages; - } catch (Exception $e) { + } else { // If remain to pay is null $error++; $errorforinvoice++; - dol_syslog('Error ' . $e->getMessage(), LOG_ERR); - $this->errors[] = 'Error ' . $e->getMessage(); + dol_syslog("Remain to pay is null for the invoice " . $this->id . " " . $this->ref . ". Why is the invoice not classified 'Paid' ?", LOG_WARNING); + $this->errors[] = "Remain to pay is null for the invoice " . $this->id . " " . $this->ref . ". Why is the invoice not classified 'Paid' ?"; } - } else { // If remain to pay is null - $error++; - $errorforinvoice++; - dol_syslog("Remain to pay is null for the invoice " . $this->id . " " . $this->ref . ". Why is the invoice not classified 'Paid' ?", LOG_WARNING); - $this->errors[] = "Remain to pay is null for the invoice " . $this->id . " " . $this->ref . ". Why is the invoice not classified 'Paid' ?"; } // Set status of the order to "Transferred" with method 'api'