Passed
Branch develop (e2dd44)
by
unknown
106:32
created

Stripe::sepaStripe()   F

Complexity

Conditions 22
Paths 973

Size

Total Lines 135
Code Lines 91

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 22
eloc 91
c 3
b 0
f 0
nc 973
nop 5
dl 0
loc 135
rs 0.0375

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* Copyright (C) 2018-2021 	Thibault FOUCART       <[email protected]>
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
 */
17
18
// Put here all includes required by your class file
19
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
20
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
21
require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
22
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
23
require_once DOL_DOCUMENT_ROOT.'/stripe/config.php'; // This set stripe global env
24
25
26
/**
27
 *	Stripe class
28
 */
29
class Stripe extends CommonObject
30
{
31
	/**
32
	 * @var int ID
33
	 */
34
	public $rowid;
35
36
	/**
37
	 * @var int Thirdparty ID
38
	 */
39
	public $fk_soc;
40
41
	/**
42
	 * @var int ID
43
	 */
44
	public $fk_key;
45
46
	/**
47
	 * @var int ID
48
	 */
49
	public $id;
50
51
	public $mode;
52
53
	/**
54
	 * @var int Entity
55
	 */
56
	public $entity;
57
58
	public $statut;
59
60
	public $type;
61
62
	public $code;
63
	public $declinecode;
64
65
	/**
66
	 * @var string Message
67
	 */
68
	public $message;
69
70
	/**
71
	 * 	Constructor
72
	 *
73
	 * 	@param	DoliDB		$db			Database handler
74
	 */
75
	public function __construct($db)
76
	{
77
		$this->db = $db;
78
	}
79
80
81
	/**
82
	 * Return main company OAuth Connect stripe account
83
	 *
84
	 * @param 	string	$mode		'StripeTest' or 'StripeLive'
85
	 * @param	int		$fk_soc		Id of thirdparty
86
	 * @param	int		$entity		Id of entity (-1 = current environment)
87
	 * @return 	string				Stripe account 'acc_....' or '' if no OAuth token found
88
	 */
89
	public function getStripeAccount($mode = 'StripeTest', $fk_soc = 0, $entity = -1)
90
	{
91
		global $conf;
92
93
		$key = '';
94
		if ($entity < 0) {
95
			$entity = $conf->entity;
96
		}
97
98
		$sql = "SELECT tokenstring";
99
		$sql .= " FROM ".MAIN_DB_PREFIX."oauth_token";
100
		$sql .= " WHERE service = '".$this->db->escape($mode)."'";
101
		$sql .= " AND entity = ".((int) $entity);
102
		if ($fk_soc > 0) {
103
			$sql .= " AND fk_soc = ".((int) $fk_soc);
104
		} else {
105
			$sql .= " AND fk_soc IS NULL";
106
		}
107
		$sql .= " AND fk_user IS NULL AND fk_adherent IS NULL";
108
109
		dol_syslog(get_class($this)."::getStripeAccount", LOG_DEBUG);
110
111
		$result = $this->db->query($sql);
112
		if ($result) {
113
			if ($this->db->num_rows($result)) {
114
				$obj = $this->db->fetch_object($result);
115
				$tokenstring = $obj->tokenstring;
116
117
				$tmparray = json_decode($tokenstring);
118
				$key = empty($tmparray->stripe_user_id) ? '' : $tmparray->stripe_user_id;
119
			} else {
120
				$tokenstring = '';
121
			}
122
		} else {
123
			dol_print_error($this->db);
124
		}
125
126
		dol_syslog("No dedicated Stripe Connect account available for entity ".$conf->entity);
127
		return $key;
128
	}
129
130
	/**
131
	 * getStripeCustomerAccount
132
	 *
133
	 * @param	int		$id				Id of third party
134
	 * @param	int		$status			Status
135
	 * @param	string	$site_account 	Value to use to identify with account to use on site when site can offer several accounts. For example: 'pk_live_123456' when using Stripe service.
136
	 * @return	string					Stripe customer ref 'cu_xxxxxxxxxxxxx' or ''
137
	 */
138
	public function getStripeCustomerAccount($id, $status = 0, $site_account = '')
139
	{
140
		include_once DOL_DOCUMENT_ROOT.'/societe/class/societeaccount.class.php';
141
		$societeaccount = new SocieteAccount($this->db);
142
		return $societeaccount->getCustomerAccount($id, 'stripe', $status, $site_account); // Get thirdparty cus_...
143
	}
144
145
146
	/**
147
	 * Get the Stripe customer of a thirdparty (with option to create it in Stripe if not linked yet).
148
	 * Search on site_account = 0 or = $stripearrayofkeysbyenv[$status]['publishable_key']
149
	 *
150
	 * @param	Societe	$object							Object thirdparty to check, or create on stripe (create on stripe also update the stripe_account table for current entity)
151
	 * @param	string	$key							''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
152
	 * @param	int		$status							Status (0=test, 1=live)
153
	 * @param	int		$createifnotlinkedtostripe		1=Create the stripe customer and the link if the thirdparty is not yet linked to a stripe customer
154
	 * @return 	\Stripe\StripeCustomer|null 			Stripe Customer or null if not found
0 ignored issues
show
Bug introduced by
The type Stripe\StripeCustomer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
155
	 */
156
	public function customerStripe(Societe $object, $key = '', $status = 0, $createifnotlinkedtostripe = 0)
157
	{
158
		global $conf, $user;
159
160
		if (empty($object->id)) {
161
			dol_syslog("customerStripe is called with the parameter object that is not loaded");
162
			return null;
163
		}
164
165
		$customer = null;
166
167
		// Force to use the correct API key
168
		global $stripearrayofkeysbyenv;
169
		\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
0 ignored issues
show
Bug introduced by
The type Stripe\Stripe was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
170
171
		$sql = "SELECT sa.key_account as key_account, sa.entity"; // key_account is cus_....
172
		$sql .= " FROM ".MAIN_DB_PREFIX."societe_account as sa";
173
		$sql .= " WHERE sa.fk_soc = ".((int) $object->id);
174
		$sql .= " AND sa.entity IN (".getEntity('societe').")";
175
		$sql .= " AND sa.site = 'stripe' AND sa.status = ".((int) $status);
176
		$sql .= " AND (sa.site_account IS NULL OR sa.site_account = '' OR sa.site_account = '".$this->db->escape($stripearrayofkeysbyenv[$status]['publishable_key'])."')";
177
		$sql .= " AND sa.key_account IS NOT NULL AND sa.key_account <> ''";
178
179
		dol_syslog(get_class($this)."::customerStripe search stripe customer id for thirdparty id=".$object->id, LOG_DEBUG);
180
		$resql = $this->db->query($sql);
181
		if ($resql) {
182
			$num = $this->db->num_rows($resql);
183
			if ($num) {
184
				$obj = $this->db->fetch_object($resql);
185
				$tiers = $obj->key_account;
186
187
				dol_syslog(get_class($this)."::customerStripe found stripe customer key_account = ".$tiers.". We will try to read it on Stripe with publishable_key = ".$stripearrayofkeysbyenv[$status]['publishable_key']);
188
189
				try {
190
					if (empty($key)) {				// If the Stripe connect account not set, we use common API usage
191
						//$customer = \Stripe\Customer::retrieve("$tiers");
192
						$customer = \Stripe\Customer::retrieve(array('id'=>"$tiers", 'expand[]'=>'sources'));
0 ignored issues
show
Bug introduced by
The type Stripe\Customer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
193
					} else {
194
						//$customer = \Stripe\Customer::retrieve("$tiers", array("stripe_account" => $key));
195
						$customer = \Stripe\Customer::retrieve(array('id'=>"$tiers", 'expand[]'=>'sources'), array("stripe_account" => $key));
196
					}
197
				} catch (Exception $e) {
198
					// For exemple, we may have error: 'No such customer: cus_XXXXX; a similar object exists in live mode, but a test mode key was used to make this request.'
199
					$this->error = $e->getMessage();
200
				}
201
			} elseif ($createifnotlinkedtostripe) {
202
				$ipaddress = getUserRemoteIP();
203
204
				$dataforcustomer = array(
205
					"email" => $object->email,
206
					"description" => $object->name,
207
					"metadata" => array('dol_id'=>$object->id, 'dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress)
208
				);
209
210
				$vatcleaned = $object->tva_intra ? $object->tva_intra : null;
211
212
				/*
213
				$taxinfo = array('type'=>'vat');
214
				if ($vatcleaned)
215
				{
216
					$taxinfo["tax_id"] = $vatcleaned;
217
				}
218
				// We force data to "null" if not defined as expected by Stripe
219
				if (empty($vatcleaned)) $taxinfo=null;
220
				$dataforcustomer["tax_info"] = $taxinfo;
221
				*/
222
223
				//$a = \Stripe\Stripe::getApiKey();
224
				//var_dump($a);var_dump($key);exit;
225
				try {
226
					// Force to use the correct API key
227
					global $stripearrayofkeysbyenv;
228
					\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
229
230
					if (empty($key)) {				// If the Stripe connect account not set, we use common API usage
231
						$customer = \Stripe\Customer::create($dataforcustomer);
232
					} else {
233
						$customer = \Stripe\Customer::create($dataforcustomer, array("stripe_account" => $key));
234
					}
235
236
					// Create the VAT record in Stripe
237
					if (!empty($conf->global->STRIPE_SAVE_TAX_IDS)) {	// We setup to save Tax info on Stripe side. Warning: This may result in error when saving customer
238
						if (!empty($vatcleaned)) {
239
							$isineec = isInEEC($object);
240
							if ($object->country_code && $isineec) {
241
								//$taxids = $customer->allTaxIds($customer->id);
242
								$customer->createTaxId($customer->id, array('type'=>'eu_vat', 'value'=>$vatcleaned));
243
							}
244
						}
245
					}
246
247
					// Create customer in Dolibarr
248
					$sql = "INSERT INTO ".MAIN_DB_PREFIX."societe_account (fk_soc, login, key_account, site, site_account, status, entity, date_creation, fk_user_creat)";
249
					$sql .= " VALUES (".((int) $object->id).", '', '".$this->db->escape($customer->id)."', 'stripe', '".$this->db->escape($stripearrayofkeysbyenv[$status]['publishable_key'])."', ".((int) $status).", ".((int) $conf->entity).", '".$this->db->idate(dol_now())."', ".((int) $user->id).")";
250
					$resql = $this->db->query($sql);
251
					if (!$resql) {
252
						$this->error = $this->db->lasterror();
253
					}
254
				} catch (Exception $e) {
255
					$this->error = $e->getMessage();
256
				}
257
			}
258
		} else {
259
			dol_print_error($this->db);
260
		}
261
262
		return $customer;
263
	}
264
265
	/**
266
	 * Get the Stripe payment method Object from its ID
267
	 *
268
	 * @param	string	$paymentmethod	   			Payment Method ID
269
	 * @param	string	$key						''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
270
	 * @param	int		$status						Status (0=test, 1=live)
271
	 * @return 	\Stripe\PaymentMethod|null 			Stripe PaymentMethod or null if not found
272
	 */
273
	public function getPaymentMethodStripe($paymentmethod, $key = '', $status = 0)
274
	{
275
		$stripepaymentmethod = null;
276
277
		try {
278
			// Force to use the correct API key
279
			global $stripearrayofkeysbyenv;
280
			\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
281
			if (empty($key)) {				// If the Stripe connect account not set, we use common API usage
282
				$stripepaymentmethod = \Stripe\PaymentMethod::retrieve((string) $paymentmethod->id);
0 ignored issues
show
Bug introduced by
The property id does not exist on string.
Loading history...
Bug introduced by
The type Stripe\PaymentMethod was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
283
			} else {
284
				$stripepaymentmethod = \Stripe\PaymentMethod::retrieve((string) $paymentmethod->id, array("stripe_account" => $key));
285
			}
286
		} catch (Exception $e) {
287
			$this->error = $e->getMessage();
288
		}
289
290
		return $stripepaymentmethod;
291
	}
292
293
	/**
294
	 * Get the Stripe reader Object from its ID
295
	 *
296
	 * @param	string	$reader	   			Reader ID
297
	 * @param	string	$key				''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
298
	 * @param	int	$status				Status (0=test, 1=live)
299
	 * @return 	\Stripe\Terminal\Reader|null		Stripe Reader or null if not found
300
	 */
301
	public function getSelectedReader($reader, $key = '', $status = 0)
302
	{
303
		$selectedreader = null;
304
305
		try {
306
			// Force to use the correct API key
307
			global $stripearrayofkeysbyenv;
308
			\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
309
			if (empty($key)) {				// If the Stripe connect account not set, we use common API usage
310
				$selectedreader = \Stripe\Terminal\Reader::retrieve((string) $reader);
0 ignored issues
show
Bug introduced by
The type Stripe\Terminal\Reader was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
311
			} else {
312
				$stripepaymentmethod = \Stripe\Terminal\Reader::retrieve((string) $reader, array("stripe_account" => $key));
313
			}
314
		} catch (Exception $e) {
315
			$this->error = $e->getMessage();
316
		}
317
318
		return $selectedreader;
319
	}
320
321
	/**
322
	 * Get the Stripe payment intent. Create it with confirmnow=false
323
	 * Warning. If a payment was tried and failed, a payment intent was created.
324
	 * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed by Stripe.
325
	 * Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay),
326
	 * that's why i comment the part of code to retrieve a payment intent with object id (never mind if we cumulate payment intent with old ones that will not be used)
327
	 * Note: This is used when option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is on when making a payment from the public/payment/newpayment.php page
328
	 * but not when using the STRIPE_USE_NEW_CHECKOUT.
329
	 *
330
	 * @param   double  $amount                             Amount
331
	 * @param   string  $currency_code                      Currency code
332
	 * @param   string  $tag                                Tag
333
	 * @param   string  $description                        Description
334
	 * @param	mixed	$object							    Object to pay with Stripe
335
	 * @param	string 	$customer							Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
336
	 * @param	string	$key							    ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
337
	 * @param	int		$status							    Status (0=test, 1=live)
338
	 * @param	int		$usethirdpartyemailforreceiptemail	1=use thirdparty email for receipt
339
	 * @param	int		$mode		                        automatic=automatic confirmation/payment when conditions are ok, manual=need to call confirm() on intent
340
	 * @param   boolean $confirmnow                         false=default, true=try to confirm immediatly after create (if conditions are ok)
341
	 * @param   string  $payment_method                     'pm_....' (if known)
342
	 * @param   string  $off_session                        If we use an already known payment method to pay when customer is not available during the checkout flow.
343
	 * @param	string	$noidempotency_key					Do not use the idempotency_key when creating the PaymentIntent
344
	 * @return 	\Stripe\PaymentIntent|null 			        Stripe PaymentIntent or null if not found and failed to create
345
	 */
346
	public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false, $payment_method = null, $off_session = 0, $noidempotency_key = 1)
347
	{
348
		global $conf, $user;
349
350
		dol_syslog(get_class($this)."::getPaymentIntent", LOG_INFO, 1);
351
352
		$error = 0;
353
354
		if (empty($status)) {
355
			$service = 'StripeTest';
356
		} else {
357
			$service = 'StripeLive';
358
		}
359
360
		$arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
361
		if (!in_array($currency_code, $arrayzerounitcurrency)) {
362
			$stripeamount = $amount * 100;
363
		} else {
364
			$stripeamount = $amount;
365
		}
366
367
		$fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE;
368
		if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
369
			$fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL;
370
		} elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
371
			$fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL;
372
		}
