Issues (3412)

Zed/Payment/Business/Facade/PaymentFacadeTest.php (5 issues)

1
<?php
2
3
/**
4
 * Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
5
 * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
6
 */
7
8
namespace SprykerTest\Zed\Payment\Business\Facade;
9
10
use Codeception\Test\Unit;
11
use DateTime;
12
use DateTimeZone;
13
use Generated\Shared\DataBuilder\CheckoutResponseBuilder;
14
use Generated\Shared\DataBuilder\PaymentMethodBuilder;
15
use Generated\Shared\DataBuilder\PaymentProviderBuilder;
16
use Generated\Shared\DataBuilder\QuoteBuilder;
17
use Generated\Shared\DataBuilder\StoreRelationBuilder;
18
use Generated\Shared\Transfer\AcpHttpRequestTransfer;
19
use Generated\Shared\Transfer\AcpHttpResponseTransfer;
20
use Generated\Shared\Transfer\AddPaymentMethodTransfer;
21
use Generated\Shared\Transfer\CheckoutResponseTransfer;
22
use Generated\Shared\Transfer\DeletePaymentMethodTransfer;
23
use Generated\Shared\Transfer\MessageAttributesTransfer;
24
use Generated\Shared\Transfer\PaymentMethodsTransfer;
25
use Generated\Shared\Transfer\PaymentMethodTransfer;
26
use Generated\Shared\Transfer\PaymentProviderTransfer;
27
use Generated\Shared\Transfer\PaymentTransfer;
28
use Generated\Shared\Transfer\QuoteTransfer;
29
use Generated\Shared\Transfer\StoreRelationTransfer;
30
use Generated\Shared\Transfer\StoreTransfer;
31
use Orm\Zed\Payment\Persistence\SpyPaymentMethodQuery;
32
use Ramsey\Uuid\Uuid;
33
use Spryker\Zed\Kernel\Container;
34
use Spryker\Zed\KernelApp\Business\KernelAppFacadeInterface;
35
use Spryker\Zed\Payment\Business\Method\PaymentMethodReader;
36
use Spryker\Zed\Payment\Business\PaymentBusinessFactory;
37
use Spryker\Zed\Payment\Business\PaymentFacade;
38
use Spryker\Zed\Payment\Dependency\Facade\PaymentToKernelAppFacadeBridge;
39
use Spryker\Zed\Payment\PaymentConfig;
40
use Spryker\Zed\Payment\PaymentDependencyProvider;
41
use SprykerTest\Zed\Payment\PaymentBusinessTester;
42
use Symfony\Component\HttpFoundation\Response;
43
44
/**
45
 * Auto-generated group annotations
46
 *
47
 * @group SprykerTest
48
 * @group Zed
49
 * @group Payment
50
 * @group Business
51
 * @group Facade
52
 * @group Facade
53
 * @group PaymentFacadeTest
54
 * Add your own group annotations below this line
55
 */
56
class PaymentFacadeTest extends Unit
57
{
58
    /**
59
     * @var string
60
     */
61
    protected const STORE_REFERENCE = 'dev-DE';
62
63
    /**
64
     * @var string
65
     */
66
    protected const STORE_NAME = 'DE';
67
68
    /**
69
     * @var string
70
     */
71
    protected const CHECKOUT_REDIRECT_URL = 'checkout-redirect-url';
72
73
    /**
74
     * @var string
75
     */
76
    protected const PAYMENT_AUTHORIZATION_ENDPOINT = 'http://localhost/authorize';
77
78
    /**
79
     * @var string
80
     */
81
    protected const PAYMENT_AUTHORIZATION_REDIRECT = 'http://localhost/redirect';
82
83
    /**
84
     * @see \Spryker\Zed\Payment\Business\ForeignPayment\ForeignPayment::ERROR_MESSAGE_PAYMENT_AUTHORIZATION
85
     *
86
     * @var string
87
     */
88
    protected const ERROR_MESSAGE_PAYMENT_AUTHORIZATION = 'Payment provider is currently unavailable, please try again later.';
89
90
    /**
91
     * @var \SprykerTest\Zed\Payment\PaymentBusinessTester
92
     */
93
    protected PaymentBusinessTester $tester;
94
95
    /**
96
     * @var \Spryker\Zed\Payment\Business\PaymentFacadeInterface|\Spryker\Zed\Kernel\Business\AbstractFacade
97
     */
98
    protected $paymentFacade;
99
100
    /**
101
     * @return void
102
     */
103
    protected function setUp(): void
104
    {
105
        parent::setUp();
106
107
        $this->tester->ensurePaymentProviderTableIsEmpty();
108
109
        $this->paymentFacade = $this->tester->getFacade();
110
        $configMock = $this->createMock(PaymentConfig::class);
111
        $configMock->method('getPaymentStatemachineMappings')->willReturn([]);
112
        $paymentBusinessFactory = new PaymentBusinessFactory();
113
        $paymentBusinessFactory->setConfig($configMock);
114
        $this->paymentFacade->setFactory($paymentBusinessFactory);
0 ignored issues
show
The method setFactory() does not exist on Spryker\Zed\Payment\Busi...\PaymentFacadeInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Spryker\Zed\Payment\Busi...\PaymentFacadeInterface. ( Ignorable by Annotation )

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

114
        $this->paymentFacade->/** @scrutinizer ignore-call */ 
115
                              setFactory($paymentBusinessFactory);
Loading history...
115
116
        $this->tester->setStoreReferenceData([
117
            'DE' => 'dev-DE',
118
            'AT' => 'dev-AT',
119
        ]);
120
    }
121
122
    /**
123
     * @return void
124
     */
125
    protected function tearDown(): void
126
    {
127
        parent::tearDown();
128
129
        $this->tester->ensurePaymentProviderTableIsEmpty();
130
    }
131
132
    /**
133
     * @return void
134
     */
135
    public function testFindPaymentMethodByIdShouldFindPaymentMethod(): void
136
    {
137
        // Arrange
138
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
139
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
140
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
141
        ]);
142
143
        // Act
144
        $paymentMethodResponseTransfer = $this->paymentFacade->findPaymentMethodById($paymentMethodTransfer->getIdPaymentMethod());
0 ignored issues
show
The method findPaymentMethodById() does not exist on Spryker\Zed\Kernel\Business\AbstractFacade. It seems like you code against a sub-type of Spryker\Zed\Kernel\Business\AbstractFacade such as Spryker\Zed\Payment\Business\PaymentFacade. ( Ignorable by Annotation )

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

144
        /** @scrutinizer ignore-call */ 
145
        $paymentMethodResponseTransfer = $this->paymentFacade->findPaymentMethodById($paymentMethodTransfer->getIdPaymentMethod());
Loading history...
145
146
        // Assert
147
        $this->assertTrue($paymentMethodResponseTransfer->getIsSuccessful(), 'Payment method should be found');
148
        $this->assertNotNull($paymentMethodResponseTransfer->getPaymentMethod(), 'Payment method should not be empty');
149
    }
150
151
    /**
152
     * @return void
153
     */
154
    public function testFindPaymentMethodByIdWithNotExistingIdShouldNotFindPaymentMethod(): void
155
    {
156
        // Act
157
        $paymentMethodResponseTransfer = $this->paymentFacade->findPaymentMethodById(1);
158
159
        // Assert
160
        $this->assertFalse($paymentMethodResponseTransfer->getIsSuccessful(), 'Payment method should not be found');
161
    }
162
163
    /**
164
     * @return void
165
     */
166
    public function testUpdatePaymentMethodShouldUpdatePaymentMethodWithStoreRelation(): void
167
    {
168
        // Arrange
169
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
170
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
171
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => 'test',
172
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
173
        ]);
174
        $storeTransfer = $this->tester->haveStore([
175
            StoreTransfer::NAME => 'DE',
176
        ]);
177
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
178
            StoreRelationTransfer::ID_ENTITY => $paymentMethodTransfer->getIdPaymentMethod(),
179
            StoreRelationTransfer::ID_STORES => [
180
                $storeTransfer->getIdStore(),
181
            ],
182
            StoreRelationTransfer::STORES => [
183
                $storeTransfer,
184
            ],
185
        ])->build();
186
        $paymentMethodTransfer->setStoreRelation($storeRelationTransfer);
187
        $paymentMethodTransfer->setPaymentMethodKey('test1');
188
189
        // Act
190
        $this->paymentFacade->updatePaymentMethod($paymentMethodTransfer);
0 ignored issues
show
The method updatePaymentMethod() does not exist on Spryker\Zed\Kernel\Business\AbstractFacade. It seems like you code against a sub-type of Spryker\Zed\Kernel\Business\AbstractFacade such as Spryker\Zed\Payment\Business\PaymentFacade. ( Ignorable by Annotation )

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

190
        $this->paymentFacade->/** @scrutinizer ignore-call */ 
191
                              updatePaymentMethod($paymentMethodTransfer);
Loading history...
191
192
        // Assert
193
        $resultPaymentMethodEntity = SpyPaymentMethodQuery::create()
194
            ->filterByIdPaymentMethod($paymentMethodTransfer->getIdPaymentMethod())
195
            ->findOne();
196
197
        $this->assertSame(
198
            'test1',
199
            $resultPaymentMethodEntity->getPaymentMethodKey(),
200
            'Payment method name should match to the expected value',
201
        );
202
    }
203
204
    /**
205
     * @return void
206
     */
207
    public function testGetAvailablePaymentMethodsShouldReturnActivePaymentMethod(): void
