Test Failed
Push — main ( 1be143...29a1e7 )
by Rafael
51:40
created

Stripe::getPaymentIntent()   F

Complexity

Conditions 54
Paths > 20000

Size

Total Lines 281
Code Lines 173

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 54
eloc 173
nc 1451229856
nop 15
dl 0
loc 281
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 DoliModules\Stripe\Model;
23
24
use DoliCore\Base\GenericDocument;
25
use DoliModules\Company\Model\Company;
26
use DoliModules\Company\Model\CompanyPaymentMode;
27
use DoliModules\Company\Model\SocieteAccount;
28
29
require_once DOL_DOCUMENT_ROOT . '/stripe/config.php'; // This set stripe global env
30
31
/**
32
 *  Stripe class
33
 */
34
class Stripe extends GenericDocument
35
{
36
    /**
37
     * @var int ID
38
     */
39
    public $rowid;
40
41
    /**
42
     * @var int Thirdparty ID
43
     */
44
    public $fk_soc;
45
46
    /**
47
     * @var int ID
48
     */
49
    public $fk_key;
50
51
    /**
52
     * @var int ID
53
     */
54
    public $id;
55
56
    /**
57
     * @var string
58
     */
59
    public $mode;
60
61
    /**
62
     * @var int Entity
63
     */
64
    public $entity;
65
66
    /**
67
     * @var string
68
     */
69
    public $statut;
70
71
    public $type;
72
73
    /**
74
     * @var string
75
     */
76
    public $code;
77
78
    /**
79
     * @var string
80
     */
81
    public $declinecode;
82
83
    /**
84
     * @var string Message
85
     */
86
    public $message;
87
88
    /**
89
     *  Constructor
90
     *
91
     * @param DoliDB $db Database handler
0 ignored issues
show
Bug introduced by
The type DoliModules\Stripe\Model\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
92
     */
93
    public function __construct($db)
94
    {
95
        $this->db = $db;
96
    }
97
98
    /**
99
     * getStripeCustomerAccount
100
     *
101
     * @param int    $id           Id of third party
102
     * @param int    $status       Status
103
     * @param string $site_account Value to use to identify with account to use on site when site can offer several
104
     *                             accounts. For example: 'pk_live_123456' when using Stripe service.
105
     *
106
     * @return  string                  Stripe customer ref 'cu_xxxxxxxxxxxxx' or ''
107
     */
108
    public function getStripeCustomerAccount($id, $status = 0, $site_account = '')
109
    {
110
        include_once DOL_DOCUMENT_ROOT . '/societe/class/societeaccount.class.php';
111
        $societeaccount = new SocieteAccount($this->db);
112
        return $societeaccount->getCustomerAccount($id, 'stripe', $status, $site_account); // Get thirdparty cus_...
113
    }
114
115
    /**
116
     * Get the Stripe customer of a thirdparty (with option to create it in Stripe if not linked yet).
117
     * Search on site_account = 0 or = $stripearrayofkeysbyenv[$status]['publishable_key']
118
     *
119
     * @param Societe $object                    Object thirdparty to check, or create on stripe (create on stripe also
120
     *                                           update the stripe_account table for current entity)
121
     * @param string  $key                       ''=Use common API. If not '', it is the Stripe connect account
122
     *                                           'acc_....' to use Stripe connect
123
     * @param int     $status                    Status (0=test, 1=live)
124
     * @param int     $createifnotlinkedtostripe 1=Create the stripe customer and the link if the thirdparty is not yet
125
     *                                           linked to a stripe customer
126
     *
127
     * @return  \Stripe\Customer|null                   Stripe Customer or null if not found
128
     */
129
    public function customerStripe(Company $object, $key = '', $status = 0, $createifnotlinkedtostripe = 0)
130
    {
131
        global $conf, $user;
132
133
        if (empty($object->id)) {
134
            dol_syslog("customerStripe is called with the parameter object that is not loaded");
135
            return null;
136
        }
137
138
        $customer = null;
139
140
        // Force to use the correct API key
141
        global $stripearrayofkeysbyenv;
142
        \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
143
144
        $sql = "SELECT sa.key_account as key_account, sa.entity"; // key_account is cus_....
145
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_account as sa";
146
        $sql .= " WHERE sa.fk_soc = " . ((int) $object->id);
147
        $sql .= " AND sa.entity IN (" . getEntity('societe') . ")";
148
        $sql .= " AND sa.site = 'stripe' AND sa.status = " . ((int) $status);
149
        $sql .= " AND (sa.site_account IS NULL OR sa.site_account = '' OR sa.site_account = '" . $this->db->escape($stripearrayofkeysbyenv[$status]['publishable_key']) . "')";
150
        $sql .= " AND sa.key_account IS NOT NULL AND sa.key_account <> ''";
151
152
        dol_syslog(get_class($this) . "::customerStripe search stripe customer id for thirdparty id=" . $object->id, LOG_DEBUG);
153
        $resql = $this->db->query($sql);
154
        if ($resql) {
155
            $num = $this->db->num_rows($resql);
156
            if ($num) {
157
                $obj = $this->db->fetch_object($resql);
158
                $tiers = $obj->key_account;
159
160
                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']);
161
162
                try {
163
                    if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
164
                        //$customer = \Stripe\Customer::retrieve("$tiers");
165
                        $customer = \Stripe\Customer::retrieve(['id' => "$tiers", 'expand[]' => 'sources']);
166
                    } else {
167
                        //$customer = \Stripe\Customer::retrieve("$tiers", array("stripe_account" => $key));
168
                        $customer = \Stripe\Customer::retrieve(['id' => "$tiers", 'expand[]' => 'sources'], ["stripe_account" => $key]);
169
                    }
170
                } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The type DoliModules\Stripe\Model\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
171
                    // 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.'
172
                    $this->error = $e->getMessage();
173
                }
174
            } elseif ($createifnotlinkedtostripe) {
175
                $ipaddress = getUserRemoteIP();
176
177
                $dataforcustomer = [
178
                    "email" => $object->email,
179
                    "description" => $object->name,
180
                    "metadata" => ['dol_id' => $object->id, 'dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress],
181
                ];
182
183
                $vatcleaned = $object->tva_intra ? $object->tva_intra : null;
184
185
                /*
186
                $taxinfo = array('type'=>'vat');
187
                if ($vatcleaned)
188
                {
189
                    $taxinfo["tax_id"] = $vatcleaned;
190
                }
191
                // We force data to "null" if not defined as expected by Stripe
192
                if (empty($vatcleaned)) $taxinfo=null;
193
                $dataforcustomer["tax_info"] = $taxinfo;
194
                */
195
196
                //$a = \Stripe\Stripe::getApiKey();
197
                //var_dump($a);var_dump($key);exit;
198
                try {
199
                    // Force to use the correct API key
200
                    global $stripearrayofkeysbyenv;
201
                    \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
202
203
                    if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
204
                        $customer = \Stripe\Customer::create($dataforcustomer);
205
                    } else {
206
                        $customer = \Stripe\Customer::create($dataforcustomer, ["stripe_account" => $key]);
207
                    }
208
209
                    // Create the VAT record in Stripe
210
                    if (getDolGlobalString('STRIPE_SAVE_TAX_IDS')) {    // We setup to save Tax info on Stripe side. Warning: This may result in error when saving customer
211
                        if (!empty($vatcleaned)) {
212
                            $isineec = isInEEC($object);
213
                            if ($object->country_code && $isineec) {
214
                                //$taxids = $customer->allTaxIds($customer->id);
215
                                $customer->createTaxId($customer->id, ['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

215
                                $customer->/** @scrutinizer ignore-call */ 
216
                                           createTaxId($customer->id, ['type' => 'eu_vat', 'value' => $vatcleaned]);
Loading history...
216
                            }
217
                        }
218
                    }
219
220
                    // Create customer in Dolibarr
221
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "societe_account (fk_soc, login, key_account, site, site_account, status, entity, date_creation, fk_user_creat)";
222
                    $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) . ")";
223
                    $resql = $this->db->query($sql);
224
                    if (!$resql) {
225
                        $this->error = $this->db->lasterror();
226
                    }
227
                } catch (Exception $e) {
228
                    $this->error = $e->getMessage();
229
                }
230
            }
231
        } else {
232
            dol_print_error($this->db);
233
        }
234
235
        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...
236
    }