373
		if (!in_array($currency_code, $arrayzerounitcurrency)) {
374
			$stripefee = round($fee * 100);
375
		} else {
376
			$stripefee = round($fee);
377
		}
378
379
		$paymentintent = null;
380
381
		if (is_object($object) && getDolGlobalInt('STRIPE_REUSE_EXISTING_INTENT_IF_FOUND') && !getDolGlobalInt('STRIPE_CARD_PRESENT')) {
382
			// Warning. If a payment was tried and failed, a payment intent was created.
383
			// But if we change something on object to pay (amount or other that does not change the idempotency key), reusing same payment intent is not allowed by Stripe.
384
			// Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed by Stripe after a delay), Stripe will
385
			// automatically return the existing payment intent if idempotency is provided when we try to create the new one.
386
			// That's why we can comment the part of code to retrieve a payment intent with object id (never mind if we cumulate payment intent with old ones that will not be used)
387
388
			$sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site";
389
			$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pi";
390
			$sql .= " WHERE pi.fk_facture = ".((int) $object->id);
391
			$sql .= " AND pi.sourcetype = '".$this->db->escape($object->element)."'";
392
			$sql .= " AND pi.entity IN (".getEntity('societe').")";
393
			$sql .= " AND pi.ext_payment_site = '".$this->db->escape($service)."'";
394
395
			dol_syslog(get_class($this)."::getPaymentIntent search stripe payment intent for object id = ".$object->id, LOG_DEBUG);
396
			$resql = $this->db->query($sql);
397
			if ($resql) {
398
				$num = $this->db->num_rows($resql);
399
				if ($num) {
400
					$obj = $this->db->fetch_object($resql);
401
					$intent = $obj->ext_payment_id;
402
403
					dol_syslog(get_class($this)."::getPaymentIntent found existing payment intent record");
404
405
					// Force to use the correct API key
406
					global $stripearrayofkeysbyenv;
407
					\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
408
409
					try {
410
						if (empty($key)) {				// If the Stripe connect account not set, we use common API usage
411
							$paymentintent = \Stripe\PaymentIntent::retrieve($intent);
0 ignored issues
show
Bug introduced by
The type Stripe\PaymentIntent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
412
						} else {
413
							$paymentintent = \Stripe\PaymentIntent::retrieve($intent, array("stripe_account" => $key));
414
						}
415
					} catch (Exception $e) {
416
						$error++;
417
						$this->error = $e->getMessage();
418
					}
419
				}
420
			}
421
		}
