Passed
Pull Request — dev (#6)
by Rafael
79:24 queued 24:08
created

Stripe::createPaymentStripe()   F

Complexity

Conditions 35
Paths > 20000

Size

Total Lines 260
Code Lines 192

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 35
eloc 192
nc 385560
nop 10
dl 0
loc 260
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* Copyright (C) 2018-2021  Thibault FOUCART            <[email protected]>
4
 * Copyright (C) 2024       Frédéric France             <[email protected]>
5
 * Copyright (C) 2024		MDW							<[email protected]>
6
 * Copyright (C) 2024       Rafael San José             <[email protected]>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Dolibarr\Code\Stripe\Classes;
23
24
use Dolibarr\Code\Societe\Classes\SocieteAccount;
25
use Dolibarr\Code\Societe\Classes\Societe;
26
use Dolibarr\Core\Base\CommonObject;
27
use DoliDB;
28
use Exception;
29
30
require_once constant('DOL_DOCUMENT_ROOT') . '/stripe/config.php'; // This set stripe global env
31
32
/**
33
 *  Stripe class
34
 *  @TODO No reason to extends CommonObject
35
 */
36
class Stripe extends CommonObject
37
{
38
    /**
39
     * @var int ID
40
     */
41
    public $rowid;
42
43
    /**
44
     * @var int Thirdparty ID
45
     */
46
    public $fk_soc;
47
48
    /**
49
     * @var int ID
50
     */
51
    public $fk_key;
52
53
    /**
54
     * @var int ID
55
     */
56
    public $id;
57
58
    /**
59
     * @var string
60
     */
61
    public $mode;
62
63
    /**
64
     * @var int Entity
65
     */
66
    public $entity;
67
68
    /**
69
     * @var string
70
     * @deprecated Was used by createPaymentStripe only that is deprecated
71
     */
72
    public $result;
73
74
    /**
75
     * @var string
76
     */
77
    public $type;
78
79
    /**
80
     * @var string
81
     */
82
    public $code;
83
84
    /**
85
     * @var string
86
     */
87
    public $declinecode;
88
89
    /**
90
     * @var string Message
91
     */
92
    public $message;
93
94
    /**
95
     *  Constructor
96
     *
97
     *  @param  DoliDB      $db         Database handler
98
     */
99
    public function __construct($db)
100
    {
101
        $this->db = $db;
102
    }
103
104
105
    /**
106
     * Return main company OAuth Connect stripe account
107
     *
108
     * @param   string  $mode       'StripeTest' or 'StripeLive'
109
     * @param   int     $fk_soc     Id of thirdparty
110
     * @param   int     $entity     Id of entity (-1 = current environment)
111
     * @return  string              Stripe account 'acc_....' or '' if no OAuth token found
112
     */
113
    public function getStripeAccount($mode = 'StripeTest', $fk_soc = 0, $entity = -1)
114
    {
115
        global $conf;
116
117
        $key = '';
118
        if ($entity < 0) {
119
            $entity = $conf->entity;
120
        }
121
122
        $sql = "SELECT tokenstring";
123
        $sql .= " FROM " . MAIN_DB_PREFIX . "oauth_token";
124
        $sql .= " WHERE service = '" . $this->db->escape($mode) . "'";
125
        $sql .= " AND entity = " . ((int) $entity);
126
        if ($fk_soc > 0) {
127
            $sql .= " AND fk_soc = " . ((int) $fk_soc);
128
        } else {
129
            $sql .= " AND fk_soc IS NULL";
130
        }
131
        $sql .= " AND fk_user IS NULL AND fk_adherent IS NULL";
132
133
        dol_syslog(get_class($this) . "::getStripeAccount", LOG_DEBUG);
134
135
        $result = $this->db->query($sql);
136
        if ($result) {
137
            if ($this->db->num_rows($result)) {
138
                $obj = $this->db->fetch_object($result);
139
                $tokenstring = $obj->tokenstring;
140
141
                if ($tokenstring) {
142
                    $tmparray = json_decode($tokenstring);
143
                    $key = empty($tmparray->stripe_user_id) ? '' : $tmparray->stripe_user_id;
144
                }
145
            } else {
146
                $tokenstring = '';
147
            }
148
        } else {
149
            dol_print_error($this->db);
150
        }
151
152
        dol_syslog("No dedicated Stripe Connect account available for entity " . $conf->entity);
153
154
        return $key;
155
    }
156
157
    /**
158
     * getStripeCustomerAccount
159
     *
160
     * @param   int     $id             Id of third party
161
     * @param   int     $status         Status
162
     * @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.
163
     * @return  string                  Stripe customer ref 'cu_xxxxxxxxxxxxx' or ''
164
     */
165
    public function getStripeCustomerAccount($id, $status = 0, $site_account = '')
166
    {
167
        include_once DOL_DOCUMENT_ROOT . '/societe/class/societeaccount.class.php';
168
        $societeaccount = new SocieteAccount($this->db);
169
        return $societeaccount->getCustomerAccount($id, 'stripe', $status, $site_account); // Get thirdparty cus_...
170
    }
171
172
    /**
173
     * Get the Stripe customer of a thirdparty (with option to create it in Stripe if not linked yet).
174
     * Search on site_account = 0 or = $stripearrayofkeysbyenv[$status]['publishable_key']
175
     *
176
     * @param   CommonObject    $object                         Object thirdparty to check, or create on stripe (create on stripe also update the stripe_account table for current entity).  Used for AdherentType and Societe.
177
     * @param   string  $key                            ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
178
     * @param   int     $status                         Status (0=test, 1=live)
179
     * @param   int     $createifnotlinkedtostripe      1=Create the stripe customer and the link if the thirdparty is not yet linked to a stripe customer
180
     * @return  \Stripe\Customer|null                   Stripe Customer or null if not found
181
     */
182
    public function customerStripe(CommonObject $object, $key = '', $status = 0, $createifnotlinkedtostripe = 0)
183
    {
184
        global $conf, $user;
185
186
        if (empty($object->id)) {
187
            dol_syslog("customerStripe is called with the parameter object that is not loaded");
188
            return null;
189
        }
190
191
        $customer = null;
192
193
        // Force to use the correct API key
194
        global $stripearrayofkeysbyenv;
195
        \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
196
197
        $sql = "SELECT sa.key_account as key_account, sa.entity"; // key_account is cus_....
198
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_account as sa";
199
        $sql .= " WHERE sa.fk_soc = " . ((int) $object->id);
200
        $sql .= " AND sa.entity IN (" . getEntity('societe') . ")";
201
        $sql .= " AND sa.site = 'stripe' AND sa.status = " . ((int) $status);
202
        $sql .= " AND (sa.site_account IS NULL OR sa.site_account = '' OR sa.site_account = '" . $this->db->escape($stripearrayofkeysbyenv[$status]['publishable_key']) . "')";
203
        $sql .= " AND sa.key_account IS NOT NULL AND sa.key_account <> ''";
204
205
        dol_syslog(get_class($this) . "::customerStripe search stripe customer id for thirdparty id=" . $object->id, LOG_DEBUG);
206
        $resql = $this->db->query($sql);
207
        if ($resql) {
208
            $num = $this->db->num_rows($resql);
209
            if ($num) {
210
                $obj = $this->db->fetch_object($resql);
211
                $tiers = $obj->key_account;
212
213
                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']);
214
215
                try {
216
                    if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
217
                        //$customer = \Stripe\Customer::retrieve("$tiers");
218
                        $customer = \Stripe\Customer::retrieve(array('id' => "$tiers", 'expand[]' => 'sources'));
219
                    } else {
220
                        //$customer = \Stripe\Customer::retrieve("$tiers", array("stripe_account" => $key));
221
                        $customer = \Stripe\Customer::retrieve(array('id' => "$tiers", 'expand[]' => 'sources'), array("stripe_account" => $key));
222
                    }
223
                } catch (Exception $e) {
224
                    // For example, 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.'
225
                    $this->error = $e->getMessage();
226
                }
227
            } elseif ($createifnotlinkedtostripe) {
228
                $ipaddress = getUserRemoteIP();
229
230
                $dataforcustomer = array(
231
                    "email" => $object->email,
0 ignored issues
show
Bug Best Practice introduced by
The property email does not exist on Dolibarr\Core\Base\CommonObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
232
                    "description" => $object->name,
233
                    "metadata" => array('dol_id' => $object->id, 'dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress)
234
                );
235
236
                $vatcleaned = $object->tva_intra ? $object->tva_intra : null;
0 ignored issues
show
Bug Best Practice introduced by
The property tva_intra does not exist on Dolibarr\Core\Base\CommonObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
237
238
                /*
239
                $taxinfo = array('type'=>'vat');
240
                if ($vatcleaned)
241
                {
242
                    $taxinfo["tax_id"] = $vatcleaned;
243
                }
244
                // We force data to "null" if not defined as expected by Stripe
245
                if (empty($vatcleaned)) $taxinfo=null;
246
                $dataforcustomer["tax_info"] = $taxinfo;
247
                */
248
249
                //$a = \Stripe\Stripe::getApiKey();
250
                //var_dump($a);var_dump($key);exit;
251
                try {
252
                    // Force to use the correct API key
253
                    global $stripearrayofkeysbyenv;
254
                    \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
255
256
                    if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
257
                        $customer = \Stripe\Customer::create($dataforcustomer);
258
                    } else {
259
                        $customer = \Stripe\Customer::create($dataforcustomer, array("stripe_account" => $key));
260
                    }
261
262
                    // Create the VAT record in Stripe
263
                    if (getDolGlobalString('STRIPE_SAVE_TAX_IDS')) {    // We setup to save Tax info on Stripe side. Warning: This may result in error when saving customer
264
                        if (!empty($vatcleaned)) {
265
                            $isineec = isInEEC($object);
266
                            if ($object->country_code && $isineec) {
267
                                //$taxids = $customer->allTaxIds($customer->id);
268
                                $customer->createTaxId($customer->id, array('type' => 'eu_vat', 'value' => $vatcleaned));
0 ignored issues
show
Bug introduced by
The method createTaxId() does not exist on Stripe\StripeObject. It seems like you code against a sub-type of Stripe\StripeObject such as Stripe\Customer. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

268
                                $customer->/** @scrutinizer ignore-call */ 
269
                                           createTaxId($customer->id, array('type' => 'eu_vat', 'value' => $vatcleaned));
Loading history...
269
                            }
270
                        }
271
                    }
272
273
                    // Create customer in Dolibarr
274
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "societe_account (fk_soc, login, key_account, site, site_account, status, entity, date_creation, fk_user_creat)";
275
                    $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) . ")";
276
                    $resql = $this->db->query($sql);
277
                    if (!$resql) {
278
                        $this->error = $this->db->lasterror();
279
                    }
280
                } catch (Exception $e) {
281
                    $this->error = $e->getMessage();
282
                }
283
            }
284
        } else {
285
            dol_print_error($this->db);
286
        }
287
288
        return $customer;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $customer also could return the type array which is incompatible with the documented return type Stripe\Customer|null.
Loading history...
289
    }