208
    {
209
        // Arrange
210
        $paymentProviderTransfer = $this->tester->havePaymentProvider([
211
            PaymentProviderTransfer::PAYMENT_PROVIDER_KEY => 'dummyPayment',
212
        ]);
213
        $storeTransfer = $this->tester->haveStore([
214
            StoreTransfer::NAME => 'DE',
215
        ]);
216
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
217
            StoreRelationTransfer::ID_STORES => [
218
                $storeTransfer->getIdStore(),
219
            ],
220
            StoreRelationTransfer::STORES => [
221
                $storeTransfer,
222
            ],
223
        ])->build();
224
        $this->tester->havePaymentMethod([
225
            PaymentMethodTransfer::IS_ACTIVE => true,
226
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => 'dummyPaymentInvoice',
227
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
228
            PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer,
229
        ]);
230
        $this->tester->havePaymentMethod([
231
            PaymentMethodTransfer::IS_ACTIVE => false,
232
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => 'dummyPaymentCreditCard',
233
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
234
        ]);
235
        $quoteTransfer = (new QuoteBuilder())->withStore([
236
            StoreTransfer::NAME => $storeTransfer->getName(),
237
        ])->build();
238
239
        // Act
240
        $paymentMethodsTransfer = $this->paymentFacade->getAvailableMethods($quoteTransfer);
0 ignored issues
show
The method getAvailableMethods() does not exist on Spryker\Zed\Kernel\Business\AbstractFacade. It seems like you code against a sub-type of Spryker\Zed\Kernel\Business\AbstractFacade such as Spryker\Zed\Payment\Business\PaymentFacade. ( Ignorable by Annotation )

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

240
        /** @scrutinizer ignore-call */ 
241
        $paymentMethodsTransfer = $this->paymentFacade->getAvailableMethods($quoteTransfer);
Loading history...
241
242
        // Assert
243
        $this->assertCount(
244
            1,
245
            $paymentMethodsTransfer->getMethods(),
246
            'Amount of found payment method does not match to the expected value',
247
        );
248
    }
249
250
    /**
251
     * @return void
252
     */
253
    public function testGetAvailablePaymentMethodsShouldCollectPersistentAndInfrastructuralPaymentMethods(): void
254
    {
255
        $paymentProviderTransfer = $this->tester->havePaymentProvider([
256
            PaymentProviderTransfer::PAYMENT_PROVIDER_KEY => 'dummyPayment',
257
        ]);
258
        $storeTransfer = $this->tester->haveStore([
259
            StoreTransfer::NAME => 'DE',
260
        ]);
261
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
262
            StoreRelationTransfer::ID_STORES => [
263
                $storeTransfer->getIdStore(),
264
            ],
265
            StoreRelationTransfer::STORES => [
266
                $storeTransfer,
267
            ],
268
        ])->build();
269
        $this->tester->havePaymentMethod([
270
            PaymentMethodTransfer::IS_ACTIVE => true,
271
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => 'dummyPaymentInvoice',
272
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
273
            PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer,
274
        ]);
275
        $this->tester->havePaymentMethod([
276
            PaymentMethodTransfer::IS_ACTIVE => false,
277
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => 'dummyPaymentCreditCard',
278
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
279
            PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer,
280
        ]);
281
        $this->tester->havePaymentMethod([
282
            PaymentMethodTransfer::IS_ACTIVE => true,
283
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => 'dummyPaymentTest',
284
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
285
            PaymentMethodTransfer::STORE_RELATION => null,
286
        ]);
287
        $configMock = $this->createMock(PaymentConfig::class);
288
        $configMock->method('getPaymentStatemachineMappings')->willReturn([
289
            'dummyPaymentInvoice' => 'statemachine1',
290
            'dummyPaymentCreditCard' => 'statemachine2',
291
            'dummyPaymentTest' => 'statemachine3',
292
            'not_in_db' => 'statemachine4',
293
        ]);
294
295
        $factory = new PaymentBusinessFactory();
296
        $factory->setConfig($configMock);
297
        $this->paymentFacade->setFactory($factory);
298
        $quoteTransfer = (new QuoteBuilder())->withStore([
299
            StoreTransfer::NAME => $storeTransfer->getName(),
300
        ])->build();
301
302
        // Act
303
        $paymentMethodsTransfer = $this->paymentFacade->getAvailableMethods($quoteTransfer);
304
305
        $this->assertCount(
306
            2,
307
            $paymentMethodsTransfer->getMethods(),
308
            'Amount of found payment method does not match to the expected value',
309
        );
310
    }
311
312
    /**
313
     * @return void
314
     */
315
    public function testGetAvailablePaymentProvidersForStoreShouldReturnActivePaymentProviderForGivenStore(): void
316
    {
317
        // Arrange
318
        $storeTransfer = $this->tester->haveStore([
319
            StoreTransfer::NAME => 'DE',
320
        ]);
321
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
322
            StoreRelationTransfer::ID_STORES => [$storeTransfer->getIdStore()],
323
        ])->build();
324
        $paymentProviderOne = $this->tester->havePaymentProvider();
325
        $paymentProviderTwo = $this->tester->havePaymentProvider();
326
        $this->tester->havePaymentMethod([
327
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderOne->getIdPaymentProvider(),
328
            PaymentMethodTransfer::IS_ACTIVE => true,
329
            PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer,
330
            PaymentMethodTransfer::NAME => 'test1',
331
        ]);
332
        $this->tester->havePaymentMethod([
333
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderOne->getIdPaymentProvider(),
334
            PaymentMethodTransfer::IS_ACTIVE => false,
335
            PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer,
336
            PaymentMethodTransfer::NAME => 'test2',
337
        ]);
338
        $this->tester->havePaymentMethod([
339
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderOne->getIdPaymentProvider(),
340
            PaymentMethodTransfer::IS_ACTIVE => true,
341
            PaymentMethodTransfer::STORE_RELATION => null,
342
            PaymentMethodTransfer::NAME => 'test3',
343
        ]);
344
        $this->tester->havePaymentMethod([
345
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTwo->getIdPaymentProvider(),
346
            PaymentMethodTransfer::IS_ACTIVE => true,
347
            PaymentMethodTransfer::NAME => 'test4',
348
        ]);
349
350
        // Act
351
        $paymentProviderCollectionTransfer = $this->paymentFacade->getAvailablePaymentProvidersForStore('DE');
0 ignored issues
show
The method getAvailablePaymentProvidersForStore() does not exist on Spryker\Zed\Kernel\Business\AbstractFacade. It seems like you code against a sub-type of Spryker\Zed\Kernel\Business\AbstractFacade such as Spryker\Zed\Payment\Business\PaymentFacade. ( Ignorable by Annotation )

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

351
        /** @scrutinizer ignore-call */ 
352
        $paymentProviderCollectionTransfer = $this->paymentFacade->getAvailablePaymentProvidersForStore('DE');
Loading history...
352
353
        // Assert
354
        $this->assertCount(
355
            1,
356
            $paymentProviderCollectionTransfer->getPaymentProviders(),
357
            'Amount of payment providers does not match the expected value',
358
        );
359
        $paymentMethods = $paymentProviderCollectionTransfer->getPaymentProviders()[0]->getPaymentMethods();
360
        $this->assertCount(
361
            1,
362
            $paymentMethods,
363
            'Amount of payment methods does not match the expected value',
364
        );
365
    }
366
367
    /**
368
     * @return void
369
     */
370
    public function testIsQuotePaymentMethodValidShouldReturnTrueIfPaymentExists(): void
371
    {
372
        // Arrange
373
        $quoteTransfer = (new QuoteBuilder())
374
            ->withPayment(['payment_selection' => 'dummyPaymentInvoice'])
375
            ->build();
376
        $checkoutResponseTransfer = (new CheckoutResponseBuilder())->build();
377
        $this->mockPaymentMethodReader();
378
379
        // Act
380
        $isPaymentMethodExists = $this->paymentFacade->isQuotePaymentMethodValid($quoteTransfer, $checkoutResponseTransfer);
381
382
        // Assert
383
        $this->assertTrue($isPaymentMethodExists);
384
    }
385
386
    /**
387
     * @return void
388
     */
389
    public function testIsQuotePaymentMethodValidShouldReturnFalseIfPaymentNotExists(): void
390
    {
391
        // Arrange
392
        $quoteTransfer = (new QuoteBuilder())
393
            ->withPayment(['payment_selection' => 'NotExists'])
394
            ->build();
395
        $checkoutResponseTransfer = (new CheckoutResponseBuilder())->build();
396
        $this->mockPaymentMethodReader();
397
398
        // Act
399
        $isPaymentMethodExists = $this->paymentFacade->isQuotePaymentMethodValid($quoteTransfer, $checkoutResponseTransfer);
400
401
        // Assert
402
        $this->assertFalse($isPaymentMethodExists);
403
    }
404
405
    /**
406
     * @return void
407
     */
408
    public function testCreatePaymentProvider(): void
409
    {
410
        // Arrange
411
        $paymentProviderTransfer = (new PaymentProviderBuilder())->build();
412
        $storeTransfer = $this->tester->haveStore([
413
            StoreTransfer::NAME => 'DE',
414
        ]);
415
416
        $paymentMethodTransfer = (new PaymentMethodBuilder())->build();
417
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
418
            StoreRelationTransfer::ID_ENTITY => $paymentMethodTransfer->getIdPaymentMethod(),
419
            StoreRelationTransfer::ID_STORES => [
420
                $storeTransfer->getIdStore(),
421
            ],
422
            StoreRelationTransfer::STORES => [
423
                $storeTransfer,
424
            ],
425
        ])->build();
426
        $paymentMethodTransfer->setStoreRelation($storeRelationTransfer);
427
        $paymentProviderTransfer->addPaymentMethod($paymentMethodTransfer);