422
423
		if (empty($paymentintent)) {
424
			// Try to create intent. See https://stripe.com/docs/api/payment_intents/create
425
			$ipaddress = getUserRemoteIP();
426
			$metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress);
427
			if (is_object($object)) {
428
				$metadata['dol_type'] = $object->element;
429
				$metadata['dol_id'] = $object->id;
430
				if (is_object($object->thirdparty) && $object->thirdparty->id > 0) {
431
					$metadata['dol_thirdparty_id'] = $object->thirdparty->id;
432
				}
433
			}
434
435
			// list of payment method types
436
			$paymentmethodtypes = array("card");
437
			$descriptor = dol_trunc($tag, 10, 'right', 'UTF-8', 1);
438
			if (getDolGlobalInt('STRIPE_SEPA_DIRECT_DEBIT')) {
439
				$paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
440
				//$descriptor = preg_replace('/ref=[^:=]+/', '', $descriptor);	// Clean ref
441
			}
442
			if (getDolGlobalInt('STRIPE_KLARNA')) {
443
				$paymentmethodtypes[] = "klarna";
444
			}
445
			if (getDolGlobalInt('STRIPE_BANCONTACT')) {
446
				$paymentmethodtypes[] = "bancontact";
447
			}
448
			if (getDolGlobalInt('STRIPE_IDEAL')) {
449
				$paymentmethodtypes[] = "ideal";
450
			}
451
			if (getDolGlobalInt('STRIPE_GIROPAY')) {
452
				$paymentmethodtypes[] = "giropay";
453
			}
454
			if (getDolGlobalInt('STRIPE_SOFORT')) {
455
				$paymentmethodtypes[] = "sofort";
456
			}
457
			if (getDolGlobalInt('STRIPE_CARD_PRESENT') && $mode == 'terminal') {
458
				$paymentmethodtypes = array("card_present");
459
			}
460
461
			$dataforintent = array(
462
				"confirm" => $confirmnow, // Do not confirm immediatly during creation of intent
463
				"confirmation_method" => $mode,
464
				"amount" => $stripeamount,
465
				"currency" => $currency_code,
466
				"payment_method_types" => $paymentmethodtypes,
467
				"description" => $description,
468
				"statement_descriptor_suffix" => $descriptor, // For card payment, 22 chars that appears on bank receipt (prefix into stripe setup + this suffix)
469
				"statement_descriptor" => $descriptor, // For SEPA, it will take only statement_descriptor, not statement_descriptor_suffix
470
				//"save_payment_method" => true,
471
				"setup_future_usage" => "on_session",
472
				"metadata" => $metadata
473
			);
474
			if (!is_null($customer)) {
475
				$dataforintent["customer"] = $customer;
476
			}
477
			// payment_method =
478
			// payment_method_types = array('card')
479
			//var_dump($dataforintent);
480
			if ($off_session) {
481
				unset($dataforintent['setup_future_usage']);
482
				// We can't use both "setup_future_usage" = "off_session" and "off_session" = true.
483
				// Because $off_session parameter is dedicated to create paymentintent off_line (and not future payment), we need to use "off_session" = true.
484
				//$dataforintent["setup_future_usage"] = "off_session";
485
				$dataforintent["off_session"] = true;
486
			}
487
			if (getDolGlobalInt('STRIPE_GIROPAY')) {
488
				unset($dataforintent['setup_future_usage']);
489
			}
490
			if (getDolGlobalInt('STRIPE_KLARNA')) {
491
				unset($dataforintent['setup_future_usage']);
492
			}
493
			if (getDolGlobalInt('STRIPE_CARD_PRESENT') && $mode == 'terminal') {
494
				unset($dataforintent['setup_future_usage']);
495
				$dataforintent["capture_method"] = "manual";
496
				$dataforintent["confirmation_method"] = "manual";
497
			}
498
			if (!is_null($payment_method)) {
499
				$dataforintent["payment_method"] = $payment_method;
500
				$description .= ' - '.$payment_method;
501
			}
502
503
			if ($conf->entity != getDolGlobalInt('STRIPECONNECT_PRINCIPAL') && $stripefee > 0) {
504
				$dataforintent["application_fee_amount"] = $stripefee;
505
			}
506
			if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) {
507
				$dataforintent["receipt_email"] = $object->thirdparty->email;
508
			}