290
291
    /**
292
     * Get the Stripe payment method Object from its ID
293
     *
294
     * @param   string  $paymentmethod              Payment Method ID
295
     * @param   string  $key                        ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
296
     * @param   int     $status                     Status (0=test, 1=live)
297
     * @return  \Stripe\PaymentMethod|null          Stripe PaymentMethod or null if not found
298
     */
299
    public function getPaymentMethodStripe($paymentmethod, $key = '', $status = 0)
300
    {
301
        $stripepaymentmethod = null;
302
303
        try {
304
            // Force to use the correct API key
305
            global $stripearrayofkeysbyenv;
306
            \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
307
            if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
308
                $stripepaymentmethod = \Stripe\PaymentMethod::retrieve((string) $paymentmethod->id);
0 ignored issues
show
Bug introduced by
The property id does not exist on string.
Loading history...
309
            } else {
310
                $stripepaymentmethod = \Stripe\PaymentMethod::retrieve((string) $paymentmethod->id, array("stripe_account" => $key));
311
            }
312
        } catch (Exception $e) {
313
            $this->error = $e->getMessage();
314
        }
315
316
        return $stripepaymentmethod;
317
    }
318
319
    /**
320
     * Get the Stripe reader Object from its ID
321
     *
322
     * @param   string  $reader             Reader ID
323
     * @param   string  $key                ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
324
     * @param   int $status             Status (0=test, 1=live)
325
     * @return  \Stripe\Terminal\Reader|null        Stripe Reader or null if not found
326
     */
327
    public function getSelectedReader($reader, $key = '', $status = 0)
328
    {
329
        $selectedreader = null;
330
331
        try {
332
            // Force to use the correct API key
333
            global $stripearrayofkeysbyenv;
334
            \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
335
            if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
336
                $selectedreader = \Stripe\Terminal\Reader::retrieve((string) $reader);
337
            } else {
338
                $stripepaymentmethod = \Stripe\Terminal\Reader::retrieve((string) $reader, array("stripe_account" => $key));
339
            }
340
        } catch (Exception $e) {
341
            $this->error = $e->getMessage();
342
        }
343
344
        return $selectedreader;
345
    }
346
347
    /**
348
     * Get the Stripe payment intent. Create it with confirmnow=false
349
     * Warning. If a payment was tried and failed, a payment intent was created.
350
     * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed by Stripe.
351
     * Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay),
352
     * 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)
353
     * 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
354
     * but not when using the STRIPE_USE_NEW_CHECKOUT.
355
     *
356
     * @param   double  $amount                             Amount
357
     * @param   string  $currency_code                      Currency code
358
     * @param   string  $tag                                Tag
359
     * @param   string  $description                        Description
360
     * @param   mixed   $object                             Object to pay with Stripe
361
     * @param   string  $customer                           Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
362
     * @param   string  $key                                ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
363
     * @param   int     $status                             Status (0=test, 1=live)
364
     * @param   int     $usethirdpartyemailforreceiptemail  1=use thirdparty email for receipt
365
     * @param   string  $mode                               automatic=automatic confirmation/payment when conditions are ok, manual=need to call confirm() on intent
366
     * @param   boolean $confirmnow                         false=default, true=try to confirm immediately after create (if conditions are ok)
367
     * @param   string  $payment_method                     'pm_....' (if known)
368
     * @param   int     $off_session                        If we use an already known payment method to pay when customer is not available during the checkout flow.
369
     * @param   int     $noidempotency_key                  Do not use the idempotency_key when creating the PaymentIntent
370
     * @param   int     $did                                ID of an existing line into llx_prelevement_demande (Dolibarr intent). If provided, no new line will be created.
371
     * @return  \Stripe\PaymentIntent|null                  Stripe PaymentIntent or null if not found and failed to create
372
     */
373
    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, $did = 0)
