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