509
510
			try {
511
				// Force to use the correct API key
512
				global $stripearrayofkeysbyenv;
513
				\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
514
515
				$arrayofoptions = array();
516
				if (empty($noidempotency_key)) {
517
					$arrayofoptions["idempotency_key"] = $description;
518
				}
519
				// Note: If all data for payment intent are same than a previous on, even if we use 'create', Stripe will return ID of the old existing payment intent.
520
				if (!empty($key)) {				// If the Stripe connect account not set, we use common API usage
521
					$arrayofoptions["stripe_account"] = $key;
522
				}
523
524
				dol_syslog("dataforintent to create paymentintent = ".var_export($dataforintent, true));
525
526
				$paymentintent = \Stripe\PaymentIntent::create($dataforintent, $arrayofoptions);
527
528
				// Store the payment intent
529
				if (is_object($object)) {
530
					$paymentintentalreadyexists = 0;
531
					// Check that payment intent $paymentintent->id is not already recorded.
532
					$sql = "SELECT pi.rowid";
533
					$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pi";
534
					$sql .= " WHERE pi.entity IN (".getEntity('societe').")";
535
					$sql .= " AND pi.ext_payment_site = '".$this->db->escape($service)."'";
536
					$sql .= " AND pi.ext_payment_id = '".$this->db->escape($paymentintent->id)."'";
537
538
					dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
539
					$resql = $this->db->query($sql);
540
					if ($resql) {
541
						$num = $this->db->num_rows($resql);
542
						if ($num) {
543
							$obj = $this->db->fetch_object($resql);
544
							if ($obj) {
545
								$paymentintentalreadyexists++;
546
							}
547
						}
548
					} else {
549
						dol_print_error($this->db);
550
					}
551
552
					// If not, we create it.
553
					if (!$paymentintentalreadyexists) {
554
						$now = dol_now();
555
						$sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site, amount)";
556
						$sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $user->id).", '".$this->db->escape($paymentintent->id)."', ".((int) $object->id).", '".$this->db->escape($object->element)."', ".((int) $conf->entity).", '".$this->db->escape($service)."', ".((float) $amount).")";
557
						$resql = $this->db->query($sql);
558
						if (!$resql) {
559
							$error++;
560
							$this->error = $this->db->lasterror();
561
							dol_syslog(get_class($this)."::PaymentIntent failed to insert paymentintent with id=".$paymentintent->id." into database.", LOG_ERR);
562
						}
563
					}
564
				} else {
565
					$_SESSION["stripe_payment_intent"] = $paymentintent;
566
				}
567
			} catch (Stripe\Error\Card $e) {
0 ignored issues
show
Bug introduced by
The type Stripe\Error\Card was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
568
				$error++;
569
				$this->error = $e->getMessage();
570
				$this->code = $e->getStripeCode();
571
				$this->declinecode = $e->getDeclineCode();
572
			} catch (Exception $e) {
573
				//var_dump($dataforintent);
574
				//var_dump($description);
575
				//var_dump($key);
576
				//var_dump($paymentintent);
577
				//var_dump($e->getMessage());
578
				//var_dump($e);
579
				$error++;
580
				$this->error = $e->getMessage();
581
				$this->code = '';
582
				$this->declinecode = '';
583
			}
584
		}
585
586
		dol_syslog(get_class($this)."::getPaymentIntent return error=".$error." this->error=".$this->error, LOG_INFO, -1);
587
588
		if (!$error) {
589
			return $paymentintent;
590
		} else {
591
			return null;
592
		}
593
	}
594
595
	/**
596
	 * Get the Stripe payment intent. Create it with confirmnow=false
597
	 * Warning. If a payment was tried and failed, a payment intent was created.
598
	 * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed.
599
	 * Recommanded solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay),
600
	 * that's why i comment the part of code to retrieve a payment intent with object id (never mind if we cumulate payment intent with old ones that will not be used)
601
	 * Note: This is used when option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is on when making a payment from the public/payment/newpayment.php page
602
	 * but not when using the STRIPE_USE_NEW_CHECKOUT.
603
	 *
604
	 * @param   string  $description                        Description
605
	 * @param	Societe	$object							    Object of company to link the Stripe payment mode with
606
	 * @param	string 	$customer							Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
607
	 * @param	string	$key							    ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
608
	 * @param	int		$status							    Status (0=test, 1=live)
609
	 * @param	int		$usethirdpartyemailforreceiptemail	1=use thirdparty email for receipt
610
	 * @param   boolean $confirmnow                         false=default, true=try to confirm immediatly after create (if conditions are ok)
611
	 * @return 	\Stripe\SetupIntent|null 			        Stripe SetupIntent or null if not found and failed to create
612
	 */
613
	public function getSetupIntent($description, $object, $customer, $key, $status, $usethirdpartyemailforreceiptemail = 0, $confirmnow = false)
614
	{
615
		global $conf;
616
617
		dol_syslog("getSetupIntent description=".$description.' confirmnow='.$confirmnow, LOG_INFO, 1);
618
619
		$error = 0;
620
621
		if (empty($status)) {
622
			$service = 'StripeTest';
623
		} else {
624
			$service = 'StripeLive';
625
		}
626
627
		$setupintent = null;
628
629
		if (empty($setupintent)) {
0 ignored issues
show
introduced by
The condition empty($setupintent) is always false.
Loading history...
630
			$ipaddress = getUserRemoteIP();
631
			$metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress);
632
			if (is_object($object)) {
633
				$metadata['dol_type'] = $object->element;
634
				$metadata['dol_id'] = $object->id;
635
				if (is_object($object->thirdparty) && $object->thirdparty->id > 0) {
636
					$metadata['dol_thirdparty_id'] = $object->thirdparty->id;
637
				}
638
			}
639
640
			// list of payment method types
641
			$paymentmethodtypes = array("card");
642
			if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT)) {
643
				$paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
644
			}
645
			if (!empty($conf->global->STRIPE_BANCONTACT)) {
646
				$paymentmethodtypes[] = "bancontact";
647
			}
648
			if (!empty($conf->global->STRIPE_IDEAL)) {
649
				$paymentmethodtypes[] = "ideal";
650
			}
651
			// Giropay not possible for setup intent
652
			if (!empty($conf->global->STRIPE_SOFORT)) {
653
				$paymentmethodtypes[] = "sofort";
654
			}
655
656
			$dataforintent = array(
657
				"confirm" => $confirmnow, // Do not confirm immediatly during creation of intent
658
				"payment_method_types" => $paymentmethodtypes,
659
				"usage" => "off_session",
660
				"metadata" => $metadata
661
			);
662
			if (!is_null($customer)) {
663
				$dataforintent["customer"] = $customer;
664
			}
665
			if (!is_null($description)) {
666
				$dataforintent["description"] = $description;
667
			}
668
			// payment_method =
669
			// payment_method_types = array('card')
670
			//var_dump($dataforintent);
671
672
			if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) {
673
				$dataforintent["receipt_email"] = $object->thirdparty->email;
674
			}