374
    {
375
        global $conf, $user;
376
377
        dol_syslog(get_class($this) . "::getPaymentIntent", LOG_INFO, 1);
378
379
        $error = 0;
380
381
        if (empty($status)) {
382
            $service = 'StripeTest';
383
        } else {
384
            $service = 'StripeLive';
385
        }
386
387
        $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
388
        if (!in_array($currency_code, $arrayzerounitcurrency)) {
389
            $stripeamount = $amount * 100;
390
        } else {
391
            $stripeamount = $amount;
392
        }
393
394
        $fee = 0;
395
        if (getDolGlobalString("STRIPE_APPLICATION_FEE_PERCENT")) {
396
            $fee = $amount * ((float) getDolGlobalString("STRIPE_APPLICATION_FEE_PERCENT", '0') / 100) + (float) getDolGlobalString("STRIPE_APPLICATION_FEE", '0');
397
        }
398
        if ($fee >= (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0') && (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0') > (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0')) {
399
            $fee = (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0');
400
        } elseif ($fee < (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0')) {
401
            $fee = (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0');
402
        }
403
        if (!in_array($currency_code, $arrayzerounitcurrency)) {
404
            $stripefee = round($fee * 100);
405
        } else {
406
            $stripefee = round($fee);
407
        }
408
409
        $paymentintent = null;
410
411
        if (is_object($object) && getDolGlobalInt('STRIPE_REUSE_EXISTING_INTENT_IF_FOUND') && !getDolGlobalInt('STRIPE_CARD_PRESENT')) {
412
            // Warning. If a payment was tried and failed, a payment intent was created.
413
            // 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.
414
            // 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
415
            // automatically return the existing payment intent if idempotency is provided when we try to create the new one.
416
            // 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)
417
418
            $sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site";
419
            $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_demande as pi";
420
            $sql .= " WHERE pi.fk_facture = " . ((int) $object->id);
421
            $sql .= " AND pi.sourcetype = '" . $this->db->escape($object->element) . "'";
422
            $sql .= " AND pi.entity IN (" . getEntity('societe') . ")";
423
            $sql .= " AND pi.ext_payment_site = '" . $this->db->escape($service) . "'";
424
425
            dol_syslog(get_class($this) . "::getPaymentIntent search stripe payment intent for object id = " . $object->id, LOG_DEBUG);
426
            $resql = $this->db->query($sql);
427
            if ($resql) {
428
                $num = $this->db->num_rows($resql);
429
                if ($num) {
430
                    $obj = $this->db->fetch_object($resql);
431
                    $intent = $obj->ext_payment_id;
432
433
                    dol_syslog(get_class($this) . "::getPaymentIntent found existing payment intent record");
434
435
                    // Force to use the correct API key
436
                    global $stripearrayofkeysbyenv;
437
                    \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
438
439
                    try {
440
                        if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
441
                            $paymentintent = \Stripe\PaymentIntent::retrieve($intent);
442
                        } else {
443
                            $paymentintent = \Stripe\PaymentIntent::retrieve($intent, array("stripe_account" => $key));
444
                        }
445
                    } catch (Exception $e) {
446
                        $error++;
447
                        $this->error = $e->getMessage();
448
                    }
449
                }
450
            }
451
        }
452
453
        if (empty($paymentintent)) {
454
            // Try to create intent. See https://stripe.com/docs/api/payment_intents/create
455
            $ipaddress = getUserRemoteIP();
456
            $metadata = array('dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress);
457
            if (is_object($object)) {
458
                $metadata['dol_type'] = $object->element;
459
                $metadata['dol_id'] = $object->id;
460
                if (is_object($object->thirdparty) && $object->thirdparty->id > 0) {
461
                    $metadata['dol_thirdparty_id'] = $object->thirdparty->id;
462
                }
463
            }
464
465
            // list of payment method types
466
            $paymentmethodtypes = array("card");
467
            $descriptor = dol_trunc($tag, 10, 'right', 'UTF-8', 1);
468
            if (getDolGlobalInt('STRIPE_SEPA_DIRECT_DEBIT')) {
469
                $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
470
                //$descriptor = preg_replace('/ref=[^:=]+/', '', $descriptor);  // Clean ref
471
            }
472
            if (getDolGlobalInt('STRIPE_KLARNA')) {
473
                $paymentmethodtypes[] = "klarna";
474
            }
475
            if (getDolGlobalInt('STRIPE_BANCONTACT')) {
476
                $paymentmethodtypes[] = "bancontact";
477
            }
478
            if (getDolGlobalInt('STRIPE_IDEAL')) {
479
                $paymentmethodtypes[] = "ideal";
480
            }
481
            if (getDolGlobalInt('STRIPE_GIROPAY')) {
482
                $paymentmethodtypes[] = "giropay";
483
            }
484
            if (getDolGlobalInt('STRIPE_SOFORT')) {
485
                $paymentmethodtypes[] = "sofort";
486
            }
487
            if (getDolGlobalInt('STRIPE_CARD_PRESENT') && $mode == 'terminal') {
488
                $paymentmethodtypes = array("card_present");
489
            }
490
491
            global $dolibarr_main_url_root;
492
493
            $dataforintent = array(
494
                "confirm" => $confirmnow, // try to confirm immediately after create (if conditions are ok)
495
                "confirmation_method" => $mode,
496
                "amount" => $stripeamount,
497
                "currency" => $currency_code,
498
                "payment_method_types" => $paymentmethodtypes,  // When payment_method_types is set, return_url is not required but payment mode can't be managed from dashboard
499
                /*
500
                'return_url' => $dolibarr_main_url_root.'/public/payment/paymentok.php',
501
                'automatic_payment_methods' => array(
502
                    'enabled' => true,
503
                    'allow_redirects' => 'never',
504
                ),
505
                */
506
                "description" => $description,
507
                //"save_payment_method" => true,
508
                "setup_future_usage" => "on_session",
509
                "metadata" => $metadata
510
            );
511
            if ($descriptor) {
512
                $dataforintent["statement_descriptor_suffix"] = $descriptor; // For card payment, 22 chars that appears on bank receipt (prefix into stripe setup + this suffix)
513
                $dataforintent["statement_descriptor"] = $descriptor;   // For SEPA, it will take only statement_descriptor, not statement_descriptor_suffix
514
            }
515
            if (!is_null($customer)) {
516
                $dataforintent["customer"] = $customer;
517
            }
518
            // payment_method =
519
            // payment_method_types = array('card')
520
            //var_dump($dataforintent);
521
            if ($off_session) {
522
                unset($dataforintent['setup_future_usage']);
523
                // We can't use both "setup_future_usage" = "off_session" and "off_session" = true.
524
                // Because $off_session parameter is dedicated to create paymentintent off_line (and not future payment), we need to use "off_session" = true.
525
                //$dataforintent["setup_future_usage"] = "off_session";
526
                $dataforintent["off_session"] = true;
527
            }
528
            if (getDolGlobalInt('STRIPE_GIROPAY')) {
529
                unset($dataforintent['setup_future_usage']);
530
            }
531
            if (getDolGlobalInt('STRIPE_KLARNA')) {
532
                unset($dataforintent['setup_future_usage']);
533
            }
534
            if (getDolGlobalInt('STRIPE_CARD_PRESENT') && $mode == 'terminal') {
535
                unset($dataforintent['setup_future_usage']);
536
                $dataforintent["capture_method"] = "manual";
537
                $dataforintent["confirmation_method"] = "manual";
538
            }
539
            if (!is_null($payment_method)) {
540
                $dataforintent["payment_method"] = $payment_method;
541
                $description .= ' - ' . $payment_method;
542
            }
543
544
            if ($conf->entity != getDolGlobalInt('STRIPECONNECT_PRINCIPAL') && $stripefee > 0) {
545
                $dataforintent["application_fee_amount"] = $stripefee;
546
            }
547
            if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) {
548
                $dataforintent["receipt_email"] = $object->thirdparty->email;
549
            }
550
551
            try {
552
                // Force to use the correct API key
553
                global $stripearrayofkeysbyenv;
554
                \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
555
556
                $arrayofoptions = array();
557
                if (empty($noidempotency_key)) {
558
                    $arrayofoptions["idempotency_key"] = $description;
559
                }
560
                // 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.
561
                if (!empty($key)) {             // If the Stripe connect account not set, we use common API usage
562
                    $arrayofoptions["stripe_account"] = $key;
563
                }
564
565
                dol_syslog("dataforintent to create paymentintent = " . var_export($dataforintent, true));
566
567
                $paymentintent = \Stripe\PaymentIntent::create($dataforintent, $arrayofoptions);
568
569
                // Store the payment intent
570
                if (is_object($object)) {
571
                    $paymentintentalreadyexists = 0;
572
573
                    if ($did > 0) {
574
                        // If a payment request line provided, we do not need to recreate one, we just update it
575
                        dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
576
577
                        $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET";
578
                        $sql .= " ext_payment_site = '" . $this->db->escape($service) . "',";
579
                        $sql .= " ext_payment_id = '" . $this->db->escape($paymentintent->id) . "'";
580
                        $sql .= " WHERE rowid = " . ((int) $did);
581
582
                        $resql = $this->db->query($sql);
583
                        if ($resql) {
584
                            $paymentintentalreadyexists++;
585
                        } else {
586
                            $error++;
587
                            dol_print_error($this->db);
588
                        }
589
                    } else {
590
                        // Check that payment intent $paymentintent->id is not already recorded.
591
                        dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
592
593
                        $sql = "SELECT pi.rowid";
594
                        $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_demande as pi";
595
                        $sql .= " WHERE pi.entity IN (" . getEntity('societe') . ")";
596
                        $sql .= " AND pi.ext_payment_site = '" . $this->db->escape($service) . "'";
597
                        $sql .= " AND pi.ext_payment_id = '" . $this->db->escape($paymentintent->id) . "'";
598
599
                        $resql = $this->db->query($sql);
600
                        if ($resql) {
601
                            $num = $this->db->num_rows($resql);
602
                            if ($num) {
603
                                $obj = $this->db->fetch_object($resql);
604
                                if ($obj) {
605
                                    $paymentintentalreadyexists++;
606
                                }
607
                            }
608
                        } else {
609
                            $error++;
610
                            dol_print_error($this->db);
611
                        }
612
                    }
613
614
                    // If not, we create it.
615
                    if (!$error && !$paymentintentalreadyexists) {
616
                        $now = dol_now();
617
                        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site, amount)";
618
                        $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) . ")";
619
                        $resql = $this->db->query($sql);
620
                        if (!$resql) {
621
                            $error++;
622
                            $this->error = $this->db->lasterror();
623
                            dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=" . $paymentintent->id . " into database.", LOG_ERR);
624
                        }
625
                    }
626
                } else {
627
                    $_SESSION["stripe_payment_intent"] = $paymentintent;
628
                }
629
            } catch (Stripe\Exception\CardException $e) {
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Stripe\Cla...Exception\CardException was not found. Did you mean Stripe\Exception\CardException? If so, make sure to prefix the type with \.
Loading history...
630
                $error++;
631
                $this->error = $e->getMessage();
632
                $this->code = $e->getStripeCode();
633
                $this->declinecode = $e->getDeclineCode();
634
            } catch (Exception $e) {
635
                //var_dump($dataforintent);
636
                //var_dump($description);
637
                //var_dump($key);
638
                //var_dump($paymentintent);
639
                //var_dump($e->getMessage());
640
                //var_dump($e);
641
                $error++;
642
                $this->error = $e->getMessage();
643
                $this->code = '';
644
                $this->declinecode = '';
645
            }
646
        }
647
648
        dol_syslog(get_class($this) . "::getPaymentIntent return error=" . $error . " this->error=" . $this->error, LOG_INFO, -1);
649
650
        if (!$error) {
651
            return $paymentintent;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $paymentintent also could return the type array which is incompatible with the documented return type Stripe\PaymentIntent|null.
Loading history...
652
        } else {
653
            return null;
654
        }
655
    }
656
657
    /**
658
     * Get the Stripe payment intent. Create it with confirmnow=false
659
     * Warning. If a payment was tried and failed, a payment intent was created.
660
     * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed.
661
     * Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay),
662
     * 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)
663
     * 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
664
     * but not when using the STRIPE_USE_NEW_CHECKOUT.
665
     *
666
     * @param   string  $description                        Description
667
     * @param   Societe $object                             Object of company to link the Stripe payment mode with
668
     * @param   string  $customer                           Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
669
     * @param   string  $key                                ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
670
     * @param   int     $status                             Status (0=test, 1=live)
671
     * @param   int     $usethirdpartyemailforreceiptemail  1=use thirdparty email for receipt
672
     * @param   boolean $confirmnow                         false=default, true=try to confirm immediately after create (if conditions are ok)
673
     * @return  \Stripe\SetupIntent|null                    Stripe SetupIntent or null if not found and failed to create
674
     */
675
    public function getSetupIntent($description, $object, $customer, $key, $status, $usethirdpartyemailforreceiptemail = 0, $confirmnow = false)
676
    {
677
        global $conf;
678
679
        dol_syslog("getSetupIntent description=" . $description . ' confirmnow=' . json_encode($confirmnow), LOG_INFO, 1);
680
681
        $error = 0;
682
683
        if (empty($status)) {
684
            $service = 'StripeTest';
685
        } else {
686
            $service = 'StripeLive';
687
        }
688
689
        $setupintent = null;
690
691
        if (empty($setupintent)) {
692
            $ipaddress = getUserRemoteIP();
693
            $metadata = array('dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress);
694
            if (is_object($object)) {
695
                $metadata['dol_type'] = $object->element;
696
                $metadata['dol_id'] = $object->id;
697
                if (is_object($object->thirdparty) && $object->thirdparty->id > 0) {
698
                    $metadata['dol_thirdparty_id'] = $object->thirdparty->id;
699
                }
700
            }
701
702
            // list of payment method types
703
            $paymentmethodtypes = array("card");
704
            if (getDolGlobalString('STRIPE_SEPA_DIRECT_DEBIT')) {
705
                $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
706
            }
707
            if (getDolGlobalString('STRIPE_BANCONTACT')) {
708
                $paymentmethodtypes[] = "bancontact";
709
            }
710
            if (getDolGlobalString('STRIPE_IDEAL')) {
711
                $paymentmethodtypes[] = "ideal";
712
            }
713
            // Giropay not possible for setup intent
714
            if (getDolGlobalString('STRIPE_SOFORT')) {
715
                $paymentmethodtypes[] = "sofort";
716
            }
717
718
            global $dolibarr_main_url_root;
719
720
            $dataforintent = array(
721
                "confirm" => $confirmnow, // Do not confirm immediately during creation of intent
722
                "payment_method_types" => $paymentmethodtypes,  // When payment_method_types is set, return_url is not required but payment mode can't be managed from dashboard
723
                /*
724
                 'return_url' => $dolibarr_main_url_root.'/public/payment/paymentok.php',
725
                 'automatic_payment_methods' => array(
726
                 'enabled' => true,
727
                 'allow_redirects' => 'never',
728
                 ),
729
                 */
730
                "usage" => "off_session",
731
                "metadata" => $metadata
732
            );
733
            if (!is_null($customer)) {
734
                $dataforintent["customer"] = $customer;
735
            }
736
            if (!is_null($description)) {
737
                $dataforintent["description"] = $description;
738
            }
739
            // payment_method =
740
            // payment_method_types = array('card')
741
            //var_dump($dataforintent);
742
743
            if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) {
744
                $dataforintent["receipt_email"] = $object->thirdparty->email;
745
            }
746
747
            try {
748
                // Force to use the correct API key
749
                global $stripearrayofkeysbyenv;
750
                \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
751
752
                dol_syslog("getSetupIntent " . $stripearrayofkeysbyenv[$status]['publishable_key'], LOG_DEBUG);
753
754
                // Note: If all data for payment intent are same than a previous one, even if we use 'create', Stripe will return ID of the old existing payment intent.
755
                if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
756
                    //$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description"));
757
                    $setupintent = \Stripe\SetupIntent::create($dataforintent, array());
758
                } else {
759
                    //$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key));
760
                    $setupintent = \Stripe\SetupIntent::create($dataforintent, array("stripe_account" => $key));
761
                }
762
                //var_dump($setupintent->id);
763
764
                // Store the setup intent
765
                /*if (is_object($object))
766
                {
767
                    $setupintentalreadyexists = 0;
768
                    // Check that payment intent $setupintent->id is not already recorded.
769
                    $sql = "SELECT pi.rowid";
770
                    $sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_demande as pi";
771
                    $sql.= " WHERE pi.entity IN (".getEntity('societe').")";
772
                    $sql.= " AND pi.ext_payment_site = '" . $this->db->escape($service) . "'";
773
                    $sql.= " AND pi.ext_payment_id = '".$this->db->escape($setupintent->id)."'";
774
775
                    dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
776
                    $resql = $this->db->query($sql);
777
                    if ($resql) {
778
                        $num = $this->db->num_rows($resql);
779
                        if ($num)
780
                        {
781
                            $obj = $this->db->fetch_object($resql);
782
                            if ($obj) $setupintentalreadyexists++;
783
                        }
784
                    }
785
                    else dol_print_error($this->db);
786
787
                    // If not, we create it.
788
                    if (! $setupintentalreadyexists)
789
                    {
790
                        $now=dol_now();
791
                        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site)";
792
                        $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).")";
793
                        $resql = $this->db->query($sql);
794
                        if (! $resql)
795
                        {
796
                            $error++;
797
                            $this->error = $this->db->lasterror();
798
                            dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$setupintent->id." into database.");
799
                        }
800
                    }
801
                }
802
                else
803
                {
804
                    $_SESSION["stripe_setup_intent"] = $setupintent;
805
                }*/
806
            } catch (Exception $e) {
807
                //var_dump($dataforintent);
808
                //var_dump($description);
809
                //var_dump($key);
810
                //var_dump($setupintent);
811
                //var_dump($e->getMessage());
812
                $error++;
813
                $this->error = $e->getMessage();
814
            }
815
        }
816
817
        if (!$error) {
818
            dol_syslog("getSetupIntent " . (is_object($setupintent) ? $setupintent->id : ''), LOG_INFO, -1);
819
            return $setupintent;
820
        } else {
821
            dol_syslog("getSetupIntent return error=" . $error, LOG_INFO, -1);
822
            return null;
823
        }
824
    }
