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