428
429
        // Act
430
        $paymentProviderResponseTransfer = $this->paymentFacade->createPaymentProvider($paymentProviderTransfer);
431
432
        // Assert
433
        $this->assertTrue($paymentProviderResponseTransfer->getIsSuccessful());
434
        $this->assertNotEmpty($paymentProviderResponseTransfer->getPaymentProvider()->getIdPaymentProvider());
435
    }
436
437
    /**
438
     * @return void
439
     */
440
    public function testCreatePaymentMethod(): void
441
    {
442
        // Arrange
443
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
444
        $storeTransfer = $this->tester->haveStore([
445
            StoreTransfer::NAME => 'DE',
446
        ]);
447
448
        $paymentMethodTransfer = (new PaymentMethodBuilder())
449
            ->seed([PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider()])
450
            ->build();
451
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
452
            StoreRelationTransfer::ID_ENTITY => $paymentMethodTransfer->getIdPaymentMethod(),
453
            StoreRelationTransfer::ID_STORES => [
454
                $storeTransfer->getIdStore(),
455
            ],
456
            StoreRelationTransfer::STORES => [
457
                $storeTransfer,
458
            ],
459
        ])->build();
460
        $paymentMethodTransfer->setStoreRelation($storeRelationTransfer);
461
462
        // Act
463
        $paymentMethodResponseTransfer = $this->paymentFacade->createPaymentMethod($paymentMethodTransfer);
464
465
        // Assert
466
        $this->assertTrue($paymentMethodResponseTransfer->getIsSuccessful());
467
        $this->assertNotEmpty($paymentMethodResponseTransfer->getPaymentMethod()->getIdPaymentMethod());
468
    }
469
470
    /**
471
     * @return void
472
     */
473
    public function testDeactivatePaymentMethod(): void
474
    {
475
        // Arrange
476
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
477
        $storeTransfer = $this->tester->haveStore([
478
            StoreTransfer::NAME => 'DE',
479
        ]);
480
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
481
            StoreRelationTransfer::ID_STORES => [
482
                $storeTransfer->getIdStore(),
483
            ],
484
            StoreRelationTransfer::STORES => [
485
                $storeTransfer,
486
            ],
487
        ])->build();
488
489
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
490
            PaymentMethodTransfer::IS_ACTIVE => true,
491
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => rand(),
492
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
493
            PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer,
494
        ]);
495
496
        // Act
497
        $paymentMethodResponseTransfer = $this->paymentFacade->deactivatePaymentMethod($paymentMethodTransfer);
498
499
        // Assert
500
        $this->assertTrue($paymentMethodResponseTransfer->getIsSuccessful());
501
        $this->assertFalse($paymentMethodResponseTransfer->getPaymentMethod()->getIsActive());
502
    }
503
504
    /**
505
     * @return void
506
     */
507
    public function testActivatePaymentMethod(): void
508
    {
509
        // Arrange
510
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
511
        $storeTransfer = $this->tester->haveStore([
512
            StoreTransfer::NAME => 'DE',
513
        ]);
514
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
515
            StoreRelationTransfer::ID_STORES => [
516
                $storeTransfer->getIdStore(),
517
            ],
518
            StoreRelationTransfer::STORES => [
519
                $storeTransfer,
520
            ],
521
        ])->build();
522
523
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
524
            PaymentMethodTransfer::IS_ACTIVE => false,
525
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
526
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => rand(),
527
            PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer,
528
        ]);
529
530
        // Act
531
        $paymentMethodResponseTransfer = $this->paymentFacade->activatePaymentMethod($paymentMethodTransfer);
532
533
        // Assert
534
        $this->assertTrue($paymentMethodResponseTransfer->getIsSuccessful());
535
        $this->assertTrue($paymentMethodResponseTransfer->getPaymentMethod()->getIsActive());
536
    }
537
538
    /**
539
     * @return void
540
     */
541
    public function testForeignPaymentInitializePaymentReceivesCorrectResponseAndUsingItAddsRedirectUrlWithCorrectData(): void
542
    {
543
        // Arrange
544
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
545
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
546
            PaymentMethodTransfer::IS_HIDDEN => false,
547
            PaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => static::PAYMENT_AUTHORIZATION_ENDPOINT,
548
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
549
        ]);
550
551
        $paymentTransfer = (new PaymentTransfer())->setPaymentSelection(
552
            sprintf('%s[%s]', PaymentTransfer::FOREIGN_PAYMENTS, $paymentMethodTransfer->getPaymentMethodKey()),
553
        );
554
555
        $quoteTransfer = $this->buildQuoteTransfer();
556
        $quoteTransfer->setPayment($paymentTransfer);
557
        $checkoutResponseTransfer = $this->buildCheckoutResponseTransfer();
558
559
        $kernelAppFacadeMock = $this->getMockBuilder(KernelAppFacadeInterface::class)->getMock();
560
561
        $kernelAppFacadeMock->expects($this->once())
562
            ->method('makeRequest')
563
            ->with($this->callback(function (AcpHttpRequestTransfer $acpHttpRequestTransfer) {
564
                return $acpHttpRequestTransfer->getUri() === static::PAYMENT_AUTHORIZATION_ENDPOINT;
565
            }))
566
            ->willReturn(
567
                (new AcpHttpResponseTransfer())
568
                    ->setHttpStatusCode(Response::HTTP_OK)
569
                    ->setContent(json_encode(['redirectUrl' => static::PAYMENT_AUTHORIZATION_REDIRECT, 'isSuccessful' => true])),
570
            );
571
572
        $this->tester->setDependency(PaymentDependencyProvider::FACADE_KERNEL_APP, new PaymentToKernelAppFacadeBridge($kernelAppFacadeMock));
573
574
        // Act
575
        $this->tester->getFacade()->initForeignPaymentForCheckoutProcess($quoteTransfer, $checkoutResponseTransfer);
576
577
        // Assert
578
        $this->assertTrue($checkoutResponseTransfer->getIsExternalRedirect());
579
        $this->assertSame(static::PAYMENT_AUTHORIZATION_REDIRECT, $checkoutResponseTransfer->getRedirectUrl());
580
    }
581
582
    /**
583
     * @return void
584
     */
585
    public function testForeignPaymentInitializePaymentReceivesUnsuccessfulResponseWithDisabledDepugModeReturnsUserfriendlyMessage(): void
586
    {
587
        // Arrange
588
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
589
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
590
            PaymentMethodTransfer::IS_HIDDEN => false,
591
            PaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => static::PAYMENT_AUTHORIZATION_ENDPOINT,
592
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
593
        ]);
594
595
        $paymentTransfer = (new PaymentTransfer())->setPaymentSelection(
596
            sprintf('%s[%s]', PaymentTransfer::FOREIGN_PAYMENTS, $paymentMethodTransfer->getPaymentMethodKey()),
597
        );
598
        $this->tester->mockConfigMethod('isDebugEnabled', false);
599
600
        $quoteTransfer = $this->buildQuoteTransfer();
601
        $quoteTransfer->setPayment($paymentTransfer);
602
        $checkoutResponseTransfer = $this->buildCheckoutResponseTransfer();
603
604
        $kernelAppFacadeMock = $this->getMockBuilder(KernelAppFacadeInterface::class)->getMock();
605
606
        $kernelAppFacadeMock->expects($this->once())
607
            ->method('makeRequest')
608
            ->with($this->callback(function (AcpHttpRequestTransfer $acpHttpRequestTransfer) {
609
                return $acpHttpRequestTransfer->getUri() === static::PAYMENT_AUTHORIZATION_ENDPOINT;
610
            }))
611
            ->willReturn(
612
                (new AcpHttpResponseTransfer())
613
                    ->setHttpStatusCode(Response::HTTP_OK)
614
                    ->setContent(json_encode(['redirectUrl' => static::PAYMENT_AUTHORIZATION_REDIRECT, 'isSuccessful' => false])),
615
            );
616
617
        $this->tester->setDependency(PaymentDependencyProvider::FACADE_KERNEL_APP, new PaymentToKernelAppFacadeBridge($kernelAppFacadeMock));
618
619
        // Act
620
        $this->tester->getFacade()->initForeignPaymentForCheckoutProcess($quoteTransfer, $checkoutResponseTransfer);
621
622
        // Assert
623
        $this->assertFalse($checkoutResponseTransfer->getIsSuccess());
624
        $this->assertSame(static::ERROR_MESSAGE_PAYMENT_AUTHORIZATION, $checkoutResponseTransfer->getErrors()->getArrayCopy()[0]->getMessage());
625
    }
626
627
    /**
628
     * @return void
629
     */
630
    public function testForeignPaymentInitializePaymentReceivesUnsuccessfulResponseWithEnabledDebugModeReturnsExternalError(): void
631
    {
632
        // Arrange
633
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
634
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
635
            PaymentMethodTransfer::IS_HIDDEN => false,
636
            PaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => static::PAYMENT_AUTHORIZATION_ENDPOINT,
637
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
638
        ]);
639
640
        $paymentTransfer = (new PaymentTransfer())->setPaymentSelection(
641
            sprintf('%s[%s]', PaymentTransfer::FOREIGN_PAYMENTS, $paymentMethodTransfer->getPaymentMethodKey()),
642
        );
643
        $this->tester->mockConfigMethod('isDebugEnabled', true);
644
645
        $quoteTransfer = $this->buildQuoteTransfer();
646
        $quoteTransfer->setPayment($paymentTransfer);
647
        $checkoutResponseTransfer = $this->buildCheckoutResponseTransfer();
648
        $content = json_encode(['redirectUrl' => static::PAYMENT_AUTHORIZATION_REDIRECT, 'isSuccessful' => false]);
