dolibarr 23.0.3
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", "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 = getDolCurrency();
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, ...
360}
361
362// Initialize $validpaymentmethod
363// The list can be complete by the hook 'doValidatePayment' executed inside getValidOnlinePaymentMethods()
364$validpaymentmethod = getValidOnlinePaymentMethods($paymentmethod);
365
366// Check security token
367$tmpsource = $source;
368if ($tmpsource == 'membersubscription') {
369 $tmpsource = 'member';
370}
371$valid = true;
372if (getDolGlobalString('PAYMENT_SECURITY_TOKEN')) {
373 $tokenisok = false;
374 if (getDolGlobalString('PAYMENT_SECURITY_TOKEN_UNIQUE')) {
375 if ($tmpsource && $REF) {
376 // Use the source in the hash to avoid duplicates if the references are identical
377 $tokenisok = dol_verifyHash(getDolGlobalString('PAYMENT_SECURITY_TOKEN') . $tmpsource.$REF, $SECUREKEY, '2');
378 // Do a second test for retro-compatibility (token may have been hashed with membersubscription in external module)
379 if ($tmpsource != $source) {
380 $tokenisok = dol_verifyHash(getDolGlobalString('PAYMENT_SECURITY_TOKEN') . $source.$REF, $SECUREKEY, '2');
381 }
382 } else {
383 $tokenisok = dol_verifyHash(getDolGlobalString('PAYMENT_SECURITY_TOKEN'), $SECUREKEY, '2');
384 }
385 } else {
386 $tokenisok = (getDolGlobalString('PAYMENT_SECURITY_TOKEN') == $SECUREKEY);
387 }
388
389 if (! $tokenisok) {
390 if (!getDolGlobalString('PAYMENT_SECURITY_ACCEPT_ANY_TOKEN')) {
391 $valid = false; // PAYMENT_SECURITY_ACCEPT_ANY_TOKEN is for backward compatibility
392 } else {
393 dol_syslog("Warning: PAYMENT_SECURITY_ACCEPT_ANY_TOKEN is on", LOG_WARNING);
394 dol_syslog("Warning: PAYMENT_SECURITY_ACCEPT_ANY_TOKEN is on", LOG_WARNING, 0, '_payment');
395 }
396 }
397
398 if (!$valid) {
399 print '<div class="error">Bad value for key.</div>';
400 //print 'SECUREKEY='.$SECUREKEY.' valid='.$valid;
401 exit;
402 }
403}
404
405if (!empty($paymentmethod) && empty($validpaymentmethod[$paymentmethod])) {
406 print 'Payment module for payment method '.$paymentmethod.' is not active';
407 exit;
408}
409if (empty($validpaymentmethod)) {
410 print 'No active payment module (Paypal, Stripe, Paybox, ...)';
411 exit;
412}
413
414// Common variables
415$creditor = $mysoc->name;
416$paramcreditor = 'ONLINE_PAYMENT_CREDITOR';
417$paramcreditorlong = 'ONLINE_PAYMENT_CREDITOR_'.$suffix;
418if (getDolGlobalString($paramcreditorlong)) {
419 $creditor = getDolGlobalString($paramcreditorlong); // use label long of the seller to show
420} elseif (getDolGlobalString($paramcreditor)) {
421 $creditor = getDolGlobalString($paramcreditor); // use label short of the seller to show
422}
423
424$mesg = '';
425
426
427/*
428 * Actions
429 */
430
431// First log into the dolibarr_payment.log file
432dol_syslog("--- newpayment.php action=".$action." paymentmethod=".$paymentmethod.' amount='.$amount.' newamount='.GETPOST("newamount", 'alpha'), LOG_DEBUG, 0, '_payment');
433
434dol_syslog("fulltag=".GETPOST("fulltag", 'alpha')." ws=".$ws." urlok=".$urlok, LOG_DEBUG, 0, '_payment');
435
436// Action dopayment is called after clicking/choosing the payment mode
437if ($action == 'dopayment') { // Test on permission not required here (anonymous action protected by mitigation of /public/... urls)
438 if ($paymentmethod == 'paypal') {
439 $PAYPAL_API_PRICE = price2num(GETPOST("newamount", 'alpha'), 'MT');
440 $PAYPAL_PAYMENT_TYPE = 'Sale';
441
442 // Vars that are used as global var later in print_paypal_redirect()
443 $origfulltag = GETPOST("fulltag", 'alpha');
444 $shipToName = GETPOST("shipToName", 'alpha');
445 $shipToStreet = GETPOST("shipToStreet", 'alpha');
446 $shipToCity = GETPOST("shipToCity", 'alpha');
447 $shipToState = GETPOST("shipToState", 'alpha');
448 $shipToCountryCode = GETPOST("shipToCountryCode", 'alpha');
449 $shipToZip = GETPOST("shipToZip", 'alpha');
450 $shipToStreet2 = GETPOST("shipToStreet2", 'alpha');
451 $phoneNum = GETPOST("phoneNum", 'alpha');
452 $email = GETPOST("email", 'alpha');
453 $desc = GETPOST("desc", 'alpha');
454 $thirdparty_id = GETPOSTINT('thirdparty_id');
455
456 // Special case for Paypal-Indonesia
457 if ($shipToCountryCode == 'ID' && !preg_match('/\-/', $shipToState)) {
458 $shipToState = 'ID-'.$shipToState;
459 }
460
461 if (empty($PAYPAL_API_PRICE) || !is_numeric($PAYPAL_API_PRICE)) {
462 $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount"));
463 $action = '';
464 // } elseif (empty($EMAIL)) { $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("YourEMail"));
465 // } elseif (! isValidEmail($EMAIL)) { $mesg=$langs->trans("ErrorBadEMail",$EMAIL);
466 } elseif (!$origfulltag) {
467 $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("PaymentCode"));
468 $action = '';
469 }
470
471 if (empty($mesg)) {
472 dol_syslog("newpayment.php call paypal api and do redirect", LOG_DEBUG);
473 dol_syslog("newpayment.php call paypal api and do redirect", LOG_DEBUG, 0, '_payment');
474
475 // Other
476 $PAYPAL_API_DEVISE = "USD";
477 if (!empty($currency)) {
478 $PAYPAL_API_DEVISE = $currency;
479 }
480
481 // Show var initialized by inclusion of paypal lib at start of this file
482 dol_syslog("Submit Paypal form", LOG_DEBUG);
483 dol_syslog("Submit Paypal form", LOG_DEBUG, 0, '_payment');
484
485 dol_syslog("PAYPAL_API_USER: $PAYPAL_API_USER", LOG_DEBUG, 0, '_payment');
486 dol_syslog("PAYPAL_API_PASSWORD: ".preg_replace('/./', '*', $PAYPAL_API_PASSWORD), LOG_DEBUG, 0, '_payment'); // No password into log files
487 dol_syslog("PAYPAL_API_SIGNATURE: $PAYPAL_API_SIGNATURE", LOG_DEBUG, 0, '_payment');
488 dol_syslog("PAYPAL_API_SANDBOX: $PAYPAL_API_SANDBOX", LOG_DEBUG, 0, '_payment');
489 dol_syslog("PAYPAL_API_OK: $PAYPAL_API_OK", LOG_DEBUG, 0, '_payment');
490 dol_syslog("PAYPAL_API_KO: $PAYPAL_API_KO", LOG_DEBUG, 0, '_payment');
491 dol_syslog("PAYPAL_API_PRICE: $PAYPAL_API_PRICE", LOG_DEBUG, 0, '_payment');
492 dol_syslog("PAYPAL_API_DEVISE: $PAYPAL_API_DEVISE", LOG_DEBUG, 0, '_payment');
493 // All those fields may be empty when making a payment for a free amount for example
494 dol_syslog("shipToName: $shipToName", LOG_DEBUG, 0, '_payment');
495 dol_syslog("shipToStreet: $shipToStreet", LOG_DEBUG, 0, '_payment');
496 dol_syslog("shipToCity: $shipToCity", LOG_DEBUG, 0, '_payment');
497 dol_syslog("shipToState: $shipToState", LOG_DEBUG, 0, '_payment');
498 dol_syslog("shipToCountryCode: $shipToCountryCode", LOG_DEBUG, 0, '_payment');
499 dol_syslog("shipToZip: $shipToZip", LOG_DEBUG, 0, '_payment');
500 dol_syslog("shipToStreet2: $shipToStreet2", LOG_DEBUG, 0, '_payment');
501 dol_syslog("phoneNum: $phoneNum", LOG_DEBUG, 0, '_payment');
502 dol_syslog("email: $email", LOG_DEBUG, 0, '_payment');
503 dol_syslog("desc: $desc", LOG_DEBUG, 0, '_payment');
504
505 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
506
507 // A redirect is added if API call successful
508 $mesg = print_paypal_redirect((float) $PAYPAL_API_PRICE, $PAYPAL_API_DEVISE, $PAYPAL_PAYMENT_TYPE, $PAYPAL_API_OK, $PAYPAL_API_KO, $FULLTAG);
509
510 // If we are here, it means the Paypal redirect was not done, so we show error message
511 $action = '';
512 }
513 }
514
515 if ($paymentmethod == 'paybox') {
516 $PRICE = price2num(GETPOST("newamount"), 'MT');
517 $email = getDolGlobalString('ONLINE_PAYMENT_SENDEMAIL');
518 $thirdparty_id = GETPOSTINT('thirdparty_id');
519
520 $origfulltag = GETPOST("fulltag", 'alpha');
521
522 // Securekey into back url useless for back url and we need an url lower than 150.
523 $urlok = preg_replace('/securekey=[^&]+&?/', '', $urlok);
524 $urlko = preg_replace('/securekey=[^&]+&?/', '', $urlko);
525
526 if (empty($PRICE) || !is_numeric($PRICE)) {
527 $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount"));
528 } elseif (empty($email)) {
529 $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ONLINE_PAYMENT_SENDEMAIL"));
530 } elseif (!isValidEmail($email)) {
531 $mesg = $langs->trans("ErrorBadEMail", $email);
532 } elseif (!$origfulltag) {
533 $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("PaymentCode"));
534 } elseif (dol_strlen($urlok) > 150) {
535 $mesg = 'Error urlok too long '.$urlok.' (Paybox requires 150, found '.strlen($urlok).')';
536 } elseif (dol_strlen($urlko) > 150) {
537 $mesg = 'Error urlko too long '.$urlko.' (Paybox requires 150, found '.strlen($urlok).')';
538 }
539
540 if (empty($mesg)) {
541 dol_syslog("newpayment.php call paybox api and do redirect", LOG_DEBUG, 0, '_payment');
542
543 include_once DOL_DOCUMENT_ROOT.'/paybox/lib/paybox.lib.php';
544 print_paybox_redirect((float) $PRICE, getDolCurrency(), $email, $urlok, $urlko, $FULLTAG);
545
546 session_destroy();
547 exit;
548 }
549 }
550
551 if ($paymentmethod == 'stripe') {
552 if (GETPOST('newamount', 'alpha')) {
553 $amount = price2num(GETPOST('newamount', 'alpha'), 'MT');
554 } else {
555 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount")), null, 'errors');
556 $action = '';
557 }
558 }
559}
560
561
562// Called when choosing Stripe mode.
563// When using the old Charge API architecture, this code is called after clicking the 'dopayment' with the Charge API architecture.
564// 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.
565if ($action == 'charge' && isModEnabled('stripe')) { // Test on permission not required here (anonymous action protected by mitigation of /public/... urls)
566 $amountstripe = (float) $amount;
567
568 // Correct the amount according to unit of currency
569 // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
570 $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
571 if (!in_array($currency, $arrayzerounitcurrency)) {
572 $amountstripe *= 100;
573 }
574
575 dol_syslog("newpayment.php execute action = ".$action." STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION=".getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION'), LOG_DEBUG, 0, '_payment');
576 dol_syslog("GET=".var_export($_GET, true), LOG_DEBUG, 0, '_payment');
577 dol_syslog("POST=".var_export($_POST, true), LOG_DEBUG, 0, '_payment');
578
579 $stripeToken = GETPOST("stripeToken", 'alpha');
580 $email = GETPOST("email", 'alpha');
581 $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
582 $dol_type = (GETPOST('s', 'alpha') ? GETPOST('s', 'alpha') : GETPOST('source', 'alpha'));
583 $dol_id = GETPOSTINT('dol_id');
584 $vatnumber = GETPOST('vatnumber', 'alpha');
585 $savesource = GETPOSTISSET('savesource') ? GETPOSTINT('savesource') : 1;
586
587 dol_syslog("POST stripeToken = ".$stripeToken, LOG_DEBUG, 0, '_payment');
588 dol_syslog("POST email = ".$email, LOG_DEBUG, 0, '_payment');
589 dol_syslog("POST thirdparty_id = ".$thirdparty_id, LOG_DEBUG, 0, '_payment');
590 dol_syslog("POST vatnumber = ".$vatnumber, LOG_DEBUG, 0, '_payment');
591
592 $error = 0;
593 $errormessage = '';
594 $stripeacc = null;
595
596 // When using the old Charge API architecture
597 if (!getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
598 try {
599 $metadata = array(
600 'dol_version' => DOL_VERSION,
601 'dol_entity' => $conf->entity,
602 'dol_company' => $mysoc->name, // Useful when using multicompany
603 'dol_tax_num' => $vatnumber,
604 'ipaddress' => getUserRemoteIP()
605 );
606
607 if (!empty($thirdparty_id)) {
608 $metadata["dol_thirdparty_id"] = $thirdparty_id;
609 }
610
611 if ($thirdparty_id > 0) {
612 dol_syslog("Search existing Stripe customer profile for thirdparty_id=".$thirdparty_id, LOG_DEBUG, 0, '_payment');
613
614 $service = 'StripeTest';
615 $servicestatus = 0;
616 if (getDolGlobalString('STRIPE_LIVE')/* && !GETPOSTINT('forcesandbox') */) {
617 $service = 'StripeLive';
618 $servicestatus = 1;
619 }
620
621 $thirdparty = new Societe($db);
622 $thirdparty->fetch($thirdparty_id);
623
624 // Create Stripe customer
625 include_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
626 $stripe = new Stripe($db);
627 $stripeacc = $stripe->getStripeAccount($service);
628 $customer = $stripe->customerStripe($thirdparty, $stripeacc, $servicestatus, 1);
629 if (empty($customer)) {
630 $error++;
631 dol_syslog('Failed to get/create stripe customer for thirdparty id = '.$thirdparty_id.' and servicestatus = '.$servicestatus.': '.$stripe->error, LOG_ERR, 0, '_payment');
632 setEventMessages('Failed to get/create stripe customer for thirdparty id = '.$thirdparty_id.' and servicestatus = '.$servicestatus.': '.$stripe->error, null, 'errors');
633 $action = '';
634 }
635
636 // Create Stripe card from Token
637 if (!$error) {
638 if ($savesource) {
639 $card = $customer->sources->create(array("source" => $stripeToken, "metadata" => $metadata));
640 } else {
641 $card = $stripeToken;
642 }
643
644 if (empty($card)) {
645 $error++;
646 dol_syslog('Failed to create card record', LOG_WARNING, 0, '_payment');
647 setEventMessages('Failed to create card record', null, 'errors');
648 $action = '';
649 } else {
650 if (!empty($FULLTAG)) {
651 $metadata["FULLTAG"] = $FULLTAG;
652 }
653 if (!empty($dol_id)) {
654 $metadata["dol_id"] = $dol_id;
655 }
656 if (!empty($dol_type)) {
657 $metadata["dol_type"] = $dol_type;
658 }
659
660 dol_syslog("Create charge on card ".$card->id, LOG_DEBUG, 0, '_payment');
661 $charge = \Stripe\Charge::create(array(
662 'amount' => price2num($amountstripe, 'MU'),
663 'currency' => $currency,
664 'capture' => true, // Charge immediately
665 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref,
666 'metadata' => $metadata,
667 'customer' => $customer->id,
668 'source' => $card,
669 'statement_descriptor_suffix' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
670 ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc"));
671 // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...)
672 if (empty($charge)) {
673 $error++;
674 dol_syslog('Failed to charge card', LOG_WARNING, 0, '_payment');
675 setEventMessages('Failed to charge card', null, 'errors');
676 $action = '';
677 }
678 }
679 }
680 } else {
681 $vatcleaned = $vatnumber ? $vatnumber : null;
682
683 /*$taxinfo = array('type'=>'vat');
684 if ($vatcleaned)
685 {
686 $taxinfo["tax_id"] = $vatcleaned;
687 }
688 // We force data to "null" if not defined as expected by Stripe
689 if (empty($vatcleaned)) $taxinfo=null;
690 */
691
692 dol_syslog("Create anonymous customer card profile", LOG_DEBUG, 0, '_payment');
693
694 $customer = \Stripe\Customer::create(array(
695 'email' => $email,
696 'description' => ($email ? 'Anonymous customer for '.$email : 'Anonymous customer'),
697 'metadata' => $metadata,
698 '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 ?)
699 ));
700 // Return $customer = array('id'=>'cus_XXXX', ...)
701
702 // Create the VAT record in Stripe
703 /* We don't know country of customer, so we can't create tax
704 if (getDolGlobalString('STRIPE_SAVE_TAX_IDS')) { // We setup to save Tax info on Stripe side. Warning: This may result in error when saving customer
705 if (!empty($vatcleaned))
706 {
707 $isineec=isInEEC($object);
708 if ($object->country_code && $isineec)
709 {
710 //$taxids = $customer->allTaxIds($customer->id);
711 $customer->createTaxId($customer->id, array('type'=>'eu_vat', 'value'=>$vatcleaned));
712 }
713 }
714 }*/
715
716 if (!empty($FULLTAG)) {
717 $metadata["FULLTAG"] = $FULLTAG;
718 }
719 if (!empty($dol_id)) {
720 $metadata["dol_id"] = $dol_id;
721 }
722 if (!empty($dol_type)) {
723 $metadata["dol_type"] = $dol_type;
724 }
725
726 // The customer was just created with a source, so we can make a charge
727 // with no card defined, the source just used for customer creation will be used.
728 dol_syslog("Create charge", LOG_DEBUG, 0, '_payment');
729 $charge = \Stripe\Charge::create(array(
730 'customer' => $customer->id,
731 'amount' => price2num($amountstripe, 'MU'),
732 'currency' => $currency,
733 'capture' => true, // Charge immediately
734 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref,
735 'metadata' => $metadata,
736 'statement_descriptor' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
737 ), array("idempotency_key" => (string) $FULLTAG, "stripe_account" => (string) $stripeacc));
738 // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...)
739 if (empty($charge)) {
740 $error++;
741 dol_syslog('Failed to charge card', LOG_WARNING, 0, '_payment');
742 setEventMessages('Failed to charge card', null, 'errors');
743 $action = '';
744 }
745 }
746 } catch (\Stripe\Exception\CardException $e) {
747 // Since it's a decline, \Stripe\Exception\Card will be caught
748 $body = $e->getJsonBody();
749 $err = $body['error'];
750
751 print('Status is:'.$e->getHttpStatus()."\n");
752 print('Type is:'.$err['type']."\n");
753 print('Code is:'.$err['code']."\n");
754 // param is '' in this case
755 print('Param is:'.$err['param']."\n");
756 print('Message is:'.$err['message']."\n");
757
758 $error++;
759 $errormessage = "ErrorCard ".$e->getMessage()." err=".var_export($err, true);
760 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
761 setEventMessages($e->getMessage(), null, 'errors');
762 $action = '';
763 } catch (\Stripe\Exception\RateLimitException $e) {
764 // Too many requests made to the API too quickly
765 $error++;
766 $errormessage = "ErrorRateLimit ".$e->getMessage();
767 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
768 setEventMessages($e->getMessage(), null, 'errors');
769 $action = '';
770 } catch (\Stripe\Exception\InvalidRequestException $e) {
771 // Invalid parameters were supplied to Stripe's API
772 $error++;
773 $errormessage = "ErrorInvalidRequest ".$e->getMessage();
774 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
775 setEventMessages($e->getMessage(), null, 'errors');
776 $action = '';
777 } catch (\Stripe\Exception\AuthenticationException $e) {
778 // Authentication with Stripe's API failed
779 // (maybe you changed API keys recently)
780 $error++;
781 $errormessage = "ErrorAuthentication ".$e->getMessage();
782 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
783 setEventMessages($e->getMessage(), null, 'errors');
784 $action = '';
785 } catch (\Stripe\Exception\ApiConnectionException $e) {
786 // Network communication with Stripe failed
787 $error++;
788 $errormessage = "ErrorApiConnection ".$e->getMessage();
789 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
790 setEventMessages($e->getMessage(), null, 'errors');
791 $action = '';
792 } catch (\Stripe\Exception\ExceptionInterface $e) {
793 // Display a very generic error to the user, and maybe send
794 // yourself an email
795 $error++;
796 $errormessage = "ErrorBase ".$e->getMessage();
797 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
798 setEventMessages($e->getMessage(), null, 'errors');
799 $action = '';
800 } catch (Exception $e) {
801 // Something else happened, completely unrelated to Stripe
802 $error++;
803 $errormessage = "ErrorException ".$e->getMessage();
804 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
805 setEventMessages($e->getMessage(), null, 'errors');
806 $action = '';
807 }
808
809 if ($error) {
810 $randomseckey = getRandomPassword(true, null, 20); // TODO Generate a key including fulltag to avoid forging URL.
811 $_SESSION['paymentkosessioncode'] = $randomseckey; // key between newpayment.php to paymentko.php
812
813 $urlko .= '&paymentkosessioncode='.urlencode($randomseckey);
814 } else {
815 $randomseckey = getRandomPassword(true, null, 20); // TODO Generate a key including fulltag to avoid forging URL.
816 $_SESSION['paymentoksessioncode'] = $randomseckey; // key between newpayment.php to paymentok.php
817
818 $urlok .= '&paymentoksessioncode='.urlencode($randomseckey);
819 }
820 }
821
822 // When using the PaymentIntent API architecture (mode set on by default into conf.class.php)
823 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
824 $service = 'StripeTest';
825 $servicestatus = 0;
826 if (getDolGlobalString('STRIPE_LIVE')/* && !GETPOSTINT('forcesandbox') */) {
827 $service = 'StripeLive';
828 $servicestatus = 1;
829 }
830 include_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
831 $stripe = new Stripe($db);
832 $stripeacc = $stripe->getStripeAccount($service);
833
834 // We go here if getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') is set.
835 // In such a case, payment is always ok when we call the "charge" action.
836 $paymentintent_id = GETPOST("paymentintent_id", "alpha");
837
838 // Force to use the correct API key
839 global $stripearrayofkeysbyenv;
840 \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']);
841
842 try {
843 if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
844 $paymentintent = \Stripe\PaymentIntent::retrieve($paymentintent_id);
845 } else {
846 $paymentintent = \Stripe\PaymentIntent::retrieve($paymentintent_id, array("stripe_account" => $stripeacc));
847 }
848 } catch (Exception $e) {
849 $error++;
850 $errormessage = "CantRetrievePaymentIntent ".$e->getMessage();
851 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
852 setEventMessages($e->getMessage(), null, 'errors');
853 $action = '';
854 }
855
856 // Security: a succeeded PaymentIntent must not be reusable to record a payment on more than one Dolibarr object.
857 // Without this check, a PaymentIntent id obtained for one invoice/order/... could be resubmitted here with a
858 // different fulltag/ref to fraudulently record (and validate) a payment on a different object that was never
859 // really paid for, since Dolibarr never re-checks that a "succeeded" PaymentIntent is bound to a specific target.
860 $paymentintentalreadyused = 0;
861 if (!$error && is_object($paymentintent) && $paymentintent->status == 'succeeded') {
862 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."paiement";
863 $sql .= " WHERE ext_payment_id = '".$db->escape($paymentintent_id)."'";
864 $sql .= " OR ext_payment_id LIKE '".$db->escape($paymentintent_id).":%'";
865 $resql = $db->query($sql);
866 if ($resql) {
867 if ($db->num_rows($resql) > 0) {
868 $paymentintentalreadyused = 1;
869 }
870 $db->free($resql);
871 }
872 }
873
874 if ($paymentintent->status != 'succeeded' || $paymentintentalreadyused) {
875 $error++;
876 if ($paymentintentalreadyused) {
877 $errormessage = "PaymentIntent ".$paymentintent_id." was already used to record a payment, it cannot be reused for another object";
878 } else {
879 $errormessage = "StatusOfRetrievedIntent is not succeeded: ".$paymentintent->status;
880 }
881 dol_syslog($errormessage, LOG_WARNING, 0, '_payment');
882 setEventMessages($errormessage, null, 'errors');
883 $action = '';
884
885 $randomseckey = getRandomPassword(true, null, 20); // TODO Generate a key including fulltag to avoid forging URL.
886 $_SESSION['paymentkosessioncode'] = $randomseckey; // key between newpayment.php to paymentko.php
887
888 $urlko .= '&paymentkosessioncode='.urlencode($randomseckey);
889 } else {
890 // We can also record the payment mode into llx_societe_rib with stripe $paymentintent->payment_method
891 // 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.
892 // dol_syslog("Create payment_method for ".$paymentintent->payment_method, LOG_DEBUG, 0, '_payment');
893
894 // Get here amount and currency used for payment and force value into $amount and $currency so the real amount is saved into session instead
895 // of the amount and currency retrieved from the POST.
896 $amount = $paymentintent->amount;
897 $currency = '';
898
899 if (!empty($paymentintent->currency)) {
900 $currency = strtoupper($paymentintent->currency);
901
902 // Correct the amount according to unit of currency
903 // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
904 $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
905 if (!in_array($currency, $arrayzerounitcurrency)) {
906 $amount /= 100;
907 }
908 }
909
910 dol_syslog("StatusOfRetrievedIntent is succeeded for amount = ".$amount." currency = ".$currency, LOG_DEBUG, 0, '_payment');
911
912 $randomseckey = getRandomPassword(true, null, 20); // TODO Generate a key including fulltag to avoid forging URL.
913 $_SESSION['paymentoksessioncode'] = $randomseckey; // key between newpayment.php to paymentok.php
914
915 $urlok .= '&paymentoksessioncode='.urlencode($randomseckey);
916 }
917 }
918
919
920 $remoteip = getUserRemoteIP();
921
922 $_SESSION["onlinetoken"] = $stripeToken;
923 $_SESSION["FinalPaymentAmt"] = $amount; // amount really paid (coming from Stripe). Will be used for check in paymentok.php.
924 $_SESSION["currencyCodeType"] = $currency; // currency really used for payment (coming from Stripe). Will be used for check in paymentok.php.
925 $_SESSION["paymentType"] = '';
926 $_SESSION['ipaddress'] = ($remoteip ? $remoteip : 'unknown'); // Payer ip
927 $_SESSION['TRANSACTIONID'] = (is_object($charge) ? $charge->id : (is_object($paymentintent) ? $paymentintent->id : ''));
928 $_SESSION['errormessage'] = $errormessage;
929 if (!getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
930 $_SESSION['payerID'] = is_object($customer) ? $customer->id : '';
931 } else {
932 $_SESSION['payerID'] = '';
933 }
934
935 dol_syslog("Action charge stripe STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION=".getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')." ip=".$remoteip, LOG_DEBUG, 0, '_payment');
936 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');
937 dol_syslog("_SERVER[SERVER_NAME] = ".(empty($_SERVER["SERVER_NAME"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_NAME"])), LOG_DEBUG, 0, '_payment');
938 dol_syslog("_SERVER[SERVER_ADDR] = ".(empty($_SERVER["SERVER_ADDR"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_ADDR"])), LOG_DEBUG, 0, '_payment');
939 dol_syslog("session_id=".session_id(), LOG_DEBUG, 0, '_payment');
940 dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." paymentoksessioncode=".$_SESSION["paymentoksessioncode"]." paymentkosessioncode=".($_SESSION["paymentkosessioncode"] ?? ''), LOG_DEBUG, 0, '_payment');
941 dol_syslog("FinalPaymentAmt=".$_SESSION["FinalPaymentAmt"]." currencyCodeType=".$_SESSION["currencyCodeType"]." payerID=".$_SESSION['payerID']." TRANSACTIONID=".$_SESSION['TRANSACTIONID'], LOG_DEBUG, 0, '_payment');
942 dol_syslog("FULLTAG=".$FULLTAG, LOG_DEBUG, 0, '_payment');
943 dol_syslog("error=".$error." errormessage=".$errormessage, LOG_DEBUG, 0, '_payment');
944 dol_syslog("Now call the redirect to paymentok or paymentko, URL = ".($error ? $urlko : $urlok), LOG_DEBUG, 0, '_payment');
945
946 if ($error) {
947 header("Location: ".$urlko);
948 exit;
949 } else {
950 header("Location: ".$urlok);
951 exit;
952 }
953}
954
955// This hook is used to push to $validpaymentmethod by external payment modules (ie Payzen, ...)
956$parameters = array(
957 'paymentmethod' => $paymentmethod,
958 'validpaymentmethod' => &$validpaymentmethod
959);
960$reshook = $hookmanager->executeHooks('doPayment', $parameters, $object, $action);
961if ($reshook < 0) {
962 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
963} elseif ($reshook > 0) {
964 print $hookmanager->resPrint;
965}
966
967
968
969/*
970 * View
971 */
972
973$form = new Form($db);
974
975$head = '';
976if (getDolGlobalString('ONLINE_PAYMENT_CSS_URL')) {
977 $head = '<link rel="stylesheet" type="text/css" href="' . getDolGlobalString('ONLINE_PAYMENT_CSS_URL').'?lang='.(!empty($getpostlang) ? $getpostlang : $langs->defaultlang).'">'."\n";
978}
979
980$conf->dol_hide_topmenu = 1;
981$conf->dol_hide_leftmenu = 1;
982
983$replacemainarea = (empty($conf->dol_hide_leftmenu) ? '<div>' : '').'<div>';
984llxHeader($head, $langs->trans("PaymentForm"), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea);
985
986dol_syslog("newpayment.php show page source=".$source." paymentmethod=".$paymentmethod.' amount='.$amount.' newamount='.GETPOST("newamount", 'alpha')." ref=".$ref, LOG_DEBUG, 0, '_payment');
987dol_syslog("_SERVER[HTTP_X_FORWARDED_HOST] = ".(empty($_SERVER["HTTP_X_FORWARDED_HOST"]) ? '' : dol_escape_htmltag($_SERVER["HTTP_X_FORWARDED_HOST"])), LOG_DEBUG, 0, '_payment');
988dol_syslog("_SERVER[SERVER_NAME] = ".(empty($_SERVER["SERVER_NAME"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_NAME"])), LOG_DEBUG, 0, '_payment');
989dol_syslog("_SERVER[SERVER_ADDR] = ".(empty($_SERVER["SERVER_ADDR"]) ? '' : dol_escape_htmltag($_SERVER["SERVER_ADDR"])), LOG_DEBUG, 0, '_payment');
990dol_syslog("session_id=".session_id(), LOG_DEBUG, 0, '_payment');
991
992// Check link validity
993if ($source && in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', 'donation_ref', ''))) {
994 $langs->load("errors");
995 dol_print_error_email('BADREFINPAYMENTFORM', $langs->trans("ErrorBadLinkSourceSetButBadValueForRef", $source, $ref));
996 // End of page
997 llxFooter();
998 $db->close();
999 exit;
1000}
1001
1002
1003// Show sandbox warning
1004if ((empty($paymentmethod) || $paymentmethod == 'paypal') && isModEnabled('paypal') && (getDolGlobalString('PAYPAL_API_SANDBOX')/* || GETPOSTINT('forcesandbox')*/)) { // We can force sand box with param 'forcesandbox'
1005 dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Paypal'), array(), 'warning');
1006}
1007if ((empty($paymentmethod) || $paymentmethod == 'stripe') && isModEnabled('stripe') && (!getDolGlobalString('STRIPE_LIVE')/* || GETPOSTINT('forcesandbox')*/)) {
1008 dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), array(), 'warning');
1009}
1010
1011
1012print '<span id="dolpaymentspan"></span>'."\n";
1013print '<div class="center">'."\n";
1014print '<form id="dolpaymentform" class="center" name="paymentform" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
1015print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
1016print '<input type="hidden" name="action" value="dopayment">'."\n";
1017print '<input type="hidden" name="tag" value="'.GETPOST("tag", 'alpha').'">'."\n";
1018print '<input type="hidden" name="suffix" value="'.dol_escape_htmltag($suffix).'">'."\n";
1019print '<input type="hidden" name="securekey" value="'.dol_escape_htmltag($SECUREKEY).'">'."\n";
1020print '<input type="hidden" name="e" value="'.$entity.'" />';
1021//print '<input type="hidden" name="forcesandbox" value="'.GETPOSTINT('forcesandbox').'" />';
1022print '<input type="hidden" name="lang" value="'.$getpostlang.'">';
1023print '<input type="hidden" name="ws" value="'.$ws.'">';
1024print '<input type="hidden" name="reload" id="reload" value="0">';
1025print "\n";
1026
1027
1028// Show logo (search order: logo defined by PAYMENT_LOGO_suffix, then PAYMENT_LOGO, then small company logo, large company logo, theme logo, common logo)
1029// Define logo and logosmall
1030$logosmall = $mysoc->logo_small;
1031$logo = $mysoc->logo;
1032$paramlogo = 'ONLINE_PAYMENT_LOGO_'.$suffix;
1033if (getDolGlobalString($paramlogo)) {
1034 $logosmall = getDolGlobalString($paramlogo);
1035} elseif (getDolGlobalString('ONLINE_PAYMENT_LOGO')) {
1036 $logosmall = getDolGlobalString('ONLINE_PAYMENT_LOGO');
1037}
1038//print '<!-- Show logo (logosmall='.$logosmall.' logo='.$logo.') -->'."\n";
1039// Define urllogo
1040$urllogo = '';
1041$urllogofull = '';
1042if (!empty($logosmall) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$logosmall)) {
1043 $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/thumbs/'.$logosmall);
1044 $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall);
1045} elseif (!empty($logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$logo)) {
1046 $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/'.$logo);
1047 $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo);
1048}
1049
1050// Output html code for logo
1051if ($ws) {
1052 // Look for a personalized header file (htmlheaderpayment.html) if the payment system is called from a website
1053 $filehtmlheader = dol_sanitizePathName(DOL_DATA_ROOT . ($conf->entity > 1 ? '/' . $conf->entity : '') . '/website/' . $ws . '/htmlheaderpayment.html');
1054 if (dol_is_file($filehtmlheader)) {
1055 print file_get_contents(dol_osencode($filehtmlheader));
1056 }
1057}
1058
1059if ($urllogo && !$ws) {
1060 print '<div class="backgreypublicpayment">';
1061 print '<div class="logopublicpayment">';
1062 print '<img id="dolpaymentlogo" src="'.$urllogo.'"';
1063 print '>';
1064 print '</div>';
1065 if (!getDolGlobalString('MAIN_HIDE_POWERED_BY')) {
1066 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>';
1067 }
1068 print '</div>';
1069} elseif ($creditor && !$ws) {
1070 print '<div class="backgreypublicpayment">';
1071 print '<div class="logopublicpayment">';
1072 print $creditor;
1073 print '</div>';
1074 print '</div>';
1075}
1076if (getDolGlobalString('MAIN_IMAGE_PUBLIC_PAYMENT')) {
1077 print '<div class="backimagepublicpayment">';
1078 print '<img id="idMAIN_IMAGE_PUBLIC_PAYMENT" src="'.getDolGlobalString('MAIN_IMAGE_PUBLIC_PAYMENT').'">';
1079 print '</div>';
1080}
1081
1082
1083
1084
1085print '<!-- Form to send a payment -->'."\n";
1086print '<!-- creditor = '.dol_escape_htmltag((string) $creditor).' -->'."\n";
1087// Additional information for each payment system
1088if (isModEnabled('paypal')) {
1089 print '<!-- PAYPAL_API_SANDBOX = '.getDolGlobalString('PAYPAL_API_SANDBOX').' -->'."\n";
1090 print '<!-- PAYPAL_API_INTEGRAL_OR_PAYPALONLY = '.getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY').' -->'."\n";
1091}
1092if (isModEnabled('paybox')) {
1093 print '<!-- PAYBOX_CGI_URL = '.getDolGlobalString('PAYBOX_CGI_URL_V2').' -->'."\n";
1094}
1095if (isModEnabled('stripe')) {
1096 print '<!-- STRIPE_LIVE = '.getDolGlobalString('STRIPE_LIVE').' -->'."\n";
1097 print '<!-- STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = '.getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION').' -->'."\n";
1098}
1099print '<!-- urlok = '.$urlok.' -->'."\n";
1100print '<!-- urlko = '.$urlko.' -->'."\n";
1101print "\n";
1102
1103// Section with payment informationsummary
1104print '<table id="dolpublictable" summary="Payment form" class="center">'."\n";
1105
1106// Output introduction text
1107$text = '';
1108if (getDolGlobalString('PAYMENT_NEWFORM_TEXT')) {
1109 $langs->load("members");
1110 $reg = array();
1111 if (preg_match('/^\‍((.*)\‍)$/', getDolGlobalString('PAYMENT_NEWFORM_TEXT'), $reg)) {
1112 $text .= $langs->trans($reg[1])."<br>\n";
1113 } else {
1114 $text .= getDolGlobalString('PAYMENT_NEWFORM_TEXT') . "<br>\n";
1115 }
1116 $text = '<tr><td class="center"><br>'.$text.'<br></td></tr>'."\n";
1117}
1118if (empty($text)) {
1119 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnPaymentPage").'</strong></td></tr>'."\n";
1120 $text .= '<tr><td class="textpublicpayment"><span class="opacitymedium">'.$langs->trans("ThisScreenAllowsYouToPay", (string) $creditor).'</span><br><br></td></tr>'."\n";
1121}
1122print $text;
1123
1124// Output payment summary form
1125print '<tr><td align="center">'; // class=center does not have the payment button centered so we keep align here.
1126print '<table class="centpercent left" id="tablepublicpayment">';
1127print '<tr class="hideonsmartphone"><td colspan="2" class="opacitymedium">'.$langs->trans("ThisIsInformationOnPayment").'...<br><br></td></tr>'."\n";
1128
1129$found = false;
1130$error = 0;
1131
1132$object = null;
1133$tag = null;
1134$fulltag = null;
1135
1136
1137// Free payment
1138if (!$source) {
1139 dol_syslog("newpayment.php no source", LOG_DEBUG);
1140
1141 $found = true;
1142 $tag = GETPOST("tag", 'alpha');
1143 if (GETPOST('fulltag', 'alpha')) {
1144 $fulltag = GETPOST('fulltag', 'alpha');
1145 } else {
1146 $fulltag = "TAG=".$tag;
1147 }
1148
1149 // Creditor
1150 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1151 print '</td><td class="CTableRow2">';
1152 print img_picto('', 'company', 'class="pictofixedwidth"');
1153 print '<b>'.$creditor.'</b>';
1154 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1155 print '</td></tr>'."\n";
1156
1157 // Amount
1158 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1159 if (empty($amount)) {
1160 print ' ('.$langs->trans("ToComplete").')';
1161 }
1162 print '</td><td class="CTableRow2">';
1163 if (empty($amount) || !is_numeric($amount)) {
1164 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1165 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1166 // Currency
1167 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1168 } else {
1169 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1170 print '<input type="hidden" name="amount" value="'.$amount.'">';
1171 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1172 }
1173 print '<input type="hidden" name="currency" value="'.$currency.'">';
1174 print '</td></tr>'."\n";
1175
1176 // Tag
1177 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1178 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1179 print '<input type="hidden" name="tag" value="'.$tag.'">';
1180 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1181 print '</td></tr>'."\n";
1182
1183 // We do not add fields shipToName, shipToStreet, shipToCity, shipToState, shipToCountryCode, shipToZip, shipToStreet2, phoneNum
1184 // as they don't exists (buyer is unknown, tag is free).
1185}
1186
1187
1188// Payment on a Sale Order
1189if ($source == 'order') {
1190 dol_syslog("newpayment.php source=order", LOG_DEBUG);
1191
1192 $found = true;
1193 $langs->load("orders");
1194
1195 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
1196
1197 $order = new Commande($db);
1198 $result = $order->fetch(0, $ref);
1199 if ($result <= 0) {
1200 $mesg = $order->error;
1201 $error++;
1202 } else {
1203 $result = $order->fetch_thirdparty($order->socid);
1204 }
1205 $object = $order;
1206
1207 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1208 $amount = $order->total_ttc;
1209 if (GETPOST("amount", 'alpha')) {
1210 $amount = GETPOST("amount", 'alpha');
1211 }
1212 $amount = price2num($amount);
1213 }
1214
1215 $tag = '';
1216 if (GETPOST('fulltag', 'alpha')) {
1217 $fulltag = GETPOST('fulltag', 'alpha');
1218 } else {
1219 $fulltag = 'ORD='.$order->id.'.CUS='.$order->thirdparty->id;
1220 if (!empty($TAG)) {
1221 $tag = $TAG;
1222 $fulltag .= '.TAG='.$TAG;
1223 }
1224 }
1225 $fulltag = dol_string_unaccent($fulltag);
1226
1227 // Creditor
1228 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1229 print '</td><td class="CTableRow2"';
1230 print ' title="'.dolPrintHTMLForAttribute($langs->transnoentitiesnoconv("Country").'='.$mysoc->country_code.' - '.$langs->transnoentitiesnoconv("VATIntra").'='.$mysoc->tva_intra).'"';
1231 print '>';
1232 print img_picto('', 'company', 'class="pictofixedwidth"');
1233 print '<b>'.$creditor.'</b>';
1234 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1235 print '</td></tr>'."\n";
1236
1237 // Debitor
1238 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1239 print '</td><td class="CTableRow2"';
1240 print ' title="'.dolPrintHTMLForAttribute($langs->transnoentitiesnoconv("Country").'='.$order->thirdparty->country_code.' - '.$langs->transnoentitiesnoconv("VATIntra").'='.$order->thirdparty->tva_intra).'"';
1241 print '>';
1242 print img_picto('', 'company', 'class="pictofixedwidth"');
1243 print '<b>'.$order->thirdparty->name.'</b>';
1244 print '</td></tr>'."\n";
1245
1246 // Object
1247 $text = '<b>'.$langs->trans("PaymentOrderRef", $order->ref).'</b>';
1248 if (GETPOST('desc', 'alpha')) {
1249 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1250 }
1251 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1252 print '</td><td class="CTableRow2">'.$text;
1253 print '<input type="hidden" name="s" value="'.dol_escape_htmltag($source).'">';
1254 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($order->ref).'">';
1255 print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag((string) $order->id).'">';
1256 $directdownloadlink = $order->getLastMainDocLink('commande');
1257 if ($directdownloadlink) {
1258 print '<br><a href="'.$directdownloadlink.'" rel="nofollow noopener">';
1259 print img_mime($order->last_main_doc, '');
1260 print $langs->trans("DownloadDocument").'</a>';
1261 }
1262 print '</td></tr>'."\n";
1263
1264 // Amount
1265 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1266 if (empty($amount)) {
1267 print ' ('.$langs->trans("ToComplete").')';
1268 }
1269 print '</td><td class="CTableRow2">';
1270 if (empty($amount) || !is_numeric($amount)) {
1271 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1272 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1273 // Currency
1274 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1275 } else {
1276 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1277 print '<input type="hidden" name="amount" value="'.$amount.'">';
1278 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1279 }
1280 print '<input type="hidden" name="currency" value="'.$currency.'">';
1281 print '</td></tr>'."\n";
1282
1283 // Tag
1284 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1285 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1286 print '<input type="hidden" name="tag" value="'.dol_escape_htmltag($tag).'">';
1287 print '<input type="hidden" name="fulltag" value="'.dol_escape_htmltag($fulltag).'">';
1288 print '</td></tr>'."\n";
1289
1290 // Shipping address
1291 $shipToName = $order->thirdparty->name;
1292 $shipToStreet = $order->thirdparty->address;
1293 $shipToCity = $order->thirdparty->town;
1294 $shipToState = $order->thirdparty->state_code;
1295 $shipToCountryCode = $order->thirdparty->country_code;
1296 $shipToZip = $order->thirdparty->zip;
1297 $shipToStreet2 = '';
1298 $phoneNum = $order->thirdparty->phone;
1299 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1300 print '<input type="hidden" name="shipToName" value="'.dol_escape_htmltag($shipToName).'">'."\n";
1301 print '<input type="hidden" name="shipToStreet" value="'.dol_escape_htmltag($shipToStreet).'">'."\n";
1302 print '<input type="hidden" name="shipToCity" value="'.dol_escape_htmltag($shipToCity).'">'."\n";
1303 print '<input type="hidden" name="shipToState" value="'.dol_escape_htmltag($shipToState).'">'."\n";
1304 print '<input type="hidden" name="shipToCountryCode" value="'.dol_escape_htmltag($shipToCountryCode).'">'."\n";
1305 print '<input type="hidden" name="shipToZip" value="'.dol_escape_htmltag($shipToZip).'">'."\n";
1306 print '<input type="hidden" name="shipToStreet2" value="'.dol_escape_htmltag($shipToStreet2).'">'."\n";
1307 print '<input type="hidden" name="phoneNum" value="'.dol_escape_htmltag($phoneNum).'">'."\n";
1308 } else {
1309 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1310 }
1311 if (is_object($order->thirdparty)) {
1312 print '<input type="hidden" name="thirdparty_id" value="'.$order->thirdparty->id.'">'."\n";
1313 }
1314 print '<input type="hidden" name="email" value="'.$order->thirdparty->email.'">'."\n";
1315 print '<input type="hidden" name="vatnumber" value="'.dol_escape_htmltag($order->thirdparty->tva_intra).'">'."\n";
1316 $labeldesc = $langs->trans("Order").' '.$order->ref;
1317 if (GETPOST('desc', 'alpha')) {
1318 $labeldesc = GETPOST('desc', 'alpha');
1319 }
1320 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1321}
1322
1323
1324// Payment on a Customer Invoice
1325if ($source == 'invoice') {
1326 dol_syslog("newpayment.php source=invoice", LOG_DEBUG);
1327
1328 $found = true;
1329 $langs->load("bills");
1330 $form->load_cache_types_paiements();
1331
1332 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1333
1334 $invoice = new Facture($db);
1335 $result = $invoice->fetch(0, $ref);
1336 if ($result <= 0) {
1337 $mesg = $invoice->error;
1338 $error++;
1339 } else {
1340 $result = $invoice->fetch_thirdparty($invoice->socid);
1341 }
1342 $object = $invoice;
1343
1344 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1345 $amount = price2num($invoice->total_ttc - ($invoice->getSommePaiement() + $invoice->getSumCreditNotesUsed() + $invoice->getSumDepositsUsed()));
1346 if (GETPOST("amount", 'alpha')) {
1347 $amount = GETPOST("amount", 'alpha');
1348 }
1349 $amount = price2num($amount);
1350 }
1351
1352 if (GETPOST('fulltag', 'alpha')) {
1353 $fulltag = GETPOST('fulltag', 'alpha');
1354 } else {
1355 $fulltag = 'INV='.$invoice->id.'.CUS='.$invoice->thirdparty->id;
1356 if (!empty($TAG)) {
1357 $tag = $TAG;
1358 $fulltag .= '.TAG='.$TAG;
1359 }
1360 }
1361 $fulltag = dol_string_unaccent($fulltag);
1362
1363 // Creditor (seller)
1364 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1365 print '</td><td class="CTableRow2"';
1366 print ' title="'.dolPrintHTMLForAttribute($langs->transnoentitiesnoconv("Country").'='.$mysoc->country_code.' - '.$langs->transnoentitiesnoconv("VATIntra").'='.$mysoc->tva_intra).'"';
1367 print '>';
1368 print img_picto('', 'company', 'class="pictofixedwidth"');
1369 print '<b>'.$creditor.'</b>';
1370 print '<input type="hidden" name="creditor" value="'.dol_escape_htmltag((string) $creditor).'">';
1371 print '</td></tr>'."\n";
1372
1373 // Debitor (buyer)
1374 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1375 print '</td><td class="CTableRow2"';
1376 print ' title="'.dolPrintHTMLForAttribute($langs->transnoentitiesnoconv("Country").'='.$invoice->thirdparty->country_code.' - '.$langs->transnoentitiesnoconv("VATIntra").'='.$invoice->thirdparty->tva_intra).'"';
1377 print '>';
1378 print img_picto('', 'company', 'class="pictofixedwidth"');
1379 print '<b>'.$invoice->thirdparty->name.'</b>';
1380 print '</td></tr>'."\n";
1381
1382 // Object
1383 $text = '<b>'.$langs->trans("PaymentInvoiceRef", $invoice->ref).'</b>';
1384 if (GETPOST('desc', 'alpha')) {
1385 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1386 }
1387 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1388 print '</td><td class="CTableRow2">'.$text;
1389 print '<input type="hidden" name="s" value="'.dol_escape_htmltag($source).'">';
1390 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($invoice->ref).'">';
1391 print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag((string) $invoice->id).'">';
1392 $directdownloadlink = $invoice->getLastMainDocLink('facture');
1393 if ($directdownloadlink) {
1394 print '<br><a href="'.$directdownloadlink.'">';
1395 print img_mime($invoice->last_main_doc, '');
1396 print $langs->trans("DownloadDocument").'</a>';
1397 }
1398 print '</td></tr>'."\n";
1399
1400 // Amount
1401 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentAmount");
1402 if (empty($amount) && empty($object->paye)) {
1403 print ' ('.$langs->trans("ToComplete").')';
1404 }
1405 print '</td><td class="CTableRow2">';
1406 if ($object->type == $object::TYPE_CREDIT_NOTE) {
1407 print '<b>'.$langs->trans("CreditNote").'</b>';
1408 } elseif (empty($object->paye)) {
1409 if (empty($amount) || !is_numeric($amount)) {
1410 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1411 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1412 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1413 } else {
1414 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1415 print '<input type="hidden" name="amount" value="'.$amount.'">';
1416 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1417 }
1418 } else {
1419 print '<b class="amount">'.price($object->total_ttc, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1420 }
1421 print '<input type="hidden" name="currency" value="'.$currency.'">';
1422 print '</td></tr>'."\n";
1423
1424 // Tag
1425 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1426 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1427 print '<input type="hidden" name="tag" value="'.(empty($tag) ? '' : $tag).'">';
1428 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1429 print '</td></tr>'."\n";
1430
1431 // Add a warning if we try to pay an invoice set to be paid in credit transfer
1432 if ($invoice->status == $invoice::STATUS_VALIDATED && $invoice->mode_reglement_id > 0 && $form->cache_types_paiements[$invoice->mode_reglement_id]["code"] == "VIR") {
1433 print '<tr class="CTableRow2 center"><td class="CTableRow2" colspan="2">';
1434 print '<div class="warning maxwidth1000">';
1435 print $langs->trans("PayOfBankTransferInvoice");
1436 print '</div>';
1437 print '</td></tr>'."\n";
1438 }
1439
1440 // Shipping address
1441 $shipToName = $invoice->thirdparty->name;
1442 $shipToStreet = $invoice->thirdparty->address;
1443 $shipToCity = $invoice->thirdparty->town;
1444 $shipToState = $invoice->thirdparty->state_code;
1445 $shipToCountryCode = $invoice->thirdparty->country_code;
1446 $shipToZip = $invoice->thirdparty->zip;
1447 $shipToStreet2 = '';
1448 $phoneNum = $invoice->thirdparty->phone;
1449 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1450 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1451 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1452 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1453 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1454 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1455 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1456 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1457 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1458 } else {
1459 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1460 }
1461 if (is_object($invoice->thirdparty)) {
1462 print '<input type="hidden" name="thirdparty_id" value="'.$invoice->thirdparty->id.'">'."\n";
1463 }
1464 print '<input type="hidden" name="email" value="'.$invoice->thirdparty->email.'">'."\n";
1465 print '<input type="hidden" name="vatnumber" value="'.$invoice->thirdparty->tva_intra.'">'."\n";
1466 $labeldesc = $langs->trans("Invoice").' '.$invoice->ref;
1467 if (GETPOST('desc', 'alpha')) {
1468 $labeldesc = GETPOST('desc', 'alpha');
1469 }
1470 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1471}
1472
1473// Payment on a Contract line
1474if ($source == 'contractline') {
1475 dol_syslog("newpayment.php source=contractline", LOG_DEBUG);
1476
1477 $found = true;
1478 $langs->load("contracts");
1479
1480 require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
1481
1482 $contract = new Contrat($db);
1483 $contractline = new ContratLigne($db);
1484
1485 $result = $contractline->fetch(0, $ref);
1486 if ($result <= 0) {
1487 $mesg = $contractline->error;
1488 $error++;
1489 } else {
1490 if ($contractline->fk_contrat > 0) {
1491 $result = $contract->fetch($contractline->fk_contrat);
1492 if ($result > 0) {
1493 $result = $contract->fetch_thirdparty($contract->socid);
1494 } else {
1495 $mesg = $contract->error;
1496 $error++;
1497 }
1498 } else {
1499 $mesg = 'ErrorRecordNotFound';
1500 $error++;
1501 }
1502 }
1503 $object = $contractline;
1504
1505 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1506 $amount = $contractline->total_ttc;
1507
1508 if ($contractline->fk_product && getDolGlobalString('PAYMENT_USE_NEW_PRICE_FOR_CONTRACTLINES')) {
1509 $product = new Product($db);
1510 $result = $product->fetch($contractline->fk_product);
1511
1512 // We define price for product (TODO Put this in a method in product class)
1513 if (getDolGlobalString('PRODUIT_MULTIPRICES')) {
1514 $pu_ht = $product->multiprices[$contract->thirdparty->price_level];
1515 $pu_ttc = $product->multiprices_ttc[$contract->thirdparty->price_level];
1516 $price_base_type = $product->multiprices_base_type[$contract->thirdparty->price_level];
1517 } else {
1518 $pu_ht = $product->price;
1519 $pu_ttc = $product->price_ttc;
1520 $price_base_type = $product->price_base_type;
1521 }
1522
1523 $amount = $pu_ttc;
1524 if (empty($amount)) {
1525 dol_print_error(null, 'ErrorNoPriceDefinedForThisProduct');
1526 exit;
1527 }
1528 }
1529
1530 if (GETPOST("amount", 'alpha')) {
1531 $amount = GETPOST("amount", 'alpha');
1532 }
1533 $amount = price2num($amount);
1534 }
1535
1536 if (GETPOST('fulltag', 'alpha')) {
1537 $fulltag = GETPOST('fulltag', 'alpha');
1538 } else {
1539 $fulltag = 'COL='.$contractline->id.'.CON='.$contract->id.'.CUS='.$contract->thirdparty->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1540 if (!empty($TAG)) {
1541 $tag = $TAG;
1542 $fulltag .= '.TAG='.$TAG;
1543 }
1544 }
1545 $fulltag = dol_string_unaccent($fulltag);
1546
1547 $qty = 1;
1548 if (GETPOST('qty')) {
1549 $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
1550 }
1551
1552 // Creditor
1553 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1554 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1555 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1556 print '</td></tr>'."\n";
1557
1558 // Debitor
1559 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
1560 print '</td><td class="CTableRow2"><b>'.$contract->thirdparty->name.'</b>';
1561 print '</td></tr>'."\n";
1562
1563 // Object
1564 $text = '<b>'.$langs->trans("PaymentRenewContractId", $contract->ref, $contractline->ref).'</b>';
1565 if ($contractline->fk_product > 0) {
1566 $contractline->fetch_product();
1567 $text .= '<br>'.$contractline->product->ref.($contractline->product->label ? ' - '.$contractline->product->label : '');
1568 }
1569 if ($contractline->description) {
1570 $text .= '<br>'.dol_htmlentitiesbr($contractline->description);
1571 }
1572 if ($contractline->date_end) {
1573 $text .= '<br>'.$langs->trans("ExpiredSince").': '.dol_print_date($contractline->date_end);
1574 }
1575 if (GETPOST('desc', 'alpha')) {
1576 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1577 }
1578 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1579 print '</td><td class="CTableRow2">'.$text;
1580 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
1581 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($contractline->ref).'">';
1582 print '<input type="hidden" name="dol_id" value="'.dol_escape_htmltag((string) $contractline->id).'">';
1583 $directdownloadlink = $contract->getLastMainDocLink('contract');
1584 if ($directdownloadlink) {
1585 print '<br><a href="'.$directdownloadlink.'">';
1586 print img_mime($contract->last_main_doc, '');
1587 print $langs->trans("DownloadDocument").'</a>';
1588 }
1589 print '</td></tr>'."\n";
1590
1591 // Quantity
1592 $label = $langs->trans("Quantity");
1593 $qty = 1;
1594 $duration = '';
1595 if ($contractline->fk_product) {
1596 if ($contractline->product->isService() && $contractline->product->duration_value > 0) {
1597 $label = $langs->trans("Duration");
1598
1599 // TODO Put this in a global method
1600 if ($contractline->product->duration_value > 1) {
1601 $dur = array("h" => $langs->trans("Hours"), "d" => $langs->trans("DurationDays"), "w" => $langs->trans("DurationWeeks"), "m" => $langs->trans("DurationMonths"), "y" => $langs->trans("DurationYears"));
1602 } else {
1603 $dur = array("h" => $langs->trans("Hour"), "d" => $langs->trans("DurationDay"), "w" => $langs->trans("DurationWeek"), "m" => $langs->trans("DurationMonth"), "y" => $langs->trans("DurationYear"));
1604 }
1605 $duration = $contractline->product->duration_value.' '.$dur[$contractline->product->duration_unit];
1606 }
1607 }
1608 print '<tr class="CTableRow2"><td class="CTableRow2">'.$label.'</td>';
1609 print '<td class="CTableRow2"><b>'.($duration ? $duration : $qty).'</b>';
1610 print '<input type="hidden" name="newqty" value="'.dol_escape_htmltag((string) $qty).'">';
1611 print '</b></td></tr>'."\n";
1612
1613 // Amount
1614 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
1615 if (empty($amount)) {
1616 print ' ('.$langs->trans("ToComplete").')';
1617 }
1618 print '</td><td class="CTableRow2">';
1619 if (empty($amount) || !is_numeric($amount)) {
1620 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
1621 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.price2num(GETPOST("newamount", "alpha"), 'MT').'">';
1622 // Currency
1623 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
1624 } else {
1625 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
1626 print '<input type="hidden" name="amount" value="'.$amount.'">';
1627 print '<input type="hidden" name="newamount" value="'.$amount.'">';
1628 }
1629 print '<input type="hidden" name="currency" value="'.$currency.'">';
1630 print '</td></tr>'."\n";
1631
1632 // Tag
1633 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
1634 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
1635 print '<input type="hidden" name="tag" value="'.$tag.'">';
1636 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
1637 print '</td></tr>'."\n";
1638
1639 // Shipping address
1640 $shipToName = $contract->thirdparty->name;
1641 $shipToStreet = $contract->thirdparty->address;
1642 $shipToCity = $contract->thirdparty->town;
1643 $shipToState = $contract->thirdparty->state_code;
1644 $shipToCountryCode = $contract->thirdparty->country_code;
1645 $shipToZip = $contract->thirdparty->zip;
1646 $shipToStreet2 = '';
1647 $phoneNum = $contract->thirdparty->phone;
1648 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
1649 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
1650 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
1651 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
1652 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
1653 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
1654 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
1655 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
1656 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
1657 } else {
1658 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
1659 }
1660 if (is_object($contract->thirdparty)) {
1661 print '<input type="hidden" name="thirdparty_id" value="'.$contract->thirdparty->id.'">'."\n";
1662 }
1663 print '<input type="hidden" name="email" value="'.$contract->thirdparty->email.'">'."\n";
1664 print '<input type="hidden" name="vatnumber" value="'.$contract->thirdparty->tva_intra.'">'."\n";
1665 $labeldesc = $langs->trans("Contract").' '.$contract->ref;
1666 if (GETPOST('desc', 'alpha')) {
1667 $labeldesc = GETPOST('desc', 'alpha');
1668 }
1669 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
1670}
1671
1672// Payment on a Member subscription
1673if ($source == 'member' || $source == 'membersubscription') {
1674 dol_syslog("newpayment.php source=".$source, LOG_DEBUG);
1675
1676 $newsource = 'member';
1677
1678 $tag = "";
1679 $found = true;
1680 $langs->load("members");
1681
1682 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1683 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
1684 require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1685
1686 $member = new Adherent($db);
1687 $adht = new AdherentType($db);
1688
1689 $result = $member->fetch(0, $ref, 0, '', true, true); // This fetch also ->last_subscription_amount
1690 if ($result <= 0) {
1691 $mesg = $member->error;
1692 $error++;
1693 } else {
1694 $member->fetch_thirdparty();
1695
1696 $adht->fetch($member->typeid);
1697 }
1698 $object = $member;
1699
1700 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
1701 $amount = $member->last_subscription_amount;
1702 if (GETPOST("amount", 'alpha')) {
1703 $amount = price2num(GETPOST("amount", 'alpha'), 'MT', 2);
1704 }
1705 // If amount still not defined, we take amount of the type of member
1706 if (empty($amount)) {
1707 $amount = $adht->amount;
1708 }
1709
1710 $amount = max(0, price2num($amount, 'MT'));
1711 }
1712
1713 if (GETPOST('fulltag', 'alpha')) {
1714 $fulltag = GETPOST('fulltag', 'alpha');
1715 } else {
1716 $fulltag = 'MEM='.$member->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1717 if (!empty($TAG)) {
1718 $tag = $TAG;
1719 $fulltag .= '.TAG='.$TAG;
1720 }
1721 }
1722 $fulltag = dol_string_unaccent($fulltag);
1723
1724 // Creditor
1725 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
1726 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
1727 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
1728 print '</td></tr>'."\n";
1729
1730 // Debitor
1731 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Member");
1732 print '</td><td class="CTableRow2">';
1733 print '<b>';
1734 if ($member->morphy == 'mor' && !empty($member->company)) {
1735 print img_picto('', 'company', 'class="pictofixedwidth"');
1736 print $member->company;
1737 } else {
1738 print img_picto('', 'member', 'class="pictofixedwidth"');
1739 print $member->getFullName($langs);
1740 }
1741 print '</b>';
1742 print '</td></tr>'."\n";
1743
1744 // Object
1745 $text = '<b>'.$langs->trans("PaymentSubscription").'</b>';
1746 if (GETPOST('desc', 'alpha')) {
1747 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
1748 }
1749 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
1750 print '</td><td class="CTableRow2">'.$text;
1751 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($newsource).'">';
1752 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($member->ref).'">';
1753 print '</td></tr>'."\n";
1754
1755 if ($object->datefin > 0) {
1756 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("DateEndSubscription");
1757 print '</td><td class="CTableRow2">'.dol_print_date($member->datefin, 'day');
1758 print '</td></tr>'."\n";
1759 }
1760
1761 if ($member->last_subscription_date || $member->last_subscription_amount) {
1762 // Last subscription date
1763
1764 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastSubscriptionDate");
1765 print '</td><td class="CTableRow2">'.dol_print_date($member->last_subscription_date, 'day');
1766 print '</td></tr>'."\n";
1767
1768 // Last subscription amount
1769
1770 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastSubscriptionAmount");
1771 print '</td><td class="CTableRow2">'.price($member->last_subscription_amount);
1772 print '</td></tr>'."\n";
1773
1774 if (empty($amount) && !GETPOST('newamount', 'alpha')) {
1775 $_GET['newamount'] = $member->last_subscription_amount;
1776 $_GET['amount'] = $member->last_subscription_amount;
1777 }
1778 if (!empty($member->last_subscription_amount) && !GETPOSTISSET('newamount') && is_numeric($amount)) {
1779 $amount = max($member->last_subscription_amount, $amount);
1780 }
1781 }
1782
1783 $amountbytype = $adht->amountByType(1);
1784
1785 $typeid = $adht->id;
1786 $caneditamount = $adht->caneditamount;
1787
1788 if ($member->type) {
1789 $oldtypeid = $member->typeid;
1790 $newtypeid = (int) (GETPOSTISSET("typeid") ? GETPOSTINT("typeid") : $member->typeid);
1791 if (getDolGlobalString('MEMBER_ALLOW_CHANGE_OF_TYPE')) {
1792 $typeid = $newtypeid;
1793 $adht->fetch($typeid); // Reload with the new type id
1794 }
1795
1796 $caneditamount = $adht->caneditamount;
1797
1798 if (getDolGlobalString('MEMBER_ALLOW_CHANGE_OF_TYPE')) {
1799 // Last member type
1800 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastMemberType");
1801 print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1802 print "</td></tr>\n";
1803
1804 // Set the new member type
1805 $member->typeid = $newtypeid;
1806 $member->type = (string) dol_getIdFromCode($db, $newtypeid, 'adherent_type', 'rowid', 'libelle');
1807
1808 // list member type
1809 if (!$action) {
1810 // Set amount for the subscription.
1811 // If we change the type, we use the amount of the new type and not the amount of last subscription.
1812 $amount = (!empty($amountbytype[$member->typeid])) ? $amountbytype[$member->typeid] : $member->last_subscription_amount;
1813
1814 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("NewSubscription");
1815 print '</td><td class="CTableRow2">';
1816 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);
1817 print "</td></tr>\n";
1818 } elseif ($action == 'dopayment') {
1819 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("NewMemberType");
1820 print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1821 print '<input type="hidden" name="membertypeid" value="'.$member->typeid.'">';
1822 print "</td></tr>\n";
1823 }
1824 } else {
1825 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("MemberType");
1826 print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
1827 print "</td></tr>\n";
1828 }
1829 }
1830
1831
1832 // Add hook to complete the form
1833 $parameters = array('mode' => 'renewal');
1834 $reshook = $hookmanager->executeHooks('membershipNewSubscriptionPublicForm', $parameters, $object, $action);
1835 if ($reshook < 0) {
1836 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1837 $error++;
1838 }
1839
1840 // TODO Move this into previous hook
1841 if (getDolGlobalString('MEMBER_NEWFORM_DOLIBARRTURNOVER') && $action != 'dopayment') {
1842 $country_id = 0;
1843 if ($member->thirdparty instanceOf Societe) {
1844 $country_id = $member->thirdparty->country_id;
1845 }
1846 $checkednature = $member->morphy;
1847 print '<input type="hidden" name="moralinput" id="moralinput" value="'.$checkednature.'">';
1848
1849 // Is it a Preferred Partner
1850 $pp = 0;
1851 include_once DOL_DOCUMENT_ROOT.'/partnership/class/partnership.class.php';
1852 $partnership = new Partnership($db);
1853 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1854 $result = $partnership->fetch(0, null, null, $member->thirdparty->id);
1855 if ($result > 0) {
1856 $pp = 1;
1857 }
1858
1859 // Do not set a default amount MEMBER_NEWFORM_AMOUNT if you use MEMBER_NEWFORM_DOLIBARRTURNOVER
1860 $s = $langs->trans("AreYouAPreferredPartner", '<a href="https://partners.dolibarr.org" target="_blank">{s1}</a>');
1861 $s = str_replace('{s1}', 'Preferred Partner', $s);
1862 print '<tr id="trbudget" class="trcompany"><td><label for="pp" class="small">'.$s.'</label></td><td>';
1863 print '<input type="checkbox" name="pp" id="pp" value="1"'.((GETPOST('reload') ? GETPOST('pp') : $pp) ? ' checked="checked"' : '').' class="reposition">';
1864 print '</td></tr>';
1865
1866 print '<tr id="trbudget" class="trcompany"><td class=""><span class="small">'.$langs->trans("TurnoverOrBudget").'</span></td><td>';
1867
1868 $country_code = dol_getIdFromCode($db, $country_id, 'c_country', 'rowid', 'code');
1869 if ($country_code === 'FR' && $checkednature === 'mor' && (GETPOST('reload') ? GETPOST('pp') : $pp)) {
1870 print '<input type="text" name="budget" id="budget" class="flat turnover right width100" value="'.GETPOST('budget').'"'.($action != 'dopayment' ? ' required autofocus' : '').'>';
1871 } else {
1872 $arraybudget = array('50' => '<= 100 000', '100' => '<= 200 000', '200' => '<= 500 000', '300' => '<= 1 500 000', '600' => '<= 3 000 000', '1000' => '<= 5 000 000', '2000' => '5 000 000+');
1873 print $form->selectarray('budget', $arraybudget, GETPOSTINT('budget'), 1, 0, 0, ($checkednature === 'mor' ? 'required' :''), 0, 0, 0, '');
1874 }
1875 print ' € or $';
1876
1877 print '<script type="text/javascript">
1878 jQuery(document).ready(function() {
1879 firstload = true;
1880
1881 newamount = initturnover();
1882 jQuery("#amount").val(newamount);
1883 jQuery("#newamount").val(newamount);
1884
1885 firstload = false;
1886
1887 jQuery("#selectcountry_id").change(function() {
1888 console.log("We change country (code added for association, replace common code), so we reload page");
1889 jQuery("#budget").val(\'\');
1890 jQuery("#amount").val(\'\');
1891 jQuery("#newamount").val(\'\');
1892 jQuery("#amounthidden").val(\'\');
1893 });
1894 jQuery("#pp").change(function() {
1895 console.log("We change the preferred partner status");
1896 selectcountry_id = jQuery("#selectcountry_id").val();
1897 morphy = jQuery("#moralinput").is(\':checked\') ? \'mor\' : \'phy\';
1898 jQuery("#budget").val(\'\');
1899 jQuery("#amount").val(\'\');
1900 jQuery("#amounthidden").val(\'\');
1901 jQuery("#newamount").val(\'\');
1902 jQuery("#reload").val(\'1\');
1903 document.paymentform.action.value="";
1904 jQuery("#dolpaymentform").submit();
1905 });
1906 jQuery("#budget").change(function() {
1907 console.log("Turnover amount has been modified on change");
1908 newamount = initturnover();
1909 jQuery("#amount").val(newamount);
1910 jQuery("#amounthidden").val(newamount);
1911 jQuery("#newamount").val(newamount);
1912 });
1913 jQuery("#budget").keyup(function() {
1914 console.log("Turnover amount has been modified on keyup");
1915 newamount = initturnover();
1916 jQuery("#amount").val(newamount);
1917 jQuery("#amounthidden").val(newamount);
1918 jQuery("#newamount").val(newamount);
1919 });
1920
1921 function initturnover() {
1922 newamount = 0;
1923
1924 //morphy = jQuery("#moralinput").is(\':checked\') ? \'mor\' : \'phy\';
1925 morphy = jQuery("#moralinput").val();
1926 selectcountry_id = '.((int) $country_id).';
1927 pp = jQuery("#pp").is(\':checked\') ? true : false;
1928 console.log("Set fields according to nature and other properties");
1929 console.log("morphy="+morphy);
1930 console.log("selectcountry_id="+selectcountry_id);
1931 console.log("pp="+pp);
1932
1933 if (morphy == \'phy\') {
1934 jQuery(".amount").val('.((float) $amount).');
1935 jQuery("#trbirth").show();
1936 jQuery(".trcompany").hide();
1937 jQuery(".trbudget").hide();
1938 newamount = '.((float) $amount).';
1939 } else {
1940 jQuery(".amount").val(\'\');
1941 jQuery("#trbirth").hide();
1942 jQuery(".trcompany").show();
1943 jQuery(".trbudget").show();
1944 jQuery(".hideifautoturnover").hide();
1945 if (firstload) {
1946 jQuery("#budget").val(\'\');
1947 }
1948
1949 if (selectcountry_id == 1) {
1950 if (jQuery("#budget").val() == \'\') {
1951 return null;
1952 }
1953 if (pp) {
1954 console.log("value selected in input text field is "+jQuery("#budget").val());
1955 newamount = Math.max(Math.round(price2numjs(jQuery("#budget").val()) * 0.005), 50);
1956 console.log("newamount = "+newamount);
1957 } else {
1958 console.log("not a pp");
1959 if (jQuery("#budget").val() > 0) {
1960 console.log("value found in budget is "+jQuery("#budget").val());
1961 newamount = jQuery("#budget").val();
1962 } else {
1963 jQuery("#budget").val(\'\');
1964 newamount = \'\';
1965 }
1966 }
1967 } else {
1968 if (jQuery("#budget").val() > 0) {
1969 newamount = jQuery("#budget").val();
1970 } else {
1971 jQuery("#budget").val(\'\');
1972 newamount = \'\';
1973 }
1974 }
1975 }
1976
1977 return newamount;
1978 }
1979 });
1980 </script>';
1981 print '</td></tr>'."\n";
1982 }
1983
1984
1985 // Set amount for the subscription from the the type and options:
1986 // - First check the amount of the member type if there is no previous payment.
1987 $amount = ($member->last_subscription_amount ? $member->last_subscription_amount : (empty($amountbytype[$typeid]) ? 0 : $amountbytype[$typeid]));
1988 // - If not found, take the default amount
1989 if (empty($amount) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
1990 $amount = getDolGlobalString('MEMBER_NEWFORM_AMOUNT');
1991 }
1992
1993 // - If an amount was posted from the form (for example from page with types of membership)
1994 if ($caneditamount && !GETPOST('reload') && GETPOSTISSET('amount') && GETPOSTFLOAT('amount', 'MT') > 0) {
1995 $amount = GETPOSTFLOAT('amount', 'MT');
1996 }
1997 // - If a new amount was posted from the form
1998 if ($caneditamount && !GETPOST('reload') && GETPOSTISSET('newamount') && GETPOSTFLOAT('newamount', 'MT') > 0) {
1999 $amount = GETPOSTFLOAT('newamount', 'MT');
2000 }
2001 // - If a min is set or an amount from the posted form, we take them into account
2002 $amount = max(0, (float) $amount, (float) getDolGlobalInt("MEMBER_MIN_AMOUNT"));
2003
2004 // Amount
2005 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
2006 // This place no longer allows amount edition
2007 if (getDolGlobalString('MEMBER_EXT_URL_SUBSCRIPTION_INFO')) {
2008 print ' - <a href="' . getDolGlobalString('MEMBER_EXT_URL_SUBSCRIPTION_INFO').'" rel="external" target="_blank" rel="noopener noreferrer">'.img_picto('', 'url', 'class="pictofixedwidth"').$langs->trans("SeeHere").'</a>';
2009 }
2010 print '</td><td class="CTableRow2">';
2011
2012 $caneditamount = $adht->caneditamount;
2013 $minimumamount = !getDolGlobalString('MEMBER_MIN_AMOUNT') ? $adht->amount : max(getDolGlobalString('MEMBER_MIN_AMOUNT'), $adht->amount, $amount);
2014
2015 if ($caneditamount && ($action != 'dopayment' || GETPOST('reload'))) {
2016 if (GETPOSTISSET('newamount')) {
2017 print '<input type="text" class="width75 amount" name="newamount" id="newamount" value="'.price(price2num(GETPOST('newamount'), '', 2), 1, $langs, 1, -1, -1).'">';
2018 } else {
2019 print '<input type="text" class="width75 amount" name="newamount" id="newamount" value="'.price($amount, 1, $langs, 1, -1, -1).'">';
2020 }
2021 } else {
2022 print '<b class="amount">'.price($amount, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
2023 if ($minimumamount > $amount) {
2024 print ' &nbsp; <span class="opacitymedium small">'. $langs->trans("AmountIsLowerToMinimumNotice", price($minimumamount, 1, $langs, 1, -1, -1, $currency)).'</span>';
2025 }
2026 print '<input type="hidden" name="newamount" value="'.$amount.'">';
2027 }
2028 print '<input type="hidden" name="amount" value="'.$amount.'">';
2029 print '<input type="hidden" name="currency" value="'.$currency.'">';
2030 print '</td></tr>'."\n";
2031
2032 // Tag
2033 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
2034 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
2035 print '<input type="hidden" name="tag" value="'.$tag.'">';
2036 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
2037 print '</td></tr>'."\n";
2038
2039 // Shipping address
2040 $shipToName = $member->getFullName($langs);
2041 $shipToStreet = $member->address;
2042 $shipToCity = $member->town;
2043 $shipToState = $member->state_code;
2044 $shipToCountryCode = $member->country_code;
2045 $shipToZip = $member->zip;
2046 $shipToStreet2 = '';
2047 $phoneNum = $member->phone;
2048 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
2049 print '<!-- Shipping address information -->';
2050 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
2051 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
2052 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
2053 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
2054 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
2055 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
2056 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
2057 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
2058 } else {
2059 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
2060 }
2061 if (is_object($member->thirdparty)) {
2062 print '<input type="hidden" name="thirdparty_id" value="'.$member->thirdparty->id.'">'."\n";
2063 }
2064 print '<input type="hidden" name="email" value="'.$member->email.'">'."\n";
2065 $labeldesc = $langs->trans("PaymentSubscription");
2066 if (GETPOST('desc', 'alpha')) {
2067 $labeldesc = GETPOST('desc', 'alpha');
2068 }
2069 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
2070}
2071
2072// Payment on donation
2073if ($source == 'donation') {
2074 dol_syslog("newpayment.php source=donation", LOG_DEBUG);
2075
2076 $found = true;
2077 $langs->load("don");
2078
2079 require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
2080
2081 $don = new Don($db);
2082 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
2083 $result = $don->fetch((int) $ref);
2084 if ($result <= 0) {
2085 $mesg = $don->error;
2086 $error++;
2087 } else {
2088 $don->fetch_thirdparty();
2089 }
2090 $object = $don;
2091
2092 if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
2093 if (GETPOST("amount", 'alpha')) {
2094 $amount = GETPOST("amount", 'alpha');
2095 } else {
2096 $amount = $don->getRemainToPay();
2097 }
2098 $amount = price2num($amount);
2099 }
2100
2101 if (GETPOST('fulltag', 'alpha')) {
2102 $fulltag = GETPOST('fulltag', 'alpha');
2103 } else {
2104 $fulltag = 'DON='.$don->ref.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
2105 if (!empty($TAG)) {
2106 $tag = $TAG;
2107 $fulltag .= '.TAG='.$TAG;
2108 }
2109 }
2110 $fulltag = dol_string_unaccent($fulltag);
2111
2112 // Creditor
2113 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
2114 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
2115 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
2116 print '</td></tr>'."\n";
2117
2118 // Debitor
2119 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
2120 print '</td><td class="CTableRow2"><b>';
2121 if ($don->morphy == 'mor' && !empty($don->societe)) {
2122 print $don->societe;
2123 } else {
2124 print $don->getFullName($langs);
2125 }
2126 print '</b>';
2127 print '</td></tr>'."\n";
2128
2129 // Object
2130 $text = '<b>'.$langs->trans("PaymentDonation").'</b>';
2131 if (GETPOST('desc', 'alpha')) {
2132 $text = '<b>'.$langs->trans(GETPOST('desc', 'alpha')).'</b>';
2133 }
2134 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
2135 print '</td><td class="CTableRow2">'.$text;
2136 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
2137 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag($don->ref).'">';
2138 print '</td></tr>'."\n";
2139
2140 // Amount
2141 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
2142 if (empty($amount)) {
2143 if (!getDolGlobalString('DONATION_NEWFORM_AMOUNT')) {
2144 print ' ('.$langs->trans("ToComplete");
2145 }
2146 if (getDolGlobalString('DONATION_EXT_URL_SUBSCRIPTION_INFO')) {
2147 print ' - <a href="' . getDolGlobalString('DONATION_EXT_URL_SUBSCRIPTION_INFO').'" rel="external" target="_blank" rel="noopener noreferrer">'.$langs->trans("SeeHere").'</a>';
2148 }
2149 if (!getDolGlobalString('DONATION_NEWFORM_AMOUNT')) {
2150 print ')';
2151 }
2152 }
2153 print '</td><td class="CTableRow2">';
2154 $valtoshow = '';
2155 if (empty($amount) || !is_numeric($amount)) {
2156 $valtoshow = price2num(GETPOST("newamount", 'alpha'), 'MT');
2157 // force default subscription amount to value defined into constant...
2158 if (empty($valtoshow)) {
2159 if (getDolGlobalString('DONATION_NEWFORM_EDITAMOUNT')) {
2160 if (getDolGlobalString('DONATION_NEWFORM_AMOUNT')) {
2161 $valtoshow = getDolGlobalString('DONATION_NEWFORM_AMOUNT');
2162 }
2163 } else {
2164 if (getDolGlobalString('DONATION_NEWFORM_AMOUNT')) {
2165 $amount = getDolGlobalString('DONATION_NEWFORM_AMOUNT');
2166 }
2167 }
2168 }
2169 }
2170 if (empty($amount) || !is_numeric($amount)) {
2171 //$valtoshow=price2num(GETPOST("newamount",'alpha'),'MT');
2172 if (getDolGlobalString('DONATION_MIN_AMOUNT') && $valtoshow) {
2173 $valtoshow = max(getDolGlobalString('DONATION_MIN_AMOUNT'), $valtoshow);
2174 }
2175 print '<input type="hidden" name="amount" value="'.price2num(GETPOST("amount", 'alpha'), 'MT').'">';
2176 print '<input class="flat maxwidth75" type="text" name="newamount" value="'.$valtoshow.'">';
2177 // Currency
2178 print ' <b>'.$langs->trans("Currency".$currency).'</b>';
2179 } else {
2180 $valtoshow = $amount;
2181 if (getDolGlobalString('DONATION_MIN_AMOUNT') && $valtoshow) {
2182 $valtoshow = max(getDolGlobalString('DONATION_MIN_AMOUNT'), $valtoshow);
2183 $amount = $valtoshow;
2184 }
2185 print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
2186 print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
2187 print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
2188 }
2189 print '<input type="hidden" name="currency" value="'.$currency.'">';
2190 print '</td></tr>'."\n";
2191
2192 // Tag
2193 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
2194 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
2195 print '<input type="hidden" name="tag" value="'.$tag.'">';
2196 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
2197 print '</td></tr>'."\n";
2198
2199 // Shipping address
2200 $shipToName = $don->getFullName($langs);
2201 $shipToStreet = $don->address;
2202 $shipToCity = $don->town;
2203 $shipToState = $don->state_code;
2204 $shipToCountryCode = $don->country_code;
2205 $shipToZip = $don->zip;
2206 $shipToStreet2 = '';
2207 $phoneNum = $don->phone;
2208 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
2209 print '<!-- Shipping address information -->';
2210 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
2211 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
2212 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
2213 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
2214 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
2215 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
2216 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
2217 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
2218 } else {
2219 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
2220 }
2221 if (is_object($don->thirdparty)) {
2222 print '<input type="hidden" name="thirdparty_id" value="'.$don->thirdparty->id.'">'."\n";
2223 }
2224 print '<input type="hidden" name="email" value="'.$don->email.'">'."\n";
2225 $labeldesc = $langs->trans("PaymentSubscription");
2226 if (GETPOST('desc', 'alpha')) {
2227 $labeldesc = GETPOST('desc', 'alpha');
2228 }
2229 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
2230}
2231
2232if ($source == 'organizedeventregistration' && is_object($thirdparty)) {
2233 dol_syslog("newpayment.php source=organizedeventregistration", LOG_DEBUG);
2234
2235 $found = true;
2236 $langs->loadLangs(array("members", "eventorganization"));
2237
2238 if (GETPOST('fulltag', 'alpha')) {
2239 $fulltag = GETPOST('fulltag', 'alpha');
2240 } else {
2241 $fulltag = 'ATT='.$attendee->id.'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
2242 if (!empty($TAG)) {
2243 $tag = $TAG;
2244 $fulltag .= '.TAG='.$TAG;
2245 }
2246 }
2247 $fulltag = dol_string_unaccent($fulltag);
2248
2249 // Creditor
2250 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
2251 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
2252 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
2253 print '</td></tr>'."\n";
2254
2255 // Debitor
2256 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Attendee");
2257 print '</td><td class="CTableRow2"><b>';
2258 print $attendee->email;
2259 print($thirdparty->name ? ' ('.$thirdparty->name.')' : '');
2260 print '</b>';
2261 print '</td></tr>'."\n";
2262
2263 if (! is_object($attendee->project)) {
2264 $text = 'ErrorProjectNotFound';
2265 } else {
2266 $text = $langs->trans("PaymentEvent").' - '.$attendee->project->title;
2267 }
2268
2269 // Object
2270 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
2271 print '</td><td class="CTableRow2"><b>'.$text.'</b>';
2272 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
2273 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag((string) $invoice->id).'">';
2274 print '</td></tr>'."\n";
2275
2276 // Amount
2277 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
2278 print '</td><td class="CTableRow2">';
2279 $valtoshow = $amount;
2280 print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
2281 print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
2282 print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
2283 print '<input type="hidden" name="currency" value="'.$currency.'">';
2284 print '</td></tr>'."\n";
2285
2286 // Tag
2287 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
2288 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
2289 print '<input type="hidden" name="tag" value="'.$tag.'">';
2290 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
2291 print '</td></tr>'."\n";
2292
2293 // Shipping address
2294 $shipToName = $thirdparty->getFullName($langs);
2295 $shipToStreet = $thirdparty->address;
2296 $shipToCity = $thirdparty->town;
2297 $shipToState = $thirdparty->state_code;
2298 $shipToCountryCode = $thirdparty->country_code;
2299 $shipToZip = $thirdparty->zip;
2300 $shipToStreet2 = '';
2301 $phoneNum = $thirdparty->phone;
2302 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
2303 print '<!-- Shipping address information -->';
2304 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
2305 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
2306 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
2307 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
2308 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
2309 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
2310 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
2311 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
2312 } else {
2313 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
2314 }
2315 print '<input type="hidden" name="thirdparty_id" value="'.$thirdparty->id.'">'."\n";
2316 print '<input type="hidden" name="email" value="'.$thirdparty->email.'">'."\n";
2317 $labeldesc = $langs->trans("PaymentSubscription");
2318 if (GETPOST('desc', 'alpha')) {
2319 $labeldesc = GETPOST('desc', 'alpha');
2320 }
2321 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
2322}
2323
2324if ($source == 'boothlocation') {
2325 dol_syslog("newpayment.php source=boothlocation", LOG_DEBUG);
2326
2327 $found = true;
2328 $langs->load("members");
2329
2330 if (GETPOST('fulltag', 'alpha')) {
2331 $fulltag = GETPOST('fulltag', 'alpha');
2332 } else {
2333 $fulltag = 'BOO='.GETPOST("booth").'.DAT='.dol_print_date(dol_now(), '%Y%m%d%H%M%S');
2334 if (!empty($TAG)) {
2335 $tag = $TAG;
2336 $fulltag .= '.TAG='.$TAG;
2337 }
2338 }
2339 $fulltag = dol_string_unaccent($fulltag);
2340
2341 // Creditor
2342 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
2343 print '</td><td class="CTableRow2"><b>'.$creditor.'</b>';
2344 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
2345 print '</td></tr>'."\n";
2346
2347 // Debitor
2348 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Attendee");
2349 print '</td><td class="CTableRow2"><b>';
2350 print $thirdparty->name;
2351 print '</b>';
2352 print '</td></tr>'."\n";
2353
2354 // Object
2355 $text = '<b>'.$langs->trans("PaymentBoothLocation").'</b>';
2356 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
2357 print '</td><td class="CTableRow2">'.$text;
2358 print '<input type="hidden" name="source" value="'.dol_escape_htmltag($source).'">';
2359 print '<input type="hidden" name="ref" value="'.dol_escape_htmltag((string) $invoice->id).'">';
2360 print '</td></tr>'."\n";
2361
2362 // Amount
2363 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
2364 print '</td><td class="CTableRow2">';
2365 $valtoshow = $amount;
2366 print '<b class="amount">'.price($valtoshow, 1, $langs, 1, -1, -1, $currency).'</b>'; // Price with currency
2367 print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
2368 print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
2369 print '<input type="hidden" name="currency" value="'.$currency.'">';
2370 print '</td></tr>'."\n";
2371
2372 // Tag
2373 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("PaymentCode");
2374 print '</td><td class="CTableRow2"><b style="word-break: break-all;">'.$fulltag.'</b>';
2375 print '<input type="hidden" name="tag" value="'.$tag.'">';
2376 print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
2377 print '</td></tr>'."\n";
2378
2379 // Shipping address
2380 $shipToName = $thirdparty->getFullName($langs);
2381 $shipToStreet = $thirdparty->address;
2382 $shipToCity = $thirdparty->town;
2383 $shipToState = $thirdparty->state_code;
2384 $shipToCountryCode = $thirdparty->country_code;
2385 $shipToZip = $thirdparty->zip;
2386 $shipToStreet2 = '';
2387 $phoneNum = $thirdparty->phone;
2388 if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip) {
2389 print '<!-- Shipping address information -->';
2390 print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
2391 print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
2392 print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
2393 print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
2394 print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
2395 print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
2396 print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
2397 print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
2398 } else {
2399 print '<!-- Shipping address not complete, so we don t use it -->'."\n";
2400 }
2401 print '<input type="hidden" name="thirdparty_id" value="'.$thirdparty->id.'">'."\n";
2402 print '<input type="hidden" name="email" value="'.$thirdparty->email.'">'."\n";
2403 $labeldesc = $langs->trans("PaymentSubscription");
2404 if (GETPOST('desc', 'alpha')) {
2405 $labeldesc = GETPOST('desc', 'alpha');
2406 }
2407 print '<input type="hidden" name="desc" value="'.dol_escape_htmltag($labeldesc).'">'."\n";
2408}
2409
2410if (!$found && !$mesg) {
2411 $mesg = $langs->trans("ErrorBadParameters");
2412}
2413
2414if ($mesg) {
2415 print '<tr><td align="center" colspan="2"><br><div class="warning">'.dol_escape_htmltag($mesg, 1, 1, 'br').'</div></td></tr>'."\n";
2416}
2417
2418print '</table>'."\n";
2419print "\n";
2420
2421
2422// Show all payment mode buttons (Stripe, Paypal, ...)
2423if ($action != 'dopayment') {
2424 dol_syslog("newpayment.php action is not dopayment so we show all payment modes", LOG_DEBUG);
2425
2426 if ($found && !$error) { // We are in a management option and no error
2427 // Check status of the object (Invoice) to verify if it is paid by external payment modules (ie Payzen, ...)
2428 $parameters = [
2429 'source' => $source,
2430 'object' => $object
2431 ];
2432 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
2433 $reshook = $hookmanager->executeHooks('doCheckStatus', $parameters, $object, $action);
2434 if ($reshook < 0) {
2435 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2436 } elseif ($reshook > 0) {
2437 print $hookmanager->resPrint;
2438 }
2439
2440 if ($source == 'order' && $object->billed) {
2441 print '<br><br><div class="amountpaymentcomplete size12x wrapimp">'.$langs->trans("OrderBilled").'</div>';
2442 } elseif ($source == 'invoice' && $object->paye) {
2443 print '<br><br><div class="amountpaymentcomplete size12x wrapimp">'.$langs->trans("InvoicePaid").'</div>';
2444 } elseif ($source == 'donation' && $object->paid) {
2445 print '<br><br><div class="amountpaymentcomplete size12x wrapimp">'.$langs->trans("DonationPaid").'</div>';
2446 } else {
2447 // Membership can be paid and we still allow to make renewal
2448 if (($source == 'member' || $source == 'membersubscription') && $object->datefin > dol_now()) {
2449 $langs->load("members");
2450 print '<br><div class="amountpaymentcomplete size12x wrapimp">';
2451 $s = $langs->trans("MembershipPaid", '{s1}');
2452 print str_replace('{s1}', '<span class="nobold">'.dol_print_date($object->datefin, 'day').'</span>', $s);
2453 print '</div>';
2454 print '<div class="opacitymedium margintoponly">'.$langs->trans("PaymentWillBeRecordedForNextPeriod").'</div>';
2455 print '<br>';
2456 }
2457
2458 // Buttons for all payments registration methods
2459
2460 // This hook is used to add Button to newpayment.php for external payment modules (ie Payzen, ...)
2461 $parameters = [
2462 'paymentmethod' => $paymentmethod
2463 ];
2464 $reshook = $hookmanager->executeHooks('doAddButton', $parameters, $object, $action);
2465 if ($reshook < 0) {
2466 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2467 } elseif ($reshook >= 0) {
2468 print $hookmanager->resPrint;
2469 }
2470
2471 if ((empty($paymentmethod) || $paymentmethod == 'paybox') && isModEnabled('paybox')) {
2472 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").'">';
2473 print '<br>';
2474 print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span>';
2475 print '</div>';
2476 print '<script>
2477 $( document ).ready(function() {
2478 $("#div_dopayment_paybox").click(function(){
2479 $("#dopayment_paybox").click();
2480 });
2481 $("#dopayment_paybox").click(function(e){
2482 $("#div_dopayment_paybox").css( \'cursor\', \'wait\' );
2483 e.stopPropagation();
2484 });
2485 });
2486 </script>
2487 ';
2488 }
2489
2490 if ((empty($paymentmethod) || $paymentmethod == 'stripe') && isModEnabled('stripe')) {
2491 $showbutton = 1;
2492 if (getDolGlobalString(strtoupper($source).'_FORCE_DISABLE_STRIPE')) { // Example: MEMBER_FORCE_DISABLE_STRIPE
2493 $showbutton = 0;
2494 }
2495
2496 if ($showbutton) {
2497 // 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.
2498 // 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).
2499 $noidempotency_key = (GETPOSTISSET('noidempotency') ? GETPOSTINT('noidempotency') : (getDolGlobalInt('STRIPE_USE_IDEMPOTENCY_BY_DEFAULT') ? 0 : 1));
2500
2501 print '<div class="button buttonpayment" id="div_dopayment_stripe">';
2502 print '<span class="fa fa-credit-card"></span> ';
2503 print '<input class="" type="submit" id="dopayment_stripe" name="dopayment_stripe" value="'.$langs->trans("StripeDoPayment").'">';
2504 print '<input type="hidden" name="noidempotency" value="'.$noidempotency_key.'">';
2505 print '<br>';
2506 print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span>';
2507 print '</div>';
2508 print '<script>
2509 $( document ).ready(function() {
2510 $("#div_dopayment_stripe").click(function(){
2511 $("#dopayment_stripe").click();
2512 });
2513 $("#dopayment_stripe").click(function(e){
2514 $("#div_dopayment_stripe").css( \'cursor\', \'wait\' );
2515 e.stopPropagation();
2516 return true;
2517 });
2518 });
2519 </script>
2520 ';
2521 }
2522 }
2523
2524 if ((empty($paymentmethod) || $paymentmethod == 'paypal') && isModEnabled('paypal')) {
2525 if (!getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY')) {
2526 $conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY = 'integral';
2527 }
2528
2529 $showbutton = 1;
2530 if (getDolGlobalString(strtoupper($source).'_FORCE_DISABLE_PAYPAL')) { // Example: MEMBER_FORCE_DISABLE_PAYPAL
2531 $showbutton = 0;
2532 }
2533
2534 if ($showbutton) {
2535 print '<div class="button buttonpayment" id="div_dopayment_paypal">';
2536 if (getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY') != 'integral') {
2537 print '<div style="line-height: 1em">&nbsp;</div>';
2538 }
2539 print '<span class="fab fa-paypal"></span> <input class="" type="submit" id="dopayment_paypal" name="dopayment_paypal" value="'.$langs->trans("PaypalDoPayment").'">';
2540 if (getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY') == 'integral') {
2541 print '<br>';
2542 print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span><span class="buttonpaymentsmall"> - </span>';
2543 print '<span class="buttonpaymentsmall">'.$langs->trans("PayPalBalance").'</span>';
2544 }
2545 //if (getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY') == 'paypalonly') {
2546 //print '<br>';
2547 //print '<span class="buttonpaymentsmall">'.$langs->trans("PayPalBalance").'"></span>';
2548 //}
2549 print '</div>';
2550 print '<script>
2551 $( document ).ready(function() {
2552 $("#div_dopayment_paypal").click(function(){
2553 $("#dopayment_paypal").click();
2554 });
2555 $("#dopayment_paypal").click(function(e){
2556 $("#div_dopayment_paypal").css( \'cursor\', \'wait\' );
2557 e.stopPropagation();
2558 return true;
2559 });
2560 });
2561 </script>
2562 ';
2563 }
2564 }
2565 }
2566 } else {
2567 dol_print_error_email('ERRORNEWPAYMENT');
2568 }
2569} else {
2570 // Print
2571}
2572
2573print '</td></tr>'."\n";
2574
2575print '</table>'."\n";
2576
2577print '</form>'."\n";
2578print '</div>'."\n";
2579
2580print '<br>';
2581
2582
2583
2584// Add more content on page for some services
2585if (preg_match('/^dopayment/', $action)) { // If we choose/clicked on the payment mode
2586 dol_syslog("newpayment.php action is dopayment... because we clicked on a payment mode - amount = ".$amount);
2587
2588 // Save some data for the paymentok
2589 $remoteip = getUserRemoteIP();
2590 $_SESSION["currencyCodeType"] = $currency;
2591 $_SESSION["FinalPaymentAmt"] = $amount;
2592 $_SESSION['ipaddress'] = ($remoteip ? $remoteip : 'unknown'); // Payer ip
2593 $_SESSION["paymentType"] = '';
2594
2595 $stripecu = null;
2596
2597 // For Stripe
2598 if (GETPOST('dopayment_stripe', 'alpha')) {
2599 // Personalized checkout
2600 print '<style>
2605 .StripeElement {
2606 background-color: white;
2607 padding: 8px 12px;
2608 border-radius: 4px;
2609 border: 1px solid transparent;
2610 box-shadow: 0 1px 3px 0 #e6ebf1;
2611 -webkit-transition: box-shadow 150ms ease;
2612 transition: box-shadow 150ms ease;
2613 }
2614
2615 .StripeElement--focus {
2616 box-shadow: 0 1px 3px 0 #cfd7df;
2617 }
2618
2619 .StripeElement--invalid {
2620 border-color: #fa755a;
2621 }
2622
2623 .StripeElement--webkit-autofill {
2624 background-color: #fefde5 !important;
2625 }
2626 </style>';
2627
2628 //print '<br>';
2629
2630 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";
2631 print '<form action="'.$_SERVER['REQUEST_URI'].'" method="POST" id="payment-form">'."\n";
2632
2633 print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
2634 print '<input type="hidden" name="dopayment_stripe" value="1">'."\n";
2635 print '<input type="hidden" name="action" value="charge">'."\n";
2636 print '<input type="hidden" name="tag" value="'.$TAG.'">'."\n";
2637 print '<input type="hidden" name="s" value="'.$source.'">'."\n";
2638 print '<input type="hidden" name="ref" value="'.$REF.'">'."\n";
2639 print '<input type="hidden" name="fulltag" value="'.$FULLTAG.'">'."\n";
2640 print '<input type="hidden" name="suffix" value="'.$suffix.'">'."\n";
2641 print '<input type="hidden" name="securekey" value="'.$SECUREKEY.'">'."\n";
2642 print '<input type="hidden" name="e" value="'.$entity.'" />'."\n";
2643 print '<input type="hidden" name="amount" value="'.$amount.'">'."\n";
2644 print '<input type="hidden" name="currency" value="'.$currency.'">'."\n";
2645 //print '<input type="hidden" name="forcesandbox" value="'.GETPOSTINT('forcesandbox').'" />';
2646 print '<input type="hidden" name="email" value="'.GETPOST('email', 'alpha').'" />';
2647 print '<input type="hidden" name="thirdparty_id" value="'.GETPOSTINT('thirdparty_id').'" />';
2648 print '<input type="hidden" name="lang" value="'.$getpostlang.'">';
2649
2650 // Make some check on amount: We accept an amount that is different to allow to pay an existing invoice partially or
2651 // to allow to pay a membership with open amount, but for a payment of an order, we have no reason to accept partial payment.
2652 $checkamount = 1;
2653 $tmptag = dolExplodeIntoArray($fulltag, '.', '=');
2654 if (array_key_exists('ORD', $tmptag) && (int) $tmptag['ORD'] > 0) {
2655 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2656 $object = new Commande($db);
2657 $result = $object->fetch((int) $tmptag['ORD']);
2658 if ($result > 0) {
2659 if ($object->total_ttc != $amount) {
2660 $checkamount = 0;
2661 }
2662 } else {
2663 $checkamount = 0;
2664 }
2665 }
2666 if (!$checkamount) {
2667 dol_syslog("Hack attempt detected", LOG_WARNING);
2668 setEventMessages('Bad value for amount. Reported as a hack attempt.', null, 'errors');
2669 }
2670
2671 if ($checkamount && (getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') || getDolGlobalString('STRIPE_USE_NEW_CHECKOUT'))) { // Use a SCA ready method
2672 require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
2673
2674 $service = 'StripeLive';
2675 $servicestatus = 1;
2676 if (!getDolGlobalString('STRIPE_LIVE')/* || GETPOST('forcesandbox', 'alpha') */) {
2677 $service = 'StripeTest';
2678 $servicestatus = 0;
2679 }
2680
2681 $stripe = new Stripe($db);
2682 $stripeacc = $stripe->getStripeAccount($service);
2683 if (is_object($object) && is_object($object->thirdparty)) {
2684 $stripecu = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1);
2685 }
2686
2687 if (getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
2688 dol_syslog("newpayment.php Create a Paymentintent for amount=".$amount, LOG_DEBUG);
2689
2690 // 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.
2691 // 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).
2692 $noidempotency_key = (GETPOSTISSET('noidempotency') ? GETPOSTINT('noidempotency') : (getDolGlobalInt('STRIPE_USE_IDEMPOTENCY_BY_DEFAULT') ? 0 : 1));
2693
2694 $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);
2695 // The paymentintnent has status 'requires_payment_method' (even if paymentintent was already paid)
2696 //var_dump($paymentintent);
2697 if ($stripe->error) {
2698 setEventMessages($stripe->error, null, 'errors');
2699 }
2700 }
2701 }
2702
2703 // Note:
2704 // $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = 1 = use intent object (default value, suggest card payment mode only)
2705 // $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = 2 = use payment object (suggest both card payment mode but also sepa, ...)
2706
2707 print '
2708 <table id="dolpaymenttable" summary="Payment form" class="center centpercent">
2709 <tbody><tr><td class="textpublicpayment">';
2710
2711 if (getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
2712 print '<div id="payment-request-button"><!-- A Stripe Element will be inserted here. --></div>';
2713 }
2714
2715 print '<div class="form-row '.(getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2 ? 'center' : 'left').'">';
2716 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) {
2717 print '<label for="card-element">'.$langs->trans("CreditOrDebitCard").'</label>';
2718 print '<br><input id="cardholder-name" class="marginbottomonly" name="cardholder-name" value="" type="text" placeholder="'.$langs->trans("CardOwner").'" autocomplete="off" spellcheck="false" autofocus required>';
2719 }
2720
2721 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) {
2722 print '<div id="card-element">
2723 <!-- a Stripe Element will be inserted here. -->
2724 </div>';
2725 }
2726 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) {
2727 print '<div id="payment-element">
2728 <!-- a Stripe Element will be inserted here. -->
2729 </div>';
2730 }
2731
2732 print '<!-- Used to display form errors -->
2733 <div id="card-errors" role="alert"></div>
2734 </div>';
2735
2736 print '<br>';
2737 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>';
2738 print '<img id="hourglasstopay" class="hidden" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/working.gif">';
2739
2740 print '</td></tr></tbody>';
2741 print '</table>';
2742 //}
2743
2744 if (getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
2745 if (empty($paymentintent)) {
2746 print '<center>'.$langs->trans("Error").' - Failed to get PaymentIntent</center>';
2747 } else {
2748 print '<input type="hidden" name="paymentintent_id" value="'.$paymentintent->id.'">';
2749 //$_SESSION["paymentintent_id"] = $paymentintent->id;
2750 }
2751 }
2752
2753 print '</form>'."\n";
2754
2755
2756 // JS Code for Stripe
2757 if (empty($stripearrayofkeys['publishable_key'])) {
2758 $langs->load("errors");
2759 print info_admin($langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("Stripe")), 0, 0, 'error marginleftonly marginrightonly');
2760 } else {
2761 print '<!-- JS Code for Stripe components -->';
2762 print '<script src="https://js.stripe.com/v3/"></script>'."\n";
2763 print '<!-- urllogofull = '.$urllogofull.' -->'."\n";
2764
2765 // Code to ask the credit card. This use the default "API version". No way to force API version when using JS code.
2766 print '<script type="text/javascript">'."\n";
2767
2768 if (getDolGlobalString('STRIPE_USE_NEW_CHECKOUT')) {
2769 $amountstripe = $amount;
2770
2771 // Correct the amount according to unit of currency
2772 // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support
2773 $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
2774 if (!in_array($currency, $arrayzerounitcurrency)) {
2775 $amountstripe *= 100;
2776 }
2777
2778 $ipaddress = getUserRemoteIP();
2779 $metadata = array('dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress);
2780 if (is_object($object)) {
2781 $metadata['dol_type'] = $object->element;
2782 $metadata['dol_id'] = $object->id;
2783
2784 $ref = $object->ref;
2785 }
2786
2787 try {
2788 $arrayforpaymentintent = array(
2789 'description' => 'Stripe payment: '.$FULLTAG.($ref ? ' ref='.$ref : ''),
2790 "metadata" => $metadata
2791 );
2792 if ($TAG) {
2793 $arrayforpaymentintent["statement_descriptor"] = dol_trunc($TAG, 10, 'right', 'UTF-8', 1); // 22 chars that appears on bank receipt (company + description)
2794 }
2795
2796 $arrayforcheckout = array(
2797 'payment_method_types' => array('card'),
2798 'line_items' => array(array(
2799 'price_data' => array(
2800 'currency' => $currency,
2801 'unit_amount' => $amountstripe,
2802 'product_data' => array(
2803 'name' => $langs->transnoentitiesnoconv("Payment").' '.$TAG, // Label of product line
2804 'description' => 'Stripe payment: '.$FULLTAG.($ref ? ' ref='.$ref : ''),
2805 //'images' => array($urllogofull),
2806 ),
2807 ),
2808 'quantity' => 1,
2809 )),
2810 'mode' => 'payment',
2811 'client_reference_id' => $FULLTAG,
2812 'success_url' => $urlok,
2813 'cancel_url' => $urlko,
2814 'payment_intent_data' => $arrayforpaymentintent
2815 );
2816 if ($stripecu) {
2817 $arrayforcheckout['customer'] = $stripecu;
2818 } elseif (GETPOST('email', 'alpha') && isValidEmail(GETPOST('email', 'alpha'))) {
2819 $arrayforcheckout['customer_email'] = GETPOST('email', 'alpha');
2820 }
2821
2822 dol_syslog("We create a stripe session with \Stripe\Checkout\Session::create for amountstripe=".$amountstripe);
2823
2824 $sessionstripe = \Stripe\Checkout\Session::create($arrayforcheckout);
2825
2826 dol_syslog("sessionstripe=".$sessionstripe->id);
2827
2828
2829 $remoteip = getUserRemoteIP();
2830
2831 // Save some data for the paymentok
2832 $_SESSION["currencyCodeType"] = $currency;
2833 $_SESSION["paymentType"] = '';
2834 $_SESSION["FinalPaymentAmt"] = $amount;
2835 $_SESSION['ipaddress'] = ($remoteip ? $remoteip : 'unknown'); // Payer ip
2836 $_SESSION['payerID'] = is_object($stripecu) ? $stripecu->id : '';
2837 $_SESSION['TRANSACTIONID'] = $sessionstripe->id;
2838 } catch (Exception $e) {
2839 print $e->getMessage();
2840 } ?>
2841 // Code for payment with option STRIPE_USE_NEW_CHECKOUT set
2842
2843 // Create a Stripe client.
2844 <?php
2845 if (empty($stripeacc)) {
2846 ?>
2847 var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php?>');
2848 <?php
2849 } else {
2850 ?>
2851 var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php?>', { stripeAccount: '<?php echo $stripeacc; ?>' });
2852 <?php
2853 } ?>
2854
2855 // Create an instance of Elements
2856 var elements = stripe.elements();
2857
2858 // Custom styling can be passed to options when creating an Element.
2859 // (Note that this demo uses a wider set of styles than the guide below.)
2860 var style = {
2861 base: {
2862 color: '#32325d',
2863 lineHeight: '24px',
2864 fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
2865 fontSmoothing: 'antialiased',
2866 fontSize: '16px',
2867 '::placeholder': {
2868 color: '#aab7c4'
2869 }
2870 },
2871 invalid: {
2872 color: '#fa755a',
2873 iconColor: '#fa755a'
2874 }
2875 }
2876
2877 var cardElement = elements.create('card', {style: style});
2878
2879 // Comment this to avoid the redirect
2880 stripe.redirectToCheckout({
2881 // Make the id field from the Checkout Session creation API response
2882 // available to this file, so you can provide it as parameter here
2883 // instead of the {{CHECKOUT_SESSION_ID}} placeholder.
2884 sessionId: '<?php print $sessionstripe->id; ?>'
2885 }).then(function (result) {
2886 // If `redirectToCheckout` fails due to a browser or network
2887 // error, display the localized error message to your customer
2888 // using `result.error.message`.
2889 });
2890
2891
2892 <?php
2893 } elseif (getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) { // default value is 1
2894 ?>
2895 // Code for payment with option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION set to 1 or 2
2896
2897 // Create a Stripe client.
2898 <?php
2899 if (empty($stripeacc)) {
2900 ?>
2901 var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php?>');
2902 <?php
2903 } else {
2904 ?>
2905 var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php?>', { stripeAccount: '<?php echo $stripeacc; ?>' });
2906 <?php
2907 } ?>
2908
2909 <?php
2910 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) { // default is 1
2911 ?>
2912 var cardButton = document.getElementById('buttontopay');
2913 var clientSecret = cardButton.dataset.secret;
2914 var options = { clientSecret: clientSecret };
2915
2916 // Create an instance of Elements
2917 var elements = stripe.elements(options);
2918 <?php
2919 } else {
2920 ?>
2921 // Create an instance of Elements
2922 var elements = stripe.elements();
2923 <?php
2924 } ?>
2925
2926 // Custom styling can be passed to options when creating an Element.
2927 // (Note that this demo uses a wider set of styles than the guide below.)
2928 var style = {
2929 base: {
2930 color: '#32325d',
2931 lineHeight: '24px',
2932 fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
2933 fontSmoothing: 'antialiased',
2934 fontSize: '16px',
2935 '::placeholder': {
2936 color: '#aab7c4'
2937 }
2938 },
2939 invalid: {
2940 color: '#fa755a',
2941 iconColor: '#fa755a'
2942 }
2943 }
2944
2945 <?php
2946 if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2) { // Default is 1.
2947 ?>
2948 var paymentElement = elements.create("payment");
2949
2950 // Add an instance of the card Element into the div #payment-element
2951 paymentElement.mount("#payment-element");
2952
2953 // Handle form submission
2954 var cardButton = document.getElementById('buttontopay');
2955
2956 cardButton.addEventListener('click', function(event) {
2957 console.log("We click on buttontopay");
2958 event.preventDefault();
2959
2960 /* Disable button to pay and show hourglass cursor */
2961 jQuery('#hourglasstopay').show();
2962 jQuery('#buttontopay').hide();
2963
2964 stripe.confirmPayment({
2965 elements,confirmParams: {
2966 return_url: '<?php echo $urlok; ?>',
2967 payment_method_data: {
2968 billing_details: {
2969 name: 'test'
2970 <?php if (GETPOST('email', 'alpha') || (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->email))) {
2971 ?>, email: '<?php echo dol_escape_js(GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $object->thirdparty->email); ?>'<?php
2972 } ?>
2973 <?php if (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->phone)) {
2974 ?>, phone: '<?php echo dol_escape_js($object->thirdparty->phone); ?>'<?php
2975 } ?>
2976 <?php if (is_object($object) && is_object($object->thirdparty)) {
2977 ?>, address: {
2978 city: '<?php echo dol_escape_js($object->thirdparty->town); ?>',
2979 <?php if ($object->thirdparty->country_code) {
2980 ?>country: '<?php echo dol_escape_js($object->thirdparty->country_code); ?>',<?php
2981 } ?>
2982 line1: '<?php echo dol_escape_js(preg_replace('/\s\s+/', ' ', $object->thirdparty->address)); ?>',
2983 postal_code: '<?php echo dol_escape_js($object->thirdparty->zip); ?>'
2984 }
2985 <?php
2986 } ?>
2987 }
2988 },
2989 save_payment_method:<?php if ($stripecu) {
2990 print 'true';
2991 } else {
2992 print 'false';
2993 } ?> /* true when a customer was provided when creating payment intent. true ask to save the card */
2994 },
2995 }
2996 ).then(function(result) {
2997 console.log(result);
2998 if (result.error) {
2999 console.log("Error on result of handleCardPayment");
3000 jQuery('#buttontopay').show();
3001 jQuery('#hourglasstopay').hide();
3002 // Inform the user if there was an error
3003 var errorElement = document.getElementById('card-errors');
3004 console.log(result);
3005 errorElement.textContent = result.error.message;
3006 } else {
3007 // The payment has succeeded. Display a success message.
3008 console.log("No error on result of handleCardPayment, so we submit the form");
3009 // Submit the form
3010 jQuery('#buttontopay').hide();
3011 jQuery('#hourglasstopay').show();
3012 // Send form (action=charge that will do nothing)
3013 jQuery('#payment-form').submit();
3014 }
3015 });
3016
3017 });
3018 <?php
3019 } else {
3020 ?>
3021 var cardElement = elements.create('card', {style: style});
3022
3023 // Add an instance of the card Element into the div #card-element
3024 cardElement.mount('#card-element');
3025
3026 // Handle real-time validation errors from the card Element.
3027 cardElement.addEventListener('change', function(event) {
3028 var displayError = document.getElementById('card-errors');
3029 if (event.error) {
3030 console.log("Show event error (like 'Incorrect card number', ...)");
3031 displayError.textContent = event.error.message;
3032 } else {
3033 console.log("Reset error message");
3034 displayError.textContent = '';
3035 }
3036 });
3037
3038 // Handle form submission
3039 var cardholderName = document.getElementById('cardholder-name');
3040 var cardButton = document.getElementById('buttontopay');
3041 var clientSecret = cardButton.dataset.secret;
3042
3043 cardButton.addEventListener('click', function(event) {
3044 console.log("We click on buttontopay");
3045 event.preventDefault();
3046
3047 if (cardholderName.value == '')
3048 {
3049 console.log("Field Card holder is empty");
3050 var displayError = document.getElementById('card-errors');
3051 displayError.textContent = '<?php print dol_escape_js($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CardOwner"))); ?>';
3052 }
3053 else
3054 {
3055 /* Disable button to pay and show hourglass cursor */
3056 jQuery('#hourglasstopay').show();
3057 jQuery('#buttontopay').hide();
3058
3059 stripe.handleCardPayment(
3060 clientSecret, cardElement, {
3061 payment_method_data: {
3062 billing_details: {
3063 name: cardholderName.value
3064 <?php if (GETPOST('email', 'alpha') || (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->email))) {
3065 ?>, email: '<?php echo dol_escape_js(GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $object->thirdparty->email); ?>'<?php
3066 } ?>
3067 <?php if (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->phone)) {
3068 ?>, phone: '<?php echo dol_escape_js($object->thirdparty->phone); ?>'<?php
3069 } ?>
3070 <?php if (is_object($object) && is_object($object->thirdparty)) {
3071 ?>, address: {
3072 city: '<?php echo dol_escape_js($object->thirdparty->town); ?>',
3073 <?php if ($object->thirdparty->country_code) {
3074 ?>country: '<?php echo dol_escape_js($object->thirdparty->country_code); ?>',<?php
3075 } ?>
3076 line1: '<?php echo dol_escape_js(preg_replace('/\s\s+/', ' ', $object->thirdparty->address)); ?>',
3077 postal_code: '<?php echo dol_escape_js($object->thirdparty->zip); ?>'
3078 }
3079 <?php
3080 } ?>
3081 }
3082 },
3083 save_payment_method:<?php if ($stripecu) {
3084 print 'true';
3085 } else {
3086 print 'false';
3087 } ?> /* true when a customer was provided when creating payment intent. true ask to save the card */
3088 }
3089 ).then(function(result) {
3090 console.log(result);
3091 if (result.error) {
3092 console.log("Error on result of handleCardPayment");
3093 jQuery('#buttontopay').show();
3094 jQuery('#hourglasstopay').hide();
3095 // Inform the user if there was an error
3096 var errorElement = document.getElementById('card-errors');
3097 errorElement.textContent = result.error.message;
3098 } else {
3099 // The payment has succeeded. Display a success message.
3100 console.log("No error on result of handleCardPayment, so we submit the form");
3101 // Submit the form
3102 jQuery('#buttontopay').hide();
3103 jQuery('#hourglasstopay').show();
3104 // Send form (action=charge that will do nothing)
3105 jQuery('#payment-form').submit();
3106 }
3107 });
3108 }
3109 });
3110 <?php
3111 } ?>
3112
3113 <?php
3114 }
3115
3116 print '</script>';
3117 }
3118 }
3119
3120 // For any other payment services
3121 // This hook can be used to show the embedded form to make payments with external payment modules (ie Payzen, ...)
3122 $parameters = [
3123 'paymentmethod' => $paymentmethod,
3124 'amount' => $amount,
3125 'currency' => $currency,
3126 'tag' => GETPOST("tag", 'alpha'),
3127 'dopayment' => GETPOST('dopayment', 'alpha')
3128 ];
3129 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
3130 $reshook = $hookmanager->executeHooks('doPayment', $parameters, $object, $action);
3131 if ($reshook < 0) {
3132 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
3133 } elseif ($reshook > 0) {
3134 print $hookmanager->resPrint;
3135 }
3136}
3137
3138if (!$ws) {
3139 htmlPrintOnlineFooter($mysoc, $langs, 1, $suffix, $object);
3140}
3141
3142llxFooter('', 'public');
3143
3144$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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 donations.
Definition don.class.php:41
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
Class to manage hooks.
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.
global $mysoc
dol_is_file($pathoffile)
Return if path is a file.
dol_now($mode='gmt')
Return date for now.
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_sanitizePathName($str, $newstr='_', $unaccent=0, $allowdash=0)
Clean a string to use it as a path name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
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_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
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.
isModEnabled($module)
Is Dolibarr module enabled.
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_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
Abort invoice creation with a given error message.
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:128
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,...