825
826
827
    /**
828
     * 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)
829
     *
830
     * @param   \Stripe\Customer        $cu                             Object stripe customer.
831
     * @param   CompanyPaymentMode      $object                         Object companypaymentmode to check, or create on stripe (create on stripe also update the societe_rib table for current entity)
832
     * @param   string                  $stripeacc                      ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
833
     * @param   int                     $status                         Status (0=test, 1=live)
834
     * @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.
835
     * @return  \Stripe\Card|\Stripe\PaymentMethod|null                 Stripe Card or null if not found
836
     */
837
    public function cardStripe($cu, CompanyPaymentMode $object, $stripeacc = '', $status = 0, $createifnotlinkedtostripe = 0)
838
    {
839
        global $conf, $user, $langs;
840
841
        $card = null;
842
843
        $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_....
844
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_rib as sa";
845
        $sql .= " WHERE sa.rowid = " . ((int) $object->id); // We get record from ID, no need for filter on entity
846
        $sql .= " AND sa.type = 'card'";
847
848
        dol_syslog(get_class($this) . "::cardStripe search stripe card id for paymentmode id=" . $object->id . ", stripeacc=" . $stripeacc . ", status=" . $status . ", createifnotlinkedtostripe=" . $createifnotlinkedtostripe, LOG_DEBUG);
849
        $resql = $this->db->query($sql);
850
        if ($resql) {
851
            $num = $this->db->num_rows($resql);
852
            if ($num) {
853
                $obj = $this->db->fetch_object($resql);
854
                $cardref = $obj->stripe_card_ref;
855
                dol_syslog(get_class($this) . "::cardStripe cardref=" . $cardref);
856
                if ($cardref) {
857
                    try {
858
                        if (empty($stripeacc)) {                // If the Stripe connect account not set, we use common API usage
859
                            if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
860
                                $card = $cu->sources->retrieve($cardref);
861
                            } else {
862
                                $card = \Stripe\PaymentMethod::retrieve($cardref);
863
                            }
864
                        } else {
865
                            if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
866
                                //$card = $cu->sources->retrieve($cardref, array("stripe_account" => $stripeacc));      // this API fails when array stripe_account is provided
867
                                $card = $cu->sources->retrieve($cardref);
868
                            } else {
869
                                //$card = \Stripe\PaymentMethod::retrieve($cardref, array("stripe_account" => $stripeacc));     // Don't know if this works
870
                                $card = \Stripe\PaymentMethod::retrieve($cardref);
871
                            }
872
                        }
873
                    } catch (Exception $e) {
874
                        $this->error = $e->getMessage();
875
                        dol_syslog($this->error, LOG_WARNING);
876
                    }
877
                } elseif ($createifnotlinkedtostripe) {
878
                    // Deprecated with new Stripe API and SCA. We should not use anymore this part of code now.
879
                    $exp_date_month = $obj->exp_date_month;
880
                    $exp_date_year = $obj->exp_date_year;
881
                    $number = $obj->number;
882
                    $cvc = $obj->cvn; // cvn in database, cvc for stripe
883
                    $cardholdername = $obj->proprio;
884
885
                    $ipaddress = getUserRemoteIP();
886
887
                    $dataforcard = array(
888
                        "source" => array(
889
                            'object' => 'card',
890
                            'exp_month' => $exp_date_month,
891
                            'exp_year' => $exp_date_year,
892
                            'number' => $number,
893
                            'cvc' => $cvc,
894
                            'name' => $cardholdername
895
                        ),
896
                        "metadata" => array(
897
                            'dol_type' => $object->element,
898
                            'dol_id' => $object->id,
899
                            'dol_version' => DOL_VERSION,
900
                            'dol_entity' => $conf->entity,
901
                            'ipaddress' => $ipaddress
902
                        )
903
                    );
904
905
                    //$a = \Stripe\Stripe::getApiKey();
906
                    //var_dump($a);
907
                    //var_dump($stripeacc);exit;
908
                    try {
909
                        if (empty($stripeacc)) {                // If the Stripe connect account not set, we use common API usage
910
                            if (!getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
911
                                dol_syslog("Try to create card with dataforcard = " . json_encode($dataforcard));
912
                                $card = $cu->sources->create($dataforcard);
0 ignored issues
show
Bug introduced by
The method create() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

912
                                /** @scrutinizer ignore-call */ 
913
                                $card = $cu->sources->create($dataforcard);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
913
                                if (!$card) {
914
                                    $this->error = 'Creation of card on Stripe has failed';
915
                                }
916
                            } else {
917
                                $connect = '';
918
                                if (!empty($stripeacc)) {
919
                                    $connect = $stripeacc . '/';
920
                                }
921
                                $url = 'https://dashboard.stripe.com/' . $connect . 'test/customers/' . $cu->id;
922
                                if ($status) {
923
                                    $url = 'https://dashboard.stripe.com/' . $connect . 'customers/' . $cu->id;
924
                                }
925
                                $urtoswitchonstripe = '<a href="' . $url . '" target="_stripe">' . img_picto($langs->trans('ShowInStripe'), 'globe') . '</a>';
926
927
                                //dol_syslog("Error: This case is not supported", LOG_ERR);
928
                                $this->error = str_replace('{s1}', $urtoswitchonstripe, $langs->trans('CreationOfPaymentModeMustBeDoneFromStripeInterface', '{s1}'));
929
                            }
930
                        } else {
931
                            if (!getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
932
                                dol_syslog("Try to create card with dataforcard = " . json_encode($dataforcard));
933
                                $card = $cu->sources->create($dataforcard, array("stripe_account" => $stripeacc));
934
                                if (!$card) {
935
                                    $this->error = 'Creation of card on Stripe has failed';
936
                                }
937
                            } else {
938
                                $connect = '';
939
                                if (!empty($stripeacc)) {
940
                                    $connect = $stripeacc . '/';
941
                                }
942
                                $url = 'https://dashboard.stripe.com/' . $connect . 'test/customers/' . $cu->id;
943
                                if ($status) {
944
                                    $url = 'https://dashboard.stripe.com/' . $connect . 'customers/' . $cu->id;
945
                                }
946
                                $urtoswitchonstripe = '<a href="' . $url . '" target="_stripe">' . img_picto($langs->trans('ShowInStripe'), 'globe') . '</a>';
947
948
                                //dol_syslog("Error: This case is not supported", LOG_ERR);
949
                                $this->error = str_replace('{s1}', $urtoswitchonstripe, $langs->trans('CreationOfPaymentModeMustBeDoneFromStripeInterface', '{s1}'));
950
                            }
951
                        }
952
953
                        if ($card) {
954
                            $sql = "UPDATE " . MAIN_DB_PREFIX . "societe_rib";
955
                            $sql .= " SET stripe_card_ref = '" . $this->db->escape($card->id) . "', card_type = '" . $this->db->escape($card->brand) . "',";
956
                            $sql .= " country_code = '" . $this->db->escape($card->country) . "',";
957
                            $sql .= " approved = " . ($card->cvc_check == 'pass' ? 1 : 0);
958
                            $sql .= " WHERE rowid = " . ((int) $object->id);
959
                            $sql .= " AND type = 'card'";
960
                            $resql = $this->db->query($sql);
961
                            if (!$resql) {
962
                                $this->error = $this->db->lasterror();
963
                            }
964
                        }
965
                    } catch (Exception $e) {
966
                        $this->error = $e->getMessage();
967
                        dol_syslog($this->error, LOG_WARNING);
968
                    }
969
                }
970
            }
