getCustomerPaymentMethodCreatedDate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
1
<?php
2
3
namespace Omnipay\Redsys\Message;
4
5
use DateTime;
6
use DateTimeZone;
7
use Omnipay\Common\Message\AbstractRequest;
8
use Omnipay\Common\Exception\InvalidRequestException;
9
10
/**
11
 * Redsys Purchase Request
12
 */
13
class PurchaseRequest extends AbstractRequest
14
{
15
    /** @var string */
16
    protected $liveEndpoint = 'https://sis.redsys.es/sis/realizarPago';
17
    /** @var string */
18
    protected $testEndpoint = 'https://sis-t.redsys.es:25443/sis/realizarPago';
19
    /** @var array */
20
    protected static $consumerLanguages = array(
21
        'es' => '001', // Spanish
22
        'en' => '002', // English
23
        'ca' => '003', // Catalan - same as Valencian (010)
24
        'fr' => '004', // French
25
        'de' => '005', // German
26
        'nl' => '006', // Dutch
27
        'it' => '007', // Italian
28
        'sv' => '008', // Swedish
29
        'pt' => '009', // Portuguese
30
        'pl' => '011', // Polish
31
        'gl' => '012', // Galician
32 2
        'eu' => '013', // Basque
33
    );
34 2
35
    /** @var string 250x400 */
36
    const CHALLENGE_WINDOW_SIZE_250_400 = "01";
37 4
    /** @var string 390x400 */
38
    const CHALLENGE_WINDOW_SIZE_390_400 = "02";
39 4
    /** @var string 500x600 */
40
    const CHALLENGE_WINDOW_SIZE_500_600 = "03";
41
    /** @var string 600x400 */
42 8
    const CHALLENGE_WINDOW_SIZE_600_400 = "04";
43
    /** @var string Fullscreen window (default) */
44 8
    const CHALLENGE_WINDOW_SIZE_FULLSCREEN = "05";
45
46
    /** @var string No 3DS Requestor authentication occurred (i.e. cardholder logged in as guest) */
47
    const ACCOUNT_AUTHENTICATION_METHOD_NONE = "01";
48
    /** @var string Login to the cardholder account at the 3DS Requestor system using 3DS Requestor's own credentials */
49
    const ACCOUNT_AUTHENTICATION_METHOD_OWN_CREDENTIALS = "02";
50
    /** @var string Login to the cardholder account at the 3DS Requestor system using federated ID */
51
    const ACCOUNT_AUTHENTICATION_METHOD_FEDERATED_ID = "03";
52 7
    /** @var string Login to the cardholder account at the 3DS Requestor system using issuer credentials */
53
    const ACCOUNT_AUTHENTICATION_METHOD_ISSUER_CREDENTIALS = "04";
54 7
    /** @var string Login to the cardholder account at the 3DS Requestor system using third-party authentication */
55 1
    const ACCOUNT_AUTHENTICATION_METHOD_THIRD_PARTY_AUTHENTICATION = "05";
56 1
    /** @var string Login to the cardholder account at the 3DS Requestor system using FIDO Authenticator */
57 1
    const ACCOUNT_AUTHENTICATION_METHOD_FIDO = "06";
58 1
59 7
    /** @var string No account (guest check-out) */
60 7
    const CUSTOMER_ACCOUNT_CREATED_NONE = "01";
61 7
    /** @var string Created during this transaction */
62
    const CUSTOMER_ACCOUNT_CREATED_THIS_TRANSACTION = "02";
63 7
    /** @var string Less than 30 days */
64
    const CUSTOMER_ACCOUNT_CREATED_LAST_30_DAYS = "03";
65
    /** @var string Between 30 and 60 days */
66 15
    const CUSTOMER_ACCOUNT_CREATED_LAST_60_DAYS = "04";
67
    /** @var string More than 60 day */
68 15
    const CUSTOMER_ACCOUNT_CREATED_MORE_THAN_60_DAYS = "05";
69
70
    /** @var string Modified in this session */
71 23
    const CUSTOMER_ACCOUNT_MODIFIED_THIS_TRANSACTION = "01";
72
    /** @var string Less than 30 days */
73 23
    const CUSTOMER_ACCOUNT_MODIFIED_LAST_30_DAYS = "02";
74
    /** @var string Between 30 and 60 days */
75
    const CUSTOMER_ACCOUNT_MODIFIED_LAST_60_DAYS = "03";
76 7
    /** @var string More than 60 day */
77
    const CUSTOMER_ACCOUNT_MODIFIED_MORE_THAN_60_DAYS = "04";
78 7
79
    /** @var string Unchanged */
80
    const CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_NONE = "01";
81 7
    /** @var string Modified in this session */
82
    const CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_THIS_TRANSACTION = "02";
83 7
    /** @var string Less than 30 days */
84
    const CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_LAST_30_DAYS = "03";
85
    /** @var string Between 30 and 60 days */
86 11
    const CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_LAST_60_DAYS = "04";
87
    /** @var string More than 60 day */
88 11
    const CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_MORE_THAN_60_DAYS = "05";
89
90
    /** @var string No account (guest check-out) */
91 23
    const PAYMENT_METHOD_CREATED_NONE = "01";
92
    /** @var string Created during this transaction */
93 23
    const PAYMENT_METHOD_CREATED_THIS_TRANSACTION = "02";
94
    /** @var string Less than 30 days */
95
    const PAYMENT_METHOD_CREATED_LAST_30_DAYS = "03";
96 11
    /** @var string Between 30 and 60 days */
97
    const PAYMENT_METHOD_CREATED_LAST_60_DAYS = "04";
98 11
    /** @var string More than 60 day */
99
    const PAYMENT_METHOD_CREATED_MORE_THAN_60_DAYS = "05";
100
101 23
    /** @var string For the first time */
102
    const SHIPPING_ADDRESS_USAGE_THIS_TRANSACTION = "01";
103 23
    /** @var string Less than 30 days */
104
    const SHIPPING_ADDRESS_USAGE_LAST_30_DAYS = "02";
105
    /** @var string Between 30 and 60 days */
106 11
    const SHIPPING_ADDRESS_USAGE_LAST_60_DAYS = "03";
107
    /** @var string More than 60 day */
108 11
    const SHIPPING_ADDRESS_USAGE_MORE_THAN_60_DAYS = "04";
109
110
    /** @var string Electronic delivery */
111 23
    const DELIVERY_TIMEFRAME_ELECTRONIC_DELIVERY = "01";
112
    /** @var string Same day shipping */
113 23
    const DELIVERY_TIMEFRAME_SAME_DAY = "02";
114
    /** @var string Next day shipping */
115
    const DELIVERY_TIMEFRAME_NEXT_DAY = "03";
116
    /** @var string Shipping in 2 or more days */
117
    const DELIVERY_TIMEFRAME_2_OR_MORE_DAYS = "04";
118
119
    /** @var string Ship to cardholder's billing address */
120
    const SHIPPING_TO_BILLING_ADDRESS = "01";
121 15
    /** @var string Ship to another verified address on file with merchant */
122
    const SHIPPING_TO_ANOTHER_VERIFIED_ADDRESS = "02";
123 15
    /** @var string Ship to address that is different than the cardholder's billing address */
124 15
    const SHIPPING_DIFFERENT_BILLING_ADDRESS = "03";
125 15
    /** @var string Pick-up at local store (Store address shall be populated in shipping address fields) */
126 15
    const SHIPPING_PICK_UP = "04";
127 15
    /** @var string Digital goods (includes online services, electronic gift cards and redemption codes) */
128 15
    const SHIPPING_DIGITAL = "05";
129 15
    /** @var string Travel and Event tickets, not shipped */
130
    const SHIPPING_TRAVEL = "06";
131 15
    /** @var string Other (for example, Gaming, digital services not shipped, emedia subscriptions, etc.) */
132 15
    const SHIPPING_OTHER = "07";
133
134 15
    /** @var string Exemption due to low amount (transactions up to € 30) */
135 15
    const SCA_EXEMPTION_LOW_AMOUNT = 'LMV';
136
    /** @var string Exemption due to low risk */
137 2
    const SCA_EXEMPTION_LOW_RISK = 'TRA';
138
    /** @var string Exemption for payments identified as corporate. */
139 2
    const SCA_EXEMPTION_CORPORATE = 'COR';
140
    /**
141
     * @var string Transactions initiated by the merchant, in which there is no intervention by the customer. They are
142
     *             outside the scope of PSD2.
143 2
     */
144 2
    const SCA_EXEMPTION_MERCHANT_INITIATED = 'MIT';
145 2
146 2
    public function getCardholder()
147 2
    {
148 2
        return $this->getParameter('cardholder');
149 2
    }
150
151 2
    public function setCardholder($value)
152 2
    {
153 2
        return $this->setParameter('cardholder', $value);
154 2
    }
155 2
156 2
    public function getConsumerLanguage()
157 2
    {
158 2
        return $this->getParameter('consumerLanguage');
159
    }
160
161 1
    /**
162
     * Set the language presented to the consumer
163 1
     *
164
     * @param null|string|int $value The ISO 639-1 code to be converted, or the gateway's own numeric language code
165 1
     */
166
    public function setConsumerLanguage($value)
167
    {
168 1
        if (is_int($value)) {
169 1
            if ($value < 0 || $value > 13) {
170 1
                $value = 1;
171 1
            }
172 1
            $value = str_pad($value, 3, '0', STR_PAD_LEFT);
173 1
        } elseif (!is_numeric($value)) {
174 1
            $value = self::$consumerLanguages[$value] ?? '001';
175 1
        }
176
177 1
        return $this->setParameter('consumerLanguage', $value);
178
    }
179
180 7
    public function getDirectPayment()
181
    {
182 7
        return $this->getParameter('directPayment');
183
    }
184
185 1
    /**
186
     * Set the "directness" of payment
187
     *
188
     * Can be true (merchant initiated), false/null (customer initiated) or "MOTO" (usually call centre initiated)
189
     * Invalid values will be converted to null as that's the most secure option
190
     *
191
     * @param null|bool|string $value
192
     */
193
    public function setDirectPayment($value)
194
    {
195
        if (is_bool($value)) {
196
            // this is fine
197
        } elseif (is_string($value)) {
198
            if (strtoupper($value) == "TRUE") {
199
                $value = true;
200
            } elseif (strtoupper($value) == "FALSE") {
201
                $value = false;
202
            } elseif (strtoupper($value) == "MOTO") {
203
                $value = "MOTO";
204
            } else {
205
                // something invalid
206
                $value = null;
207
            }
208
        } else {
209
            // something invalid
210
            $value = null;
211
        }
212
        return $this->setParameter('directPayment', $value);
213
    }
214
215
    public function getHmacKey()
216
    {
217
        return $this->getParameter('hmacKey');
218
    }
219
220
    public function setHmacKey($value)
221
    {
222
        return $this->setParameter('hmacKey', $value);
223
    }
224
225
    public function getMerchantData()
226
    {
227
        return $this->getParameter('merchantData');
228
    }
229
230
    public function setMerchantData($value)
231
    {
232
        return $this->setParameter('merchantData', $value);
233
    }
234
235
    public function getMerchantId()
236
    {
237
        return $this->getParameter('merchantId');
238
    }
239
240
    public function setMerchantId($value)
241
    {
242
        return $this->setParameter('merchantId', $value);
243
    }
244
245
    public function getMerchantName()
246
    {
247
        return $this->getParameter('merchantName');
248
    }
249
250
    public function setMerchantName($value)
251
    {
252
        return $this->setParameter('merchantName', $value);
253
    }
254
255
    public function getTerminalId()
256
    {
257
        return $this->getParameter('terminalId');
258
    }
259
260
    public function setTerminalId($value)
261
    {
262
        return $this->setParameter('terminalId', $value);
263
    }
264
265
    public function getCreateToken()
266
    {
267
        return $this->getParameter('createToken');
268
    }
269
270
    public function setCreateToken($value)
271
    {
272
        return $this->setParameter('createToken', $value);
273
    }
274
275
    /**
276
     * Get the protocolVersion field
277
     * Corresponds to the Ds_Merchant_Emv3Ds.protocolVersion. field in Redsys documentation.
278
     *
279
     * @return null|string
280
     *
281
     */
282
    public function getProtocolVersion()
283
    {
284
        return $this->getParameter('protocolVersion');
285
    }
286
287
    /**
288
     * Set the protocolVersion field
289
     *
290
     * Corresponds to the Ds_Merchant_Emv3Ds.protocolVersion field
291
     *
292
     * @param null|string $value
293
     * @return self
294
     */
295
    public function setProtocolVersion($value)
296
    {
297
        return $this->setParameter('protocolVersion', $value);
298
    }
299
300
    /**
301
     * Get the use3ds field
302
     *
303
     * Controls the presence of the Ds_Merchant_Emv3Ds structure
304
     *
305
     * @return bool
306
     */
307
    public function getUse3DS()
308
    {
309
        return (bool) $this->getParameter('use3ds');
310
    }
311
312
    /**
313
     * Set the use3ds field
314
     *
315
     * Controls the presence of the Ds_Merchant_Emv3Ds structure
316
     *
317
     * @param bool $value
318
     * @return self
319
     */
320
    public function setUse3DS($value)
321
    {
322
        return $this->setParameter('use3ds', $value);
323
    }
324
325
    /**
326
     * Get the threeDSCompInd field, which indicates whether the 3DSMethod has been executed
327
     *
328
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSCompInd field in Redsys documentation.
329
     *
330
     * @return null|string Y = Successfully completed, N = Completed with errors, U = 3DSMethod not executed
331
     */
332
    public function getThreeDSCompInd()
333
    {
334
        return $this->getParameter('threeDSCompInd');
335
    }
336
337
    /**
338
     * Set the threeDSCompInd field
339
     *
340
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSCompInd field
341
     *
342
     * @param null|string $value
343
     * @return self
344
     */
345
    public function setThreeDSCompInd($value)
346
    {
347
        return $this->setParameter('threeDSCompInd', $value);
348
    }
349
350
    /**
351
     * Get the threeDSInfo field (the type of request)
352
     *
353
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSInfo field in Redsys documentation.
354
     *
355
     * @return null|string Possible values: CardData, AuthenticationData, ChallengeResponse
356
     */
357
    public function getThreeDSInfo()
358
    {
359
        return $this->getParameter('threeDSInfo');
360
    }
361
362
    /**
363
     * Set the threeDSInfo field
364
     *
365
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSInfo field
366
     *
367
     * @param null|string $value
368
     * @return self
369
     */
370
    public function setThreeDSInfo($value)
371
    {
372
        return $this->setParameter('threeDSInfo', $value);
373
    }
374
375
    /**
376
     * Get the homePhoneCountryPrefix field
377
     *
378
     * Corresponds to the Ds_Merchant_Emv3Ds.homePhone.cc field
379
     *
380
     * @return null|string
381
     */
382
    public function getHomePhoneCountryPrefix()
383
    {
384
        return $this->getParameter('homePhoneCountryPrefix');
385
    }
386
387
    /**
388
     * Set the homePhoneCountryPrefix field
389
     *
390
     * Corresponds to the Ds_Merchant_Emv3Ds.homePhone.cc field
391
     *
392
     * @param null|string $value
393
     * @return self
394
     */
395
    public function setHomePhoneCountryPrefix($value)
396
    {
397
        return $this->setParameter('homePhoneCountryPrefix', $value);
398
    }
399
400
    /**
401
     * Get the homePhone field
402
     *
403
     * Corresponds to the Ds_Merchant_Emv3Ds.homePhone.subscriber field
404
     *
405
     * @return null|string
406
     */
407
    public function getHomePhone()
408
    {
409
        return $this->getParameter('homePhone');
410
    }
411
412
    /**
413
     * Set the homePhone field
414
     *
415
     * Corresponds to the Ds_Merchant_Emv3Ds.homePhone.subscriber field
416
     *
417
     * @param null|string $value
418
     * @return self
419
     */
420
    public function setHomePhone($value)
421
    {
422
        return $this->setParameter('homePhone', $value);
423
    }
424
425
    /**
426
     * Get the mobilePhoneCountryPrefix field
427
     *
428
     * Corresponds to the Ds_Merchant_Emv3Ds.mobilePhone.cc field
429
     *
430
     * @return null|string
431
     */
432
    public function getMobilePhoneCountryPrefix()
433
    {
434
        return $this->getParameter('mobilePhoneCountryPrefix');
435
    }
436
437
    /**
438
     * Set the mobilePhoneCountryPrefix field
439
     *
440
     * Corresponds to the Ds_Merchant_Emv3Ds.mobilePhone.cc field
441
     *
442
     * @param null|string $value
443
     * @return self
444
     */
445
    public function setMobilePhoneCountryPrefix($value)
446
    {
447
        return $this->setParameter('mobilePhoneCountryPrefix', $value);
448
    }
449
450
    /**
451
     * Get the mobilePhone field
452
     *
453
     * Corresponds to the Ds_Merchant_Emv3Ds.mobilePhone.subscriber field
454
     *
455
     * @return null|string
456
     */
457
    public function getMobilePhone()
458
    {
459
        return $this->getParameter('mobilePhone');
460
    }
461
462
    /**
463
     * Set the mobilePhone field
464
     *
465
     * Corresponds to the Ds_Merchant_Emv3Ds.mobilePhone.subscriber field
466
     *
467
     * @param null|string $value
468
     * @return self
469
     */
470
    public function setMobilePhone($value)
471
    {
472
        return $this->setParameter('mobilePhone', $value);
473
    }
474
475
    /**
476
     * Get the workPhoneCountryPrefix field
477
     *
478
     * Corresponds to the Ds_Merchant_Emv3Ds.workPhone.cc field
479
     *
480
     * @return null|string
481
     */
482
    public function getWorkPhoneCountryPrefix()
483
    {
484
        return $this->getParameter('workPhoneCountryPrefix');
485
    }
486
487
    /**
488
     * Set the workPhoneCountryPrefix field
489
     *
490
     * Corresponds to the Ds_Merchant_Emv3Ds.workPhone.cc field
491
     *
492
     * @param null|string $value
493
     * @return self
494
     */
495
    public function setWorkPhoneCountryPrefix($value)
496
    {
497
        return $this->setParameter('workPhoneCountryPrefix', $value);
498
    }
499
500
    /**
501
     * Get the workPhone field
502
     *
503
     * Corresponds to the Ds_Merchant_Emv3Ds.workPhone.subscriber field
504
     *
505
     * @return null|string
506
     */
507
    public function getWorkPhone()
508
    {
509
        return $this->getParameter('workPhone');
510
    }
511
512
    /**
513
     * Set the workPhone field
514
     *
515
     * Corresponds to the Ds_Merchant_Emv3Ds.workPhone.subscriber field
516
     *
517
     * @param null|string $value
518
     * @return self
519
     */
520
    public function setWorkPhone($value)
521
    {
522
        return $this->setParameter('workPhone', $value);
523
    }
524
525
    /**
526
     * Get the addressMatch field
527
     *
528
     * Corresponds to the Ds_Merchant_Emv3Ds.addrMatch field
529
     *
530
     * @return string  Either 'Y' or 'N'
531
     */
532
    public function getAddressMatch()
533
    {
534
        $match = $this->getParameter('addressMatch');
535
536
        if ($match === null) {
537
            $match = false;
538
            $card = $this->getCard();
539
            if ($card !== null) {
540
                $match = $card->getShippingAddress1() === $card->getBillingAddress1()
541
                    && $card->getShippingAddress2() === $card->getBillingAddress2()
542
                    && $card->getShippingAddress3() === $card->getBillingAddress3()
543
                    && $card->getShippingCity() === $card->getBillingCity()
544
                    && $card->getShippingPostcode() === $card->getBillingPostcode()
545
                    && $card->getShippingState() === $card->getBillingState()
546
                    && $card->getShippingCountry() === $card->getBillingCountry();
547
            }
548
        }
549
550
        return $match ? "Y" : "N";
551
    }
552
553
    /**
554
     * Set the addressMatch field
555
     *
556
     * Corresponds to the Ds_Merchant_Emv3Ds.addrMatch field
557
     *
558
     * @param null|boolean $value
559
     * @return self
560
     */
561
    public function setAddressMatch($value)
562
    {
563
        return $this->setParameter('addressMatch', $value);
564
    }
565
566
    /**
567
     * Get the challengeWindowSize field
568
     *
569
     * Corresponds to the Ds_Merchant_Emv3Ds.challengeWindowSize field
570
     *
571
     * @return null|string One of the self::CHALLENGE_WINDOW_SIZE_* constants
572
     */
573
    public function getChallengeWindowSize()
574
    {
575
        return $this->getParameter('challengeWindowSize');
576
    }
577
578
    /**
579
     * Set the challengeWindowSize field
580
     *
581
     * Corresponds to the Ds_Merchant_Emv3Ds.challengeWindowSize field
582
     *
583
     * @param null|string $value One of the self::CHALLENGE_WINDOW_SIZE_* constants
584
     * @return self
585
     * @throws InvalidRequestException if $value is invalid.
586
     */
587
    public function setChallengeWindowSize($value)
588
    {
589
        if (in_array(
590
            $value,
591
            [
592
                null,
593
                self::CHALLENGE_WINDOW_SIZE_250_400,
594
                self::CHALLENGE_WINDOW_SIZE_390_400,
595
                self::CHALLENGE_WINDOW_SIZE_500_600,
596
                self::CHALLENGE_WINDOW_SIZE_600_400,
597
                self::CHALLENGE_WINDOW_SIZE_FULLSCREEN,
598
            ]
599
        )) {
600
            return $this->setParameter('challengeWindowSize', $value);
601
        }
602
        throw new InvalidRequestException("Invalid challengeWindowSize parameter");
603
    }
604
605
    /**
606
     * Get the customerAdditionalInformation field
607
     *
608
     * Corresponds to the Ds_Merchant_Emv3Ds.acctID field
609
     *
610
     * @return null|string
611
     */
612
    public function getCustomerAdditionalInformation()
613
    {
614
        return $this->getParameter('customerAdditionalInformation');
615
    }
616
617
    /**
618
     * Set the customerAdditionalInformation field
619
     *
620
     * Corresponds to the Ds_Merchant_Emv3Ds.acctID field
621
     *
622
     * @param null|string $value
623
     * @return self
624
     */
625
    public function setCustomerAdditionalInformation($value)
626
    {
627
        return $this->setParameter('customerAdditionalInformation', $value);
628
    }
629
630
    /**
631
     * Get the 3DsRequestAuthenticationMethodData field
632
     *
633
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSRequestorAuthenticationInfo.threeDSReqAuthData field in Redsys
634
     * documentation.
635
     *
636
     * @return null|string
637
     */
638
    public function get3DsRequestAuthenticationMethodData()
639
    {
640
        return $this->getParameter('3DsRequestAuthenticationMethodData');
641
    }
642
643
    /**
644
     * Set the 3DsRequestAuthenticationMethodData field
645
     *
646
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSRequestorAuthenticationInfo.threeDSReqAuthData field in the Redsys
647
     * documentation.
648
     *
649
     * @param null|string $value
650
     * @return self
651
     */
652
    public function set3DsRequestAuthenticationMethodData($value)
653
    {
654
        return $this->setParameter('3DsRequestAuthenticationMethodData', $value);
655
    }
656
657
    /**
658
     * Get the 3DsRequestAuthenticationMethod field
659
     *
660
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSRequestorAuthenticationInfo.threeDSReqAuthMethod field in Redsys
661
     * documentation.
662
     *
663
     * @return null|string One of the self::ACCOUNT_AUTHENTICATION_METHOD_* constants.
664
     */
665
    public function get3DsRequestAuthenticationMethod()
666
    {
667
        return $this->getParameter('3DsRequestAuthenticationMethod');
668
    }
669
670
    /**
671
     * Set the 3DsRequestAuthenticationMethod field
672
     *
673
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSRequestorAuthenticationInfo.threeDSReqAuthMethod field in the Redsys
674
     * documentation.
675
     *
676
     * @param null|string $value One of the self::ACCOUNT_AUTHENTICATION_METHOD_* constants.
677
     * @return self
678
     * @throws InvalidRequestException if $value is invalid.
679
     */
680
    public function set3DsRequestAuthenticationMethod($value)
681
    {
682
        if (in_array(
683
            $value,
684
            [
685
                null,
686
                self::ACCOUNT_AUTHENTICATION_METHOD_NONE,
687
                self::ACCOUNT_AUTHENTICATION_METHOD_OWN_CREDENTIALS,
688
                self::ACCOUNT_AUTHENTICATION_METHOD_FEDERATED_ID,
689
                self::ACCOUNT_AUTHENTICATION_METHOD_ISSUER_CREDENTIALS,
690
                self::ACCOUNT_AUTHENTICATION_METHOD_THIRD_PARTY_AUTHENTICATION,
691
                self::ACCOUNT_AUTHENTICATION_METHOD_FIDO,
692
            ]
693
        )) {
694
            return $this->setParameter('3DsRequestAuthenticationMethod', $value);
695
        }
696
        throw new InvalidRequestException("Invalid 3DsRequestAuthenticationMethod parameter");
697
    }
698
699
    /**
700
     * Get the 3DsRequestAuthenticationTime field
701
     *
702
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSRequestorAuthenticationInfo.threeDSReqAuthTimestamp field
703
     *
704
     * @return null|string
705
     */
706
    public function get3DsRequestAuthenticationTime()
707
    {
708
        return $this->getParameter('3DsRequestAuthenticationTime');
709
    }
710
711
    /**
712
     * Set the 3DsRequestAuthenticationTime field
713
     *
714
     * Corresponds to the Ds_Merchant_Emv3Ds.threeDSRequestorAuthenticationInfo.threeDSReqAuthTimestamp field
715
     *
716
     * @param null|DateTime|int $value
717
     * @return self
718
     */
719
    public function set3DsRequestAuthenticationTime($value)
720
    {
721
        return $this->setParameter('3DsRequestAuthenticationTime', $this->formatDateTime($value, "YmdHi"));
722
    }
723
724
    /**
725
     * Get the customerAccountCreatedIndicator field
726
     *
727
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccAgeInd field
728
     *
729
     * @return null|string One of the CUSTOMER_ACCOUNT_CREATED_* constants
730
     */
731
    public function getCustomerAccountCreatedIndicator()
732
    {
733
        return $this->getParameter('customerAccountCreatedIndicator');
734
    }
735
736
    /**
737
     * Set the customerAccountCreatedIndicator field
738
     *
739
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccAgeInd field
740
     *
741
     * @param null|string $value One of the CUSTOMER_ACCOUNT_CREATED_* constants
742
     * @return self
743
     * @throws InvalidRequestException if $value is invalid.
744
     */
745
    public function setCustomerAccountCreatedIndicator($value)
746
    {
747
        if (in_array(
748
            $value,
749
            [
750
                null,
751
                self::CUSTOMER_ACCOUNT_CREATED_NONE,
752
                self::CUSTOMER_ACCOUNT_CREATED_THIS_TRANSACTION,
753
                self::CUSTOMER_ACCOUNT_CREATED_LAST_30_DAYS,
754
                self::CUSTOMER_ACCOUNT_CREATED_LAST_60_DAYS,
755
                self::CUSTOMER_ACCOUNT_CREATED_MORE_THAN_60_DAYS,
756
            ]
757
        )) {
758
            return $this->setParameter('customerAccountCreatedIndicator', $value);
759
        }
760
        throw new InvalidRequestException("Invalid customerAccountCreatedIndicator parameter");
761
    }
762
763
    /**
764
     * Get the customerAccountCreatedDate field
765
     *
766
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccDate field
767
     *
768
     * @return null|string
769
     */
770
    public function getCustomerAccountCreatedDate()
771
    {
772
        return $this->getParameter('customerAccountCreatedDate');
773
    }
774
775
    /**
776
     * Set the customerAccountCreatedDate field
777
     *
778
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccDate field
779
     *
780
     * @param null|DateTime|int $value
781
     * @return self
782
     */
783
    public function setCustomerAccountCreatedDate($value)
784
    {
785
        return $this->setParameter('customerAccountCreatedDate', $this->formatDateTime($value, "Ymd"));
786
    }
787
788
    /**
789
     * Get the customerAccountChangedIndicator field
790
     *
791
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccChangeInd field
792
     *
793
     * @return null|string One of the CUSTOMER_ACCOUNT_MODIFIED_* constants
794
     */
795
    public function getCustomerAccountChangedIndicator()
796
    {
797
        return $this->getParameter('customerAccountChangedIndicator');
798
    }
799
800
    /**
801
     * Set the customerAccountChangedIndicator field
802
     *
803
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccChangeInd field
804
     *
805
     * @param null|string $value One of the CUSTOMER_ACCOUNT_MODIFIED_* constants
806
     * @return self
807
     * @throws InvalidRequestException if $value is invalid.
808
     */
809
    public function setCustomerAccountChangedIndicator($value)
810
    {
811
        if (in_array(
812
            $value,
813
            [
814
                null,
815
                self::CUSTOMER_ACCOUNT_MODIFIED_THIS_TRANSACTION,
816
                self::CUSTOMER_ACCOUNT_MODIFIED_LAST_30_DAYS,
817
                self::CUSTOMER_ACCOUNT_MODIFIED_LAST_60_DAYS,
818
                self::CUSTOMER_ACCOUNT_MODIFIED_MORE_THAN_60_DAYS,
819
            ]
820
        )) {
821
            return $this->setParameter('customerAccountChangedIndicator', $value);
822
        }
823
        throw new InvalidRequestException("Invalid customerAccountChangedIndicator parameter");
824
    }
825
826
    /**
827
     * Get the customerAccountChangedDate field
828
     *
829
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccChange field
830
     *
831
     * @return null|string
832
     */
833
    public function getCustomerAccountChangedDate()
834
    {
835
        return $this->getParameter('customerAccountChangedDate');
836
    }
837
838
    /**
839
     * Set the customerAccountChangedDate field
840
     *
841
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccChange field
842
     *
843
     * @param null|DateTime|int $value
844
     * @return self
845
     */
846
    public function setCustomerAccountChangedDate($value)
847
    {
848
        return $this->setParameter('customerAccountChangedDate', $this->formatDateTime($value, "Ymd"));
849
    }
850
851
    /**
852
     * Get the customerPasswordAgeIndicator field
853
     *
854
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccPwChangeInd field
855
     *
856
     * @return null|string One of the CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_* constants
857
     */
858
    public function getCustomerPasswordChangedIndicator()
859
    {
860
        return $this->getParameter('customerPasswordAgeIndicator');
861
    }
862
863
    /**
864
     * Set the customerPasswordAgeIndicator field
865
     *
866
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccPwChangeInd field
867
     *
868
     * @param null|string $value One of the CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_* constants
869
     * @return self
870
     * @throws InvalidRequestException if $value is invalid.
871
     */
872
    public function setCustomerPasswordChangedIndicator($value)
873
    {
874
        if (in_array(
875
            $value,
876
            [
877
                null,
878
                self::CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_NONE,
879
                self::CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_THIS_TRANSACTION,
880
                self::CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_LAST_30_DAYS,
881
                self::CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_LAST_60_DAYS,
882
                self::CUSTOMER_ACCOUNT_PASSWORD_MODIFIED_MORE_THAN_60_DAYS,
883
            ]
884
        )) {
885
            return $this->setParameter('customerPasswordAgeIndicator', $value);
886
        }
887
        throw new InvalidRequestException("Invalid customerPasswordAgeIndicator parameter");
888
    }
889
890
    /**
891
     * Get the customerPasswordChangedDate field
892
     *
893
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccPwChange field
894
     *
895
     * @return null|string
896
     */
897
    public function getCustomerPasswordChangedDate()
898
    {
899
        return $this->getParameter('customerPasswordChangedDate');
900
    }
901
902
    /**
903
     * Set the customerPasswordChangedDate field
904
     *
905
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.chAccPwChange field
906
     *
907
     * @param null|DateTime|int $value
908
     * @return self
909
     */
910
    public function setCustomerPasswordChangedDate($value)
911
    {
912
        return $this->setParameter('customerPasswordChangedDate', $this->formatDateTime($value, "Ymd"));
913
    }
914
915
    /**
916
     * Get the customerPurchasesInLast6Months field
917
     *
918
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.nbPurchaseAccount field
919
     *
920
     * @return null|int
921
     */
922
    public function getCustomerPurchasesInLast6Months()
923
    {
924
        return $this->getParameter('customerPurchasesInLast6Months');
925
    }
926
927
    /**
928
     * Set the customerPurchasesInLast6Months field
929
     *
930
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.nbPurchaseAccount field
931
     *
932
     * @param null|int $value
933
     * @return self
934
     */
935
    public function setCustomerPurchasesInLast6Months($value)
936
    {
937
        return $this->setParameter('customerPurchasesInLast6Months', $value);
938
    }
939
940
    /**
941
     * Get the customerAccountCardProvisionsLast24Hours field
942
     *
943
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.provisionAttemptsDay field
944
     *
945
     * @return null|int
946
     */
947
    public function getCustomerAccountCardProvisionsLast24Hours()
948
    {
949
        return $this->getParameter('customerAccountCardProvisionsLast24Hours');
950
    }
951
952
    /**
953
     * Set the customerAccountCardProvisionsLast24Hours field
954
     *
955
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.provisionAttemptsDay field
956
     *
957
     * @param null|int $value
958
     * @return self
959
     */
960
    public function setCustomerAccountCardProvisionsLast24Hours($value)
961
    {
962
        return $this->setParameter('customerAccountCardProvisionsLast24Hours', $value);
963
    }
964
965
    /**
966
     * Get the customerAccountTransactionsLast24Hours field
967
     *
968
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.txnActivityDay field
969
     *
970
     * @return null|int
971
     */
972
    public function getCustomerAccountTransactionsLast24Hours()
973
    {
974
        return $this->getParameter('customerAccountTransactionsLast24Hours');
975
    }
976
977
    /**
978
     * Set the customerAccountTransactionsLast24Hours field
979
     *
980
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.txnActivityDay field
981
     *
982
     * @param null|int $value
983
     * @return self
984
     */
985
    public function setCustomerAccountTransactionsLast24Hours($value)
986
    {
987
        return $this->setParameter('customerAccountTransactionsLast24Hours', $value);
988
    }
989
990
    /**
991
     * Get the customerAccountTransactionsLastYear field
992
     *
993
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.txnActivityYear field
994
     *
995
     * @return null|int
996
     */
997
    public function getCustomerAccountTransactionsLastYear()
998
    {
999
        return $this->getParameter('customerAccountTransactionsLastYear');
1000
    }
1001
1002
    /**
1003
     * Set the customerAccountTransactionsLastYear field
1004
     *
1005
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.txnActivityYear field
1006
     *
1007
     * @param null|int $value
1008
     * @return self
1009
     */
1010
    public function setCustomerAccountTransactionsLastYear($value)
1011
    {
1012
        return $this->setParameter('customerAccountTransactionsLastYear', $value);
1013
    }
1014
1015
    /**
1016
     * Get the customerPaymentMethodCreatedIndicator field
1017
     *
1018
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.paymentAccInd field
1019
     *
1020
     * @return null|string One of the PAYMENT_METHOD_CREATED_* constants
1021
     */
1022
    public function getCustomerPaymentMethodCreatedIndicator()
1023
    {
1024
        return $this->getParameter('customerPaymentMethodCreatedIndicator');
1025
    }
1026
1027
    /**
1028
     * Set the customerPaymentMethodCreatedIndicator field
1029
     *
1030
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.paymentAccInd field
1031
     *
1032
     * @param null|string $value One of the PAYMENT_METHOD_CREATED_* constants
1033
     * @return self
1034
     * @throws InvalidRequestException if $value is invalid.
1035
     */
1036
    public function setCustomerPaymentMethodCreatedIndicator($value)
1037
    {
1038
        if (in_array(
1039
            $value,
1040
            [
1041
                null,
1042
                self::PAYMENT_METHOD_CREATED_NONE,
1043
                self::PAYMENT_METHOD_CREATED_THIS_TRANSACTION,
1044
                self::PAYMENT_METHOD_CREATED_LAST_30_DAYS,
1045
                self::PAYMENT_METHOD_CREATED_LAST_60_DAYS,
1046
                self::PAYMENT_METHOD_CREATED_MORE_THAN_60_DAYS,
1047
            ]
1048
        )) {
1049
            return $this->setParameter('customerPaymentMethodCreatedIndicator', $value);
1050
        }
1051
        throw new InvalidRequestException("Invalid customerPaymentMethodCreatedIndicator parameter");
1052
    }
1053
1054
    /**
1055
     * Get the customerPaymentMethodCreatedDate field
1056
     *
1057
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.paymentAccAge field
1058
     *
1059
     * @return null|string
1060
     */
1061
    public function getCustomerPaymentMethodCreatedDate()
1062
    {
1063
        return $this->getParameter('customerPaymentMethodCreatedDate');
1064
    }
1065
1066
    /**
1067
     * Set the customerPaymentMethodCreatedDate field
1068
     *
1069
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.paymentAccAge field
1070
     *
1071
     * @param null|DateTime|int $value
1072
     * @return self
1073
     */
1074
    public function setCustomerPaymentMethodCreatedDate($value)
1075
    {
1076
        return $this->setParameter('customerPaymentMethodCreatedDate', $this->formatDateTime($value, "Ymd"));
1077
    }
1078
1079
    /**
1080
     * Get the shippingAddressFirstUsedIndicator field
1081
     *
1082
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.shipAddressUsageInd field
1083
     *
1084
     * @return null|string One of the SHIPPING_ADDRESS_USAGE_* constants
1085
     */
1086
    public function getShippingAddressFirstUsedIndicator()
1087
    {
1088
        return $this->getParameter('shippingAddressFirstUsedIndicator');
1089
    }
1090
1091
    /**
1092
     * Set the shippingAddressFirstUsedIndicator field
1093
     *
1094
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.shipAddressUsageInd field
1095
     *
1096
     * @param null|string $value One of the SHIPPING_ADDRESS_USAGE_* constants
1097
     * @return self
1098
     * @throws InvalidRequestException if $value is invalid.
1099
     */
1100
    public function setShippingAddressFirstUsedIndicator($value)
1101
    {
1102
        if (in_array(
1103
            $value,
1104
            [
1105
                null,
1106
                self::SHIPPING_ADDRESS_USAGE_THIS_TRANSACTION,
1107
                self::SHIPPING_ADDRESS_USAGE_LAST_30_DAYS,
1108
                self::SHIPPING_ADDRESS_USAGE_LAST_60_DAYS,
1109
                self::SHIPPING_ADDRESS_USAGE_MORE_THAN_60_DAYS,
1110
            ]
1111
        )) {
1112
            return $this->setParameter('shippingAddressFirstUsedIndicator', $value);
1113
        }
1114
        throw new InvalidRequestException("Invalid shippingAddressFirstUsedIndicator parameter");
1115
    }
1116
1117
    /**
1118
     * Get the shippingAddressFirstUsedDate field
1119
     *
1120
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.shipAddressUsage field
1121
     *
1122
     * @return null|string
1123
     */
1124
    public function getShippingAddressFirstUsedDate()
1125
    {
1126
        return $this->getParameter('shippingAddressFirstUsedDate');
1127
    }
1128
1129
    /**
1130
     * Set the shippingAddressFirstUsedDate field
1131
     *
1132
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.shipAddressUsage field
1133
     *
1134
     * @param null|DateTime|int $value
1135
     * @return self
1136
     */
1137
    public function setShippingAddressFirstUsedDate($value)
1138
    {
1139
        return $this->setParameter('shippingAddressFirstUsedDate', $this->formatDateTime($value, "Ymd"));
1140
    }
1141
1142
    /**
1143
     * Get the shippingNameCustomerNameMatch field
1144
     *
1145
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.shipNameIndicator field
1146
     *
1147
     * @return null|boolean
1148
     */
1149
    public function getShippingNameCustomerNameMatch()
1150
    {
1151
        return $this->getParameter('shippingNameCustomerNameMatch');
1152
    }
1153
1154
    /**
1155
     * Set the shippingNameCustomerNameMatch field
1156
     *
1157
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.shipNameIndicator field
1158
     *
1159
     * @param null|boolean $value
1160
     * @return self
1161
     */
1162
    public function setShippingNameCustomerNameMatch($value)
1163
    {
1164
        return $this->setParameter('shippingNameCustomerNameMatch', $value);
1165
    }
1166
1167
    /**
1168
     * Get the customerHasSuspiciousActivity field
1169
     *
1170
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.suspiciousAccActivity field
1171
     *
1172
     * @return null|boolean
1173
     */
1174
    public function getCustomerHasSuspiciousActivity()
1175
    {
1176
        return $this->getParameter('customerHasSuspiciousActivity');
1177
    }
1178
1179
    /**
1180
     * Set the customerHasSuspiciousActivity field
1181
     *
1182
     * Corresponds to the Ds_Merchant_Emv3Ds.acctInfo.suspiciousAccActivity field
1183
     *
1184
     * @param null|boolean $value
1185
     * @return self
1186
     */
1187
    public function setCustomerHasSuspiciousActivity($value)
1188
    {
1189
        return $this->setParameter('customerHasSuspiciousActivity', $value);
1190
    }
1191
1192
    /**
1193
     * Get the deliveryEmail field
1194
     *
1195
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.deliveryEmailAddress field
1196
     *
1197
     * @return null|string
1198
     */
1199
    public function getDeliveryEmail()
1200
    {
1201
        return $this->getParameter('deliveryEmail');
1202
    }
1203
1204
    /**
1205
     * Set the deliveryEmail field
1206
     *
1207
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.deliveryEmailAddress field
1208
     *
1209
     * @param null|string $value
1210
     * @return self
1211
     */
1212
    public function setDeliveryEmail($value)
1213
    {
1214
        return $this->setParameter('deliveryEmail', $value);
1215
    }
1216
1217
    /**
1218
     * Get the deliveryTimeframeIndicator field
1219
     *
1220
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.deliveryTimeframe field
1221
     *
1222
     * @return null|string One of the DELIVERY_TIMEFRAME_* constants
1223
     */
1224
    public function getDeliveryTimeframeIndicator()
1225
    {
1226
        return $this->getParameter('deliveryTimeframeIndicator');
1227
    }
1228
1229
    /**
1230
     * Set the deliveryTimeframeIndicator field
1231
     *
1232
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.deliveryTimeframe field
1233
     *
1234
     * @param null|string $value One of the DELIVERY_TIMEFRAME_* constants
1235
     * @return self
1236
     * @throws InvalidRequestException if $value is invalid.
1237
     */
1238
    public function setDeliveryTimeframeIndicator($value)
1239
    {
1240
        if (in_array(
1241
            $value,
1242
            [
1243
                null,
1244
                self::DELIVERY_TIMEFRAME_ELECTRONIC_DELIVERY,
1245
                self::DELIVERY_TIMEFRAME_SAME_DAY,
1246
                self::DELIVERY_TIMEFRAME_NEXT_DAY,
1247
                self::DELIVERY_TIMEFRAME_2_OR_MORE_DAYS,
1248
            ]
1249
        )) {
1250
            return $this->setParameter('deliveryTimeframeIndicator', $value);
1251
        }
1252
        throw new InvalidRequestException("Invalid deliveryTimeframeIndicator parameter");
1253
    }
1254
1255
    /**
1256
     * Get the giftCardAmount field
1257
     *
1258
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.giftCardAmount field
1259
     *
1260
     * @return null|int
1261
     */
1262
    public function getGiftCardAmount()
1263
    {
1264
        return $this->getParameter('giftCardAmount');
1265
    }
1266
1267
    /**
1268
     * Set the giftCardAmount field
1269
     *
1270
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.giftCardAmount field
1271
     *
1272
     * @param null|int $value
1273
     * @return self
1274
     */
1275
    public function setGiftCardAmount($value)
1276
    {
1277
        return $this->setParameter('giftCardAmount', $value);
1278
    }
1279
1280
    /**
1281
     * Get the giftCardCount field
1282
     *
1283
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.giftCardCount field
1284
     *
1285
     * @return null|int
1286
     */
1287
    public function getGiftCardCount()
1288
    {
1289
        return $this->getParameter('giftCardCount');
1290
    }
1291
1292
    /**
1293
     * Set the giftCardCount field
1294
     *
1295
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.giftCardCount field
1296
     *
1297
     * @param null|int $value
1298
     * @return self
1299
     */
1300
    public function setGiftCardCount($value)
1301
    {
1302
        return $this->setParameter('giftCardCount', $value);
1303
    }
1304
1305
    /**
1306
     * Get the giftCardCurrency field
1307
     *
1308
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.giftCardCurr field
1309
     *
1310
     * @return null|string ISO-4217 currency code
1311
     */
1312
    public function getGiftCardCurrency()
1313
    {
1314
        return $this->getParameter('giftCardCurrency');
1315
    }
1316
1317
    /**
1318
     * Set the giftCardCurrency field
1319
     *
1320
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.giftCardCurr field
1321
     *
1322
     * @param null|string $value ISO-4217 currency code
1323
     * @return self
1324
     */
1325
    public function setGiftCardCurrency($value)
1326
    {
1327
        return $this->setParameter('giftCardCurrency', $value);
1328
    }
1329
1330
    /**
1331
     * Get the purchasingPreOrder field
1332
     *
1333
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.preOrderPurchaseInd field
1334
     *
1335
     * @return null|boolean True if the customer is purchasing a preorder
1336
     */
1337
    public function getPurchasingPreOrder()
1338
    {
1339
        return $this->getParameter('purchasingPreOrder');
1340
    }
1341
1342
    /**
1343
     * Set the purchasingPreOrder field
1344
     *
1345
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.preOrderPurchaseInd field
1346
     *
1347
     * @param null|boolean $value True if the customer is purchasing a preorder
1348
     * @return self
1349
     */
1350
    public function setPurchasingPreOrder($value)
1351
    {
1352
        return $this->setParameter('purchasingPreOrder', $value);
1353
    }
1354
1355
    /**
1356
     * Get the preOrderDate field
1357
     *
1358
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.preOrderDate field
1359
     *
1360
     * @return null|string
1361
     */
1362
    public function getPreOrderDate()
1363
    {
1364
        return $this->getParameter('preOrderDate');
1365
    }
1366
1367
    /**
1368
     * Set the preOrderDate field
1369
     *
1370
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.preOrderDate field
1371
     *
1372
     * @param null|DateTime|int $value
1373
     * @return self
1374
     */
1375
    public function setPreOrderDate($value)
1376
    {
1377
        return $this->setParameter('preOrderDate', $this->formatDateTime($value, "Ymd"));
1378
    }
1379
1380
    /**
1381
     * Get the customerHasPurchasedProductBefore field
1382
     *
1383
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.reorderItemsInd field
1384
     *
1385
     * @return null|boolean
1386
     */
1387
    public function getCustomerHasPurchasedProductBefore()
1388
    {
1389
        return $this->getParameter('customerHasPurchasedProductBefore');
1390
    }
1391
1392
    /**
1393
     * Set the customerHasPurchasedProductBefore field
1394
     *
1395
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.reorderItemsInd field
1396
     *
1397
     * @param null|boolean $value
1398
     * @return self
1399
     */
1400
    public function setCustomerHasPurchasedProductBefore($value)
1401
    {
1402
        return $this->setParameter('customerHasPurchasedProductBefore', $value);
1403
    }
1404
1405
    /**
1406
     * Get the shippingAddressIndicator field
1407
     *
1408
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.shipIndicator field
1409
     *
1410
     * @return null|string One of the self::SHIPPING_* constants
1411
     */
1412
    public function getShippingAddressIndicator()
1413
    {
1414
        return $this->getParameter('shippingAddressIndicator');
1415
    }
1416
1417
    /**
1418
     * Set the shippingAddressIndicator field
1419
     *
1420
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.shipIndicator field
1421
     *
1422
     * @param null|string $value One of the self::SHIPPING_* constants
1423
     * @return self
1424
     * @throws InvalidRequestException if $value is invalid.
1425
     */
1426
    public function setShippingAddressIndicator($value)
1427
    {
1428
        if (in_array(
1429
            $value,
1430
            [
1431
                null,
1432
                self::SHIPPING_TO_BILLING_ADDRESS,
1433
                self::SHIPPING_TO_ANOTHER_VERIFIED_ADDRESS,
1434
                self::SHIPPING_DIFFERENT_BILLING_ADDRESS,
1435
                self::SHIPPING_PICK_UP,
1436
                self::SHIPPING_DIGITAL,
1437
                self::SHIPPING_TRAVEL,
1438
                self::SHIPPING_OTHER,
1439
            ]
1440
        )) {
1441
            return $this->setParameter('shippingAddressIndicator', $value);
1442
        }
1443
        throw new InvalidRequestException("Invalid shippingAddressIndicator parameter");
1444
    }
1445
1446
    /**
1447
     * Get the SCA exemption field
1448
     *
1449
     * Corresponds to the Ds_Merchant_Excep_Sca field
1450
     *
1451
     * @return null|string One of the self::SCA_EXEMPTION_* constants
1452
     */
1453
    public function getScaExemptionIndicator()
1454
    {
1455
        return $this->getParameter('scaExemptionIndicator');
1456
    }
1457
1458
    /**
1459
     * Set the SCA exemption field
1460
     *
1461
     * Corresponds to the Ds_Merchant_Emv3Ds.MerchantRiskIndicator.shipIndicator field
1462
     *
1463
     * @param null|string $value One of the self::SCA_EXEMPTION_* constants
1464
     * @return self
1465
     * @throws InvalidRequestException if $value is invalid.
1466
     */
1467
    public function setScaExemptionIndicator($value)
1468
    {
1469
        if (in_array(
1470
            $value,
1471
            [
1472
                null,
1473
                self::SCA_EXEMPTION_LOW_AMOUNT,
1474
                self::SCA_EXEMPTION_LOW_RISK,
1475
                self::SCA_EXEMPTION_CORPORATE,
1476
                self::SCA_EXEMPTION_MERCHANT_INITIATED,
1477
            ]
1478
        )) {
1479
            return $this->setParameter('scaExemptionIndicator', $value);
1480
        }
1481
        throw new InvalidRequestException("Invalid scaExemptionIndicator parameter");
1482
    }
1483
1484
    /**
1485
     * Override the abstract method to add requirement that it must start with 4 numeric characters
1486
     *
1487
     * @param string|int $value The transaction ID (merchant order) to set for the transaction
1488
     */
1489
    public function setTransactionId($value)
1490
    {
1491
        $start = substr($value, 0, 4);
1492
        $numerics = 0;
1493
        foreach (str_split($start) as $char) {
1494
            if (is_numeric($char)) {
1495
                $numerics++;
1496
            } else {
1497
                break;
1498
            }
1499
        }
1500
        $value = str_pad(substr($start, 0, $numerics), 4, 0, STR_PAD_LEFT).substr($value, $numerics);
1501
1502
        parent::setTransactionId($value);
1503
    }
1504
1505
    /**
1506
     * Get the browserAcceptHeader field
1507
     *
1508
     * Corresponds to the Ds_Merchant_Emv3Ds.browserAcceptHeader field
1509
     *
1510
     * @return null|string
1511
     */
1512
    public function getBrowserAcceptHeader()
1513
    {
1514
        return $this->getParameter('browserAcceptHeader');
1515
    }
1516
1517
    /**
1518
     * Set the browserAcceptHeader field
1519
     *
1520
     * Corresponds to the Ds_Merchant_Emv3Ds.browserAcceptHeader field
1521
     *
1522
     * @param null|string $value
1523
     * @return self
1524
     */
1525
    public function setBrowserAcceptHeader($value)
1526
    {
1527
        return $this->setParameter('browserAcceptHeader', $value);
1528
    }
1529
1530
    /**
1531
     * Get the browserColorDepth field
1532
     *
1533
     * Corresponds to the Ds_Merchant_Emv3Ds.browserColorDepth field
1534
     *
1535
     * @return null|int
1536
     */
1537
    public function getBrowserColorDepth()
1538
    {
1539
        return $this->getParameter('browserColorDepth');
1540
    }
1541
1542
    /**
1543
     * Set the browserColorDepth field
1544
     *
1545
     * Corresponds to the Ds_Merchant_Emv3Ds.browserColorDepth field
1546
     *
1547
     * @param null|int $value
1548
     * @return self
1549
     */
1550
    public function setBrowserColorDepth($value)
1551
    {
1552
        return $this->setParameter('browserColorDepth', $value);
1553
    }
1554
1555
    /**
1556
     * Get the browserJavaEnabled field
1557
     *
1558
     * Corresponds to the Ds_Merchant_Emv3Ds.browserJavaEnabled field
1559
     *
1560
     * @return null|bool
1561
     */
1562
    public function getBrowserJavaEnabled()
1563
    {
1564
        return $this->getParameter('browserJavaEnabled');
1565
    }
1566
1567
    /**
1568
     * Set the browserJavaEnabled field
1569
     *
1570
     * Corresponds to the Ds_Merchant_Emv3Ds.browserJavaEnabled field
1571
     *
1572
     * @param null|bool $value
1573
     * @return self
1574
     */
1575
    public function setBrowserJavaEnabled($value)
1576
    {
1577
        return $this->setParameter('browserJavaEnabled', $value);
1578
    }
1579
1580
    /**
1581
     * Get the browserLanguage field
1582
     *
1583
     * Corresponds to the Ds_Merchant_Emv3Ds.browserLanguage field
1584
     *
1585
     * @return null|string
1586
     */
1587
    public function getBrowserLanguage()
1588
    {
1589
        return $this->getParameter('browserLanguage');
1590
    }
1591
1592
    /**
1593
     * Set the browserLanguage field
1594
     *
1595
     * Corresponds to the Ds_Merchant_Emv3Ds.browserLanguage field
1596
     *
1597
     * @param null|string $value
1598
     * @return self
1599
     */
1600
    public function setBrowserLanguage($value)
1601
    {
1602
        return $this->setParameter('browserLanguage', $value);
1603
    }
1604
1605
    /**
1606
     * Get the browserScreenHeight field
1607
     *
1608
     * Corresponds to the Ds_Merchant_Emv3Ds.browserScreenHeight field
1609
     *
1610
     * @return null|int
1611
     */
1612
    public function getBrowserScreenHeight()
1613
    {
1614
        return $this->getParameter('browserScreenHeight');
1615
    }
1616
1617
    /**
1618
     * Set the browserScreenHeight field
1619
     *
1620
     * Corresponds to the Ds_Merchant_Emv3Ds.browserScreenHeight field
1621
     *
1622
     * @param null|int $value
1623
     * @return self
1624
     */
1625
    public function setBrowserScreenHeight($value)
1626
    {
1627
        return $this->setParameter('browserScreenHeight', $value);
1628
    }
1629
1630
    /**
1631
     * Get the browserScreenWidth field
1632
     *
1633
     * Corresponds to the Ds_Merchant_Emv3Ds.browserScreenWidth field
1634
     *
1635
     * @return null|int
1636
     */
1637
    public function getBrowserScreenWidth()
1638
    {
1639
        return $this->getParameter('browserScreenWidth');
1640
    }
1641
1642
    /**
1643
     * Set the browserScreenWidth field
1644
     *
1645
     * Corresponds to the Ds_Merchant_Emv3Ds.browserScreenWidth field
1646
     *
1647
     * @param null|int $value
1648
     * @return self
1649
     */
1650
    public function setBrowserScreenWidth($value)
1651
    {
1652
        return $this->setParameter('browserScreenWidth', $value);
1653
    }
1654
1655
    /**
1656
     * Get the browserTZ field
1657
     *
1658
     * Corresponds to the Ds_Merchant_Emv3Ds.browserTZ field
1659
     *
1660
     * @return null|int
1661
     */
1662
    public function getBrowserTZ()
1663
    {
1664
        return $this->getParameter('browserTZ');
1665
    }
1666
1667
    /**
1668
     * Set the browserTZ field
1669
     *
1670
     * Corresponds to the Ds_Merchant_Emv3Ds.browserTZ field
1671
     *
1672
     * @param null|int $value
1673
     * @return self
1674
     */
1675
    public function setBrowserTZ($value)
1676
    {
1677
        return $this->setParameter('browserTZ', $value);
1678
    }
1679
1680
    /**
1681
     * Get the browserUserAgent field
1682
     *
1683
     * Corresponds to the Ds_Merchant_Emv3Ds.browserUserAgent field
1684
     *
1685
     * @return null|string
1686
     */
1687
    public function getBrowserUserAgent()
1688
    {
1689
        return $this->getParameter('browserUserAgent');
1690
    }
1691
1692
    /**
1693
     * Set the browserUserAgent field
1694
     *
1695
     * Corresponds to the Ds_Merchant_Emv3Ds.browserUserAgent field
1696
     *
1697
     * @param null|string $value
1698
     * @return self
1699
     */
1700
    public function setBrowserUserAgent($value)
1701
    {
1702
        return $this->setParameter('browserUserAgent', $value);
1703
    }
1704
1705
    /**
1706
     * Get the basic data fields that don't require any 3DS/SCA fields
1707
     */
1708
    public function getBaseData()
1709
    {
1710
        $this->validate('merchantId', 'terminalId', 'amount', 'currency');
1711
1712
        return [
1713
            // mandatory fields
1714
            'Ds_Merchant_MerchantCode'       => $this->getMerchantId(),
1715
            'Ds_Merchant_Terminal'           => $this->getTerminalId(),
1716
            'Ds_Merchant_TransactionType'    => '0',                          // Authorisation
1717
            'Ds_Merchant_Amount'             => $this->getAmountInteger(),
1718
            'Ds_Merchant_Currency'           => $this->getCurrencyNumeric(),  // uses ISO-4217 codes
1719
            'Ds_Merchant_Order'              => $this->getTransactionId(),
1720
            'Ds_Merchant_MerchantUrl'        => $this->getNotifyUrl(),
1721
            // optional fields
1722
            'Ds_Merchant_ProductDescription' => $this->getDescription(),
1723
            'Ds_Merchant_Cardholder'         => $this->getCardholder(),
1724
            'Ds_Merchant_UrlOK'              => $this->getReturnUrl(),
1725
            'Ds_Merchant_UrlKO'              => $this->getCancelUrl(),
1726
            'Ds_Merchant_MerchantName'       => $this->getMerchantName(),
1727
            'Ds_Merchant_ConsumerLanguage'   => $this->getConsumerLanguage(),
1728
            'Ds_Merchant_MerchantData'       => $this->getMerchantData(),
1729
            'Ds_Merchant_Identifier'         => $this->getCreateToken()
1730
                ? 'REQUIRED'
1731
                : ($this->getToken() ?? $this->getCardReference()),
1732
        ];
1733
    }
1734
1735
    public function get3DSAccountInfoData()
1736
    {
1737
        $data = array_filter([
1738
            'chAccAgeInd'           => $this->getCustomerAccountCreatedIndicator(),
1739
            'chAccDate'             => $this->getCustomerAccountCreatedDate(),
1740
            'chAccChangeInd'        => $this->getCustomerAccountChangedIndicator(),
1741
            'chAccChange'           => $this->getCustomerAccountChangedDate(),
1742
            'chAccPwChangeInd'      => $this->getCustomerPasswordChangedIndicator(),
1743
            'chAccPwChange'         => $this->getCustomerPasswordChangedDate(),
1744
            'paymentAccInd'         => $this->getCustomerPaymentMethodCreatedIndicator(),
1745
            'paymentAccAge'         => $this->getCustomerPaymentMethodCreatedDate(),
1746
            'shipAddressUsageInd'   => $this->getShippingAddressFirstUsedIndicator(),
1747
            'shipAddressUsage'      => $this->getShippingAddressFirstUsedDate(),
1748
        ]);
1749
        // checks that can't rely on a simple filter (which could remove or add values unintentionally)
1750
        if ($this->getShippingNameCustomerNameMatch() !== null) {
1751
            $data['shipNameIndicator'] = $this->getShippingNameCustomerNameMatch() ? "01" : "02";
1752
        }
1753
        if ($this->getCustomerHasSuspiciousActivity() !== null) {
1754
            $data['suspiciousAccActivity'] = $this->getCustomerHasSuspiciousActivity() ? "02" : "01";
1755
        }
1756
        if ($this->getCustomerPurchasesInLast6Months() !== null) {
1757
            $data['nbPurchaseAccount'] = $this->getCustomerPurchasesInLast6Months();
1758
        }
1759
        if ($this->getCustomerAccountCardProvisionsLast24Hours() !== null) {
1760
            $data['provisionAttemptsDay'] = $this->getCustomerAccountCardProvisionsLast24Hours();
1761
        }
1762
        if ($this->getCustomerAccountTransactionsLast24Hours() !== null) {
1763
            $data['txnActivityDay'] = $this->getCustomerAccountTransactionsLast24Hours();
1764
        }
1765
        if ($this->getCustomerAccountTransactionsLastYear() !== null) {
1766
            $data['txnActivityYear'] = $this->getCustomerAccountTransactionsLastYear();
1767
        }
1768
1769
        return $data;
1770
    }
1771
1772
    public function getMerchantRiskData()
1773
    {
1774
        $data = array_filter([
1775
            'deliveryEmailAddress' => $this->getDeliveryEmail(),
1776
            'deliveryTimeframe'    => $this->getDeliveryTimeframeIndicator(),
1777
            'giftCardCount'        => $this->getGiftCardCount(),
1778
            'giftCardCurr'         => $this->getGiftCardCurrency(),
1779
            'preOrderDate'         => $this->getPreOrderDate(),
1780
            'shipIndicator'        => $this->getShippingAddressIndicator(),
1781
        ]);
1782
        if ($this->getGiftCardAmount() !== null) {
1783
            $data['giftCardAmount'] = (int) $this->getGiftCardAmount();
1784
        }
1785
        if ($this->getPurchasingPreOrder() !== null) {
1786
            $data['preOrderPurchaseInd'] = $this->getPurchasingPreOrder() ? "02" : "01";
1787
        }
1788
        if ($this->getCustomerHasPurchasedProductBefore() !== null) {
1789
            $data['reorderItemsInd'] = $this->getCustomerHasPurchasedProductBefore() ? "02" : "01";
1790
        }
1791
1792
        return $data;
1793
    }
1794
1795
    public function getData()
1796
    {
1797
        $data = $this->getBaseData();
1798
1799
        if ($this->getDirectPayment() !== null) {
1800
            $data['Ds_Merchant_DirectPayment'] = $this->getDirectPayment();
1801
        }
1802
1803
        if ($this->getScaExemptionIndicator() !== null) {
1804
            $data['Ds_Merchant_Excep_Sca'] = $this->getScaExemptionIndicator();
1805
        }
1806
1807
        // only generate an EMV 3DS request if requested to
1808
        if ($this->getUse3DS()) {
1809
            // Validating the presence of the card under the assumption that at least an address is required
1810
            // NOTE: normally would validate() for other submission params, but the minimum depends on bank contract
1811
            $this->validate('card');
1812
            $card = $this->getCard();
1813
1814
            $homePhone = array_filter([
1815
                'cc'         => $this->getHomePhoneCountryPrefix(),
1816
                'subscriber' => $this->getHomePhone(),
1817
            ]);
1818
            $mobilePhone = array_filter([
1819
                'cc'         => $this->getMobilePhoneCountryPrefix(),
1820
                'subscriber' => $this->getMobilePhone(),
1821
            ]);
1822
            $workPhone = array_filter([
1823
                'cc'         => $this->getWorkPhoneCountryPrefix(),
1824
                'subscriber' => $this->getWorkPhone(),
1825
            ]);
1826
            // for optional threeDSRequestorAuthenticationInfo param
1827
            $threeDSAuthInfo = array_filter([
1828
                'threeDSReqAuthData'      => $this->get3DsRequestAuthenticationMethodData(),
1829
                'threeDSReqAuthMethod'    => $this->get3DsRequestAuthenticationMethod(),
1830
                'threeDSReqAuthTimestamp' => $this->get3DsRequestAuthenticationTime(),
1831
            ]);
1832
            // for optional DS_MERCHANT_EMV3DS param object
1833
            $emv3DsParameters = array_filter([
1834
                // required parameters for v2
1835
                'browserAcceptHeader'                => $this->getBrowserAcceptHeader(),
1836
                'browserColorDepth'                  => $this->getBrowserColorDepth(),
1837
                'browserIP'                          => $this->getClientIp(),
1838
                'browserJavaEnabled'                 => $this->getBrowserJavaEnabled(),
1839
                'browserLanguage'                    => $this->getBrowserLanguage(),
1840
                'browserScreenHeight'                => $this->getBrowserScreenHeight(),
1841
                'browserScreenWidth'                 => $this->getBrowserScreenWidth(),
1842
                'browserTZ'                          => $this->getBrowserTZ(),
1843
                'browserUserAgent'                   => $this->getBrowserUserAgent(),
1844
                'notificationURL'                    => $this->getNotifyUrl(),
1845
                'protocolVersion'                    => $this->getProtocolVersion(),
1846
                'threeDSCompInd'                     => $this->getThreeDSCompInd(),
1847
                'threeDSInfo'                        => $this->getThreeDSInfo(),
1848
                'threeDSServerTransID'               => $this->getTransactionId(),
1849
                // optional parameters for v2
1850
                'cardholderName'                     => $this->getCardholder(),
1851
                // in Redsys DS_MERCHANT_EMV3DS table as 'E-mail'
1852
                'email'                              => $card->getEmail(),
1853
                'homePhone'                          => $homePhone,
1854
                'mobilePhone'                        => $mobilePhone,
1855
                'workPhone'                          => $workPhone,
1856
                'shipAddrLine1'                      => $card->getShippingAddress1(),
1857
                'shipAddrLine2'                      => $card->getShippingAddress2(),
1858
                'shipAddrLine3'                      => $card->getShippingAddress3(),
1859
                'shipAddrCity'                       => $card->getShippingCity(),
1860
                'shipAddrPostCode'                   => $card->getShippingPostcode(),
1861
                'shipAddrState'                      => $card->getShippingState(),
1862
                'shipAddrCountry'                    => $card->getShippingCountry(),
1863
                'billAddrLine1'                      => $card->getBillingAddress1(),
1864
                'billAddrLine2'                      => $card->getBillingAddress2(),
1865
                'billAddrLine3'                      => $card->getBillingAddress3(),
1866
                'billAddrCity'                       => $card->getBillingCity(),
1867
                'billAddrPostCode'                   => $card->getBillingPostcode(),
1868
                'billAddrState'                      => $card->getBillingState(),
1869
                'billAddrCountry'                    => $card->getBillingCountry(),
1870
                'addrMatch'                          => $this->getAddressMatch(),
1871
                'challengeWindowSize'                => $this->getChallengeWindowSize(),
1872
                'acctID'                             => $this->getCustomerAdditionalInformation(),
1873
                'threeDSRequestorAuthenticationInfo' => $threeDSAuthInfo,
1874
            ]);
1875
1876
            $acctInfo = $this->get3DSAccountInfoData();
1877
            if ($acctInfo !== []) {
1878
                $emv3DsParameters['acctInfo'] = $acctInfo;
1879
            }
1880
1881
            $merchantRiskIndicator = $this->getMerchantRiskData();
1882
            if ($merchantRiskIndicator !== []) {
1883
                $emv3DsParameters['merchantRiskIndicator'] = $merchantRiskIndicator;
1884
            }
1885
1886
            if ($emv3DsParameters !== []) {
1887
                $data['Ds_Merchant_Emv3Ds'] = $emv3DsParameters;
1888
            }
1889
        }
1890
1891
        return $data;
1892
    }
1893
1894
    public function sendData($data)
1895
    {
1896
        $security = new Security;
1897
1898
        $encoded_data = $security->encodeMerchantParameters($data);
1899
1900
        $response_data = array(
1901
            'Ds_SignatureVersion'   => Security::VERSION,
1902
            'Ds_MerchantParameters' => $encoded_data,
1903
            'Ds_Signature'          => $security->createSignature(
1904
                $encoded_data,
1905
                $data['Ds_Merchant_Order'],
1906
                $this->getHmacKey()
1907
            ),
1908
        );
1909
1910
        return $this->response = new PurchaseResponse($this, $response_data);
1911
    }
1912
1913
    public function getEndpoint()
1914
    {
1915
        return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint;
1916
    }
1917
1918
    /**
1919
     * Convert a DateTime or timestamp to a formatted date.
1920
     *
1921
     * @param DateTime|int|null $date   The date to format.
1922
     * @param string            $format The format to use.
1923
     *
1924
     * @return string|null The formatted date, or null if date isn't a timestamp or DateTime object.
1925
     */
1926
    protected function formatDateTime($date, $format)
1927
    {
1928
        if (is_int($date)) {
1929
            return (new DateTime('@'.$date))->format($format);
1930
        } elseif ($date instanceof DateTime) {
1931
            return $date->setTimezone(new DateTimeZone('UTC'))->format($format);
1932
        }
1933
    }
1934
}
1935