237
238
    /**
239
     * Get the Stripe payment method Object from its ID
240
     *
241
     * @param string $paymentmethod Payment Method ID
242
     * @param string $key           ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use
243
     *                              Stripe connect
244
     * @param int    $status        Status (0=test, 1=live)
245
     *
246
     * @return  \Stripe\PaymentMethod|null          Stripe PaymentMethod or null if not found
247
     */
248
    public function getPaymentMethodStripe($paymentmethod, $key = '', $status = 0)
249
    {
250
        $stripepaymentmethod = null;
251
252
        try {
253
            // Force to use the correct API key
254
            global $stripearrayofkeysbyenv;
255
            \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
256
            if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
257
                $stripepaymentmethod = \Stripe\PaymentMethod::retrieve((string) $paymentmethod->id);
0 ignored issues
show
Bug introduced by
The property id does not exist on string.
Loading history...
258
            } else {
259
                $stripepaymentmethod = \Stripe\PaymentMethod::retrieve((string) $paymentmethod->id, ["stripe_account" => $key]);
260
            }
261
        } catch (Exception $e) {
262
            $this->error = $e->getMessage();
263
        }
264
265
        return $stripepaymentmethod;
266
    }
267
268
    /**
269
     * Get the Stripe reader Object from its ID
270
     *
271
     * @param string $reader Reader ID
272
     * @param string $key    ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe
273
     *                       connect
274
     * @param int    $status Status (0=test, 1=live)
275
     *
276
     * @return  \Stripe\Terminal\Reader|null        Stripe Reader or null if not found
277
     */
278
    public function getSelectedReader($reader, $key = '', $status = 0)
279
    {
280
        $selectedreader = null;
281
282
        try {
283
            // Force to use the correct API key
284
            global $stripearrayofkeysbyenv;
285
            \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
286
            if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
287
                $selectedreader = \Stripe\Terminal\Reader::retrieve((string) $reader);
288
            } else {
289
                $stripepaymentmethod = \Stripe\Terminal\Reader::retrieve((string) $reader, ["stripe_account" => $key]);
290
            }
291
        } catch (Exception $e) {
292
            $this->error = $e->getMessage();
293
        }
294
295
        return $selectedreader;
296
    }
297
298
    /**
299
     * Get the Stripe payment intent. Create it with confirmnow=false
300
     * Warning. If a payment was tried and failed, a payment intent was created.
301
     * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed.
302
     * Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically
303
     * closed after a delay), that's why i comment the part of code to retrieve a payment intent with object id (never
304
     * mind if we cumulate payment intent with old ones that will not be used) Note: This is used when option
305
     * STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is on when making a payment from the public/payment/newpayment.php
306
     * page but not when using the STRIPE_USE_NEW_CHECKOUT.
307
     *
308
     * @param string  $description                       Description
309
     * @param Societe $object                            Object of company to link the Stripe payment mode with
310
     * @param string  $customer                          Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
311
     * @param string  $key                               ''=Use common API. If not '', it is the Stripe connect account
312
     *                                                   'acc_....' to use Stripe connect
313
     * @param int     $status                            Status (0=test, 1=live)
314
     * @param int     $usethirdpartyemailforreceiptemail 1=use thirdparty email for receipt
315
     * @param boolean $confirmnow                        false=default, true=try to confirm immediately after create
316
     *                                                   (if conditions are ok)
317
     *
318
     * @return  \Stripe\SetupIntent|null                    Stripe SetupIntent or null if not found and failed to
319
     *                                                      create
320
     */
321
    public function getSetupIntent($description, $object, $customer, $key, $status, $usethirdpartyemailforreceiptemail = 0, $confirmnow = false)
322
    {
323
        global $conf;
324
325
        dol_syslog("getSetupIntent description=" . $description . ' confirmnow=' . $confirmnow, LOG_INFO, 1);
326
327
        $error = 0;
328
329
        if (empty($status)) {
330
            $service = 'StripeTest';
331
        } else {
332
            $service = 'StripeLive';
333
        }
334
335
        $setupintent = null;
336
337
        if (empty($setupintent)) {
338
            $ipaddress = getUserRemoteIP();
339
            $metadata = ['dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress];
340
            if (is_object($object)) {
341
                $metadata['dol_type'] = $object->element;
342
                $metadata['dol_id'] = $object->id;
343
                if (is_object($object->thirdparty) && $object->thirdparty->id > 0) {
344
                    $metadata['dol_thirdparty_id'] = $object->thirdparty->id;
345
                }
346
            }
347
348
            // list of payment method types
349
            $paymentmethodtypes = ["card"];
350
            if (getDolGlobalString('STRIPE_SEPA_DIRECT_DEBIT')) {
351
                $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
352
            }
353
            if (getDolGlobalString('STRIPE_BANCONTACT')) {
354
                $paymentmethodtypes[] = "bancontact";
355
            }
356
            if (getDolGlobalString('STRIPE_IDEAL')) {
357
                $paymentmethodtypes[] = "ideal";
358
            }
359
            // Giropay not possible for setup intent
360
            if (getDolGlobalString('STRIPE_SOFORT')) {
361
                $paymentmethodtypes[] = "sofort";
362
            }
363
364
            global $dolibarr_main_url_root;
365
366
            $dataforintent = [
367
                "confirm" => $confirmnow, // Do not confirm immediately during creation of intent
368
                "payment_method_types" => $paymentmethodtypes,  // When payment_method_types is set, return_url is not required but payment mode can't be managed from dashboard
369
                /*
370
                 'return_url' => $dolibarr_main_url_root.'/public/payment/paymentok.php',
371
                 'automatic_payment_methods' => array(
372
                 'enabled' => true,
373
                 'allow_redirects' => 'never',
374
                 ),
375
                 */
376
                "usage" => "off_session",
377
                "metadata" => $metadata,
378
            ];
379
            if (!is_null($customer)) {
380
                $dataforintent["customer"] = $customer;
381
            }
382
            if (!is_null($description)) {
383
                $dataforintent["description"] = $description;
384
            }
385
            // payment_method =
386
            // payment_method_types = array('card')
387
            //var_dump($dataforintent);
388
389
            if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) {
390
                $dataforintent["receipt_email"] = $object->thirdparty->email;
391
            }
392
393
            try {
394
                // Force to use the correct API key
395
                global $stripearrayofkeysbyenv;
396
                \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
397
398
                dol_syslog("getSetupIntent " . $stripearrayofkeysbyenv[$status]['publishable_key'], LOG_DEBUG);
399
400
                // 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.
401
                if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
402
                    //$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description"));
403
                    $setupintent = \Stripe\SetupIntent::create($dataforintent, []);
404
                } else {
405
                    //$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key));
406
                    $setupintent = \Stripe\SetupIntent::create($dataforintent, ["stripe_account" => $key]);
407
                }
408
                //var_dump($setupintent->id);
409
410
                // Store the setup intent
411
                /*if (is_object($object))
412
                {
413
                    $setupintentalreadyexists = 0;
414
                    // Check that payment intent $setupintent->id is not already recorded.
415
                    $sql = "SELECT pi.rowid";
416
                    $sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_demande as pi";
417
                    $sql.= " WHERE pi.entity IN (".getEntity('societe').")";
418
                    $sql.= " AND pi.ext_payment_site = '" . $this->db->escape($service) . "'";
419
                    $sql.= " AND pi.ext_payment_id = '".$this->db->escape($setupintent->id)."'";
420
421
                    dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
422
                    $resql = $this->db->query($sql);
423
                    if ($resql) {
424
                        $num = $this->db->num_rows($resql);
425
                        if ($num)
426
                        {
427
                            $obj = $this->db->fetch_object($resql);
428
                            if ($obj) $setupintentalreadyexists++;
429
                        }
430
                    }
431
                    else dol_print_error($this->db);
432
433
                    // If not, we create it.
434
                    if (! $setupintentalreadyexists)
435
                    {
436
                        $now=dol_now();
437
                        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site)";
438
                        $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).")";
439
                        $resql = $this->db->query($sql);
440
                        if (! $resql)
441
                        {
442
                            $error++;
443
                            $this->error = $this->db->lasterror();
444
                            dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$setupintent->id." into database.");
445
                        }
446
                    }
447
                }
448
                else
449
                {
450
                    $_SESSION["stripe_setup_intent"] = $setupintent;
451
                }*/
452
            } catch (Exception $e) {
453
                //var_dump($dataforintent);
454
                //var_dump($description);
455
                //var_dump($key);
456
                //var_dump($setupintent);
457
                //var_dump($e->getMessage());
458
                $error++;
459
                $this->error = $e->getMessage();
460
            }
461
        }
