dolibarr 25.0.0-alpha
pay.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2018 Andreu Bisquerra <jove@bisquerra.com>
3 * Copyright (C) 2021-2022 Thibault FOUCART <support@ptibogxiv.net>
4 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
27// if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Not disabled cause need to load personalized language
28// if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Not disabled cause need to load personalized language
29// if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1');
30// if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1');
31
32if (!defined('NOTOKENRENEWAL')) {
33 define('NOTOKENRENEWAL', '1');
34}
35if (!defined('NOREQUIREMENU')) {
36 define('NOREQUIREMENU', '1');
37}
38if (!defined('NOREQUIREHTML')) {
39 define('NOREQUIREHTML', '1');
40}
41
42// Load Dolibarr environment
43require '../main.inc.php'; // Load $user and permissions
52require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
53require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
54require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
55
56// Load translation files required by the page
57$langs->loadLangs(array("main", "bills", "cashdesk", "banks"));
58
59$action = GETPOST('action', 'aZ09');
60
61$place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : '0'); // $place is id of table for Bar or Restaurant
62
63$invoiceid = GETPOSTINT('invoiceid');
64
65$hookmanager->initHooks(array('takepospay'));
66
67if (!$user->hasRight('takepos', 'run')) {
69}
70
71
72/*
73 * View
74 */
75
76$arrayofcss = array('/takepos/css/pos.css.php');
77$arrayofjs = array();
78
79$head = '';
80$title = '';
81$disablejs = 0;
82$disablehead = 0;
83
84$head = '<link rel="stylesheet" href="css/pos.css.php">';
85if (getDolGlobalInt('TAKEPOS_COLOR_THEME') == 1) {
86 $head .= '<link rel="stylesheet" href="css/colorful.css">';
87}
88
89top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
90
91?>
92<body>
93<?php
94
95$usestripeterminals = 0;
96$keyforstripeterminalbank = '';
97$stripe = null;
98$servicestatus = 0;
99$stripeacc = null;
100
101if (isModEnabled('stripe')) {
102 $service = 'StripeTest';
103
104 if (getDolGlobalString('STRIPE_LIVE')/* && !GETPOST('forcesandbox', 'alpha') */) {
105 $service = 'StripeLive';
106 $servicestatus = 1;
107 }
108
109 // Force to use the correct API key
110 global $stripearrayofkeysbyenv;
111 $site_account = $stripearrayofkeysbyenv[$servicestatus]['publishable_key'];
112
113 $stripe = new Stripe($db);
114 $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account (no remote access to Stripe here)
115
116 include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
117 $invoicetmp = new Facture($db);
118 $invoicetmp->fetch($invoiceid);
119 $stripecu = $stripe->getStripeCustomerAccount($invoicetmp->socid, $servicestatus, $site_account); // Get remote Stripe customer 'cus_...' (no remote access to Stripe here)
120 $keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".(empty($_SESSION['takeposterminal']) ? '' : $_SESSION['takeposterminal']);
121
122 $usestripeterminals = getDolGlobalString('STRIPE_LOCATION');
123
124 if ($usestripeterminals) {
125 ?>
126<script src="https://js.stripe.com/terminal/v1/"></script>
127<script>
128var terminal = StripeTerminal.create({
129 onFetchConnectionToken: fetchConnectionToken,
130 onUnexpectedReaderDisconnect: unexpectedDisconnect,
131});
132
133function unexpectedDisconnect() {
134 // In this function, your app should notify the user that the reader disconnected.
135 // You can also include a way to attempt to reconnect to a reader.
136 console.log("Disconnected from reader")
137}
138
139function fetchConnectionToken() {
140 <?php
141 $urlconnexiontoken = DOL_URL_ROOT.'/stripe/ajax/ajax.php?action=getConnexionToken&token='.currentToken().'&servicestatus='.urlencode((string) ($servicestatus));
142 if (getDolGlobalString('STRIPE_LOCATION')) {
143 $urlconnexiontoken .= '&location='.urlencode(getDolGlobalString('STRIPE_LOCATION'));
144 }
145 if (!empty($stripeacc)) {
146 $urlconnexiontoken .= '&stripeacc='.urlencode($stripeacc);
147 } ?>
148 // Do not cache or hardcode the ConnectionToken. The SDK manages the ConnectionToken's lifecycle.
149 return fetch('<?php echo $urlconnexiontoken; ?>', { method: "POST" })
150 .then(function(response) {
151 return response.json();
152 })
153 .then(function(data) {
154 return data.secret;
155 });
156}
157
158</script>
159 <?php
160 }
161}
162
163if (isModEnabled('stripe') && isset($keyforstripeterminalbank) && (!getDolGlobalString('STRIPE_LIVE')/* || GETPOST('forcesandbox', 'alpha') */)) {
164 dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), [], 'warning', 1);
165}
166
167$invoice = new Facture($db);
168if ($invoiceid > 0) {
169 $invoice->fetch($invoiceid);
170} else {
171 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture";
172 $sql .= " WHERE entity IN (".getEntity('invoice').")";
173 $sql .= " AND ref = '(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")'";
174 $resql = $db->query($sql);
175 $obj = $db->fetch_object($resql);
176 if ($obj) {
177 $invoiceid = $obj->rowid;
178 }
179 if (!$invoiceid) {
180 $invoiceid = 0; // Invoice does not exist yet
181 } else {
182 $invoice->fetch($invoiceid);
183 }
184}
185
186?>
187<script>
188<?php
189if ($usestripeterminals && $invoice->type != $invoice::TYPE_CREDIT_NOTE) {
190 if (!getDolGlobalString((string) $keyforstripeterminalbank) || $stripeacc === null) { ?>
191 const config = {
192 simulated: <?php if (empty($servicestatus) && getDolGlobalString('STRIPE_TERMINAL_SIMULATED')) { ?> true <?php } else { ?> false <?php } ?>
193 <?php if (getDolGlobalString('STRIPE_LOCATION')) { ?>, location: <?php echo "'".dol_escape_js(getDolGlobalString('STRIPE_LOCATION'))."'"; ?><?php } ?>
194 }
195 terminal.discoverReaders(config).then(function(discoverResult) {
196 if (discoverResult.error) {
197 console.log('Failed to discover: ', discoverResult.error);
198 } else if (discoverResult.discoveredReaders.length === 0) {
199 console.log('No available readers.');
200 } else {
201 // You should show the list of discoveredReaders to the
202 // cashier here and let them select which to connect to (see below).
203 selectedReader = discoverResult.discoveredReaders[0];
204 //console.log('terminal.discoverReaders', selectedReader); // only active for development
205
206 terminal.connectReader(selectedReader).then(function(connectResult) {
207 if (connectResult.error) {
208 document.getElementById("card-present-alert").innerHTML = '<div class="error">'+connectResult.error.message+'</div>';
209 console.log('Failed to connect: ', connectResult.error);
210 } else {
211 document.getElementById("card-present-alert").innerHTML = '';
212 console.log('Connected to reader: ', connectResult.reader.label);
213 if (document.getElementById("StripeTerminal")) {
214 document.getElementById("StripeTerminal").innerHTML = '<button type="button" class="calcbutton2" onclick="ValidateStripeTerminal();"><span class="fa fa-2x fa-credit-card iconwithlabel"></span><br>'+connectResult.reader.label+'</button>';
215 }
216 }
217 });
218 }
219 });
220 <?php } else { ?>
221 terminal.connectReader(<?php echo json_encode($stripe->getSelectedReader(getDolGlobalString((string) $keyforstripeterminalbank), $stripeacc, $servicestatus)); ?>).then(function(connectResult) {
222 if (connectResult.error) {
223 document.getElementById("card-present-alert").innerHTML = '<div class="error clearboth">'+connectResult.error.message+'</div>';
224 console.log('Failed to connect: ', connectResult.error);
225 } else {
226 document.getElementById("card-present-alert").innerHTML = '';
227 console.log('Connected to reader: ', connectResult.reader.label);
228 if (document.getElementById("StripeTerminal")) {
229 document.getElementById("StripeTerminal").innerHTML = '<button type="button" class="calcbutton2" onclick="ValidateStripeTerminal();"><span class="fa fa-2x fa-credit-card iconwithlabel"></span><br>'+connectResult.reader.label+'</button>';
230 }
231 }
232 });
233
234 <?php }
235} ?>
236</script>
237<?php
238
239// Define list of possible payments
240$arrayOfValidPaymentModes = array();
241$arrayOfValidBankAccount = array();
242
243$sql = "SELECT code, libelle as label FROM ".MAIN_DB_PREFIX."c_paiement";
244$sql .= " WHERE entity IN (".getEntity('c_paiement').")";
245$sql .= " AND active = 1";
246if (isALNERunningVersion() && $mysoc->country_code == 'FR') {
247 // In certified version, we can use only 3 payments modes in POS because
248 // the cash control feature support only this 3 payment modes
249 $sql .= " AND code IN ('LIQ', 'CB', 'CHQ')";
250}
251$sql .= " ORDER BY libelle";
252$resql = $db->query($sql);
253
254if ($resql) {
255 while ($obj = $db->fetch_object($resql)) {
256 $paycode = $obj->code;
257 if ($paycode == 'LIQ') {
258 $paycode = 'CASH';
259 }
260 if ($paycode == 'CB') {
261 $paycode = 'CB';
262 }
263 if ($paycode == 'CHQ') {
264 $paycode = 'CHEQUE';
265 }
266
267 $accountname = "CASHDESK_ID_BANKACCOUNT_".$paycode.$_SESSION["takeposterminal"];
268 if (getDolGlobalInt($accountname) > 0) {
269 $arrayOfValidBankAccount[getDolGlobalInt($accountname)] = getDolGlobalInt($accountname);
270 $arrayOfValidPaymentModes[] = $obj;
271 }
272 if (!isModEnabled('bank')) {
273 if ($paycode == 'CASH' || $paycode == 'CB') {
274 $arrayOfValidPaymentModes[] = $obj;
275 }
276 }
277 }
278}
279
280?>
281
282<script>
283<?php
284$remaintopay = 0;
285if ($invoice->id > 0) {
286 $remaintopay = $invoice->getRemainToPay();
287}
288$alreadypayed = (is_object($invoice) ? ($invoice->total_ttc - $remaintopay) : 0);
289
290$parameters = array();
291$reshook = $hookmanager->executeHooks('takeposPayActions', $parameters, $invoice, $action);
292
293
294if (!getDolGlobalInt("TAKEPOS_NUMPAD")) {
295 print "var received='';";
296} else {
297 print "var received=0;";
298}
299
300?>
301 var alreadypayed = <?php echo $alreadypayed ?>;
302 var invoicetype = <?php echo $invoice->type ?>;
303
304 function addreceived(price)
305 {
306 <?php
307 if (!getDolGlobalInt("TAKEPOS_NUMPAD")) {
308 print 'received+=String(price);'."\n";
309 } else {
310 print 'received+=parseFloat(price);'."\n";
311 }
312 ?>
313 $('.change1').html(pricejs(parseFloat(received), 'MT'));
314 $('.change1').val(parseFloat(received));
315 console.log("invoicetype="+invoicetype);
316 console.log("alreadyreceived="+alreadypayed);
317 console.log("received="+received);
318 if (invoicetype == 2) {
319 alreadypaydplusreceived = price2numjs(alreadypayed - parseFloat(received));
320 } else {
321 alreadypaydplusreceived = price2numjs(alreadypayed + parseFloat(received));
322 }
323 console.log("already+received = "+alreadypaydplusreceived);
324 //console.log("total_ttc = "+<?php echo (float) $invoice->total_ttc; ?>);
325 if (Math.abs(alreadypaydplusreceived) > Math.abs(<?php echo ((float) $invoice->total_ttc); ?>)) {
326 if (invoicetype == 2) {
327 var change = parseFloat(alreadypayed + parseFloat(received) + <?php echo (float) $invoice->total_ttc; ?>);
328 } else {
329 var change = parseFloat(alreadypayed + parseFloat(received) - <?php echo (float) $invoice->total_ttc; ?>);
330 }
331 $('.change2').html(pricejs(change, 'MT'));
332 $('.change2').val(change);
333 $('.change1').removeClass('colorred');
334 $('.change1').addClass('colorgreen');
335 $('.change2').removeClass('colorwhite');
336 $('.change2').addClass('colorred');
337 } else {
338 $('.change2').html(pricejs(0, 'MT'));
339 $('.change2').val(0);
340 if (alreadypaydplusreceived == <?php echo (float) $invoice->total_ttc; ?>) {
341 $('.change1').removeClass('colorred');
342 $('.change1').addClass('colorgreen');
343 $('.change2').removeClass('colorred');
344 $('.change2').addClass('colorwhite');
345 } else {
346 $('.change1').removeClass('colorgreen');
347 $('.change1').addClass('colorred');
348 $('.change2').removeClass('colorred');
349 $('.change2').addClass('colorwhite');
350 }
351 }
352
353 return true;
354 }
355
356 function reset()
357 {
358 received=0;
359 $('.change1').html(pricejs(received, 'MT'));
360 $('.change1').val(price2numjs(received));
361 $('.change2').html(pricejs(received, 'MT'));
362 $('.change2').val(price2numjs(received));
363 $('.change1').removeClass('colorgreen');
364 $('.change1').addClass('colorred');
365 $('.change2').removeClass('colorred');
366 $('.change2').addClass('colorwhite');
367 }
368
369 function Validate(payment)
370 {
371 console.log("Launch Validate");
372
373 var invoiceid = <?php echo($invoiceid > 0 ? $invoiceid : 0); ?>;
374 var accountid = $("#selectaccountid").val();
375 var amountpayed = $("#change1").val();
376 var excess = $("#change2").val();
377 if (amountpayed > <?php echo (float) $invoice->total_ttc; ?>) {
378 amountpayed = <?php echo (float) $invoice->total_ttc; ?>;
379 }
380 console.log("We click on the payment mode to pay amount = "+amountpayed);
381 parent.$("#poslines").load("invoice.php?place=<?php echo $place; ?>&action=valid&token=<?php echo currentToken(); ?>&pay="+payment+"&amount="+amountpayed+"&excess="+excess+"&invoiceid="+invoiceid+"&accountid="+accountid, function() {
382 if (amountpayed > <?php echo (float) $remaintopay; ?> || amountpayed == <?php echo (float) $remaintopay; ?> || amountpayed == 0 ) {
383 console.log("Close popup");
384 parent.$('#invoiceid').val("");
385 parent.$.colorbox.close();
386 } else {
387 console.log("Amount is not complete, so we do NOT close popup and reload it.");
388 location.reload();
389 }
390 });
391
392 return true;
393 }
394
395 function fetchPaymentIntentClientSecret(amount, invoiceid) {
396 const bodyContent = JSON.stringify({ amount : amount, invoiceid : invoiceid });
397 <?php
398 $urlpaymentintent = DOL_URL_ROOT.'/stripe/ajax/ajax.php?action=createPaymentIntent&token='.currentToken().'&servicestatus='.urlencode((string) $servicestatus);
399 if (!empty($stripeacc)) {
400 $urlpaymentintent .= '&stripeacc='.$stripeacc;
401 }
402 ?>
403 return fetch('<?php echo $urlpaymentintent; ?>', {
404 method: "POST",
405 headers: {
406 'Content-Type': 'application/json'
407 },
408 body: bodyContent
409 })
410 .then(function(response) {
411 return response.json();
412 })
413 .then(function(data) {
414 return data.client_secret;
415 });
416 }
417
418
419 function capturePaymentIntent(paymentIntentId) {
420 const bodyContent = JSON.stringify({"id": paymentIntentId})
421 <?php
422 $urlpaymentintent = DOL_URL_ROOT.'/stripe/ajax/ajax.php?action=capturePaymentIntent&token='.currentToken().'&servicestatus='.urlencode((string) ($servicestatus));
423 if (!empty($stripeacc)) {
424 $urlpaymentintent .= '&stripeacc='.urlencode($stripeacc);
425 }
426 ?>
427 return fetch('<?php echo $urlpaymentintent; ?>', {
428 method: "POST",
429 headers: {
430 'Content-Type': 'application/json'
431 },
432 body: bodyContent
433 })
434 .then(function(response) {
435 return response.json();
436 })
437 .then(function(data) {
438 return data.client_secret;
439 });
440 }
441
442
443 function ValidateStripeTerminal() {
444 console.log("Launch ValidateStripeTerminal");
445 var invoiceid = <?php echo($invoiceid > 0 ? $invoiceid : 0); ?>;
446 var accountid = $("#selectaccountid").val();
447 var amountpayed = $("#change1").val();
448 var excess = $("#change2").val();
449 if (amountpayed > <?php echo (float) $invoice->getRemainToPay(); ?>) {
450 amountpayed = <?php echo (float) $invoice->getRemainToPay(); ?>;
451 }
452 if (amountpayed == 0) {
453 amountpayed = <?php echo (float) $invoice->getRemainToPay(); ?>;
454 }
455
456 console.log("Pay with terminal ", amountpayed);
457
458 fetchPaymentIntentClientSecret(amountpayed, invoiceid).then(function(client_secret) {
459 <?php if (empty($servicestatus) && getDolGlobalString('STRIPE_TERMINAL_SIMULATED')) { ?>
460 terminal.setSimulatorConfiguration({testCardNumber: <?php echo "'".dol_escape_js(getDolGlobalString('STRIPE_TERMINAL_SIMULATED'))."'" ; ?>});
461 <?php } ?>
462 document.getElementById("card-present-alert").innerHTML = '<div class="warning clearboth"><?php echo $langs->trans('PaymentSendToStripeTerminal'); ?></div>';
463 terminal.collectPaymentMethod(client_secret).then(function(result) {
464 if (result.error) {
465 // Placeholder for handling result.error
466 document.getElementById("card-present-alert").innerHTML = '<div class="error clearboth">'+result.error.message+'</div>';
467 } else {
468 document.getElementById("card-present-alert").innerHTML = '<div class="warning clearboth"><?php echo $langs->trans('PaymentBeingProcessed'); ?></div>';
469 console.log('terminal.collectPaymentMethod', result.paymentIntent);
470 terminal.processPayment(result.paymentIntent).then(function(result) {
471 if (result.error) {
472 document.getElementById("card-present-alert").innerHTML = '<div class="error clearboth">'+result.error.message+'</div>';
473 console.log(result.error)
474 } else if (result.paymentIntent) {
475 paymentIntentId = result.paymentIntent.id;
476 console.log('terminal.processPayment', result.paymentIntent);
477 capturePaymentIntent(paymentIntentId).then(function(client_secret) {
478 if (result.error) {
479 // Placeholder for handling result.error
480 document.getElementById("card-present-alert").innerHTML = '<div class="error clearboth">'+result.error.message+'</div>';
481 console.log("error when capturing paymentIntent", result.error);
482 } else {
483 document.getElementById("card-present-alert").innerHTML = '<div class="warning clearboth"><?php echo $langs->trans('PaymentValidated'); ?></div>';
484 console.log("Capture paymentIntent successful "+paymentIntentId);
485 parent.$("#poslines").load("invoice.php?place=<?php echo $place; ?>&action=valid&token=<?php echo newToken(); ?>&pay=CB&amount="+amountpayed+"&excess="+excess+"&invoiceid="+invoiceid+"&accountid="+accountid, function() {
486 if (amountpayed > <?php echo (float) $remaintopay; ?> || amountpayed == <?php echo (float) $remaintopay; ?> || amountpayed == 0 ) {
487 console.log("Close popup");
488 parent.$.colorbox.close();
489 }
490 else {
491 console.log("Amount is not comple, so we do NOT close popup and reload it.");
492 location.reload();
493 }
494 });
495
496 }
497 });
498 }
499 });
500 }
501 });
502 });
503 }
504
505 function ValidateSumup() {
506 console.log("Launch ValidateSumup");
507 <?php $_SESSION['SMP_CURRENT_PAYMENT'] = "NEW" ?>
508 var invoiceid = <?php echo ($invoiceid > 0 ? $invoiceid : 0); ?>;
509 var amountpayed = $("#change1").val();
510 if (amountpayed > <?php echo (float) $invoice->total_ttc; ?>) {
511 amountpayed = <?php echo (float) $invoice->total_ttc; ?>;
512 }
513 if (amountpayed == 0) {
514 amountpayed = <?php echo (float) $invoice->total_ttc; ?>;
515 }
516 var currencycode = "<?php echo $invoice->multicurrency_code; ?>";
517
518 // Starting sumup app
519 window.open('sumupmerchant://pay/1.0?affiliate-key=<?php echo urlencode(getDolGlobalString('TAKEPOS_SUMUP_AFFILIATE')) ?>&app-id=<?php echo urlencode(getDolGlobalString('TAKEPOS_SUMUP_APPID')) ?>&amount=' + amountpayed + '&currency=' + currencycode + '&title=' + invoiceid + '&callback=<?php echo DOL_MAIN_URL_ROOT ?>/takepos/smpcb.php');
520
521 var loop = window.setInterval(function () {
522 $.ajax({
523 method: 'POST',
524 data: { token: '<?php echo currentToken(); ?>' },
525 url: '<?php echo DOL_URL_ROOT ?>/takepos/smpcb.php?status' }).done(function (data) {
526 console.log(data);
527 if (data === "SUCCESS") {
528 parent.$("#poslines").load("invoice.php?place=<?php echo urlencode($place); ?>&action=valid&token=<?php echo newToken(); ?>&pay=CB&amount=" + amountpayed + "&invoiceid=" + invoiceid, function () {
529 //parent.$("#poslines").scrollTop(parent.$("#poslines")[0].scrollHeight);
530 parent.$.colorbox.close();
531 //parent.setFocusOnSearchField(); // This does not have effect
532 });
533 clearInterval(loop);
534 } else if (data === "FAILED") {
535 parent.$.colorbox.close();
536 clearInterval(loop);
537 }
538 });
539 }, 2500);
540 }
541
542<?php
543if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
544 echo "var line1='".$langs->trans('TotalTTC')."'.substring(0,20);";
545 echo "line1=line1.padEnd(20);";
546 echo "var line2='".price($invoice->total_ttc, 1, '', 1, -1, -1)."'.substring(0,20);";
547 echo "line2=line2.padEnd(20);";
548 if (getDolGlobalString('TAKEPOS_CONNECTOR_TO_WHB_CUSTOMER_DISPLAY')) {
549 echo 'webSocketCustomerDisplay.onOpen(function() {';
550 echo ' webSocketCustomerDisplay.send(line1);';
551 echo ' webSocketCustomerDisplay.send(line2);';
552 echo '});';
553 } else {
554 echo "$.ajax({
555 type: 'GET',
556 data: { text: line1+line2 },
557 url: '".getDolGlobalString('TAKEPOS_PRINT_SERVER')."/display/index.php',
558 });";
559 }
560}
561?>
562</script>
563
564<?php
565$sessioncurrency = $_SESSION["takeposcustomercurrency"] ?? '';
566print '<!-- conf->currency = '.$conf->currency.' - sessioncurrency = '.$sessioncurrency.' -->'."\n";
567$multicurrency = null;
568if (isModEnabled('multicurrency') && $sessioncurrency != "" && $conf->currency != $sessioncurrency) {
569 // Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
570 include_once DOL_DOCUMENT_ROOT . '/multicurrency/class/multicurrency.class.php';
571 $multicurrency = new MultiCurrency($db);
572 $multicurrency->fetch(0, $sessioncurrency);
573}
574?>
575
576<div style="position:relative; padding-top: 20px; left:5%; height:140px; width:90%;">
577 <div class="paymentbordline paymentbordlinetotal center">
578 <span class="takepospay colorwhite"><?php echo $langs->trans('TotalTTC'); ?>: <span id="totaldisplay" class="colorwhite"><?php
579 echo price($invoice->total_ttc, 1, '', 1, -1, -1, $conf->currency);
580 if ($multicurrency !== null) {
581 print ' &nbsp; <span id="linecolht-span-total opacitymedium" style="font-size:0.9em; font-style:italic;">(' . price($invoice->total_ht * $multicurrency->rate->rate) . ' ' . $sessioncurrency . ')</span>';
582 }
583 ?></span></span>
584 </div>
585 <?php if ($remaintopay != $invoice->total_ttc) { ?>
586 <div class="paymentbordline paymentbordlineremain center">
587 <span class="takepospay colorwhite"><?php echo $langs->trans('RemainToPay'); ?>: <span id="remaintopaydisplay" class="colorwhite"><?php
588 echo price($remaintopay, 1, '', 1, -1, -1, $conf->currency);
589 if ($multicurrency !== null) {
590 print ' &nbsp; <span id="linecolht-span-total opacitymedium" style="font-size:0.9em; font-style:italic;">(' . price($remaintopay * $multicurrency->rate->rate) . ' ' . $sessioncurrency . ')</span>';
591 }
592 ?></span></span>
593 </div>
594 <?php } ?>
595 <div class="paymentbordline paymentbordlinereceived center">
596 <span class="takepospay colorwhite"><?php echo $invoice->type == $invoice::TYPE_CREDIT_NOTE ? $langs->trans("Refunded") : $langs->trans("Received"); ?>: <span class="change1 colorred"><?php
597 echo price(0, 1, '', 1, -1, -1, $conf->currency);
598 if ($multicurrency !== null) {
599 print ' &nbsp; <span id="linecolht-span-total opacitymedium" style="font-size:0.9em; font-style:italic;">(' . price(0 * $multicurrency->rate->rate) . ' ' . $sessioncurrency . ')</span>';
600 }
601 ?></span><input type="hidden" id="change1" class="change1" value="0"></span>
602 </div>
603 <div class="paymentbordline paymentbordlinechange center">
604 <span class="takepospay colorwhite"><?php echo $langs->trans("Change"); ?>: <span class="change2 colorwhite"><?php
605 echo price(0, 1, '', 1, -1, -1, $conf->currency);
606 if ($multicurrency !== null) {
607 print ' &nbsp; <span id="linecolht-span-total opacitymedium" style="font-size:0.9em; font-style:italic;">(' . price(0 * $multicurrency->rate->rate) . ' ' . $sessioncurrency . ')</span>';
608 }
609 ?></span><input type="hidden" id="change2" class="change2" value="0"></span>
610 </div>
611 <?php
612 if (getDolGlobalString('TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT')) {
613 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
614 print '<div class="paymentbordline paddingtop paddingbottom center">';
615 $filter = '';
616 $form = new Form($db);
617 print '<span class="takepospay colorwhite">'.$langs->trans("BankAccount").': </span>';
618 $form->select_comptes(0, 'accountid', 0, $filter, 1, '');
619 print ajax_combobox('selectaccountid');
620 print '</div>';
621 }
622 ?>
623</div>
624<div style="position:absolute; left:5%; height:52%; width:90%;">
625<?php
626$action_buttons = array(
627array(
628"function" => "reset()",
629"span" => "style='font-size: 150%;'",
630"text" => "C",
631"class" => "poscolorblue"
632),
633array(
634"function" => "parent.$.colorbox.close();",
635"span" => "id='printtext' style='font-weight: bold; font-size: 18pt;'",
636"text" => "X",
637"class" => "poscolordelete"
638),
639);
640$numpad = getDolGlobalInt('TAKEPOS_NUMPAD');
641if (isModEnabled('stripe') && isset($keyforstripeterminalbank) && getDolGlobalString('STRIPE_CARD_PRESENT')) {
642 print '<span id="card-present-alert">';
643 dol_htmloutput_mesg($langs->trans('ConnectingToStripeTerminal', 'Stripe'), [], 'warning', 1);
644 print '</span>';
645}
646print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '7' : '10').')">'.($numpad == 0 ? '7' : '10').'</button>';
647print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '8' : '20').')">'.($numpad == 0 ? '8' : '20').'</button>';
648print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '9' : '50').')">'.($numpad == 0 ? '9' : '50').'</button>';
649?>
650<?php if (count($arrayOfValidPaymentModes) > 0) {
651 $paycode = $arrayOfValidPaymentModes[0]->code;
652 $payIcon = '';
653 if ($paycode == 'LIQ') {
654 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
655 $payIcon = 'coins';
656 }
657 } elseif ($paycode == 'CB') {
658 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
659 $payIcon = 'credit-card';
660 }
661 } elseif ($paycode == 'CHQ') {
662 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
663 $payIcon = 'money-check';
664 }
665 }
666
667 print '<button type="button" class="calcbutton2" onclick="Validate(\''.dol_escape_js($paycode).'\')">'.(!empty($payIcon) ? '<span class="fa fa-2x fa-'.$payIcon.' iconwithlabel"></span><span class="hideonsmartphone"><br>'.$langs->trans("PaymentTypeShort".$arrayOfValidPaymentModes[0]->code) : $langs->trans("PaymentTypeShort".$arrayOfValidPaymentModes[0]->code)).'</span></button>';
668} else {
669 print '<button type="button" class="calcbutton2">'.$langs->trans("NoPaimementModesDefined").'</button>';
670}
671
672print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '4' : '1').')">'.($numpad == 0 ? '4' : '1').'</button>';
673print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '5' : '2').')">'.($numpad == 0 ? '5' : '2').'</button>';
674print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '6' : '5').')">'.($numpad == 0 ? '6' : '5').'</button>';
675?>
676<?php if (count($arrayOfValidPaymentModes) > 1) {
677 $paycode = $arrayOfValidPaymentModes[1]->code;
678 $payIcon = '';
679 if ($paycode == 'LIQ') {
680 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
681 $payIcon = 'coins';
682 }
683 } elseif ($paycode == 'CB') {
684 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
685 $payIcon = 'credit-card';
686 }
687 } elseif ($paycode == 'CHQ') {
688 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
689 $payIcon = 'money-check';
690 }
691 }
692
693 print '<button type="button" class="calcbutton2" onclick="Validate(\''.dol_escape_js($paycode).'\')">'.(!empty($payIcon) ? '<span class="fa fa-2x fa-'.$payIcon.' iconwithlabel"></span><br> '.$langs->trans("PaymentTypeShort".$arrayOfValidPaymentModes[1]->code) : $langs->trans("PaymentTypeShort".$arrayOfValidPaymentModes[1]->code)).'</button>';
694} else {
695 $button = array_pop($action_buttons);
696 print '<button type="button" class="calcbutton2" onclick="'.$button["function"].'"><span '.$button["span"].'>'.$button["text"].'</span></button>';
697}
698
699print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '1' : '0.10').')">'.($numpad == 0 ? '1' : '0.10').'</button>';
700print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '2' : '0.20').')">'.($numpad == 0 ? '2' : '0.20').'</button>';
701print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '3' : '0.50').')">'.($numpad == 0 ? '3' : '0.50').'</button>';
702?>
703<?php if (count($arrayOfValidPaymentModes) > 2) {
704 $paycode = $arrayOfValidPaymentModes[2]->code;
705 $payIcon = '';
706 if ($paycode == 'LIQ') {
707 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
708 $payIcon = 'coins';
709 }
710 } elseif ($paycode == 'CB') {
711 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
712 $payIcon = 'credit-card';
713 }
714 } elseif ($paycode == 'CHQ') {
715 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
716 $payIcon = 'money-check';
717 }
718 }
719
720 print '<button type="button" class="calcbutton2" onclick="Validate(\''.dol_escape_js($paycode).'\')">'.(!empty($payIcon) ? '<span class="fa fa-2x fa-'.$payIcon.' iconwithlabel"></span><br>'.$langs->trans("PaymentTypeShort".$arrayOfValidPaymentModes[2]->code) : $langs->trans("PaymentTypeShort".$arrayOfValidPaymentModes[2]->code)).'</button>';
721} else {
722 $button = array_pop($action_buttons);
723 print '<button type="button" class="calcbutton2" onclick="'.$button["function"].'"><span '.$button["span"].'>'.$button["text"].'</span></button>';
724}
725
726print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '0' : '0.01').')">'.($numpad == 0 ? '0' : '0.01').'</button>';
727print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '\'000\'' : '0.02').')">'.($numpad == 0 ? '000' : '0.02').'</button>';
728print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '\'.\'' : '0.05').')">'.($numpad == 0 ? '.' : '0.05').'</button>';
729
730$i = 3;
731while ($i < count($arrayOfValidPaymentModes)) {
732 $paycode = $arrayOfValidPaymentModes[$i]->code;
733 $payIcon = '';
734 if ($paycode == 'LIQ') {
735 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
736 $payIcon = 'coins';
737 }
738 } elseif ($paycode == 'CB') {
739 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
740 $payIcon = 'credit-card';
741 }
742 } elseif ($paycode == 'CHQ') {
743 if (!isset($conf->global->TAKEPOS_NUMPAD_USE_PAYMENT_ICON) || getDolGlobalString('TAKEPOS_NUMPAD_USE_PAYMENT_ICON')) {
744 $payIcon = 'money-check';
745 }
746 }
747
748 print '<button type="button" class="calcbutton2" onclick="Validate(\''.dol_escape_js($paycode).'\')">'.(!empty($payIcon) ? '<span class="fa fa-2x fa-'.$payIcon.' iconwithlabel"></span><br>'.$langs->trans("PaymentTypeShort".$arrayOfValidPaymentModes[$i]->code) : $langs->trans("PaymentTypeShort".$arrayOfValidPaymentModes[$i]->code)).'</button>';
749 $i += 1;
750}
751
752if (isModEnabled('stripe') && isset($keyforstripeterminalbank) && getDolGlobalString('STRIPE_CARD_PRESENT')) {
753 $keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$_SESSION["takeposterminal"];
754 print '<span id="StripeTerminal"></span>';
755 if (getDolGlobalString((string) $keyforstripeterminalbank)) {
756 // Nothing
757 } else {
758 $langs->loadLangs(array("errors", "admin"));
759 //print '<button type="button" class="calcbutton2 disabled" title="'.$langs->trans("SetupNotComplete").'">TerminalOff</button>';
760 }
761}
762
763$keyforsumupbank = "CASHDESK_ID_BANKACCOUNT_SUMUP".$_SESSION["takeposterminal"];
764if (getDolGlobalInt("TAKEPOS_ENABLE_SUMUP")) {
765 if (getDolGlobalString($keyforsumupbank)) {
766 print '<button type="button" class="calcbutton2" onclick="ValidateSumup();">Sumup</button>';
767 } else {
768 $langs->loadLangs(array("errors", "admin"));
769 print '<button type="button" class="calcbutton2 disabled" title="'.$langs->trans("SetupNotComplete").'">Sumup</button>';
770 }
771}
772
773$parameters = array('action_buttons' => $action_buttons);
774$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $invoice, $action); // Note that $action and $invoice may have been modified by hook
775if ($reshook < 0) {
776 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
777} elseif ($reshook == 0) {
778 $action_buttons = array_merge($action_buttons, $hookmanager->resArray);
779} elseif ($reshook > 0) {
780 $action_buttons = $hookmanager->resArray;
781}
782
783$class = ($i == 3) ? "calcbutton3" : "calcbutton2";
784foreach ($action_buttons as $button) {
785 $newclass = $class.($button["class"] ? " ".$button["class"] : "");
786 print '<button type="button" class="'.$newclass.'" onclick="'.$button["function"].'"><span '.$button["span"].'>'.$button["text"].'</span></button>';
787}
788
789if (getDolGlobalString('TAKEPOS_DELAYED_PAYMENT')) {
790 print '<button type="button" class="calcbutton2" onclick="Validate(\'delayed\')">'.$langs->trans("Reported").'</button>';
791}
792?>
793
794<?php
795// Add code from hooks
796$parameters = array();
797$hookmanager->executeHooks('completePayment', $parameters, $invoice);
798print $hookmanager->resPrint;
799?>
800
801</div>
802
803</body>
804</html>
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition propal.php:280
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='', $placeholder='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:477
isALNERunningVersion($blockedlogusagealreadychecked=0, $blockedlogmoduleonalreadychecked=0)
Return if the application is executed with the LNE requirements on.
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
Class Currency.
Stripe class @TODO No reason to extend CommonObject.
Class toolbox to validate values.
global $mysoc
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
currentToken()
Return the value of token currently saved into session with name 'token'.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into JavaScript code.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
multi select button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
a disabled
dol_htmloutput_mesg($mesgstring='', $mesgarray=array(), $style='ok', $keepembedded=0)
Print formatted messages to output (Used to show messages on html output).
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs=array(), $arrayofcss=array(), $disableforlogin=0, $disablenofollow=0, $disablenoindex=0)
Output html header of a page.
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as p p num_paiement as f pf amount as amount
Definition receipt.php:494
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.