971
        } else {
972
            dol_print_error($this->db);
973
        }
974
975
        return $card;
976
    }
977
978
979
    /**
980
     * Get the Stripe SEPA of a company payment mode (create it if it doesn't exists and $createifnotlinkedtostripe is set)
981
     *
982
     * @param   \Stripe\Customer        $cu                             Object stripe customer.
983
     * @param   CompanyPaymentMode      $object                         Object companypaymentmode to check, or create on stripe (create on stripe also update the societe_rib table for current entity)
984
     * @param   string                  $stripeacc                      ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
985
     * @param   int                     $status                         Status (0=test, 1=live)
986
     * @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.
987
     * @return  \Stripe\PaymentMethod|null                              Stripe SEPA or null if not found
988
     */
989
    public function sepaStripe($cu, CompanyPaymentMode $object, $stripeacc = '', $status = 0, $createifnotlinkedtostripe = 0)
990
    {
991
        global $conf;
992
        $sepa = null;
993
994
        $sql = "SELECT sa.stripe_card_ref, sa.proprio, sa.iban_prefix as iban, sa.rum"; // stripe_card_ref is 'src_...' for Stripe SEPA
995
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_rib as sa";
996
        $sql .= " WHERE sa.rowid = " . ((int) $object->id); // We get record from ID, no need for filter on entity
997
        $sql .= " AND sa.type = 'ban'"; //type ban to get normal bank account of customer (prelevement)
998
999
        $soc = new Societe($this->db);
1000
        $soc->fetch($object->fk_soc);
1001
1002
        dol_syslog(get_class($this) . "::sepaStripe search stripe ban id for paymentmode id=" . $object->id . ", stripeacc=" . $stripeacc . ", status=" . $status . ", createifnotlinkedtostripe=" . $createifnotlinkedtostripe, LOG_DEBUG);
1003
        $resql = $this->db->query($sql);
1004
        if ($resql) {
1005
            $num = $this->db->num_rows($resql);
1006
            if ($num) {
1007
                $obj = $this->db->fetch_object($resql);
1008
                $cardref = $obj->stripe_card_ref;
1009
                dol_syslog(get_class($this) . "::sepaStripe paymentmode=" . $cardref);
1010
                if ($cardref) {
1011
                    try {
1012
                        if (empty($stripeacc)) {                // If the Stripe connect account not set, we use common API usage
1013
                            if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
1014
                                $sepa = $cu->sources->retrieve($cardref);
1015
                            } else {
1016
                                $sepa = \Stripe\PaymentMethod::retrieve($cardref);
1017
                            }
1018
                        } else {
1019
                            if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
1020
                                //$sepa = $cu->sources->retrieve($cardref, array("stripe_account" => $stripeacc));      // this API fails when array stripe_account is provided
1021
                                $sepa = $cu->sources->retrieve($cardref);
1022
                            } else {
1023
                                //$sepa = \Stripe\PaymentMethod::retrieve($cardref, array("stripe_account" => $stripeacc));     // Don't know if this works
1024
                                $sepa = \Stripe\PaymentMethod::retrieve($cardref);
1025
                            }
1026
                        }
1027
                    } catch (Exception $e) {
1028
                        $this->error = $e->getMessage();
1029
                        dol_syslog($this->error, LOG_WARNING);
1030
                    }
1031
                } elseif ($createifnotlinkedtostripe) {
1032
                    $iban = $obj->iban;
1033
                    $ipaddress = getUserRemoteIP();
1034
                    $metadata = array('dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress);
1035
                    if (is_object($object)) {
1036
                        $metadata['dol_type'] = $object->element;
1037
                        $metadata['dol_id'] = $object->id;
1038
                        $metadata['dol_thirdparty_id'] = $soc->id;
1039
                    }
1040
1041
                    $description = 'SEPA for IBAN ' . $iban;
1042
1043
                    $dataforcard = array(
1044
                        'type' => 'sepa_debit',
1045
                        "sepa_debit" => array('iban' => $iban),
1046
                        'billing_details' => array(
1047
                            'name' => $soc->name,
1048
                            'email' => !empty($soc->email) ? $soc->email : "",
1049
                        ),
1050
                        "metadata" => $metadata
1051
                    );
1052
                    // Complete owner name
1053
                    if (!empty($soc->town)) {
1054
                        $dataforcard['billing_details']['address']['city'] = $soc->town;
1055
                    }
1056
                    if (!empty($soc->country_code)) {
1057
                        $dataforcard['billing_details']['address']['country'] = $soc->country_code;
1058
                    }
1059
                    if (!empty($soc->address)) {
1060
                        $dataforcard['billing_details']['address']['line1'] = $soc->address;
1061
                    }
1062
                    if (!empty($soc->zip)) {
1063
                        $dataforcard['billing_details']['address']['postal_code'] = $soc->zip;
1064
                    }
1065
                    if (!empty($soc->state)) {
1066
                        $dataforcard['billing_details']['address']['state'] = $soc->state;
1067
                    }
1068
1069
                    //$a = \Stripe\Stripe::getApiKey();
1070
                    //var_dump($a);var_dump($stripeacc);exit;
1071
                    try {
1072
                        dol_syslog("Try to create sepa_debit");
1073
1074
                        $service = 'StripeTest';
1075
                        $servicestatus = 0;
1076
                        if (getDolGlobalString('STRIPE_LIVE') && !GETPOST('forcesandbox', 'alpha')) {
1077
                            $service = 'StripeLive';
1078
                            $servicestatus = 1;
1079
                        }
1080
                        // Force to use the correct API key
1081
                        global $stripearrayofkeysbyenv;
1082
                        $stripeacc = $stripearrayofkeysbyenv[$servicestatus]['secret_key'];
1083
1084
                        dol_syslog("Try to create sepa_debit with data = " . json_encode($dataforcard));
1085
1086
                        $s = new \Stripe\StripeClient($stripeacc);
1087
1088
                        //var_dump($dataforcard);exit;
1089
1090
                        $sepa = $s->paymentMethods->create($dataforcard);
1091
                        if (!$sepa) {
1092
                            $this->error = 'Creation of payment method sepa_debit on Stripe has failed';
1093
                        } else {
1094
                            // link customer and src
1095
                            //$cs = $this->getSetupIntent($description, $soc, $cu, '', $status);
1096
                            $dataforintent = array(0 => ['description' => $description, 'payment_method_types' => ['sepa_debit'], 'customer' => $cu->id, 'payment_method' => $sepa->id], 'metadata' => $metadata);
1097
1098
                            $cs = $s->setupIntents->create($dataforintent);
1099
                            //$cs = $s->setupIntents->update($cs->id, ['payment_method' => $sepa->id]);
1100
                            $cs = $s->setupIntents->confirm($cs->id, ['mandate_data' => ['customer_acceptance' => ['type' => 'offline']]]);
1101
                            // note: $cs->mandate contains ID of mandate on Stripe side
1102
1103
                            if (!$cs) {
1104
                                $this->error = 'Link SEPA <-> Customer failed';
1105
                            } else {
1106
                                dol_syslog("Update the payment mode of the customer");
1107
1108
                                // print json_encode($sepa);
1109
1110
                                // Save the Stripe payment mode ID into the Dolibarr database
1111
                                $sql = "UPDATE " . MAIN_DB_PREFIX . "societe_rib";
1112
                                $sql .= " SET stripe_card_ref = '" . $this->db->escape($sepa->id) . "',";
1113
                                $sql .= " card_type = 'sepa_debit',";
1114
                                $sql .= " stripe_account= '" . $this->db->escape($cu->id . "@" . $stripeacc) . "',";
1115
                                $sql .= " ext_payment_site = '" . $this->db->escape($service) . "'";
1116
                                if (!empty($cs->mandate)) {
1117
                                    $mandateservice = new \Stripe\Mandate($stripeacc);
1118
                                    $mandate = $mandateservice->retrieve($cs->mandate);
1119
                                    if (is_object($mandate) && is_object($mandate->payment_method_details) && is_object($mandate->payment_method_details->sepa_debit)) {
1120
                                        $refmandate = $mandate->payment_method_details->sepa_debit->reference;
1121
                                        //$urlmandate = $mandate->payment_method_details->sepa_debit->url;
1122
                                        $sql .= ", rum = '" . $this->db->escape($refmandate) . "'";
1123
                                    }
1124
                                    $sql .= ", comment = '" . $this->db->escape($cs->mandate) . "'";
1125
                                    $sql .= ", date_rum = '" . $this->db->idate(dol_now()) . "'";
1126
                                }
1127
                                $sql .= " WHERE rowid = " . ((int) $object->id);
1128
                                $sql .= " AND type = 'ban'";
1129
                                $resql = $this->db->query($sql);
1130
                                if (!$resql) {
1131
                                    $this->error = $this->db->lasterror();
1132
                                }
1133
                            }
1134
                        }
1135
                    } catch (Exception $e) {
1136
                        $sepa = null;
1137
                        $this->error = 'Stripe error: ' . $e->getMessage() . '. Check the BAN information.';
1138
                        dol_syslog($this->error, LOG_WARNING);  // Error from Stripe, so a warning on Dolibarr
1139
                    }
1140
                }
1141
            }
1142
        } else {
1143
            dol_print_error($this->db);
1144
        }
