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