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