1145
1146
        return $sepa;
1147
    }
1148
1149
1150
    /**
1151
     * Create charge.
1152
     * This was called by page htdocs/stripe/payment.php and may be deprecated.
1153
     *
1154
     * @param   int     $amount                                 Amount to pay
1155
     * @param   string  $currency                               EUR, GPB...
1156
     * @param   string  $origin                                 Object type to pay (order, invoice, contract...)
1157
     * @param   int     $item                                   Object id to pay
1158
     * @param   string  $source                                 src_xxxxx or card_xxxxx or pm_xxxxx
1159
     * @param   string  $customer                               Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
1160
     * @param   string  $account                                Stripe account ref 'acc_xxxxxxxxxxxxx' via  getStripeAccount()
1161
     * @param   int     $status                                 Status (0=test, 1=live)
1162
     * @param   int     $usethirdpartyemailforreceiptemail      Use thirdparty email as receipt email
1163
     * @param   boolean $capture                                Set capture flag to true (take payment) or false (wait)
1164
     * @return Stripe
1165
     * @deprecated
1166
     */
1167
    public function createPaymentStripe($amount, $currency, $origin, $item, $source, $customer, $account, $status = 0, $usethirdpartyemailforreceiptemail = 0, $capture = true)
1168
    {
1169
        global $conf;
1170
1171
        $error = 0;
1172
1173
        if (empty($status)) {
1174
            $service = 'StripeTest';
1175
        } else {
1176
            $service = 'StripeLive';
1177
        }
1178
1179
        $sql = "SELECT sa.key_account as key_account, sa.fk_soc, sa.entity";
1180
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_account as sa";
1181
        $sql .= " WHERE sa.key_account = '" . $this->db->escape($customer) . "'";
1182
        //$sql.= " AND sa.entity IN (".getEntity('societe').")";
1183
        $sql .= " AND sa.site = 'stripe' AND sa.status = " . ((int) $status);
1184
1185
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
1186
        $result = $this->db->query($sql);
1187
        if ($result) {
1188
            if ($this->db->num_rows($result)) {
1189
                $obj = $this->db->fetch_object($result);
1190
                $key = $obj->fk_soc;
1191
            } else {
1192
                $key = null;
1193
            }
1194
        } else {
1195
            $key = null;
1196
        }
1197
1198
        $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF');
1199
        if (!in_array($currency, $arrayzerounitcurrency)) {
1200
            $stripeamount = $amount * 100;
1201
        } else {
1202
            $stripeamount = $amount;
1203
        }
1204
1205
        $societe = new Societe($this->db);
1206
        if ($key > 0) {
1207
            $societe->fetch($key);
1208
        }
1209
1210
        $description = "";
1211
        $ref = "";
1212
        if ($origin == 'order') {
1213
            $order = new Commande($this->db);
1214
            $order->fetch($item);
1215
            $ref = $order->ref;
1216
            $description = "ORD=" . $ref . ".CUS=" . $societe->id . ".PM=stripe";
1217
        } elseif ($origin == 'invoice') {
1218
            $invoice = new Facture($this->db);
1219
            $invoice->fetch($item);
1220
            $ref = $invoice->ref;
1221
            $description = "INV=" . $ref . ".CUS=" . $societe->id . ".PM=stripe";
1222
        }
1223
1224
        $ipaddress = getUserRemoteIP();
1225
1226
        $metadata = array(
1227
            "dol_id" => (string) $item,
1228
            "dol_type" => (string) $origin,
1229
            "dol_thirdparty_id" => (string) $societe->id,
1230
            'dol_thirdparty_name' => $societe->name,
1231
            'dol_version' => DOL_VERSION,
1232
            'dol_entity' => $conf->entity,
1233
            'ipaddress' => $ipaddress
1234
        );
1235
        $return = new Stripe($this->db);
1236
        try {
1237
            // Force to use the correct API key
1238
            global $stripearrayofkeysbyenv;
1239
            \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
1240
1241
            if (empty($conf->stripeconnect->enabled)) { // With a common Stripe account
1242
                if (preg_match('/pm_/i', $source)) {
1243
                    $stripecard = $source;
1244
                    $amountstripe = $stripeamount;
1245
                    $FULLTAG = 'PFBO'; // Payment From Back Office
1246
                    $stripe = $return;
1247
                    $amounttopay = $amount;
1248
                    $servicestatus = $status;
1249
1250
                    dol_syslog("* createPaymentStripe get stripeacc", LOG_DEBUG);
1251
                    $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account if it exists (no network access here)
1252
1253
                    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...
1254
1255
                    // Create payment intent and charge payment (confirmnow = true)
1256
                    $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1);
1257
1258
                    $charge = new stdClass();
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Stripe\Classes\stdClass was not found. Did you mean stdClass? If so, make sure to prefix the type with \.
Loading history...
1259
                    if ($paymentintent->status == 'succeeded') {
1260
                        $charge->status = 'ok';
1261
                    } else {
1262
                        $charge->status = 'failed';
1263
                        $charge->failure_code = $stripe->code;
1264
                        $charge->failure_message = $stripe->error;
1265
                        $charge->failure_declinecode = $stripe->declinecode;
1266
                        $stripefailurecode = $stripe->code;
1267
                        $stripefailuremessage = $stripe->error;
1268
                        $stripefailuredeclinecode = $stripe->declinecode;
1269
                    }
1270
                } elseif (preg_match('/acct_/i', $source)) {
1271
                    $charge = \Stripe\Charge::create(array(
1272
                        "amount" => "$stripeamount",
1273
                        "currency" => "$currency",
1274
                        "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
1275
                        "description" => "Stripe payment: " . $description,
1276
                        "capture"  => $capture,
1277
                        "metadata" => $metadata,
1278
                        "source" => "$source"
1279
                    ));
1280
                } else {
1281
                    $paymentarray = array(
1282
                        "amount" => "$stripeamount",
1283
                        "currency" => "$currency",
1284
                        "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
1285
                        "description" => "Stripe payment: " . $description,
1286
                        "capture"  => $capture,
1287
                        "metadata" => $metadata,
1288
                        "source" => "$source",
1289
                        "customer" => "$customer"
1290
                    );
1291
1292
                    if ($societe->email && $usethirdpartyemailforreceiptemail) {
1293
                        $paymentarray["receipt_email"] = $societe->email;
1294
                    }
1295
1296
                    $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description"));
1297
                }
1298
            } else {
1299
                // With Stripe Connect
1300
                $fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE;
1301
                if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
1302
                    $fee = getDolGlobalString('STRIPE_APPLICATION_FEE_MAXIMAL');
1303
                } elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
1304
                    $fee = getDolGlobalString('STRIPE_APPLICATION_FEE_MINIMAL');
1305
                }