462
463
        if (!$error) {
464
            dol_syslog("getSetupIntent " . (is_object($setupintent) ? $setupintent->id : ''), LOG_INFO, -1);
465
            return $setupintent;
466
        } else {
467
            dol_syslog("getSetupIntent return error=" . $error, LOG_INFO, -1);
468
            return null;
469
        }
470
    }
471
472
    /**
473
     * Get the Stripe card of a company payment mode (option to create it on Stripe if not linked yet is no more
474
     * available on new Stripe API)
475
     *
476
     * @param \Stripe\Customer   $cu                        Object stripe customer.
477
     * @param CompanyPaymentMode $object                    Object companypaymentmode to check, or create on stripe
478
     *                                                      (create on stripe also update the societe_rib table for
479
     *                                                      current entity)
480
     * @param string             $stripeacc                 ''=Use common API. If not '', it is the Stripe connect
481
     *                                                      account 'acc_....' to use Stripe connect
482
     * @param int                $status                    Status (0=test, 1=live)
483
     * @param int                $createifnotlinkedtostripe 1=Create the stripe card and the link if the card is not
484
     *                                                      yet linked to a stripe card. Deprecated with new Stripe API
485
     *                                                      and SCA.
486
     *
487
     * @return  \Stripe\Card|\Stripe\PaymentMethod|null                 Stripe Card or null if not found
488
     */
489
    public function cardStripe($cu, CompanyPaymentMode $object, $stripeacc = '', $status = 0, $createifnotlinkedtostripe = 0)
490
    {
491
        global $conf, $user, $langs;
492
493
        $card = null;
494
495
        $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_....
496
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_rib as sa";
497
        $sql .= " WHERE sa.rowid = " . ((int) $object->id); // We get record from ID, no need for filter on entity
498
        $sql .= " AND sa.type = 'card'";
499
500
        dol_syslog(get_class($this) . "::cardStripe search stripe card id for paymentmode id=" . $object->id . ", stripeacc=" . $stripeacc . ", status=" . $status . ", createifnotlinkedtostripe=" . $createifnotlinkedtostripe, LOG_DEBUG);
501
        $resql = $this->db->query($sql);
502
        if ($resql) {
503
            $num = $this->db->num_rows($resql);
504
            if ($num) {
505
                $obj = $this->db->fetch_object($resql);
506
                $cardref = $obj->stripe_card_ref;
507
                dol_syslog(get_class($this) . "::cardStripe cardref=" . $cardref);
508
                if ($cardref) {
509
                    try {
510
                        if (empty($stripeacc)) {                // If the Stripe connect account not set, we use common API usage
511
                            if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
512
                                $card = $cu->sources->retrieve($cardref);
513
                            } else {
514
                                $card = \Stripe\PaymentMethod::retrieve($cardref);
515
                            }
516
                        } else {
517
                            if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
518
                                //$card = $cu->sources->retrieve($cardref, array("stripe_account" => $stripeacc));      // this API fails when array stripe_account is provided
519
                                $card = $cu->sources->retrieve($cardref);
520
                            } else {
521
                                //$card = \Stripe\PaymentMethod::retrieve($cardref, array("stripe_account" => $stripeacc));     // Don't know if this works
522
                                $card = \Stripe\PaymentMethod::retrieve($cardref);
523
                            }
524
                        }
525
                    } catch (Exception $e) {
526
                        $this->error = $e->getMessage();
527
                        dol_syslog($this->error, LOG_WARNING);
528
                    }
529
                } elseif ($createifnotlinkedtostripe) {
530
                    // Deprecated with new Stripe API and SCA. We should not use anymore this part of code now.
531
                    $exp_date_month = $obj->exp_date_month;
532
                    $exp_date_year = $obj->exp_date_year;
533
                    $number = $obj->number;
534
                    $cvc = $obj->cvn; // cvn in database, cvc for stripe
535
                    $cardholdername = $obj->proprio;
536
537
                    $ipaddress = getUserRemoteIP();
538
539
                    $dataforcard = [
540
                        "source" => [
541
                            'object' => 'card',
542
                            'exp_month' => $exp_date_month,
543
                            'exp_year' => $exp_date_year,
544
                            'number' => $number,
545
                            'cvc' => $cvc,
546
                            'name' => $cardholdername,
547
                        ],
548
                        "metadata" => [
549
                            'dol_type' => $object->element,
550
                            'dol_id' => $object->id,
551
                            'dol_version' => DOL_VERSION,
552
                            'dol_entity' => $conf->entity,
553
                            'ipaddress' => $ipaddress,
554
                        ],
555
                    ];
556
557
                    //$a = \Stripe\Stripe::getApiKey();
558
                    //var_dump($a);
559
                    //var_dump($stripeacc);exit;
560
                    try {
561
                        if (empty($stripeacc)) {                // If the Stripe connect account not set, we use common API usage
562
                            if (!getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
563
                                dol_syslog("Try to create card with dataforcard = " . json_encode($dataforcard));
564
                                $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

564
                                /** @scrutinizer ignore-call */ 
565
                                $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...
565
                                if (!$card) {
566
                                    $this->error = 'Creation of card on Stripe has failed';
567
                                }
568
                            } else {
569
                                $connect = '';
570
                                if (!empty($stripeacc)) {
571
                                    $connect = $stripeacc . '/';
572
                                }
573
                                $url = 'https://dashboard.stripe.com/' . $connect . 'test/customers/' . $cu->id;
574
                                if ($status) {
575
                                    $url = 'https://dashboard.stripe.com/' . $connect . 'customers/' . $cu->id;
576
                                }
577
                                $urtoswitchonstripe = '<a href="' . $url . '" target="_stripe">' . img_picto($langs->trans('ShowInStripe'), 'globe') . '</a>';
578
579
                                //dol_syslog("Error: This case is not supported", LOG_ERR);
580
                                $this->error = str_replace('{s1}', $urtoswitchonstripe, $langs->trans('CreationOfPaymentModeMustBeDoneFromStripeInterface', '{s1}'));
581
                            }
582
                        } else {
583
                            if (!getDolGlobalString('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION')) {
584
                                dol_syslog("Try to create card with dataforcard = " . json_encode($dataforcard));
585
                                $card = $cu->sources->create($dataforcard, ["stripe_account" => $stripeacc]);
586
                                if (!$card) {
587
                                    $this->error = 'Creation of card on Stripe has failed';
588
                                }
589
                            } else {
590
                                $connect = '';
591
                                if (!empty($stripeacc)) {
592
                                    $connect = $stripeacc . '/';
593
                                }
594
                                $url = 'https://dashboard.stripe.com/' . $connect . 'test/customers/' . $cu->id;
595
                                if ($status) {
596
                                    $url = 'https://dashboard.stripe.com/' . $connect . 'customers/' . $cu->id;
597
                                }
598
                                $urtoswitchonstripe = '<a href="' . $url . '" target="_stripe">' . img_picto($langs->trans('ShowInStripe'), 'globe') . '</a>';
599
600
                                //dol_syslog("Error: This case is not supported", LOG_ERR);
601
                                $this->error = str_replace('{s1}', $urtoswitchonstripe, $langs->trans('CreationOfPaymentModeMustBeDoneFromStripeInterface', '{s1}'));
602
                            }
603
                        }
604
605
                        if ($card) {
606
                            $sql = "UPDATE " . MAIN_DB_PREFIX . "societe_rib";
607
                            $sql .= " SET stripe_card_ref = '" . $this->db->escape($card->id) . "', card_type = '" . $this->db->escape($card->brand) . "',";
608
                            $sql .= " country_code = '" . $this->db->escape($card->country) . "',";
609
                            $sql .= " approved = " . ($card->cvc_check == 'pass' ? 1 : 0);
610
                            $sql .= " WHERE rowid = " . ((int) $object->id);
611
                            $sql .= " AND type = 'card'";
612
                            $resql = $this->db->query($sql);
613
                            if (!$resql) {
614
                                $this->error = $this->db->lasterror();
615
                            }
616
                        }
617
                    } catch (Exception $e) {
618
                        $this->error = $e->getMessage();
619
                        dol_syslog($this->error, LOG_WARNING);
620
                    }
621
                }
622
            }
