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