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)) {
100 $user =
new User($db);
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');
195if ($event->type ==
'payout.created' &&
getDolGlobalString(
'STRIPE_AUTO_RECORD_PAYOUT')) {
197 dol_syslog(
"object = ".var_export($event->data,
true));
198 dol_syslog(
"object = ".var_export($event->data,
true), LOG_DEBUG, 0,
'_payment');
202 $result =
dolibarr_set_const($db, $service.
"_NEXTPAYOUT",
date(
'Y-m-d H:i:s', $event->data->object->arrival_date),
'chaine', 0,
'', $conf->entity);
205 $subject =
'['.$societeName.
'] Notification - Stripe payout scheduled';
206 if (!empty($user->email)) {
217 $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');
233 $ret = $mailfile->sendfile();
238 http_response_code(500);
241} elseif ($event->type ==
'payout.paid' &&
getDolGlobalString(
'STRIPE_AUTO_RECORD_PAYOUT')) {
243 dol_syslog(
"object = ".var_export($event->data,
true));
244 dol_syslog(
"object = ".var_export($event->data,
true), LOG_DEBUG, 0,
'_payment');
247 $result =
dolibarr_set_const($db, $service.
"_NEXTPAYOUT", 0,
'chaine', 0,
'', $conf->entity);
249 $langs->load(
"errors");
254 $label = $event->data->object->description.
' - '.
getDolGlobalString(
'STRIPE_AUTO_RECORD_PAYOUT_LABEL',
'autorecord by IPN, see Stripe setup');
255 $amount = $stripe->convertAmount($event->data->object->amount, $currency_code, 1);
257 require_once DOL_DOCUMENT_ROOT.
'/compta/bank/class/account.class.php';
259 $accountfrom =
new Account($db);
260 $accountfrom->fetch(
getDolGlobalInt(
'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS'));
263 $accountto->fetch(
getDolGlobalInt(
'STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS'));
265 if (($accountto->id != $accountfrom->id) && empty($error)) {
266 $bank_line_id_from = 0;
267 $bank_line_id_to = 0;
279 $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');
281 if (!($bank_line_id_from > 0)) {
285 $bank_line_id_to = $accountto->addline($dateo, $typeto, $label, (
float)
price2num($amount), $numChqOrOpe, 0, $user,
'',
'',
'',
null,
'',
null,
'Record payout from public/stripe/ipn.php');
287 if (!($bank_line_id_to > 0)) {
293 $result = $accountfrom->add_url_line($bank_line_id_from, $bank_line_id_to, DOL_URL_ROOT.
'/compta/bank/line.php?rowid=',
'(banktransfert)',
'banktransfert');
295 if (!($result > 0)) {
299 $result = $accountto->add_url_line($bank_line_id_to, $bank_line_id_from, DOL_URL_ROOT.
'/compta/bank/line.php?rowid=',
'(banktransfert)',
'banktransfert');
301 if (!($result > 0)) {
313 $subject =
'['.$societeName.
'] Notification - Stripe payout done';
314 if (!empty($user->email)) {
325 $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');
341 $ret = $mailfile->sendfile();
348 http_response_code(500);
351} elseif ($event->type ==
'customer.source.created') {
353} elseif ($event->type ==
'customer.source.updated') {
355} elseif ($event->type ==
'customer.source.delete') {
357} elseif ($event->type ==
'customer.deleted') {
360 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"societe_account WHERE key_account = '".$db->escape($event->data->object->id).
"' AND site = 'stripe'";
363} elseif ($event->type ==
'payment_intent.succeeded') {
365 dol_syslog(
"object = ".var_export($event->data,
true));
366 dol_syslog(
"object = ".var_export($event->data,
true), LOG_DEBUG, 0,
'_payment');
368 include_once DOL_DOCUMENT_ROOT .
'/compta/paiement/class/paiement.class.php';
369 global $stripearrayofkeysbyenv;
371 $object = $event->data->object;
372 $objectType =
$object->metadata->dol_type;
374 $ipaddress =
$object->metadata->ipaddress;
376 $currencyCodeType = strtoupper(
$object->currency);
377 $paymentmethodstripeid =
$object->payment_method;
378 $customer_id =
$object->customer;
380 $supplierinvoice_id = 0;
382 $paymentTypeCode =
"";
383 $paymentTypeCodeInDolibarr =
"";
385 $payment_amountInDolibarr = 0;
387 dol_syslog(
"Try to find a payment in database for the payment_intent id = ".$TRANSACTIONID);
388 dol_syslog(
"Try to find a payment in database for the payment_intent id = ".$TRANSACTIONID, LOG_DEBUG, 0,
'_payment');
390 $sql =
"SELECT pi.rowid, pi.fk_facture, fk_facture_fourn, fk_salary, pi.fk_prelevement_bons, pi.amount, pi.type, pi.traite";
391 $sql .=
" FROM ".MAIN_DB_PREFIX.
"prelevement_demande as pi";
392 $sql .=
" WHERE pi.ext_payment_id = '".$db->escape($TRANSACTIONID).
"'";
393 $sql .=
" AND pi.ext_payment_site = '".$db->escape($service).
"'";
395 $result = $db->query($sql);
397 $obj = $db->fetch_object($result);
399 if ($obj->type ==
'ban') {
401 $directdebitorcreditransfer_id = $obj->fk_prelevement_bons;
403 if ($obj->traite == 1) {
406 $invoice_id = $obj->fk_facture;
407 $supplierinvoice_id = $obj->fk_facture_fourn;
408 $salary_id = $obj->fk_salary;
409 $payment_amountInDolibarr = $obj->amount;
410 $paymentTypeCodeInDolibarr = $obj->type;
412 dol_syslog(
"Found a request in database to pay with direct debit generated (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")");
413 dol_syslog(
"Found a request in database to pay with direct debit generated (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")", LOG_DEBUG, 0,
'_payment');
415 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);
416 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');
419 if ($obj->type ==
'card' || empty($obj->type)) {
421 if ($obj->traite == 0) {
423 $invoice_id = $obj->fk_facture;
424 $payment_amountInDolibarr = $obj->amount;
425 $paymentTypeCodeInDolibarr = empty($obj->type) ?
'card' : $obj->type;
427 dol_syslog(
"Found a request in database to pay with card (pdid = ".$pdid.
"). We should fix status traite to 1");
428 dol_syslog(
"Found a request in database to pay with card (pdid = ".$pdid.
"). We should fix status traite to 1", LOG_DEBUG, 0,
'_payment');
430 dol_syslog(
"Found a request in database to pay with card (pdid = ".$pdid.
") already set to traite=1. Nothing to fix.");
431 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');
435 dol_syslog(
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.");
436 dol_syslog(
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.", LOG_DEBUG, 0,
'_payment');
437 http_response_code(200);
438 print
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.";
442 http_response_code(500);
443 print $db->lasterror();
447 if ($paymentTypeCodeInDolibarr) {
450 $stripeacc = $stripearrayofkeysbyenv[$servicestatus][
'secret_key'];
452 dol_syslog(
"Get the Stripe payment object for the payment method id = ".json_encode($paymentmethodstripeid));
453 dol_syslog(
"Get the Stripe payment object for the payment method id = ".json_encode($paymentmethodstripeid), LOG_DEBUG, 0,
'_payment');
455 $s = new \Stripe\StripeClient($stripeacc);
457 $paymentmethodstripe = $s->paymentMethods->retrieve($paymentmethodstripeid);
458 $paymentTypeCode = $paymentmethodstripe->type;
459 if ($paymentTypeCode ==
"ban" || $paymentTypeCode ==
"sepa_debit") {
460 $paymentTypeCode =
"PRE";
461 } elseif ($paymentTypeCode ==
"card") {
462 $paymentTypeCode =
"CB";
465 $payment_amount = $payment_amountInDolibarr;
471 $postactionmessages = array();
473 if ($paymentTypeCode ==
"CB" && ($paymentTypeCodeInDolibarr ==
'card' || empty($paymentTypeCodeInDolibarr))) {
479 dol_syslog(
"TODO update flag traite to 1", LOG_DEBUG, 0,
'_payment');
480 } elseif ($paymentTypeCode ==
"PRE" && $paymentTypeCodeInDolibarr ==
'ban') {
486 $paiement->datepaye = $now;
487 $paiement->date = $now;
489 $paiement->amounts = [$invoice_id => $payment_amount];
491 $paiement->multicurrency_amounts = [$invoice_id => $payment_amount];
493 $postactionmessages[] =
'Payment was done in a currency ('.$currencyCodeType.
') other than the expected currency of company ('.
getDolCurrency().
')';
494 $ispostactionok = -1;
500 $paiement->paiementcode = $paymentTypeCode;
501 $sql =
"SELECT id FROM ".MAIN_DB_PREFIX.
"c_paiement";
502 $sql .=
" WHERE code = '".$db->escape($paymentTypeCode).
"'";
503 $sql .=
" AND entity IN (".getEntity(
'c_paiement').
")";
504 $resql = $db->query($sql);
506 $obj = $db->fetch_object($resql);
507 $paiement->paiementid = $obj->id;
512 $paiement->num_payment =
'';
513 $paiement->note_public =
'';
514 $paiement->note_private =
'Stripe Sepa payment received by IPN service listening webhooks - ' .
dol_print_date($now,
'standard') .
' (TZ server) using servicestatus=' . $servicestatus . ($ipaddress ?
' from ip ' . $ipaddress :
'') .
' - Transaction ID = ' . $TRANSACTIONID;
516 $paiement->ext_payment_id = $TRANSACTIONID.
':'.$customer_id.
'@'.$stripearrayofkeysbyenv[$servicestatus][
'publishable_key'];
517 $paiement->ext_payment_site = $service;
520 $sql =
"SELECT p.rowid FROM ".MAIN_DB_PREFIX.
"paiement as p";
521 $sql .=
" WHERE (p.ext_payment_id = '".$db->escape($paiement->ext_payment_id).
"' OR p.ext_payment_id = '".$db->escape($TRANSACTIONID).
"')";
522 $sql .=
" AND p.ext_payment_site = '".$db->escape($paiement->ext_payment_site).
"'";
523 $result = $db->query($sql);
525 if ($db->num_rows($result)) {
527 dol_syslog(
'* Payment for ext_payment_id '.$paiement->ext_payment_id.
' already done. We do not recreate the payment');
528 dol_syslog(
'* Payment for ext_payment_id '.$paiement->ext_payment_id.
' already done. We do not recreate the payment', LOG_DEBUG, 0,
'_payment');
534 if (!$error && !$ispaymentdone) {
535 dol_syslog(
'* Record payment type PRE for invoice id ' . $invoice_id .
'. It includes closing of invoice and regenerating document.');
536 dol_syslog(
'* Record payment type PRE for invoice id ' . $invoice_id .
'. It includes closing of invoice and regenerating document.', LOG_DEBUG, 0,
'_payment');
539 $thirdpartyofpayment =
null;
541 $paiement_id = $paiement->create($user, 1, $thirdpartyofpayment);
542 if ($paiement_id < 0) {
543 $postactionmessages[] = $paiement->error . ($paiement->error ?
' ' :
'') . implode(
"<br>\n", $paiement->errors);
544 $ispostactionok = -1;
547 dol_syslog(
"Failed to create the payment for invoice id " . $invoice_id);
548 dol_syslog(
"Failed to create the payment for invoice id " . $invoice_id, LOG_DEBUG, 0,
'_payment');
550 $postactionmessages[] =
'Payment created';
552 dol_syslog(
"The payment has been created for invoice id " . $invoice_id);
553 dol_syslog(
"The payment has been created for invoice id " . $invoice_id, LOG_DEBUG, 0,
'_payment');
560 $sql =
"SELECT p.rowid, p.fk_bank FROM ".MAIN_DB_PREFIX.
"paiement as p";
561 $sql .=
" WHERE (p.ext_payment_id = '".$db->escape($paiement->ext_payment_id).
"' OR p.ext_payment_id = '".$db->escape($TRANSACTIONID).
"')";
562 $sql .=
" AND p.ext_payment_site = '".$db->escape($paiement->ext_payment_site).
"'";
563 $sql .=
" AND p.fk_bank <> 0";
564 $result = $db->query($sql);
566 if ($db->num_rows($result)) {
568 $obj = $db->fetch_object($result);
569 dol_syslog(
'* Payment already linked to bank record '.$obj->fk_bank.
' . We do not recreate the link');
570 dol_syslog(
'* Payment already linked to bank record '.$obj->fk_bank.
' . We do not recreate the link', LOG_DEBUG, 0,
'_payment');
573 if (!$ispaymentdone) {
575 dol_syslog(
'* Add payment to bank', LOG_DEBUG, 0,
'_payment');
578 $paymentmethod =
'stripe';
581 if ($bankaccountid > 0) {
582 $label =
'(CustomerInvoicePayment)';
583 $result = $paiement->addPaymentToBank($user,
'payment', $label, $bankaccountid, $customer_id,
'');
585 $postactionmessages[] = $paiement->error . ($paiement->error ?
' ' :
'') . implode(
"<br>\n", $paiement->errors);
586 $ispostactionok = -1;
589 $postactionmessages[] =
'Bank transaction of payment created (by ipn.php file)';
592 $postactionmessages[] =
'Setup of bank account to use in module ' . $paymentmethod .
' was not set. No way to record the payment.';
593 $ispostactionok = -1;
602 $sql =
"SELECT dp.fk_prelevement_bons as idbon";
603 $sql .=
" FROM ".MAIN_DB_PREFIX.
"prelevement_demande as dp";
604 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"prelevement_bons as pb";
605 $sql .=
" ON pb.rowid = dp.fk_prelevement_bons";
606 $sql .=
" WHERE dp.fk_facture = ".((int) $invoice_id);
607 $sql .=
" AND dp.sourcetype = 'facture'";
608 $sql .=
" AND (dp.ext_payment_id = '".$db->escape($paiement->ext_payment_id).
"' OR dp.ext_payment_id = '".$db->escape($TRANSACTIONID).
"')";
609 $sql .=
" AND dp.traite = 1";
610 $sql .=
" AND statut = ".((int) $bon::STATUS_TRANSFERED);
611 $result = $db->query($sql);
613 if ($db->num_rows($result)) {
614 $obj = $db->fetch_object($result);
615 $idbon = $obj->idbon;
616 dol_syslog(
'* Prelevement must be set to credited');
617 dol_syslog(
'* Prelevement must be set to credited', LOG_DEBUG, 0,
'_payment');
619 dol_syslog(
'* Prelevement not found or already credited');
620 dol_syslog(
'* Prelevement not found or already credited', LOG_DEBUG, 0,
'_payment');
623 $postactionmessages[] = $db->lasterror();
624 $ispostactionok = -1;
628 if (!$error && !empty($idbon)) {
629 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"prelevement_bons";
630 $sql .=
" SET fk_user_credit = ".((int) $user->id);
631 $sql .=
", statut = ".((int) $bon::STATUS_CREDITED);
632 $sql .=
", date_credit = '".$db->idate($now).
"'";
633 $sql .=
", credite = 1";
634 $sql .=
" WHERE rowid = ".((int) $idbon);
635 $sql .=
" AND statut = ".((int) $bon::STATUS_TRANSFERED);
637 $result = $db->query($sql);
639 $postactionmessages[] = $db->lasterror();
640 $ispostactionok = -1;
645 if (!$error && !empty($idbon)) {
646 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"prelevement_lignes";
647 $sql .=
" SET statut = 2";
648 $sql .=
" WHERE fk_prelevement_bons = ".((int) $idbon);
649 $result = $db->query($sql);
651 $postactionmessages[] = $db->lasterror();
652 $ispostactionok = -1;
661 $labeltouse =
getDolGlobalString(
'STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION');
665 $invoice->fetch($invoice_id);
666 $invoice->fetch_thirdparty();
670 $outputlangs->setDefaultLang(empty($invoice->thirdparty->default_lang) ?
$mysoc->default_lang : $invoice->thirdparty->default_lang);
671 $outputlangs->loadLangs(array(
"main",
"members",
"bills"));
674 $arraydefaultmessage=
null;
676 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
679 $arraydefaultmessage = $formmail->getEMailTemplate($db,
'facture_send', $user, $outputlangs, 0, 1, $labeltouse);
683 $subject =
'['.$appli.
'] Invoice direct debit payment recevied';
684 $msg =
'An invoice direct debit payment for invoice '.$invoice->ref.
' has been recevied';
685 if (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
686 $subject = $arraydefaultmessage->topic;
687 $msg = $arraydefaultmessage->content;
690 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0,
null, $invoice);
696 $foundcontract =
null;
697 $invoice->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 1);
699 if (is_array($invoice->linkedObjects[
'contrat']) && count($invoice->linkedObjects[
'contrat']) > 0) {
701 foreach ($invoice->linkedObjects[
'contrat'] as $contract) {
703 '@phan-var-force Contrat $contract';
704 $substitutionarray[
'__CONTRACT_REF__'] = $contract->ref_customer;
705 $substitutionarray[
'__REFCLIENT__'] = $contract->ref_customer;
706 $substitutionarray[
'__REF_CLIENT__'] = $contract->ref_customer;
707 $substitutionarray[
'__REF_CUSTOMER__'] = $contract->ref_customer;
708 $foundcontract = $contract;
713 dol_syslog(
'__DIRECTDOWNLOAD_URL_INVOICE__='.$substitutionarray[
'__DIRECTDOWNLOAD_URL_INVOICE__']);
719 $listofpaths=array();
720 $listofnames=array();
721 $listofmimes=array();
738 $trackid =
'inv'.$invoice->id;
739 $moreinheader =
'X-Dolibarr-Info: public stripe ipn.php'.
"\r\n";
741 if (!empty($invoice->thirdparty->array_options[
'options_emailccinvoice'])) {
742 dol_syslog(
"We add the recipient ".$invoice->thirdparty->array_options[
'options_emailccinvoice'].
" as CC", LOG_DEBUG);
743 $addr_cc = $invoice->thirdparty->array_options[
'options_emailccinvoice'];
747 include_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
748 $mailfile =
new CMailFile($subjecttosend, $invoice->thirdparty->email, $from, $texttosend, $listofpaths, $listofmimes, $listofnames, $addr_cc,
'', 0, -1,
'',
'', $trackid, $moreinheader);
749 if (empty($mailfile->error) && $mailfile->sendfile()) {
752 $errmsg = $langs->trans(
"ErrorFailedToSendMail", $from, $invoice->thirdparty->email).
'. '.$mailfile->error;
755 dol_syslog($errmsg, LOG_WARNING, 0,
'_payment');
758 dol_syslog(
"No email sent. Option STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION not set to the tmeplate label");
759 dol_syslog(
"No email sent. Option STRIPE_IPN_SEND_EMAIL_ON_DIRECT_DEBIT_CONFIRMATION not set to the tmeplate label", LOG_DEBUG, 0,
'_payment');
763 http_response_code(200);
767 http_response_code(500);
771 dol_syslog(
"The payment mode of this payment is ".$paymentTypeCode.
" in Stripe and ".$paymentTypeCodeInDolibarr.
" in Dolibarr. This case is not managed by the IPN");
772 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');
775 dol_syslog(
"Nothing to do in database because we don't know paymentTypeIdInDolibarr");
776 dol_syslog(
"Nothing to do in database because we don't know paymentTypeIdInDolibarr", LOG_DEBUG, 0,
'_payment');
778} elseif ($event->type ==
'payment_intent.payment_failed') {
780 dol_syslog(
"A try to make a payment has failed");
781 dol_syslog(
"A try to make a payment has failed", LOG_DEBUG, 0,
'_payment');
783 $object = $event->data->object;
784 $ipaddress =
$object->metadata->ipaddress;
785 $currencyCodeType = strtoupper(
$object->currency);
786 $paymentmethodstripeid =
$object->payment_method;
787 $customer_id =
$object->customer;
789 $chargesdataarray = array();
795 $objpaymentmodetype =
'';
796 if (!empty(
$object->charges)) {
797 $chargesdataarray =
$object->charges->data;
798 foreach ($chargesdataarray as $chargesdata) {
799 $objpayid = $chargesdata->id;
800 $objpaydesc = $chargesdata->description;
802 if ($chargesdata->metadata->dol_type ==
'facture') {
803 $objinvoiceid = $chargesdata->metadata->dol_id;
805 $objerrcode = $chargesdata->outcome->reason;
806 $objerrmessage = $chargesdata->outcome->seller_message;
808 $objpaymentmodetype = $chargesdata->payment_method_details->type;
812 if (!empty(
$object->last_payment_error)) {
814 $objpayid =
$object->latest_charge;
815 $objpaydesc =
$object->description;
817 if (
$object->metadata->dol_type ==
'facture') {
818 $objinvoiceid =
$object->metadata->dol_id;
820 $objerrcode = empty(
$object->last_payment_error->code) ?
$object->last_payment_error->decline_code :
$object->last_payment_error->code;
821 $objerrmessage =
$object->last_payment_error->message;
823 $objpaymentmodetype =
$object->last_payment_error->payment_method->type;
826 dol_syslog(
"objpayid=".$objpayid.
" objpaymentmodetype=".$objpaymentmodetype.
" objerrcode=".$objerrcode);
827 dol_syslog(
"objpayid=".$objpayid.
" objpaymentmodetype=".$objpaymentmodetype.
" objerrcode=".$objerrcode, LOG_DEBUG, 0,
'_payment');
830 if ($objpaymentmodetype ==
'sepa_debit') {
833 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
836 if ($objinvoiceid > 0) {
837 require_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
839 $invoice->fetch($objinvoiceid);
841 $actioncomm->userownerid = 0;
842 $actioncomm->percentage = -1;
844 $actioncomm->type_code =
'AC_OTH_AUTO';
845 $actioncomm->code =
'AC_PAYMENT_STRIPE_IPN_SEPA_KO';
847 $actioncomm->datep = $now;
848 $actioncomm->datef = $now;
850 $actioncomm->socid = $invoice->socid;
851 $actioncomm->fk_project = $invoice->fk_project;
852 $actioncomm->elementid = $invoice->id;
853 $actioncomm->elementtype =
'invoice';
857 $actioncomm->note_private =
'Error returned on payment id '.$objpayid.
' after SEPA payment request '.$objpaydesc.
'<br>Error code is: '.$objerrcode.
'<br>Error message is: '.$objerrmessage;
858 $actioncomm->label =
'Payment error (SEPA Stripe)';
860 $result = $actioncomm->create($user);
863 dol_syslog($actioncomm->error, LOG_ERR, 0,
'_payment');
871 http_response_code(500);
875} elseif ($event->type ==
'checkout.session.completed') {
877} elseif ($event->type ==
'payment_method.attached') {
878 dol_syslog(
"object = ".var_export($event->data,
true));
879 dol_syslog(
"object = ".var_export($event->data,
true), LOG_DEBUG, 0,
'_payment');
882 require_once DOL_DOCUMENT_ROOT.
'/societe/class/companypaymentmode.class.php';
883 require_once DOL_DOCUMENT_ROOT.
'/societe/class/societeaccount.class.php';
888 $idthirdparty = $societeaccount->getThirdPartyID($db->escape($event->data->object->customer),
'stripe', $servicestatus);
889 if ($idthirdparty > 0) {
892 $companypaymentmode->stripe_card_ref = $event->data->object->id;
893 $companypaymentmode->fk_soc = $idthirdparty;
894 $companypaymentmode->bank =
null;
895 $companypaymentmode->label =
'';
896 $companypaymentmode->number = $event->data->object->id;
897 $companypaymentmode->last_four = $event->data->object->card->last4;
898 $companypaymentmode->card_type = $event->data->object->card->branding;
900 $companypaymentmode->owner_name = $event->data->object->billing_details->name;
901 $companypaymentmode->proprio = $companypaymentmode->owner_name;
903 $companypaymentmode->exp_date_month = (int) $event->data->object->card->exp_month;
904 $companypaymentmode->exp_date_year = (int) $event->data->object->card->exp_year;
905 $companypaymentmode->cvn =
null;
906 $companypaymentmode->datec = $event->data->object->created;
907 $companypaymentmode->default_rib = 0;
908 $companypaymentmode->type = $event->data->object->type;
909 $companypaymentmode->country_code = $event->data->object->card->country;
910 $companypaymentmode->status = $servicestatus;
916 $result = $companypaymentmode->create($user);
924 http_response_code(500);
929} elseif ($event->type ==
'payment_method.updated') {
930 dol_syslog(
"object = ".var_export($event->data,
true));
931 dol_syslog(
"object = ".var_export($event->data,
true), LOG_DEBUG, 0,
'_payment');
934 require_once DOL_DOCUMENT_ROOT.
'/societe/class/companypaymentmode.class.php';
936 $companypaymentmode->fetch(0,
'', 0,
'',
" AND stripe_card_ref = '".$db->escape($event->data->object->id).
"'");
937 if ($companypaymentmode->id > 0) {
939 $companypaymentmode->bank =
null;
940 $companypaymentmode->label =
'';
941 $companypaymentmode->number = $db->escape($event->data->object->id);
942 $companypaymentmode->last_four = $db->escape($event->data->object->card->last4);
943 $companypaymentmode->proprio = $db->escape($event->data->object->billing_details->name);
944 $companypaymentmode->owner_name = $db->escape($event->data->object->billing_details->name);
945 $companypaymentmode->exp_date_month = (int) $event->data->object->card->exp_month;
946 $companypaymentmode->exp_date_year = (int) $event->data->object->card->exp_year;
947 $companypaymentmode->cvn =
null;
948 $companypaymentmode->datec = (int) $event->data->object->created;
949 $companypaymentmode->default_rib = 0;
950 $companypaymentmode->type = $db->escape($event->data->object->type);
951 $companypaymentmode->country_code = $db->escape($event->data->object->card->country);
952 $companypaymentmode->status = $servicestatus;
956 $result = $companypaymentmode->update($user);
965 http_response_code(500);
969} elseif ($event->type ==
'payment_method.detached') {
972 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"societe_rib WHERE number = '".$db->escape($event->data->object->id).
"' and status = ".((int) $servicestatus);
975} elseif ($event->type ==
'charge.succeeded') {
977} elseif ($event->type ==
'charge.failed') {
979} elseif (($event->type ==
'source.chargeable') && ($event->data->object->type ==
'three_d_secure') && ($event->data->object->three_d_secure->authenticated ==
true)) {
981} elseif ($event->type ==
'charge.dispute.closed') {
983 dol_syslog(
"object = ".var_export($event->data,
true));
984 dol_syslog(
"object = ".var_export($event->data,
true), LOG_DEBUG, 0,
'_payment');
985} elseif ($event->type ==
'charge.dispute.funds_withdrawn') {
987 dol_syslog(
"object = ".var_export($event->data,
true));
988 dol_syslog(
"object = ".var_export($event->data,
true), LOG_DEBUG, 0,
'_payment');
990 global $stripearrayofkeysbyenv;
993 $object = $event->data->object;
994 $TRANSACTIONID =
$object->payment_intent;
995 $ipaddress =
$object->metadata->ipaddress;
997 $currencyCodeType = strtoupper(
$object->currency);
998 $paymentmethodstripeid =
$object->payment_method;
999 $customer_id =
$object->customer;
1001 $amountdisputestripe =
$object->amount;
1002 $amountdispute = $stripe->convertAmount($amountdisputestripe, $currencyCodeType, 1);
1003 $statusdispute =
$object->status;
1006 if (isset($stripearrayofkeysbyenv[$servicestatus][
'publishable_key'])) {
1007 $pkey = $stripearrayofkeysbyenv[$servicestatus][
'publishable_key'];
1009 $LONGTRANSACTIONID = $TRANSACTIONID.
':'.$customer_id.
'@'.$pkey;
1012 $balance_transactions_array =
$object->balance_transactions;
1014 if (!empty($balance_transactions_array) && is_array($balance_transactions_array)) {
1015 foreach ($balance_transactions_array as $tmpval) {
1016 if (isset($tmpval[
'fee'])) {
1017 $feesstripe += (int) $tmpval[
'fee'];
1021 $fees = $stripe->convertAmount($feesstripe, $currencyCodeType, 1);
1024 $paymentTypeCode =
"";
1025 $paymentTypeCodeInDolibarr =
"";
1026 $payment_amount = 0;
1027 $payment_amountInDolibarr = 0;
1029 dol_syslog(
"Try to find the payment in database for the payment_intent id = ".$TRANSACTIONID);
1030 dol_syslog(
"Try to find the payment in database for the payment_intent id = ".$TRANSACTIONID, LOG_DEBUG, 0,
'_payment');
1032 $sql =
"SELECT pi.rowid, pi.fk_facture, pi.fk_prelevement_bons, pi.amount, pi.type, pi.traite";
1033 $sql .=
" FROM ".MAIN_DB_PREFIX.
"prelevement_demande as pi";
1035 $sql .=
" WHERE (pi.ext_payment_id = '".$db->escape($LONGTRANSACTIONID).
"' OR pi.ext_payment_id = '".$db->escape($TRANSACTIONID).
"')";
1036 $sql .=
" AND pi.ext_payment_site = '".$db->escape($service).
"'";
1038 $result = $db->query($sql);
1040 $obj = $db->fetch_object($result);
1042 if ($obj->type ==
'ban') {
1044 $pdid = $obj->rowid;
1045 $invoice_id = $obj->fk_facture;
1046 $directdebitorcreditransfer_id = $obj->fk_prelevement_bons;
1047 $payment_amountInDolibarr = $obj->amount;
1048 $paymentTypeCodeInDolibarr = $obj->type;
1050 dol_syslog(
"Found the payment intent for ban in database (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")");
1051 dol_syslog(
"Found the payment intent for ban in database (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")", LOG_DEBUG, 0,
'_payment');
1053 if ($obj->type ==
'card' || empty($obj->type)) {
1055 $pdid = $obj->rowid;
1056 $invoice_id = $obj->fk_facture;
1057 $directdebitorcreditransfer_id = 0;
1058 $payment_amountInDolibarr = $obj->amount;
1059 $paymentTypeCodeInDolibarr = empty($obj->type) ?
'card' : $obj->type;
1061 dol_syslog(
"Found the payment intent for card in database (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")");
1062 dol_syslog(
"Found the payment intent for card in database (pdid = ".$pdid.
" directdebitorcreditransfer_id=".$directdebitorcreditransfer_id.
")", LOG_DEBUG, 0,
'_payment');
1065 dol_syslog(
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.");
1066 dol_syslog(
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.", LOG_DEBUG, 0,
'_payment');
1067 http_response_code(200);
1068 print
"Payment intent ".$TRANSACTIONID.
" not found into database, so ignored.";
1072 http_response_code(500);
1073 print $db->lasterror();
1078 dol_syslog(
"objinvoiceid=".$invoice_id, LOG_DEBUG, 0,
'_payment');
1079 $tmpinvoice =
new Facture($db);
1080 $tmpinvoice->fetch($invoice_id);
1081 $tmpinvoice->fetch_thirdparty();
1083 dol_syslog(
"The payment disputed has the amount ".$amountdispute.
", fees of ".$fees.
" and the invoice has ".$payment_amountInDolibarr);
1084 dol_syslog(
"The payment disputed has the amount ".$amountdispute.
", fees of ".$fees.
" and the invoice has ".$payment_amountInDolibarr, LOG_DEBUG, 0,
'_payment');
1098 if ($statusdispute ==
'needs_response') {
1107 $errormsg = $tmpinvoice->error.implode(
', ', $tmpinvoice->errors);
1136 $result = $tmpinvoice->setStatut(1,
null,
'',
'FACTURE_MODIFY',
'dispute_status');
1138 $errormsg = $tmpinvoice->error.implode(
', ', $tmpinvoice->errors);
1145 dol_syslog(
"The dispute_status of invoice ".$tmpinvoice->ref.
" has been modified to 1");
1146 dol_syslog(
"The dispute_status of invoice ".$tmpinvoice->ref.
" has been modified to 1", LOG_DEBUG, 0,
'_payment');
1148 http_response_code(200);
1149 print
"Payment dispute received for ".$TRANSACTIONID.
". We have changed the status of dispute_status to 1 for invoice ".$tmpinvoice->ref;
1154 dol_syslog(
"Technicalerror ".$db->lasterror().
" - ".$errormsg, LOG_ERR);
1155 dol_syslog(
"Technicalerror ".$db->lasterror().
" - ".$errormsg, LOG_ERR, 0,
'_payment');
1157 http_response_code(500);
1158 print $db->lasterror();
1163 $accountfrom =
new Account($db);
1164 $accountfrom->fetch(
getDolGlobalInt(
'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS'));
1170 $amounts[$tmpinvoice->id] = -1 * $payment_amountInDolibarr;
1172 $paiement->datepaye =
dol_now();
1173 $paiement->amounts = $amounts;
1178 $paiement->paiementid =
dol_getIdFromCode($db,
'PRE',
'c_paiement',
'code',
'id', 1);
1179 $paiement->num_payment =
$object->id;
1180 $paiement->note_private =
'Fund withdrawn by bank with id='.$object->id.
'. Reason: '.$reason;
1181 $paiement->fk_account = $accountfrom->id;
1183 $paiement->ext_payment_id =
$object->payment_intent;
1184 $paiement->ext_payment_site = $service;
1188 $alreadytransferedinaccounting = $tmpinvoice->getVentilExportCompta();
1190 dol_syslog(
"The invoice has alreadytransferedinaccounting=".$alreadytransferedinaccounting);
1191 dol_syslog(
"The invoice has alreadytransferedinaccounting=".$alreadytransferedinaccounting, LOG_DEBUG, 0,
'_payment');
1206 $errormsg = $tmpinvoice->error.implode(
', ', $tmpinvoice->errors);
1213 $result = $tmpinvoice->setStatut(1,
null,
'',
'FACTURE_MODIFY',
'dispute_status');
1215 $errormsg = $tmpinvoice->error.implode(
', ', $tmpinvoice->errors);
1220 dol_syslog(
"The dispute_status of invoice ".$tmpinvoice->ref.
" has been modified to 1");
1221 dol_syslog(
"The dispute_status of invoice ".$tmpinvoice->ref.
" has been modified to 1", LOG_DEBUG, 0,
'_payment');
1226 $withdrawn_payment_already_exists =
true;
1227 $sql =
"SELECT p.rowid, p.ref";
1228 $sql .=
" FROM ".MAIN_DB_PREFIX.
"paiement as p";
1229 $sql .=
" WHERE p.ext_payment_id = '".$db->escape($paiement->ext_payment_id).
"'";
1230 $sql .=
" AND p.ext_payment_site = '".$db->escape($service).
"'";
1232 $tmpresql = $db->query($sql);
1234 $obj = $db->fetch_object($tmpresql);
1236 $withdrawn_payment_already_exists =
false;
1237 dol_syslog(
"No withdraw payment already exists", LOG_DEBUG);
1239 dol_syslog(
"A withdraw payment already exists", LOG_DEBUG);
1243 if (!$error && !$alreadytransferedinaccounting && !$withdrawn_payment_already_exists) {
1244 if ($paiement->fk_account > 0) {
1248 dol_syslog(
"We try to record the payment", LOG_DEBUG, 0,
'_payment');
1250 $paiement_id = $paiement->create($user, 0, $tmpinvoice->thirdparty);
1251 if ($paiement_id < 0) {
1252 $errormsg = $paiement->error.implode(
', ', $paiement->errors);
1255 $banklineid = $paiement->addPaymentToBank($user,
'payment',
'IPN Stripe dispute funds withdrawn', $paiement->fk_account,
'',
'', 1,
'',
'');
1256 if ($banklineid < 0) {
1257 $errormsg = $paiement->error.implode(
', ', $paiement->errors);
1262 dol_syslog(
"No bank account defined to record payment so no payment recorded");
1263 dol_syslog(
"No bank account defined to record payment so no payment recorded", LOG_DEBUG, 0,
'_payment');
1277 dol_syslog(
"Invoice status updated and/or Revert payment created", LOG_WARNING);
1278 dol_syslog(
"Invoice status updated and/or Revert payment created", LOG_WARNING, 0,
'_payment');
1282 dol_syslog(
"Error - Return HTTP 500 - ".$errormsg, LOG_ERR);
1283 dol_syslog(
"Error - Return HTTP 500 - ".$errormsg, LOG_ERR, 0,
'_payment');
1285 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...
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.
if(getDolGlobalString( 'TAKEPOS_SHOW_CUSTOMER')) print $langs trans('Date')." left 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 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.