649
650
        $kernelAppFacadeMock = $this->getMockBuilder(KernelAppFacadeInterface::class)->getMock();
651
        $kernelAppFacadeMock->expects($this->once())
652
            ->method('makeRequest')
653
            ->with($this->callback(function (AcpHttpRequestTransfer $acpHttpRequestTransfer) {
654
                return $acpHttpRequestTransfer->getUri() === static::PAYMENT_AUTHORIZATION_ENDPOINT;
655
            }))
656
            ->willReturn(
657
                (new AcpHttpResponseTransfer())
658
                    ->setHttpStatusCode(Response::HTTP_OK)
659
                    ->setContent($content),
660
            );
661
662
        $this->tester->setDependency(PaymentDependencyProvider::FACADE_KERNEL_APP, new PaymentToKernelAppFacadeBridge($kernelAppFacadeMock));
663
664
        // Act
665
        $this->tester->getFacade()->initForeignPaymentForCheckoutProcess($quoteTransfer, $checkoutResponseTransfer);
666
667
        // Assert
668
        $this->assertFalse($checkoutResponseTransfer->getIsSuccess());
669
        $this->assertSame($content, $checkoutResponseTransfer->getErrors()->getArrayCopy()[0]->getMessage());
670
    }
671
672
    /**
673
     * @return void
674
     */
675
    public function testForeignPaymentAuthorizerForwardsAdditionPaymentDataToThePaymentServiceProviderApp(): void
676
    {
677
        // Arrange
678
        $this->tester->setStoreReferenceData([static::STORE_NAME => static::STORE_REFERENCE]);
679
680
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
681
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
682
            PaymentMethodTransfer::IS_HIDDEN => false,
683
            PaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => static::PAYMENT_AUTHORIZATION_ENDPOINT,
684
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
685
        ]);
686
687
        $paymentTransfer = (new PaymentTransfer())->setPaymentSelection(
688
            sprintf('%s[%s]', PaymentTransfer::FOREIGN_PAYMENTS, $paymentMethodTransfer->getPaymentMethodKey()),
689
        );
690
691
        $additionalPaymentData = [
692
            'internalId' => Uuid::uuid4()->toString(),
693
            'externalId' => Uuid::uuid4()->toString(),
694
        ];
695
696
        $paymentTransfer->setAdditionalPaymentData($additionalPaymentData);
697
698
        $quoteTransfer = $this->buildQuoteTransfer();
699
        $quoteTransfer->setPayment($paymentTransfer);
700
        $checkoutResponseTransfer = $this->buildCheckoutResponseTransfer();
701
702
        $forwardedAdditionPaymentData = [];
703
704
        $kernelAppFacadeMock = $this->getMockBuilder(KernelAppFacadeInterface::class)->getMock();
705
706
        $kernelAppFacadeMock->expects($this->once())
707
            ->method('makeRequest')
708
            ->with($this->callback(function (AcpHttpRequestTransfer $acpHttpRequestTransfer) use (&$forwardedAdditionPaymentData) {
709
                // This is what would be sent, we want to compare later.
710
                $decodedBody = json_decode($acpHttpRequestTransfer->getBody(), true);
711
                $forwardedAdditionPaymentData = $decodedBody['orderData'][PaymentTransfer::ADDITIONAL_PAYMENT_DATA];
712
713
                return $acpHttpRequestTransfer->getUri() === static::PAYMENT_AUTHORIZATION_ENDPOINT;
714
            }))
715
            ->willReturn(
716
                (new AcpHttpResponseTransfer())
717
                    ->setHttpStatusCode(Response::HTTP_OK)
718
                    ->setContent(json_encode(['redirectUrl' => static::PAYMENT_AUTHORIZATION_REDIRECT])),
719
            );
720
721
        $this->tester->setDependency(PaymentDependencyProvider::FACADE_KERNEL_APP, new PaymentToKernelAppFacadeBridge($kernelAppFacadeMock));
722
723
        // Act
724
        $this->tester->getFacade()->initForeignPaymentForCheckoutProcess($quoteTransfer, $checkoutResponseTransfer);
725
726
        // Assert
727
        $this->assertSame($forwardedAdditionPaymentData, $additionalPaymentData);
728
    }
729
730
    /**
731
     * @return void
732
     */
733
    public function testForeignPaymentAuthorizerDoesNothingWithIncorrectData(): void
734
    {
735
        // Arrange
736
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
737
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
738
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
739
        ]);
740
741
        $initialQuoteTransfer = $this->buildQuoteTransfer();
742
        $initialQuoteTransfer->setPayment(
743
            (new PaymentTransfer())->setPaymentSelection($paymentMethodTransfer->getPaymentMethodKey()),
744
        );
745
        $initialCheckoutResponseTransfer = $this->buildCheckoutResponseTransfer();
746
747
        $quoteTransfer = clone $initialQuoteTransfer;
748
        $checkoutResponseTransfer = clone $initialCheckoutResponseTransfer;
749
750
        // Act
751
        $this->tester->getFacade()->initForeignPaymentForCheckoutProcess($quoteTransfer, $checkoutResponseTransfer);
752
753
        // Assert
754
        $this->assertEquals($initialQuoteTransfer->toArray(), $quoteTransfer->toArray());
755
        $this->assertEquals($initialCheckoutResponseTransfer->toArray(), $checkoutResponseTransfer->toArray());
756
    }
757
758
    /**
759
     * @return void
760
     */
761
    public function testInitForeignPaymentForCheckoutProcessReturnsRedirectToRelativePaymentPageFromConfig(): void
762
    {
763
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
764
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
765
            PaymentMethodTransfer::IS_HIDDEN => false,
766
            PaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => static::PAYMENT_AUTHORIZATION_ENDPOINT,
767
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
768
        ]);
769
770
        $paymentTransfer = (new PaymentTransfer())->setPaymentSelection(
771
            sprintf('%s[%s]', PaymentTransfer::FOREIGN_PAYMENTS, $paymentMethodTransfer->getPaymentMethodKey()),
772
        );
773
774
        $quoteTransfer = $this->buildQuoteTransfer();
775
        $quoteTransfer->setPayment($paymentTransfer);
776
        $checkoutResponseTransfer = $this->buildCheckoutResponseTransfer();
777
778
        $kernelAppFacadeMock = $this->getMockBuilder(KernelAppFacadeInterface::class)->getMock();
779
780
        $kernelAppFacadeMock->expects($this->once())
781
            ->method('makeRequest')
782
            ->with($this->callback(function (AcpHttpRequestTransfer $acpHttpRequestTransfer) {
783
                return $acpHttpRequestTransfer->getUri() === static::PAYMENT_AUTHORIZATION_ENDPOINT;
784
            }))
785
            ->willReturn(
786
                (new AcpHttpResponseTransfer())
787
                    ->setHttpStatusCode(Response::HTTP_OK)
788
                    ->setContent(json_encode(['redirectUrl' => static::PAYMENT_AUTHORIZATION_REDIRECT, 'isSuccessful' => true])),
789
            );
790
791
        $this->tester->setDependency(PaymentDependencyProvider::FACADE_KERNEL_APP, new PaymentToKernelAppFacadeBridge($kernelAppFacadeMock));
792
793
        $this->tester->mockConfigMethod('getStoreFrontPaymentPage', '/my-custom-payment-page');
794
795
        // Act
796
        $this->tester->getFacade()->initForeignPaymentForCheckoutProcess($quoteTransfer, $checkoutResponseTransfer);
797
798
        // Assert
799
        $this->assertTrue($checkoutResponseTransfer->getIsExternalRedirect());
800
        $this->assertSame(
801
            '/my-custom-payment-page?' . http_build_query(['url' => base64_encode(static::PAYMENT_AUTHORIZATION_REDIRECT)]),
802
            $checkoutResponseTransfer->getRedirectUrl(),
803
        );
804
    }
805
806
    /**
807
     * @return void
808
     */
809
    public function testInitForeignPaymentForCheckoutProcessReturnsRedirectToAbsolutePaymentPageOnAnotherDomainFromConfig(): void
810
    {
811
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
812
        $paymentMethodTransfer = $this->tester->havePaymentMethod([
813
            PaymentMethodTransfer::IS_HIDDEN => false,
814
            PaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => static::PAYMENT_AUTHORIZATION_ENDPOINT,
815
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
816
        ]);
817
818
        $paymentTransfer = (new PaymentTransfer())->setPaymentSelection(
819
            sprintf('%s[%s]', PaymentTransfer::FOREIGN_PAYMENTS, $paymentMethodTransfer->getPaymentMethodKey()),
820
        );
821
822
        $quoteTransfer = $this->buildQuoteTransfer();
823
        $quoteTransfer->setPayment($paymentTransfer);
824
        $checkoutResponseTransfer = $this->buildCheckoutResponseTransfer();
825
826
        $kernelAppFacadeMock = $this->getMockBuilder(KernelAppFacadeInterface::class)->getMock();
827
828
        $kernelAppFacadeMock->expects($this->once())
829
            ->method('makeRequest')
830
            ->with($this->callback(function (AcpHttpRequestTransfer $acpHttpRequestTransfer) {
831
                return $acpHttpRequestTransfer->getUri() === static::PAYMENT_AUTHORIZATION_ENDPOINT;
832
            }))
833
            ->willReturn(
834
                (new AcpHttpResponseTransfer())
835
                    ->setHttpStatusCode(Response::HTTP_OK)
836
                    ->setContent(json_encode(['redirectUrl' => static::PAYMENT_AUTHORIZATION_REDIRECT, 'isSuccessful' => true])),
837
            );
838
839
        $this->tester->setDependency(PaymentDependencyProvider::FACADE_KERNEL_APP, new PaymentToKernelAppFacadeBridge($kernelAppFacadeMock));
840
841
        $this->tester->mockConfigMethod('getStoreFrontPaymentPage', 'https://my-custom-domain.com/payment?some=param');
842
843
        // Act
844
        $this->tester->getFacade()->initForeignPaymentForCheckoutProcess($quoteTransfer, $checkoutResponseTransfer);
845
846
        // Assert
847
        $this->assertTrue($checkoutResponseTransfer->getIsExternalRedirect());
848
        $this->assertSame(
849
            'https://my-custom-domain.com/payment?some=param&' . http_build_query(['url' => base64_encode(static::PAYMENT_AUTHORIZATION_REDIRECT)]),
850
            $checkoutResponseTransfer->getRedirectUrl(),
851
        );
852
    }
