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