675
676
			try {
677
				// Force to use the correct API key
678
				global $stripearrayofkeysbyenv;
679
				\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
680
681
				dol_syslog("getSetupIntent ".$stripearrayofkeysbyenv[$status]['publishable_key'], LOG_DEBUG);
682
683
				// Note: If all data for payment intent are same than a previous on, even if we use 'create', Stripe will return ID of the old existing payment intent.
684
				if (empty($key)) {				// If the Stripe connect account not set, we use common API usage
685
					//$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description"));
686
					$setupintent = \Stripe\SetupIntent::create($dataforintent, array());
0 ignored issues
show
Bug introduced by
The type Stripe\SetupIntent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
687
				} else {
688
					//$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key));
689
					$setupintent = \Stripe\SetupIntent::create($dataforintent, array("stripe_account" => $key));
690
				}
691
				//var_dump($setupintent->id);
692
693
				// Store the setup intent
694
				/*if (is_object($object))
695
				{
696
					$setupintentalreadyexists = 0;
697
					// Check that payment intent $setupintent->id is not already recorded.
698
					$sql = "SELECT pi.rowid";
699
					$sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_demande as pi";
700
					$sql.= " WHERE pi.entity IN (".getEntity('societe').")";
701
					$sql.= " AND pi.ext_payment_site = '" . $this->db->escape($service) . "'";
702
					$sql.= " AND pi.ext_payment_id = '".$this->db->escape($setupintent->id)."'";
703
704
					dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
705
					$resql = $this->db->query($sql);
706
					if ($resql) {
707
						$num = $this->db->num_rows($resql);
708
						if ($num)
709
						{
710
							$obj = $this->db->fetch_object($resql);
711
							if ($obj) $setupintentalreadyexists++;
712
						}
713
					}
714
					else dol_print_error($this->db);
715
716
					// If not, we create it.
717
					if (! $setupintentalreadyexists)
718
					{
719
						$now=dol_now();
720
						$sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site)";
721
						$sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $user->id).", '".$this->db->escape($setupintent->id)."', ".((int) $object->id).", '".$this->db->escape($object->element)."', " . ((int) $conf->entity) . ", '" . $this->db->escape($service) . "', ".((float) $amount).")";
722
						$resql = $this->db->query($sql);
723
						if (! $resql)
724
						{
725
							$error++;
726
							$this->error = $this->db->lasterror();
727
							dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$setupintent->id." into database.");
728
						}
729
					}
730
				}
731
				else
732
				{
733
					$_SESSION["stripe_setup_intent"] = $setupintent;
734
				}*/
735
			} catch (Exception $e) {
736
				//var_dump($dataforintent);
737
				//var_dump($description);
738
				//var_dump($key);
739
				//var_dump($setupintent);
740
				//var_dump($e->getMessage());
741
				$error++;
742
				$this->error = $e->getMessage();
743
			}
744
		}
745
746
		if (!$error) {
747
			dol_syslog("getSetupIntent ".(is_object($setupintent) ? $setupintent->id : ''), LOG_INFO, -1);
748
			return $setupintent;
749
		} else {
750
			dol_syslog("getSetupIntent return error=".$error, LOG_INFO, -1);
751
			return null;
752
		}
753
	}
754
755
756
	/**
757
	 * Get the Stripe card of a company payment mode (option to create it on Stripe if not linked yet is no more available on new Stripe API)
758
	 *
759
	 * @param	\Stripe\StripeCustomer	$cu								Object stripe customer.
760
	 * @param	CompanyPaymentMode		$object							Object companypaymentmode to check, or create on stripe (create on stripe also update the societe_rib table for current entity)
761
	 * @param	string					$stripeacc						''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
762
	 * @param	int						$status							Status (0=test, 1=live)
763
	 * @param	int						$createifnotlinkedtostripe		1=Create the stripe card and the link if the card is not yet linked to a stripe card. Deprecated with new Stripe API and SCA.
764
	 * @return 	\Stripe\StripeCard|\Stripe\PaymentMethod|null 			Stripe Card or null if not found
765
	 */
766
	public function cardStripe($cu, CompanyPaymentMode $object, $stripeacc = '', $status = 0, $createifnotlinkedtostripe = 0)
767
	{
768
		global $conf, $user, $langs;
769
770
		$card = null;
771
772
		$sql = "SELECT sa.stripe_card_ref, sa.proprio, sa.exp_date_month, sa.exp_date_year, sa.number, sa.cvn"; // stripe_card_ref is card_....
773
		$sql .= " FROM ".MAIN_DB_PREFIX."societe_rib as sa";
774
		$sql .= " WHERE sa.rowid = ".((int) $object->id); // We get record from ID, no need for filter on entity
775
		$sql .= " AND sa.type = 'card'";
776
777
		dol_syslog(get_class($this)."::cardStripe search stripe card id for paymentmode id=".$object->id.", stripeacc=".$stripeacc.", status=".$status.", createifnotlinkedtostripe=".$createifnotlinkedtostripe, LOG_DEBUG);
778
		$resql = $this->db->query($sql);
779
		if ($resql) {
780
			$num = $this->db->num_rows($resql);
781
			if ($num) {
782
				$obj = $this->db->fetch_object($resql);
783
				$cardref = $obj->stripe_card_ref;
784
				dol_syslog(get_class($this)."::cardStripe cardref=".$cardref);
785
				if ($cardref) {
786
					try {
787
						if (empty($stripeacc)) {				// If the Stripe connect account not set, we use common API usage
788
							if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
789
								$card = $cu->sources->retrieve($cardref);
790
							} else {
791
								$card = \Stripe\PaymentMethod::retrieve($cardref);
792
							}
793
						} else {
794
							if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
795
								//$card = $cu->sources->retrieve($cardref, array("stripe_account" => $stripeacc));		// this API fails when array stripe_account is provided
796
								$card = $cu->sources->retrieve($cardref);
797
							} else {
798
								//$card = \Stripe\PaymentMethod::retrieve($cardref, array("stripe_account" => $stripeacc));		// Don't know if this works
799
								$card = \Stripe\PaymentMethod::retrieve($cardref);
800
							}
801
						}
802
					} catch (Exception $e) {
803
						$this->error = $e->getMessage();
804
						dol_syslog($this->error, LOG_WARNING);
805
					}
806
				} elseif ($createifnotlinkedtostripe) {
807
					// Deprecated with new Stripe API and SCA. We should not use anymore this part of code now.
808
					$exp_date_month = $obj->exp_date_month;
809
					$exp_date_year = $obj->exp_date_year;
810
					$number = $obj->number;
811
					$cvc = $obj->cvn; // cvn in database, cvc for stripe
812
					$cardholdername = $obj->proprio;
813
814
					$ipaddress = getUserRemoteIP();
815
816
					$dataforcard = array(
817
						"source" => array(
818
							'object'=>'card',
819
							'exp_month'=>$exp_date_month,
820
							'exp_year'=>$exp_date_year,
821
							'number'=>$number,
822
							'cvc'=>$cvc,
823
							'name'=>$cardholdername
824
						),
825
						"metadata" => array(
826
							'dol_type'=>$object->element,
827
							'dol_id'=>$object->id,
828
							'dol_version'=>DOL_VERSION,
829
							'dol_entity'=>$conf->entity,
830
							'ipaddress'=>$ipaddress
831
						)
832
					);
833
834
					//$a = \Stripe\Stripe::getApiKey();
835
					//var_dump($a);
836
					//var_dump($stripeacc);exit;
837
					try {
838
						if (empty($stripeacc)) {				// If the Stripe connect account not set, we use common API usage
839
							if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
840
								dol_syslog("Try to create card with dataforcard = ".json_encode($dataforcard));
841
								$card = $cu->sources->create($dataforcard);
842
								if (!$card) {
843
									$this->error = 'Creation of card on Stripe has failed';
844
								}
845
							} else {
846
								$connect = '';
847
								if (!empty($stripeacc)) {
848
									$connect = $stripeacc.'/';
849
								}
850
								$url = 'https://dashboard.stripe.com/'.$connect.'test/customers/'.$cu->id;
851
								if ($status) {
852
									$url = 'https://dashboard.stripe.com/'.$connect.'customers/'.$cu->id;
853
								}
854
								$urtoswitchonstripe = ' <a href="'.$url.'" target="_stripe">'.img_picto($langs->trans('ShowInStripe'), 'globe').'</a>';
855
856
								//dol_syslog("Error: This case is not supported", LOG_ERR);
857
								$this->error = $langs->trans('CreationOfPaymentModeMustBeDoneFromStripeInterface', $urtoswitchonstripe);
858
							}
859
						} else {
860
							if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
861
								dol_syslog("Try to create card with dataforcard = ".json_encode($dataforcard));
862
								$card = $cu->sources->create($dataforcard, array("stripe_account" => $stripeacc));
863
								if (!$card) {
864
									$this->error = 'Creation of card on Stripe has failed';
865
								}
866
							} else {
867
								$connect = '';
868
								if (!empty($stripeacc)) {
869
									$connect = $stripeacc.'/';
870
								}
871
								$url = 'https://dashboard.stripe.com/'.$connect.'test/customers/'.$cu->id;
872
								if ($status) {
873
									$url = 'https://dashboard.stripe.com/'.$connect.'customers/'.$cu->id;
874
								}
875
								$urtoswitchonstripe = ' <a href="'.$url.'" target="_stripe">'.img_picto($langs->trans('ShowInStripe'), 'globe').'</a>';
876
877
								//dol_syslog("Error: This case is not supported", LOG_ERR);
878
								$this->error = $langs->trans('CreationOfPaymentModeMustBeDoneFromStripeInterface', $urtoswitchonstripe);
879
							}
880
						}
881
882
						if ($card) {
883
							$sql = "UPDATE ".MAIN_DB_PREFIX."societe_rib";
884
							$sql .= " SET stripe_card_ref = '".$this->db->escape($card->id)."', card_type = '".$this->db->escape($card->brand)."',";
885
							$sql .= " country_code = '".$this->db->escape($card->country)."',";
886
							$sql .= " approved = ".($card->cvc_check == 'pass' ? 1 : 0);
887
							$sql .= " WHERE rowid = ".((int) $object->id);
888
							$sql .= " AND type = 'card'";
889
							$resql = $this->db->query($sql);
890
							if (!$resql) {
891
								$this->error = $this->db->lasterror();
892
							}
893
						}
894
					} catch (Exception $e) {
895
						$this->error = $e->getMessage();
896
						dol_syslog($this->error, LOG_WARNING);
897
					}