853
854
    /**
855
     * @return void
856
     */
857
    public function testEnablePaymentMethodReturnsSavedPaymentMethodTransferWithCorrectData(): void
858
    {
859
        // Arrange
860
        $this->tester->setStoreReferenceData([static::STORE_NAME => static::STORE_REFERENCE]);
861
862
        $addPaymentMethodTransfer = $this->tester->haveAddPaymentMethodTransfer([
863
            AddPaymentMethodTransfer::NAME => 'name-1',
864
            AddPaymentMethodTransfer::PROVIDER_NAME => 'provider-name-1',
865
            AddPaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => 'redirect-url',
866
        ], [
867
            MessageAttributesTransfer::STORE_REFERENCE => static::STORE_REFERENCE,
868
        ]);
869
870
        // Act
871
        $createdPaymentMethodTransfer = $this->tester->getFacade()
872
            ->enableForeignPaymentMethod($addPaymentMethodTransfer);
873
874
        $createdAddPaymentMethodTransfer = $this->tester->mapPaymentMethodTransferToAddPaymentMethodTransfer(
875
            $createdPaymentMethodTransfer,
876
            new AddPaymentMethodTransfer(),
877
        );
878
879
        // Assert
880
        $this->assertNotNull($createdPaymentMethodTransfer->getIdPaymentMethod());
881
        $this->assertNotNull($createdPaymentMethodTransfer->getIdPaymentProvider());
882
        $this->assertFalse($createdPaymentMethodTransfer->getIsHidden());
883
884
        $this->assertSame($addPaymentMethodTransfer->getName(), $createdAddPaymentMethodTransfer->getName());
885
        $this->assertSame($addPaymentMethodTransfer->getProviderName(), $createdAddPaymentMethodTransfer->getProviderName());
886
        $this->assertSame($addPaymentMethodTransfer->getPaymentAuthorizationEndpoint(), $createdAddPaymentMethodTransfer->getPaymentAuthorizationEndpoint());
887
    }
888
889
    /**
890
     * @return void
891
     */
892
    public function testAddPaymentMethodReturnsSavedPaymentMethodTransferWithCorrectData(): void
893
    {
894
        // Arrange
895
        $addPaymentMethodTransfer = $this->tester->haveAddPaymentMethodTransfer(
896
            [
897
                AddPaymentMethodTransfer::NAME => 'name-1',
898
                AddPaymentMethodTransfer::PROVIDER_NAME => 'provider-name-1',
899
                AddPaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => 'redirect-url',
900
            ],
901
            [],
902
        );
903
904
        // Act
905
        $createdPaymentMethodTransfer = $this->tester->getFacade()
906
            ->addPaymentMethod($addPaymentMethodTransfer);
907
908
        $createdAddPaymentMethodTransfer = $this->tester->mapPaymentMethodTransferToAddPaymentMethodTransfer(
909
            $createdPaymentMethodTransfer,
910
            new AddPaymentMethodTransfer(),
911
        );
912
913
        // Assert
914
        $this->assertNotNull($createdPaymentMethodTransfer->getIdPaymentMethod());
915
        $this->assertNotNull($createdPaymentMethodTransfer->getIdPaymentProvider());
916
        $this->assertFalse($createdPaymentMethodTransfer->getIsHidden());
917
918
        $this->assertSame($addPaymentMethodTransfer->getName(), $createdAddPaymentMethodTransfer->getName());
919
        $this->assertSame($addPaymentMethodTransfer->getProviderName(), $createdAddPaymentMethodTransfer->getProviderName());
920
        $this->assertSame($addPaymentMethodTransfer->getPaymentAuthorizationEndpoint(), $createdAddPaymentMethodTransfer->getPaymentAuthorizationEndpoint());
921
    }
922
923
    /**
924
     * Reflecting an Update of a PaymentMethod.
925
     *
926
     * @return void
927
     */
928
    public function testGivenThePaymentMethodAlreadyExistsAndIsActiveWhenTheAddPaymentMethodMessageIsHandledThenThePaymentMethodIsUpdatedAndIsStillActive(): void
929
    {
930
        // Arrange
931
        $paymentMethodName = 'MethodName' . Uuid::uuid4()->toString();
932
        $paymentProviderKey = 'ProviderKey' . Uuid::uuid4()->toString();
933
934
        $paymentProviderTransfer = $this->tester->havePaymentProvider([PaymentProviderTransfer::PAYMENT_PROVIDER_KEY => $paymentProviderKey]);
935
936
        $this->tester->havePaymentMethod([
937
            PaymentMethodTransfer::IS_ACTIVE => true,
938
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => (new PaymentFacade())->generatePaymentMethodKey($paymentProviderKey, $paymentMethodName),
939
            PaymentMethodTransfer::NAME => $paymentMethodName,
940
            PaymentMethodTransfer::PAYMENT_PROVIDER => $paymentProviderTransfer,
941
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
942
            PaymentMethodTransfer::IS_FOREIGN => true,
943
        ]);
944
945
        $addPaymentMethodTransfer = $this->tester->haveAddPaymentMethodTransfer(
946
            [
947
                AddPaymentMethodTransfer::NAME => $paymentMethodName,
948
                AddPaymentMethodTransfer::PROVIDER_NAME => $paymentProviderKey,
949
                AddPaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => 'redirect-url',
950
            ],
951
        );
952
953
        // Act
954
        $createdPaymentMethodTransfer = $this->tester->getFacade()->addPaymentMethod($addPaymentMethodTransfer);
955
956
        // Assert
957
        $this->assertNotNull($createdPaymentMethodTransfer->getIdPaymentMethod());
958
        $this->assertNotNull($createdPaymentMethodTransfer->getIdPaymentProvider());
959
        $this->assertFalse($createdPaymentMethodTransfer->getIsHidden(), 'Expected that the payment method is visible but it is hidden');
960
        $this->assertTrue($createdPaymentMethodTransfer->getIsActive(), 'Expected that the payment method is active but it is inactive');
961
    }
962
963
    /**
964
     * Reflecting an Update of a PaymentMethod.
965
     *
966
     * @return void
967
     */
968
    public function testGivenThePaymentMethodAlreadyExistsAndIsInactiveWhenTheAddPaymentMethodMessageIsHandledThenThePaymentMethodIsUpdatedAndIsStillInctive(): void
969
    {
970
        // Arrange
971
        $paymentMethodName = 'MethodName' . Uuid::uuid4()->toString();
972
        $paymentProviderKey = 'ProviderKey' . Uuid::uuid4()->toString();
973
974
        $paymentProviderTransfer = $this->tester->havePaymentProvider([PaymentProviderTransfer::PAYMENT_PROVIDER_KEY => $paymentProviderKey]);
975
976
        $this->tester->havePaymentMethod([
977
            PaymentMethodTransfer::IS_ACTIVE => false,
978
            PaymentMethodTransfer::PAYMENT_METHOD_KEY => (new PaymentFacade())->generatePaymentMethodKey($paymentProviderKey, $paymentMethodName),
979
            PaymentMethodTransfer::NAME => $paymentMethodName,
980
            PaymentMethodTransfer::PAYMENT_PROVIDER => $paymentProviderTransfer,
981
            PaymentMethodTransfer::ID_PAYMENT_PROVIDER => $paymentProviderTransfer->getIdPaymentProvider(),
982
            PaymentMethodTransfer::IS_FOREIGN => true,
983
        ]);
984
985
        $addPaymentMethodTransfer = $this->tester->haveAddPaymentMethodTransfer(
986
            [
987
                AddPaymentMethodTransfer::NAME => $paymentMethodName,
988
                AddPaymentMethodTransfer::PROVIDER_NAME => $paymentProviderKey,
989
                AddPaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => 'redirect-url',
990
            ],
991
        );
992
993
        // Act
994
        $createdPaymentMethodTransfer = $this->tester->getFacade()->addPaymentMethod($addPaymentMethodTransfer);
995
996
        // Assert
997
        $this->assertNotNull($createdPaymentMethodTransfer->getIdPaymentMethod());
998
        $this->assertNotNull($createdPaymentMethodTransfer->getIdPaymentProvider());
999
        $this->assertFalse($createdPaymentMethodTransfer->getIsHidden(), 'Expected that the payment method is visible but it is hidden');
1000
        $this->assertFalse($createdPaymentMethodTransfer->getIsActive(), 'Expected that the payment method is inactive but it is active');
1001
    }
1002
1003
    /**
1004
     * @return void
1005
     */
1006
    public function testDisableForeignPaymentMethodSetsPaymentMethodIsDeletedFlagToTrueWithCorrectData(): void
