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