898
				}
899
			}
900
		} else {
901
			dol_print_error($this->db);
902
		}
903
904
		return $card;
905
	}
906
907
908
	/**
909
	 * Get the Stripe SEPA of a company payment mode
910
	 *
911
	 * @param	\Stripe\StripeCustomer	$cu								Object stripe customer.
912
	 * @param	CompanyPaymentMode		$object							Object companypaymentmode to check, or create on stripe (create on stripe also update the societe_rib table for current entity)
913
	 * @param	string					$stripeacc						''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
914
	 * @param	int						$status							Status (0=test, 1=live)
915
	 * @param	int						$createifnotlinkedtostripe		1=Create the stripe sepa and the link if the sepa is not yet linked to a stripe sepa. Used by the "Create bank to Stripe" feature.
916
	 * @return 	\Stripe\PaymentMethod|null 								Stripe SEPA or null if not found
917
	 */
918
	public function sepaStripe($cu, CompanyPaymentMode $object, $stripeacc = '', $status = 0, $createifnotlinkedtostripe = 0)
919
	{
920
		global $conf, $user, $langs;
921
		$sepa = null;
922
923
		$sql = "SELECT sa.stripe_card_ref, sa.proprio, sa.iban_prefix, sa.rum"; // stripe_card_ref is 'src_...' for Stripe SEPA
924
		$sql .= " FROM ".MAIN_DB_PREFIX."societe_rib as sa";
925
		$sql .= " WHERE sa.rowid = ".((int) $object->id); // We get record from ID, no need for filter on entity
926
		$sql .= " AND sa.type = 'ban'"; //type ban to get normal bank account of customer (prelevement)
927
928
		$soc = new Societe($this->db);
929
		$soc->fetch($object->fk_soc);
930
931
		dol_syslog(get_class($this)."::sepaStripe search stripe ban id for paymentmode id=".$object->id.", stripeacc=".$stripeacc.", status=".$status.", createifnotlinkedtostripe=".$createifnotlinkedtostripe, LOG_DEBUG);
932
		$resql = $this->db->query($sql);
933
		if ($resql) {
934
			$num = $this->db->num_rows($resql);
935
			if ($num) {
936
				$obj = $this->db->fetch_object($resql);
937
				$cardref = $obj->stripe_card_ref;
938
				dol_syslog(get_class($this)."::sepaStripe cardref=".$cardref);
939
				if ($cardref) {
940
					try {
941
						if (empty($stripeacc)) {				// If the Stripe connect account not set, we use common API usage
942
							if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
943
								$sepa = $cu->sources->retrieve($cardref);
944
							} else {
945
								$sepa = \Stripe\PaymentMethod::retrieve($cardref);
946
							}
947
						} else {
948
							if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
949
								//$sepa = $cu->sources->retrieve($cardref, array("stripe_account" => $stripeacc));		// this API fails when array stripe_account is provided
950
								$sepa = $cu->sources->retrieve($cardref);
951
							} else {
952
								//$sepa = \Stripe\PaymentMethod::retrieve($cardref, array("stripe_account" => $stripeacc));		// Don't know if this works
953
								$sepa = \Stripe\PaymentMethod::retrieve($cardref);
954
							}
955
						}
956
					} catch (Exception $e) {
957
						$this->error = $e->getMessage();
958
						dol_syslog($this->error, LOG_WARNING);
959
					}
960
				} elseif ($createifnotlinkedtostripe) {
961
					$iban = $obj->iban_prefix; //prefix ?
962
					$ipaddress = getUserRemoteIP();
963
964
					$dataforcard = array(
965
						'type'=>'sepa_debit',
966
						"sepa_debit" => array('iban' => $iban),
967
						'currency' => strtolower($conf->currency),
968
						'usage' => 'reusable',
969
						'owner' => array(
970
							'name' => $soc->name,
971
						),
972
						"metadata" => array(
973
							'dol_type'=>$object->element,
974
							'dol_id'=>$object->id,
975
							'dol_version'=>DOL_VERSION,
976
							'dol_entity'=>$conf->entity,
977
							'ipaddress'=>$ipaddress
978
						)
979
					);
980
					// Complete owner name
981
					if (!empty($soc->town)) {
982
						$dataforcard['owner']['address']['city']=$soc->town;
983
					}
984
					if (!empty($soc->country_code)) {
985
						$dataforcard['owner']['address']['country']=$soc->country_code;
986
					}
987
					if (!empty($soc->address)) {
988
						$dataforcard['owner']['address']['line1']=$soc->address;
989
					}
990
					if (!empty($soc->zip)) {
991
						$dataforcard['owner']['address']['postal_code']=$soc->zip;
992
					}
993
					if (!empty($soc->state)) {
994
						$dataforcard['owner']['address']['state']=$soc->state;
995
					}
996
997
					//$a = \Stripe\Stripe::getApiKey();
998
					//var_dump($a);var_dump($stripeacc);exit;
999
					try {
1000
						dol_syslog("Try to create sepa_debit 0");
1001
1002
						$service = 'StripeTest';
1003
						$servicestatus = 0;
1004
						if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) {
1005
							$service = 'StripeLive';
1006
							$servicestatus = 1;
1007
						}
1008
						// Force to use the correct API key
1009
						global $stripearrayofkeysbyenv;
1010
						$stripeacc = $stripearrayofkeysbyenv[$servicestatus]['secret_key'];
1011
1012
						dol_syslog("Try to create sepa_debit with data = ".json_encode($dataforcard));
1013
1014
						$s = new \Stripe\StripeClient($stripeacc);
0 ignored issues
show
Bug introduced by
The type Stripe\StripeClient was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1015
1016
						// TODO Deprecated with the new Stripe API and SCA.
1017
						// TODO Replace ->create() and ->createSource() and replace with ->getSetupIntent() to get a Payment mode with $payment_method = \Stripe\PaymentMethod::retrieve($setupintent->payment_method); ?
1018
						$sepa = $s->sources->create($dataforcard);
1019
						if (!$sepa) {
1020
							$this->error = 'Creation of sepa_debit on Stripe has failed';
1021
						} else {
1022
							// link customer and src
1023
							$cs = $cu->createSource($cu->id, array('source' => $sepa->id));
1024
							if (!$cs) {
1025
								$this->error = 'Link SEPA <-> Customer failed';
1026
							} else {
1027
								dol_syslog("Update the payment mode of the customer");
1028
								// print json_encode($sepa);
1029
1030
								// Save the Stripe payment mode ID into the Dolibarr database
1031
								$sql = "UPDATE ".MAIN_DB_PREFIX."societe_rib";
1032
								$sql .= " SET stripe_card_ref = '".$this->db->escape($sepa->id)."', card_type = 'sepa_debit',";
1033
								$sql .= " stripe_account= '" . $this->db->escape($cu->id . "@" . $stripeacc) . "'";
1034
								$sql .= " WHERE rowid = ".((int) $object->id);
1035
								$sql .= " AND type = 'ban'";
1036
								$resql = $this->db->query($sql);
1037
								if (!$resql) {
1038
									$this->error = $this->db->lasterror();
1039
								}
1040
							}
1041
						}
1042
					} catch (Exception $e) {
1043
						$this->error = $e->getMessage();
1044
						dol_syslog($this->error, LOG_WARNING);
1045
					}
1046
				}