1007
    {
1008
        // Arrange
1009
        $storeTransfer = $this->tester->getStoreTransfer([
1010
            StoreTransfer::STORE_REFERENCE => static::STORE_REFERENCE,
1011
        ]);
1012
        $this->tester->setStoreReferenceData([static::STORE_NAME => static::STORE_REFERENCE]);
1013
1014
        $addPaymentMethodTransfer = $this->tester->haveAddPaymentMethodTransfer([
1015
            AddPaymentMethodTransfer::NAME => 'name-2',
1016
            AddPaymentMethodTransfer::PROVIDER_NAME => 'provider-name-2',
1017
            AddPaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => 'redirect-url',
1018
        ], [
1019
            MessageAttributesTransfer::STORE_REFERENCE => static::STORE_REFERENCE,
1020
        ]);
1021
1022
        // Act
1023
        $paymentMethodTransfer = $this->tester->getFacade()
1024
            ->enableForeignPaymentMethod($addPaymentMethodTransfer);
1025
1026
        $deletePaymentMethodTransfer = $this->tester->mapPaymentMethodTransferToDeletePaymentMethodTransfer(
1027
            $paymentMethodTransfer,
1028
            (new DeletePaymentMethodTransfer())
1029
                ->setMessageAttributes($addPaymentMethodTransfer->getMessageAttributes()),
1030
        );
1031
        $this->tester->getFacade()->disableForeignPaymentMethod($deletePaymentMethodTransfer);
1032
1033
        $filterPaymentMethodTransfer = (new PaymentMethodTransfer())
1034
            ->setIdPaymentMethod($paymentMethodTransfer->getIdPaymentMethod());
1035
        $updatedPaymentMethodTransfer = $this->tester->findPaymentMethod($filterPaymentMethodTransfer);
1036
1037
        // Assert
1038
        $this->assertSame($paymentMethodTransfer->getIdPaymentMethod(), $updatedPaymentMethodTransfer->getIdPaymentMethod());
1039
        $this->assertTrue($updatedPaymentMethodTransfer->getIsHidden());
1040
    }
1041
1042
    /**
1043
     * @return void
1044
     */
1045
    public function testDeletePaymentMethodSetsPaymentMethodIsDeletedFlagToTrueWithCorrectData(): void
1046
    {
1047
        // Arrange
1048
        $addPaymentMethodTransfer = $this->tester->haveAddPaymentMethodTransfer(
1049
            [
1050
                AddPaymentMethodTransfer::NAME => 'name-2',
1051
                AddPaymentMethodTransfer::PROVIDER_NAME => 'provider-name-2',
1052
                AddPaymentMethodTransfer::PAYMENT_AUTHORIZATION_ENDPOINT => 'redirect-url',
1053
            ],
1054
            [],
1055
        );
1056
1057
        // Act
1058
        $paymentMethodTransfer = $this->tester->getFacade()
1059
            ->addPaymentMethod($addPaymentMethodTransfer);
1060
1061
        $deletePaymentMethodTransfer = $this->tester->mapPaymentMethodTransferToDeletePaymentMethodTransfer(
1062
            $paymentMethodTransfer,
1063
            (new DeletePaymentMethodTransfer())
1064
                ->setMessageAttributes($addPaymentMethodTransfer->getMessageAttributes()),
1065
        );
1066
        $this->tester->getFacade()->deletePaymentMethod($deletePaymentMethodTransfer);
1067
1068
        $filterPaymentMethodTransfer = (new PaymentMethodTransfer())
1069
            ->setIdPaymentMethod($paymentMethodTransfer->getIdPaymentMethod());
1070
        $updatedPaymentMethodTransfer = $this->tester->findPaymentMethod($filterPaymentMethodTransfer);
1071
1072
        // Assert
1073
        $this->assertSame($paymentMethodTransfer->getIdPaymentMethod(), $updatedPaymentMethodTransfer->getIdPaymentMethod());
1074
        $this->assertTrue($updatedPaymentMethodTransfer->getIsHidden());
1075
    }
1076
1077
    /**
1078
     * When the `disableForeignPaymentMethod()` method is called and the Payment Method doesn't exist yet
1079
     * (disable message arrived before add message), it must be created and stored with `is_hidden=true` (soft deletion)
1080
     * so the add message can be handled without adding it after it got removed (Payment method gets updated and stays as soft deleted).
1081
     *
1082
     * @return void
1083
     */
1084
    public function testDisablePaymentMethodMessageCreatesPaymentMethodAndMarkItAsDeletedWhenThePaymentMethodDoesNotExistsBeforeTheDeleteMessageArrives(): void
1085
    {
1086
        // Arrange
1087
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithoutTimestamp();
1088
1089
        // Act
1090
        $this->tester->getFacade()->disableForeignPaymentMethod($deletePaymentMethodMessage);
1091
1092
        // Assert
1093
        $this->tester->assertDisabledPaymentMethodWasCreatedWithSoftDeletion(
1094
            $deletePaymentMethodMessage,
1095
        );
1096
    }
1097
1098
    /**
1099
     * When the `deletePaymentMethod()` method is called and the Payment Method doesn't exist yet
1100
     * (disable message arrived before add message), it must be created and stored with `is_hidden=true` (soft deletion)
1101
     * so the add message can be handled without adding it after it got removed (Payment method gets updated and stays as soft deleted).
1102
     *
1103
     * @return void
1104
     */
1105
    public function testDeletePaymentMethodMessageCreatesPaymentMethodAndMarkItAsDeletedWhenThePaymentMethodDoesNotExistsBeforeTheDeleteMessageArrives(): void
1106
    {
1107
        // Arrange
1108
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithoutTimestamp();
1109
1110
        // Act
1111
        $this->tester->getFacade()->deletePaymentMethod($deletePaymentMethodMessage);
1112
1113
        // Assert
1114
        $this->tester->assertDisabledPaymentMethodWasCreatedWithSoftDeletion(
1115
            $deletePaymentMethodMessage,
1116
            false,
1117
        );
1118
    }
1119
1120
    /**
1121
     * If the `AddPaymentMethodTransfer` comes from a message when `enableForeignPaymentMethod()` is called
1122
     * it must compare its timestamp with the last message timestamp stored on the existing payment method record.
1123
     * If the last message timestamp stored on the existing payment method record is newer the method must not do any change.
1124
     *
1125
     * @return void
1126
     */
1127
    public function testAddPaymentMethodMessageShouldNotChangeDeletedStateOfPaymentMethodWhenDeletePaymentMethodMessageWasSentAfterAddPaymentMethodMessage(): void
1128
    {
1129
        // Arrange
1130
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1131
        $addPaymentMethodMessage = $this->tester->haveAddPaymentMethodTransferWithTimestamp(
1132
            $paymentProviderTransfer,
1133
            $this->generateNowTimestamp(),
1134
        );
1135
        $disabledPaymentMethod = $this->tester->createDisabledPaymentMethodWithTimestampOnDatabase(
1136
            $paymentProviderTransfer,
1137
            $this->generateNowTimestamp(),
1138
        );
1139
1140
        // Act
1141
        $this->tester->getFacade()->enableForeignPaymentMethod($addPaymentMethodMessage);
1142
1143
        // Assert
1144
        $this->tester->assertDisabledPaymentMethodDidNotChange($disabledPaymentMethod);
1145
    }
1146
1147
    /**
1148
     * If the `AddPaymentMethodTransfer` comes from a message when `enableForeignPaymentMethod()` is called
1149
     * it must compare its timestamp with the last message timestamp stored on the existing payment method record.
1150
     * If the last message timestamp stored on the existing payment method record is newer the method must not do any change.
1151
     *
1152
     * @return void
1153
     */
1154
    public function testAddPaymentMethodMessageShouldNotChangeStateOfPaymentMethodWhenDeletePaymentMethodMessageWasSentAfterAddPaymentMethodMessage(): void
1155
    {
1156
        // Arrange
1157
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1158
        $addPaymentMethodMessage = $this->tester->haveAddPaymentMethodTransferWithTimestamp(
1159
            $paymentProviderTransfer,
1160
            $this->generateNowTimestamp(),
1161
        );
1162
        $disabledPaymentMethod = $this->tester->createDisabledPaymentMethodWithTimestampOnDatabase(
1163
            $paymentProviderTransfer,
1164
            $this->generateNowTimestamp(),
1165
        );
1166
1167
        // Act
1168
        $this->tester->getFacade()->addPaymentMethod($addPaymentMethodMessage);
1169
1170
        // Assert
1171
        $this->tester->assertDisabledPaymentMethodDidNotChange($disabledPaymentMethod);
1172
    }
1173
1174
    /**
1175
     * If the last message timestamp is null when `enableForeignPaymentMethod()` is called it should always
1176
     * proceed with the change and update the timestamp.
1177
     *
1178
     * @return void
1179
     */
1180
    public function testEnableForeignPaymentMethodShouldChangeDeletedStateOfPaymentMethodWhenPaymentMethodsLastMessageTimestampIsNull(): void
1181
    {
1182
        // Arrange
1183
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1184
        $addPaymentMethodMessage = $this->tester->haveAddPaymentMethodTransferWithTimestamp(
1185
            $paymentProviderTransfer,
1186
            $this->generateNowTimestamp(),
1187
        );
1188
        $disabledPaymentMethod = $this->tester->createDisabledPaymentMethodWithoutTimestampOnDatabase($paymentProviderTransfer);
1189
1190
        // Act
1191
        $this->tester->getFacade()->enableForeignPaymentMethod($addPaymentMethodMessage);
1192
1193
        // Assert
1194
        $this->tester->assertDisabledPaymentMethodWasEnabledAndTimestampChanged(
1195
            $disabledPaymentMethod,
1196
            $addPaymentMethodMessage,
1197
        );
1198
    }
