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