1306
1307
                if (!in_array($currency, $arrayzerounitcurrency)) {
1308
                    $stripefee = round($fee * 100);
1309
                } else {
1310
                    $stripefee = round($fee);
1311
                }
1312
1313
                $paymentarray = array(
1314
                    "amount" => "$stripeamount",
1315
                    "currency" => "$currency",
1316
                "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
1317
                    "description" => "Stripe payment: " . $description,
1318
                    "capture"  => $capture,
1319
                    "metadata" => $metadata,
1320
                    "source" => "$source",
1321
                    "customer" => "$customer"
1322
                );
1323
                if ($conf->entity != $conf->global->STRIPECONNECT_PRINCIPAL && $stripefee > 0) {
1324
                    $paymentarray["application_fee_amount"] = $stripefee;
1325
                }
1326
                if ($societe->email && $usethirdpartyemailforreceiptemail) {
1327
                    $paymentarray["receipt_email"] = $societe->email;
1328
                }
1329
1330
                if (preg_match('/pm_/i', $source)) {
1331
                    $stripecard = $source;
1332
                    $amountstripe = $stripeamount;
1333
                    $FULLTAG = 'PFBO'; // Payment From Back Office
1334
                    $stripe = $return;
1335
                    $amounttopay = $amount;
1336
                    $servicestatus = $status;
1337
1338
                    dol_syslog("* createPaymentStripe get stripeacc", LOG_DEBUG);
1339
                    $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account if it exists (no network access here)
1340
1341
                    dol_syslog("* createPaymentStripe Create payment on card " . $stripecard->id . ", amounttopay=" . $amounttopay . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG);
1342
1343
                    // Create payment intent and charge payment (confirmnow = true)
1344
                    $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1);