623
        } else {
624
            dol_print_error($this->db);
625
        }
626
627
        return $card;
628
    }
629
630
    /**
631
     * Get the Stripe SEPA of a company payment mode (create it if it doesn't exists and $createifnotlinkedtostripe is
632
     * set)
633
     *
634
     * @param \Stripe\Customer   $cu                        Object stripe customer.
635
     * @param CompanyPaymentMode $object                    Object companypaymentmode to check, or create on stripe
636
     *                                                      (create on stripe also update the societe_rib table for
637
     *                                                      current entity)
638
     * @param string             $stripeacc                 ''=Use common API. If not '', it is the Stripe connect
639
     *                                                      account 'acc_....' to use Stripe connect
640
     * @param int                $status                    Status (0=test, 1=live)
641
     * @param int                $createifnotlinkedtostripe 1=Create the stripe sepa and the link if the sepa is not
642
     *                                                      yet linked to a stripe sepa. Used by the "Create bank to
643
     *                                                      Stripe" feature.
644
     *
645
     * @return  \Stripe\PaymentMethod|null                              Stripe SEPA or null if not found
646
     */
647
    public function sepaStripe($cu, CompanyPaymentMode $object, $stripeacc = '', $status = 0, $createifnotlinkedtostripe = 0)
648
    {
649
        global $conf;
650
        $sepa = null;
651
652
        $sql = "SELECT sa.stripe_card_ref, sa.proprio, sa.iban_prefix as iban, sa.rum"; // stripe_card_ref is 'src_...' for Stripe SEPA
653
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_rib as sa";
654
        $sql .= " WHERE sa.rowid = " . ((int) $object->id); // We get record from ID, no need for filter on entity
655
        $sql .= " AND sa.type = 'ban'"; //type ban to get normal bank account of customer (prelevement)
656
657
        $soc = new Company($this->db);
658
        $soc->fetch($object->fk_soc);
659
660
        dol_syslog(get_class($this) . "::sepaStripe search stripe ban id for paymentmode id=" . $object->id . ", stripeacc=" . $stripeacc . ", status=" . $status . ", createifnotlinkedtostripe=" . $createifnotlinkedtostripe, LOG_DEBUG);
661
        $resql = $this->db->query($sql);
662
        if ($resql) {
663
            $num = $this->db->num_rows($resql);
664
            if ($num) {
665
                $obj = $this->db->fetch_object($resql);
666
                $cardref = $obj->stripe_card_ref;
667
                dol_syslog(get_class($this) . "::sepaStripe paymentmode=" . $cardref);
668
                if ($cardref) {
669
                    try {
670
                        if (empty($stripeacc)) {                // If the Stripe connect account not set, we use common API usage
671
                            if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
672
                                $sepa = $cu->sources->retrieve($cardref);
673
                            } else {
674
                                $sepa = \Stripe\PaymentMethod::retrieve($cardref);
675
                            }
676
                        } else {
677
                            if (!preg_match('/^pm_/', $cardref) && !empty($cu->sources)) {
678
                                //$sepa = $cu->sources->retrieve($cardref, array("stripe_account" => $stripeacc));      // this API fails when array stripe_account is provided
679
                                $sepa = $cu->sources->retrieve($cardref);
680
                            } else {
681
                                //$sepa = \Stripe\PaymentMethod::retrieve($cardref, array("stripe_account" => $stripeacc));     // Don't know if this works
682
                                $sepa = \Stripe\PaymentMethod::retrieve($cardref);
683
                            }
684
                        }
685
                    } catch (Exception $e) {
686
                        $this->error = $e->getMessage();
687
                        dol_syslog($this->error, LOG_WARNING);
688
                    }
689
                } elseif ($createifnotlinkedtostripe) {
690
                    $iban = $obj->iban;
691
                    $ipaddress = getUserRemoteIP();
692
                    $metadata = ['dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress];
693
                    if (is_object($object)) {
694
                        $metadata['dol_type'] = $object->element;
695
                        $metadata['dol_id'] = $object->id;
696
                        $metadata['dol_thirdparty_id'] = $soc->id;
697
                    }
698
699
                    $description = 'SEPA for IBAN ' . $iban;
700
701
                    $dataforcard = [
702
                        'type' => 'sepa_debit',
703
                        "sepa_debit" => ['iban' => $iban],
704
                        'billing_details' => [
705
                            'name' => $soc->name,
706
                            'email' => !empty($soc->email) ? $soc->email : "",
707
                        ],
708
                        "metadata" => $metadata,
709
                    ];
710
                    // Complete owner name
711
                    if (!empty($soc->town)) {
712
                        $dataforcard['billing_details']['address']['city'] = $soc->town;
713
                    }
714
                    if (!empty($soc->country_code)) {
715
                        $dataforcard['billing_details']['address']['country'] = $soc->country_code;
716
                    }
717
                    if (!empty($soc->address)) {
718
                        $dataforcard['billing_details']['address']['line1'] = $soc->address;
719
                    }
720
                    if (!empty($soc->zip)) {
721
                        $dataforcard['billing_details']['address']['postal_code'] = $soc->zip;
722
                    }
723
                    if (!empty($soc->state)) {
724
                        $dataforcard['billing_details']['address']['state'] = $soc->state;
725
                    }
726
727
                    //$a = \Stripe\Stripe::getApiKey();
728
                    //var_dump($a);var_dump($stripeacc);exit;
729
                    try {
730
                        dol_syslog("Try to create sepa_debit");
731
732
                        $service = 'StripeTest';
733
                        $servicestatus = 0;
734
                        if (getDolGlobalString('STRIPE_LIVE') && !GETPOST('forcesandbox', 'alpha')) {
735
                            $service = 'StripeLive';
736
                            $servicestatus = 1;
737
                        }
738
                        // Force to use the correct API key
739
                        global $stripearrayofkeysbyenv;
740
                        $stripeacc = $stripearrayofkeysbyenv[$servicestatus]['secret_key'];
741
742
                        dol_syslog("Try to create sepa_debit with data = " . json_encode($dataforcard));
743
744
                        $s = new \Stripe\StripeClient($stripeacc);
745
746
                        //var_dump($dataforcard);exit;
747
748
                        $sepa = $s->paymentMethods->create($dataforcard);
749
                        if (!$sepa) {
750
                            $this->error = 'Creation of payment method sepa_debit on Stripe has failed';
751
                        } else {
752
                            // link customer and src
753
                            //$cs = $this->getSetupIntent($description, $soc, $cu, '', $status);
754
                            $dataforintent = [0 => ['description' => $description, 'payment_method_types' => ['sepa_debit'], 'customer' => $cu->id, 'payment_method' => $sepa->id], 'metadata' => $metadata];
755
756
                            $cs = $s->setupIntents->create($dataforintent);
757
                            //$cs = $s->setupIntents->update($cs->id, ['payment_method' => $sepa->id]);
758
                            $cs = $s->setupIntents->confirm($cs->id, ['mandate_data' => ['customer_acceptance' => ['type' => 'offline']]]);
759
                            // note: $cs->mandate contains ID of mandate on Stripe side
760
761
                            if (!$cs) {
762
                                $this->error = 'Link SEPA <-> Customer failed';
763
                            } else {
764
                                dol_syslog("Update the payment mode of the customer");
765
766
                                // print json_encode($sepa);
767
768
                                // Save the Stripe payment mode ID into the Dolibarr database
769
                                $sql = "UPDATE " . MAIN_DB_PREFIX . "societe_rib";
770
                                $sql .= " SET stripe_card_ref = '" . $this->db->escape($sepa->id) . "',";
771
                                $sql .= " card_type = 'sepa_debit',";
772
                                $sql .= " stripe_account= '" . $this->db->escape($cu->id . "@" . $stripeacc) . "',";
773
                                $sql .= " ext_payment_site = '" . $this->db->escape($service) . "'";
774
                                if (!empty($cs->mandate)) {
775
                                    $mandateservice = new \Stripe\Mandate($stripeacc);
776
                                    $mandate = $mandateservice->retrieve($cs->mandate);
777
                                    if (is_object($mandate) && is_object($mandate->payment_method_details) && is_object($mandate->payment_method_details->sepa_debit)) {
778
                                        $refmandate = $mandate->payment_method_details->sepa_debit->reference;
779
                                        //$urlmandate = $mandate->payment_method_details->sepa_debit->url;
780
                                        $sql .= ", rum = '" . $this->db->escape($refmandate) . "'";
781
                                    }
782
                                    $sql .= ", comment = '" . $this->db->escape($cs->mandate) . "'";
783
                                    $sql .= ", date_rum = '" . $this->db->idate(dol_now()) . "'";
784
                                }
785
                                $sql .= " WHERE rowid = " . ((int) $object->id);
786
                                $sql .= " AND type = 'ban'";
787
                                $resql = $this->db->query($sql);
788
                                if (!$resql) {
789
                                    $this->error = $this->db->lasterror();
790
                                }
791
                            }
792
                        }
793
                    } catch (Exception $e) {
794
                        $sepa = null;
795
                        $this->error = 'Stripe error: ' . $e->getMessage() . '. Check the BAN information.';
796
                        dol_syslog($this->error, LOG_WARNING);  // Error from Stripe, so a warning on Dolibarr
797
                    }
798
                }
799
            }
800
        } else {
801
            dol_print_error($this->db);
802
        }
803
804
        return $sepa;
805
    }