1199
1200
    /**
1201
     * If the last message timestamp is null when `addPaymentMethod()` is called it should always
1202
     * proceed with the change and update the timestamp.
1203
     *
1204
     * @return void
1205
     */
1206
    public function testAddPaymentMethodShouldChangeDeletedStateOfPaymentMethodWhenPaymentMethodsLastMessageTimestampIsNull(): void
1207
    {
1208
        // Arrange
1209
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1210
        $addPaymentMethodMessage = $this->tester->haveAddPaymentMethodTransferWithTimestamp(
1211
            $paymentProviderTransfer,
1212
            $this->generateNowTimestamp(),
1213
        );
1214
        $disabledPaymentMethod = $this->tester->createDisabledPaymentMethodWithoutTimestampOnDatabase(
1215
            $paymentProviderTransfer,
1216
            false,
1217
        );
1218
1219
        // Act
1220
        $this->tester->getFacade()->addPaymentMethod($addPaymentMethodMessage);
1221
1222
        // Assert
1223
        $this->tester->assertDisabledPaymentMethodWasEnabledAndTimestampChanged(
1224
            $disabledPaymentMethod,
1225
            $addPaymentMethodMessage,
1226
        );
1227
    }
1228
1229
    /**
1230
     * If `AddPaymentMethodTransfer` doesn't come from a message it likely will not have a timestamp and this can not
1231
     * avoid the process to keep on running and the change must happen, and the timestamp must be updated.
1232
     *
1233
     * @return void
1234
     */
1235
    public function testEnabledForeignPaymentMethodShouldChangeDeletedStateOfPaymentMethodWhenAddPaymentMethodTransferDoNotComeFromAMessageAndItsTimestampIsNull(): void
1236
    {
1237
        // Arrange
1238
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1239
        $addPaymentMethodMessage = $this->tester->haveAddPaymentMethodTransferWithoutTimestamp($paymentProviderTransfer);
1240
        $disabledPaymentMethod = $this->tester->createDisabledPaymentMethodWithTimestampOnDatabase(
1241
            $paymentProviderTransfer,
1242
            $this->generateNowTimestamp(),
1243
        );
1244
1245
        // Act
1246
        $this->tester->getFacade()->enableForeignPaymentMethod($addPaymentMethodMessage);
1247
1248
        // Assert
1249
        $this->tester->assertDisabledPaymentMethodWasEnabledAndTimestampWasUpdated(
1250
            $disabledPaymentMethod,
1251
        );
1252
    }
1253
1254
    /**
1255
     * If `AddPaymentMethodTransfer` doesn't come from a message it likely will not have a timestamp and this can not
1256
     * avoid the process to keep on running and the change must happen, and the timestamp must be updated.
1257
     *
1258
     * @return void
1259
     */
1260
    public function testEnabledForeignPaymentMethodShouldModifyStateOfPaymentMethodWhenAddPaymentMethodTransferDoNotComeFromAMessageAndItsTimestampIsNull(): void
1261
    {
1262
        // Arrange
1263
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1264
        $addPaymentMethodMessage = $this->tester->haveAddPaymentMethodTransferWithoutTimestamp($paymentProviderTransfer);
1265
        $disabledPaymentMethod = $this->tester->createDisabledPaymentMethodWithTimestampOnDatabase(
1266
            $paymentProviderTransfer,
1267
            $this->generateNowTimestamp(),
1268
            false,
1269
        );
1270
1271
        // Act
1272
        $this->tester->getFacade()->addPaymentMethod($addPaymentMethodMessage);
1273
1274
        // Assert
1275
        $this->tester->assertDisabledPaymentMethodWasEnabledAndTimestampWasUpdated(
1276
            $disabledPaymentMethod,
1277
        );
1278
    }
1279
1280
    /**
1281
     * If the `DeletePaymentMethodTransfer` comes from a message when `disableForeignPaymentMethod()` is called
1282
     * it must compare its timestamp with the last message timestamp stored on the existing payment method record.
1283
     * If the last message timestamp stored on the existing payment method record is newer the method must not do any change.
1284
     *
1285
     * @return void
1286
     */
1287
    public function testDisableForeignPaymentMethodShouldNotChangeEnabledStateOfPaymentMethodIfLastMessageTimestampIsOlderThanDeletePaymentMethodTransferTimestamp(): void
1288
    {
1289
        // Arrange
1290
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1291
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithTimestamp(
1292
            $paymentProviderTransfer,
1293
            $this->generateNowTimestamp(),
1294
        );
1295
        $enabledPaymentMethod = $this->tester->createEnabledPaymentMethodWithTimestampOnDatabase(
1296
            $paymentProviderTransfer,
1297
            $this->generateNowTimestamp(),
1298
        );
1299
1300
        // Act
1301
        $this->tester->getFacade()->disableForeignPaymentMethod($deletePaymentMethodMessage);
1302
1303
        // Assert
1304
        $this->tester->assertEnabledPaymentMethodDidNotChange($enabledPaymentMethod);
1305
    }
1306
1307
    /**
1308
     * If the `DeletePaymentMethodTransfer` comes from a message when `deletePaymentMethod()` is called
1309
     * it must compare its timestamp with the last message timestamp stored on the existing payment method record.
1310
     * If the last message timestamp stored on the existing payment method record is newer the method must not do any change.
1311
     *
1312
     * @return void
1313
     */
1314
    public function testDeletePaymentMethodShouldNotChangeEnabledStateOfPaymentMethodIfLastMessageTimestampIsOlderThanDeletePaymentMethodTransferTimestamp(): void
1315
    {
1316
        // Arrange
1317
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1318
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithTimestamp(
1319
            $paymentProviderTransfer,
1320
            $this->generateNowTimestamp(),
1321
        );
1322
        $enabledPaymentMethod = $this->tester->createEnabledPaymentMethodWithTimestampOnDatabase(
1323
            $paymentProviderTransfer,
1324
            $this->generateNowTimestamp(),
1325
            false,
1326
        );
1327
1328
        // Act
1329
        $this->tester->getFacade()->deletePaymentMethod($deletePaymentMethodMessage);
1330
1331
        // Assert
1332
        $this->tester->assertEnabledPaymentMethodDidNotChange($enabledPaymentMethod);
1333
    }
1334
1335
    /**
1336
     * If the last message timestamp is null when `disableForeignPaymentMethod()` is called it should always
1337
     * proceed with the change and update the timestamp.
1338
     *
1339
     * @return void
1340
     */
1341
    public function testDisableForeignPaymentMethodShouldChangeEnabledStateOfPaymentMethodWhenPaymentMethodsLastMessageTimestampIsNull(): void
1342
    {
1343
        // Arrange
1344
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1345
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithTimestamp(
1346
            $paymentProviderTransfer,
1347
            $this->generateNowTimestamp(),
1348
        );
1349
        $enabledPaymentMethod = $this->tester->createEnabledPaymentMethodWithoutTimestampOnDatabase($paymentProviderTransfer);
1350
1351
        // Act
1352
        $this->tester->getFacade()->disableForeignPaymentMethod($deletePaymentMethodMessage);
1353
1354
        // Assert
1355
        $this->tester->assertEnabledPaymentMethodWasDisabledAndTimestampChanged(
1356
            $enabledPaymentMethod,
1357
            $deletePaymentMethodMessage,
1358
        );
1359
    }
1360
1361
    /**
1362
     * If the last message timestamp is null when `deletePaymentMethod()` is called it should always
1363
     * proceed with the change and update the timestamp.
1364
     *
1365
     * @return void
1366
     */
1367
    public function testDeletePaymentMethodShouldChangeEnabledStateOfPaymentMethodWhenPaymentMethodsLastMessageTimestampIsNull(): void
1368
    {
1369
        // Arrange
1370
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1371
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithTimestamp(
1372
            $paymentProviderTransfer,
1373
            $this->generateNowTimestamp(),
1374
        );
1375
        $enabledPaymentMethod = $this->tester->createEnabledPaymentMethodWithoutTimestampOnDatabase(
1376
            $paymentProviderTransfer,
1377
            false,
1378
        );
1379
1380
        // Act
1381
        $this->tester->getFacade()->deletePaymentMethod($deletePaymentMethodMessage);
1382
1383
        // Assert
1384
        $this->tester->assertEnabledPaymentMethodWasDisabledAndTimestampChanged(
1385
            $enabledPaymentMethod,
1386
            $deletePaymentMethodMessage,
1387
        );
1388
    }
1389
1390
    /**
1391
     * If `DeletePaymentMethodTransfer` doesn't come from a message it likely will not have a timestamp and this can not
1392
     * avoid the process to keep up running and the change must happen, and the timestamp must be updated.
1393
     *
1394
     * @return void
1395
     */
1396
    public function testDisableForeignPaymentMethodShouldChangeEnabledStateOfPaymentMethodWhenDeletePaymentMethodTransferDoNotComeFromAMessageAndItsTimestampIsNull(): void
1397
    {
1398
        // Arrange
1399
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1400
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithoutTimestamp($paymentProviderTransfer);
1401
        $enabledPaymentMethod = $this->tester->createEnabledPaymentMethodWithTimestampOnDatabase(
1402
            $paymentProviderTransfer,
1403
            $this->generateNowTimestamp(),
1404
        );
1405
1406
        // Act
1407
        $this->tester->getFacade()->disableForeignPaymentMethod($deletePaymentMethodMessage);
1408
1409
        // Assert
1410
        $this->tester->assertEnabledPaymentMethodWasDisabledAndTimestampWasUpdated(
1411
            $enabledPaymentMethod,
1412
            $deletePaymentMethodMessage,
1413
        );
1414
    }
