21if (!defined(
'NOLOGIN')) {
24if (!defined(
'NOCSRFCHECK')) {
25 define(
"NOCSRFCHECK", 1);
27if (!defined(
'NOIPCHECK')) {
28 define(
'NOIPCHECK',
'1');
30if (!defined(
'NOBROWSERNOTIF')) {
31 define(
'NOBROWSERNOTIF',
'1');
35$entity = (!empty($_GET[
'entity']) ? (int) $_GET[
'entity'] : (!empty($_POST[
'entity']) ? (int) $_POST[
'entity'] : 1));
36if (is_numeric($entity)) {
37 define(
"DOLENTITY", $entity);
41if (!defined(
'USESUFFIXINLOG')) {
42 define(
'USESUFFIXINLOG',
'_stripeipn');
46require
'../../main.inc.php';
54require_once DOL_DOCUMENT_ROOT.
'/core/lib/admin.lib.php';
55require_once DOL_DOCUMENT_ROOT.
'/user/class/user.class.php';
56require_once DOL_DOCUMENT_ROOT.
'/core/class/ccountry.class.php';
57require_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
58require_once DOL_DOCUMENT_ROOT.
'/compta/paiement/class/paiement.class.php';
59require_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
60require_once DOL_DOCUMENT_ROOT.
'/compta/bank/class/account.class.php';
61require_once DOL_DOCUMENT_ROOT.
'/compta/prelevement/class/bonprelevement.class.php';
62require_once DOL_DOCUMENT_ROOT.
'/societe/class/societe.class.php';
63require_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
64require_once DOL_DOCUMENT_ROOT.
'/includes/stripe/stripe-php/init.php';
65require_once DOL_DOCUMENT_ROOT.
'/stripe/class/stripe.class.php';
68if (GETPOSTISSET(
'connect')) {
69 if (GETPOSTISSET(
'test')) {
71 $service =
'StripeTest';
75 $service =
'StripeLive';
79 if (GETPOSTISSET(
'test')) {
81 $service =
'StripeTest';
85 $service =
'StripeLive';
94if (empty($endpoint_secret)) {
117$payload = @file_get_contents(
"php://input");
118$sig_header = empty($_SERVER[
"HTTP_STRIPE_SIGNATURE"]) ?
'' : $_SERVER[
"HTTP_STRIPE_SIGNATURE"];
122 $fh = fopen(DOL_DATA_ROOT.
'/dolibarr_stripeipn_payload.log',
'w+');
124 fwrite($fh,
dol_print_date(
dol_now(
'gmt'),
'standard').
' IPN Called. service='.$service.
' HTTP_STRIPE_SIGNATURE='.$sig_header.
"\n");
125 fwrite($fh, $payload);
127 dolChmod(DOL_DATA_ROOT.
'/dolibarr_stripeipn_payload.log');
134 $event = \Stripe\Webhook::constructEvent($payload, $sig_header, $endpoint_secret);
135}
catch (UnexpectedValueException $e) {
137 dol_syslog(
"***** Stripe IPN was called with UnexpectedValueException (invalid payload) service=".$service);
138 dol_syslog(
"***** Stripe IPN was called with UnexpectedValueException (invalid payload) service=".$service, LOG_DEBUG, 0,
'_payment');
141 dol_syslog(
"***** Stripe IPN was called with SignatureVerificationException service=".$service);
142 dol_syslog(
"***** Stripe IPN was called with SignatureVerificationException service=".$service, LOG_DEBUG, 0,
'_payment');
143 httponly_accessforbidden(
'Invalid signature. May be a hook for an event created by another Stripe env or a hack attempt ? Check setup of your keys whsec_...', 400);
145 dol_syslog(
"***** Stripe IPN was called with Exception (".$e->getMessage().
") service=".$service);
146 dol_syslog(
"***** Stripe IPN was called with Exception (".$e->getMessage().
") service=".$service, LOG_DEBUG, 0,
'_payment');
155if (
isModEnabled(
'multicompany') && !empty(
$conf->stripeconnect->enabled) && isset($mc) && is_object($mc)) {
156 $sql =
"SELECT entity";
157 $sql .=
" FROM ".MAIN_DB_PREFIX.
"oauth_token";
158 $sql .=
" WHERE service = '".$db->escape($service).
"' and tokenstring LIKE '%".
$db->escape(
$db->escapeforlike($event->account)).
"%'";
160 dol_syslog(get_class(
$db).
"::fetch", LOG_DEBUG, 0,
'_payment');
162 $result =
$db->query($sql);
164 if (
$db->num_rows($result)) {
165 $obj =
$db->fetch_object($result);
173 $ret = $mc->switchEntity($key);
191dol_syslog(
"***** Stripe IPN was called with event->type=".$event->type.
" service=".$service);
192dol_syslog(
"***** Stripe IPN was called with event->type=".$event->type.
" service=".$service, LOG_DEBUG, 0,
'_payment');
197$hookmanager->initHooks(array(
'stripeipn'));
198$parameters = array(
'event' => $event,
'servicestatus' => $servicestatus,
'service' => $service);
199$reshook = $hookmanager->executeHooks(
'stripeWebhookEvent', $parameters, $event->data->object, $event->type);
202 http_response_code(200);
207if ($event->type ==
'payout.created' &&
getDolGlobalString(
'STRIPE_AUTO_RECORD_PAYOUT')) {
214 $result =
dolibarr_set_const(
$db, $service.
"_NEXTPAYOUT",
date(
'Y-m-d H:i:s', $event->data->object->arrival_date),
'chaine', 0,
'',
$conf->entity);
217 $subject =
'['.$societeName.
'] Notification - Stripe payout scheduled';
218 if (!empty($user->email)) {
229 $message =
"A bank transfer of ".price2num($event->data->object->amount / 100).
" ".$event->data->object->currency.
" should arrive in your account the ".
dol_print_date($event->data->object->arrival_date,
'dayhour');
245 $ret = $mailfile->sendfile();
250 http_response_code(500);
253} elseif ($event->type ==
'payout.paid' &&
getDolGlobalString(
'STRIPE_AUTO_RECORD_PAYOUT')) {
261 $langs->load(
"errors");
266 $label = $event->data->object->description.
' - '.
getDolGlobalString(
'STRIPE_AUTO_RECORD_PAYOUT_LABEL',
'autorecord by IPN, see Stripe setup');
267 $amount = $stripe->convertAmount($event->data->object->amount, $currency_code, 1);
269 require_once DOL_DOCUMENT_ROOT.
'/compta/bank/class/account.class.php';
272 $accountfrom->fetch(
getDolGlobalInt(
'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS'));
275 $accountto->fetch(
getDolGlobalInt(
'STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS'));
277 if (($accountto->id != $accountfrom->id) && empty($error)) {
278 $bank_line_id_from = 0;
279 $bank_line_id_to = 0;
286 $numChqOrOpe = $event->data->object->id;
291 $bank_line_id_from = $accountfrom->addline($dateo, $typefrom, $label, -1 * (
float)
price2num($amount), $numChqOrOpe, 0, $user,
'',
'',
'',
null,
'',
null,
'Record payout from public/stripe/ipn.php');
293 if (!($bank_line_id_from > 0)) {
297 $bank_line_id_to = $accountto->addline($dateo, $typeto, $label, (
float)
price2num($amount), $numChqOrOpe, 0, $user,
'',
'',
'',
null,
'',
null,
'Record payout from public/stripe/ipn.php');
299 if (!($bank_line_id_to > 0)) {
305 $result = $accountfrom->add_url_line($bank_line_id_from, $bank_line_id_to, DOL_URL_ROOT.
'/compta/bank/line.php?rowid=',
'(banktransfert)',
'banktransfert');
307 if (!($result > 0)) {
311 $result = $accountto->add_url_line($bank_line_id_to, $bank_line_id_from, DOL_URL_ROOT.
'/compta/bank/line.php?rowid=',
'(banktransfert)',
'banktransfert');
313 if (!($result > 0)) {
325 $subject =
'['.$societeName.
'] Notification - Stripe payout done';
326 if (!empty($user->email)) {
337 $message =
"A bank transfer of ".price2num($event->data->object->amount / 100).
" ".$event->data->object->currency.
" has been done to your account the ".
dol_print_date($event->data->object->arrival_date,
'dayhour');
353 $ret = $mailfile->sendfile();
360 http_response_code(500);
363} elseif ($event->type ==
'customer.source.created') {
365} elseif ($event->type ==
'customer.source.updated') {
367} elseif ($event->type ==
'customer.source.delete') {
369} elseif ($event->type ==
'customer.deleted') {
372 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"societe_account WHERE key_account = '".
$db->escape($event->data->object->id).
"' AND site = 'stripe'";
375} elseif ($event->type ==
'payment_intent.succeeded') {
380 include_once DOL_DOCUMENT_ROOT .
'/compta/paiement/class/paiement.class.php';
381 global $stripearrayofkeysbyenv;
383 $object = $event->data->object;
384 $objectType =
$object->metadata->dol_type;
386 $ipaddress =
$object->metadata->ipaddress;
389 $currencyCodeType = strtoupper(
$object->currency);
390 $paymentmethodstripeid =
$object->payment_method;
391 $customer_id =
$object->customer;
393 $supplierinvoice_id = 0;
395 $paymentTypeCode =
"";
396 $paymentTypeCodeInDolibarr =
"";
398 $payment_amountInDolibarr = 0;
400 dol_syslog(
"Try to find a payment in database for the payment_intent id = ".$TRANSACTIONID);
401 dol_syslog(
"Try to find a payment in database for the payment_intent id = ".$TRANSACTIONID, LOG_DEBUG, 0,
'_payment');
403 $sql =
"SELECT pi.rowid, pi.fk_facture, fk_facture_fourn, fk_salary, pi.fk_prelevement_bons, pi.amount, pi.type, pi.traite";
404 $sql .=
" FROM ".MAIN_DB_PREFIX.
"prelevement_demande as pi";
405 $sql .=
" WHERE pi.ext_payment_id = '".$db->escape($TRANSACTIONID).
"'";
406 $sql .=
" AND pi.ext_payment_site = '".$db->escape($service).
"'";
408 $result =
$db->query($sql);
410 $obj =
$db->fetch_object($result);
412 if ($obj->type ==
'ban') {
414 $directdebitorcreditransfer_id = $obj->fk_prelevement_bons;
416 if ($obj->traite == 1) {
419 $invoice_id = $obj->fk_facture;
420 $supplierinvoice_id = $obj->fk_facture_fourn;
421 $salary_id = $obj->fk_salary;
422 $payment_amountInDolibarr = $obj->amount;
423 $paymentTypeCodeInDolibarr = $obj->type;
425 dol_syslog(
"Found a request in database to pay with direct debit generated (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")");
426 dol_syslog(
"Found a request in database to pay with direct debit generated (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")", LOG_DEBUG, 0,
'_payment');
428 dol_syslog(
"Found a request in database not yet generated (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
"). Was the order deleted after being sent ?", LOG_WARNING);
429 dol_syslog(
"Found a request in database not yet generated (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
"). Was the order deleted after being sent ?", LOG_WARNING, 0,
'_payment');
432 if ($obj->type ==
'card' || empty($obj->type)) {
434 if ($obj->traite == 0) {
436 $invoice_id = $obj->fk_facture;
437 $payment_amountInDolibarr = $obj->amount;
438 $paymentTypeCodeInDolibarr = empty($obj->type) ?
'card' : $obj->type;
440 dol_syslog(
"Found a request in database to pay with card (pdid = ".$pdid.
"). We should fix status traite to 1");
441 dol_syslog(
"Found a request in database to pay with card (pdid = ".$pdid.
"). We should fix status traite to 1", LOG_DEBUG, 0,
'_payment');
443 dol_syslog(
"Found a request in database to pay with card (pdid = ".$pdid.
") already set to traite=1. Nothing to fix.");
444 dol_syslog(
"Found a request in database to pay with card (pdid = ".$pdid.
") already set to traite=1. Nothing to fix.", LOG_DEBUG, 0,
'_payment');
448 dol_syslog(
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.");
449 dol_syslog(
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.", LOG_DEBUG, 0,
'_payment');
450 http_response_code(200);
451 print
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.";
455 http_response_code(500);
456 print
$db->lasterror();
460 if ($paymentTypeCodeInDolibarr) {
463 $stripeacc = $stripearrayofkeysbyenv[$servicestatus][
'secret_key'];
466 dol_syslog(
"Get the Stripe payment object for the payment method id = ".
formatLogObject($paymentmethodstripeid), LOG_DEBUG, 0,
'_payment');
468 $s = new \Stripe\StripeClient($stripeacc);
470 $paymentmethodstripe = $s->paymentMethods->retrieve($paymentmethodstripeid);
471 $paymentTypeCode = $paymentmethodstripe->type;
472 if ($paymentTypeCode ==
"ban" || $paymentTypeCode ==
"sepa_debit") {
473 $paymentTypeCode =
"PRE";
474 } elseif ($paymentTypeCode ==
"card") {
475 $paymentTypeCode =
"CB";
478 $payment_amount = $payment_amountInDolibarr;
484 $postactionmessages = array();
486 if ($paymentTypeCode ==
"CB" && ($paymentTypeCodeInDolibarr ==
'card' || empty($paymentTypeCodeInDolibarr))) {
491 $paiement_ext_payment_id = $TRANSACTIONID.
':'.$customer_id.
'@'.$stripearrayofkeysbyenv[$servicestatus][
'publishable_key'];
492 $paiement_ext_payment_idold = $TRANSACTIONID;
493 $paiement_ext_payment_site = $service;
496 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"prelevement_demande SET traite = 1 WHERE traite = 0";
497 $sql .=
" AND (type = '' OR type = 'card')";
498 $sql .=
" AND (ext_payment_id = '".$db->escape($paiement_ext_payment_id).
"' OR ext_payment_id = '".
$db->escape($paiement_ext_payment_idold).
"')";
499 $sql .=
" AND ext_payment_site = '".$db->escape($paiement_ext_payment_site).
"'";
500 $sql .=
" AND fk_facture = ".((int) $invoice_id);
501 $sql .=
" AND sourcetype = 'facture'";
503 dol_syslog(
"TODO update flag traite to 1 sql=".$sql);
504 dol_syslog(
"TODO update flag traite to 1 sql=".$sql, LOG_DEBUG, 0,
'_payment');
506 } elseif ($paymentTypeCode ==
"PRE" && $paymentTypeCodeInDolibarr ==
'ban') {
512 $paiement->datepaye = $now;
513 $paiement->date = $now;
515 $paiement->amounts = [$invoice_id => $payment_amount];
517 $paiement->multicurrency_amounts = [$invoice_id => $payment_amount];
519 $postactionmessages[] =
'Payment was done in a currency ('.$currencyCodeType.
') other than the expected currency of company ('.
getDolCurrency().
')';
520 $ispostactionok = -1;
526 $paiement->paiementcode = $paymentTypeCode;
527 $sql =
"SELECT id FROM ".MAIN_DB_PREFIX.
"c_paiement";
528 $sql .=
" WHERE code = '".$db->escape($paymentTypeCode).
"'";
529 $sql .=
" AND entity IN (".getEntity(
'c_paiement').
")";
530 $resql =
$db->query($sql);
532 $obj =
$db->fetch_object($resql);
533 $paiement->paiementid = $obj->id;
538 $paiement->num_payment =
'';
539 $paiement->note_public =
'';
540 $paiement->note_private =
'Stripe Sepa payment received by IPN service listening webhooks - ' .
dol_print_date($now,
'standard') .
' (TZ server) using servicestatus=' . $servicestatus . ($remoteipaddress ?
' remote ip ' . $remoteipaddress :
'').($ipaddress ?
' user ip ' . $ipaddress :
'') .
' - Transaction ID = ' . $TRANSACTIONID;
542 $paiement->ext_payment_id = $TRANSACTIONID.
':'.$customer_id.
'@'.$stripearrayofkeysbyenv[$servicestatus][
'publishable_key'];
543 $paiement->ext_payment_site = $service;
546 $sql =
"SELECT p.rowid FROM ".MAIN_DB_PREFIX.
"paiement as p";
547 $sql .=
" WHERE (p.ext_payment_id = '".$db->escape($paiement->ext_payment_id).
"' OR p.ext_payment_id = '".
$db->escape($TRANSACTIONID).
"')";
548 $sql .=
" AND p.ext_payment_site = '".$db->escape($paiement->ext_payment_site).
"'";
549 $result =
$db->query($sql);
551 if (
$db->num_rows($result)) {
553 dol_syslog(
'* Payment for ext_payment_id '.$paiement->ext_payment_id.
' already done. We do not recreate the payment');
554 dol_syslog(
'* Payment for ext_payment_id '.$paiement->ext_payment_id.
' already done. We do not recreate the payment', LOG_DEBUG, 0,
'_payment');
560 if (!$error && !$ispaymentdone) {
561 dol_syslog(
'* Record payment type PRE for invoice id ' . $invoice_id .
'. It includes closing of invoice and regenerating document.');
562 dol_syslog(
'* Record payment type PRE for invoice id ' . $invoice_id .
'. It includes closing of invoice and regenerating document.', LOG_DEBUG, 0,
'_payment');
565 $thirdpartyofpayment =
null;
567 $paiement_id = $paiement->create($user, 1, $thirdpartyofpayment);
568 if ($paiement_id < 0) {
569 $postactionmessages[] = $paiement->error . ($paiement->error ?
' ' :
'') . implode(
"<br>\n", $paiement->errors);
570 $ispostactionok = -1;
573 dol_syslog(
"Failed to create the payment for invoice id " . $invoice_id);
574 dol_syslog(
"Failed to create the payment for invoice id " . $invoice_id, LOG_DEBUG, 0,
'_payment');
576 $postactionmessages[] =
'Payment created';
578 dol_syslog(
"The payment has been created for invoice id " . $invoice_id);
579 dol_syslog(
"The payment has been created for invoice id " . $invoice_id, LOG_DEBUG, 0,
'_payment');
586 $sql =
"SELECT p.rowid, p.fk_bank FROM ".MAIN_DB_PREFIX.
"paiement as p";
587 $sql .=
" WHERE (p.ext_payment_id = '".$db->escape($paiement->ext_payment_id).
"' OR p.ext_payment_id = '".
$db->escape($TRANSACTIONID).
"')";
588 $sql .=
" AND p.ext_payment_site = '".$db->escape($paiement->ext_payment_site).
"'";
589 $sql .=
" AND p.fk_bank <> 0";
590 $result =
$db->query($sql);
592 if (
$db->num_rows($result)) {
594 $obj =
$db->fetch_object($result);
595 dol_syslog(
'* Payment already linked to bank record '.$obj->fk_bank.
' . We do not recreate the link');
596 dol_syslog(
'* Payment already linked to bank record '.$obj->fk_bank.
' . We do not recreate the link', LOG_DEBUG, 0,
'_payment');
599 if (!$ispaymentdone) {
601 dol_syslog(
'* Add payment to bank', LOG_DEBUG, 0,
'_payment');
604 $paymentmethod =
'stripe';
607 if ($bankaccountid > 0) {
608 $label =
'(CustomerInvoicePayment)';
609 $result = $paiement->addPaymentToBank($user,
'payment', $label, $bankaccountid, $customer_id,
'');
611 $postactionmessages[] = $paiement->error . ($paiement->error ?
' ' :
'') . implode(
"<br>\n", $paiement->errors);
612 $ispostactionok = -1;
615 $postactionmessages[] =
'Bank transaction of payment created (by ipn.php file)';
618 $postactionmessages[] =
'Setup of bank account to use in module ' . $paymentmethod .
' was not set. No way to record the payment.';
619 $ispostactionok = -1;
628 $sql =
"SELECT dp.fk_prelevement_bons as idbon";
629 $sql .=
" FROM ".MAIN_DB_PREFIX.
"prelevement_demande as dp";
630 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"prelevement_bons as pb";
631 $sql .=
" ON pb.rowid = dp.fk_prelevement_bons";
632 $sql .=
" WHERE dp.fk_facture = ".((int) $invoice_id);
633 $sql .=
" AND dp.sourcetype = 'facture'";
634 $sql .=
" AND (dp.ext_payment_id = '".$db->escape($paiement->ext_payment_id).
"' OR dp.ext_payment_id = '".
$db->escape($TRANSACTIONID).
"')";
635 $sql .=
" AND dp.traite = 1";
636 $sql .=
" AND statut = ".((int) $bon::STATUS_TRANSFERED);
637 $result =
$db->query($sql);
639 if (
$db->num_rows($result)) {
640 $obj =
$db->fetch_object($result);
641 $idbon = $obj->idbon;
642 dol_syslog(
'* Prelevement must be set to credited');
643 dol_syslog(
'* Prelevement must be set to credited', LOG_DEBUG, 0,
'_payment');
645 dol_syslog(
'* Prelevement not found or already credited');
646 dol_syslog(
'* Prelevement not found or already credited', LOG_DEBUG, 0,
'_payment');
649 $postactionmessages[] =
$db->lasterror();
650 $ispostactionok = -1;
654 if (!$error && !empty($idbon)) {
655 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"prelevement_bons";
656 $sql .=
" SET fk_user_credit = ".((int) $user->id);
657 $sql .=
", statut = ".((int) $bon::STATUS_CREDITED);
658 $sql .=
", date_credit = '".$db->idate($now).
"'";
659 $sql .=
", credite = 1";
660 $sql .=
" WHERE rowid = ".((int) $idbon);
661 $sql .=
" AND statut = ".((int) $bon::STATUS_TRANSFERED);
663 $result =
$db->query($sql);
665 $postactionmessages[] =
$db->lasterror();
666 $ispostactionok = -1;
671 if (!$error && !empty($idbon)) {
672 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"prelevement_lignes";
673 $sql .=
" SET statut = 2";
674 $sql .=
" WHERE fk_prelevement_bons = ".((int) $idbon);
675 $result =
$db->query($sql);
677 $postactionmessages[] =
$db->lasterror();
678 $ispostactionok = -1;
688 http_response_code(500);
696 $labeltouse =
getDolGlobalString(
'STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION');
700 $invoice->fetch($invoice_id);
701 $invoice->fetch_thirdparty();
705 $outputlangs->setDefaultLang(empty($invoice->thirdparty->default_lang) ?
$mysoc->default_lang : $invoice->thirdparty->default_lang);
706 $outputlangs->loadLangs(array(
"main",
"members",
"bills"));
709 $arraydefaultmessage =
null;
711 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
714 $arraydefaultmessage = $formmail->getEMailTemplate(
$db,
'facture_send', $user, $outputlangs, 0, 1, $labeltouse);
719 $subject =
'['.$appli.
'] Invoice direct debit payment recieved';
720 $msg =
'An invoice direct debit payment for invoice '.$invoice->ref.
' has been recieved';
721 if (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
722 $subject = $arraydefaultmessage->topic;
723 $msg = $arraydefaultmessage->content;
726 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0,
null, $invoice);
732 $foundcontract =
null;
733 $invoice->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 1);
735 if (is_array($invoice->linkedObjects[
'contrat']) && count($invoice->linkedObjects[
'contrat']) > 0) {
737 foreach ($invoice->linkedObjects[
'contrat'] as $contract) {
739 '@phan-var-force Contrat $contract';
740 $substitutionarray[
'__CONTRACT_REF__'] = $contract->ref_customer;
741 $substitutionarray[
'__REFCLIENT__'] = $contract->ref_customer;
742 $substitutionarray[
'__REF_CLIENT__'] = $contract->ref_customer;
743 $substitutionarray[
'__REF_CUSTOMER__'] = $contract->ref_customer;
744 $foundcontract = $contract;
749 dol_syslog(
'__DIRECTDOWNLOAD_URL_INVOICE__='.$substitutionarray[
'__DIRECTDOWNLOAD_URL_INVOICE__']);
755 $listofpaths = array();
756 $listofnames = array();
757 $listofmimes = array();
774 $trackid =
'inv'.$invoice->id;
775 $moreinheader =
'X-Dolibarr-Info: public stripe ipn.php'.
"\r\n";
777 if (!empty($invoice->thirdparty->array_options[
'options_emailccinvoice'])) {
778 dol_syslog(
"We add the recipient ".$invoice->thirdparty->array_options[
'options_emailccinvoice'].
" as CC", LOG_DEBUG);
779 $addr_cc = $invoice->thirdparty->array_options[
'options_emailccinvoice'];
783 include_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
784 $mailfile =
new CMailFile($subjecttosend, $invoice->thirdparty->email, $from, $texttosend, $listofpaths, $listofmimes, $listofnames, $addr_cc,
'', 0, -1,
'',
'', $trackid, $moreinheader);
785 if (empty($mailfile->error) && $mailfile->sendfile()) {
788 dol_syslog(
"Option STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION: Email sent");
789 dol_syslog(
"Option STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION: Email sent", LOG_DEBUG, 0,
'_payment');
791 $errmsg =
'Option STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION: '.$langs->trans(
"ErrorFailedToSendMail", $from, $invoice->thirdparty->email).
'. '.$mailfile->error;
794 dol_syslog($errmsg, LOG_WARNING, 0,
'_payment');
799 dol_syslog(
"Option STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION not set to the template label. No email sent.");
800 dol_syslog(
"Option STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION not set to the template label. No email sent.", LOG_DEBUG, 0,
'_payment');
803 dol_syslog(
"The payment mode of this payment is ".$paymentTypeCode.
" in Stripe and ".$paymentTypeCodeInDolibarr.
" in Dolibarr. This case is not managed by the IPN");
804 dol_syslog(
"The payment mode of this payment is ".$paymentTypeCode.
" in Stripe and ".$paymentTypeCodeInDolibarr.
" in Dolibarr. This case is not managed by the IPN", LOG_DEBUG, 0,
'_payment');
807 dol_syslog(
"Nothing to do in database because we don't know paymentTypeIdInDolibarr");
808 dol_syslog(
"Nothing to do in database because we don't know paymentTypeIdInDolibarr", LOG_DEBUG, 0,
'_payment');
810} elseif ($event->type ==
'payment_intent.payment_failed') {
812 dol_syslog(
"A try to make a payment has failed");
813 dol_syslog(
"A try to make a payment has failed", LOG_DEBUG, 0,
'_payment');
815 $object = $event->data->object;
816 $ipaddress =
$object->metadata->ipaddress;
818 $currencyCodeType = strtoupper(
$object->currency);
819 $paymentmethodstripeid =
$object->payment_method;
820 $customer_id =
$object->customer;
822 $chargesdataarray = array();
828 $objpaymentmodetype =
'';
829 if (!empty(
$object->charges)) {
830 $chargesdataarray =
$object->charges->data;
831 foreach ($chargesdataarray as $chargesdata) {
832 $objpayid = $chargesdata->id;
833 $objpaydesc = $chargesdata->description;
835 if ($chargesdata->metadata->dol_type ==
'facture') {
836 $objinvoiceid = $chargesdata->metadata->dol_id;
838 $objerrcode = $chargesdata->outcome->reason;
839 $objerrmessage = $chargesdata->outcome->seller_message;
841 $objpaymentmodetype = $chargesdata->payment_method_details->type;
845 if (!empty(
$object->last_payment_error)) {
847 $objpayid =
$object->latest_charge;
848 $objpaydesc =
$object->description;
850 if (
$object->metadata->dol_type ==
'facture') {
851 $objinvoiceid =
$object->metadata->dol_id;
853 $objerrcode = empty(
$object->last_payment_error->code) ?
$object->last_payment_error->decline_code :
$object->last_payment_error->code;
854 $objerrmessage =
$object->last_payment_error->message;
856 $objpaymentmodetype =
$object->last_payment_error->payment_method->type;
859 dol_syslog(
"objpayid=".$objpayid.
" objpaymentmodetype=".$objpaymentmodetype.
" objerrcode=".$objerrcode);
860 dol_syslog(
"objpayid=".$objpayid.
" objpaymentmodetype=".$objpaymentmodetype.
" objerrcode=".$objerrcode, LOG_DEBUG, 0,
'_payment');
863 if ($objpaymentmodetype ==
'sepa_debit') {
866 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
869 if ($objinvoiceid > 0) {
870 require_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
872 $invoice->fetch($objinvoiceid);
874 $actioncomm->userownerid = 0;
875 $actioncomm->percentage = -1;
877 $actioncomm->type_code =
'AC_OTH_AUTO';
878 $actioncomm->code =
'AC_PAYMENT_STRIPE_IPN_SEPA_KO';
880 $actioncomm->datep = $now;
881 $actioncomm->datef = $now;
883 $actioncomm->socid = $invoice->socid;
884 $actioncomm->fk_project = $invoice->fk_project;
885 $actioncomm->elementid = $invoice->id;
886 $actioncomm->elementtype =
'invoice';
890 $actioncomm->note_private =
'Stripe Sepa payment error received by IPN service listening webhooks - ' .
dol_print_date($now,
'standard') .
' (TZ server) using servicestatus=' . $servicestatus . ($remoteipaddress ?
' remote ip ' . $remoteipaddress :
'').($ipaddress ?
' user ip ' . $ipaddress :
'').
' - Payment id '.$objpayid.
' after SEPA payment request '.$objpaydesc.
'<br>Error code is: '.$objerrcode.
'<br>Error message is: '.$objerrmessage;
891 $actioncomm->label =
'Payment error (SEPA Stripe)';
893 $result = $actioncomm->create($user);
896 dol_syslog($actioncomm->error, LOG_ERR, 0,
'_payment');
911 http_response_code(500);
915} elseif ($event->type ==
'checkout.session.completed') {
917} elseif ($event->type ==
'payment_method.attached') {
922 require_once DOL_DOCUMENT_ROOT.
'/societe/class/companypaymentmode.class.php';
923 require_once DOL_DOCUMENT_ROOT.
'/societe/class/societeaccount.class.php';
928 $idthirdparty = $societeaccount->getThirdPartyID(
$db->escape($event->data->object->customer),
'stripe', $servicestatus);
929 if ($idthirdparty > 0) {
932 $companypaymentmode->stripe_card_ref = $event->data->object->id;
933 $companypaymentmode->fk_soc = $idthirdparty;
934 $companypaymentmode->bank =
null;
935 $companypaymentmode->label =
'';
936 $companypaymentmode->number = $event->data->object->id;
937 $companypaymentmode->last_four = $event->data->object->card->last4;
938 $companypaymentmode->card_type = $event->data->object->card->branding;
940 $companypaymentmode->owner_name = $event->data->object->billing_details->name;
941 $companypaymentmode->proprio = $companypaymentmode->owner_name;
943 $companypaymentmode->exp_date_month = (int) $event->data->object->card->exp_month;
944 $companypaymentmode->exp_date_year = (int) $event->data->object->card->exp_year;
945 $companypaymentmode->cvn =
null;
946 $companypaymentmode->datec = $event->data->object->created;
947 $companypaymentmode->default_rib = 0;
948 $companypaymentmode->type = $event->data->object->type;
949 $companypaymentmode->country_code = $event->data->object->card->country;
950 $companypaymentmode->status = $servicestatus;
956 $result = $companypaymentmode->create($user);
964 http_response_code(500);
969} elseif ($event->type ==
'payment_method.updated') {
974 require_once DOL_DOCUMENT_ROOT.
'/societe/class/companypaymentmode.class.php';
976 $companypaymentmode->fetch(0,
'', 0,
'',
" AND stripe_card_ref = '".
$db->escape($event->data->object->id).
"'");
977 if ($companypaymentmode->id > 0) {
979 $companypaymentmode->bank =
null;
980 $companypaymentmode->label =
'';
981 $companypaymentmode->number =
$db->escape($event->data->object->id);
982 $companypaymentmode->last_four =
$db->escape($event->data->object->card->last4);
983 $companypaymentmode->proprio =
$db->escape($event->data->object->billing_details->name);
984 $companypaymentmode->owner_name =
$db->escape($event->data->object->billing_details->name);
985 $companypaymentmode->exp_date_month = (int) $event->data->object->card->exp_month;
986 $companypaymentmode->exp_date_year = (int) $event->data->object->card->exp_year;
987 $companypaymentmode->cvn =
null;
988 $companypaymentmode->datec = (int) $event->data->object->created;
989 $companypaymentmode->default_rib = 0;
990 $companypaymentmode->type =
$db->escape($event->data->object->type);
991 $companypaymentmode->country_code =
$db->escape($event->data->object->card->country);
992 $companypaymentmode->status = $servicestatus;
996 $result = $companypaymentmode->update($user);
1006 http_response_code(500);
1010} elseif ($event->type ==
'payment_method.detached') {
1013 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"societe_rib WHERE number = '".
$db->escape($event->data->object->id).
"' and status = ".((int) $servicestatus);
1016} elseif ($event->type ==
'charge.succeeded') {
1018} elseif ($event->type ==
'charge.failed') {
1020} elseif (($event->type ==
'source.chargeable') && ($event->data->object->type ==
'three_d_secure') && ($event->data->object->three_d_secure->authenticated ==
true)) {
1022} elseif ($event->type ==
'charge.dispute.closed') {
1026} elseif ($event->type ==
'charge.dispute.funds_withdrawn') {
1031 global $stripearrayofkeysbyenv;
1034 $object = $event->data->object;
1035 $TRANSACTIONID =
$object->payment_intent;
1036 $ipaddress =
$object->metadata->ipaddress;
1039 $currencyCodeType = strtoupper(
$object->currency);
1040 $paymentmethodstripeid =
$object->payment_method;
1041 $customer_id =
$object->customer;
1043 $amountdisputestripe =
$object->amount;
1044 $amountdispute = $stripe->convertAmount($amountdisputestripe, $currencyCodeType, 1);
1045 $statusdispute =
$object->status;
1048 if (isset($stripearrayofkeysbyenv[$servicestatus][
'publishable_key'])) {
1049 $pkey = $stripearrayofkeysbyenv[$servicestatus][
'publishable_key'];
1051 $LONGTRANSACTIONID = $TRANSACTIONID.
':'.$customer_id.
'@'.$pkey;
1054 $balance_transactions_array =
$object->balance_transactions;
1056 if (!empty($balance_transactions_array) && is_array($balance_transactions_array)) {
1057 foreach ($balance_transactions_array as $tmpval) {
1058 if (isset($tmpval[
'fee'])) {
1059 $feesstripe += (int) $tmpval[
'fee'];
1063 $fees = $stripe->convertAmount($feesstripe, $currencyCodeType, 1);
1066 $paymentTypeCode =
"";
1067 $paymentTypeCodeInDolibarr =
"";
1068 $payment_amount = 0;
1069 $payment_amountInDolibarr = 0;
1071 dol_syslog(
"Try to find the payment in database for the payment_intent id = ".$TRANSACTIONID);
1072 dol_syslog(
"Try to find the payment in database for the payment_intent id = ".$TRANSACTIONID, LOG_DEBUG, 0,
'_payment');
1074 $sql =
"SELECT pi.rowid, pi.fk_facture, pi.fk_prelevement_bons, pi.amount, pi.type, pi.traite";
1075 $sql .=
" FROM ".MAIN_DB_PREFIX.
"prelevement_demande as pi";
1077 $sql .=
" WHERE (pi.ext_payment_id = '".$db->escape($LONGTRANSACTIONID).
"' OR pi.ext_payment_id = '".
$db->escape($TRANSACTIONID).
"')";
1078 $sql .=
" AND pi.ext_payment_site = '".$db->escape($service).
"'";
1080 $result =
$db->query($sql);
1082 $obj =
$db->fetch_object($result);
1084 if ($obj->type ==
'ban') {
1086 $pdid = $obj->rowid;
1087 $invoice_id = $obj->fk_facture;
1088 $directdebitorcreditransfer_id = $obj->fk_prelevement_bons;
1089 $payment_amountInDolibarr = $obj->amount;
1090 $paymentTypeCodeInDolibarr = $obj->type;
1092 dol_syslog(
"Found the payment intent for ban in database (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")");
1093 dol_syslog(
"Found the payment intent for ban in database (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")", LOG_DEBUG, 0,
'_payment');
1095 if ($obj->type ==
'card' || empty($obj->type)) {
1097 $pdid = $obj->rowid;
1098 $invoice_id = $obj->fk_facture;
1099 $directdebitorcreditransfer_id = 0;
1100 $payment_amountInDolibarr = $obj->amount;
1101 $paymentTypeCodeInDolibarr = empty($obj->type) ?
'card' : $obj->type;
1103 dol_syslog(
"Found the payment intent for card in database (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")");
1104 dol_syslog(
"Found the payment intent for card in database (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")", LOG_DEBUG, 0,
'_payment');
1107 dol_syslog(
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.");
1108 dol_syslog(
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.", LOG_DEBUG, 0,
'_payment');
1109 http_response_code(200);
1110 print
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.";
1114 http_response_code(500);
1115 print
$db->lasterror();
1120 dol_syslog(
"objinvoiceid=".$invoice_id, LOG_DEBUG, 0,
'_payment');
1122 $tmpinvoice->fetch($invoice_id);
1123 $tmpinvoice->fetch_thirdparty();
1125 dol_syslog(
"The payment disputed has the amount ".$amountdispute.
", fees of ".$fees.
" and the invoice has ".$payment_amountInDolibarr);
1126 dol_syslog(
"The payment disputed has the amount ".$amountdispute.
", fees of ".$fees.
" and the invoice has ".$payment_amountInDolibarr, LOG_DEBUG, 0,
'_payment');
1140 if ($statusdispute ==
'needs_response') {
1149 $errormsg = $tmpinvoice->error.implode(
', ', $tmpinvoice->errors);
1180 $errormsg = $tmpinvoice->error.implode(
', ', $tmpinvoice->errors);
1187 dol_syslog(
"The dispute_status of invoice ".$tmpinvoice->ref.
" has been modified to 1");
1188 dol_syslog(
"The dispute_status of invoice ".$tmpinvoice->ref.
" has been modified to 1", LOG_DEBUG, 0,
'_payment');
1190 http_response_code(200);
1191 print
"Payment dispute received for ".$TRANSACTIONID.
". We have changed the status of dispute_status to 1 for invoice ".$tmpinvoice->ref;
1196 dol_syslog(
"Technicalerror ".
$db->lasterror().
" - ".$errormsg, LOG_ERR);
1197 dol_syslog(
"Technicalerror ".
$db->lasterror().
" - ".$errormsg, LOG_ERR, 0,
'_payment');
1199 http_response_code(500);
1200 print
$db->lasterror();
1206 $accountfrom->fetch(
getDolGlobalInt(
'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS'));
1212 $amounts[$tmpinvoice->id] = -1 * $payment_amountInDolibarr;
1214 $paiement->datepaye =
dol_now();
1215 $paiement->amounts = $amounts;
1221 $paiement->num_payment =
$object->id;
1223 $paiement->note_private =
'Stripe fund withdrawn message received by IPN service listening webhooks - ' .
dol_print_date($now,
'standard') .
' (TZ server) using servicestatus=' . $servicestatus . ($remoteipaddress ?
' remote ip ' . $remoteipaddress :
'').($ipaddress ?
' user ip ' . $ipaddress :
'');
1224 $paiement->note_private .=
' - Fund withdrawn by bank with id='.$object->id.
'. Reason: '.$reason.
'. A fee of '.$fees.
' may have been charged by Stripe.';
1226 $paiement->fk_account = $accountfrom->id;
1228 $paiement->ext_payment_id =
$object->payment_intent;
1229 $paiement->ext_payment_site = $service;
1233 $alreadytransferedinaccounting = $tmpinvoice->getVentilExportCompta();
1235 dol_syslog(
"The invoice has alreadytransferedinaccounting=".$alreadytransferedinaccounting);
1236 dol_syslog(
"The invoice has alreadytransferedinaccounting=".$alreadytransferedinaccounting, LOG_DEBUG, 0,
'_payment');
1251 $errormsg = $tmpinvoice->error.implode(
', ', $tmpinvoice->errors);
1260 $errormsg = $tmpinvoice->error.implode(
', ', $tmpinvoice->errors);
1265 dol_syslog(
"The dispute_status of invoice ".$tmpinvoice->ref.
" has been modified to 1");
1266 dol_syslog(
"The dispute_status of invoice ".$tmpinvoice->ref.
" has been modified to 1", LOG_DEBUG, 0,
'_payment');
1271 $withdrawn_payment_already_exists =
true;
1272 $sql =
"SELECT p.rowid, p.ref";
1273 $sql .=
" FROM ".MAIN_DB_PREFIX.
"paiement as p";
1274 $sql .=
" WHERE p.ext_payment_id = '".$db->escape($paiement->ext_payment_id).
"'";
1275 $sql .=
" AND p.ext_payment_site = '".$db->escape($service).
"'";
1277 $tmpresql =
$db->query($sql);
1279 $obj =
$db->fetch_object($tmpresql);
1281 $withdrawn_payment_already_exists =
false;
1282 dol_syslog(
"No withdraw payment already exists", LOG_DEBUG);
1284 dol_syslog(
"A withdraw payment already exists", LOG_DEBUG);
1288 if (!$error && !$alreadytransferedinaccounting && !$withdrawn_payment_already_exists) {
1289 if ($paiement->fk_account > 0) {
1293 dol_syslog(
"We try to record the payment", LOG_DEBUG, 0,
'_payment');
1295 $paiement_id = $paiement->create($user, 0, $tmpinvoice->thirdparty);
1296 if ($paiement_id < 0) {
1297 $errormsg = $paiement->error.implode(
', ', $paiement->errors);
1300 $banklineid = $paiement->addPaymentToBank($user,
'payment',
'IPN Stripe dispute funds withdrawn', $paiement->fk_account,
'',
'', 1,
'',
'');
1301 if ($banklineid < 0) {
1302 $errormsg = $paiement->error.implode(
', ', $paiement->errors);
1307 dol_syslog(
"No bank account defined to record payment so no payment recorded");
1308 dol_syslog(
"No bank account defined to record payment so no payment recorded", LOG_DEBUG, 0,
'_payment');
1322 dol_syslog(
"Invoice status updated and/or Revert payment created", LOG_WARNING);
1323 dol_syslog(
"Invoice status updated and/or Revert payment created", LOG_WARNING, 0,
'_payment');
1327 dol_syslog(
"Error - Return HTTP 500 - ".$errormsg, LOG_ERR);
1328 dol_syslog(
"Error - Return HTTP 500 - ".$errormsg, LOG_ERR, 0,
'_payment');
1330 http_response_code(500);
if(! $sortfield) if(! $sortorder) $object
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
Class to manage bank accounts.
Class to manage agenda events (actions)
Class to manage withdrawal receipts.
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
Class for CompanyPaymentMode.
Class to manage invoices.
const STATUS_VALIDATED
Validated (need to be paid)
const STATUS_CLOSED
Classified paid.
Class to manage payments of customer invoices.
Class for SocieteAccount.
Stripe class @TODO No reason to extend CommonObject.
Class to manage translations.
Class to manage Dolibarr users.
dol_now($mode='gmt')
Return date for now.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
if(!function_exists( 'utf8_encode')) if(!function_exists('utf8_decode')) if(!function_exists( 'str_starts_with')) if(!function_exists('str_ends_with')) if(!function_exists( 'str_contains')) formatLogObject($data)
Return a string serialized to be output on log with dol_syslog() An option allow to output log in one...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getUserRemoteIP($trusted=0)
Return the real IP of remote user.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.