806
807
    /**
808
     * Create charge.
809
     * This is called by page htdocs/stripe/payment.php and may be deprecated.
810
     *
811
     * @param int     $amount                            Amount to pay
812
     * @param string  $currency                          EUR, GPB...
813
     * @param string  $origin                            Object type to pay (order, invoice, contract...)
814
     * @param int     $item                              Object id to pay
815
     * @param string  $source                            src_xxxxx or card_xxxxx or pm_xxxxx
816
     * @param string  $customer                          Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
817
     * @param string  $account                           Stripe account ref 'acc_xxxxxxxxxxxxx' via  getStripeAccount()
818
     * @param int     $status                            Status (0=test, 1=live)
819
     * @param int     $usethirdpartyemailforreceiptemail Use thirdparty email as receipt email
820
     * @param boolean $capture                           Set capture flag to true (take payment) or false (wait)
821
     *
822
     * @return Stripe
823
     */
824
    public function createPaymentStripe($amount, $currency, $origin, $item, $source, $customer, $account, $status = 0, $usethirdpartyemailforreceiptemail = 0, $capture = true)
825
    {
826
        global $conf;
827
828
        $error = 0;
829
830
        if (empty($status)) {
831
            $service = 'StripeTest';
832
        } else {
833
            $service = 'StripeLive';
834
        }
835
836
        $sql = "SELECT sa.key_account as key_account, sa.fk_soc, sa.entity";
837
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_account as sa";
838
        $sql .= " WHERE sa.key_account = '" . $this->db->escape($customer) . "'";
839
        //$sql.= " AND sa.entity IN (".getEntity('societe').")";
840
        $sql .= " AND sa.site = 'stripe' AND sa.status = " . ((int) $status);
841
842
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
843
        $result = $this->db->query($sql);
844
        if ($result) {
845
            if ($this->db->num_rows($result)) {
846
                $obj = $this->db->fetch_object($result);
847
                $key = $obj->fk_soc;
848
            } else {
849
                $key = null;
850
            }
851
        } else {
852
            $key = null;
853
        }
854
855
        $arrayzerounitcurrency = ['BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'];
856
        if (!in_array($currency, $arrayzerounitcurrency)) {
857
            $stripeamount = $amount * 100;
858
        } else {
859
            $stripeamount = $amount;
860
        }
861
862
        $societe = new Company($this->db);
863
        if ($key > 0) {
864
            $societe->fetch($key);
865
        }
866
867
        $description = "";
868
        $ref = "";
869
        if ($origin == 'order') {
870
            $order = new Commande($this->db);
871
            $order->fetch($item);
872
            $ref = $order->ref;
873
            $description = "ORD=" . $ref . ".CUS=" . $societe->id . ".PM=stripe";
874
        } elseif ($origin == 'invoice') {
875
            $invoice = new Facture($this->db);
876
            $invoice->fetch($item);
877
            $ref = $invoice->ref;
878
            $description = "INV=" . $ref . ".CUS=" . $societe->id . ".PM=stripe";
879
        }
880
881
        $ipaddress = getUserRemoteIP();
882
883
        $metadata = [
884
            "dol_id" => (string) $item,
885
            "dol_type" => (string) $origin,
886
            "dol_thirdparty_id" => (string) $societe->id,
887
            'dol_thirdparty_name' => $societe->name,
888
            'dol_version' => DOL_VERSION,
889
            'dol_entity' => $conf->entity,
890
            'ipaddress' => $ipaddress,
891
        ];
892
        $return = new Stripe($this->db);
893
        try {
894
            // Force to use the correct API key
895
            global $stripearrayofkeysbyenv;
896
            \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
897
898
            if (empty($conf->stripeconnect->enabled)) { // With a common Stripe account
899
                if (preg_match('/pm_/i', $source)) {
900
                    $stripecard = $source;
901
                    $amountstripe = $stripeamount;
902
                    $FULLTAG = 'PFBO'; // Payment From Back Office
903
                    $stripe = $return;
904
                    $amounttopay = $amount;
905
                    $servicestatus = $status;
906
907
                    dol_syslog("* createPaymentStripe get stripeacc", LOG_DEBUG);
908
                    $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account if it exists (no network access here)
909
910
                    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...
911
912
                    // Create payment intent and charge payment (confirmnow = true)
913
                    $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1);
914
915
                    $charge = new stdClass();
0 ignored issues
show
Bug introduced by
The type DoliModules\Stripe\Model\stdClass was not found. Did you mean stdClass? If so, make sure to prefix the type with \.
Loading history...
916
                    if ($paymentintent->status == 'succeeded') {
917
                        $charge->status = 'ok';
918
                    } else {
919
                        $charge->status = 'failed';
920
                        $charge->failure_code = $stripe->code;
921
                        $charge->failure_message = $stripe->error;
922
                        $charge->failure_declinecode = $stripe->declinecode;
923
                        $stripefailurecode = $stripe->code;
924
                        $stripefailuremessage = $stripe->error;
925
                        $stripefailuredeclinecode = $stripe->declinecode;
926
                    }
927
                } elseif (preg_match('/acct_/i', $source)) {
928
                    $charge = \Stripe\Charge::create([
929
                        "amount" => "$stripeamount",
930
                        "currency" => "$currency",
931
                        "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
932
                        "description" => "Stripe payment: " . $description,
933
                        "capture" => $capture,
934
                        "metadata" => $metadata,
935
                        "source" => "$source",
936
                    ]);
937
                } else {
938
                    $paymentarray = [
939
                        "amount" => "$stripeamount",
940
                        "currency" => "$currency",
941
                        "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
942
                        "description" => "Stripe payment: " . $description,
943
                        "capture" => $capture,
944
                        "metadata" => $metadata,
945
                        "source" => "$source",
946
                        "customer" => "$customer",
947
                    ];
948
949
                    if ($societe->email && $usethirdpartyemailforreceiptemail) {
950
                        $paymentarray["receipt_email"] = $societe->email;
951
                    }
952
953
                    $charge = \Stripe\Charge::create($paymentarray, ["idempotency_key" => "$description"]);
954
                }
955
            } else {
956
                // With Stripe Connect
957
                $fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE;
958
                if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
959
                    $fee = getDolGlobalString('STRIPE_APPLICATION_FEE_MAXIMAL');
960
                } elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
961
                    $fee = getDolGlobalString('STRIPE_APPLICATION_FEE_MINIMAL');
962
                }
