dolibarr  x.y.z
newpayment.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2018 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2018-2021 Thibault FOUCART <support@ptibogxiv.net>
7  * Copyright (C) 2021 Waël Almoman <info@almoman.com>
8  * Copyright (C) 2021 Dorian Vabre <dorian.vabre@gmail.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <https://www.gnu.org/licenses/>.
22  *
23  * For Paypal test: https://developer.paypal.com/
24  * For Paybox test: ???
25  * For Stripe test: Use credit card 4242424242424242 .More example on https://stripe.com/docs/testing
26  *
27  * Variants:
28  * - When option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is on, we use the new PaymentIntent API
29  * - When option STRIPE_USE_NEW_CHECKOUT is on, we use the new checkout API
30  * - If no option set, we use old APIS (charge)
31  */
32 
39 if (!defined('NOLOGIN')) {
40  define("NOLOGIN", 1); // This means this output page does not require to be logged.
41 }
42 if (!defined('NOCSRFCHECK')) {
43  define("NOCSRFCHECK", 1); // We accept to go on this page from external web site.
44 }
45 if (!defined('NOIPCHECK')) {
46  define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
47 }
48 if (!defined('NOBROWSERNOTIF')) {
49  define('NOBROWSERNOTIF', '1');
50 }
51 
52 // For MultiCompany module.
53 // Do not use GETPOST here, function is not defined and get of entity must be done before including main.inc.php
54 $entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : (!empty($_GET['e']) ? (int) $_GET['e'] : (!empty($_POST['e']) ? (int) $_POST['e'] : 1))));
55 if (is_numeric($entity)) {
56  define("DOLENTITY", $entity);
57 }
58 
59 // Load Dolibarr environment
60 require '../../main.inc.php';
61 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
62 require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
63 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
64 require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php';
65 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
66 require_once DOL_DOCUMENT_ROOT.'/societe/class/societeaccount.class.php';
67 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
68 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
69 // Hook to be used by external payment modules (ie Payzen, ...)
70 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
71 $hookmanager = new HookManager($db);
72 $hookmanager->initHooks(array('newpayment'));
73 
74 // Load translation files
75 $langs->loadLangs(array("main", "other", "dict", "bills", "companies", "errors", "paybox", "paypal", "stripe")); // File with generic data
76 
77 // Security check
78 // No check on module enabled. Done later according to $validpaymentmethod
79 
80 $action = GETPOST('action', 'aZ09');
81 
82 // Input are:
83 // type ('invoice','order','contractline'),
84 // id (object id),
85 // amount (required if id is empty),
86 // tag (a free text, required if type is empty)
87 // currency (iso code)
88 
89 $suffix = GETPOST("suffix", 'aZ09');
90 $amount = price2num(GETPOST("amount", 'alpha'));
91 if (!GETPOST("currency", 'alpha')) {
92  $currency = $conf->currency;
93 } else {
94  $currency = GETPOST("currency", 'aZ09');
95 }
96 $source = GETPOST("s", 'aZ09') ?GETPOST("s", 'aZ09') : GETPOST("source", 'aZ09');
97 //$download = GETPOST('d', 'int') ?GETPOST('d', 'int') : GETPOST('download', 'int');
98 
99 if (!$action) {
100  if (!GETPOST("amount", 'alpha') && !$source) {
101  print $langs->trans('ErrorBadParameters')." - amount or source";
102  exit;
103  }
104  if (is_numeric($amount) && !GETPOST("tag", 'alpha') && !$source) {
105  print $langs->trans('ErrorBadParameters')." - tag or source";
106  exit;
107  }
108  if ($source && !GETPOST("ref", 'alpha')) {
109  print $langs->trans('ErrorBadParameters')." - ref";
110  exit;
111  }
112 }
113 
114 if ($source == 'organizedeventregistration') {
115  // Finding the Attendee
116  $attendee = new ConferenceOrBoothAttendee($db);
117 
118  $invoiceid = GETPOST('ref', 'int');
119  $invoice = new Facture($db);
120 
121  $resultinvoice = $invoice->fetch($invoiceid);
122 
123  if ($resultinvoice <= 0) {
124  setEventMessages(null, $invoice->errors, "errors");
125  } else {
126  /*
127  $attendeeid = 0;
128 
129  $invoice->fetchObjectLinked();
130  $linkedAttendees = $invoice->linkedObjectsIds['conferenceorboothattendee'];
131 
132  if (is_array($linkedAttendees)) {
133  $linkedAttendees = array_values($linkedAttendees);
134  $attendeeid = $linkedAttendees[0];
135  }*/
136  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."eventorganization_conferenceorboothattendee";
137  $sql .= " WHERE fk_invoice = ".((int) $invoiceid);
138  $resql = $db->query($sql);
139  if ($resql) {
140  $obj = $db->fetch_object($resql);
141  if ($obj) {
142  $attendeeid = $obj->rowid;
143  }
144  }
145 
146  if ($attendeeid > 0) {
147  $resultattendee = $attendee->fetch($attendeeid);
148 
149  if ($resultattendee <= 0) {
150  setEventMessages(null, $attendee->errors, "errors");
151  } else {
152  $attendee->fetch_projet();
153 
154  $amount = price2num($invoice->total_ttc);
155  // Finding the associated thirdparty
156  $thirdparty = new Societe($db);
157  $resultthirdparty = $thirdparty->fetch($invoice->socid);
158  if ($resultthirdparty <= 0) {
159  setEventMessages(null, $thirdparty->errors, "errors");
160  }
161  $object = $thirdparty;
162  }
163  }
164  }
165 } elseif ($source == 'boothlocation') {
166  // Getting the amount to pay, the invoice, finding the thirdparty
167  $invoiceid = GETPOST('ref');
168  $invoice = new Facture($db);
169  $resultinvoice = $invoice->fetch($invoiceid);
170  if ($resultinvoice <= 0) {
171  setEventMessages(null, $invoice->errors, "errors");
172  } else {
173  $amount = price2num($invoice->total_ttc);
174  // Finding the associated thirdparty
175  $thirdparty = new Societe($db);
176  $resultthirdparty = $thirdparty->fetch($invoice->socid);
177  if ($resultthirdparty <= 0) {
178  setEventMessages(null, $thirdparty->errors, "errors");
179  }
180  $object = $thirdparty;
181  }
182 }
183 
184 
185 $paymentmethod = GETPOST('paymentmethod', 'alphanohtml') ? GETPOST('paymentmethod', 'alphanohtml') : ''; // Empty in most cases. Defined when a payment mode is forced
186 $validpaymentmethod = array();
187 
188 // Detect $paymentmethod
189 foreach ($_POST as $key => $val) {
190  $reg = array();
191  if (preg_match('/^dopayment_(.*)$/', $key, $reg)) {
192  $paymentmethod = $reg[1];
193  break;
194  }
195 }
196 
197 
198 // Define $urlwithroot
199 //$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
200 //$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
201 $urlwithroot = DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost.
202 
203 $urlok = $urlwithroot.'/public/payment/paymentok.php?';
204 $urlko = $urlwithroot.'/public/payment/paymentko.php?';
205 
206 // Complete urls for post treatment
207 $ref = $REF = GETPOST('ref', 'alpha');
208 $TAG = GETPOST("tag", 'alpha');
209 $FULLTAG = GETPOST("fulltag", 'alpha'); // fulltag is tag with more informations
210 $SECUREKEY = GETPOST("securekey"); // Secure key
211 
212 if ($paymentmethod && !preg_match('/'.preg_quote('PM='.$paymentmethod, '/').'/', $FULLTAG)) {
213  $FULLTAG .= ($FULLTAG ? '.' : '').'PM='.$paymentmethod;
214 }
215 
216 if (!empty($suffix)) {
217  $urlok .= 'suffix='.urlencode($suffix).'&';
218  $urlko .= 'suffix='.urlencode($suffix).'&';
219 }
220 if ($source) {
221  $urlok .= 's='.urlencode($source).'&';
222  $urlko .= 's='.urlencode($source).'&';
223 }
224 if (!empty($REF)) {
225  $urlok .= 'ref='.urlencode($REF).'&';
226  $urlko .= 'ref='.urlencode($REF).'&';
227 }
228 if (!empty($TAG)) {
229  $urlok .= 'tag='.urlencode($TAG).'&';
230  $urlko .= 'tag='.urlencode($TAG).'&';
231 }
232 if (!empty($FULLTAG)) {
233  $urlok .= 'fulltag='.urlencode($FULLTAG).'&';
234  $urlko .= 'fulltag='.urlencode($FULLTAG).'&';
235 }
236 if (!empty($SECUREKEY)) {
237  $urlok .= 'securekey='.urlencode($SECUREKEY).'&';
238  $urlko .= 'securekey='.urlencode($SECUREKEY).'&';
239 }
240 if (!empty($entity)) {
241  $urlok .= 'e='.urlencode($entity).'&';
242  $urlko .= 'e='.urlencode($entity).'&';
243 }
244 $urlok = preg_replace('/&$/', '', $urlok); // Remove last &
245 $urlko = preg_replace('/&$/', '', $urlko); // Remove last &
246 
247 
248 // Make special controls
249 
250 if ((empty($paymentmethod) || $paymentmethod == 'paypal') && isModEnabled('paypal')) {
251  require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php';
252  require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php';
253 
254  // Check parameters
255  $PAYPAL_API_OK = "";
256  if ($urlok) {
257  $PAYPAL_API_OK = $urlok;
258  }
259  $PAYPAL_API_KO = "";
260  if ($urlko) {
261  $PAYPAL_API_KO = $urlko;
262  }
263  if (empty($PAYPAL_API_USER)) {
264  dol_print_error('', "Paypal setup param PAYPAL_API_USER not defined");
265  return -1;
266  }
267  if (empty($PAYPAL_API_PASSWORD)) {
268  dol_print_error('', "Paypal setup param PAYPAL_API_PASSWORD not defined");
269  return -1;
270  }
271  if (empty($PAYPAL_API_SIGNATURE)) {
272  dol_print_error('', "Paypal setup param PAYPAL_API_SIGNATURE not defined");
273  return -1;
274  }
275 }
276 if ((empty($paymentmethod) || $paymentmethod == 'paybox') && isModEnabled('paybox')) {
277  // No specific test for the moment
278 }
279 if ((empty($paymentmethod) || $paymentmethod == 'stripe') && isModEnabled('stripe')) {
280  require_once DOL_DOCUMENT_ROOT.'/stripe/config.php'; // This include also /stripe/lib/stripe.lib.php, /includes/stripe/stripe-php/init.php, ...
281 }
282 
283 // Initialize $validpaymentmethod
284 // The list can be complete by the hook 'doValidatePayment' executed inside getValidOnlinePaymentMethods()
285 $validpaymentmethod = getValidOnlinePaymentMethods($paymentmethod);
286 
287 // Check security token
288 $tmpsource = $source;
289 if ($tmpsource == 'membersubscription') {
290  $tmpsource = 'member';
291 }
292 $valid = true;
293 if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) {
294  $tokenisok = false;
295  if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) {
296  if ($tmpsource && $REF) {
297  // Use the source in the hash to avoid duplicates if the references are identical
298  $tokenisok = dol_verifyHash($conf->global->PAYMENT_SECURITY_TOKEN.$tmpsource.$REF, $SECUREKEY, '2');
299  // Do a second test for retro-compatibility (token may have been hashed with membersubscription in external module)
300  if ($tmpsource != $source) {
301  $tokenisok = dol_verifyHash($conf->global->PAYMENT_SECURITY_TOKEN.$source.$REF, $SECUREKEY, '2');
302  }
303  } else {
304  $tokenisok = dol_verifyHash($conf->global->PAYMENT_SECURITY_TOKEN, $SECUREKEY, '2');
305  }
306  } else {
307  $tokenisok = ($conf->global->PAYMENT_SECURITY_TOKEN == $SECUREKEY);
308  }
309 
310  if (! $tokenisok) {
311  if (empty($conf->global->PAYMENT_SECURITY_ACCEPT_ANY_TOKEN)) {
312  $valid = false; // PAYMENT_SECURITY_ACCEPT_ANY_TOKEN is for backward compatibility
313  } else {
314  dol_syslog("Warning: PAYMENT_SECURITY_ACCEPT_ANY_TOKEN is on", LOG_WARNING);
315  }
316  }
317 
318  if (!$valid) {
319  print '<div class="error">Bad value for key.</div>';
320  //print 'SECUREKEY='.$SECUREKEY.' valid='.$valid;
321  exit;
322  }
323 }
324 
325 if (!empty($paymentmethod) && empty($validpaymentmethod[$paymentmethod])) {
326  print 'Payment module for payment method '.$paymentmethod.' is not active';
327  exit;
328 }
329 if (empty($validpaymentmethod)) {
330  print 'No active payment module (Paypal, Stripe, Paybox, ...)';
331  exit;
332 }
333 
334 // Common variables
335 $creditor = $mysoc->name;
336 $paramcreditor = 'ONLINE_PAYMENT_CREDITOR';
337 $paramcreditorlong = 'ONLINE_PAYMENT_CREDITOR_'.$suffix;
338 if (!empty($conf->global->$paramcreditorlong)) {
339  $creditor = $conf->global->$paramcreditorlong; // use label long of the seller to show
340 } elseif (!empty($conf->global->$paramcreditor)) {
341  $creditor = $conf->global->$paramcreditor; // use label short of the seller to show
342 }
343 
344 $mesg = '';
345 
346 
347 /*
348  * Actions
349  */
350 
351 // Action dopayment is called after clicking/choosing the payment mode
352 if ($action == 'dopayment') {
353  dol_syslog("--- newpayment.php Execute action = ".$action." paymentmethod=".$paymentmethod.' amount='.$amount.' newamount='.GETPOST("newamount", 'alpha'), LOG_DEBUG, 0, '_payment');
354 
355  if ($paymentmethod == 'paypal') {
356  $PAYPAL_API_PRICE = price2num(GETPOST("newamount", 'alpha'), 'MT');
357  $PAYPAL_PAYMENT_TYPE = 'Sale';
358 
359  // Vars that are used as global var later in print_paypal_redirect()
360  $origfulltag = GETPOST("fulltag", 'alpha');
361  $shipToName = GETPOST("shipToName", 'alpha');
362  $shipToStreet = GETPOST("shipToStreet", 'alpha');
363  $shipToCity = GETPOST("shipToCity", 'alpha');
364  $shipToState = GETPOST("shipToState", 'alpha');
365  $shipToCountryCode = GETPOST("shipToCountryCode", 'alpha');
366  $shipToZip = GETPOST("shipToZip", 'alpha');
367  $shipToStreet2 = GETPOST("shipToStreet2", 'alpha');
368  $phoneNum = GETPOST("phoneNum", 'alpha');
369  $email = GETPOST("email", 'alpha');
370  $desc = GETPOST("desc", 'alpha');
371  $thirdparty_id = GETPOST('thirdparty_id', 'int');
372 
373  // Special case for Paypal-Indonesia
374  if ($shipToCountryCode == 'ID' && !preg_match('/\-/', $shipToState)) {
375  $shipToState = 'ID-'.$shipToState;
376  }
377 
378  if (empty($PAYPAL_API_PRICE) || !is_numeric($PAYPAL_API_PRICE)) {
379  $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount"));
380  $action = '';
381  // } elseif (empty($EMAIL)) { $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("YourEMail"));
382  // } elseif (! isValidEMail($EMAIL)) { $mesg=$langs->trans("ErrorBadEMail",$EMAIL);
383  } elseif (!$origfulltag) {
384  $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("PaymentCode"));
385  $action = '';
386  }
387 
388  //var_dump($_POST);
389  if (empty($mesg)) {
390  dol_syslog("newpayment.php call paypal api and do redirect", LOG_DEBUG);
391 
392  // Other
393  $PAYPAL_API_DEVISE = "USD";
394  if (!empty($currency)) {
395  $PAYPAL_API_DEVISE = $currency;
396  }
397 
398  // Show var initialized by include fo paypal lib at begin of this file
399  dol_syslog("Submit Paypal form", LOG_DEBUG);
400  dol_syslog("PAYPAL_API_USER: $PAYPAL_API_USER", LOG_DEBUG);
401  dol_syslog("PAYPAL_API_PASSWORD: ".preg_replace('/./', '*', $PAYPAL_API_PASSWORD), LOG_DEBUG); // No password into log files
402  dol_syslog("PAYPAL_API_SIGNATURE: $PAYPAL_API_SIGNATURE", LOG_DEBUG);
403  dol_syslog("PAYPAL_API_SANDBOX: $PAYPAL_API_SANDBOX", LOG_DEBUG);
404  dol_syslog("PAYPAL_API_OK: $PAYPAL_API_OK", LOG_DEBUG);
405  dol_syslog("PAYPAL_API_KO: $PAYPAL_API_KO", LOG_DEBUG);
406  dol_syslog("PAYPAL_API_PRICE: $PAYPAL_API_PRICE", LOG_DEBUG);
407  dol_syslog("PAYPAL_API_DEVISE: $PAYPAL_API_DEVISE", LOG_DEBUG);
408  // All those fields may be empty when making a payment for a free amount for example
409  dol_syslog("shipToName: $shipToName", LOG_DEBUG);
410  dol_syslog("shipToStreet: $shipToStreet", LOG_DEBUG);
411  dol_syslog("shipToCity: $shipToCity", LOG_DEBUG);
412  dol_syslog("shipToState: $shipToState", LOG_DEBUG);
413  dol_syslog("shipToCountryCode: $shipToCountryCode", LOG_DEBUG);
414  dol_syslog("shipToZip: $shipToZip", LOG_DEBUG);
415  dol_syslog("shipToStreet2: $shipToStreet2", LOG_DEBUG);
416  dol_syslog("phoneNum: $phoneNum", LOG_DEBUG);
417  dol_syslog("email: $email", LOG_DEBUG);
418  dol_syslog("desc: $desc", LOG_DEBUG);
419 
420  dol_syslog("SCRIPT_URI: ".(empty($_SERVER["SCRIPT_URI"]) ? '' : $_SERVER["SCRIPT_URI"]), LOG_DEBUG); // If defined script uri must match domain of PAYPAL_API_OK and PAYPAL_API_KO
421 
422  // A redirect is added if API call successfull
423  $mesg = print_paypal_redirect($PAYPAL_API_PRICE, $PAYPAL_API_DEVISE, $PAYPAL_PAYMENT_TYPE, $PAYPAL_API_OK, $PAYPAL_API_KO, $FULLTAG);
424 
425  // If we are here, it means the Paypal redirect was not done, so we show error message
426  $action = '';
427  }
428  }
429 
430  if ($paymentmethod == 'paybox') {
431  $PRICE = price2num(GETPOST("newamount"), 'MT');
432  $email = $conf->global->ONLINE_PAYMENT_SENDEMAIL;
433  $thirdparty_id = GETPOST('thirdparty_id', 'int');
434 
435  $origfulltag = GETPOST("fulltag", 'alpha');
436 
437  // Securekey into back url useless for back url and we need an url lower than 150.
438  $urlok = preg_replace('/securekey=[^&]+&?/', '', $urlok);
439  $urlko = preg_replace('/securekey=[^&]+&?/', '', $urlko);
440 
441  if (empty($PRICE) || !is_numeric($PRICE)) {
442  $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount"));
443  } elseif (empty($email)) {
444  $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ONLINE_PAYMENT_SENDEMAIL"));
445  } elseif (!isValidEMail($email)) {
446  $mesg = $langs->trans("ErrorBadEMail", $email);
447  } elseif (!$origfulltag) {
448  $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("PaymentCode"));
449  } elseif (dol_strlen($urlok) > 150) {
450  $mesg = 'Error urlok too long '.$urlok.' (Paybox requires 150, found '.strlen($urlok).')';
451  } elseif (dol_strlen($urlko) > 150) {
452  $mesg = 'Error urlko too long '.$urlko.' (Paybox requires 150, found '.strlen($urlok).')';
453  }
454 
455  if (empty($mesg)) {
456  dol_syslog("newpayment.php call paybox api and do redirect", LOG_DEBUG);
457 
458  include_once DOL_DOCUMENT_ROOT.'/paybox/lib/paybox.lib.php';
459  print_paybox_redirect($PRICE, $conf->currency, $email, $urlok, $urlko, $FULLTAG);
460 
461  session_destroy();
462  exit;
463  }
464  }
465 
466  if ($paymentmethod == 'stripe') {
467  if (GETPOST('newamount', 'alpha')) {
468  $amount = price2num(GETPOST('newamount', 'alpha'), 'MT');
469  } else {
470  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount")), null, 'errors');
471  $action = '';
472  }
473  }
474 }
475 
476 
477 // Called when choosing Stripe mode.
478 // When using the old Charge API architecture, this code is called after clicking the 'dopayment' with the Charge API architecture.
479 // When using the PaymentIntent API architecture, the Stripe customer was already created when creating PaymentIntent when showing payment page, and the payment is already ok when action=charge.
480 if ($action == 'charge' && isModEnabled('stripe')) {
481  $amountstripe = $amount;
482 
483  // Correct the amount according to unit of currency
484  // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
485  $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
486  if (!in_array($currency, $arrayzerounitcurrency)) {
487  $amountstripe = $amountstripe * 100;
488  }
489 
490  dol_syslog("--- newpayment.php Execute action = ".$action." STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION=".getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION'), LOG_DEBUG, 0, '_payment');
491  dol_syslog("GET=".var_export($_GET, true), LOG_DEBUG, 0, '_payment');
492  dol_syslog("POST=".var_export($_POST, true), LOG_DEBUG, 0, '_payment');
493 
494  $stripeToken = GETPOST("stripeToken", 'alpha');
495  $email = GETPOST("email", 'alpha');
496  $thirdparty_id = GETPOST('thirdparty_id', 'int'); // Note that for payment following online registration for members, this is empty because thirdparty is created once payment is confirmed by paymentok.php
497  $dol_type = (GETPOST('s', 'alpha') ? GETPOST('s', 'alpha') : GETPOST('source', 'alpha'));
498  $dol_id = GETPOST('dol_id', 'int');
499  $vatnumber = GETPOST('vatnumber', 'alpha');
500  $savesource = GETPOSTISSET('savesource') ? GETPOST('savesource', 'int') : 1;
501 
502  dol_syslog("POST stripeToken = ".$stripeToken, LOG_DEBUG, 0, '_payment');
503  dol_syslog("POST email = ".$email, LOG_DEBUG, 0, '_payment');
504  dol_syslog("POST thirdparty_id = ".$thirdparty_id, LOG_DEBUG, 0, '_payment');
505  dol_syslog("POST vatnumber = ".$vatnumber, LOG_DEBUG, 0, '_payment');
506 
507  $error = 0;
508  $errormessage = '';
509 
510  // When using the old Charge API architecture
511  if (!getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
512  try {
513  $metadata = array(
514  'dol_version' => DOL_VERSION,
515  'dol_entity' => $conf->entity,
516  'dol_company' => $mysoc->name, // Usefull when using multicompany
517  'dol_tax_num' => $vatnumber,
518  'ipaddress'=> getUserRemoteIP()
519  );
520 
521  if (!empty($thirdparty_id)) {
522  $metadata["dol_thirdparty_id"] = $thirdparty_id;
523  }
524 
525  if ($thirdparty_id > 0) {
526  dol_syslog("Search existing Stripe customer profile for thirdparty_id=".$thirdparty_id, LOG_DEBUG, 0, '_payment');
527 
528  $service = 'StripeTest';
529  $servicestatus = 0;
530  if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'int')) {
531  $service = 'StripeLive';
532  $servicestatus = 1;
533  }
534 
535  $thirdparty = new Societe($db);
536  $thirdparty->fetch($thirdparty_id);
537 
538  // Create Stripe customer
539  include_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
540  $stripe = new Stripe($db);
541  $stripeacc = $stripe->getStripeAccount($service);
542  $customer = $stripe->customerStripe($thirdparty, $stripeacc, $servicestatus, 1);
543  if (empty($customer)) {
544  $error++;
545  dol_syslog('Failed to get/create stripe customer for thirdparty id = '.$thirdparty_id.' and servicestatus = '.$servicestatus.': '.$stripe->error, LOG_ERR, 0, '_payment');
546  setEventMessages('Failed to get/create stripe customer for thirdparty id = '.$thirdparty_id.' and servicestatus = '.$servicestatus.': '.$stripe->error, null, 'errors');
547  $action = '';
548  }
549 
550  // Create Stripe card from Token
551  if (!$error) {
552  if ($savesource) {
553  $card = $customer->sources->create(array("source" => $stripeToken, "metadata" => $metadata));
554  } else {
555  $card = $stripeToken;
556  }
557 
558  if (empty($card)) {
559  $error++;
560  dol_syslog('Failed to create card record', LOG_WARNING, 0, '_payment');
561  setEventMessages('Failed to create card record', null, 'errors');
562  $action = '';
563  } else {
564  if (!empty($FULLTAG)) {
565  $metadata["FULLTAG"] = $FULLTAG;
566  }
567  if (!empty($dol_id)) {
568  $metadata["dol_id"] = $dol_id;
569  }
570  if (!empty($dol_type)) {
571  $metadata["dol_type"] = $dol_type;
572  }
573 
574  dol_syslog("Create charge on card ".$card->id, LOG_DEBUG, 0, '_payment');
575  $charge = \Stripe\Charge::create(array(
576  'amount' => price2num($amountstripe, 'MU'),
577  'currency' => $currency,
578  'capture' => true, // Charge immediatly
579  'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref,
580  'metadata' => $metadata,
581  'customer' => $customer->id,
582  'source' => $card,
583  'statement_descriptor_suffix' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
584  ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc"));
585  // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...)
586  if (empty($charge)) {
587  $error++;
588  dol_syslog('Failed to charge card', LOG_WARNING, 0, '_payment');
589  setEventMessages('Failed to charge card', null, 'errors');
590  $action = '';
591  }
592  }
593  }
594  } else {
595  $vatcleaned = $vatnumber ? $vatnumber : null;
596 
597  /*$taxinfo = array('type'=>'vat');
598  if ($vatcleaned)
599  {
600  $taxinfo["tax_id"] = $vatcleaned;
601  }
602  // We force data to "null" if not defined as expected by Stripe
603  if (empty($vatcleaned)) $taxinfo=null;
604  */
605 
606  dol_syslog("Create anonymous customer card profile", LOG_DEBUG, 0, '_payment');
607 
608  $customer = \Stripe\Customer::create(array(
609  'email' => $email,
610  'description' => ($email ? 'Anonymous customer for '.$email : 'Anonymous customer'),
611  'metadata' => $metadata,
612  'source' => $stripeToken // source can be a token OR array('object'=>'card', 'exp_month'=>xx, 'exp_year'=>xxxx, 'number'=>xxxxxxx, 'cvc'=>xxx, 'name'=>'Cardholder's full name', zip ?)
613  ));
614  // Return $customer = array('id'=>'cus_XXXX', ...)
615 
616  // Create the VAT record in Stripe
617  /* We don't know country of customer, so we can't create tax
618  if (!empty($conf->global->STRIPE_SAVE_TAX_IDS)) // We setup to save Tax info on Stripe side. Warning: This may result in error when saving customer
619  {
620  if (!empty($vatcleaned))
621  {
622  $isineec=isInEEC($object);
623  if ($object->country_code && $isineec)
624  {
625  //$taxids = $customer->allTaxIds($customer->id);
626  $customer->createTaxId($customer->id, array('type'=>'eu_vat', 'value'=>$vatcleaned));
627  }
628  }
629  }*/
630 
631  if (!empty($FULLTAG)) {
632  $metadata["FULLTAG"] = $FULLTAG;
633  }
634  if (!empty($dol_id)) {
635  $metadata["dol_id"] = $dol_id;
636  }
637  if (!empty($dol_type)) {
638  $metadata["dol_type"] = $dol_type;
639  }
640 
641  // The customer was just created with a source, so we can make a charge
642  // with no card defined, the source just used for customer creation will be used.
643  dol_syslog("Create charge", LOG_DEBUG, 0, '_payment');
644  $charge = \Stripe\Charge::create(array(
645  'customer' => $customer->id,
646  'amount' => price2num($amountstripe, 'MU'),
647  'currency' => $currency,
648  'capture' => true, // Charge immediatly
649  'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref,
650  'metadata' => $metadata,
651  'statement_descriptor' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
652  ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc"));
653  // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...)
654  if (empty($charge)) {
655  $error++;
656  dol_syslog('Failed to charge card', LOG_WARNING, 0, '_payment');
657  setEventMessages('Failed to charge card', null, 'errors');
658  $action = '';
659  }
660  }
661  } catch (\Stripe\Error\Card $e) {
662  // Since it's a decline, \Stripe\Error\Card will be caught
663  $body = $e->getJsonBody();
664  $err = $body['error'];
665 
666  print('Status is:'.$e->getHttpStatus()."\n");
667  print('Type is:'.$err['type']."\n");
668  print('Code is:'.$err['code']."\n");
669  // param is '' in this case
670  print('Param is:'.$err['param']."\n");
671  print('Message is:'.$err['message']."\n");
672 
673  $error++;
674  $errormessage = "ErrorCard ".$e->getMessage()." err=".var_export($err, true);
675  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
676  setEventMessages($e->getMessage(), null, 'errors');
677  $action = '';
678  } catch (\Stripe\Error\RateLimit $e) {
679  // Too many requests made to the API too quickly
680  $error++;
681  $errormessage = "ErrorRateLimit ".$e->getMessage();
682  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
683  setEventMessages($e->getMessage(), null, 'errors');
684  $action = '';
685  } catch (\Stripe\Error\InvalidRequest $e) {
686  // Invalid parameters were supplied to Stripe's API
687  $error++;
688  $errormessage = "ErrorInvalidRequest ".$e->getMessage();
689  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
690  setEventMessages($e->getMessage(), null, 'errors');
691  $action = '';
692  } catch (\Stripe\Error\Authentication $e) {
693  // Authentication with Stripe's API failed
694  // (maybe you changed API keys recently)
695  $error++;
696  $errormessage = "ErrorAuthentication ".$e->getMessage();
697  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
698  setEventMessages($e->getMessage(), null, 'errors');
699  $action = '';
700  } catch (\Stripe\Error\ApiConnection $e) {
701  // Network communication with Stripe failed
702  $error++;
703  $errormessage = "ErrorApiConnection ".$e->getMessage();
704  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
705  setEventMessages($e->getMessage(), null, 'errors');
706  $action = '';
707  } catch (\Stripe\Error\Base $e) {
708  // Display a very generic error to the user, and maybe send
709  // yourself an email
710  $error++;
711  $errormessage = "ErrorBase ".$e->getMessage();
712  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
713  setEventMessages($e->getMessage(), null, 'errors');
714  $action = '';
715  } catch (Exception $e) {
716  // Something else happened, completely unrelated to Stripe
717  $error++;
718  $errormessage = "ErrorException ".$e->getMessage();
719  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
720  setEventMessages($e->getMessage(), null, 'errors');
721  $action = '';
722  }
723  }
724 
725  // When using the PaymentIntent API architecture (mode set on by default into conf.class.php)
726  if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
727  $service = 'StripeTest';
728  $servicestatus = 0;
729  if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'int')) {
730  $service = 'StripeLive';
731  $servicestatus = 1;
732  }
733  include_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
734  $stripe = new Stripe($db);
735  $stripeacc = $stripe->getStripeAccount($service);
736 
737  // We go here if $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is set.
738  // In such a case, payment is always ok when we call the "charge" action.
739  $paymentintent_id = GETPOST("paymentintent_id", "alpha");
740 
741  // Force to use the correct API key
742  global $stripearrayofkeysbyenv;
743  \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']);
744 
745  try {
746  if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
747  $paymentintent = \Stripe\PaymentIntent::retrieve($paymentintent_id);
748  } else {
749  $paymentintent = \Stripe\PaymentIntent::retrieve($paymentintent_id, array("stripe_account" => $stripeacc));
750  }
751  } catch (Exception $e) {
752  $error++;
753  $errormessage = "CantRetrievePaymentIntent ".$e->getMessage();
754  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
755  setEventMessages($e->getMessage(), null, 'errors');
756  $action = '';
757  }
758 
759  if ($paymentintent->status != 'succeeded') {
760  $error++;
761  $errormessage = "StatusOfRetrievedIntent is not succeeded: ".$paymentintent->status;
762  dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
763  setEventMessages($paymentintent->status, null, 'errors');
764  $action = '';
765  } else {
766  // TODO We can also record the payment mode into llx_societe_rib with stripe $paymentintent->payment_method
767  // Note that with other old Stripe architecture (using Charge API), the payment mode was not recorded, so it is not mandatory to do it here.
768  //dol_syslog("Create payment_method for ".$paymentintent->payment_method, LOG_DEBUG, 0, '_payment');
769 
770  // Get here amount and currency used for payment and force value into $amount and $currency so the real amount is saved into session instead
771  // of the amount and currency retreived from the POST.
772  if (!empty($paymentintent->currency) && !empty($paymentintent->amount)) {
773  $currency = strtoupper($paymentintent->currency);
774  $amount = $paymentintent->amount;
775 
776  // Correct the amount according to unit of currency
777  // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
778  $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
779  if (!in_array($currency, $arrayzerounitcurrency)) {
780  $amount = $amount / 100;
781  }
782  }
783  }
784  }
785 
786 
787  $remoteip = getUserRemoteIP();
788 
789  $_SESSION["onlinetoken"] = $stripeToken;
790  $_SESSION["FinalPaymentAmt"] = $amount; // amount really paid (coming from Stripe). Will be used for check in paymentok.php.
791  $_SESSION["currencyCodeType"] = $currency; // currency really used for payment (coming from Stripe). Will be used for check in paymentok.php.
792  $_SESSION["paymentType"] = '';
793  $_SESSION['ipaddress'] = ($remoteip ? $remoteip : 'unknown'); // Payer ip
794  $_SESSION['payerID'] = is_object($customer) ? $customer->id : '';
795  $_SESSION['TRANSACTIONID'] = (is_object($charge) ? $charge->id : (is_object($paymentintent) ? $paymentintent->id : ''));
796  $_SESSION['errormessage'] = $errormessage;
797 
798  dol_syslog("Action charge stripe STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION=".getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')." ip=".$remoteip, LOG_DEBUG, 0, '_payment');
799  dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." FinalPaymentAmt=".$_SESSION["FinalPaymentAmt"]." currencyCodeType=".$_SESSION["currencyCodeType"]." payerID=".$_SESSION['payerID']." TRANSACTIONID=".$_SESSION['TRANSACTIONID'], LOG_DEBUG, 0, '_payment');
800  dol_syslog("FULLTAG=".$FULLTAG, LOG_DEBUG, 0, '_payment');
801  dol_syslog("error=".$error." errormessage=".$errormessage, LOG_DEBUG, 0, '_payment');
802  dol_syslog("_SERVER[SERVER_NAME] = ".(empty($_SERVER["SERVER_NAME"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_NAME"])), LOG_DEBUG, 0, '_payment');
803  dol_syslog("_SERVER[SERVER_ADDR] = ".(empty($_SERVER["SERVER_ADDR"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_ADDR"])), LOG_DEBUG, 0, '_payment');
804  dol_syslog("Now call the redirect to paymentok or paymentko, URL = ".($error ? $urlko : $urlok), LOG_DEBUG, 0, '_payment');
805 
806  if ($error) {
807  header("Location: ".$urlko);
808  exit;
809  } else {
810  header("Location: ".$urlok);
811  exit;
812  }
813 }
814 
815 
816 /*
817  * View
818  */
819 
820 $form = new Form($db);
821 
822 $head = '';
823 if (!empty($conf->global->ONLINE_PAYMENT_CSS_URL)) {
824  $head = '<link rel="stylesheet" type="text/css" href="'.$conf->global->ONLINE_PAYMENT_CSS_URL.'?lang='.$langs->defaultlang.'">'."\n";
825 }
826 
827 $conf->dol_hide_topmenu = 1;
828 $conf->dol_hide_leftmenu = 1;
829 
830 $replacemainarea = (empty($conf->dol_hide_leftmenu) ? '<div>' : '').'<div>';
831 llxHeader($head, $langs->trans("PaymentForm"), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea);
832 
833 dol_syslog("--- newpayment.php action = ".$action, LOG_DEBUG, 0, '_payment');
834 dol_syslog("newpayment.php show page source=".$source." paymentmethod=".$paymentmethod.' amount='.$amount.' newamount='.GETPOST("newamount", 'alpha')." ref=".$ref, LOG_DEBUG, 0, '_payment');
835 dol_syslog("_SERVER[SERVER_NAME] = ".(empty($_SERVER["SERVER_NAME"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_NAME"])), LOG_DEBUG, 0, '_payment');
836 dol_syslog("_SERVER[SERVER_ADDR] = ".(empty($_SERVER["SERVER_ADDR"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_ADDR"])), LOG_DEBUG, 0, '_payment');
837 
838 // Check link validity
839 if ($source && in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', 'donation_ref', ''))) {
840  $langs->load("errors");
841  dol_print_error_email('BADREFINPAYMENTFORM', $langs->trans("ErrorBadLinkSourceSetButBadValueForRef", $source, $ref));
842  // End of page
843  llxFooter();
844  $db->close();
845  exit;
846 }
847 
848 
849 // Show sandbox warning
850 if ((empty($paymentmethod) || $paymentmethod == 'paypal') && isModEnabled('paypal') && (!empty($conf->global->PAYPAL_API_SANDBOX) || GETPOST('forcesandbox', 'int'))) { // We can force sand box with param 'forcesandbox'
851  dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Paypal'), '', 'warning');
852 }
853 if ((empty($paymentmethod) || $paymentmethod == 'stripe') && isModEnabled('stripe') && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'int'))) {
854  dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning');
855 }
856 
857 
858 print '<span id="dolpaymentspan"></span>'."\n";
859 print '<div class="center">'."\n";
860 print '<form id="dolpaymentform" class="center" name="paymentform" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
861 print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
862 print '<input type="hidden" name="action" value="dopayment">'."\n";
863 print '<input type="hidden" name="tag" value="'.GETPOST("tag", 'alpha').'">'."\n";
864 print '<input type="hidden" name="suffix" value="'.dol_escape_htmltag($suffix).'">'."\n";
865 print '<input type="hidden" name="securekey" value="'.dol_escape_htmltag($SECUREKEY).'">'."\n";
866 print '<input type="hidden" name="e" value="'.$entity.'" />';
867 print '<input type="hidden" name="forcesandbox" value="'.GETPOST('forcesandbox', 'int').'" />';
868 print "\n";
869 
870 
871 // Show logo (search order: logo defined by PAYMENT_LOGO_suffix, then PAYMENT_LOGO, then small company logo, large company logo, theme logo, common logo)
872 // Define logo and logosmall
873 $logosmall = $mysoc->logo_small;
874 $logo = $mysoc->logo;
875 $paramlogo = 'ONLINE_PAYMENT_LOGO_'.$suffix;
876 if (!empty($conf->global->$paramlogo)) {
877  $logosmall = $conf->global->$paramlogo;
878 } elseif (!empty($conf->global->ONLINE_PAYMENT_LOGO)) {
879  $logosmall = $conf->global->ONLINE_PAYMENT_LOGO;
880 }
881 //print '<!-- Show logo (logosmall='.$logosmall.' logo='.$logo.') -->'."\n";
882 // Define urllogo
883 $urllogo = '';
884 $urllogofull = '';
885 if (!empty($logosmall) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$logosmall)) {
886  $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/thumbs/'.$logosmall);
887  $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall);
888 } elseif (!empty($logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$logo)) {
889  $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/'.$logo);
890  $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo);
891 }
892 
893 // Output html code for logo
894 if ($urllogo) {
895  print '<div class="backgreypublicpayment">';
896  print '<div class="logopublicpayment">';
897  print '<img id="dolpaymentlogo" src="'.$urllogo.'"';
898  print '>';
899  print '</div>';
900  if (empty($conf->global->MAIN_HIDE_POWERED_BY)) {
901  print '<div class="poweredbypublicpayment opacitymedium right"><a class="poweredbyhref" href="https://www.dolibarr.org?utm_medium=website&utm_source=poweredby" target="dolibarr" rel="noopener">'.$langs->trans("PoweredBy").'<br><img class="poweredbyimg" src="'.DOL_URL_ROOT.'/theme/dolibarr_logo.svg" width="80px"></a></div>';
902  }
903  print '</div>';
904 }
905 if (!empty($conf->global->MAIN_IMAGE_PUBLIC_PAYMENT)) {
906  print '<div class="backimagepublicpayment">';
907  print '<img id="idMAIN_IMAGE_PUBLIC_PAYMENT" src="'.$conf->global->MAIN_IMAGE_PUBLIC_PAYMENT.'">';
908  print '</div>';
909 }
910 
911 
912 
913 
914 print '<!-- Form to send a payment -->'."\n";
915 print '<!-- creditor = '.dol_escape_htmltag($creditor).' -->'."\n";
916 // Additionnal information for each payment system
917 if (isModEnabled('paypal')) {
918  print '<!-- PAYPAL_API_SANDBOX = '.getDolGlobalString('PAYPAL_API_SANDBOX').' -->'."\n";
919  print '<!-- PAYPAL_API_INTEGRAL_OR_PAYPALONLY = '.getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY').' -->'."\n";
920 }
921 if (isModEnabled('paybox')) {
922  print '<!-- PAYBOX_CGI_URL = '.getDolGlobalString('PAYBOX_CGI_URL_V2').' -->'."\n";
923 }
924 if (isModEnabled('stripe')) {
925  print '<!-- STRIPE_LIVE = '.getDolGlobalString('STRIPE_LIVE').' -->'."\n";
926 }
927 print '<!-- urlok = '.$urlok.' -->'."\n";
928 print '<!-- urlko = '.$urlko.' -->'."\n";
929 print "\n";
930 
931 // Section with payment informationsummary
932 print '<table id="dolpublictable" summary="Payment form" class="center">'."\n";
933 
934 // Output introduction text
935 $text = '';
936 if (!empty($conf->global->PAYMENT_NEWFORM_TEXT)) {
937  $langs->load("members");
938  if (preg_match('/^\‍((.*)\‍)$/', $conf->global->PAYMENT_NEWFORM_TEXT, $reg)) {
939  $text .= $langs->trans($reg[1])."<br>\n";
940  } else {
941  $text .= $conf->global->PAYMENT_NEWFORM_TEXT."<br>\n";
942  }
943  $text = '<tr><td align="center"><br>'.$text.'<br></td></tr>'."\n";
944 }
945 if (empty($text)) {
946  $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnPaymentPage").'</strong></td></tr>'."\n";
947  $text .= '<tr><td class="textpublicpayment">'.$langs->trans("ThisScreenAllowsYouToPay", $creditor).'<br><br></td></tr>'."\n";
948 }
949 print $text;
950 
951 // Output payment summary form
952 print '<tr><td align="center">';
953 print '<table with="100%" id="tablepublicpayment">';
954 print '<tr><td align="left" colspan="2" class="opacitymedium">'.$langs->trans("ThisIsInformationOnPayment").' :</td></tr>'."\n";
955 
956 $found = false;
957 $error = 0;
958 
959 $object = null;
960 
961 
962 // Free payment
963 if (!$source) {
964  $found = true;
965  $tag = GETPOST("tag", 'alpha');
966  if (GETPOST('fulltag', 'alpha')) {
967  $fulltag = GETPOST('fulltag', 'alpha');
968  } else {
969  $fulltag = "TAG=".$tag;
970  }
971 
972  // Creditor
973  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
974  print '</td><td class="CTableRow2">';
975  print img_picto('', 'company', 'class="pictofixedwidth"');
976  print '<b>'.$creditor.'</b>';
977  print '<input type="hidden" name="creditor" value="'.$creditor.'">';
978  print '</td></tr>'."\n";
979 
980  // Amount
981  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
982  if (empty($amount)) {
983  print ' ('.$langs->trans("ToComplete").')';
984  }
985  print '</td><td class="CTableRow2">';
986  if (empty($amount) || !is_numeric($amount)) {
987  print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
988  print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
989  // Currency
990  print ' <b>'.$langs->trans("Currency".$currency).'</b>';
991  } else {
992  print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
993  print '<input type="hidden" name="amount" value="'.$amount.'">';
994  print '<input type="hidden" name="newamount" value="'.$amount.'">';
995  }
996  print '<input type="hidden" name="currency" value="'.$currency.'">';
997  print '</td></tr>'."\n";
998 
999  // Tag
1000  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1001  print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1002  print '<input type="hidden" name="tag" value="'.$tag.'">';
1003  print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1004  print '</td></tr>'."\n";
1005 
1006  // We do not add fields shipToName, shipToStreet, shipToCity, shipToState, shipToCountryCode, shipToZip, shipToStreet2, phoneNum
1007  // as they don't exists (buyer is unknown, tag is free).
1008 }
1009 
1010 
1011 // Payment on sales order
1012 if ($source == 'order') {
1013  $found = true;
1014  $langs->load("orders");
1015 
1016  require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
1017 
1018  $order = new Commande($db);
1019  $result = $order->fetch('', $ref);
1020  if ($result <= 0) {
1021  $mesg = $order->error;
1022  $error++;
1023  } else {
1024  $result = $order->fetch_thirdparty($order->socid);
1025  }
1026  $object = $order;
1027 
1028  if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1029  $amount = $order->total_ttc;
1030  if (GETPOST("amount", 'alpha')) {
1031  $amount = GETPOST("amount", 'alpha');
1032  }
1033  $amount = price2num($amount);
1034  }
1035 
1036  if (GETPOST('fulltag', 'alpha')) {
1037  $fulltag = GETPOST('fulltag', 'alpha');
1038  } else {
1039  $fulltag = 'ORD='.$order->id.'.CUS='.$order->thirdparty->id;
1040  if (!empty($TAG)) {
1041  $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1042  }
1043  }
1044  $fulltag = dol_string_unaccent($fulltag);
1045 
1046  // Creditor
1047  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1048  print '</td><td class="CTableRow2">';
1049  print img_picto('', 'company', 'class="pictofixedwidth"');
1050  print '<b>'.$creditor.'</b>';
1051  print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1052  print '</td></tr>'."\n";
1053 
1054  // Debitor
1055  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1056  print '</td><td class="CTableRow2">';
1057  print img_picto('', 'company', 'class="pictofixedwidth"');
1058  print '<b>'.$order->thirdparty->name.'</b>';
1059  print '</td></tr>'."\n";
1060 
1061  // Object
1062  $text = '<b>'.$langs->trans("PaymentOrderRef", $order->ref).'</b>';
1063  if (GETPOST('desc', 'alpha')) {
1064  $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1065  }
1066  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1067  print '</td><td class="CTableRow2">'.$text;
1068  print '<input type="hidden" name="s" value="'.dol_escape_htmltag($source).'">';
1069  print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($order->ref).'">';
1070  print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag($order->id).'">';
1071  $directdownloadlink = $order->getLastMainDocLink('commande');
1072  if ($directdownloadlink) {
1073  print '<br><a href="'.$directdownloadlink.'" rel="nofollow noopener">';
1074  print img_mime($order->last_main_doc, '');
1075  print $langs->trans("DownloadDocument").'</a>';
1076  }
1077  print '</td></tr>'."\n";
1078 
1079  // Amount
1080  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1081  if (empty($amount)) {
1082  print ' ('.$langs->trans("ToComplete").')';
1083  }
1084  print '</td><td class="CTableRow2">';
1085  if (empty($amount) || !is_numeric($amount)) {
1086  print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1087  print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1088  // Currency
1089  print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1090  } else {
1091  print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1092  print '<input type="hidden" name="amount" value="'.$amount.'">';
1093  print '<input type="hidden" name="newamount" value="'.$amount.'">';
1094  }
1095  print '<input type="hidden" name="currency" value="'.$currency.'">';
1096  print '</td></tr>'."\n";
1097 
1098  // Tag
1099  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1100  print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1101  print '<input type="hidden" name="tag" value="'.dol_escape_htmltag($tag).'">';
1102  print '<input type="hidden" name="fulltag" value="'.dol_escape_htmltag($fulltag).'">';
1103  print '</td></tr>'."\n";
1104 
1105  // Shipping address
1106  $shipToName = $order->thirdparty->name;
1107  $shipToStreet = $order->thirdparty->address;
1108  $shipToCity = $order->thirdparty->town;
1109  $shipToState = $order->thirdparty->state_code;
1110  $shipToCountryCode = $order->thirdparty->country_code;
1111  $shipToZip = $order->thirdparty->zip;
1112  $shipToStreet2 = '';
1113  $phoneNum = $order->thirdparty->phone;
1114  if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1115  print '<input type="hidden" name="shipToName" value="'.dol_escape_htmltag($shipToName).'">'."\n";
1116  print '<input type="hidden" name="shipToStreet" value="'.dol_escape_htmltag($shipToStreet).'">'."\n";
1117  print '<input type="hidden" name="shipToCity" value="'.dol_escape_htmltag($shipToCity).'">'."\n";
1118  print '<input type="hidden" name="shipToState" value="'.dol_escape_htmltag($shipToState).'">'."\n";
1119  print '<input type="hidden" name="shipToCountryCode" value="'.dol_escape_htmltag($shipToCountryCode).'">'."\n";
1120  print '<input type="hidden" name="shipToZip" value="'.dol_escape_htmltag($shipToZip).'">'."\n";
1121  print '<input type="hidden" name="shipToStreet2" value="'.dol_escape_htmltag($shipToStreet2).'">'."\n";
1122  print '<input type="hidden" name="phoneNum" value="'.dol_escape_htmltag($phoneNum).'">'."\n";
1123  } else {
1124  print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1125  }
1126  if (is_object($order->thirdparty)) {
1127  print '<input type="hidden" name="thirdparty_id" value="'.$order->thirdparty->id.'">'."\n";
1128  }
1129  print '<input type="hidden" name="email" value="'.$order->thirdparty->email.'">'."\n";
1130  print '<input type="hidden" name="vatnumber" value="'.dol_escape_htmltag($order->thirdparty->tva_intra).'">'."\n";
1131  $labeldesc = $langs->trans("Order").' '.$order->ref;
1132  if (GETPOST('desc', 'alpha')) {
1133  $labeldesc = GETPOST('desc', 'alpha');
1134  }
1135  print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1136 }
1137 
1138 
1139 // Payment on customer invoice
1140 if ($source == 'invoice') {
1141  $found = true;
1142  $langs->load("bills");
1143 
1144  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1145 
1146  $invoice = new Facture($db);
1147  $result = $invoice->fetch('', $ref);
1148  if ($result <= 0) {
1149  $mesg = $invoice->error;
1150  $error++;
1151  } else {
1152  $result = $invoice->fetch_thirdparty($invoice->socid);
1153  }
1154  $object = $invoice;
1155 
1156  if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1157  $amount = price2num($invoice->total_ttc - ($invoice->getSommePaiement() + $invoice->getSumCreditNotesUsed() + $invoice->getSumDepositsUsed()));
1158  if (GETPOST("amount", 'alpha')) {
1159  $amount = GETPOST("amount", 'alpha');
1160  }
1161  $amount = price2num($amount);
1162  }
1163 
1164  if (GETPOST('fulltag', 'alpha')) {
1165  $fulltag = GETPOST('fulltag', 'alpha');
1166  } else {
1167  $fulltag = 'INV='.$invoice->id.'.CUS='.$invoice->thirdparty->id;
1168  if (!empty($TAG)) {
1169  $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1170  }
1171  }
1172  $fulltag = dol_string_unaccent($fulltag);
1173 
1174  // Creditor
1175  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1176  print '</td><td class="CTableRow2">';
1177  print img_picto('', 'company', 'class="pictofixedwidth"');
1178  print '<b>'.$creditor.'</b>';
1179  print '<input type="hidden" name="creditor" value="'.dol_escape_htmltag($creditor).'">';
1180  print '</td></tr>'."\n";
1181 
1182  // Debitor
1183  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1184  print '</td><td class="CTableRow2">';
1185  print img_picto('', 'company', 'class="pictofixedwidth"');
1186  print '<b>'.$invoice->thirdparty->name.'</b>';
1187  print '</td></tr>'."\n";
1188 
1189  // Object
1190  $text = '<b>'.$langs->trans("PaymentInvoiceRef", $invoice->ref).'</b>';
1191  if (GETPOST('desc', 'alpha')) {
1192  $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1193  }
1194  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1195  print '</td><td class="CTableRow2">'.$text;
1196  print '<input type="hidden" name="s" value="'.dol_escape_htmltag($source).'">';
1197  print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($invoice->ref).'">';
1198  print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag($invoice->id).'">';
1199  $directdownloadlink = $invoice->getLastMainDocLink('facture');
1200  if ($directdownloadlink) {
1201  print '<br><a href="'.$directdownloadlink.'">';
1202  print img_mime($invoice->last_main_doc, '');
1203  print $langs->trans("DownloadDocument").'</a>';
1204  }
1205  print '</td></tr>'."\n";
1206 
1207  // Amount
1208  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentAmount");
1209  if (empty($amount) && empty($object->paye)) {
1210  print ' ('.$langs->trans("ToComplete").')';
1211  }
1212  print '</td><td class="CTableRow2">';
1213  if ($object->type == $object::TYPE_CREDIT_NOTE) {
1214  print '<b>'.$langs->trans("CreditNote").'</b>';
1215  } elseif (empty($object->paye)) {
1216  if (empty($amount) || !is_numeric($amount)) {
1217  print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1218  print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1219  print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1220  } else {
1221  print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1222  print '<input type="hidden" name="amount" value="'.$amount.'">';
1223  print '<input type="hidden" name="newamount" value="'.$amount.'">';
1224  }
1225  } else {
1226  print '<b class="amount">'.price($object->total_ttc, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1227  }
1228  print '<input type="hidden" name="currency" value="'.$currency.'">';
1229  print '</td></tr>'."\n";
1230 
1231  // Tag
1232  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1233  print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1234  print '<input type="hidden" name="tag" value="'.$tag.'">';
1235  print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1236  print '</td></tr>'."\n";
1237 
1238  // Shipping address
1239  $shipToName = $invoice->thirdparty->name;
1240  $shipToStreet = $invoice->thirdparty->address;
1241  $shipToCity = $invoice->thirdparty->town;
1242  $shipToState = $invoice->thirdparty->state_code;
1243  $shipToCountryCode = $invoice->thirdparty->country_code;
1244  $shipToZip = $invoice->thirdparty->zip;
1245  $shipToStreet2 = '';
1246  $phoneNum = $invoice->thirdparty->phone;
1247  if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1248  print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1249  print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1250  print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1251  print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1252  print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1253  print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1254  print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1255  print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1256  } else {
1257  print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1258  }
1259  if (is_object($invoice->thirdparty)) {
1260  print '<input type="hidden" name="thirdparty_id" value="'.$invoice->thirdparty->id.'">'."\n";
1261  }
1262  print '<input type="hidden" name="email" value="'.$invoice->thirdparty->email.'">'."\n";
1263  print '<input type="hidden" name="vatnumber" value="'.$invoice->thirdparty->tva_intra.'">'."\n";
1264  $labeldesc = $langs->trans("Invoice").' '.$invoice->ref;
1265  if (GETPOST('desc', 'alpha')) {
1266  $labeldesc = GETPOST('desc', 'alpha');
1267  }
1268  print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1269 }
1270 
1271 // Payment on contract line
1272 if ($source == 'contractline') {
1273  $found = true;
1274  $langs->load("contracts");
1275 
1276  require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
1277 
1278  $contract = new Contrat($db);
1279  $contractline = new ContratLigne($db);
1280 
1281  $result = $contractline->fetch('', $ref);
1282  if ($result <= 0) {
1283  $mesg = $contractline->error;
1284  $error++;
1285  } else {
1286  if ($contractline->fk_contrat > 0) {
1287  $result = $contract->fetch($contractline->fk_contrat);
1288  if ($result > 0) {
1289  $result = $contract->fetch_thirdparty($contract->socid);
1290  } else {
1291  $mesg = $contract->error;
1292  $error++;
1293  }
1294  } else {
1295  $mesg = 'ErrorRecordNotFound';
1296  $error++;
1297  }
1298  }
1299  $object = $contractline;
1300 
1301  if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1302  $amount = $contractline->total_ttc;
1303 
1304  if ($contractline->fk_product && !empty($conf->global->PAYMENT_USE_NEW_PRICE_FOR_CONTRACTLINES)) {
1305  $product = new Product($db);
1306  $result = $product->fetch($contractline->fk_product);
1307 
1308  // We define price for product (TODO Put this in a method in product class)
1309  if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
1310  $pu_ht = $product->multiprices[$contract->thirdparty->price_level];
1311  $pu_ttc = $product->multiprices_ttc[$contract->thirdparty->price_level];
1312  $price_base_type = $product->multiprices_base_type[$contract->thirdparty->price_level];
1313  } else {
1314  $pu_ht = $product->price;
1315  $pu_ttc = $product->price_ttc;
1316  $price_base_type = $product->price_base_type;
1317  }
1318 
1319  $amount = $pu_ttc;
1320  if (empty($amount)) {
1321  dol_print_error('', 'ErrorNoPriceDefinedForThisProduct');
1322  exit;
1323  }
1324  }
1325 
1326  if (GETPOST("amount", 'alpha')) {
1327  $amount = GETPOST("amount", 'alpha');
1328  }
1329  $amount = price2num($amount);
1330  }
1331 
1332  if (GETPOST('fulltag', 'alpha')) {
1333  $fulltag = GETPOST('fulltag', 'alpha');
1334  } else {
1335  $fulltag = 'COL='.$contractline->id.'.CON='.$contract->id.'.CUS='.$contract->thirdparty->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1336  if (!empty($TAG)) {
1337  $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1338  }
1339  }
1340  $fulltag = dol_string_unaccent($fulltag);
1341 
1342  $qty = 1;
1343  if (GETPOST('qty')) {
1344  $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
1345  }
1346 
1347  // Creditor
1348  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1349  print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1350  print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1351  print '</td></tr>'."\n";
1352 
1353  // Debitor
1354  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1355  print '</td><td class="CTableRow2"><b>'.$contract->thirdparty->name.'</b>';
1356  print '</td></tr>'."\n";
1357 
1358  // Object
1359  $text = '<b>'.$langs->trans("PaymentRenewContractId", $contract->ref, $contractline->ref).'</b>';
1360  if ($contractline->fk_product > 0) {
1361  $contractline->fetch_product();
1362  $text .= '<br>'.$contractline->product->ref.($contractline->product->label ? ' - '.$contractline->product->label : '');
1363  }
1364  if ($contractline->description) {
1365  $text .= '<br>'.dol_htmlentitiesbr($contractline->description);
1366  }
1367  if ($contractline->date_end) {
1368  $text .= '<br>'.$langs->trans("ExpiredSince").': '.dol_print_date($contractline->date_end);
1369  }
1370  if (GETPOST('desc', 'alpha')) {
1371  $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1372  }
1373  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1374  print '</td><td class="CTableRow2">'.$text;
1375  print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1376  print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($contractline->ref).'">';
1377  print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag($contractline->id).'">';
1378  $directdownloadlink = $contract->getLastMainDocLink('contract');
1379  if ($directdownloadlink) {
1380  print '<br><a href="'.$directdownloadlink.'">';
1381  print img_mime($contract->last_main_doc, '');
1382  print $langs->trans("DownloadDocument").'</a>';
1383  }
1384  print '</td></tr>'."\n";
1385 
1386  // Quantity
1387  $label = $langs->trans("Quantity");
1388  $qty = 1;
1389  $duration = '';
1390  if ($contractline->fk_product) {
1391  if ($contractline->product->isService() && $contractline->product->duration_value > 0) {
1392  $label = $langs->trans("Duration");
1393 
1394  // TODO Put this in a global method
1395  if ($contractline->product->duration_value > 1) {
1396  $dur = array("h"=>$langs->trans("Hours"), "d"=>$langs->trans("DurationDays"), "w"=>$langs->trans("DurationWeeks"), "m"=>$langs->trans("DurationMonths"), "y"=>$langs->trans("DurationYears"));
1397  } else {
1398  $dur = array("h"=>$langs->trans("Hour"), "d"=>$langs->trans("DurationDay"), "w"=>$langs->trans("DurationWeek"), "m"=>$langs->trans("DurationMonth"), "y"=>$langs->trans("DurationYear"));
1399  }
1400  $duration = $contractline->product->duration_value.' '.$dur[$contractline->product->duration_unit];
1401  }
1402  }
1403  print '<tr class="CTableRow2"><td class="CTableRow2">'.$label.'</td>';
1404  print '<td class="CTableRow2"><b>'.($duration ? $duration : $qty).'</b>';
1405  print '<input type="hidden" name="newqty" value="'.dol_escape_htmltag($qty).'">';
1406  print '</b></td></tr>'."\n";
1407 
1408  // Amount
1409  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1410  if (empty($amount)) {
1411  print ' ('.$langs->trans("ToComplete").')';
1412  }
1413  print '</td><td class="CTableRow2">';
1414  if (empty($amount) || !is_numeric($amount)) {
1415  print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1416  print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1417  // Currency
1418  print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1419  } else {
1420  print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1421  print '<input type="hidden" name="amount" value="'.$amount.'">';
1422  print '<input type="hidden" name="newamount" value="'.$amount.'">';
1423  }
1424  print '<input type="hidden" name="currency" value="'.$currency.'">';
1425  print '</td></tr>'."\n";
1426 
1427  // Tag
1428  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1429  print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1430  print '<input type="hidden" name="tag" value="'.$tag.'">';
1431  print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1432  print '</td></tr>'."\n";
1433 
1434  // Shipping address
1435  $shipToName = $contract->thirdparty->name;
1436  $shipToStreet = $contract->thirdparty->address;
1437  $shipToCity = $contract->thirdparty->town;
1438  $shipToState = $contract->thirdparty->state_code;
1439  $shipToCountryCode = $contract->thirdparty->country_code;
1440  $shipToZip = $contract->thirdparty->zip;
1441  $shipToStreet2 = '';
1442  $phoneNum = $contract->thirdparty->phone;
1443  if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1444  print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1445  print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1446  print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1447  print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1448  print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1449  print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1450  print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1451  print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1452  } else {
1453  print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1454  }
1455  if (is_object($contract->thirdparty)) {
1456  print '<input type="hidden" name="thirdparty_id" value="'.$contract->thirdparty->id.'">'."\n";
1457  }
1458  print '<input type="hidden" name="email" value="'.$contract->thirdparty->email.'">'."\n";
1459  print '<input type="hidden" name="vatnumber" value="'.$contract->thirdparty->tva_intra.'">'."\n";
1460  $labeldesc = $langs->trans("Contract").' '.$contract->ref;
1461  if (GETPOST('desc', 'alpha')) {
1462  $labeldesc = GETPOST('desc', 'alpha');
1463  }
1464  print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1465 }
1466 
1467 // Payment on member subscription
1468 if ($source == 'member' || $source == 'membersubscription') {
1469  $newsource = 'member';
1470 
1471  $tag="";
1472  $found = true;
1473  $langs->load("members");
1474 
1475  require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1476  require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
1477  require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1478 
1479  $member = new Adherent($db);
1480  $adht = new AdherentType($db);
1481 
1482  $result = $member->fetch('', $ref);
1483  if ($result <= 0) {
1484  $mesg = $member->error;
1485  $error++;
1486  } else {
1487  $member->fetch_thirdparty();
1488  $subscription = new Subscription($db);
1489 
1490  $adht->fetch($member->typeid);
1491  }
1492  $object = $member;
1493 
1494  if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1495  $amount = $subscription->total_ttc;
1496  if (GETPOST("amount", 'alpha')) {
1497  $amount = GETPOST("amount", 'alpha');
1498  }
1499  // If amount still not defined, we take amount of the type of member
1500  if (empty($amount)) {
1501  $amount = $adht->amount;
1502  }
1503 
1504  $amount = max(0, price2num($amount, 'MT'));
1505  }
1506 
1507  if (GETPOST('fulltag', 'alpha')) {
1508  $fulltag = GETPOST('fulltag', 'alpha');
1509  } else {
1510  $fulltag = 'MEM='.$member->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1511  if (!empty($TAG)) {
1512  $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1513  }
1514  }
1515  $fulltag = dol_string_unaccent($fulltag);
1516 
1517  // Creditor
1518  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1519  print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1520  print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1521  print '</td></tr>'."\n";
1522 
1523  // Debitor
1524  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Member");
1525  print '</td><td class="CTableRow2">';
1526  print '<b>';
1527  if ($member->morphy == 'mor' && !empty($member->company)) {
1528  print img_picto('', 'company', 'class="pictofixedwidth"');
1529  print $member->company;
1530  } else {
1531  print img_picto('', 'member', 'class="pictofixedwidth"');
1532  print $member->getFullName($langs);
1533  }
1534  print '</b>';
1535  print '</td></tr>'."\n";
1536 
1537  // Object
1538  $text = '<b>'.$langs->trans("PaymentSubscription").'</b>';
1539  if (GETPOST('desc', 'alpha')) {
1540  $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1541  }
1542  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1543  print '</td><td class="CTableRow2">'.$text;
1544  print '<input type="hidden" name="source" value="'.dol_escape_htmltag($newsource).'">';
1545  print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($member->ref).'">';
1546  print '</td></tr>'."\n";
1547 
1548  if ($object->datefin > 0) {
1549  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("DateEndSubscription");
1550  print '</td><td class="CTableRow2">'.dol_print_date($member->datefin, 'day');
1551  print '</td></tr>'."\n";
1552  }
1553 
1554  if ($member->last_subscription_date || $member->last_subscription_amount) {
1555  // Last subscription date
1556 
1557  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastSubscriptionDate");
1558  print '</td><td class="CTableRow2">'.dol_print_date($member->last_subscription_date, 'day');
1559  print '</td></tr>'."\n";
1560 
1561  // Last subscription amount
1562 
1563  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastSubscriptionAmount");
1564  print '</td><td class="CTableRow2">'.price($member->last_subscription_amount);
1565  print '</td></tr>'."\n";
1566 
1567  if (empty($amount) && !GETPOST('newamount', 'alpha')) {
1568  $_GET['newamount'] = $member->last_subscription_amount;
1569  }
1570  }
1571 
1572  if ($member->type) {
1573  $oldtypeid = $member->typeid;
1574  $newtypeid = (int) (GETPOSTISSET("typeid") ? GETPOST("typeid", 'int') : $member->typeid);
1575 
1576  if (!empty($conf->global->MEMBER_ALLOW_CHANGE_OF_TYPE)) {
1577  require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
1578  $adht = new AdherentType($db);
1579  // Amount by member type
1580  $amountbytype = $adht->amountByType(1);
1581 
1582  // Last member type
1583  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastMemberType");
1584  print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1585  print "</td></tr>\n";
1586 
1587  // Set the new member type
1588  $member->typeid = $newtypeid;
1589  $member->type = dol_getIdFromCode($db, $newtypeid, 'adherent_type', 'rowid', 'libelle');
1590 
1591  // list member type
1592  if (!$action) {
1593  // Set amount for the subscription
1594  $amount = (!empty($amountbytype[$member->typeid])) ? $amountbytype[$member->typeid] : $member->last_subscription_amount;
1595 
1596  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("NewSubscription");
1597  print '</td><td class="CTableRow2">';
1598  print $form->selectarray("typeid", $adht->liste_array(1), $member->typeid, 0, 0, 0, 'onchange="window.location.replace(\''.$urlwithroot.'/public/payment/newpayment.php?source='.urlencode($source).'&ref='.urlencode($ref).'&amount='.urlencode($amount).'&typeid=\' + this.value + \'&securekey='.urlencode($SECUREKEY).'\');"', 0, 0, 0, '', '', 1);
1599  print "</td></tr>\n";
1600  } elseif ($action == 'dopayment') {
1601  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("NewMemberType");
1602  print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1603  print '<input type="hidden" name="membertypeid" value="'.$member->typeid.'">';
1604  print "</td></tr>\n";
1605  }
1606  } else {
1607  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("MemberType");
1608  print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1609  print "</td></tr>\n";
1610  }
1611  }
1612 
1613  // Amount
1614  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1615  // This place no longer allows amount edition
1616  if (!empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) {
1617  print ' - <a href="'.$conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO.'" rel="external" target="_blank" rel="noopener noreferrer">'.$langs->trans("SeeHere").'</a>';
1618  }
1619  print '</td><td class="CTableRow2">';
1620  if (!empty($conf->global->MEMBER_MIN_AMOUNT) && $amount) {
1621  $amount = max(0, $conf->global->MEMBER_MIN_AMOUNT, $amount);
1622  }
1623  print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1624  $caneditamount = !empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) || $adht->caneditamount;
1625  $minimumamount = empty($conf->global->MEMBER_MIN_AMOUNT)? $adht->amount : max($conf->global->MEMBER_MIN_AMOUNT, $adht->amount > $amount);
1626  if (!$caneditamount && $minimumamount > $amount) {
1627  print ' '. $langs->trans("AmountIsLowerToMinimumNotice", price($adht->amount, 1, $langs, 1, -1, -1, $currency));
1628  }
1629 
1630  print '<input type="hidden" name="amount" value="'.$amount.'">';
1631  print '<input type="hidden" name="newamount" value="'.$amount.'">';
1632  print '<input type="hidden" name="currency" value="'.$currency.'">';
1633  print '</td></tr>'."\n";
1634 
1635  // Tag
1636  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1637  print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1638  print '<input type="hidden" name="tag" value="'.$tag.'">';
1639  print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1640  print '</td></tr>'."\n";
1641 
1642  // Shipping address
1643  $shipToName = $member->getFullName($langs);
1644  $shipToStreet = $member->address;
1645  $shipToCity = $member->town;
1646  $shipToState = $member->state_code;
1647  $shipToCountryCode = $member->country_code;
1648  $shipToZip = $member->zip;
1649  $shipToStreet2 = '';
1650  $phoneNum = $member->phone;
1651  if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1652  print '<!-- Shipping address information -->';
1653  print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1654  print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1655  print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1656  print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1657  print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1658  print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1659  print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1660  print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1661  } else {
1662  print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1663  }
1664  if (is_object($member->thirdparty)) {
1665  print '<input type="hidden" name="thirdparty_id" value="'.$member->thirdparty->id.'">'."\n";
1666  }
1667  print '<input type="hidden" name="email" value="'.$member->email.'">'."\n";
1668  $labeldesc = $langs->trans("PaymentSubscription");
1669  if (GETPOST('desc', 'alpha')) {
1670  $labeldesc = GETPOST('desc', 'alpha');
1671  }
1672  print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1673 }
1674 
1675 // Payment on donation
1676 if ($source == 'donation') {
1677  $found = true;
1678  $langs->load("don");
1679 
1680  require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
1681 
1682  $don = new Don($db);
1683  $result = $don->fetch($ref);
1684  if ($result <= 0) {
1685  $mesg = $don->error;
1686  $error++;
1687  } else {
1688  $don->fetch_thirdparty();
1689  }
1690  $object = $don;
1691 
1692  if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1693  if (GETPOST("amount", 'alpha')) {
1694  $amount = GETPOST("amount", 'alpha');
1695  } else {
1696  $amount = $don->getRemainToPay();
1697  }
1698  $amount = price2num($amount);
1699  }
1700 
1701  if (GETPOST('fulltag', 'alpha')) {
1702  $fulltag = GETPOST('fulltag', 'alpha');
1703  } else {
1704  $fulltag = 'DON='.$don->ref.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1705  if (!empty($TAG)) {
1706  $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1707  }
1708  }
1709  $fulltag = dol_string_unaccent($fulltag);
1710 
1711  // Creditor
1712  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1713  print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1714  print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1715  print '</td></tr>'."\n";
1716 
1717  // Debitor
1718  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1719  print '</td><td class="CTableRow2"><b>';
1720  if ($don->morphy == 'mor' && !empty($don->societe)) {
1721  print $don->societe;
1722  } else {
1723  print $don->getFullName($langs);
1724  }
1725  print '</b>';
1726  print '</td></tr>'."\n";
1727 
1728  // Object
1729  $text = '<b>'.$langs->trans("PaymentDonation").'</b>';
1730  if (GETPOST('desc', 'alpha')) {
1731  $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1732  }
1733  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1734  print '</td><td class="CTableRow2">'.$text;
1735  print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1736  print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($don->ref).'">';
1737  print '</td></tr>'."\n";
1738 
1739  // Amount
1740  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1741  if (empty($amount)) {
1742  if (empty($conf->global->MEMBER_NEWFORM_AMOUNT)) {
1743  print ' ('.$langs->trans("ToComplete");
1744  }
1745  if (!empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) {
1746  print ' - <a href="'.$conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO.'" rel="external" target="_blank" rel="noopener noreferrer">'.$langs->trans("SeeHere").'</a>';
1747  }
1748  if (empty($conf->global->MEMBER_NEWFORM_AMOUNT)) {
1749  print ')';
1750  }
1751  }
1752  print '</td><td class="CTableRow2">';
1753  $valtoshow = '';
1754  if (empty($amount) || !is_numeric($amount)) {
1755  $valtoshow = price2num(GETPOST("newamount", 'alpha'), 'MT');
1756  // force default subscription amount to value defined into constant...
1757  if (empty($valtoshow)) {
1758  if (!empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT)) {
1759  if (!empty($conf->global->MEMBER_NEWFORM_AMOUNT)) {
1760  $valtoshow = $conf->global->MEMBER_NEWFORM_AMOUNT;
1761  }
1762  } else {
1763  if (!empty($conf->global->MEMBER_NEWFORM_AMOUNT)) {
1764  $amount = $conf->global->MEMBER_NEWFORM_AMOUNT;
1765  }
1766  }
1767  }
1768  }
1769  if (empty($amount) || !is_numeric($amount)) {
1770  //$valtoshow=price2num(GETPOST("newamount",'alpha'),'MT');
1771  if (!empty($conf->global->MEMBER_MIN_AMOUNT) && $valtoshow) {
1772  $valtoshow = max($conf->global->MEMBER_MIN_AMOUNT, $valtoshow);
1773  }
1774  print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1775  print '<input class="flat maxwidth75" type="text" name="newamount" value="'.$valtoshow.'">';
1776  // Currency
1777  print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1778  } else {
1779  $valtoshow = $amount;
1780  if (!empty($conf->global->MEMBER_MIN_AMOUNT) && $valtoshow) {
1781  $valtoshow = max($conf->global->MEMBER_MIN_AMOUNT, $valtoshow);
1782  $amount = $valtoshow;
1783  }
1784  print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1785  print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
1786  print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
1787  }
1788  print '<input type="hidden" name="currency" value="'.$currency.'">';
1789  print '</td></tr>'."\n";
1790 
1791  // Tag
1792  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1793  print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1794  print '<input type="hidden" name="tag" value="'.$tag.'">';
1795  print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1796  print '</td></tr>'."\n";
1797 
1798  // Shipping address
1799  $shipToName = $don->getFullName($langs);
1800  $shipToStreet = $don->address;
1801  $shipToCity = $don->town;
1802  $shipToState = $don->state_code;
1803  $shipToCountryCode = $don->country_code;
1804  $shipToZip = $don->zip;
1805  $shipToStreet2 = '';
1806  $phoneNum = $don->phone;
1807  if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1808  print '<!-- Shipping address information -->';
1809  print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1810  print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1811  print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1812  print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1813  print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1814  print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1815  print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1816  print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1817  } else {
1818  print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1819  }
1820  if (is_object($don->thirdparty)) {
1821  print '<input type="hidden" name="thirdparty_id" value="'.$don->thirdparty->id.'">'."\n";
1822  }
1823  print '<input type="hidden" name="email" value="'.$don->email.'">'."\n";
1824  $labeldesc = $langs->trans("PaymentSubscription");
1825  if (GETPOST('desc', 'alpha')) {
1826  $labeldesc = GETPOST('desc', 'alpha');
1827  }
1828  print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1829 }
1830 
1831 if ($source == 'organizedeventregistration') {
1832  $found = true;
1833  $langs->loadLangs(array("members", "eventorganization"));
1834 
1835  if (GETPOST('fulltag', 'alpha')) {
1836  $fulltag = GETPOST('fulltag', 'alpha');
1837  } else {
1838  $fulltag = 'ATT='.$attendee->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1839  if (!empty($TAG)) {
1840  $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1841  }
1842  }
1843  $fulltag = dol_string_unaccent($fulltag);
1844 
1845  // Creditor
1846  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1847  print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1848  print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1849  print '</td></tr>'."\n";
1850 
1851  // Debitor
1852  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Attendee");
1853  print '</td><td class="CTableRow2"><b>';
1854  print $attendee->email;
1855  print ($thirdparty->name ? ' ('.$thirdparty->name.')' : '');
1856  print '</b>';
1857  print '</td></tr>'."\n";
1858 
1859  if (! is_object($attendee->project)) {
1860  $text = 'ErrorProjectNotFound';
1861  } else {
1862  $text = $langs->trans("PaymentEvent").' - '.$attendee->project->title;
1863  }
1864 
1865  // Object
1866  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1867  print '</td><td class="CTableRow2"><b>'.$text.'</b>';
1868  print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1869  print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($invoice->id).'">';
1870  print '</td></tr>'."\n";
1871 
1872  // Amount
1873  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1874  print '</td><td class="CTableRow2">';
1875  $valtoshow = $amount;
1876  print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1877  print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
1878  print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
1879  print '<input type="hidden" name="currency" value="'.$currency.'">';
1880  print '</td></tr>'."\n";
1881 
1882  // Tag
1883  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1884  print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1885  print '<input type="hidden" name="tag" value="'.$tag.'">';
1886  print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1887  print '</td></tr>'."\n";
1888 
1889  // Shipping address
1890  $shipToName = $thirdparty->getFullName($langs);
1891  $shipToStreet = $thirdparty->address;
1892  $shipToCity = $thirdparty->town;
1893  $shipToState = $thirdparty->state_code;
1894  $shipToCountryCode = $thirdparty->country_code;
1895  $shipToZip = $thirdparty->zip;
1896  $shipToStreet2 = '';
1897  $phoneNum = $thirdparty->phone;
1898  if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1899  print '<!-- Shipping address information -->';
1900  print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1901  print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1902  print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1903  print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1904  print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1905  print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1906  print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1907  print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1908  } else {
1909  print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1910  }
1911  print '<input type="hidden" name="thirdparty_id" value="'.$thirdparty->id.'">'."\n";
1912  print '<input type="hidden" name="email" value="'.$thirdparty->email.'">'."\n";
1913  $labeldesc = $langs->trans("PaymentSubscription");
1914  if (GETPOST('desc', 'alpha')) {
1915  $labeldesc = GETPOST('desc', 'alpha');
1916  }
1917  print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1918 }
1919 
1920 if ($source == 'boothlocation') {
1921  $found = true;
1922  $langs->load("members");
1923 
1924  if (GETPOST('fulltag', 'alpha')) {
1925  $fulltag = GETPOST('fulltag', 'alpha');
1926  } else {
1927  $fulltag = 'BOO='.GETPOST("booth").'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1928  if (!empty($TAG)) {
1929  $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1930  }
1931  }
1932  $fulltag = dol_string_unaccent($fulltag);
1933 
1934  // Creditor
1935  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1936  print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1937  print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1938  print '</td></tr>'."\n";
1939 
1940  // Debitor
1941  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Attendee");
1942  print '</td><td class="CTableRow2"><b>';
1943  print $thirdparty->name;
1944  print '</b>';
1945  print '</td></tr>'."\n";
1946 
1947  // Object
1948  $text = '<b>'.$langs->trans("PaymentBoothLocation").'</b>';
1949  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1950  print '</td><td class="CTableRow2">'.$text;
1951  print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1952  print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($invoice->id).'">';
1953  print '</td></tr>'."\n";
1954 
1955  // Amount
1956  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1957  print '</td><td class="CTableRow2">';
1958  $valtoshow = $amount;
1959  print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1960  print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
1961  print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
1962  print '<input type="hidden" name="currency" value="'.$currency.'">';
1963  print '</td></tr>'."\n";
1964 
1965  // Tag
1966  print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1967  print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1968  print '<input type="hidden" name="tag" value="'.$tag.'">';
1969  print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1970  print '</td></tr>'."\n";
1971 
1972  // Shipping address
1973  $shipToName = $thirdparty->getFullName($langs);
1974  $shipToStreet = $thirdparty->address;
1975  $shipToCity = $thirdparty->town;
1976  $shipToState = $thirdparty->state_code;
1977  $shipToCountryCode = $thirdparty->country_code;
1978  $shipToZip = $thirdparty->zip;
1979  $shipToStreet2 = '';
1980  $phoneNum = $thirdparty->phone;
1981  if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1982  print '<!-- Shipping address information -->';
1983  print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1984  print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1985  print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1986  print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1987  print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1988  print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1989  print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1990  print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1991  } else {
1992  print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1993  }
1994  print '<input type="hidden" name="thirdparty_id" value="'.$thirdparty->id.'">'."\n";
1995  print '<input type="hidden" name="email" value="'.$thirdparty->email.'">'."\n";
1996  $labeldesc = $langs->trans("PaymentSubscription");
1997  if (GETPOST('desc', 'alpha')) {
1998  $labeldesc = GETPOST('desc', 'alpha');
1999  }
2000  print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
2001 }
2002 
2003 if (!$found && !$mesg) {
2004  $mesg = $langs->trans("ErrorBadParameters");
2005 }
2006 
2007 if ($mesg) {
2008  print '<tr><td align="center" colspan="2"><br><div class="warning">'.dol_escape_htmltag($mesg, 1, 1, 'br').'</div></td></tr>'."\n";
2009 }
2010 
2011 print '</table>'."\n";
2012 print "\n";
2013 
2014 
2015 // Show all payment mode buttons (Stripe, Paypal, ...)
2016 if ($action != 'dopayment') {
2017  if ($found && !$error) { // We are in a management option and no error
2018  // Check status of the object (Invoice) to verify if it is paid by external payment modules (ie Payzen, ...)
2019  $parameters = [
2020  'source' => $source,
2021  'object' => $object
2022  ];
2023  $reshook = $hookmanager->executeHooks('doCheckStatus', $parameters, $object, $action);
2024  if ($source == 'order' && $object->billed) {
2025  print '<br><br><span class="amountpaymentcomplete size15x">'.$langs->trans("OrderBilled").'</span>';
2026  } elseif ($source == 'invoice' && $object->paye) {
2027  print '<br><br><span class="amountpaymentcomplete size15x">'.$langs->trans("InvoicePaid").'</span>';
2028  } elseif ($source == 'donation' && $object->paid) {
2029  print '<br><br><span class="amountpaymentcomplete size15x">'.$langs->trans("DonationPaid").'</span>';
2030  } else {
2031  // Membership can be paid and we still allow to make renewal
2032  if (($source == 'member' || $source == 'membersubscription') && $object->datefin > dol_now()) {
2033  $langs->load("members");
2034  print '<br><span class="amountpaymentcomplete size15x">'.$langs->trans("MembershipPaid", dol_print_date($object->datefin, 'day')).'</span><br>';
2035  print '<div class="opacitymedium margintoponly">'.$langs->trans("PaymentWillBeRecordedForNextPeriod").'</div>';
2036  }
2037 
2038  // Buttons for all payments registration methods
2039 
2040  // This hook is used to add Button to newpayment.php for external payment modules (ie Payzen, ...)
2041  $parameters = [
2042  'paymentmethod' => $paymentmethod
2043  ];
2044  $reshook = $hookmanager->executeHooks('doAddButton', $parameters, $object, $action);
2045  if ((empty($paymentmethod) || $paymentmethod == 'paybox') && isModEnabled('paybox')) {
2046  print '<div class="button buttonpayment" id="div_dopayment_paybox"><span class="fa fa-credit-card"></span> <input class="" type="submit" id="dopayment_paybox" name="dopayment_paybox" value="'.$langs->trans("PayBoxDoPayment").'">';
2047  print '<br>';
2048  print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span>';
2049  print '</div>';
2050  print '<script>
2051  $( document ).ready(function() {
2052  $("#div_dopayment_paybox").click(function(){
2053  $("#dopayment_paybox").click();
2054  });
2055  $("#dopayment_paybox").click(function(e){
2056  $("#div_dopayment_paybox").css( \'cursor\', \'wait\' );
2057  e.stopPropagation();
2058  });
2059  });
2060  </script>
2061  ';
2062  }
2063 
2064  if ((empty($paymentmethod) || $paymentmethod == 'stripe') && isModEnabled('stripe')) {
2065  print '<div class="button buttonpayment" id="div_dopayment_stripe"><span class="fa fa-credit-card"></span> <input class="" type="submit" id="dopayment_stripe" name="dopayment_stripe" value="'.$langs->trans("StripeDoPayment").'">';
2066  print '<input type="hidden" name="noidempotency" value="'.GETPOST('noidempotency', 'int').'">';
2067  print '<br>';
2068  print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span>';
2069  print '</div>';
2070  print '<script>
2071  $( document ).ready(function() {
2072  $("#div_dopayment_stripe").click(function(){
2073  $("#dopayment_stripe").click();
2074  });
2075  $("#dopayment_stripe").click(function(e){
2076  $("#div_dopayment_stripe").css( \'cursor\', \'wait\' );
2077  e.stopPropagation();
2078  return true;
2079  });
2080  });
2081  </script>
2082  ';
2083  }
2084 
2085  if ((empty($paymentmethod) || $paymentmethod == 'paypal') && isModEnabled('paypal')) {
2086  if (empty($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY)) {
2087  $conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY = 'integral';
2088  }
2089 
2090  print '<div class="button buttonpayment" id="div_dopayment_paypal">';
2091  if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY != 'integral') {
2092  print '<div style="line-height: 1em">&nbsp;</div>';
2093  }
2094  print '<span class="fa fa-paypal"></span> <input class="" type="submit" id="dopayment_paypal" name="dopayment_paypal" value="'.$langs->trans("PaypalDoPayment").'">';
2095  if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'integral') {
2096  print '<br>';
2097  print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span><span class="buttonpaymentsmall"> - </span>';
2098  print '<span class="buttonpaymentsmall">'.$langs->trans("PayPalBalance").'</span>';
2099  }
2100  if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'paypalonly') {
2101  //print '<br>';
2102  //print '<span class="buttonpaymentsmall">'.$langs->trans("PayPalBalance").'"></span>';
2103  }
2104  print '</div>';
2105  print '<script>
2106  $( document ).ready(function() {
2107  $("#div_dopayment_paypal").click(function(){
2108  $("#dopayment_paypal").click();
2109  });
2110  $("#dopayment_paypal").click(function(e){
2111  $("#div_dopayment_paypal").css( \'cursor\', \'wait\' );
2112  e.stopPropagation();
2113  return true;
2114  });
2115  });
2116  </script>
2117  ';
2118  }
2119  }
2120  } else {
2121  dol_print_error_email('ERRORNEWPAYMENT');
2122  }
2123 } else {
2124  // Print
2125 }
2126 
2127 print '</td></tr>'."\n";
2128 
2129 print '</table>'."\n";
2130 
2131 print '</form>'."\n";
2132 print '</div>'."\n";
2133 
2134 print '<br>';
2135 
2136 
2137 
2138 // Add more content on page for some services
2139 if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payment mode
2140  // Save some data for the paymentok
2141  $remoteip = getUserRemoteIP();
2142  $_SESSION["currencyCodeType"] = $currency;
2143  $_SESSION["FinalPaymentAmt"] = $amount;
2144  $_SESSION['ipaddress'] = ($remoteip ? $remoteip : 'unknown'); // Payer ip
2145  $_SESSION["paymentType"] = '';
2146 
2147  // For Stripe
2148  if (GETPOST('dopayment_stripe', 'alpha')) {
2149  // Personalized checkout
2150  print '<style>
2155  .StripeElement {
2156  background-color: white;
2157  padding: 8px 12px;
2158  border-radius: 4px;
2159  border: 1px solid transparent;
2160  box-shadow: 0 1px 3px 0 #e6ebf1;
2161  -webkit-transition: box-shadow 150ms ease;
2162  transition: box-shadow 150ms ease;
2163  }
2164 
2165  .StripeElement--focus {
2166  box-shadow: 0 1px 3px 0 #cfd7df;
2167  }
2168 
2169  .StripeElement--invalid {
2170  border-color: #fa755a;
2171  }
2172 
2173  .StripeElement--webkit-autofill {
2174  background-color: #fefde5 !important;
2175  }
2176  </style>';
2177 
2178  //print '<br>';
2179 
2180  print '<!-- Form payment-form STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = '.$conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION.' STRIPE_USE_NEW_CHECKOUT = '.$conf->global->STRIPE_USE_NEW_CHECKOUT.' -->'."\n";
2181  print '<form action="'.$_SERVER['REQUEST_URI'].'" method="POST" id="payment-form">'."\n";
2182 
2183  print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
2184  print '<input type="hidden" name="dopayment_stripe" value="1">'."\n";
2185  print '<input type="hidden" name="action" value="charge">'."\n";
2186  print '<input type="hidden" name="tag" value="'.$TAG.'">'."\n";
2187  print '<input type="hidden" name="s" value="'.$source.'">'."\n";
2188  print '<input type="hidden" name="ref" value="'.$REF.'">'."\n";
2189  print '<input type="hidden" name="fulltag" value="'.$FULLTAG.'">'."\n";
2190  print '<input type="hidden" name="suffix" value="'.$suffix.'">'."\n";
2191  print '<input type="hidden" name="securekey" value="'.$SECUREKEY.'">'."\n";
2192  print '<input type="hidden" name="e" value="'.$entity.'" />';
2193  print '<input type="hidden" name="amount" value="'.$amount.'">'."\n";
2194  print '<input type="hidden" name="currency" value="'.$currency.'">'."\n";
2195  print '<input type="hidden" name="forcesandbox" value="'.GETPOST('forcesandbox', 'int').'" />';
2196  print '<input type="hidden" name="email" value="'.GETPOST('email', 'alpha').'" />';
2197  print '<input type="hidden" name="thirdparty_id" value="'.GETPOST('thirdparty_id', 'int').'" />';
2198 
2199  if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION) || !empty($conf->global->STRIPE_USE_NEW_CHECKOUT)) { // Use a SCA ready method
2200  require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
2201 
2202  $service = 'StripeLive';
2203  $servicestatus = 1;
2204  if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) {
2205  $service = 'StripeTest';
2206  $servicestatus = 0;
2207  }
2208 
2209  $stripe = new Stripe($db);
2210  $stripeacc = $stripe->getStripeAccount($service);
2211  $stripecu = null;
2212  if (is_object($object) && is_object($object->thirdparty)) {
2213  $stripecu = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1);
2214  }
2215 
2216  if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
2217  $noidempotency_key = (GETPOSTISSET('noidempotency') ? GETPOST('noidempotency', 'int') : 0); // By default noidempotency is unset, so we must use a different tag/ref for each payment. If set, we can pay several times the same tag/ref.
2218  $paymentintent = $stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag.(is_object($object) ? ' ref='.$object->ref : ''), $object, $stripecu, $stripeacc, $servicestatus, 0, 'automatic', false, null, 0, $noidempotency_key);
2219  // The paymentintnent has status 'requires_payment_method' (even if paymentintent was already paid)
2220  //var_dump($paymentintent);
2221  if ($stripe->error) {
2222  setEventMessages($stripe->error, null, 'errors');
2223  }
2224  }
2225  }
2226 
2227  // Note:
2228  // $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = 1 = use intent (default value)
2229  // $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = 2 = use payment
2230 
2231  //if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION) || !empty($paymentintent))
2232  //{
2233  print '
2234  <table id="dolpaymenttable" summary="Payment form" class="center centpercent">
2235  <tbody><tr><td class="textpublicpayment">';
2236 
2237  if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
2238  print '<div id="payment-request-button"><!-- A Stripe Element will be inserted here. --></div>';
2239  }
2240 
2241  print '<div class="form-row '.(getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2 ? 'center' : 'left').'">';
2242  if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) {
2243  print '<label for="card-element">'.$langs->trans("CreditOrDebitCard").'</label>';
2244  print '<br><input id="cardholder-name" class="marginbottomonly" name="cardholder-name" value="" type="text" placeholder="'.$langs->trans("CardOwner").'" autocomplete="off" autofocus required>';
2245  }
2246 
2247  if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) {
2248  print '<div id="card-element">
2249  <!-- a Stripe Element will be inserted here. -->
2250  </div>';
2251  }
2252  if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) {
2253  print '<div id="payment-element">
2254  <!-- a Stripe Element will be inserted here. -->
2255  </div>';
2256  }
2257 
2258  print '<!-- Used to display form errors -->
2259  <div id="card-errors" role="alert"></div>
2260  </div>';
2261 
2262  print '<br>';
2263  print '<button class="button buttonpayment" style="text-align: center; padding-left: 0; padding-right: 0;" id="buttontopay" data-secret="'.(is_object($paymentintent) ? $paymentintent->client_secret : '').'">'.$langs->trans("ValidatePayment").'</button>';
2264  print '<img id="hourglasstopay" class="hidden" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/working.gif">';
2265 
2266  print '</td></tr></tbody>';
2267  print '</table>';
2268  //}
2269 
2270  if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
2271  if (empty($paymentintent)) {
2272  print '<center>'.$langs->trans("Error").'</center>';
2273  } else {
2274  print '<input type="hidden" name="paymentintent_id" value="'.$paymentintent->id.'">';
2275  //$_SESSION["paymentintent_id"] = $paymentintent->id;
2276  }
2277  }
2278 
2279  print '</form>'."\n";
2280 
2281 
2282  // JS Code for Stripe
2283  if (empty($stripearrayofkeys['publishable_key'])) {
2284  $langs->load("errors");
2285  print info_admin($langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("Stripe")), 0, 0, 'error');
2286  } else {
2287  print '<!-- JS Code for Stripe components -->';
2288  print '<script src="https://js.stripe.com/v3/"></script>'."\n";
2289  print '<!-- urllogofull = '.$urllogofull.' -->'."\n";
2290 
2291  // Code to ask the credit card. This use the default "API version". No way to force API version when using JS code.
2292  print '<script type="text/javascript">'."\n";
2293 
2294  if (!empty($conf->global->STRIPE_USE_NEW_CHECKOUT)) {
2295  $amountstripe = $amount;
2296 
2297  // Correct the amount according to unit of currency
2298  // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
2299  $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
2300  if (!in_array($currency, $arrayzerounitcurrency)) {
2301  $amountstripe = $amountstripe * 100;
2302  }
2303 
2304  $ipaddress = getUserRemoteIP();
2305  $metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress);
2306  if (is_object($object)) {
2307  $metadata['dol_type'] = $object->element;
2308  $metadata['dol_id'] = $object->id;
2309 
2310  $ref = $object->ref;
2311  }
2312 
2313  try {
2314  $arrayforpaymentintent = array(
2315  'description'=>'Stripe payment: '.$FULLTAG.($ref ? ' ref='.$ref : ''),
2316  "metadata" => $metadata
2317  );
2318  if ($TAG) {
2319  $arrayforpaymentintent["statement_descriptor"] = dol_trunc($TAG, 10, 'right', 'UTF-8', 1); // 22 chars that appears on bank receipt (company + description)
2320  }
2321 
2322  $arrayforcheckout = array(
2323  'payment_method_types' => array('card'),
2324  'line_items' => array(array(
2325  'name' => $langs->transnoentitiesnoconv("Payment").' '.$TAG, // Label of product line
2326  'description' => 'Stripe payment: '.$FULLTAG.($ref ? ' ref='.$ref : ''),
2327  'amount' => $amountstripe,
2328  'currency' => $currency,
2329  //'images' => array($urllogofull),
2330  'quantity' => 1,
2331  )),
2332  'client_reference_id' => $FULLTAG,
2333  'success_url' => $urlok,
2334  'cancel_url' => $urlko,
2335  'payment_intent_data' => $arrayforpaymentintent
2336  );
2337  if ($stripecu) {
2338  $arrayforcheckout['customer'] = $stripecu;
2339  } elseif (GETPOST('email', 'alpha') && isValidEmail(GETPOST('email', 'alpha'))) {
2340  $arrayforcheckout['customer_email'] = GETPOST('email', 'alpha');
2341  }
2342  $sessionstripe = \Stripe\Checkout\Session::create($arrayforcheckout);
2343 
2344  $remoteip = getUserRemoteIP();
2345 
2346  // Save some data for the paymentok
2347  $_SESSION["currencyCodeType"] = $currency;
2348  $_SESSION["paymentType"] = '';
2349  $_SESSION["FinalPaymentAmt"] = $amount;
2350  $_SESSION['ipaddress'] = ($remoteip ? $remoteip : 'unknown'); // Payer ip
2351  $_SESSION['payerID'] = is_object($stripecu) ? $stripecu->id : '';
2352  $_SESSION['TRANSACTIONID'] = $sessionstripe->id;
2353  } catch (Exception $e) {
2354  print $e->getMessage();
2355  }
2356  ?>
2357  // Code for payment with option STRIPE_USE_NEW_CHECKOUT set
2358 
2359  // Create a Stripe client.
2360  <?php
2361  if (empty($stripeacc)) {
2362  ?>
2363  var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>');
2364  <?php
2365  } else {
2366  ?>
2367  var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>', { stripeAccount: '<?php echo $stripeacc; ?>' });
2368  <?php
2369  }
2370  ?>
2371 
2372  // Create an instance of Elements
2373  var elements = stripe.elements();
2374 
2375  // Custom styling can be passed to options when creating an Element.
2376  // (Note that this demo uses a wider set of styles than the guide below.)
2377  var style = {
2378  base: {
2379  color: '#32325d',
2380  lineHeight: '24px',
2381  fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
2382  fontSmoothing: 'antialiased',
2383  fontSize: '16px',
2384  '::placeholder': {
2385  color: '#aab7c4'
2386  }
2387  },
2388  invalid: {
2389  color: '#fa755a',
2390  iconColor: '#fa755a'
2391  }
2392  }
2393 
2394  var cardElement = elements.create('card', {style: style});
2395 
2396  // Comment this to avoid the redirect
2397  stripe.redirectToCheckout({
2398  // Make the id field from the Checkout Session creation API response
2399  // available to this file, so you can provide it as parameter here
2400  // instead of the {{CHECKOUT_SESSION_ID}} placeholder.
2401  sessionId: '<?php print $sessionstripe->id; ?>'
2402  }).then(function (result) {
2403  // If `redirectToCheckout` fails due to a browser or network
2404  // error, display the localized error message to your customer
2405  // using `result.error.message`.
2406  });
2407 
2408 
2409  <?php
2410  } elseif (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
2411  ?>
2412  // Code for payment with option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION set to 1 or 2
2413 
2414  // Create a Stripe client.
2415  <?php
2416  if (empty($stripeacc)) {
2417  ?>
2418  var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>');
2419  <?php
2420  } else {
2421  ?>
2422  var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>', { stripeAccount: '<?php echo $stripeacc; ?>' });
2423  <?php
2424  }
2425  ?>
2426 
2427  <?php
2428  if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) {
2429  ?>
2430  var cardButton = document.getElementById('buttontopay');
2431  var clientSecret = cardButton.dataset.secret;
2432  var options = { clientSecret: clientSecret };
2433 
2434  // Create an instance of Elements
2435  var elements = stripe.elements(options);
2436  <?php
2437  } else {
2438  ?>
2439  // Create an instance of Elements
2440  var elements = stripe.elements();
2441  <?php
2442  }
2443  ?>
2444 
2445  // Custom styling can be passed to options when creating an Element.
2446  // (Note that this demo uses a wider set of styles than the guide below.)
2447  var style = {
2448  base: {
2449  color: '#32325d',
2450  lineHeight: '24px',
2451  fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
2452  fontSmoothing: 'antialiased',
2453  fontSize: '16px',
2454  '::placeholder': {
2455  color: '#aab7c4'
2456  }
2457  },
2458  invalid: {
2459  color: '#fa755a',
2460  iconColor: '#fa755a'
2461  }
2462  }
2463 
2464  <?php
2465  if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) {
2466  ?>
2467  var paymentElement = elements.create("payment");
2468 
2469  // Add an instance of the card Element into the `card-element` <div>
2470  paymentElement.mount("#payment-element");
2471 
2472  // Handle form submission
2473  var cardButton = document.getElementById('buttontopay');
2474 
2475  cardButton.addEventListener('click', function(event) {
2476  console.log("We click on buttontopay");
2477  event.preventDefault();
2478 
2479  /* Disable button to pay and show hourglass cursor */
2480  jQuery('#hourglasstopay').show();
2481  jQuery('#buttontopay').hide();
2482 
2483  stripe.confirmPayment({
2484  elements,confirmParams: {
2485  return_url: '<?php echo $urlok; ?>',
2486  payment_method_data: {
2487  billing_details: {
2488  name: 'test'
2489  <?php if (GETPOST('email', 'alpha') || (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->email))) {
2490  ?>, email: '<?php echo dol_escape_js(GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $object->thirdparty->email); ?>'<?php
2491  } ?>
2492  <?php if (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->phone)) {
2493  ?>, phone: '<?php echo dol_escape_js($object->thirdparty->phone); ?>'<?php
2494  } ?>
2495  <?php if (is_object($object) && is_object($object->thirdparty)) {
2496  ?>, address: {
2497  city: '<?php echo dol_escape_js($object->thirdparty->town); ?>',
2498  <?php if ($object->thirdparty->country_code) {
2499  ?>country: '<?php echo dol_escape_js($object->thirdparty->country_code); ?>',<?php
2500  } ?>
2501  line1: '<?php echo dol_escape_js(preg_replace('/\s\s+/', ' ', $object->thirdparty->address)); ?>',
2502  postal_code: '<?php echo dol_escape_js($object->thirdparty->zip); ?>'
2503  }
2504  <?php } ?>
2505  }
2506  },
2507  save_payment_method:<?php if ($stripecu) {
2508  print 'true';
2509  } else {
2510  print 'false';
2511  } ?> /* true when a customer was provided when creating payment intent. true ask to save the card */
2512  },
2513  }
2514  ).then(function(result) {
2515  console.log(result);
2516  if (result.error) {
2517  console.log("Error on result of handleCardPayment");
2518  jQuery('#buttontopay').show();
2519  jQuery('#hourglasstopay').hide();
2520  // Inform the user if there was an error
2521  var errorElement = document.getElementById('card-errors');
2522  console.log(result);
2523  errorElement.textContent = result.error.message;
2524  } else {
2525  // The payment has succeeded. Display a success message.
2526  console.log("No error on result of handleCardPayment, so we submit the form");
2527  // Submit the form
2528  jQuery('#buttontopay').hide();
2529  jQuery('#hourglasstopay').show();
2530  // Send form (action=charge that will do nothing)
2531  jQuery('#payment-form').submit();
2532  }
2533  });
2534 
2535  });
2536  <?php
2537  } else {
2538  ?>
2539  var cardElement = elements.create('card', {style: style});
2540 
2541  // Add an instance of the card Element into the `card-element` <div>
2542  cardElement.mount('#card-element');
2543 
2544  // Handle real-time validation errors from the card Element.
2545  cardElement.addEventListener('change', function(event) {
2546  var displayError = document.getElementById('card-errors');
2547  if (event.error) {
2548  console.log("Show event error (like 'Incorrect card number', ...)");
2549  displayError.textContent = event.error.message;
2550  } else {
2551  console.log("Reset error message");
2552  displayError.textContent = '';
2553  }
2554  });
2555 
2556  // Handle form submission
2557  var cardholderName = document.getElementById('cardholder-name');
2558  var cardButton = document.getElementById('buttontopay');
2559  var clientSecret = cardButton.dataset.secret;
2560 
2561  cardButton.addEventListener('click', function(event) {
2562  console.log("We click on buttontopay");
2563  event.preventDefault();
2564 
2565  if (cardholderName.value == '')
2566  {
2567  console.log("Field Card holder is empty");
2568  var displayError = document.getElementById('card-errors');
2569  displayError.textContent = '<?php print dol_escape_js($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CardOwner"))); ?>';
2570  }
2571  else
2572  {
2573  /* Disable button to pay and show hourglass cursor */
2574  jQuery('#hourglasstopay').show();
2575  jQuery('#buttontopay').hide();
2576 
2577  stripe.handleCardPayment(
2578  clientSecret, cardElement, {
2579  payment_method_data: {
2580  billing_details: {
2581  name: cardholderName.value
2582  <?php if (GETPOST('email', 'alpha') || (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->email))) {
2583  ?>, email: '<?php echo dol_escape_js(GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $object->thirdparty->email); ?>'<?php
2584  } ?>
2585  <?php if (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->phone)) {
2586  ?>, phone: '<?php echo dol_escape_js($object->thirdparty->phone); ?>'<?php
2587  } ?>
2588  <?php if (is_object($object) && is_object($object->thirdparty)) {
2589  ?>, address: {
2590  city: '<?php echo dol_escape_js($object->thirdparty->town); ?>',
2591  <?php if ($object->thirdparty->country_code) {
2592  ?>country: '<?php echo dol_escape_js($object->thirdparty->country_code); ?>',<?php
2593  } ?>
2594  line1: '<?php echo dol_escape_js(preg_replace('/\s\s+/', ' ', $object->thirdparty->address)); ?>',
2595  postal_code: '<?php echo dol_escape_js($object->thirdparty->zip); ?>'
2596  }
2597  <?php } ?>
2598  }
2599  },
2600  save_payment_method:<?php if ($stripecu) {
2601  print 'true';
2602  } else {
2603  print 'false';
2604  } ?> /* true when a customer was provided when creating payment intent. true ask to save the card */
2605  }
2606  ).then(function(result) {
2607  console.log(result);
2608  if (result.error) {
2609  console.log("Error on result of handleCardPayment");
2610  jQuery('#buttontopay').show();
2611  jQuery('#hourglasstopay').hide();
2612  // Inform the user if there was an error
2613  var errorElement = document.getElementById('card-errors');
2614  errorElement.textContent = result.error.message;
2615  } else {
2616  // The payment has succeeded. Display a success message.
2617  console.log("No error on result of handleCardPayment, so we submit the form");
2618  // Submit the form
2619  jQuery('#buttontopay').hide();
2620  jQuery('#hourglasstopay').show();
2621  // Send form (action=charge that will do nothing)
2622  jQuery('#payment-form').submit();
2623  }
2624  });
2625  }
2626  });
2627  <?php
2628  }
2629  ?>
2630 
2631  <?php
2632  }
2633 
2634  print '</script>';
2635  }
2636  }
2637 
2638  // For any other payment services
2639  // This hook can be used to show the embedded form to make payments with external payment modules (ie Payzen, ...)
2640  $parameters = [
2641  'paymentmethod' => $paymentmethod,
2642  'amount' => $amount,
2643  'currency' => $currency,
2644  'tag' => GETPOST("tag", 'alpha'),
2645  'dopayment' => GETPOST('dopayment', 'alpha')
2646  ];
2647  $reshook = $hookmanager->executeHooks('doPayment', $parameters, $object, $action);
2648 }
2649 
2650 
2651 htmlPrintOnlinePaymentFooter($mysoc, $langs, 1, $suffix, $object);
2652 
2653 llxFooter('', 'public');
2654 
2655 $db->close();
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
$object ref
Definition: info.php:78
Class to manage members of a foundation.
Class to manage members type.
Class to manage customers orders.
Class for ConferenceOrBoothAttendee.
Class to manage contracts.
Class to manage lines of contracts.
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
Class to manage hooks.
Class to manage payments of donations.
Class to manage products or services.
Class to manage third parties objects (customers, suppliers, prospects...)
Stripe class.
Class to manage subscriptions of foundation members.
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:745
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
dol_print_error_email($prefixcode, $errormessage='', $errormessages=array(), $morecss='error', $email='')
Show a public email and error code to contact if technical error.
dol_htmloutput_mesg($mesgstring='', $mesgarray=array(), $style='ok', $keepembedded=0)
Print formated messages to output (Used to show messages on html output).
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
isValidEmail($address, $acceptsupervisorkey=0, $acceptuserkey=0)
Return true if email syntax is ok.
getUserRemoteIP()
Return the IP of remote user.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
table tableforfield button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
Definition: style.css.php:843
print_paybox_redirect($PRICE, $CURRENCY, $EMAIL, $urlok, $urlko, $TAG)
Create a redirect form to paybox form.
Definition: paybox.lib.php:39
print_paypal_redirect($paymentAmount, $currencyCodeType, $paymentType, $returnURL, $cancelURL, $tag)
Send redirect to paypal to browser.
Definition: paypal.lib.php:70
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:122
dol_verifyHash($chain, $hash, $type='0')
Compute a hash and compare it to the given one For backward compatibility reasons,...