1345
1346
                    $charge = new stdClass();
1347
                    if ($paymentintent->status == 'succeeded') {
1348
                        $charge->status = 'ok';
1349
                        $charge->id = $paymentintent->id;
1350
                    } else {
1351
                        $charge->status = 'failed';
1352
                        $charge->failure_code = $stripe->code;
1353
                        $charge->failure_message = $stripe->error;
1354
                        $charge->failure_declinecode = $stripe->declinecode;
1355
                    }
1356
                } else {
1357
                    $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description", "stripe_account" => "$account"));
1358
                }
1359
            }
1360
            if (isset($charge->id)) {
1361
            }
1362
1363
            $return->result = 'success';
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Stripe\Classes\Stripe::$result has been deprecated: Was used by createPaymentStripe only that is deprecated ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1363
            /** @scrutinizer ignore-deprecated */ $return->result = 'success';

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1364
            $return->id = $charge->id;
0 ignored issues
show
Documentation Bug introduced by
It seems like $charge->id can also be of type string. However, the property $id is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1365
1366
            if (preg_match('/pm_/i', $source)) {
1367
                $return->message = 'Payment retrieved by card status = ' . $charge->status;
1368
            } else {
1369
                if ($charge->source->type == 'card') {
1370
                    $return->message = $charge->source->card->brand . " ...." . $charge->source->card->last4;
1371
                } elseif ($charge->source->type == 'three_d_secure') {
1372
                    $stripe = new Stripe($this->db);
1373
                    $src = \Stripe\Source::retrieve("" . $charge->source->three_d_secure->card, array(
1374
                    "stripe_account" => $stripe->getStripeAccount($service)
1375
                    ));
1376
                    $return->message = $src->card->brand . " ...." . $src->card->last4;
1377
                } else {
1378
                    $return->message = $charge->id;
1379
                }
1380
            }
1381
        } catch (\Stripe\Exception\CardException $e) {
1382
            include DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php';
1383
            // Since it's a decline, \Stripe\Exception\Card will be caught
1384
            $body = $e->getJsonBody();
1385
            $err = $body['error'];
1386
1387
            $return->result = 'error';
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Stripe\Classes\Stripe::$result has been deprecated: Was used by createPaymentStripe only that is deprecated ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1387
            /** @scrutinizer ignore-deprecated */ $return->result = 'error';

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1388
            $return->id = $err['charge'];
1389
            $return->type = $err['type'];
1390
            $return->code = $err['code'];
1391
            $return->message = $err['message'];
1392
            $body = "Error: <br>" . $return->id . " " . $return->message . " ";
1393
            $subject = '[Alert] Payment error using Stripe';
1394
            $cmailfile = new CMailFile($subject, $conf->global->ONLINE_PAYMENT_SENDEMAIL, $conf->global->MAIN_INFO_SOCIETE_MAIL, $body);
1395
            $cmailfile->sendfile();
1396
1397
            $error++;
1398
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1399
        } catch (\Stripe\Exception\RateLimitException $e) {
1400
            // Too many requests made to the API too quickly
1401
            $error++;
1402
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1403
        } catch (\Stripe\Exception\InvalidRequestException $e) {
1404
            // Invalid parameters were supplied to Stripe's API
1405
            $error++;
1406
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1407
        } catch (\Stripe\Exception\AuthenticationException $e) {
1408
            // Authentication with Stripe's API failed
1409
            // (maybe you changed API keys recently)
1410
            $error++;
1411
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1412
        } catch (\Stripe\Exception\ApiConnectionException $e) {
1413
            // Network communication with Stripe failed
1414
            $error++;
1415
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1416
        } catch (\Stripe\Exception\ExceptionInterface $e) {
1417
            // Display a very generic error to the user, and maybe send
1418
            // yourself an email
1419
            $error++;
1420
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
0 ignored issues
show
Bug introduced by
The method getMessage() does not exist on Stripe\Exception\ExceptionInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Stripe\Exception\OAuth\ExceptionInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1420
            dol_syslog($e->/** @scrutinizer ignore-call */ getMessage(), LOG_WARNING, 0, '_stripe');
Loading history...
1421
        } catch (Exception $e) {
1422
            // Something else happened, completely unrelated to Stripe
1423
            $error++;
1424
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1425
        }
1426
        return $return;
1427
    }
1428
}
1429