963
964
                if (!in_array($currency, $arrayzerounitcurrency)) {
965
                    $stripefee = round($fee * 100);
966
                } else {
967
                    $stripefee = round($fee);
968
                }
969
970
                $paymentarray = [
971
                    "amount" => "$stripeamount",
972
                    "currency" => "$currency",
973
                    "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
974
                    "description" => "Stripe payment: " . $description,
975
                    "capture" => $capture,
976
                    "metadata" => $metadata,
977
                    "source" => "$source",
978
                    "customer" => "$customer",
979
                ];
980
                if ($conf->entity != $conf->global->STRIPECONNECT_PRINCIPAL && $stripefee > 0) {
981
                    $paymentarray["application_fee_amount"] = $stripefee;
982
                }
983
                if ($societe->email && $usethirdpartyemailforreceiptemail) {
984
                    $paymentarray["receipt_email"] = $societe->email;
985
                }
986
987
                if (preg_match('/pm_/i', $source)) {
988
                    $stripecard = $source;
989
                    $amountstripe = $stripeamount;
990
                    $FULLTAG = 'PFBO'; // Payment From Back Office
991
                    $stripe = $return;
992
                    $amounttopay = $amount;
993
                    $servicestatus = $status;
994
995
                    dol_syslog("* createPaymentStripe get stripeacc", LOG_DEBUG);
996
                    $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account if it exists (no network access here)
997
998
                    dol_syslog("* createPaymentStripe Create payment on card " . $stripecard->id . ", amounttopay=" . $amounttopay . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG);
999
1000
                    // Create payment intent and charge payment (confirmnow = true)
1001
                    $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1);
1002
1003
                    $charge = new stdClass();
1004
                    if ($paymentintent->status == 'succeeded') {
1005
                        $charge->status = 'ok';
1006
                        $charge->id = $paymentintent->id;
1007
                    } else {
1008
                        $charge->status = 'failed';
1009
                        $charge->failure_code = $stripe->code;
1010
                        $charge->failure_message = $stripe->error;
1011
                        $charge->failure_declinecode = $stripe->declinecode;
1012
                    }
1013
                } else {
1014
                    $charge = \Stripe\Charge::create($paymentarray, ["idempotency_key" => "$description", "stripe_account" => "$account"]);
1015
                }
1016
            }
1017
            if (isset($charge->id)) {
1018
            }
1019
1020
            $return->statut = 'success';
1021
            $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...
1022
1023
            if (preg_match('/pm_/i', $source)) {
1024
                $return->message = 'Payment retrieved by card status = ' . $charge->status;
1025
            } else {
1026
                if ($charge->source->type == 'card') {
1027
                    $return->message = $charge->source->card->brand . " ...." . $charge->source->card->last4;
1028
                } elseif ($charge->source->type == 'three_d_secure') {
1029
                    $stripe = new Stripe($this->db);
1030
                    $src = \Stripe\Source::retrieve("" . $charge->source->three_d_secure->card, [
1031
                        "stripe_account" => $stripe->getStripeAccount($service),
1032
                    ]);
1033
                    $return->message = $src->card->brand . " ...." . $src->card->last4;
1034
                } else {
1035
                    $return->message = $charge->id;
1036
                }
1037
            }
1038
        } catch (\Stripe\Exception\CardException $e) {
1039
            include DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php';
1040
            // Since it's a decline, \Stripe\Exception\Card will be caught
1041
            $body = $e->getJsonBody();
1042
            $err = $body['error'];
1043
1044
            $return->statut = 'error';
1045
            $return->id = $err['charge'];
1046
            $return->type = $err['type'];
1047
            $return->code = $err['code'];
1048
            $return->message = $err['message'];
1049
            $body = "Error: <br>" . $return->id . " " . $return->message . " ";
1050
            $subject = '[Alert] Payment error using Stripe';
1051
            $cmailfile = new CMailFile($subject, $conf->global->ONLINE_PAYMENT_SENDEMAIL, $conf->global->MAIN_INFO_SOCIETE_MAIL, $body);
0 ignored issues
show
Bug introduced by
The type DoliModules\Stripe\Model\CMailFile was not found. Did you mean CMailFile? If so, make sure to prefix the type with \.
Loading history...
1052
            $cmailfile->sendfile();
1053
1054
            $error++;
1055
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1056
        } catch (\Stripe\Exception\RateLimitException $e) {
1057
            // Too many requests made to the API too quickly
1058
            $error++;
1059
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1060
        } catch (\Stripe\Exception\InvalidRequestException $e) {
1061
            // Invalid parameters were supplied to Stripe's API
1062
            $error++;
1063
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1064
        } catch (\Stripe\Exception\AuthenticationException $e) {
1065
            // Authentication with Stripe's API failed
1066
            // (maybe you changed API keys recently)
1067
            $error++;
1068
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1069
        } catch (\Stripe\Exception\ApiConnectionException $e) {
1070
            // Network communication with Stripe failed
1071
            $error++;
1072
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1073
        } catch (\Stripe\Exception\ExceptionInterface $e) {
1074
            // Display a very generic error to the user, and maybe send
1075
            // yourself an email
1076
            $error++;
1077
            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

1077
            dol_syslog($e->/** @scrutinizer ignore-call */ getMessage(), LOG_WARNING, 0, '_stripe');
Loading history...
1078
        } catch (Exception $e) {
1079
            // Something else happened, completely unrelated to Stripe
1080
            $error++;
1081
            dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe');
1082
        }
1083
        return $return;
1084
    }
1085
1086
    /**
1087
     * Return main company OAuth Connect stripe account
1088
     *
1089
     * @param string $mode   'StripeTest' or 'StripeLive'
1090
     * @param int    $fk_soc Id of thirdparty
1091
     * @param int    $entity Id of entity (-1 = current environment)
1092
     *
1093
     * @return  string              Stripe account 'acc_....' or '' if no OAuth token found
1094
     */
1095
    public function getStripeAccount($mode = 'StripeTest', $fk_soc = 0, $entity = -1)