1047
			}
1048
		} else {
1049
			dol_print_error($this->db);
1050
		}
1051
1052
		return $sepa;
1053
	}
1054
1055
1056
	/**
1057
	 * Create charge.
1058
	 * This is called by page htdocs/stripe/payment.php and may be deprecated.
1059
	 *
1060
	 * @param	int 	$amount									Amount to pay
1061
	 * @param	string 	$currency								EUR, GPB...
1062
	 * @param	string 	$origin									Object type to pay (order, invoice, contract...)
1063
	 * @param	int 	$item									Object id to pay
1064
	 * @param	string 	$source									src_xxxxx or card_xxxxx or pm_xxxxx
1065
	 * @param	string 	$customer								Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
1066
	 * @param	string 	$account								Stripe account ref 'acc_xxxxxxxxxxxxx' via  getStripeAccount()
1067
	 * @param	int		$status									Status (0=test, 1=live)
1068
	 * @param	int		$usethirdpartyemailforreceiptemail		Use thirdparty email as receipt email
1069
	 * @param	boolean	$capture								Set capture flag to true (take payment) or false (wait)
1070
	 * @return Stripe
1071
	 */
1072
	public function createPaymentStripe($amount, $currency, $origin, $item, $source, $customer, $account, $status = 0, $usethirdpartyemailforreceiptemail = 0, $capture = true)
