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