dolibarr 18.0.6
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
39if (!defined('NOLOGIN')) {
40 define("NOLOGIN", 1); // This means this output page does not require to be logged.
41}
42if (!defined('NOCSRFCHECK')) {
43 define("NOCSRFCHECK", 1); // We accept to go on this page from external web site.
44}
45if (!defined('NOIPCHECK')) {
46 define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
47}
48if (!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))));
55if (is_numeric($entity)) {
56 define("DOLENTITY", $entity);
57}
58
59// Load Dolibarr environment
60require '../../main.inc.php';
61require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
62require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
63require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
64require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php';
65require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
66require_once DOL_DOCUMENT_ROOT.'/societe/class/societeaccount.class.php';
67require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
68require_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'));
91if (!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
99if (!$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
114if ($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
189foreach ($_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
212if ($paymentmethod && !preg_match('/'.preg_quote('PM='.$paymentmethod, '/').'/', $FULLTAG)) {
213 $FULLTAG .= ($FULLTAG ? '.' : '').'PM='.$paymentmethod;
214}
215
216if (!empty($suffix)) {
217 $urlok .= 'suffix='.urlencode($suffix).'&';
218 $urlko .= 'suffix='.urlencode($suffix).'&';
219}
220if ($source) {
221 $urlok .= 's='.urlencode($source).'&';
222 $urlko .= 's='.urlencode($source).'&';
223}
224if (!empty($REF)) {
225 $urlok .= 'ref='.urlencode($REF).'&';
226 $urlko .= 'ref='.urlencode($REF).'&';
227}
228if (!empty($TAG)) {
229 $urlok .= 'tag='.urlencode($TAG).'&';
230 $urlko .= 'tag='.urlencode($TAG).'&';
231}
232if (!empty($FULLTAG)) {
233 $urlok .= 'fulltag='.urlencode($FULLTAG).'&';
234 $urlko .= 'fulltag='.urlencode($FULLTAG).'&';
235}
236if (!empty($SECUREKEY)) {
237 $urlok .= 'securekey='.urlencode($SECUREKEY).'&';
238 $urlko .= 'securekey='.urlencode($SECUREKEY).'&';
239}
240if (!empty($entity)) {
241 $urlok .= 'e='.urlencode($entity).'&';
242 $urlko .= 'e='.urlencode($entity).'&';
243}
244if (!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
254if ((empty($paymentmethod) || $paymentmethod == 'paypal') && isModEnabled('paypal')) {
255 require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php';
256 require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php';
257
258 // Check parameters
259 $PAYPAL_API_OK = "";
260 if ($urlok) {
261 $PAYPAL_API_OK = $urlok;
262 }
263 $PAYPAL_API_KO = "";
264 if ($urlko) {
265 $PAYPAL_API_KO = $urlko;
266 }
267 if (empty($PAYPAL_API_USER)) {
268 dol_print_error('', "Paypal setup param PAYPAL_API_USER not defined");
269 return -1;
270 }
271 if (empty($PAYPAL_API_PASSWORD)) {
272 dol_print_error('', "Paypal setup param PAYPAL_API_PASSWORD not defined");
273 return -1;
274 }
275 if (empty($PAYPAL_API_SIGNATURE)) {
276 dol_print_error('', "Paypal setup param PAYPAL_API_SIGNATURE not defined");
277 return -1;
278 }
279}
280if ((empty($paymentmethod) || $paymentmethod == 'paybox') && isModEnabled('paybox')) {
281 // No specific test for the moment
282}
283if ((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;
293if ($tmpsource == 'membersubscription') {
294 $tmpsource = 'member';
295}
296$valid = true;
297if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) {
298 $tokenisok = false;
299 if (!empty($conf->global->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($conf->global->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($conf->global->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 (empty($conf->global->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
329if (!empty($paymentmethod) && empty($validpaymentmethod[$paymentmethod])) {
330 print 'Payment module for payment method '.$paymentmethod.' is not active';
331 exit;
332}
333if (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;
342if (!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
356if ($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.
484if ($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 (!empty($conf->global->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 (!empty($conf->global->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);
825if ($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 = '';
840if (!empty($conf->global->ONLINE_PAYMENT_CSS_URL)) {
841 $head = '<link rel="stylesheet" type="text/css" href="'.$conf->global->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>';
848llxHeader($head, $langs->trans("PaymentForm"), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea);
849
850dol_syslog("--- newpayment.php action = ".$action, LOG_DEBUG, 0, '_payment');
851dol_syslog("newpayment.php show page source=".$source." paymentmethod=".$paymentmethod.' amount='.$amount.' newamount='.GETPOST("newamount", 'alpha')." ref=".$ref, LOG_DEBUG, 0, '_payment');
852dol_syslog("_SERVER[SERVER_NAME] = ".(empty($_SERVER["SERVER_NAME"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_NAME"])), LOG_DEBUG, 0, '_payment');
853dol_syslog("_SERVER[SERVER_ADDR] = ".(empty($_SERVER["SERVER_ADDR"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_ADDR"])), LOG_DEBUG, 0, '_payment');
854
855// Check link validity
856if ($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
867if ((empty($paymentmethod) || $paymentmethod == 'paypal') && isModEnabled('paypal') && (!empty($conf->global->PAYPAL_API_SANDBOX) || GETPOST('forcesandbox', 'int'))) { // We can force sand box with param 'forcesandbox'
868 dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Paypal'), '', 'warning');
869}
870if ((empty($paymentmethod) || $paymentmethod == 'stripe') && isModEnabled('stripe') && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'int'))) {
871 dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning');
872}
873
874
875print '<span id="dolpaymentspan"></span>'."\n";
876print '<div class="center">'."\n";
877print '<form id="dolpaymentform" class="center" name="paymentform" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
878print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
879print '<input type="hidden" name="action" value="dopayment">'."\n";
880print '<input type="hidden" name="tag" value="'.GETPOST("tag", 'alpha').'">'."\n";
881print '<input type="hidden" name="suffix" value="'.dol_escape_htmltag($suffix).'">'."\n";
882print '<input type="hidden" name="securekey" value="'.dol_escape_htmltag($SECUREKEY).'">'."\n";
883print '<input type="hidden" name="e" value="'.$entity.'" />';
884print '<input type="hidden" name="forcesandbox" value="'.GETPOST('forcesandbox', 'int').'" />';
885print '<input type="hidden" name="lang" value="'.$getpostlang.'">';
886print "\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;
894if (!empty($conf->global->$paramlogo)) {
895 $logosmall = $conf->global->$paramlogo;
896} elseif (!empty($conf->global->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 = '';
903if (!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
912if ($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 (empty($conf->global->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}
923if (!empty($conf->global->MAIN_IMAGE_PUBLIC_PAYMENT)) {
924 print '<div class="backimagepublicpayment">';
925 print '<img id="idMAIN_IMAGE_PUBLIC_PAYMENT" src="'.$conf->global->MAIN_IMAGE_PUBLIC_PAYMENT.'">';
926 print '</div>';
927}
928
929
930
931
932print '<!-- Form to send a payment -->'."\n";
933print '<!-- creditor = '.dol_escape_htmltag($creditor).' -->'."\n";
934// Additionnal information for each payment system
935if (isModEnabled('paypal')) {
936 print '<!-- PAYPAL_API_SANDBOX = '.getDolGlobalString('PAYPAL_API_SANDBOX').' -->'."\n";
937 print '<!-- PAYPAL_API_INTEGRAL_OR_PAYPALONLY = '.getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY').' -->'."\n";
938}
939if (isModEnabled('paybox')) {
940 print '<!-- PAYBOX_CGI_URL = '.getDolGlobalString('PAYBOX_CGI_URL_V2').' -->'."\n";
941}
942if (isModEnabled('stripe')) {
943 print '<!-- STRIPE_LIVE = '.getDolGlobalString('STRIPE_LIVE').' -->'."\n";
944}
945print '<!-- urlok = '.$urlok.' -->'."\n";
946print '<!-- urlko = '.$urlko.' -->'."\n";
947print "\n";
948
949// Section with payment informationsummary
950print '<table id="dolpublictable" summary="Payment form" class="center">'."\n";
951
952// Output introduction text
953$text = '';
954if (!empty($conf->global->PAYMENT_NEWFORM_TEXT)) {
955 $langs->load("members");
956 if (preg_match('/^\‍((.*)\‍)$/', $conf->global->PAYMENT_NEWFORM_TEXT, $reg)) {
957 $text .= $langs->trans($reg[1])."<br>\n";
958 } else {
959 $text .= $conf->global->PAYMENT_NEWFORM_TEXT."<br>\n";
960 }
961 $text = '<tr><td align="center"><br>'.$text.'<br></td></tr>'."\n";
962}
963if (empty($text)) {
964 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnPaymentPage").'</strong></td></tr>'."\n";
965 $text .= '<tr><td class="textpublicpayment">'.$langs->trans("ThisScreenAllowsYouToPay", $creditor).'<br><br></td></tr>'."\n";
966}
967print $text;
968
969// Output payment summary form
970print '<tr><td align="center">';
971print '<table with="100%" id="tablepublicpayment">';
972print '<tr><td align="left" colspan="2" class="opacitymedium">'.$langs->trans("ThisIsInformationOnPayment").' :</td></tr>'."\n";
973
974$found = false;
975$error = 0;
976
977$object = null;
978
979
980// Free payment
981if (!$source) {
982 $found = true;
983 $tag = GETPOST("tag", 'alpha');
984 if (GETPOST('fulltag', 'alpha')) {
985 $fulltag = GETPOST('fulltag', 'alpha');
986 } else {
987 $fulltag = "TAG=".$tag;
988 }
989
990 // Creditor
991 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
992 print '</td><td class="CTableRow2">';
993 print img_picto('', 'company', 'class="pictofixedwidth"');
994 print '<b>'.$creditor.'</b>';
995 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
996 print '</td></tr>'."\n";
997
998 // Amount
999 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1000 if (empty($amount)) {
1001 print ' ('.$langs->trans("ToComplete").')';
1002 }
1003 print '</td><td class="CTableRow2">';
1004 if (empty($amount) || !is_numeric($amount)) {
1005 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1006 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1007 // Currency
1008 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1009 } else {
1010 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1011 print '<input type="hidden" name="amount" value="'.$amount.'">';
1012 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1013 }
1014 print '<input type="hidden" name="currency" value="'.$currency.'">';
1015 print '</td></tr>'."\n";
1016
1017 // Tag
1018 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1019 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1020 print '<input type="hidden" name="tag" value="'.$tag.'">';
1021 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1022 print '</td></tr>'."\n";
1023
1024 // We do not add fields shipToName, shipToStreet, shipToCity, shipToState, shipToCountryCode, shipToZip, shipToStreet2, phoneNum
1025 // as they don't exists (buyer is unknown, tag is free).
1026}
1027
1028
1029// Payment on a Sale Order
1030if ($source == 'order') {
1031 $found = true;
1032 $langs->load("orders");
1033
1034 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
1035
1036 $order = new Commande($db);
1037 $result = $order->fetch('', $ref);
1038 if ($result <= 0) {
1039 $mesg = $order->error;
1040 $error++;
1041 } else {
1042 $result = $order->fetch_thirdparty($order->socid);
1043 }
1044 $object = $order;
1045
1046 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1047 $amount = $order->total_ttc;
1048 if (GETPOST("amount", 'alpha')) {
1049 $amount = GETPOST("amount", 'alpha');
1050 }
1051 $amount = price2num($amount);
1052 }
1053
1054 $tag = '';
1055 if (GETPOST('fulltag', 'alpha')) {
1056 $fulltag = GETPOST('fulltag', 'alpha');
1057 } else {
1058 $fulltag = 'ORD='.$order->id.'.CUS='.$order->thirdparty->id;
1059 if (!empty($TAG)) {
1060 $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1061 }
1062 }
1063 $fulltag = dol_string_unaccent($fulltag);
1064
1065 // Creditor
1066 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1067 print '</td><td class="CTableRow2">';
1068 print img_picto('', 'company', 'class="pictofixedwidth"');
1069 print '<b>'.$creditor.'</b>';
1070 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1071 print '</td></tr>'."\n";
1072
1073 // Debitor
1074 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1075 print '</td><td class="CTableRow2">';
1076 print img_picto('', 'company', 'class="pictofixedwidth"');
1077 print '<b>'.$order->thirdparty->name.'</b>';
1078 print '</td></tr>'."\n";
1079
1080 // Object
1081 $text = '<b>'.$langs->trans("PaymentOrderRef", $order->ref).'</b>';
1082 if (GETPOST('desc', 'alpha')) {
1083 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1084 }
1085 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1086 print '</td><td class="CTableRow2">'.$text;
1087 print '<input type="hidden" name="s" value="'.dol_escape_htmltag($source).'">';
1088 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($order->ref).'">';
1089 print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag($order->id).'">';
1090 $directdownloadlink = $order->getLastMainDocLink('commande');
1091 if ($directdownloadlink) {
1092 print '<br><a href="'.$directdownloadlink.'" rel="nofollow noopener">';
1093 print img_mime($order->last_main_doc, '');
1094 print $langs->trans("DownloadDocument").'</a>';
1095 }
1096 print '</td></tr>'."\n";
1097
1098 // Amount
1099 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1100 if (empty($amount)) {
1101 print ' ('.$langs->trans("ToComplete").')';
1102 }
1103 print '</td><td class="CTableRow2">';
1104 if (empty($amount) || !is_numeric($amount)) {
1105 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1106 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1107 // Currency
1108 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1109 } else {
1110 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1111 print '<input type="hidden" name="amount" value="'.$amount.'">';
1112 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1113 }
1114 print '<input type="hidden" name="currency" value="'.$currency.'">';
1115 print '</td></tr>'."\n";
1116
1117 // Tag
1118 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1119 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1120 print '<input type="hidden" name="tag" value="'.dol_escape_htmltag($tag).'">';
1121 print '<input type="hidden" name="fulltag" value="'.dol_escape_htmltag($fulltag).'">';
1122 print '</td></tr>'."\n";
1123
1124 // Shipping address
1125 $shipToName = $order->thirdparty->name;
1126 $shipToStreet = $order->thirdparty->address;
1127 $shipToCity = $order->thirdparty->town;
1128 $shipToState = $order->thirdparty->state_code;
1129 $shipToCountryCode = $order->thirdparty->country_code;
1130 $shipToZip = $order->thirdparty->zip;
1131 $shipToStreet2 = '';
1132 $phoneNum = $order->thirdparty->phone;
1133 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1134 print '<input type="hidden" name="shipToName" value="'.dol_escape_htmltag($shipToName).'">'."\n";
1135 print '<input type="hidden" name="shipToStreet" value="'.dol_escape_htmltag($shipToStreet).'">'."\n";
1136 print '<input type="hidden" name="shipToCity" value="'.dol_escape_htmltag($shipToCity).'">'."\n";
1137 print '<input type="hidden" name="shipToState" value="'.dol_escape_htmltag($shipToState).'">'."\n";
1138 print '<input type="hidden" name="shipToCountryCode" value="'.dol_escape_htmltag($shipToCountryCode).'">'."\n";
1139 print '<input type="hidden" name="shipToZip" value="'.dol_escape_htmltag($shipToZip).'">'."\n";
1140 print '<input type="hidden" name="shipToStreet2" value="'.dol_escape_htmltag($shipToStreet2).'">'."\n";
1141 print '<input type="hidden" name="phoneNum" value="'.dol_escape_htmltag($phoneNum).'">'."\n";
1142 } else {
1143 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1144 }
1145 if (is_object($order->thirdparty)) {
1146 print '<input type="hidden" name="thirdparty_id" value="'.$order->thirdparty->id.'">'."\n";
1147 }
1148 print '<input type="hidden" name="email" value="'.$order->thirdparty->email.'">'."\n";
1149 print '<input type="hidden" name="vatnumber" value="'.dol_escape_htmltag($order->thirdparty->tva_intra).'">'."\n";
1150 $labeldesc = $langs->trans("Order").' '.$order->ref;
1151 if (GETPOST('desc', 'alpha')) {
1152 $labeldesc = GETPOST('desc', 'alpha');
1153 }
1154 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1155}
1156
1157
1158// Payment on a Customer Invoice
1159if ($source == 'invoice') {
1160 $found = true;
1161 $langs->load("bills");
1162
1163 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1164
1165 $invoice = new Facture($db);
1166 $result = $invoice->fetch('', $ref);
1167 if ($result <= 0) {
1168 $mesg = $invoice->error;
1169 $error++;
1170 } else {
1171 $result = $invoice->fetch_thirdparty($invoice->socid);
1172 }
1173 $object = $invoice;
1174
1175 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1176 $amount = price2num($invoice->total_ttc - ($invoice->getSommePaiement() + $invoice->getSumCreditNotesUsed() + $invoice->getSumDepositsUsed()));
1177 if (GETPOST("amount", 'alpha')) {
1178 $amount = GETPOST("amount", 'alpha');
1179 }
1180 $amount = price2num($amount);
1181 }
1182
1183 if (GETPOST('fulltag', 'alpha')) {
1184 $fulltag = GETPOST('fulltag', 'alpha');
1185 } else {
1186 $fulltag = 'INV='.$invoice->id.'.CUS='.$invoice->thirdparty->id;
1187 if (!empty($TAG)) {
1188 $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1189 }
1190 }
1191 $fulltag = dol_string_unaccent($fulltag);
1192
1193 // Creditor
1194 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1195 print '</td><td class="CTableRow2">';
1196 print img_picto('', 'company', 'class="pictofixedwidth"');
1197 print '<b>'.$creditor.'</b>';
1198 print '<input type="hidden" name="creditor" value="'.dol_escape_htmltag($creditor).'">';
1199 print '</td></tr>'."\n";
1200
1201 // Debitor
1202 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1203 print '</td><td class="CTableRow2">';
1204 print img_picto('', 'company', 'class="pictofixedwidth"');
1205 print '<b>'.$invoice->thirdparty->name.'</b>';
1206 print '</td></tr>'."\n";
1207
1208 // Object
1209 $text = '<b>'.$langs->trans("PaymentInvoiceRef", $invoice->ref).'</b>';
1210 if (GETPOST('desc', 'alpha')) {
1211 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1212 }
1213 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1214 print '</td><td class="CTableRow2">'.$text;
1215 print '<input type="hidden" name="s" value="'.dol_escape_htmltag($source).'">';
1216 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($invoice->ref).'">';
1217 print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag($invoice->id).'">';
1218 $directdownloadlink = $invoice->getLastMainDocLink('facture');
1219 if ($directdownloadlink) {
1220 print '<br><a href="'.$directdownloadlink.'">';
1221 print img_mime($invoice->last_main_doc, '');
1222 print $langs->trans("DownloadDocument").'</a>';
1223 }
1224 print '</td></tr>'."\n";
1225
1226 // Amount
1227 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentAmount");
1228 if (empty($amount) && empty($object->paye)) {
1229 print ' ('.$langs->trans("ToComplete").')';
1230 }
1231 print '</td><td class="CTableRow2">';
1232 if ($object->type == $object::TYPE_CREDIT_NOTE) {
1233 print '<b>'.$langs->trans("CreditNote").'</b>';
1234 } elseif (empty($object->paye)) {
1235 if (empty($amount) || !is_numeric($amount)) {
1236 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1237 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1238 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1239 } else {
1240 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1241 print '<input type="hidden" name="amount" value="'.$amount.'">';
1242 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1243 }
1244 } else {
1245 print '<b class="amount">'.price($object->total_ttc, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1246 }
1247 print '<input type="hidden" name="currency" value="'.$currency.'">';
1248 print '</td></tr>'."\n";
1249
1250 // Tag
1251 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1252 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1253 print '<input type="hidden" name="tag" value="'.$tag.'">';
1254 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1255 print '</td></tr>'."\n";
1256
1257 // Shipping address
1258 $shipToName = $invoice->thirdparty->name;
1259 $shipToStreet = $invoice->thirdparty->address;
1260 $shipToCity = $invoice->thirdparty->town;
1261 $shipToState = $invoice->thirdparty->state_code;
1262 $shipToCountryCode = $invoice->thirdparty->country_code;
1263 $shipToZip = $invoice->thirdparty->zip;
1264 $shipToStreet2 = '';
1265 $phoneNum = $invoice->thirdparty->phone;
1266 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1267 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1268 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1269 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1270 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1271 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1272 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1273 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1274 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1275 } else {
1276 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1277 }
1278 if (is_object($invoice->thirdparty)) {
1279 print '<input type="hidden" name="thirdparty_id" value="'.$invoice->thirdparty->id.'">'."\n";
1280 }
1281 print '<input type="hidden" name="email" value="'.$invoice->thirdparty->email.'">'."\n";
1282 print '<input type="hidden" name="vatnumber" value="'.$invoice->thirdparty->tva_intra.'">'."\n";
1283 $labeldesc = $langs->trans("Invoice").' '.$invoice->ref;
1284 if (GETPOST('desc', 'alpha')) {
1285 $labeldesc = GETPOST('desc', 'alpha');
1286 }
1287 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1288}
1289
1290// Payment on a Contract line
1291if ($source == 'contractline') {
1292 $found = true;
1293 $langs->load("contracts");
1294
1295 require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
1296
1297 $contract = new Contrat($db);
1298 $contractline = new ContratLigne($db);
1299
1300 $result = $contractline->fetch('', $ref);
1301 if ($result <= 0) {
1302 $mesg = $contractline->error;
1303 $error++;
1304 } else {
1305 if ($contractline->fk_contrat > 0) {
1306 $result = $contract->fetch($contractline->fk_contrat);
1307 if ($result > 0) {
1308 $result = $contract->fetch_thirdparty($contract->socid);
1309 } else {
1310 $mesg = $contract->error;
1311 $error++;
1312 }
1313 } else {
1314 $mesg = 'ErrorRecordNotFound';
1315 $error++;
1316 }
1317 }
1318 $object = $contractline;
1319
1320 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1321 $amount = $contractline->total_ttc;
1322
1323 if ($contractline->fk_product && !empty($conf->global->PAYMENT_USE_NEW_PRICE_FOR_CONTRACTLINES)) {
1324 $product = new Product($db);
1325 $result = $product->fetch($contractline->fk_product);
1326
1327 // We define price for product (TODO Put this in a method in product class)
1328 if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
1329 $pu_ht = $product->multiprices[$contract->thirdparty->price_level];
1330 $pu_ttc = $product->multiprices_ttc[$contract->thirdparty->price_level];
1331 $price_base_type = $product->multiprices_base_type[$contract->thirdparty->price_level];
1332 } else {
1333 $pu_ht = $product->price;
1334 $pu_ttc = $product->price_ttc;
1335 $price_base_type = $product->price_base_type;
1336 }
1337
1338 $amount = $pu_ttc;
1339 if (empty($amount)) {
1340 dol_print_error('', 'ErrorNoPriceDefinedForThisProduct');
1341 exit;
1342 }
1343 }
1344
1345 if (GETPOST("amount", 'alpha')) {
1346 $amount = GETPOST("amount", 'alpha');
1347 }
1348 $amount = price2num($amount);
1349 }
1350
1351 if (GETPOST('fulltag', 'alpha')) {
1352 $fulltag = GETPOST('fulltag', 'alpha');
1353 } else {
1354 $fulltag = 'COL='.$contractline->id.'.CON='.$contract->id.'.CUS='.$contract->thirdparty->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1355 if (!empty($TAG)) {
1356 $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1357 }
1358 }
1359 $fulltag = dol_string_unaccent($fulltag);
1360
1361 $qty = 1;
1362 if (GETPOST('qty')) {
1363 $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
1364 }
1365
1366 // Creditor
1367 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1368 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1369 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1370 print '</td></tr>'."\n";
1371
1372 // Debitor
1373 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1374 print '</td><td class="CTableRow2"><b>'.$contract->thirdparty->name.'</b>';
1375 print '</td></tr>'."\n";
1376
1377 // Object
1378 $text = '<b>'.$langs->trans("PaymentRenewContractId", $contract->ref, $contractline->ref).'</b>';
1379 if ($contractline->fk_product > 0) {
1380 $contractline->fetch_product();
1381 $text .= '<br>'.$contractline->product->ref.($contractline->product->label ? ' - '.$contractline->product->label : '');
1382 }
1383 if ($contractline->description) {
1384 $text .= '<br>'.dol_htmlentitiesbr($contractline->description);
1385 }
1386 if ($contractline->date_end) {
1387 $text .= '<br>'.$langs->trans("ExpiredSince").': '.dol_print_date($contractline->date_end);
1388 }
1389 if (GETPOST('desc', 'alpha')) {
1390 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1391 }
1392 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1393 print '</td><td class="CTableRow2">'.$text;
1394 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1395 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($contractline->ref).'">';
1396 print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag($contractline->id).'">';
1397 $directdownloadlink = $contract->getLastMainDocLink('contract');
1398 if ($directdownloadlink) {
1399 print '<br><a href="'.$directdownloadlink.'">';
1400 print img_mime($contract->last_main_doc, '');
1401 print $langs->trans("DownloadDocument").'</a>';
1402 }
1403 print '</td></tr>'."\n";
1404
1405 // Quantity
1406 $label = $langs->trans("Quantity");
1407 $qty = 1;
1408 $duration = '';
1409 if ($contractline->fk_product) {
1410 if ($contractline->product->isService() && $contractline->product->duration_value > 0) {
1411 $label = $langs->trans("Duration");
1412
1413 // TODO Put this in a global method
1414 if ($contractline->product->duration_value > 1) {
1415 $dur = array("h"=>$langs->trans("Hours"), "d"=>$langs->trans("DurationDays"), "w"=>$langs->trans("DurationWeeks"), "m"=>$langs->trans("DurationMonths"), "y"=>$langs->trans("DurationYears"));
1416 } else {
1417 $dur = array("h"=>$langs->trans("Hour"), "d"=>$langs->trans("DurationDay"), "w"=>$langs->trans("DurationWeek"), "m"=>$langs->trans("DurationMonth"), "y"=>$langs->trans("DurationYear"));
1418 }
1419 $duration = $contractline->product->duration_value.' '.$dur[$contractline->product->duration_unit];
1420 }
1421 }
1422 print '<tr class="CTableRow2"><td class="CTableRow2">'.$label.'</td>';
1423 print '<td class="CTableRow2"><b>'.($duration ? $duration : $qty).'</b>';
1424 print '<input type="hidden" name="newqty" value="'.dol_escape_htmltag($qty).'">';
1425 print '</b></td></tr>'."\n";
1426
1427 // Amount
1428 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1429 if (empty($amount)) {
1430 print ' ('.$langs->trans("ToComplete").')';
1431 }
1432 print '</td><td class="CTableRow2">';
1433 if (empty($amount) || !is_numeric($amount)) {
1434 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1435 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1436 // Currency
1437 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1438 } else {
1439 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1440 print '<input type="hidden" name="amount" value="'.$amount.'">';
1441 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1442 }
1443 print '<input type="hidden" name="currency" value="'.$currency.'">';
1444 print '</td></tr>'."\n";
1445
1446 // Tag
1447 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1448 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1449 print '<input type="hidden" name="tag" value="'.$tag.'">';
1450 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1451 print '</td></tr>'."\n";
1452
1453 // Shipping address
1454 $shipToName = $contract->thirdparty->name;
1455 $shipToStreet = $contract->thirdparty->address;
1456 $shipToCity = $contract->thirdparty->town;
1457 $shipToState = $contract->thirdparty->state_code;
1458 $shipToCountryCode = $contract->thirdparty->country_code;
1459 $shipToZip = $contract->thirdparty->zip;
1460 $shipToStreet2 = '';
1461 $phoneNum = $contract->thirdparty->phone;
1462 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1463 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1464 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1465 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1466 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1467 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1468 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1469 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1470 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1471 } else {
1472 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1473 }
1474 if (is_object($contract->thirdparty)) {
1475 print '<input type="hidden" name="thirdparty_id" value="'.$contract->thirdparty->id.'">'."\n";
1476 }
1477 print '<input type="hidden" name="email" value="'.$contract->thirdparty->email.'">'."\n";
1478 print '<input type="hidden" name="vatnumber" value="'.$contract->thirdparty->tva_intra.'">'."\n";
1479 $labeldesc = $langs->trans("Contract").' '.$contract->ref;
1480 if (GETPOST('desc', 'alpha')) {
1481 $labeldesc = GETPOST('desc', 'alpha');
1482 }
1483 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1484}
1485
1486// Payment on a Member subscription
1487if ($source == 'member' || $source == 'membersubscription') {
1488 $newsource = 'member';
1489
1490 $tag="";
1491 $found = true;
1492 $langs->load("members");
1493
1494 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1495 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
1496 require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1497
1498 $member = new Adherent($db);
1499 $adht = new AdherentType($db);
1500
1501 $result = $member->fetch('', $ref);
1502 if ($result <= 0) {
1503 $mesg = $member->error;
1504 $error++;
1505 } else {
1506 $member->fetch_thirdparty();
1507 $subscription = new Subscription($db);
1508
1509 $adht->fetch($member->typeid);
1510 }
1511 $object = $member;
1512
1513 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1514 $amount = $subscription->total_ttc;
1515 if (GETPOST("amount", 'alpha')) {
1516 $amount = GETPOST("amount", 'alpha');
1517 }
1518 // If amount still not defined, we take amount of the type of member
1519 if (empty($amount)) {
1520 $amount = $adht->amount;
1521 }
1522
1523 $amount = max(0, price2num($amount, 'MT'));
1524 }
1525
1526 if (GETPOST('fulltag', 'alpha')) {
1527 $fulltag = GETPOST('fulltag', 'alpha');
1528 } else {
1529 $fulltag = 'MEM='.$member->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1530 if (!empty($TAG)) {
1531 $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1532 }
1533 }
1534 $fulltag = dol_string_unaccent($fulltag);
1535
1536 // Creditor
1537 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1538 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1539 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1540 print '</td></tr>'."\n";
1541
1542 // Debitor
1543 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Member");
1544 print '</td><td class="CTableRow2">';
1545 print '<b>';
1546 if ($member->morphy == 'mor' && !empty($member->company)) {
1547 print img_picto('', 'company', 'class="pictofixedwidth"');
1548 print $member->company;
1549 } else {
1550 print img_picto('', 'member', 'class="pictofixedwidth"');
1551 print $member->getFullName($langs);
1552 }
1553 print '</b>';
1554 print '</td></tr>'."\n";
1555
1556 // Object
1557 $text = '<b>'.$langs->trans("PaymentSubscription").'</b>';
1558 if (GETPOST('desc', 'alpha')) {
1559 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1560 }
1561 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1562 print '</td><td class="CTableRow2">'.$text;
1563 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($newsource).'">';
1564 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($member->ref).'">';
1565 print '</td></tr>'."\n";
1566
1567 if ($object->datefin > 0) {
1568 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("DateEndSubscription");
1569 print '</td><td class="CTableRow2">'.dol_print_date($member->datefin, 'day');
1570 print '</td></tr>'."\n";
1571 }
1572
1573 if ($member->last_subscription_date || $member->last_subscription_amount) {
1574 // Last subscription date
1575
1576 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastSubscriptionDate");
1577 print '</td><td class="CTableRow2">'.dol_print_date($member->last_subscription_date, 'day');
1578 print '</td></tr>'."\n";
1579
1580 // Last subscription amount
1581
1582 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastSubscriptionAmount");
1583 print '</td><td class="CTableRow2">'.price($member->last_subscription_amount);
1584 print '</td></tr>'."\n";
1585
1586 if (empty($amount) && !GETPOST('newamount', 'alpha')) {
1587 $_GET['newamount'] = $member->last_subscription_amount;
1588 $_GET['amount'] = $member->last_subscription_amount;
1589 }
1590 if (!empty($member->last_subscription_amount) && !GETPOSTISSET('newamount') && is_numeric($amount)) {
1591 $amount = max($member->last_subscription_amount, $amount);
1592 }
1593 }
1594
1595 if ($member->type) {
1596 $oldtypeid = $member->typeid;
1597 $newtypeid = (int) (GETPOSTISSET("typeid") ? GETPOST("typeid", 'int') : $member->typeid);
1598
1599 if (!empty($conf->global->MEMBER_ALLOW_CHANGE_OF_TYPE)) {
1600 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
1601 $adht = new AdherentType($db);
1602 // Amount by member type
1603 $amountbytype = $adht->amountByType(1);
1604
1605 // Last member type
1606 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastMemberType");
1607 print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1608 print "</td></tr>\n";
1609
1610 // Set the new member type
1611 $member->typeid = $newtypeid;
1612 $member->type = dol_getIdFromCode($db, $newtypeid, 'adherent_type', 'rowid', 'libelle');
1613
1614 // list member type
1615 if (!$action) {
1616 // Set amount for the subscription
1617 $amount = (!empty($amountbytype[$member->typeid])) ? $amountbytype[$member->typeid] : $member->last_subscription_amount;
1618
1619 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("NewSubscription");
1620 print '</td><td class="CTableRow2">';
1621 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);
1622 print "</td></tr>\n";
1623 } elseif ($action == 'dopayment') {
1624 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("NewMemberType");
1625 print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1626 print '<input type="hidden" name="membertypeid" value="'.$member->typeid.'">';
1627 print "</td></tr>\n";
1628 }
1629 } else {
1630 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("MemberType");
1631 print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1632 print "</td></tr>\n";
1633 }
1634 }
1635
1636 // Amount
1637 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1638 // This place no longer allows amount edition
1639 if (!empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) {
1640 print ' - <a href="'.$conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO.'" rel="external" target="_blank" rel="noopener noreferrer">'.$langs->trans("SeeHere").'</a>';
1641 }
1642 print '</td><td class="CTableRow2">';
1643 if (!empty($conf->global->MEMBER_MIN_AMOUNT) && $amount) {
1644 $amount = max(0, $conf->global->MEMBER_MIN_AMOUNT, $amount);
1645 }
1646 $caneditamount = $adht->caneditamount;
1647 $minimumamount = empty($conf->global->MEMBER_MIN_AMOUNT)? $adht->amount : max($conf->global->MEMBER_MIN_AMOUNT, $adht->amount, $amount);
1648
1649 if ($caneditamount && $action != 'dopayment') {
1650 if (GETPOSTISSET('newamount')) {
1651 print '<input type="text" class="width75" name="newamount" value="'.price(price2num(GETPOST('newamount'), '', 2), 1, $langs, 1, -1, -1).'">';
1652 } else {
1653 print '<input type="text" class="width75" name="newamount" value="'.price($amount, 1, $langs, 1, -1, -1).'">';
1654 }
1655 } else {
1656 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1657 if ($minimumamount > $amount) {
1658 print ' &nbsp; <span class="opacitymedium small">'. $langs->trans("AmountIsLowerToMinimumNotice", price($minimumamount, 1, $langs, 1, -1, -1, $currency)).'</span>';
1659 }
1660 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1661 }
1662 print '<input type="hidden" name="amount" value="'.$amount.'">';
1663 print '<input type="hidden" name="currency" value="'.$currency.'">';
1664 print '</td></tr>'."\n";
1665
1666 // Tag
1667 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1668 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1669 print '<input type="hidden" name="tag" value="'.$tag.'">';
1670 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1671 print '</td></tr>'."\n";
1672
1673 // Shipping address
1674 $shipToName = $member->getFullName($langs);
1675 $shipToStreet = $member->address;
1676 $shipToCity = $member->town;
1677 $shipToState = $member->state_code;
1678 $shipToCountryCode = $member->country_code;
1679 $shipToZip = $member->zip;
1680 $shipToStreet2 = '';
1681 $phoneNum = $member->phone;
1682 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1683 print '<!-- Shipping address information -->';
1684 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1685 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1686 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1687 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1688 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1689 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1690 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1691 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1692 } else {
1693 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1694 }
1695 if (is_object($member->thirdparty)) {
1696 print '<input type="hidden" name="thirdparty_id" value="'.$member->thirdparty->id.'">'."\n";
1697 }
1698 print '<input type="hidden" name="email" value="'.$member->email.'">'."\n";
1699 $labeldesc = $langs->trans("PaymentSubscription");
1700 if (GETPOST('desc', 'alpha')) {
1701 $labeldesc = GETPOST('desc', 'alpha');
1702 }
1703 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1704}
1705
1706// Payment on donation
1707if ($source == 'donation') {
1708 $found = true;
1709 $langs->load("don");
1710
1711 require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
1712
1713 $don = new Don($db);
1714 $result = $don->fetch($ref);
1715 if ($result <= 0) {
1716 $mesg = $don->error;
1717 $error++;
1718 } else {
1719 $don->fetch_thirdparty();
1720 }
1721 $object = $don;
1722
1723 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1724 if (GETPOST("amount", 'alpha')) {
1725 $amount = GETPOST("amount", 'alpha');
1726 } else {
1727 $amount = $don->getRemainToPay();
1728 }
1729 $amount = price2num($amount);
1730 }
1731
1732 if (GETPOST('fulltag', 'alpha')) {
1733 $fulltag = GETPOST('fulltag', 'alpha');
1734 } else {
1735 $fulltag = 'DON='.$don->ref.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1736 if (!empty($TAG)) {
1737 $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1738 }
1739 }
1740 $fulltag = dol_string_unaccent($fulltag);
1741
1742 // Creditor
1743 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1744 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1745 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1746 print '</td></tr>'."\n";
1747
1748 // Debitor
1749 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1750 print '</td><td class="CTableRow2"><b>';
1751 if ($don->morphy == 'mor' && !empty($don->societe)) {
1752 print $don->societe;
1753 } else {
1754 print $don->getFullName($langs);
1755 }
1756 print '</b>';
1757 print '</td></tr>'."\n";
1758
1759 // Object
1760 $text = '<b>'.$langs->trans("PaymentDonation").'</b>';
1761 if (GETPOST('desc', 'alpha')) {
1762 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1763 }
1764 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1765 print '</td><td class="CTableRow2">'.$text;
1766 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1767 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($don->ref).'">';
1768 print '</td></tr>'."\n";
1769
1770 // Amount
1771 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1772 if (empty($amount)) {
1773 if (empty($conf->global->DONATION_NEWFORM_AMOUNT)) {
1774 print ' ('.$langs->trans("ToComplete");
1775 }
1776 if (!empty($conf->global->DONATION_EXT_URL_SUBSCRIPTION_INFO)) {
1777 print ' - <a href="'.$conf->global->DONATION_EXT_URL_SUBSCRIPTION_INFO.'" rel="external" target="_blank" rel="noopener noreferrer">'.$langs->trans("SeeHere").'</a>';
1778 }
1779 if (empty($conf->global->DONATION_NEWFORM_AMOUNT)) {
1780 print ')';
1781 }
1782 }
1783 print '</td><td class="CTableRow2">';
1784 $valtoshow = '';
1785 if (empty($amount) || !is_numeric($amount)) {
1786 $valtoshow = price2num(GETPOST("newamount", 'alpha'), 'MT');
1787 // force default subscription amount to value defined into constant...
1788 if (empty($valtoshow)) {
1789 if (!empty($conf->global->DONATION_NEWFORM_EDITAMOUNT)) {
1790 if (!empty($conf->global->DONATION_NEWFORM_AMOUNT)) {
1791 $valtoshow = $conf->global->DONATION_NEWFORM_AMOUNT;
1792 }
1793 } else {
1794 if (!empty($conf->global->DONATION_NEWFORM_AMOUNT)) {
1795 $amount = $conf->global->DONATION_NEWFORM_AMOUNT;
1796 }
1797 }
1798 }
1799 }
1800 if (empty($amount) || !is_numeric($amount)) {
1801 //$valtoshow=price2num(GETPOST("newamount",'alpha'),'MT');
1802 if (!empty($conf->global->DONATION_MIN_AMOUNT) && $valtoshow) {
1803 $valtoshow = max($conf->global->DONATION_MIN_AMOUNT, $valtoshow);
1804 }
1805 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1806 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.$valtoshow.'">';
1807 // Currency
1808 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1809 } else {
1810 $valtoshow = $amount;
1811 if (!empty($conf->global->DONATION_MIN_AMOUNT) && $valtoshow) {
1812 $valtoshow = max($conf->global->DONATION_MIN_AMOUNT, $valtoshow);
1813 $amount = $valtoshow;
1814 }
1815 print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1816 print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
1817 print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
1818 }
1819 print '<input type="hidden" name="currency" value="'.$currency.'">';
1820 print '</td></tr>'."\n";
1821
1822 // Tag
1823 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1824 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1825 print '<input type="hidden" name="tag" value="'.$tag.'">';
1826 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1827 print '</td></tr>'."\n";
1828
1829 // Shipping address
1830 $shipToName = $don->getFullName($langs);
1831 $shipToStreet = $don->address;
1832 $shipToCity = $don->town;
1833 $shipToState = $don->state_code;
1834 $shipToCountryCode = $don->country_code;
1835 $shipToZip = $don->zip;
1836 $shipToStreet2 = '';
1837 $phoneNum = $don->phone;
1838 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1839 print '<!-- Shipping address information -->';
1840 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1841 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1842 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1843 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1844 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1845 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1846 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1847 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1848 } else {
1849 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1850 }
1851 if (is_object($don->thirdparty)) {
1852 print '<input type="hidden" name="thirdparty_id" value="'.$don->thirdparty->id.'">'."\n";
1853 }
1854 print '<input type="hidden" name="email" value="'.$don->email.'">'."\n";
1855 $labeldesc = $langs->trans("PaymentSubscription");
1856 if (GETPOST('desc', 'alpha')) {
1857 $labeldesc = GETPOST('desc', 'alpha');
1858 }
1859 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1860}
1861
1862if ($source == 'organizedeventregistration') {
1863 $found = true;
1864 $langs->loadLangs(array("members", "eventorganization"));
1865
1866 if (GETPOST('fulltag', 'alpha')) {
1867 $fulltag = GETPOST('fulltag', 'alpha');
1868 } else {
1869 $fulltag = 'ATT='.$attendee->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1870 if (!empty($TAG)) {
1871 $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1872 }
1873 }
1874 $fulltag = dol_string_unaccent($fulltag);
1875
1876 // Creditor
1877 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1878 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1879 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1880 print '</td></tr>'."\n";
1881
1882 // Debitor
1883 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Attendee");
1884 print '</td><td class="CTableRow2"><b>';
1885 print $attendee->email;
1886 print ($thirdparty->name ? ' ('.$thirdparty->name.')' : '');
1887 print '</b>';
1888 print '</td></tr>'."\n";
1889
1890 if (! is_object($attendee->project)) {
1891 $text = 'ErrorProjectNotFound';
1892 } else {
1893 $text = $langs->trans("PaymentEvent").' - '.$attendee->project->title;
1894 }
1895
1896 // Object
1897 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1898 print '</td><td class="CTableRow2"><b>'.$text.'</b>';
1899 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1900 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($invoice->id).'">';
1901 print '</td></tr>'."\n";
1902
1903 // Amount
1904 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1905 print '</td><td class="CTableRow2">';
1906 $valtoshow = $amount;
1907 print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1908 print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
1909 print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
1910 print '<input type="hidden" name="currency" value="'.$currency.'">';
1911 print '</td></tr>'."\n";
1912
1913 // Tag
1914 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1915 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1916 print '<input type="hidden" name="tag" value="'.$tag.'">';
1917 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1918 print '</td></tr>'."\n";
1919
1920 // Shipping address
1921 $shipToName = $thirdparty->getFullName($langs);
1922 $shipToStreet = $thirdparty->address;
1923 $shipToCity = $thirdparty->town;
1924 $shipToState = $thirdparty->state_code;
1925 $shipToCountryCode = $thirdparty->country_code;
1926 $shipToZip = $thirdparty->zip;
1927 $shipToStreet2 = '';
1928 $phoneNum = $thirdparty->phone;
1929 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1930 print '<!-- Shipping address information -->';
1931 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1932 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1933 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1934 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1935 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1936 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1937 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1938 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1939 } else {
1940 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1941 }
1942 print '<input type="hidden" name="thirdparty_id" value="'.$thirdparty->id.'">'."\n";
1943 print '<input type="hidden" name="email" value="'.$thirdparty->email.'">'."\n";
1944 $labeldesc = $langs->trans("PaymentSubscription");
1945 if (GETPOST('desc', 'alpha')) {
1946 $labeldesc = GETPOST('desc', 'alpha');
1947 }
1948 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1949}
1950
1951if ($source == 'boothlocation') {
1952 $found = true;
1953 $langs->load("members");
1954
1955 if (GETPOST('fulltag', 'alpha')) {
1956 $fulltag = GETPOST('fulltag', 'alpha');
1957 } else {
1958 $fulltag = 'BOO='.GETPOST("booth").'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1959 if (!empty($TAG)) {
1960 $tag = $TAG; $fulltag .= '.TAG='.$TAG;
1961 }
1962 }
1963 $fulltag = dol_string_unaccent($fulltag);
1964
1965 // Creditor
1966 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1967 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1968 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1969 print '</td></tr>'."\n";
1970
1971 // Debitor
1972 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Attendee");
1973 print '</td><td class="CTableRow2"><b>';
1974 print $thirdparty->name;
1975 print '</b>';
1976 print '</td></tr>'."\n";
1977
1978 // Object
1979 $text = '<b>'.$langs->trans("PaymentBoothLocation").'</b>';
1980 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1981 print '</td><td class="CTableRow2">'.$text;
1982 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1983 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($invoice->id).'">';
1984 print '</td></tr>'."\n";
1985
1986 // Amount
1987 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1988 print '</td><td class="CTableRow2">';
1989 $valtoshow = $amount;
1990 print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1991 print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
1992 print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
1993 print '<input type="hidden" name="currency" value="'.$currency.'">';
1994 print '</td></tr>'."\n";
1995
1996 // Tag
1997 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1998 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1999 print '<input type="hidden" name="tag" value="'.$tag.'">';
2000 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
2001 print '</td></tr>'."\n";
2002
2003 // Shipping address
2004 $shipToName = $thirdparty->getFullName($langs);
2005 $shipToStreet = $thirdparty->address;
2006 $shipToCity = $thirdparty->town;
2007 $shipToState = $thirdparty->state_code;
2008 $shipToCountryCode = $thirdparty->country_code;
2009 $shipToZip = $thirdparty->zip;
2010 $shipToStreet2 = '';
2011 $phoneNum = $thirdparty->phone;
2012 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
2013 print '<!-- Shipping address information -->';
2014 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
2015 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
2016 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
2017 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
2018 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
2019 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
2020 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
2021 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
2022 } else {
2023 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
2024 }
2025 print '<input type="hidden" name="thirdparty_id" value="'.$thirdparty->id.'">'."\n";
2026 print '<input type="hidden" name="email" value="'.$thirdparty->email.'">'."\n";
2027 $labeldesc = $langs->trans("PaymentSubscription");
2028 if (GETPOST('desc', 'alpha')) {
2029 $labeldesc = GETPOST('desc', 'alpha');
2030 }
2031 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
2032}
2033
2034if (!$found && !$mesg) {
2035 $mesg = $langs->trans("ErrorBadParameters");
2036}
2037
2038if ($mesg) {
2039 print '<tr><td align="center" colspan="2"><br><div class="warning">'.dol_escape_htmltag($mesg, 1, 1, 'br').'</div></td></tr>'."\n";
2040}
2041
2042print '</table>'."\n";
2043print "\n";
2044
2045
2046// Show all payment mode buttons (Stripe, Paypal, ...)
2047if ($action != 'dopayment') {
2048 if ($found && !$error) { // We are in a management option and no error
2049 // Check status of the object (Invoice) to verify if it is paid by external payment modules (ie Payzen, ...)
2050 $parameters = [
2051 'source' => $source,
2052 'object' => $object
2053 ];
2054 $reshook = $hookmanager->executeHooks('doCheckStatus', $parameters, $object, $action);
2055 if ($reshook < 0) {
2056 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2057 } elseif ($reshook > 0) {
2058 print $hookmanager->resPrint;
2059 }
2060
2061 if ($source == 'order' && $object->billed) {
2062 print '<br><br><span class="amountpaymentcomplete size15x">'.$langs->trans("OrderBilled").'</span>';
2063 } elseif ($source == 'invoice' && $object->paye) {
2064 print '<br><br><span class="amountpaymentcomplete size15x">'.$langs->trans("InvoicePaid").'</span>';
2065 } elseif ($source == 'donation' && $object->paid) {
2066 print '<br><br><span class="amountpaymentcomplete size15x">'.$langs->trans("DonationPaid").'</span>';
2067 } else {
2068 // Membership can be paid and we still allow to make renewal
2069 if (($source == 'member' || $source == 'membersubscription') && $object->datefin > dol_now()) {
2070 $langs->load("members");
2071 print '<br><span class="amountpaymentcomplete size15x">'.$langs->trans("MembershipPaid", dol_print_date($object->datefin, 'day')).'</span><br>';
2072 print '<div class="opacitymedium margintoponly">'.$langs->trans("PaymentWillBeRecordedForNextPeriod").'</div>';
2073 }
2074
2075 // Buttons for all payments registration methods
2076
2077 // This hook is used to add Button to newpayment.php for external payment modules (ie Payzen, ...)
2078 $parameters = [
2079 'paymentmethod' => $paymentmethod
2080 ];
2081 $reshook = $hookmanager->executeHooks('doAddButton', $parameters, $object, $action);
2082 if ($reshook < 0) {
2083 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2084 } elseif ($reshook > 0) {
2085 print $hookmanager->resPrint;
2086 }
2087
2088 if ((empty($paymentmethod) || $paymentmethod == 'paybox') && isModEnabled('paybox')) {
2089 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").'">';
2090 print '<br>';
2091 print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span>';
2092 print '</div>';
2093 print '<script>
2094 $( document ).ready(function() {
2095 $("#div_dopayment_paybox").click(function(){
2096 $("#dopayment_paybox").click();
2097 });
2098 $("#dopayment_paybox").click(function(e){
2099 $("#div_dopayment_paybox").css( \'cursor\', \'wait\' );
2100 e.stopPropagation();
2101 });
2102 });
2103 </script>
2104 ';
2105 }
2106
2107 if ((empty($paymentmethod) || $paymentmethod == 'stripe') && isModEnabled('stripe')) {
2108 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").'">';
2109 print '<input type="hidden" name="noidempotency" value="'.GETPOST('noidempotency', 'int').'">';
2110 print '<br>';
2111 print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span>';
2112 print '</div>';
2113 print '<script>
2114 $( document ).ready(function() {
2115 $("#div_dopayment_stripe").click(function(){
2116 $("#dopayment_stripe").click();
2117 });
2118 $("#dopayment_stripe").click(function(e){
2119 $("#div_dopayment_stripe").css( \'cursor\', \'wait\' );
2120 e.stopPropagation();
2121 return true;
2122 });
2123 });
2124 </script>
2125 ';
2126 }
2127
2128 if ((empty($paymentmethod) || $paymentmethod == 'paypal') && isModEnabled('paypal')) {
2129 if (empty($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY)) {
2130 $conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY = 'integral';
2131 }
2132
2133 print '<div class="button buttonpayment" id="div_dopayment_paypal">';
2134 if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY != 'integral') {
2135 print '<div style="line-height: 1em">&nbsp;</div>';
2136 }
2137 print '<span class="fa fa-paypal"></span> <input class="" type="submit" id="dopayment_paypal" name="dopayment_paypal" value="'.$langs->trans("PaypalDoPayment").'">';
2138 if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'integral') {
2139 print '<br>';
2140 print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span><span class="buttonpaymentsmall"> - </span>';
2141 print '<span class="buttonpaymentsmall">'.$langs->trans("PayPalBalance").'</span>';
2142 }
2143 if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'paypalonly') {
2144 //print '<br>';
2145 //print '<span class="buttonpaymentsmall">'.$langs->trans("PayPalBalance").'"></span>';
2146 }
2147 print '</div>';
2148 print '<script>
2149 $( document ).ready(function() {
2150 $("#div_dopayment_paypal").click(function(){
2151 $("#dopayment_paypal").click();
2152 });
2153 $("#dopayment_paypal").click(function(e){
2154 $("#div_dopayment_paypal").css( \'cursor\', \'wait\' );
2155 e.stopPropagation();
2156 return true;
2157 });
2158 });
2159 </script>
2160 ';
2161 }
2162 }
2163 } else {
2164 dol_print_error_email('ERRORNEWPAYMENT');
2165 }
2166} else {
2167 // Print
2168}
2169
2170print '</td></tr>'."\n";
2171
2172print '</table>'."\n";
2173
2174print '</form>'."\n";
2175print '</div>'."\n";
2176
2177print '<br>';
2178
2179
2180
2181// Add more content on page for some services
2182if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payment mode
2183 // Save some data for the paymentok
2184 $remoteip = getUserRemoteIP();
2185 $_SESSION["currencyCodeType"] = $currency;
2186 $_SESSION["FinalPaymentAmt"] = $amount;
2187 $_SESSION['ipaddress'] = ($remoteip ? $remoteip : 'unknown'); // Payer ip
2188 $_SESSION["paymentType"] = '';
2189
2190 // For Stripe
2191 if (GETPOST('dopayment_stripe', 'alpha')) {
2192 // Personalized checkout
2193 print '<style>
2198 .StripeElement {
2199 background-color: white;
2200 padding: 8px 12px;
2201 border-radius: 4px;
2202 border: 1px solid transparent;
2203 box-shadow: 0 1px 3px 0 #e6ebf1;
2204 -webkit-transition: box-shadow 150ms ease;
2205 transition: box-shadow 150ms ease;
2206 }
2207
2208 .StripeElement--focus {
2209 box-shadow: 0 1px 3px 0 #cfd7df;
2210 }
2211
2212 .StripeElement--invalid {
2213 border-color: #fa755a;
2214 }
2215
2216 .StripeElement--webkit-autofill {
2217 background-color: #fefde5 !important;
2218 }
2219 </style>';
2220
2221 //print '<br>';
2222
2223 print '<!-- Show Stripe form payment-form STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = '.$conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION.' STRIPE_USE_NEW_CHECKOUT = '.$conf->global->STRIPE_USE_NEW_CHECKOUT.' -->'."\n";
2224 print '<form action="'.$_SERVER['REQUEST_URI'].'" method="POST" id="payment-form">'."\n";
2225
2226 print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
2227 print '<input type="hidden" name="dopayment_stripe" value="1">'."\n";
2228 print '<input type="hidden" name="action" value="charge">'."\n";
2229 print '<input type="hidden" name="tag" value="'.$TAG.'">'."\n";
2230 print '<input type="hidden" name="s" value="'.$source.'">'."\n";
2231 print '<input type="hidden" name="ref" value="'.$REF.'">'."\n";
2232 print '<input type="hidden" name="fulltag" value="'.$FULLTAG.'">'."\n";
2233 print '<input type="hidden" name="suffix" value="'.$suffix.'">'."\n";
2234 print '<input type="hidden" name="securekey" value="'.$SECUREKEY.'">'."\n";
2235 print '<input type="hidden" name="e" value="'.$entity.'" />';
2236 print '<input type="hidden" name="amount" value="'.$amount.'">'."\n";
2237 print '<input type="hidden" name="currency" value="'.$currency.'">'."\n";
2238 print '<input type="hidden" name="forcesandbox" value="'.GETPOST('forcesandbox', 'int').'" />';
2239 print '<input type="hidden" name="email" value="'.GETPOST('email', 'alpha').'" />';
2240 print '<input type="hidden" name="thirdparty_id" value="'.GETPOST('thirdparty_id', 'int').'" />';
2241 print '<input type="hidden" name="lang" value="'.$getpostlang.'">';
2242
2243 if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION) || !empty($conf->global->STRIPE_USE_NEW_CHECKOUT)) { // Use a SCA ready method
2244 require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
2245
2246 $service = 'StripeLive';
2247 $servicestatus = 1;
2248 if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) {
2249 $service = 'StripeTest';
2250 $servicestatus = 0;
2251 }
2252
2253 $stripe = new Stripe($db);
2254 $stripeacc = $stripe->getStripeAccount($service);
2255 $stripecu = null;
2256 if (is_object($object) && is_object($object->thirdparty)) {
2257 $stripecu = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1);
2258 }
2259
2260 if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
2261 $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.
2262 $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);
2263 // The paymentintnent has status 'requires_payment_method' (even if paymentintent was already paid)
2264 //var_dump($paymentintent);
2265 if ($stripe->error) {
2266 setEventMessages($stripe->error, null, 'errors');
2267 }
2268 }
2269 }
2270
2271 // Note:
2272 // $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = 1 = use intent object (default value, suggest card payment mode only)
2273 // $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = 2 = use payment object (suggest both card payment mode but also sepa, ...)
2274
2275 print '
2276 <table id="dolpaymenttable" summary="Payment form" class="center centpercent">
2277 <tbody><tr><td class="textpublicpayment">';
2278
2279 if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
2280 print '<div id="payment-request-button"><!-- A Stripe Element will be inserted here. --></div>';
2281 }
2282
2283 print '<div class="form-row '.(getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2 ? 'center' : 'left').'">';
2284 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) {
2285 print '<label for="card-element">'.$langs->trans("CreditOrDebitCard").'</label>';
2286 print '<br><input id="cardholder-name" class="marginbottomonly" name="cardholder-name" value="" type="text" placeholder="'.$langs->trans("CardOwner").'" autocomplete="off" autofocus required>';
2287 }
2288
2289 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) {
2290 print '<div id="card-element">
2291 <!-- a Stripe Element will be inserted here. -->
2292 </div>';
2293 }
2294 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) {
2295 print '<div id="payment-element">
2296 <!-- a Stripe Element will be inserted here. -->
2297 </div>';
2298 }
2299
2300 print '<!-- Used to display form errors -->
2301 <div id="card-errors" role="alert"></div>
2302 </div>';
2303
2304 print '<br>';
2305 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>';
2306 print '<img id="hourglasstopay" class="hidden" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/working.gif">';
2307
2308 print '</td></tr></tbody>';
2309 print '</table>';
2310 //}
2311
2312 if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
2313 if (empty($paymentintent)) {
2314 print '<center>'.$langs->trans("Error").'</center>';
2315 } else {
2316 print '<input type="hidden" name="paymentintent_id" value="'.$paymentintent->id.'">';
2317 //$_SESSION["paymentintent_id"] = $paymentintent->id;
2318 }
2319 }
2320
2321 print '</form>'."\n";
2322
2323
2324 // JS Code for Stripe
2325 if (empty($stripearrayofkeys['publishable_key'])) {
2326 $langs->load("errors");
2327 print info_admin($langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("Stripe")), 0, 0, 'error');
2328 } else {
2329 print '<!-- JS Code for Stripe components -->';
2330 print '<script src="https://js.stripe.com/v3/"></script>'."\n";
2331 print '<!-- urllogofull = '.$urllogofull.' -->'."\n";
2332
2333 // Code to ask the credit card. This use the default "API version". No way to force API version when using JS code.
2334 print '<script type="text/javascript">'."\n";
2335
2336 if (!empty($conf->global->STRIPE_USE_NEW_CHECKOUT)) {
2337 $amountstripe = $amount;
2338
2339 // Correct the amount according to unit of currency
2340 // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
2341 $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
2342 if (!in_array($currency, $arrayzerounitcurrency)) {
2343 $amountstripe = $amountstripe * 100;
2344 }
2345
2346 $ipaddress = getUserRemoteIP();
2347 $metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress);
2348 if (is_object($object)) {
2349 $metadata['dol_type'] = $object->element;
2350 $metadata['dol_id'] = $object->id;
2351
2352 $ref = $object->ref;
2353 }
2354
2355 try {
2356 $arrayforpaymentintent = array(
2357 'description'=>'Stripe payment: '.$FULLTAG.($ref ? ' ref='.$ref : ''),
2358 "metadata" => $metadata
2359 );
2360 if ($TAG) {
2361 $arrayforpaymentintent["statement_descriptor"] = dol_trunc($TAG, 10, 'right', 'UTF-8', 1); // 22 chars that appears on bank receipt (company + description)
2362 }
2363
2364 $arrayforcheckout = array(
2365 'payment_method_types' => array('card'),
2366 'line_items' => array(array(
2367 'name' => $langs->transnoentitiesnoconv("Payment").' '.$TAG, // Label of product line
2368 'description' => 'Stripe payment: '.$FULLTAG.($ref ? ' ref='.$ref : ''),
2369 'amount' => $amountstripe,
2370 'currency' => $currency,
2371 //'images' => array($urllogofull),
2372 'quantity' => 1,
2373 )),
2374 'client_reference_id' => $FULLTAG,
2375 'success_url' => $urlok,
2376 'cancel_url' => $urlko,
2377 'payment_intent_data' => $arrayforpaymentintent
2378 );
2379 if ($stripecu) {
2380 $arrayforcheckout['customer'] = $stripecu;
2381 } elseif (GETPOST('email', 'alpha') && isValidEmail(GETPOST('email', 'alpha'))) {
2382 $arrayforcheckout['customer_email'] = GETPOST('email', 'alpha');
2383 }
2384 $sessionstripe = \Stripe\Checkout\Session::create($arrayforcheckout);
2385
2386 $remoteip = getUserRemoteIP();
2387
2388 // Save some data for the paymentok
2389 $_SESSION["currencyCodeType"] = $currency;
2390 $_SESSION["paymentType"] = '';
2391 $_SESSION["FinalPaymentAmt"] = $amount;
2392 $_SESSION['ipaddress'] = ($remoteip ? $remoteip : 'unknown'); // Payer ip
2393 $_SESSION['payerID'] = is_object($stripecu) ? $stripecu->id : '';
2394 $_SESSION['TRANSACTIONID'] = $sessionstripe->id;
2395 } catch (Exception $e) {
2396 print $e->getMessage();
2397 }
2398 ?>
2399 // Code for payment with option STRIPE_USE_NEW_CHECKOUT set
2400
2401 // Create a Stripe client.
2402 <?php
2403 if (empty($stripeacc)) {
2404 ?>
2405 var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>');
2406 <?php
2407 } else {
2408 ?>
2409 var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>', { stripeAccount: '<?php echo $stripeacc; ?>' });
2410 <?php
2411 }
2412 ?>
2413
2414 // Create an instance of Elements
2415 var elements = stripe.elements();
2416
2417 // Custom styling can be passed to options when creating an Element.
2418 // (Note that this demo uses a wider set of styles than the guide below.)
2419 var style = {
2420 base: {
2421 color: '#32325d',
2422 lineHeight: '24px',
2423 fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
2424 fontSmoothing: 'antialiased',
2425 fontSize: '16px',
2426 '::placeholder': {
2427 color: '#aab7c4'
2428 }
2429 },
2430 invalid: {
2431 color: '#fa755a',
2432 iconColor: '#fa755a'
2433 }
2434 }
2435
2436 var cardElement = elements.create('card', {style: style});
2437
2438 // Comment this to avoid the redirect
2439 stripe.redirectToCheckout({
2440 // Make the id field from the Checkout Session creation API response
2441 // available to this file, so you can provide it as parameter here
2442 // instead of the {{CHECKOUT_SESSION_ID}} placeholder.
2443 sessionId: '<?php print $sessionstripe->id; ?>'
2444 }).then(function (result) {
2445 // If `redirectToCheckout` fails due to a browser or network
2446 // error, display the localized error message to your customer
2447 // using `result.error.message`.
2448 });
2449
2450
2451 <?php
2452 } elseif (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
2453 ?>
2454 // Code for payment with option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION set to 1 or 2
2455
2456 // Create a Stripe client.
2457 <?php
2458 if (empty($stripeacc)) {
2459 ?>
2460 var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>');
2461 <?php
2462 } else {
2463 ?>
2464 var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>', { stripeAccount: '<?php echo $stripeacc; ?>' });
2465 <?php
2466 }
2467 ?>
2468
2469 <?php
2470 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) {
2471 ?>
2472 var cardButton = document.getElementById('buttontopay');
2473 var clientSecret = cardButton.dataset.secret;
2474 var options = { clientSecret: clientSecret };
2475
2476 // Create an instance of Elements
2477 var elements = stripe.elements(options);
2478 <?php
2479 } else {
2480 ?>
2481 // Create an instance of Elements
2482 var elements = stripe.elements();
2483 <?php
2484 }
2485 ?>
2486
2487 // Custom styling can be passed to options when creating an Element.
2488 // (Note that this demo uses a wider set of styles than the guide below.)
2489 var style = {
2490 base: {
2491 color: '#32325d',
2492 lineHeight: '24px',
2493 fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
2494 fontSmoothing: 'antialiased',
2495 fontSize: '16px',
2496 '::placeholder': {
2497 color: '#aab7c4'
2498 }
2499 },
2500 invalid: {
2501 color: '#fa755a',
2502 iconColor: '#fa755a'
2503 }
2504 }
2505
2506 <?php
2507 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) {
2508 ?>
2509 var paymentElement = elements.create("payment");
2510
2511 // Add an instance of the card Element into the `card-element` <div>
2512 paymentElement.mount("#payment-element");
2513
2514 // Handle form submission
2515 var cardButton = document.getElementById('buttontopay');
2516
2517 cardButton.addEventListener('click', function(event) {
2518 console.log("We click on buttontopay");
2519 event.preventDefault();
2520
2521 /* Disable button to pay and show hourglass cursor */
2522 jQuery('#hourglasstopay').show();
2523 jQuery('#buttontopay').hide();
2524
2525 stripe.confirmPayment({
2526 elements,confirmParams: {
2527 return_url: '<?php echo $urlok; ?>',
2528 payment_method_data: {
2529 billing_details: {
2530 name: 'test'
2531 <?php if (GETPOST('email', 'alpha') || (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->email))) {
2532 ?>, email: '<?php echo dol_escape_js(GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $object->thirdparty->email); ?>'<?php
2533 } ?>
2534 <?php if (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->phone)) {
2535 ?>, phone: '<?php echo dol_escape_js($object->thirdparty->phone); ?>'<?php
2536 } ?>
2537 <?php if (is_object($object) && is_object($object->thirdparty)) {
2538 ?>, address: {
2539 city: '<?php echo dol_escape_js($object->thirdparty->town); ?>',
2540 <?php if ($object->thirdparty->country_code) {
2541 ?>country: '<?php echo dol_escape_js($object->thirdparty->country_code); ?>',<?php
2542 } ?>
2543 line1: '<?php echo dol_escape_js(preg_replace('/\s\s+/', ' ', $object->thirdparty->address)); ?>',
2544 postal_code: '<?php echo dol_escape_js($object->thirdparty->zip); ?>'
2545 }
2546 <?php } ?>
2547 }
2548 },
2549 save_payment_method:<?php if ($stripecu) {
2550 print 'true';
2551 } else {
2552 print 'false';
2553 } ?> /* true when a customer was provided when creating payment intent. true ask to save the card */
2554 },
2555 }
2556 ).then(function(result) {
2557 console.log(result);
2558 if (result.error) {
2559 console.log("Error on result of handleCardPayment");
2560 jQuery('#buttontopay').show();
2561 jQuery('#hourglasstopay').hide();
2562 // Inform the user if there was an error
2563 var errorElement = document.getElementById('card-errors');
2564 console.log(result);
2565 errorElement.textContent = result.error.message;
2566 } else {
2567 // The payment has succeeded. Display a success message.
2568 console.log("No error on result of handleCardPayment, so we submit the form");
2569 // Submit the form
2570 jQuery('#buttontopay').hide();
2571 jQuery('#hourglasstopay').show();
2572 // Send form (action=charge that will do nothing)
2573 jQuery('#payment-form').submit();
2574 }
2575 });
2576
2577 });
2578 <?php
2579 } else {
2580 ?>
2581 var cardElement = elements.create('card', {style: style});
2582
2583 // Add an instance of the card Element into the `card-element` <div>
2584 cardElement.mount('#card-element');
2585
2586 // Handle real-time validation errors from the card Element.
2587 cardElement.addEventListener('change', function(event) {
2588 var displayError = document.getElementById('card-errors');
2589 if (event.error) {
2590 console.log("Show event error (like 'Incorrect card number', ...)");
2591 displayError.textContent = event.error.message;
2592 } else {
2593 console.log("Reset error message");
2594 displayError.textContent = '';
2595 }
2596 });
2597
2598 // Handle form submission
2599 var cardholderName = document.getElementById('cardholder-name');
2600 var cardButton = document.getElementById('buttontopay');
2601 var clientSecret = cardButton.dataset.secret;
2602
2603 cardButton.addEventListener('click', function(event) {
2604 console.log("We click on buttontopay");
2605 event.preventDefault();
2606
2607 if (cardholderName.value == '')
2608 {
2609 console.log("Field Card holder is empty");
2610 var displayError = document.getElementById('card-errors');
2611 displayError.textContent = '<?php print dol_escape_js($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CardOwner"))); ?>';
2612 }
2613 else
2614 {
2615 /* Disable button to pay and show hourglass cursor */
2616 jQuery('#hourglasstopay').show();
2617 jQuery('#buttontopay').hide();
2618
2619 stripe.handleCardPayment(
2620 clientSecret, cardElement, {
2621 payment_method_data: {
2622 billing_details: {
2623 name: cardholderName.value
2624 <?php if (GETPOST('email', 'alpha') || (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->email))) {
2625 ?>, email: '<?php echo dol_escape_js(GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $object->thirdparty->email); ?>'<?php
2626 } ?>
2627 <?php if (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->phone)) {
2628 ?>, phone: '<?php echo dol_escape_js($object->thirdparty->phone); ?>'<?php
2629 } ?>
2630 <?php if (is_object($object) && is_object($object->thirdparty)) {
2631 ?>, address: {
2632 city: '<?php echo dol_escape_js($object->thirdparty->town); ?>',
2633 <?php if ($object->thirdparty->country_code) {
2634 ?>country: '<?php echo dol_escape_js($object->thirdparty->country_code); ?>',<?php
2635 } ?>
2636 line1: '<?php echo dol_escape_js(preg_replace('/\s\s+/', ' ', $object->thirdparty->address)); ?>',
2637 postal_code: '<?php echo dol_escape_js($object->thirdparty->zip); ?>'
2638 }
2639 <?php } ?>
2640 }
2641 },
2642 save_payment_method:<?php if ($stripecu) {
2643 print 'true';
2644 } else {
2645 print 'false';
2646 } ?> /* true when a customer was provided when creating payment intent. true ask to save the card */
2647 }
2648 ).then(function(result) {
2649 console.log(result);
2650 if (result.error) {
2651 console.log("Error on result of handleCardPayment");
2652 jQuery('#buttontopay').show();
2653 jQuery('#hourglasstopay').hide();
2654 // Inform the user if there was an error
2655 var errorElement = document.getElementById('card-errors');
2656 errorElement.textContent = result.error.message;
2657 } else {
2658 // The payment has succeeded. Display a success message.
2659 console.log("No error on result of handleCardPayment, so we submit the form");
2660 // Submit the form
2661 jQuery('#buttontopay').hide();
2662 jQuery('#hourglasstopay').show();
2663 // Send form (action=charge that will do nothing)
2664 jQuery('#payment-form').submit();
2665 }
2666 });
2667 }
2668 });
2669 <?php
2670 }
2671 ?>
2672
2673 <?php
2674 }
2675
2676 print '</script>';
2677 }
2678 }
2679
2680 // For any other payment services
2681 // This hook can be used to show the embedded form to make payments with external payment modules (ie Payzen, ...)
2682 $parameters = [
2683 'paymentmethod' => $paymentmethod,
2684 'amount' => $amount,
2685 'currency' => $currency,
2686 'tag' => GETPOST("tag", 'alpha'),
2687 'dopayment' => GETPOST('dopayment', 'alpha')
2688 ];
2689 $reshook = $hookmanager->executeHooks('doPayment', $parameters, $object, $action);
2690 if ($reshook < 0) {
2691 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2692 } elseif ($reshook > 0) {
2693 print $hookmanager->resPrint;
2694 }
2695}
2696
2697htmlPrintOnlineFooter($mysoc, $langs, 1, $suffix, $object);
2698
2699llxFooter('', 'public');
2700
2701$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:56
llxFooter()
Empty footer.
Definition wrapper.php:70
$object ref
Definition info.php:78
Class to manage members of a foundation.
Class to manage members type.
Class to manage customers orders.
Class for ConferenceOrBoothAttendee.
Class to manage contracts.
Class to manage lines of contracts.
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
Class to manage hooks.
Class to manage payments of donations.
Class to manage products or services.
Class to manage third parties objects (customers, suppliers, prospects...)
Stripe class.
Class to manage subscriptions of foundation members.
htmlPrintOnlineFooter($fromcompany, $langs, $addformmessage=0, $suffix='', $object=null)
Show footer of company in HTML pages.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_error_email($prefixcode, $errormessage='', $errormessages=array(), $morecss='error', $email='')
Show a public email and error code to contact if technical error.
dol_htmloutput_mesg($mesgstring='', $mesgarray=array(), $style='ok', $keepembedded=0)
Print formated messages to output (Used to show messages on html output).
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
isValidEmail($address, $acceptsupervisorkey=0, $acceptuserkey=0)
Return true if email syntax is ok.
getUserRemoteIP()
Return the IP of remote user.
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'))
ui dialog ui datepicker calendar ui widget content ui state ui datepicker calendar ui widget header ui state ui datepicker calendar ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
print_paybox_redirect($PRICE, $CURRENCY, $EMAIL, $urlok, $urlko, $TAG)
Create a redirect form to paybox form.
print_paypal_redirect($paymentAmount, $currencyCodeType, $paymentType, $returnURL, $cancelURL, $tag)
Send redirect to paypal to browser.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:123
dol_verifyHash($chain, $hash, $type='0')
Compute a hash and compare it to the given one For backward compatibility reasons,...