1073
	{
1074
		global $conf;
1075
1076
		$error = 0;
1077
1078
		if (empty($status)) {
1079
			$service = 'StripeTest';
1080
		} else {
1081
			$service = 'StripeLive';
1082
		}
1083
1084
		$sql = "SELECT sa.key_account as key_account, sa.fk_soc, sa.entity";
1085
		$sql .= " FROM ".MAIN_DB_PREFIX."societe_account as sa";
1086
		$sql .= " WHERE sa.key_account = '".$this->db->escape($customer)."'";
1087
		//$sql.= " AND sa.entity IN (".getEntity('societe').")";
1088
		$sql .= " AND sa.site = 'stripe' AND sa.status = ".((int) $status);
1089
1090
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1091
		$result = $this->db->query($sql);
1092
		if ($result) {
1093
			if ($this->db->num_rows($result)) {
1094
				$obj = $this->db->fetch_object($result);
1095
				$key = $obj->fk_soc;
1096
			} else {
1097
				$key = null;
1098
			}
1099
		} else {
1100
			$key = null;
1101
		}
1102
1103
		$arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
1104
		if (!in_array($currency, $arrayzerounitcurrency)) {
1105
			$stripeamount = $amount * 100;
1106
		} else {
1107
			$stripeamount = $amount;
1108
		}
1109
1110
		$societe = new Societe($this->db);
1111
		if ($key > 0) {
1112
			$societe->fetch($key);
1113
		}
1114
1115
		$description = "";
1116
		$ref = "";
1117
		if ($origin == 'order') {
1118
			$order = new Commande($this->db);
1119
			$order->fetch($item);
1120
			$ref = $order->ref;
1121
			$description = "ORD=".$ref.".CUS=".$societe->id.".PM=stripe";
1122
		} elseif ($origin == 'invoice') {
1123
			$invoice = new Facture($this->db);
1124
			$invoice->fetch($item);
1125
			$ref = $invoice->ref;
1126
			$description = "INV=".$ref.".CUS=".$societe->id.".PM=stripe";
1127
		}
1128
1129
		$ipaddress = getUserRemoteIP();
1130
1131
		$metadata = array(
1132
			"dol_id" => (string) $item,
1133
			"dol_type" => (string) $origin,
1134
			"dol_thirdparty_id" => (string) $societe->id,
1135
			'dol_thirdparty_name' => $societe->name,
1136
			'dol_version' => DOL_VERSION,
1137
			'dol_entity' => $conf->entity,
1138
			'ipaddress' => $ipaddress
1139
		);
1140
		$return = new Stripe($this->db);
1141
		try {
1142
			// Force to use the correct API key
1143
			global $stripearrayofkeysbyenv;
1144
			\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
1145
1146
			if (empty($conf->stripeconnect->enabled)) {	// With a common Stripe account
1147
				if (preg_match('/pm_/i', $source)) {
1148
					$stripecard = $source;
1149
					$amountstripe = $stripeamount;
1150
					$FULLTAG = 'PFBO'; // Payment From Back Office
1151
					$stripe = $return;
1152
					$amounttopay = $amount;
1153
					$servicestatus = $status;
1154
1155
					dol_syslog("* createPaymentStripe get stripeacc", LOG_DEBUG);
1156
					$stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account if it exists (no network access here)
1157
1158
					dol_syslog("* createPaymentStripe Create payment for customer ".$customer->id." on source card ".$stripecard->id.", amounttopay=".$amounttopay.", amountstripe=".$amountstripe.", FULLTAG=".$FULLTAG, LOG_DEBUG);
0 ignored issues
show
Bug introduced by
The property id does not exist on string.
Loading history...
1159
1160
					// Create payment intent and charge payment (confirmnow = true)
1161
					$paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $invoice does not seem to be defined for all execution paths leading up to this point.
Loading history...
1162
1163
					$charge = new stdClass();
1164
					if ($paymentintent->status == 'succeeded') {
1165
						$charge->status = 'ok';
1166
					} else {
1167
						$charge->status = 'failed';
1168
						$charge->failure_code = $stripe->code;
1169
						$charge->failure_message = $stripe->error;
1170
						$charge->failure_declinecode = $stripe->declinecode;
1171
						$stripefailurecode = $stripe->code;
1172
						$stripefailuremessage = $stripe->error;
1173
						$stripefailuredeclinecode = $stripe->declinecode;
1174
					}
1175
				} elseif (preg_match('/acct_/i', $source)) {
1176
					$charge = \Stripe\Charge::create(array(
0 ignored issues
show
Bug introduced by
The type Stripe\Charge was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1177
						"amount" => "$stripeamount",
1178
						"currency" => "$currency",
1179
						"statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
1180
						"description" => "Stripe payment: ".$description,
1181
						"capture"  => $capture,
1182
						"metadata" => $metadata,
1183
						"source" => "$source"
1184
					));
1185
				} else {
1186
					$paymentarray = array(
1187
						"amount" => "$stripeamount",
1188
						"currency" => "$currency",
1189
						"statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
1190
						"description" => "Stripe payment: ".$description,
1191
						"capture"  => $capture,
1192
						"metadata" => $metadata,
1193
						"source" => "$source",
1194
						"customer" => "$customer"
1195
					);
1196
1197
					if ($societe->email && $usethirdpartyemailforreceiptemail) {
1198
						$paymentarray["receipt_email"] = $societe->email;
1199
					}
1200
1201
					$charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description"));
1202
				}
1203
			} else {
1204
				// With Stripe Connect
1205
				$fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE;
1206
				if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
1207
					$fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL;
1208
				} elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
1209
					$fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL;
1210
				}
1211
1212
				if (!in_array($currency, $arrayzerounitcurrency)) {
1213
					$stripefee = round($fee * 100);
1214
				} else {
1215
					$stripefee = round($fee);
1216
				}
1217
1218
				$paymentarray = array(
1219
					"amount" => "$stripeamount",
1220
					"currency" => "$currency",
1221
				"statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
1222
					"description" => "Stripe payment: ".$description,
1223
					"capture"  => $capture,
1224
					"metadata" => $metadata,
1225
					"source" => "$source",
1226
					"customer" => "$customer"
1227
				);
1228
				if ($conf->entity != $conf->global->STRIPECONNECT_PRINCIPAL && $stripefee > 0) {
1229
					$paymentarray["application_fee_amount"] = $stripefee;
1230
				}
1231
				if ($societe->email && $usethirdpartyemailforreceiptemail) {
1232
					$paymentarray["receipt_email"] = $societe->email;
1233
				}
1234
1235
				if (preg_match('/pm_/i', $source)) {
1236
					$stripecard = $source;
1237
					$amountstripe = $stripeamount;
1238
					$FULLTAG = 'PFBO'; // Payment From Back Office
1239
					$stripe = $return;
1240
					$amounttopay = $amount;
1241
					$servicestatus = $status;
1242
1243
					dol_syslog("* createPaymentStripe get stripeacc", LOG_DEBUG);
1244
					$stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account if it exists (no network access here)
1245
1246
					dol_syslog("* createPaymentStripe Create payment on card ".$stripecard->id.", amounttopay=".$amounttopay.", amountstripe=".$amountstripe.", FULLTAG=".$FULLTAG, LOG_DEBUG);
1247
1248
					// Create payment intent and charge payment (confirmnow = true)
1249
					$paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1);
1250
1251
					$charge = new stdClass();
1252
					if ($paymentintent->status == 'succeeded') {
1253
						$charge->status = 'ok';
1254
						$charge->id = $paymentintent->id;
1255
					} else {
1256
						$charge->status = 'failed';
1257
						$charge->failure_code = $stripe->code;
1258
						$charge->failure_message = $stripe->error;
1259
						$charge->failure_declinecode = $stripe->declinecode;
1260
					}
1261
				} else {
1262
					$charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description", "stripe_account" => "$account"));
1263
				}
1264
			}
1265
			if (isset($charge->id)) {
1266
			}
1267
1268
			$return->statut = 'success';
1269
			$return->id = $charge->id;
1270
1271
			if (preg_match('/pm_/i', $source)) {
1272
				$return->message = 'Payment retrieved by card status = '.$charge->status;
1273
			} else {
1274
				if ($charge->source->type == 'card') {
1275
					$return->message = $charge->source->card->brand." ....".$charge->source->card->last4;
1276
				} elseif ($charge->source->type == 'three_d_secure') {
1277
					$stripe = new Stripe($this->db);
1278
					$src = \Stripe\Source::retrieve("".$charge->source->three_d_secure->card, array(
0 ignored issues
show
Bug introduced by
The type Stripe\Source was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1279
					"stripe_account" => $stripe->getStripeAccount($service)
1280
					));
1281
					$return->message = $src->card->brand." ....".$src->card->last4;
1282
				} else {
1283
					$return->message = $charge->id;
1284
				}
1285
			}
1286
		} catch (\Stripe\Error\Card $e) {
1287
			include DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
1288
			// Since it's a decline, \Stripe\Error\Card will be caught
1289
			$body = $e->getJsonBody();
1290
			$err = $body['error'];
1291
1292
			$return->statut = 'error';
1293
			$return->id = $err['charge'];
1294
			$return->type = $err['type'];
1295
			$return->code = $err['code'];
1296
			$return->message = $err['message'];
1297
			$body = "Error: <br>".$return->id." ".$return->message." ";
1298
			$subject = '[Alert] Payment error using Stripe';
1299
			$cmailfile = new CMailFile($subject, $conf->global->ONLINE_PAYMENT_SENDEMAIL, $conf->global->MAIN_INFO_SOCIETE_MAIL, $body);
1300
			$cmailfile->sendfile();
1301
1302
			$error++;
1303
			dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1304
		} catch (\Stripe\Error\RateLimit $e) {
0 ignored issues
show
Bug introduced by
The type Stripe\Error\RateLimit was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1305
			// Too many requests made to the API too quickly
1306
			$error++;
1307
			dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1308
		} catch (\Stripe\Error\InvalidRequest $e) {
0 ignored issues
show
Bug introduced by
The type Stripe\Error\InvalidRequest was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1309
			// Invalid parameters were supplied to Stripe's API
1310
			$error++;
1311
			dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1312
		} catch (\Stripe\Error\Authentication $e) {
0 ignored issues
show
Bug introduced by
The type Stripe\Error\Authentication was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1313
			// Authentication with Stripe's API failed
1314
			// (maybe you changed API keys recently)
1315
			$error++;
1316
			dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1317
		} catch (\Stripe\Error\ApiConnection $e) {
0 ignored issues
show
Bug introduced by
The type Stripe\Error\ApiConnection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1318
			// Network communication with Stripe failed
1319
			$error++;
1320
			dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1321
		} catch (\Stripe\Error\Base $e) {
0 ignored issues
show
Bug introduced by
The type Stripe\Error\Base was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1322
			// Display a very generic error to the user, and maybe send
1323
			// yourself an email
1324
			$error++;
1325
			dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1326
		} catch (Exception $e) {
1327
			// Something else happened, completely unrelated to Stripe
1328
			$error++;
1329
			dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1330
		}
1331
		return $return;
1332
	}
1333
}
1334