1415
1416
    /**
1417
     * If `DeletePaymentMethodTransfer` doesn't come from a message it likely will not have a timestamp and this can not
1418
     * avoid the process to keep up running and the change must happen, and the timestamp must be updated.
1419
     *
1420
     * @return void
1421
     */
1422
    public function testDeletePaymentMethodShouldChangeEnabledStateOfPaymentMethodWhenDeletePaymentMethodTransferDoNotComeFromAMessageAndItsTimestampIsNull(): void
1423
    {
1424
        // Arrange
1425
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1426
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithoutTimestamp($paymentProviderTransfer);
1427
        $enabledPaymentMethod = $this->tester->createEnabledPaymentMethodWithTimestampOnDatabase(
1428
            $paymentProviderTransfer,
1429
            $this->generateNowTimestamp(),
1430
            false,
1431
        );
1432
1433
        // Act
1434
        $this->tester->getFacade()->deletePaymentMethod($deletePaymentMethodMessage);
1435
1436
        // Assert
1437
        $this->tester->assertEnabledPaymentMethodWasDisabledAndTimestampWasUpdated(
1438
            $enabledPaymentMethod,
1439
            $deletePaymentMethodMessage,
1440
        );
1441
    }
1442
1443
    /**
1444
     * Tests if a new Payment Method will be created and the Payment Method that already
1445
     * exists will not be modified when PaymentMethodUpdater::disableForeignPaymentMethod() is called.
1446
     *
1447
     * This bug was reported on https://spryker.atlassian.net/browse/PBC-1674.
1448
     *
1449
     * @return void
1450
     */
1451
    public function testEnableForeignPaymentMethodMustChangeTheRightPaymentMethodWhenThereIsMoreThanOneMethodStored(): void
1452
    {
1453
        // Arrange
1454
        $existentPaymentMethod = $this->tester->createEnabledPaymentMethodWithoutTimestampOnDatabase(
1455
            $this->tester->havePaymentProvider(),
1456
        );
1457
1458
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1459
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithTimestamp(
1460
            $paymentProviderTransfer,
1461
            $this->generateNowTimestamp(),
1462
        );
1463
1464
        // Act
1465
        $this->tester->getFacade()->disableForeignPaymentMethod($deletePaymentMethodMessage);
1466
1467
        // Assert
1468
        $this->tester->assertRightPaymentMethodWasUpdated(
1469
            $existentPaymentMethod,
1470
            $deletePaymentMethodMessage->getProviderName(),
1471
        );
1472
    }
1473
1474
    /**
1475
     * Tests if a new Payment Method will be created and the Payment Method that already
1476
     * exists will not be modified when PaymentMethodUpdater::deletePaymentMethod() is called.
1477
     *
1478
     * This bug was reported on https://spryker.atlassian.net/browse/PBC-1674.
1479
     *
1480
     * @return void
1481
     */
1482
    public function testDeletePaymentMethodMustChangeTheRightPaymentMethodWhenThereIsMoreThanOneMethodStored(): void
1483
    {
1484
        // Arrange
1485
        $existentPaymentMethod = $this->tester->createEnabledPaymentMethodWithoutTimestampOnDatabase(
1486
            $this->tester->havePaymentProvider(),
1487
            false,
1488
        );
1489
1490
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1491
        $deletePaymentMethodMessage = $this->tester->haveDeletePaymentMethodTransferWithTimestamp(
1492
            $paymentProviderTransfer,
1493
            $this->generateNowTimestamp(),
1494
        );
1495
1496
        // Act
1497
        $this->tester->getFacade()->deletePaymentMethod($deletePaymentMethodMessage);
1498
1499
        // Assert
1500
        $this->tester->assertRightPaymentMethodWasUpdated(
1501
            $existentPaymentMethod,
1502
            $deletePaymentMethodMessage->getProviderName(),
1503
            false,
1504
        );
1505
    }
1506
1507
    /**
1508
     * Tests if a new Payment Method will be created and the Payment Method that already
1509
     * exists will not be modified when PaymentMethodUpdater::enableForeignPaymentMethod() is called.
1510
     *
1511
     * This bug was reported on https://spryker.atlassian.net/browse/PBC-1674.
1512
     *
1513
     * @return void
1514
     */
1515
    public function testDisableForeignPaymentMethodMustChangeTheRightPaymentMethodWhenThereIsMoreThanOneMethodStored(): void
1516
    {
1517
        // Arrange
1518
        $existentPaymentMethod = $this->tester->createDisabledPaymentMethodWithoutTimestampOnDatabase(
1519
            $this->tester->havePaymentProvider(),
1520
        );
1521
1522
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1523
        $addPaymentMethodMessage = $this->tester->haveAddPaymentMethodTransferWithTimestamp(
1524
            $paymentProviderTransfer,
1525
            $this->generateNowTimestamp(),
1526
        );
1527
1528
        // Act
1529
        $this->tester->getFacade()->enableForeignPaymentMethod($addPaymentMethodMessage);
1530
1531
        // Assert
1532
        $this->tester->assertRightPaymentMethodWasUpdated(
1533
            $existentPaymentMethod,
1534
            $addPaymentMethodMessage->getProviderName(),
1535
        );
1536
    }
1537
1538
    /**
1539
     * Tests if a new Payment Method will be created and the Payment Method that already
1540
     * exists will not be modified when PaymentMethodUpdater::addPaymentMethod() is called.
1541
     *
1542
     * This bug was reported on https://spryker.atlassian.net/browse/PBC-1674.
1543
     *
1544
     * @return void
1545
     */
1546
    public function testDisableForeignPaymentMethodMustModifyTheRightPaymentMethodWhenThereIsMoreThanOneMethodStored(): void
1547
    {
1548
        // Arrange
1549
        $existentPaymentMethod = $this->tester->createDisabledPaymentMethodWithoutTimestampOnDatabase(
1550
            $this->tester->havePaymentProvider(),
1551
            false,
1552
        );
1553
1554
        $paymentProviderTransfer = $this->tester->havePaymentProvider();
1555
        $addPaymentMethodMessage = $this->tester->haveAddPaymentMethodTransferWithTimestamp(
1556
            $paymentProviderTransfer,
1557
            $this->generateNowTimestamp(),
1558
        );
1559
1560
        // Act
1561
        $this->tester->getFacade()->addPaymentMethod($addPaymentMethodMessage);
1562
1563
        // Assert
1564
        $this->tester->assertRightPaymentMethodWasUpdated(
1565
            $existentPaymentMethod,
1566
            $addPaymentMethodMessage->getProviderName(),
1567
            false,
1568
        );
1569
    }
1570
1571
    /**
1572
     * @return \Generated\Shared\Transfer\CheckoutResponseTransfer
1573
     */
1574
    protected function buildCheckoutResponseTransfer(): CheckoutResponseTransfer
1575
    {
1576
        return (new CheckoutResponseBuilder())
1577
            ->withSaveOrder()
1578
            ->build();
1579
    }
1580
1581
    /**
1582
     * @return \Generated\Shared\Transfer\QuoteTransfer
1583
     */
1584
    protected function buildQuoteTransfer(): QuoteTransfer
1585
    {
1586
        return (new QuoteBuilder())
1587
            ->withItem()
1588
            ->withStore([
1589
                'name' => static::STORE_NAME,
1590
            ])
1591
            ->withCustomer()
1592
            ->withTotals()
1593
            ->withCurrency()
1594
            ->withBillingAddress()
1595
            ->withShippingAddress()
1596
            ->build();
1597
    }
1598
1599
    /**
1600
     * @return void
1601
     */
1602
    protected function mockPaymentMethodReader(): void
1603
    {
1604
        $paymentMethodReaderMock = $this->getMockBuilder(PaymentMethodReader::class)
1605
            ->onlyMethods(['getAvailableMethods'])
1606
            ->disableOriginalConstructor()
1607
            ->getMock();
1608
        $paymentMethodReaderMock->method('getAvailableMethods')->willReturn(
1609
            (new PaymentMethodsTransfer())
1610
                ->addMethod(
1611
                    (new PaymentMethodTransfer())->setMethodName('dummyPaymentInvoice')
1612
                        ->setPaymentMethodKey('dummyPaymentInvoice'),
1613
                ),
1614
        );
1615
1616
        $container = new Container();
1617
        /** @var \Spryker\Zed\Payment\Business\PaymentBusinessFactory $paymentBusinessFactoryMock */
1618
        $paymentBusinessFactoryMock = $this->getMockBuilder(PaymentBusinessFactory::class)
1619
            ->onlyMethods(['createPaymentMethodReader', 'getPaymentService'])
1620
            ->getMock();
1621
        $paymentBusinessFactoryMock->method('createPaymentMethodReader')
1622
            ->willReturn($paymentMethodReaderMock);
1623
        $paymentBusinessFactoryMock->method('getPaymentService')
1624
            ->willReturn($container->getLocator()->payment()->service());
1625
1626
        $this->paymentFacade->setFactory($paymentBusinessFactoryMock);
1627
    }
1628
1629
    /**
1630
     * @return string
1631
     */
1632
    protected function generateNowTimestamp(): string
1633
    {
1634
        return (new DateTime('now', new DateTimeZone('UTC')))->format('Y-m-d\TH:i:s.u');
1635
    }
1636
1637
    /**
1638
     * @return void
1639
     */
1640
    public function testGeneratePaymentMethodKeyReturnsPaymentMethodKeyForGivenProviderAndMethod(): void
1641
    {
1642
        // Arrange, Act, Assert
1643
        $this->assertSame('foo-bar-baz', $this->paymentFacade->generatePaymentMethodKey('foo', 'bar baz'));
1644
    }
1645
}
1646