Clean code to manage SEPA payment using external service

This commit is contained in:
Laurent Destailleur 2022-09-09 04:10:48 +02:00
parent 9a09e0f304
commit 584f9e6a73
5 changed files with 1148 additions and 124 deletions

View File

@ -823,6 +823,815 @@ abstract class CommonInvoice extends CommonObject
} }
} }
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Create a withdrawal request for a direct debit order or a credit transfer order.
* Use the remain to pay excluding all existing open direct debit requests.
*
* @param User $fuser User asking the direct debit transfer
* @param float $amount Amount we request direct debit for
* @param string $type 'direct-debit' or 'bank-transfer'
* @param string $sourcetype Source ('facture' or 'supplier_invoice')
* @return int <0 if KO, >0 if OK
*/
public function demande_prelevement_stripe($fuser, $amount = 0, $type = 'direct-debit', $sourcetype = 'facture')
{
// phpcs:enable
global $conf, $mysoc, $user, $langs;
if (empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT)) {
//exit
return 0;
}
$error = 0;
dol_syslog(get_class($this)."::demande_prelevement_stripe 0", LOG_DEBUG);
if ($this->statut > self::STATUS_DRAFT && $this->paye == 0) {
require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
$bac = new CompanyBankAccount($this->db);
$bac->fetch(0, $this->socid);
$sql = 'SELECT count(*)';
$sql .= ' FROM '.MAIN_DB_PREFIX.'prelevement_facture_demande';
$sql .= ' WHERE fk_facture = '.$this->id;
$sql .= ' AND ext_payment_id IS NULL'; // To exclude record done for some online payments
$sql .= ' AND traite = 0';
dol_syslog(get_class($this)."::demande_prelevement_stripe 1", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$row = $this->db->fetch_row($resql);
if ($row[0] == 0) {
$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);
if (empty($amount)) {
$amount = price2num($this->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits, 'MT');
}
if (is_numeric($amount) && $amount != 0) {
require_once DOL_DOCUMENT_ROOT.'/societe/class/companypaymentmode.class.php';
$companypaymentmode = new CompanyPaymentMode($this->db);
$companypaymentmode->fetch($bac->id);
dol_syslog(get_class($this)."::demande_prelevement_stripe amount=$amount, companypaymentmode = " . $companypaymentmode->id, LOG_DEBUG);
//Start code from sellyoursaas
$service = 'StripeTest';
$servicestatus = 0;
if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) {
$service = 'StripeLive';
$servicestatus = 1;
}
$langs->load("agenda");
dol_syslog("doTakePaymentStripeForThirdparty service=" . $service . " servicestatus=" . $servicestatus . " thirdparty_id=" . $this->socid . " companypaymentmode=" . $companypaymentmode->id . " noemailtocustomeriferror=" . $noemailtocustomeriferror . " nocancelifpaymenterror=" . $nocancelifpaymenterror . " calledinmyaccountcontext=" . $calledinmyaccountcontext);
$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);
$alreadypayed = $this->getSommePaiement();
$amount_credit_notes_included = $this->getSumCreditNotesUsed();
$amounttopay = $this->total_ttc - $alreadypayed - $amount_credit_notes_included;
// Correct the amount according to unit of currency
// See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
$arrayzerounitcurrency = ['BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'];
$amountstripe = $amounttopay;
if (!in_array($currency, $arrayzerounitcurrency)) {
$amountstripe = $amountstripe * 100;
}
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);
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);
if (empty($savstripearrayofkeysbyenv)) {
$savstripearrayofkeysbyenv = $stripearrayofkeysbyenv;
}
dol_syslog("Current Stripe environment is " . $stripearrayofkeysbyenv[$servicestatus]['publishable_key']);
dol_syslog("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("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);
}
dol_syslog("get stripe account", LOG_DEBUG);
$stripeacc = $stripe->getStripeAccount($service, $this->socid); // Get Stripe OAuth connect account if it exists (no network access here)
dol_syslog("get stripe 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';
}*/
}
// $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 && ($this->date < ($now - ($nbdaysbeforeendoftries * 24 * 3600))) // We try until we reach $nbdaysbeforeendoftries
// && ($this->date < ($now - (62 * 24 * 3600)) || $this->date > ($now - (60 * 24 * 3600))) // or when we have 60 days
// && ($this->date < ($now - (92 * 24 * 3600)) || $this->date > ($now - (90 * 24 * 3600))) // or when we have 90 days
// && empty($nocancelifpaymenterror)) {
// $errmsg = 'Payment try was canceled (invoice date is older than ' . $nbdaysbeforeendoftries . ' days and not 60 days old and not 90 days old) - You can still take payment from backoffice.';
// dol_syslog($errmsg, LOG_DEBUG);
// $error++;
// $errorforinvoice++;
// $this->errors[] = $errmsg;
// }
// if (!$error && empty($nocancelifpaymenterror)) { // If we are not in a mode that ask to avoid cancelation, we cancel payment.
// // Test if last AC_PAYMENT_STRIPE_KO event is an old error lower than $nbhoursbetweentries hours.
// $recentfailedpayment = false;
// $sqlonevents = 'SELECT COUNT(*) as nb FROM ' . MAIN_DB_PREFIX . 'actioncomm WHERE fk_soc = ' . $thirdparty->id . " AND code ='AC_PAYMENT_STRIPE_KO' AND datep > '" . $this->db->idate($now - ($nbhoursbetweentries * 3600)) . "'";
// $resqlonevents = $this->db->query($sqlonevents);
// if ($resqlonevents) {
// $obj = $this->db->fetch_object($resqlonevents);
// if ($obj && $obj->nb > 0) {
// $recentfailedpayment = true;
// }
// }
// if ($recentfailedpayment) {
// $errmsg = 'Payment try was canceled (recent payment, in last ' . $nbhoursbetweentries . ' hours, with error AC_PAYMENT_STRIPE_KO for this customer)';
// dol_syslog($errmsg, LOG_DEBUG);
// $error++;
// $errorforinvoice++;
// $this->errors[] = $errmsg;
// }
// }
if (!$error) { // Payment was not canceled
//erics card or sepa ?
$sepaMode = false;
if ($companypaymentmode->type == 'ban') {
$sepaMode = true;
$stripecard = $stripe->sepaStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0);
} else {
$stripecard = $stripe->cardStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0);
}
if ($stripecard) { // Can be card_... (old mode) or pm_... (new mode)
$FULLTAG = 'INV=' . $this->id . '-CUS=' . $thirdparty->id;
$description = 'Stripe payment from doTakePaymentStripeForThirdparty: ' . $FULLTAG . ' ref=' . $this->ref;
$stripefailurecode = '';
$stripefailuremessage = '';
$stripefailuredeclinecode = '';
if (preg_match('/^card_/', $stripecard->id)) { // Using old method
dol_syslog("* Create charge on card " . $stripecard->id . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG);
$ipaddress = getUserRemoteIP();
$charge = null; // Force reset of $charge, so, if already set from a previous fetch, it will be empty even if there is an exception at next step
try {
$charge = \Stripe\Charge::create([
'amount' => price2num($amountstripe, 'MU'),
'currency' => $currency,
'capture' => true, // Charge immediatly
'description' => $description,
'metadata' => ["FULLTAG" => $FULLTAG, 'Recipient' => $mysoc->name, 'dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress],
'customer' => $customer->id,
//'customer' => 'bidon_to_force_error', // To use to force a stripe error
'source' => $stripecard,
'statement_descriptor' => dol_trunc('INV=' . $this->id, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
]);
} catch (\Stripe\Error\Card $e) {
// Since it's a decline, Stripe_CardError will be caught
$body = $e->getJsonBody();
$err = $body['error'];
$stripefailurecode = $err['code'];
$stripefailuremessage = $err['message'];
$stripefailuredeclinecode = $err['decline_code'];
} catch (Exception $e) {
$stripefailurecode = 'UnknownChargeError';
$stripefailuremessage = $e->getMessage();
}
} else { // Using new SCA method
if ($sepaMode)
dol_syslog("* Create payment on SEPA " . $stripecard->id . ", amounttopay=" . $amounttopay . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG);
else dol_syslog("* Create payment on card " . $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, $invoice, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1);
$charge = new stdClass();
//erics add processing sepa is like success ?
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;
}
//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 card or 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 doTakePaymentStripeForThirdparty: ' . $FULLTAG;
$postactionmessages[] = $errmsg . ' (' . $stripearrayofkeys['publishable_key'] . ')';
$this->errors[] = $errmsg;
} else {
dol_syslog('Successfuly charge card ' . $stripecard->id);
$postactionmessages[] = 'Success to charge card (' . $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 OK (' . $charge->id . ') from doTakePaymentStripeForThirdparty: ' . $FULLTAG;
$db = $this->db;
$ipaddress = getUserRemoteIP();
$TRANSACTIONID = $charge->id;
$currency = $conf->currency;
$paymentmethod = 'stripe';
$emetteur_name = $charge->customer;
// Same code than into paymentok.php...
$paymentTypeId = 0;
if ($paymentmethod == 'paybox') {
$paymentTypeId = $conf->global->PAYBOX_PAYMENT_MODE_FOR_PAYMENTS;
}
if ($paymentmethod == 'paypal') {
$paymentTypeId = $conf->global->PAYPAL_PAYMENT_MODE_FOR_PAYMENTS;
}
if ($paymentmethod == 'stripe') {
$paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS;
}
if (empty($paymentTypeId)) {
//erics
if ($sepaMode) {
$paymentType = 'PRE';
} else {
$paymentType = $_SESSION["paymentType"];
if (empty($paymentType)) {
$paymentType = 'CB';
}
}
$paymentTypeId = dol_getIdFromCode($this->db, $paymentType, 'c_paiement', 'code', 'id', 1);
}
$currencyCodeType = $currency;
$ispostactionok = 1;
// Creation of payment line
include_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
$paiement = new Paiement($this->db);
$paiement->datepaye = $now;
$paiement->date = $now;
if ($currencyCodeType == $conf->currency) {
$paiement->amounts = [$this->id => $amounttopay]; // Array with all payments dispatching with invoice id
} else {
$paiement->multicurrency_amounts = [$this->id => $amounttopay]; // Array with all payments dispatching
$postactionmessages[] = 'Payment was done in a different currency than currency expected of company';
$ispostactionok = -1;
// Not yet supported, so error
$error++;
$errorforinvoice++;
}
$paiement->paiementid = $paymentTypeId;
$paiement->num_paiement = '';
$paiement->num_payment = '';
// Add a comment with keyword 'SellYourSaas' in text. Used by trigger.
$paiement->note_public = 'StripeSepa payment ' . dol_print_date($now, 'standard') . ' using ' . $paymentmethod . ($ipaddress ? ' from ip ' . $ipaddress : '') . ' - Transaction ID = ' . $TRANSACTIONID;
$paiement->note_private = 'StripeSepa payment ' . dol_print_date($now, 'standard') . ' using ' . $paymentmethod . ($ipaddress ? ' from ip ' . $ipaddress : '') . ' - Transaction ID = ' . $TRANSACTIONID;
$paiement->ext_payment_id = $charge->id . ':' . $customer->id . '@' . $stripearrayofkeys['publishable_key'];
$paiement->ext_payment_site = 'stripe';
if (!$errorforinvoice) {
dol_syslog('* Record payment for invoice id ' . $this->id . '. It includes closing of invoice and regenerating document');
// This include closing invoices to 'paid' (and trigger including unsuspending) and regenerating document
$paiement_id = $paiement->create($user, 1);
if ($paiement_id < 0) {
$postactionmessages[] = $paiement->error . ($paiement->error ? ' ' : '') . join("<br>\n", $paiement->errors);
$ispostactionok = -1;
$error++;
$errorforinvoice++;
} else {
$postactionmessages[] = 'Payment created';
}
dol_syslog("The payment has been created for invoice id " . $this->id);
}
if (!$errorforinvoice && !empty($conf->banque->enabled)) {
dol_syslog('* Add payment to bank');
$bankaccountid = 0;
if ($paymentmethod == 'paybox') {
$bankaccountid = $conf->global->PAYBOX_BANK_ACCOUNT_FOR_PAYMENTS;
}
if ($paymentmethod == 'paypal') {
$bankaccountid = $conf->global->PAYPAL_BANK_ACCOUNT_FOR_PAYMENTS;
}
if ($paymentmethod == 'stripe') {
$bankaccountid = $conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS;
}
if ($bankaccountid > 0) {
$label = '(CustomerInvoicePayment)';
if ($this->type == Facture::TYPE_CREDIT_NOTE) {
$label = '(CustomerInvoicePaymentBack)';
} // Refund of a credit note
$result = $paiement->addPaymentToBank($user, 'payment', $label, $bankaccountid, $emetteur_name, '');
if ($result < 0) {
$postactionmessages[] = $paiement->error . ($paiement->error ? ' ' : '') . join("<br>\n", $paiement->errors);
$ispostactionok = -1;
$error++;
$errorforinvoice++;
} else {
$postactionmessages[] = 'Bank transaction of payment created (by doTakePaymentStripeForThirdparty)';
}
} else {
$postactionmessages[] = 'Setup of bank account to use in module ' . $paymentmethod . ' was not set. No way to record the payment.';
$ispostactionok = -1;
$error++;
$errorforinvoice++;
}
}
if ($ispostactionok < 1) {
$description = 'Stripe payment OK (' . $charge->id . ' - ' . $amounttopay . ' ' . $conf->currency . ') but post action KO from doTakePaymentStripeForThirdparty: ' . $FULLTAG;
} else {
$description = 'Stripe payment+post action OK (' . $charge->id . ' - ' . $amounttopay . ' ' . $conf->currency . ') from doTakePaymentStripeForThirdparty: ' . $FULLTAG;
}
}
$object = $invoice;
// 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';
$extraparams = $stripefailurecode;
$extraparams .= (($extraparams && $stripefailuremessage) ? ' - ' : '') . $stripefailuremessage;
$extraparams .= (($extraparams && $stripefailuredeclinecode) ? ' - ' : '') . $stripefailuredeclinecode;
} else {
$actioncode = 'PAYMENT_STRIPE_OK';
$extraparams = '';
}
} else {
$error++;
$errorforinvoice++;
dol_syslog("No card or payment method found for this stripe customer " . $customer->id, LOG_WARNING);
$this->errors[] = 'Failed to get card | 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';
$postactionmessages[] = $description . ' (' . $stripearrayofkeys['publishable_key'] . ')';
$object = $invoice;
$actioncode = 'PAYMENT_STRIPE_KO';
$extraparams = '';
}
} else {
// If error because payment was canceled for a logical reason, we do nothing (no email and no event added)
$labeltouse = '';
$sendemailtocustomer = 0;
$description = '';
$stripefailurecode = '';
$stripefailuremessage = '';
$object = $invoice;
$actioncode = '';
$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'];
}
$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)';
$postactionmessages = [];
$object = $invoice;
$actioncode = 'PAYMENT_STRIPE_KO';
$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: doTakeStripePaymentForThirdParty' . "\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);
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++;
dol_syslog('Error ' . $e->getMessage(), LOG_ERR);
$this->errors[] = 'Error ' . $e->getMessage();
}
} 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' ?";
}
//end copy
// print json_encode($stripecard);
// exit;
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'prelevement_facture_demande(';
$sql .= 'fk_facture, ';
$sql .= ' amount, date_demande, fk_user_demande, ext_payment_id, ext_payment_site, sourcetype, entity)';
$sql .= ' VALUES ('.$this->id;
$sql .= ",'".price2num($amount)."'";
$sql .= ",'".$this->db->idate($now)."'";
$sql .= ",".$fuser->id;
$sql .= ",'".$this->db->escape($stripe_id)."'";
$sql .= ",'".$this->db->escape($stripe_uri)."'";
$sql .= ",'".$this->db->escape($sourcetype)."'";
$sql .= ",".$conf->entity;
$sql .= ")";
dol_syslog(get_class($this)."::demande_prelevement_stripe", LOG_DEBUG);
$resql = $this->db->query($sql);
if (!$resql) {
$this->error = $this->db->lasterror();
dol_syslog(get_class($this).'::demande_prelevement_stripe Erreur');
$error++;
}
} else {
$this->error = 'WithdrawRequestErrorNilAmount';
dol_syslog(get_class($this).'::demande_prelevement_stripe WithdrawRequestErrorNilAmount');
$error++;
}
if (!$error) {
// Force payment mode of 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;
}
return 1;
} else {
$this->error = "A request already exists";
dol_syslog(get_class($this).'::demande_prelevement_stripe Impossible de creer une demande, demande deja en cours');
return 0;
}
} else {
$this->error = $this->db->error();
dol_syslog(get_class($this).'::demande_prelevement_stripe Erreur -2');
return -2;
}
} else {
$this->error = "Status of invoice does not allow this";
dol_syslog(get_class($this)."::demande_prelevement_stripe ".$this->error." $this->statut, $this->paye, $this->mode_reglement_id");
return -3;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/** /**
* Remove a direct debit request or a credit transfer request * Remove a direct debit request or a credit transfer request

View File

@ -292,6 +292,7 @@ ErrorThirpdartyOrMemberidIsMandatory=Third party or Member of partnership is man
ErrorFailedToWriteInTempDirectory=Failed to write in temp directory ErrorFailedToWriteInTempDirectory=Failed to write in temp directory
ErrorQuantityIsLimitedTo=Quantity is limited to %s ErrorQuantityIsLimitedTo=Quantity is limited to %s
ErrorFailedToLoadThirdParty=Failed to find/load thirdparty from id=%s, email=%s, name=%s ErrorFailedToLoadThirdParty=Failed to find/load thirdparty from id=%s, email=%s, name=%s
ErrorThisPaymentModeIsNotSepa=This payment mode is not a bank account
# Warnings # Warnings
WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup.

View File

@ -47,6 +47,9 @@ class CompanyBankAccount extends Account
public $rum; public $rum;
public $date_rum; public $date_rum;
public $stripe_card_ref; // ID of BAN into an external payment system
public $stripe_account; // Account of the external payment system
/** /**
* Date creation record (datec) * Date creation record (datec)
* *
@ -187,6 +190,8 @@ class CompanyBankAccount extends Account
} else { } else {
$sql .= ",label = NULL"; $sql .= ",label = NULL";
} }
$sql .= ",stripe_card_ref = '".$this->db->escape($this->stripe_card_ref)."'";
$sql .= ",stripe_account = '".$this->db->escape($this->stripe_account)."'";
$sql .= " WHERE rowid = ".((int) $this->id); $sql .= " WHERE rowid = ".((int) $this->id);
$result = $this->db->query($sql); $result = $this->db->query($sql);
@ -232,7 +237,8 @@ class CompanyBankAccount extends Account
} }
$sql = "SELECT rowid, type, fk_soc, bank, number, code_banque, code_guichet, cle_rib, bic, iban_prefix as iban, domiciliation, proprio,"; $sql = "SELECT rowid, type, fk_soc, bank, number, code_banque, code_guichet, cle_rib, bic, iban_prefix as iban, domiciliation, proprio,";
$sql .= " owner_address, default_rib, label, datec, tms as datem, rum, frstrecur, date_rum"; $sql .= " owner_address, default_rib, label, datec, tms as datem, rum, frstrecur, date_rum,";
$sql .= " stripe_card_ref, stripe_account";
$sql .= " FROM ".MAIN_DB_PREFIX."societe_rib"; $sql .= " FROM ".MAIN_DB_PREFIX."societe_rib";
if ($id) { if ($id) {
$sql .= " WHERE rowid = ".((int) $id); $sql .= " WHERE rowid = ".((int) $id);
@ -274,6 +280,8 @@ class CompanyBankAccount extends Account
$this->rum = $obj->rum; $this->rum = $obj->rum;
$this->frstrecur = $obj->frstrecur; $this->frstrecur = $obj->frstrecur;
$this->date_rum = $this->db->jdate($obj->date_rum); $this->date_rum = $this->db->jdate($obj->date_rum);
$this->stripe_card_ref = $obj->stripe_card_ref;
$this->stripe_account = $obj->stripe_account;
} }
$this->db->free($resql); $this->db->free($resql);

View File

@ -175,6 +175,12 @@ if (empty($reshook)) {
$companybankaccount->rum = $prelevement->buildRumNumber($object->code_client, $companybankaccount->datec, $companybankaccount->id); $companybankaccount->rum = $prelevement->buildRumNumber($object->code_client, $companybankaccount->datec, $companybankaccount->id);
} }
if (GETPOST('stripe_card_ref', 'alpha') && GETPOST('stripe_card_ref', 'alpha') != $companypaymentmode->stripe_card_ref) {
// If we set a stripe value that is different than previous one, we also set the stripe account
$companypaymentmode->stripe_account = $stripecu.'@'.$site_account;
}
$companybankaccount->stripe_card_ref = GETPOST('stripe_card_ref', 'alpha');
$result = $companybankaccount->update($user); $result = $companybankaccount->update($user);
if (!$result) { if (!$result) {
setEventMessages($companybankaccount->error, $companybankaccount->errors, 'errors'); setEventMessages($companybankaccount->error, $companybankaccount->errors, 'errors');
@ -416,6 +422,7 @@ if (empty($reshook)) {
if ($action == 'confirm_deletecard' && GETPOST('confirm', 'alpha') == 'yes') { if ($action == 'confirm_deletecard' && GETPOST('confirm', 'alpha') == 'yes') {
$companypaymentmode = new CompanyPaymentMode($db); $companypaymentmode = new CompanyPaymentMode($db);
if ($companypaymentmode->fetch($ribid ? $ribid : $id)) { if ($companypaymentmode->fetch($ribid ? $ribid : $id)) {
// TODO This is currently done at bottom of page instead of asking confirm
/*if ($companypaymentmode->stripe_card_ref && preg_match('/pm_/', $companypaymentmode->stripe_card_ref)) /*if ($companypaymentmode->stripe_card_ref && preg_match('/pm_/', $companypaymentmode->stripe_card_ref))
{ {
$payment_method = \Stripe\PaymentMethod::retrieve($companypaymentmode->stripe_card_ref); $payment_method = \Stripe\PaymentMethod::retrieve($companypaymentmode->stripe_card_ref);
@ -440,6 +447,16 @@ if (empty($reshook)) {
if ($action == 'confirm_delete' && GETPOST('confirm', 'alpha') == 'yes') { if ($action == 'confirm_delete' && GETPOST('confirm', 'alpha') == 'yes') {
$companybankaccount = new CompanyBankAccount($db); $companybankaccount = new CompanyBankAccount($db);
if ($companybankaccount->fetch($ribid ? $ribid : $id)) { if ($companybankaccount->fetch($ribid ? $ribid : $id)) {
// TODO This is currently done at bottom of page instead of asking confirm
/*if ($companypaymentmode->stripe_card_ref && preg_match('/pm_/', $companypaymentmode->stripe_card_ref))
{
$payment_method = \Stripe\PaymentMethod::retrieve($companypaymentmode->stripe_card_ref);
if ($payment_method)
{
$payment_method->detach();
}
}*/
$result = $companybankaccount->delete($user); $result = $companybankaccount->delete($user);
if ($result > 0) { if ($result > 0) {
$url = $_SERVER['PHP_SELF']."?socid=".$object->id; $url = $_SERVER['PHP_SELF']."?socid=".$object->id;
@ -505,7 +522,7 @@ if (empty($reshook)) {
} }
if (!$error) { if (!$error) {
// Creation of Stripe card + update of societe_account // Creation of Stripe card + update of llx_societe_rib
// Note that with the new Stripe API, option to create a card is no more available, instead an error message will be returned to // Note that with the new Stripe API, option to create a card is no more available, instead an error message will be returned to
// ask to create the crdit card from Stripe backoffice. // ask to create the crdit card from Stripe backoffice.
$card = $stripe->cardStripe($cu, $companypaymentmode, $stripeacc, $servicestatus, 1); $card = $stripe->cardStripe($cu, $companypaymentmode, $stripeacc, $servicestatus, 1);
@ -517,18 +534,13 @@ if (empty($reshook)) {
} }
} }
if ($action == 'syncsepatostripe') { if ($action == 'syncsepatostripe') {
$companybankaccount->fetch(GETPOST('bankid', 'int')); $companypaymentmode = new CompanyPaymentMode($db); // Get record in llx_societe_rib
// print "stripe account = " . json_encode($stripe->getStripeAccount($service)); $companypaymentmode->fetch($id);
// print json_encode($companybankaccount);
// print "fetch id = " . json_encode($socid);
$companypaymentmode = new CompanyPaymentMode($db);
$companypaymentmode->fetch(null, null, $socid);
// print json_encode($companypaymentmode);
if ($companypaymentmode->type != 'ban') { if ($companypaymentmode->type != 'ban') {
$error++; $error++;
setEventMessages('ThisPaymentModeIsNotSepa', null, 'errors'); $langs->load("errors");
setEventMessages('ThisPaymentModeIsNotABan', null, 'errors');
} else { } else {
// Get the Stripe customer // Get the Stripe customer
$cu = $stripe->customerStripe($object, $stripeacc, $servicestatus); $cu = $stripe->customerStripe($object, $stripeacc, $servicestatus);
@ -539,13 +551,13 @@ if (empty($reshook)) {
} }
if (!$error) { if (!$error) {
// Creation of Stripe SEPA + update of societe_account // Creation of Stripe SEPA + update of llx_societe_rib
$card = $stripe->sepaStripe($cu, $companypaymentmode, $stripeacc, $servicestatus, 1); $card = $stripe->sepaStripe($cu, $companypaymentmode, $stripeacc, $servicestatus, 1);
if (!$card) { if (!$card) {
$error++; $error++;
setEventMessages($stripe->error, $stripe->errors, 'errors'); setEventMessages($stripe->error, $stripe->errors, 'errors');
} else { } else {
setEventMessages("", array("SEPA on Stripe", "SEPA IBAN is now linked to the Stripe customer account !")); setEventMessages("", array("Bank Account on Stripe", "BAN is now linked to the Stripe customer account !"));
} }
} }
} }
@ -711,6 +723,37 @@ if (empty($reshook)) {
$error++; $error++;
setEventMessages($e->getMessage(), null, 'errors'); setEventMessages($e->getMessage(), null, 'errors');
} }
} elseif ($action == 'delete' && $source) {
try {
if (preg_match('/pm_/', $source)) {
$payment_method = \Stripe\PaymentMethod::retrieve($source, array("stripe_account" => $stripeacc));
if ($payment_method) {
$payment_method->detach();
}
} else {
$cu = $stripe->customerStripe($object, $stripeacc, $servicestatus);
$card = $cu->sources->retrieve("$source");
if ($card) {
// $card->detach(); Does not work with card_, only with src_
if (method_exists($card, 'detach')) {
$card->detach();
$sql = "UPDATE ".MAIN_DB_PREFIX."societe_rib as sr ";
$sql .= " SET stripe_card_ref = null";
$sql .= " WHERE sr.stripe_card_ref = '".$db->escape($source)."'";
$resql = $db->query($sql);
} else {
$card->delete();
}
}
}
$url = DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id;
header('Location: '.$url);
exit;
} catch (Exception $e) {
$error++;
setEventMessages($e->getMessage(), null, 'errors');
}
} }
} }
} }
@ -938,70 +981,75 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print '<br>'; print '<br>';
// List of Stripe payment modes $showcardpaymentmode = 0;
if (!(empty($conf->stripe->enabled)) && $object->client) { if (isModEnabled('stripe')) {
$showcardpaymentmode++;
}
// Get list of remote payment modes
$listofsources = array();
if (is_object($stripe)) {
try {
$customerstripe = $stripe->customerStripe($object, $stripeacc, $servicestatus);
if (!empty($customerstripe->id)) {
// When using the Charge API architecture
if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
$listofsources = $customerstripe->sources->data;
} else {
$service = 'StripeTest';
$servicestatus = 0;
if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) {
$service = 'StripeLive';
$servicestatus = 1;
}
// Force to use the correct API key
global $stripearrayofkeysbyenv;
\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']);
try {
if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
$paymentmethodobjsA = \Stripe\PaymentMethod::all(array("customer" => $customerstripe->id, "type" => "card"));
$paymentmethodobjsB = \Stripe\PaymentMethod::all(array("customer" => $customerstripe->id, "type" => "sepa_debit"));
} else {
$paymentmethodobjsA = \Stripe\PaymentMethod::all(array("customer" => $customerstripe->id, "type" => "card"), array("stripe_account" => $stripeacc));
$paymentmethodobjsB = \Stripe\PaymentMethod::all(array("customer" => $customerstripe->id, "type" => "sepa_debit"), array("stripe_account" => $stripeacc));
}
if ($paymentmethodobjsA->data != null && $paymentmethodobjsB->data != null) {
$listofsources = array_merge((array) $paymentmethodobjsA->data, (array) $paymentmethodobjsB->data);
} elseif ($paymentmethodobjsB->data != null) {
$listofsources = $paymentmethodobjsB->data;
} else {
$listofsources = $paymentmethodobjsA->data;
}
} catch (Exception $e) {
$error++;
setEventMessages($e->getMessage(), null, 'errors');
}
}
}
} catch (Exception $e) {
dol_syslog("Error when searching/loading Stripe customer for thirdparty id =".$object->id);
}
}
// List of Card payment modes
if ($showcardpaymentmode && $object->client) {
$morehtmlright = ''; $morehtmlright = '';
if (!empty($conf->global->STRIPE_ALLOW_LOCAL_CARD)) { if (!empty($conf->global->STRIPE_ALLOW_LOCAL_CARD)) {
$morehtmlright .= dolGetButtonTitle($langs->trans('Add'), '', 'fa fa-plus-circle', $_SERVER["PHP_SELF"].'?socid='.$object->id.'&amp;action=createcard'); $morehtmlright .= dolGetButtonTitle($langs->trans('Add'), '', 'fa fa-plus-circle', $_SERVER["PHP_SELF"].'?socid='.$object->id.'&amp;action=createcard');
} }
print load_fiche_titre($langs->trans('StripePaymentModes').($stripeacc ? ' (Stripe connection with StripeConnect account '.$stripeacc.')' : ' (Stripe connection with keys from Stripe module setup)'), $morehtmlright, 'stripe-s'); print load_fiche_titre($langs->trans('CreditCard').($stripeacc ? ' (Stripe connection with StripeConnect account '.$stripeacc.')' : ' (Stripe connection with keys from Stripe module setup)'), $morehtmlright, 'fa-credit-card');
$listofsources = array(); print '<!-- List of card payments -->'."\n";
if (is_object($stripe)) {
try {
$customerstripe = $stripe->customerStripe($object, $stripeacc, $servicestatus);
if (!empty($customerstripe->id)) {
// When using the Charge API architecture
if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
$listofsources = $customerstripe->sources->data;
} else {
$service = 'StripeTest';
$servicestatus = 0;
if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) {
$service = 'StripeLive';
$servicestatus = 1;
}
// Force to use the correct API key
global $stripearrayofkeysbyenv;
\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']);
try {
if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
$paymentmethodobjsA = \Stripe\PaymentMethod::all(array("customer" => $customerstripe->id, "type" => "card"));
$paymentmethodobjsB = \Stripe\PaymentMethod::all(array("customer" => $customerstripe->id, "type" => "sepa_debit"));
} else {
$paymentmethodobjsA = \Stripe\PaymentMethod::all(array("customer" => $customerstripe->id, "type" => "card"), array("stripe_account" => $stripeacc));
$paymentmethodobjsB = \Stripe\PaymentMethod::all(array("customer" => $customerstripe->id, "type" => "sepa_debit"), array("stripe_account" => $stripeacc));
}
if ($paymentmethodobjsA->data != null && $paymentmethodobjsB->data != null) {
$listofsources = array_merge((array) $paymentmethodobjsA->data, (array) $paymentmethodobjsB->data);
} elseif ($paymentmethodobjsB->data != null) {
$listofsources = $paymentmethodobjsB->data;
} else {
$listofsources = $paymentmethodobjsA->data;
}
} catch (Exception $e) {
$error++;
setEventMessages($e->getMessage(), null, 'errors');
}
}
}
} catch (Exception $e) {
dol_syslog("Error when searching/loading Stripe customer for thirdparty id =".$object->id);
}
}
print '<!-- List of stripe payments -->'."\n";
print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
print '<table class="liste centpercent">'."\n"; print '<table class="liste centpercent">'."\n";
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
if (!empty($conf->global->STRIPE_ALLOW_LOCAL_CARD)) {
print '<td>'.$langs->trans('LocalID').'</td>';
}
print '<td>'.$langs->trans('Label').'</td>'; print '<td>'.$langs->trans('Label').'</td>';
print '<td>'.$langs->trans('StripeID').'</td>'; print '<td>'.$langs->trans('StripeID').'</td>'; // external system ID
print '<td>'.$langs->trans('Type').'</td>'; print '<td>'.$langs->trans('Type').'</td>';
print '<td>'.$langs->trans('Informations').'</td>'; print '<td>'.$langs->trans('Informations').'</td>';
print '<td></td>'; print '<td></td>';
@ -1018,7 +1066,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
$nbremote = 0; $nbremote = 0;
$nblocal = 0; $nblocal = 0;
$arrayofstripecard = array(); $arrayofremotecard = array();
// Show local sources // Show local sources
if (!empty($conf->global->STRIPE_ALLOW_LOCAL_CARD)) { if (!empty($conf->global->STRIPE_ALLOW_LOCAL_CARD)) {
@ -1042,18 +1090,16 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
if ($obj) { if ($obj) {
$companypaymentmodetemp->fetch($obj->rowid); $companypaymentmodetemp->fetch($obj->rowid);
$arrayofstripecard[$companypaymentmodetemp->stripe_card_ref] = $companypaymentmodetemp->stripe_card_ref; $arrayofremotecard[$companypaymentmodetemp->stripe_card_ref] = $companypaymentmodetemp->stripe_card_ref;
print '<tr class="oddeven">'; print '<tr class="oddeven" data-rowid="'.((int) $companypaymentmodetemp->id).'">';
print '<td>'; // Label
print $companypaymentmodetemp->id;
print '</td>';
print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($companypaymentmodetemp->label).'">'; print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($companypaymentmodetemp->label).'">';
print dol_escape_htmltag($companypaymentmodetemp->label); print dol_escape_htmltag($companypaymentmodetemp->label);
print '</td>'; print '</td>';
print '<td>'; // External card ID
print $companypaymentmodetemp->stripe_card_ref; print '<td class="tdoverflowmax150">';
if ($companypaymentmodetemp->stripe_card_ref) { if (!empty($companypaymentmodetemp->stripe_card_ref)) {
$connect = ''; $connect = '';
if (!empty($stripeacc)) { if (!empty($stripeacc)) {
$connect = $stripeacc.'/'; $connect = $stripeacc.'/';
@ -1062,12 +1108,15 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
if ($servicestatus) { if ($servicestatus) {
$url = 'https://dashboard.stripe.com/'.$connect.'search?query='.$companypaymentmodetemp->stripe_card_ref; $url = 'https://dashboard.stripe.com/'.$connect.'search?query='.$companypaymentmodetemp->stripe_card_ref;
} }
print ' <a href="'.$url.'" target="_stripe">'.img_picto($langs->trans('ShowInStripe').' - Customer and Publishable key = '.$companypaymentmodetemp->stripe_account, 'globe').'</a>'; print '<a href="'.$url.'" target="_stripe">'.img_picto($langs->trans('ShowInStripe').' - Customer and Publishable key = '.$companypaymentmodetemp->stripe_account, 'globe').'</a> ';
} }
print $companypaymentmodetemp->stripe_card_ref;
print '</td>'; print '</td>';
// Type
print '<td>'; print '<td>';
print img_credit_card($companypaymentmodetemp->type); print img_credit_card($companypaymentmodetemp->type);
print '</td>'; print '</td>';
// Information (Owner, ...)
print '<td>'; print '<td>';
if ($companypaymentmodetemp->proprio) { if ($companypaymentmodetemp->proprio) {
print '<span class="opacitymedium">'.$companypaymentmodetemp->proprio.'</span><br>'; print '<span class="opacitymedium">'.$companypaymentmodetemp->proprio.'</span><br>';
@ -1121,7 +1170,6 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print '<a class="editfielda marginleftonly marginrightonly" href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id.'&id='.$companypaymentmodetemp->id.'&action=editcard&token='.newToken().'">'; print '<a class="editfielda marginleftonly marginrightonly" href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id.'&id='.$companypaymentmodetemp->id.'&action=editcard&token='.newToken().'">';
print img_picto($langs->trans("Modify"), 'edit'); print img_picto($langs->trans("Modify"), 'edit');
print '</a>'; print '</a>';
print '&nbsp;';
print '<a class="marginleftonly marginrightonly" href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id.'&id='.$companypaymentmodetemp->id.'&action=deletecard&token='.newToken().'">'; // source='.$companypaymentmodetemp->stripe_card_ref.'& print '<a class="marginleftonly marginrightonly" href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id.'&id='.$companypaymentmodetemp->id.'&action=deletecard&token='.newToken().'">'; // source='.$companypaymentmodetemp->stripe_card_ref.'&
print img_picto($langs->trans("Delete"), 'delete'); print img_picto($langs->trans("Delete"), 'delete');
print '</a>'; print '</a>';
@ -1140,24 +1188,31 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
// Show remote sources (not already shown as local source) // Show remote sources (not already shown as local source)
if (is_array($listofsources) && count($listofsources)) { if (is_array($listofsources) && count($listofsources)) {
foreach ($listofsources as $src) { foreach ($listofsources as $src) {
if (!empty($arrayofstripecard[$src->id])) { if (!empty($arrayofremotecard[$src->id])) {
continue; // Already in previous list continue; // Already in previous list
} }
$nbremote++; $nbremote++;
print '<tr class="oddeven">'; $imgline = '';
// Local ID if ($src->object == 'card') {
if (!empty($conf->global->STRIPE_ALLOW_LOCAL_CARD)) { $imgline = img_credit_card($src->brand);
print '<td>'; } elseif ($src->object == 'source' && $src->type == 'card') {
print '</td>'; $imgline = img_credit_card($src->card->brand);
} elseif ($src->object == 'payment_method' && $src->type == 'card') {
$imgline = img_credit_card($src->card->brand);
} elseif ($src->object == 'source' && $src->type == 'sepa_debit') {
continue;
} elseif ($src->object == 'payment_method' && $src->type == 'sepa_debit') {
continue;
} }
print '<tr class="oddeven">';
print '<td>'; print '<td>';
print '</td>'; print '</td>';
// Src ID // Src ID
print '<td>'; print '<td class="tdoverflowmax150">';
$connect = ''; $connect = '';
print $src->id;
if (!empty($stripeacc)) { if (!empty($stripeacc)) {
$connect = $stripeacc.'/'; $connect = $stripeacc.'/';
} }
@ -1167,21 +1222,12 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
//$url='https://dashboard.stripe.com/'.$connect.'sources/'.$src->id; //$url='https://dashboard.stripe.com/'.$connect.'sources/'.$src->id;
$url = 'https://dashboard.stripe.com/'.$connect.'search?query='.$src->id; $url = 'https://dashboard.stripe.com/'.$connect.'search?query='.$src->id;
} }
print " <a href='".$url."' target='_stripe'>".img_picto($langs->trans('ShowInStripe'), 'globe')."</a>"; print "<a href='".$url."' target='_stripe'>".img_picto($langs->trans('ShowInStripe'), 'globe')."</a> ";
print $src->id;
print '</td>'; print '</td>';
// Img of credit card // Img
print '<td>'; print '<td>';
if ($src->object == 'card') { print $imgline;
print img_credit_card($src->brand);
} elseif ($src->object == 'source' && $src->type == 'card') {
print img_credit_card($src->card->brand);
} elseif ($src->object == 'source' && $src->type == 'sepa_debit') {
print '<span class="fa fa-university fa-2x fa-fw"></span>';
} elseif ($src->object == 'payment_method' && $src->type == 'card') {
print img_credit_card($src->card->brand);
} elseif ($src->object == 'payment_method' && $src->type == 'sepa_debit') {
print '<span class="fa fa-university fa-2x fa-fw"></span>';
}
print'</td>'; print'</td>';
// Information // Information
print '<td valign="middle">'; print '<td valign="middle">';
@ -1256,18 +1302,20 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print $langs->trans("Remote"); print $langs->trans("Remote");
//if ($src->cvc_check == 'fail') print ' - CVC check fail'; //if ($src->cvc_check == 'fail') print ' - CVC check fail';
print '</td>'; print '</td>';
print '<td>'; print '<td>';
//var_dump($src); //var_dump($src);
print '';
print '</td>'; print '</td>';
// Fields from hook // Fields from hook
$parameters = array('arrayfields'=>array(), 'stripesource'=>$src, 'linetype'=>'stripecardremoteonly'); $parameters = array('arrayfields'=>array(), 'stripesource'=>$src, 'linetype'=>'stripecardremoteonly');
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint; print $hookmanager->resPrint;
// Action column // Action column
print '<td class="right nowraponall">'; print '<td class="right nowraponall">';
if ($permissiontoaddupdatepaymentinformation) { if ($permissiontoaddupdatepaymentinformation) {
print '<a href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id.'&source='.$src->id.'&action=deletecard&token='.newToken().'">'; print '<a class="marginleftonly marginrightonly" href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id.'&source='.$src->id.'&action=deletecard&token='.newToken().'">';
print img_picto($langs->trans("Delete"), 'delete'); print img_picto($langs->trans("Delete"), 'delete');
print '</a>'; print '</a>';
} }
@ -1286,7 +1334,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print '<br>'; print '<br>';
} }
// List of Stripe payment modes // List of Stripe connect accounts
if (!empty($conf->stripe->enabled) && !empty($conf->stripeconnect->enabled) && !empty($stripesupplieracc)) { if (!empty($conf->stripe->enabled) && !empty($conf->stripeconnect->enabled) && !empty($stripesupplieracc)) {
print load_fiche_titre($langs->trans('StripeBalance').($stripesupplieracc ? ' (Stripe connection with StripeConnect account '.$stripesupplieracc.')' : ' (Stripe connection with keys from Stripe module setup)'), $morehtmlright, 'stripe-s'); print load_fiche_titre($langs->trans('StripeBalance').($stripesupplieracc ? ' (Stripe connection with StripeConnect account '.$stripesupplieracc.')' : ' (Stripe connection with keys from Stripe module setup)'), $morehtmlright, 'stripe-s');
$balance = \Stripe\Balance::retrieve(array("stripe_account" => $stripesupplieracc)); $balance = \Stripe\Balance::retrieve(array("stripe_account" => $stripesupplieracc));
@ -1337,16 +1385,20 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
$morehtmlright = dolGetButtonTitle($langs->trans('Add'), '', 'fa fa-plus-circle', $_SERVER["PHP_SELF"] . '?socid=' . $object->id . '&amp;action=create'); $morehtmlright = dolGetButtonTitle($langs->trans('Add'), '', 'fa fa-plus-circle', $_SERVER["PHP_SELF"] . '?socid=' . $object->id . '&amp;action=create');
} }
print load_fiche_titre($langs->trans("BankAccounts"), $morehtmlright, 'bank'); print load_fiche_titre($langs->trans("BankAccounts"), $morehtmlright, 'bank');
$nblocal = 0; $nbremote = 0;
$arrayofremoteban = array();
$rib_list = $object->get_all_rib(); $rib_list = $object->get_all_rib();
if (is_array($rib_list)) { if (is_array($rib_list)) {
print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
print '<table class="liste centpercent">'; print '<table class="liste centpercent">';
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
print_liste_field_titre("LabelRIB"); print_liste_field_titre("Label");
print_liste_field_titre("StripeID"); // external system ID
print_liste_field_titre("Bank"); print_liste_field_titre("Bank");
print_liste_field_titre("RIB"); print_liste_field_titre("RIB");
print_liste_field_titre("IBAN"); print_liste_field_titre("IBAN");
@ -1356,17 +1408,43 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print_liste_field_titre("DateRUM"); print_liste_field_titre("DateRUM");
print_liste_field_titre("WithdrawMode"); print_liste_field_titre("WithdrawMode");
} }
print_liste_field_titre("DefaultRIB", '', '', '', '', '', '', '', 'center '); print_liste_field_titre("Default", '', '', '', '', '', '', '', 'center ');
print_liste_field_titre('', '', '', '', '', '', '', '', 'center '); print_liste_field_titre('', '', '', '', '', '', '', '', 'center ');
// Fields from hook
$parameters = array('arrayfields'=>array(), 'linetype'=>'stripebantitle');
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint;
print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', '', '', '', '', 'maxwidthsearch '); print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', '', '', '', '', 'maxwidthsearch ');
print "</tr>\n"; print "</tr>\n";
// List of local BAN
foreach ($rib_list as $rib) { foreach ($rib_list as $rib) {
$arrayofremoteban[$rib->stripe_card_ref] = $rib->stripe_card_ref;
$nblocal++;
print '<tr class="oddeven">'; print '<tr class="oddeven">';
// Label // Label
print '<td>'.$rib->label.'</td>'; print '<td>'.dol_escape_htmltag($rib->label).'</td>';
// Stripe ID
print '<td class="tdoverflowmax150">';
if ($rib->stripe_card_ref) {
$connect = '';
if (!empty($stripeacc)) {
$connect = $stripeacc.'/';
}
//$url='https://dashboard.stripe.com/'.$connect.'test/sources/'.$src->id;
$url = 'https://dashboard.stripe.com/'.$connect.'test/search?query='.$rib->stripe_card_ref;
if ($servicestatus) {
//$url='https://dashboard.stripe.com/'.$connect.'sources/'.$src->id;
$url = 'https://dashboard.stripe.com/'.$connect.'search?query='.$rib->stripe_card_ref;
}
print "<a href='".$url."' target='_stripe'>".img_picto($langs->trans('ShowInStripe'), 'globe')."</a> ";
}
print $rib->stripe_card_ref;
print '</td>';
// Bank name // Bank name
print '<td>'.$rib->bank.'</td>'; print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($rib->bank).'">'.dol_escape_htmltag($rib->bank).'</td>';
// Account number // Account number
print '<td>'; print '<td>';
$string = ''; $string = '';
@ -1398,7 +1476,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print $string; print $string;
print '</td>'; print '</td>';
// IBAN // IBAN
print '<td>'.$rib->iban; print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($rib->iban).'">'.dol_escape_htmltag($rib->iban);
if (!empty($rib->iban)) { if (!empty($rib->iban)) {
if (!checkIbanForAccount($rib)) { if (!checkIbanForAccount($rib)) {
print ' '.img_picto($langs->trans("IbanNotValid"), 'warning'); print ' '.img_picto($langs->trans("IbanNotValid"), 'warning');
@ -1417,7 +1495,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
if (!empty($conf->prelevement->enabled)) { if (!empty($conf->prelevement->enabled)) {
// RUM // RUM
//print '<td>'.$prelevement->buildRumNumber($object->code_client, $rib->datec, $rib->id).'</td>'; //print '<td>'.$prelevement->buildRumNumber($object->code_client, $rib->datec, $rib->id).'</td>';
print '<td>'.$rib->rum.'</td>'; print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($rib->rum).'">'.dol_escape_htmltag($rib->rum).'</td>';
print '<td>'.dol_print_date($rib->date_rum, 'day').'</td>'; print '<td>'.dol_print_date($rib->date_rum, 'day').'</td>';
@ -1500,12 +1578,19 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print $out; print $out;
print '</td>'; print '</td>';
// Fields from hook
$parameters = array('arrayfields'=>array(), 'stripe_card_ref'=>$rib->stripe_card_ref, 'stripe_account'=>$rib->stripe_account, 'linetype'=>'stripeban');
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint;
// Edit/Delete // Edit/Delete
print '<td class="right nowraponall">'; print '<td class="right nowraponall">';
if ($permissiontoaddupdatepaymentinformation) { if ($permissiontoaddupdatepaymentinformation) {
print '<a class="editfielda marginrightonly marginleftonly" href="'.$_SERVER["PHP_SELF"].'?socid='.$object->id.'&id='.$rib->id.'&action=syncsepatostripe">'; if (empty($rib->stripe_card_ref)) {
print img_picto($langs->trans("CreateBAN"), 'stripe'); print '<a class="editfielda marginrightonly marginleftonly" href="'.$_SERVER["PHP_SELF"].'?socid='.$object->id.'&id='.$rib->id.'&action=syncsepatostripe">';
print '</a>'; print img_picto($langs->trans("CreateBAN"), 'stripe');
print '</a>';
}
print '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?socid='.$object->id.'&id='.$rib->id.'&action=edit">'; print '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?socid='.$object->id.'&id='.$rib->id.'&action=edit">';
print img_picto($langs->trans("Modify"), 'edit'); print img_picto($langs->trans("Modify"), 'edit');
@ -1520,10 +1605,114 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print '</tr>'; print '</tr>';
} }
if (count($rib_list) == 0) {
$colspan = 9; // List of remote BAN (if not already added as local)
foreach ($listofsources as $src) {
if (!empty($arrayofremoteban[$src->id])) {
continue; // Already in previous list
}
$nbremote++;
$imgline = '';
if ($src->object == 'source' && $src->type == 'sepa_debit') {
$imgline = '<span class="fa fa-university fa-2x fa-fw"></span>';
} elseif ($src->object == 'payment_method' && $src->type == 'sepa_debit') {
$imgline = '<span class="fa fa-university fa-2x fa-fw"></span>';
} else {
continue;
}
print '<tr class="oddeven">';
print '<td>';
print '</td>';
// Src ID
print '<td class="tdoverflowmax150">';
$connect = '';
if (!empty($stripeacc)) {
$connect = $stripeacc.'/';
}
//$url='https://dashboard.stripe.com/'.$connect.'test/sources/'.$src->id;
$url = 'https://dashboard.stripe.com/'.$connect.'test/search?query='.$src->id;
if ($servicestatus) {
//$url='https://dashboard.stripe.com/'.$connect.'sources/'.$src->id;
$url = 'https://dashboard.stripe.com/'.$connect.'search?query='.$src->id;
}
print "<a href='".$url."' target='_stripe'>".img_picto($langs->trans('ShowInStripe'), 'globe')."</a> ";
print $src->id;
print '</td>';
// Bank
print '<td>';
print'</td>';
// Account number
print '<td valign="middle">';
print '</td>';
// IBAN
print '<td valign="middle">';
//var_dump($src);
print '</td>';
// BIC
print '<td valign="middle">';
//var_dump($src);
print '</td>';
if (!empty($conf->prelevement->enabled)) { if (!empty($conf->prelevement->enabled)) {
$colspan += 2; // RUM
print '<td valign="middle">';
//var_dump($src);
print '</td>';
// Date
print '<td valign="middle">';
//var_dump($src);
print '</td>';
// Mode mandate
print '<td valign="middle">';
//var_dump($src);
print '</td>';
}
// Default
print '<td class="center" width="50">';
if ((empty($customerstripe->invoice_settings) && $customerstripe->default_source != $src->id) ||
(!empty($customerstripe->invoice_settings) && $customerstripe->invoice_settings->default_payment_method != $src->id)) {
print '<a href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id.'&source='.$src->id.'&action=setassourcedefault&token='.newToken().'">';
print img_picto($langs->trans("Default"), 'off');
print '</a>';
} else {
print img_picto($langs->trans("Default"), 'on');
}
print '</td>';
/*
print '<td>';
print $langs->trans("Remote");
//if ($src->cvc_check == 'fail') print ' - CVC check fail';
print '</td>';
*/
print '<td>';
print '</td>';
// Fields from hook
$parameters = array('arrayfields'=>array(), 'stripe_card_ref'=>$rib->stripe_card_ref, 'stripe_account'=>$rib->stripe_account, 'linetype'=>'stripebanremoteonly');
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint;
// Action column
print '<td class="right nowraponall">';
if ($permissiontoaddupdatepaymentinformation) {
print '<a class="marginleftonly marginrightonly" href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$object->id.'&source='.$src->id.'&action=delete&token='.newToken().'">';
print img_picto($langs->trans("Delete"), 'delete');
print '</a>';
}
print '</td>';
print '</tr>';
}
if ($nbremote == 0 && $nblocal == 0) {
$colspan = 10;
if (!empty($conf->prelevement->enabled)) {
$colspan += 3;
} }
print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoBANRecord").'</span></td></tr>'; print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoBANRecord").'</span></td></tr>';
} }
@ -1603,10 +1792,12 @@ if ($socid && $action == 'edit' && $permissiontoaddupdatepaymentinformation) {
print '<div class="underbanner clearboth"></div>'; print '<div class="underbanner clearboth"></div>';
print '<br>';
print '<div class="div-table-responsive-no-min">'; print '<div class="div-table-responsive-no-min">';
print '<table class="border centpercent">'; print '<table class="border centpercent">';
print '<tr><td class="titlefield fieldrequired">'.$langs->trans("LabelRIB").'</td>'; print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Label").'</td>';
print '<td><input class="minwidth300" type="text" name="label" value="'.$companybankaccount->label.'"></td></tr>'; print '<td><input class="minwidth300" type="text" name="label" value="'.$companybankaccount->label.'"></td></tr>';
print '<tr><td class="fieldrequired">'.$langs->trans("BankName").'</td>'; print '<tr><td class="fieldrequired">'.$langs->trans("BankName").'</td>';
@ -1702,6 +1893,9 @@ if ($socid && $action == 'edit' && $permissiontoaddupdatepaymentinformation) {
print $form->selectarray("frstrecur", $tblArraychoice, dol_escape_htmltag(GETPOST('frstrecur', 'alpha') ?GETPOST('frstrecur', 'alpha') : $companybankaccount->frstrecur), 0); print $form->selectarray("frstrecur", $tblArraychoice, dol_escape_htmltag(GETPOST('frstrecur', 'alpha') ?GETPOST('frstrecur', 'alpha') : $companybankaccount->frstrecur), 0);
print '</td></tr>'; print '</td></tr>';
print '<tr><td>'.$langs->trans("StripeID")." ('src_....')</td>";
print '<td><input class="minwidth300" type="text" name="stripe_card_ref" value="'.$companypaymentmode->stripe_card_ref.'"></td></tr>';
print '</table>'; print '</table>';
print '</div>'; print '</div>';
} }
@ -1720,9 +1914,12 @@ if ($socid && $action == 'editcard' && $permissiontoaddupdatepaymentinformation)
dol_banner_tab($object, 'socid', $linkback, ($user->socid ? 0 : 1), 'rowid', 'nom'); dol_banner_tab($object, 'socid', $linkback, ($user->socid ? 0 : 1), 'rowid', 'nom');
print '<div class="fichecenter">'; print '<div class="nofichecenter">';
print '<div class="underbanner clearboth"></div>'; print '<div class="underbanner clearboth"></div>';
print '<br>';
print '<table class="border centpercent">'; print '<table class="border centpercent">';
print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td>'; print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td>';
@ -1766,9 +1963,12 @@ if ($socid && $action == 'create' && $permissiontoaddupdatepaymentinformation) {
print '<div class="nofichecenter">'; print '<div class="nofichecenter">';
print '<div class="underbanner clearboth"></div>'; print '<div class="underbanner clearboth"></div>';
print '<br>';
print '<table class="border centpercent">'; print '<table class="border centpercent">';
print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("LabelRIB").'</td>'; print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td>';
print '<td><input class="minwidth200" type="text" id="label" name="label" value="'.(GETPOSTISSET('label') ? GETPOST('label') : $object->name).'"></td></tr>'; print '<td><input class="minwidth200" type="text" id="label" name="label" value="'.(GETPOSTISSET('label') ? GETPOST('label') : $object->name).'"></td></tr>';
print '<tr><td class="fieldrequired">'.$langs->trans("Bank").'</td>'; print '<tr><td class="fieldrequired">'.$langs->trans("Bank").'</td>';
@ -1858,6 +2058,9 @@ if ($socid && $action == 'create' && $permissiontoaddupdatepaymentinformation) {
print $form->selectarray("frstrecur", $tblArraychoice, (GETPOSTISSET('frstrecur') ? GETPOST('frstrecur') : 'FRST'), 0); print $form->selectarray("frstrecur", $tblArraychoice, (GETPOSTISSET('frstrecur') ? GETPOST('frstrecur') : 'FRST'), 0);
print '</td></tr>'; print '</td></tr>';
print '<tr><td>'.$langs->trans("StripeID")." ('src_....')</td>";
print '<td><input class="minwidth300" type="text" name="stripe_card_ref" value="'.GETPOST('stripe_card_ref', 'alpha').'"></td></tr>';
print '</table>'; print '</table>';
} }
@ -1881,6 +2084,9 @@ if ($socid && $action == 'createcard' && $permissiontoaddupdatepaymentinformatio
print '<div class="nofichecenter">'; print '<div class="nofichecenter">';
print '<div class="underbanner clearboth"></div>'; print '<div class="underbanner clearboth"></div>';
print '<br>';
print '<table class="border centpercent">'; print '<table class="border centpercent">';
print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td>'; print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td>';

View File

@ -774,7 +774,7 @@ class Stripe extends CommonObject
$sql .= " WHERE sa.rowid = ".((int) $object->id); // We get record from ID, no need for filter on entity $sql .= " WHERE sa.rowid = ".((int) $object->id); // We get record from ID, no need for filter on entity
$sql .= " AND sa.type = 'card'"; $sql .= " AND sa.type = 'card'";
dol_syslog(get_class($this)."::fetch search stripe card id for paymentmode id=".$object->id.", stripeacc=".$stripeacc.", status=".$status.", createifnotlinkedtostripe=".$createifnotlinkedtostripe, LOG_DEBUG); dol_syslog(get_class($this)."::cardStripe search stripe card id for paymentmode id=".$object->id.", stripeacc=".$stripeacc.", status=".$status.", createifnotlinkedtostripe=".$createifnotlinkedtostripe, LOG_DEBUG);
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if ($resql) { if ($resql) {
$num = $this->db->num_rows($resql); $num = $this->db->num_rows($resql);
@ -914,14 +914,14 @@ class Stripe extends CommonObject
$soc = new Societe($this->db); $soc = new Societe($this->db);
$soc->fetch($object->fk_soc); $soc->fetch($object->fk_soc);
dol_syslog(get_class($this)."::fetch search stripe sepa(card) id for paymentmode id=".$object->id.", stripeacc=".$stripeacc.", status=".$status.", createifnotlinkedtostripe=".$createifnotlinkedtostripe, LOG_DEBUG); dol_syslog(get_class($this)."::sepaStripe search stripe ban id for paymentmode id=".$object->id.", stripeacc=".$stripeacc.", status=".$status.", createifnotlinkedtostripe=".$createifnotlinkedtostripe, LOG_DEBUG);
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if ($resql) { if ($resql) {
$num = $this->db->num_rows($resql); $num = $this->db->num_rows($resql);
if ($num) { if ($num) {
$obj = $this->db->fetch_object($resql); $obj = $this->db->fetch_object($resql);
$cardref = $obj->stripe_card_ref; $cardref = $obj->stripe_card_ref;
dol_syslog(get_class($this)."::cardStripe cardref=".$cardref); dol_syslog(get_class($this)."::sepaStripe cardref=".$cardref);
if ($cardref) { if ($cardref) {
try { try {
if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
@ -990,7 +990,7 @@ class Stripe extends CommonObject
$sql = "UPDATE ".MAIN_DB_PREFIX."societe_rib"; $sql = "UPDATE ".MAIN_DB_PREFIX."societe_rib";
$sql .= " SET stripe_card_ref = '".$this->db->escape($sepa->id)."', card_type = 'sepa_debit',"; $sql .= " SET stripe_card_ref = '".$this->db->escape($sepa->id)."', card_type = 'sepa_debit',";
$sql .= " stripe_account= '" . $this->db->escape($cu->id . "@" . $stripeacc) . "'"; $sql .= " stripe_account= '" . $this->db->escape($cu->id . "@" . $stripeacc) . "'";
$sql .= " WHERE rowid = '".$this->db->escape($object->id)."'"; $sql .= " WHERE rowid = ".((int) $object->id);
$sql .= " AND type = 'ban'"; $sql .= " AND type = 'ban'";
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if (!$resql) { if (!$resql) {