1096
    {
1097
        global $conf;
1098
1099
        $key = '';
1100
        if ($entity < 0) {
1101
            $entity = $conf->entity;
1102
        }
1103
1104
        $sql = "SELECT tokenstring";
1105
        $sql .= " FROM " . MAIN_DB_PREFIX . "oauth_token";
1106
        $sql .= " WHERE service = '" . $this->db->escape($mode) . "'";
1107
        $sql .= " AND entity = " . ((int) $entity);
1108
        if ($fk_soc > 0) {
1109
            $sql .= " AND fk_soc = " . ((int) $fk_soc);
1110
        } else {
1111
            $sql .= " AND fk_soc IS NULL";
1112
        }
1113
        $sql .= " AND fk_user IS NULL AND fk_adherent IS NULL";
1114
1115
        dol_syslog(get_class($this) . "::getStripeAccount", LOG_DEBUG);
1116
1117
        $result = $this->db->query($sql);
1118
        if ($result) {
1119
            if ($this->db->num_rows($result)) {
1120
                $obj = $this->db->fetch_object($result);
1121
                $tokenstring = $obj->tokenstring;
1122
1123
                if ($tokenstring) {
1124
                    $tmparray = json_decode($tokenstring);
1125
                    $key = empty($tmparray->stripe_user_id) ? '' : $tmparray->stripe_user_id;
1126
                }
1127
            } else {
1128
                $tokenstring = '';
1129
            }
1130
        } else {
1131
            dol_print_error($this->db);
1132
        }
1133
1134
        dol_syslog("No dedicated Stripe Connect account available for entity " . $conf->entity);
1135
1136
        return $key;
1137
    }
1138
1139
    /**
1140
     * Get the Stripe payment intent. Create it with confirmnow=false
1141
     * Warning. If a payment was tried and failed, a payment intent was created.
1142
     * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed by
1143
     * Stripe. Recommended solution is to recreate a new payment intent each time we need one (old one will be
1144
     * automatically closed after a delay), that's why i comment the part of code to retrieve a payment intent with
1145
     * object id (never mind if we cumulate payment intent with old ones that will not be used) Note: This is used when
1146
     * option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is on when making a payment from the
1147
     * public/payment/newpayment.php page but not when using the STRIPE_USE_NEW_CHECKOUT.
1148
     *
1149
     * @param double  $amount                            Amount
1150
     * @param string  $currency_code                     Currency code
1151
     * @param string  $tag                               Tag
1152
     * @param string  $description                       Description
1153
     * @param mixed   $object                            Object to pay with Stripe
1154
     * @param string  $customer                          Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe()
1155
     * @param string  $key                               ''=Use common API. If not '', it is the Stripe connect account
1156
     *                                                   'acc_....' to use Stripe connect
1157
     * @param int     $status                            Status (0=test, 1=live)
1158
     * @param int     $usethirdpartyemailforreceiptemail 1=use thirdparty email for receipt
1159
     * @param string  $mode                              automatic=automatic confirmation/payment when conditions are
1160
     *                                                   ok, manual=need to call confirm() on intent
1161
     * @param boolean $confirmnow                        false=default, true=try to confirm immediately after create
1162
     *                                                   (if conditions are ok)
1163
     * @param string  $payment_method                    'pm_....' (if known)
1164
     * @param int     $off_session                       If we use an already known payment method to pay when customer
1165
     *                                                   is not available during the checkout flow.
1166
     * @param int     $noidempotency_key                 Do not use the idempotency_key when creating the PaymentIntent
1167
     * @param int     $did                               ID of an existing line into llx_prelevement_demande (Dolibarr
1168
     *                                                   intent). If provided, no new line will be created.
1169
     *
1170
     * @return  \Stripe\PaymentIntent|null                  Stripe PaymentIntent or null if not found and failed to
1171
     *                                                      create
1172
     */
1173
    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)
