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