1174
    {
1175
        global $conf, $user;
1176
1177
        dol_syslog(get_class($this) . "::getPaymentIntent", LOG_INFO, 1);
1178
1179
        $error = 0;
1180
1181
        if (empty($status)) {
1182
            $service = 'StripeTest';
1183
        } else {
1184
            $service = 'StripeLive';
1185
        }
1186
1187
        $arrayzerounitcurrency = ['BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'];
1188
        if (!in_array($currency_code, $arrayzerounitcurrency)) {
1189
            $stripeamount = $amount * 100;
1190
        } else {
1191
            $stripeamount = $amount;
1192
        }
1193
1194
        $fee = 0;
1195
        if (getDolGlobalString("STRIPE_APPLICATION_FEE_PERCENT")) {
1196
            $fee = $amount * ((float) getDolGlobalString("STRIPE_APPLICATION_FEE_PERCENT", '0') / 100) + (float) getDolGlobalString("STRIPE_APPLICATION_FEE", '0');
1197
        }
1198
        if ($fee >= (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0') && (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0') > (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0')) {
1199
            $fee = (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0');
1200
        } elseif ($fee < (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0')) {
1201
            $fee = (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0');
1202
        }
1203
        if (!in_array($currency_code, $arrayzerounitcurrency)) {
1204
            $stripefee = round($fee * 100);
1205
        } else {
1206
            $stripefee = round($fee);
1207
        }
1208
1209
        $paymentintent = null;
1210
1211
        if (is_object($object) && getDolGlobalInt('STRIPE_REUSE_EXISTING_INTENT_IF_FOUND') && !getDolGlobalInt('STRIPE_CARD_PRESENT')) {
1212
            // Warning. If a payment was tried and failed, a payment intent was created.
1213
            // 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.
1214
            // 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
1215
            // automatically return the existing payment intent if idempotency is provided when we try to create the new one.
1216
            // 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)
1217
1218
            $sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site";
1219
            $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_demande as pi";
1220
            $sql .= " WHERE pi.fk_facture = " . ((int) $object->id);
1221
            $sql .= " AND pi.sourcetype = '" . $this->db->escape($object->element) . "'";
1222
            $sql .= " AND pi.entity IN (" . getEntity('societe') . ")";
1223
            $sql .= " AND pi.ext_payment_site = '" . $this->db->escape($service) . "'";
1224
1225
            dol_syslog(get_class($this) . "::getPaymentIntent search stripe payment intent for object id = " . $object->id, LOG_DEBUG);
1226
            $resql = $this->db->query($sql);
1227
            if ($resql) {
1228
                $num = $this->db->num_rows($resql);
1229
                if ($num) {
1230
                    $obj = $this->db->fetch_object($resql);
1231
                    $intent = $obj->ext_payment_id;
1232
1233
                    dol_syslog(get_class($this) . "::getPaymentIntent found existing payment intent record");
1234
1235
                    // Force to use the correct API key
1236
                    global $stripearrayofkeysbyenv;
1237
                    \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
1238
1239
                    try {
1240
                        if (empty($key)) {              // If the Stripe connect account not set, we use common API usage
1241
                            $paymentintent = \Stripe\PaymentIntent::retrieve($intent);
1242
                        } else {
1243
                            $paymentintent = \Stripe\PaymentIntent::retrieve($intent, ["stripe_account" => $key]);
1244
                        }
1245
                    } catch (Exception $e) {
1246
                        $error++;
1247
                        $this->error = $e->getMessage();
1248
                    }
1249
                }
1250
            }
1251
        }
1252
1253
        if (empty($paymentintent)) {
1254
            // Try to create intent. See https://stripe.com/docs/api/payment_intents/create
1255
            $ipaddress = getUserRemoteIP();
1256
            $metadata = ['dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress];
1257
            if (is_object($object)) {
1258
                $metadata['dol_type'] = $object->element;
1259
                $metadata['dol_id'] = $object->id;
1260
                if (is_object($object->thirdparty) && $object->thirdparty->id > 0) {
1261
                    $metadata['dol_thirdparty_id'] = $object->thirdparty->id;
1262
                }
1263
            }
1264
1265
            // list of payment method types
1266
            $paymentmethodtypes = ["card"];
1267
            $descriptor = dol_trunc($tag, 10, 'right', 'UTF-8', 1);
1268
            if (getDolGlobalInt('STRIPE_SEPA_DIRECT_DEBIT')) {
1269
                $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
1270
                //$descriptor = preg_replace('/ref=[^:=]+/', '', $descriptor);  // Clean ref
1271
            }
1272
            if (getDolGlobalInt('STRIPE_KLARNA')) {
1273
                $paymentmethodtypes[] = "klarna";
1274
            }
1275
            if (getDolGlobalInt('STRIPE_BANCONTACT')) {
1276
                $paymentmethodtypes[] = "bancontact";
1277
            }
1278
            if (getDolGlobalInt('STRIPE_IDEAL')) {
1279
                $paymentmethodtypes[] = "ideal";
1280
            }
1281
            if (getDolGlobalInt('STRIPE_GIROPAY')) {
1282
                $paymentmethodtypes[] = "giropay";
1283
            }
1284
            if (getDolGlobalInt('STRIPE_SOFORT')) {
1285
                $paymentmethodtypes[] = "sofort";
1286
            }
1287
            if (getDolGlobalInt('STRIPE_CARD_PRESENT') && $mode == 'terminal') {
1288
                $paymentmethodtypes = ["card_present"];
1289
            }
1290
1291
            global $dolibarr_main_url_root;
1292
1293
            $dataforintent = [
1294
                "confirm" => $confirmnow, // try to confirm immediately after create (if conditions are ok)
1295
                "confirmation_method" => $mode,
1296
                "amount" => $stripeamount,
1297
                "currency" => $currency_code,
1298
                "payment_method_types" => $paymentmethodtypes,  // When payment_method_types is set, return_url is not required but payment mode can't be managed from dashboard
1299
                /*
1300
                'return_url' => $dolibarr_main_url_root.'/public/payment/paymentok.php',
1301
                'automatic_payment_methods' => array(
1302
                    'enabled' => true,
1303
                    'allow_redirects' => 'never',
1304
                ),
1305
                */
1306
                "description" => $description,
1307
                //"save_payment_method" => true,
1308
                "setup_future_usage" => "on_session",
1309
                "metadata" => $metadata,
1310
            ];
1311
            if ($descriptor) {
1312
                $dataforintent["statement_descriptor_suffix"] = $descriptor; // For card payment, 22 chars that appears on bank receipt (prefix into stripe setup + this suffix)
1313
                $dataforintent["statement_descriptor"] = $descriptor;   // For SEPA, it will take only statement_descriptor, not statement_descriptor_suffix
1314
            }
1315
            if (!is_null($customer)) {
1316
                $dataforintent["customer"] = $customer;
1317
            }
1318
            // payment_method =
1319
            // payment_method_types = array('card')
1320
            //var_dump($dataforintent);
1321
            if ($off_session) {
1322
                unset($dataforintent['setup_future_usage']);
1323
                // We can't use both "setup_future_usage" = "off_session" and "off_session" = true.
1324
                // Because $off_session parameter is dedicated to create paymentintent off_line (and not future payment), we need to use "off_session" = true.
1325
                //$dataforintent["setup_future_usage"] = "off_session";
1326
                $dataforintent["off_session"] = true;
1327
            }
1328
            if (getDolGlobalInt('STRIPE_GIROPAY')) {
1329
                unset($dataforintent['setup_future_usage']);
1330
            }
1331
            if (getDolGlobalInt('STRIPE_KLARNA')) {
1332
                unset($dataforintent['setup_future_usage']);
1333
            }
1334
            if (getDolGlobalInt('STRIPE_CARD_PRESENT') && $mode == 'terminal') {
1335
                unset($dataforintent['setup_future_usage']);
1336
                $dataforintent["capture_method"] = "manual";
1337
                $dataforintent["confirmation_method"] = "manual";
1338
            }
1339
            if (!is_null($payment_method)) {
1340
                $dataforintent["payment_method"] = $payment_method;
1341
                $description .= ' - ' . $payment_method;
1342
            }
1343
1344
            if ($conf->entity != getDolGlobalInt('STRIPECONNECT_PRINCIPAL') && $stripefee > 0) {
1345
                $dataforintent["application_fee_amount"] = $stripefee;
1346
            }
1347
            if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) {
1348
                $dataforintent["receipt_email"] = $object->thirdparty->email;
1349
            }
1350
1351
            try {
1352
                // Force to use the correct API key
1353
                global $stripearrayofkeysbyenv;
1354
                \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
1355
1356
                $arrayofoptions = [];
1357
                if (empty($noidempotency_key)) {
1358
                    $arrayofoptions["idempotency_key"] = $description;
1359
                }
1360
                // 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.
1361
                if (!empty($key)) {             // If the Stripe connect account not set, we use common API usage
1362
                    $arrayofoptions["stripe_account"] = $key;
1363
                }
1364
1365
                dol_syslog("dataforintent to create paymentintent = " . var_export($dataforintent, true));
1366
1367
                $paymentintent = \Stripe\PaymentIntent::create($dataforintent, $arrayofoptions);
1368
1369
                // Store the payment intent
1370
                if (is_object($object)) {
1371
                    $paymentintentalreadyexists = 0;
1372
1373
                    if ($did > 0) {
1374
                        // If a payment request line provided, we do not need to recreate one, we just update it
1375
                        dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
1376
1377
                        $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET";
1378
                        $sql .= " ext_payment_site = '" . $this->db->escape($service) . "',";
1379
                        $sql .= " ext_payment_id = '" . $this->db->escape($paymentintent->id) . "'";
1380
                        $sql .= " WHERE rowid = " . ((int) $did);
1381
1382
                        $resql = $this->db->query($sql);
1383
                        if ($resql) {
1384
                            $paymentintentalreadyexists++;
1385
                        } else {
1386
                            $error++;
1387
                            dol_print_error($this->db);
1388
                        }
1389
                    } else {
1390
                        // Check that payment intent $paymentintent->id is not already recorded.
1391
                        dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG);
1392
1393
                        $sql = "SELECT pi.rowid";
1394
                        $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_demande as pi";
1395
                        $sql .= " WHERE pi.entity IN (" . getEntity('societe') . ")";
1396
                        $sql .= " AND pi.ext_payment_site = '" . $this->db->escape($service) . "'";
1397
                        $sql .= " AND pi.ext_payment_id = '" . $this->db->escape($paymentintent->id) . "'";
1398
1399
                        $resql = $this->db->query($sql);
1400
                        if ($resql) {
1401
                            $num = $this->db->num_rows($resql);
1402
                            if ($num) {
1403
                                $obj = $this->db->fetch_object($resql);
1404
                                if ($obj) {
1405
                                    $paymentintentalreadyexists++;
1406
                                }
1407
                            }
1408
                        } else {
1409
                            $error++;
1410
                            dol_print_error($this->db);
1411
                        }
1412
                    }
1413
1414
                    // If not, we create it.
1415
                    if (!$error && !$paymentintentalreadyexists) {
1416
                        $now = dol_now();
1417
                        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site, amount)";
1418
                        $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) . ")";
1419
                        $resql = $this->db->query($sql);
1420
                        if (!$resql) {
1421
                            $error++;
1422
                            $this->error = $this->db->lasterror();
1423
                            dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=" . $paymentintent->id . " into database.", LOG_ERR);
1424
                        }
1425
                    }
1426
                } else {
1427
                    $_SESSION["stripe_payment_intent"] = $paymentintent;
1428
                }
1429
            } catch (Stripe\Exception\CardException $e) {
0 ignored issues
show
Bug introduced by
The type DoliModules\Stripe\Model...Exception\CardException was not found. Did you mean Stripe\Exception\CardException? If so, make sure to prefix the type with \.
Loading history...
1430
                $error++;
1431
                $this->error = $e->getMessage();
1432
                $this->code = $e->getStripeCode();
1433
                $this->declinecode = $e->getDeclineCode();
1434
            } catch (Exception $e) {
1435
                //var_dump($dataforintent);
1436
                //var_dump($description);
1437
                //var_dump($key);
1438
                //var_dump($paymentintent);
1439
                //var_dump($e->getMessage());
1440
                //var_dump($e);
1441
                $error++;
1442
                $this->error = $e->getMessage();
1443
                $this->code = '';
1444
                $this->declinecode = '';
1445
            }
1446
        }
1447
1448
        dol_syslog(get_class($this) . "::getPaymentIntent return error=" . $error . " this->error=" . $this->error, LOG_INFO, -1);
1449
1450
        if (!$error) {
1451
            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...
1452
        } else {
1453
            return null;
1454
        }
1455
    }
1456
}
1457