Passed
Push — trunk ( b25d7b...3c7131 )
by Christian
11:39 queued 13s
created

getRecurringPaymentHandler()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Checkout\Payment\Cart\PaymentHandler;
4
5
use Doctrine\DBAL\Connection;
6
use Shopware\Core\Framework\App\Payment\Handler\AppAsyncPaymentHandler;
7
use Shopware\Core\Framework\App\Payment\Handler\AppSyncPaymentHandler;
8
use Shopware\Core\Framework\Log\Package;
9
use Shopware\Core\Framework\Uuid\Uuid;
10
use Symfony\Contracts\Service\ServiceProviderInterface;
11
12
#[Package('checkout')]
13
class PaymentHandlerRegistry
14
{
15
    /**
16
     * @var array<string, PaymentHandlerInterface>
17
     */
18
    private array $handlers = [];
19
20
    /**
21
     * @internal
22
     *
23
     * @param ServiceProviderInterface<PaymentHandlerInterface> $syncHandlers
24
     * @param ServiceProviderInterface<PaymentHandlerInterface> $asyncHandlers
25
     * @param ServiceProviderInterface<PaymentHandlerInterface> $preparedHandlers
26
     * @param ServiceProviderInterface<PaymentHandlerInterface> $refundHandlers
27
     * @param ServiceProviderInterface<PaymentHandlerInterface> $recurringHandlers
28
     */
29
    public function __construct(
30
        ServiceProviderInterface $syncHandlers,
31
        ServiceProviderInterface $asyncHandlers,
32
        ServiceProviderInterface $preparedHandlers,
33
        ServiceProviderInterface $refundHandlers,
34
        ServiceProviderInterface $recurringHandlers,
35
        private readonly Connection $connection
36
    ) {
37
        foreach (\array_keys($syncHandlers->getProvidedServices()) as $serviceId) {
38
            $handler = $syncHandlers->get($serviceId);
39
            $this->handlers[(string) $serviceId] = $handler;
40
        }
41
42
        foreach (\array_keys($asyncHandlers->getProvidedServices()) as $serviceId) {
43
            $handler = $asyncHandlers->get($serviceId);
44
            $this->handlers[(string) $serviceId] = $handler;
45
        }
46
47
        foreach (\array_keys($preparedHandlers->getProvidedServices()) as $serviceId) {
48
            $handler = $preparedHandlers->get($serviceId);
49
            $this->handlers[(string) $serviceId] = $handler;
50
        }
51
52
        foreach (\array_keys($refundHandlers->getProvidedServices()) as $serviceId) {
53
            $handler = $refundHandlers->get($serviceId);
54
            $this->handlers[(string) $serviceId] = $handler;
55
        }
56
57
        foreach (\array_keys($recurringHandlers->getProvidedServices()) as $serviceId) {
58
            $handler = $recurringHandlers->get($serviceId);
59
            $this->handlers[(string) $serviceId] = $handler;
60
        }
61
    }
62
63
    public function getPaymentMethodHandler(
64
        string $paymentMethodId,
65
        ?string $expectedHandlerType = null
66
    ): ?PaymentHandlerInterface {
67
        $result = $this->connection->createQueryBuilder()
68
            ->select('
69
                payment_method.handler_identifier,
70
                app_payment_method.id as app_payment_method_id,
71
                app_payment_method.pay_url,
72
                app_payment_method.finalize_url,
73
                app_payment_method.capture_url,
74
                app_payment_method.validate_url,
75
                app_payment_method.refund_url,
76
                app_payment_method.recurring_url
77
            ')
78
            ->from('payment_method')
79
            ->leftJoin(
80
                'payment_method',
81
                'app_payment_method',
82
                'app_payment_method',
83
                'payment_method.id = app_payment_method.payment_method_id'
84
            )
85
            ->andWhere('payment_method.id = :paymentMethodId')
86
            ->setParameter('paymentMethodId', Uuid::fromHexToBytes($paymentMethodId))
87
            ->executeQuery()
88
            ->fetchAssociative();
89
90
        if (!$result || !\array_key_exists('handler_identifier', $result)) {
91
            return null;
92
        }
93
94
        // app payment method is set: we need to resolve an app handler
95
        if (isset($result['app_payment_method_id'])) {
96
            return $this->resolveAppPaymentMethodHandler($result, $expectedHandlerType);
97
        }
98
99
        $handlerIdentifier = $result['handler_identifier'];
100
101
        if (!\array_key_exists($handlerIdentifier, $this->handlers)) {
102
            return null;
103
        }
104
105
        $handler = $this->handlers[$handlerIdentifier];
106
107
        // a specific handler type was requested
108
        if ($expectedHandlerType !== null && !\is_a($handler, $expectedHandlerType, true)) {
109
            return null;
110
        }
111
112
        return $this->handlers[$handlerIdentifier];
113
    }
114
115
    public function getSyncPaymentHandler(string $paymentMethodId): ?SynchronousPaymentHandlerInterface
116
    {
117
        $handler = $this->getPaymentMethodHandler($paymentMethodId, SynchronousPaymentHandlerInterface::class);
118
119
        if (!$handler instanceof SynchronousPaymentHandlerInterface) {
120
            return null;
121
        }
122
123
        return $handler;
124
    }
125
126
    public function getAsyncPaymentHandler(string $paymentMethodId): ?AsynchronousPaymentHandlerInterface
127
    {
128
        $handler = $this->getPaymentMethodHandler($paymentMethodId, AsynchronousPaymentHandlerInterface::class);
129
130
        if (!$handler instanceof AsynchronousPaymentHandlerInterface) {
131
            return null;
132
        }
133
134
        return $handler;
135
    }
136
137
    public function getPreparedPaymentHandler(string $paymentMethodId): ?PreparedPaymentHandlerInterface
138
    {
139
        $handler = $this->getPaymentMethodHandler($paymentMethodId, PreparedPaymentHandlerInterface::class);
140
141
        if (!$handler instanceof PreparedPaymentHandlerInterface) {
142
            return null;
143
        }
144
145
        return $handler;
146
    }
147
148
    public function getRefundPaymentHandler(string $paymentMethodId): ?RefundPaymentHandlerInterface
149
    {
150
        $handler = $this->getPaymentMethodHandler($paymentMethodId, RefundPaymentHandlerInterface::class);
151
152
        if (!$handler instanceof RefundPaymentHandlerInterface) {
153
            return null;
154
        }
155
156
        return $handler;
157
    }
158
159
    public function getRecurringPaymentHandler(string $paymentMethodId): ?RecurringPaymentHandlerInterface
160
    {
161
        $handler = $this->getPaymentMethodHandler($paymentMethodId, RecurringPaymentHandlerInterface::class);
162
163
        if (!$handler instanceof RecurringPaymentHandlerInterface) {
164
            return null;
165
        }
166
167
        return $handler;
168
    }
169
170
    /**
171
     * @param array<string, mixed> $appPaymentMethod
172
     */
173
    private function resolveAppPaymentMethodHandler(
174
        array $appPaymentMethod,
175
        ?string $expectedHandlerType = null
176
    ): ?PaymentHandlerInterface {
177
        // validate if prepared and refund handlers have all information set
178
        if ($expectedHandlerType) {
179
            if (\is_a(PreparedPaymentHandlerInterface::class, $expectedHandlerType, true)) {
180
                if (empty($appPaymentMethod['capture_url']) || empty($appPaymentMethod['validate_url'])) {
181
                    return null;
182
                }
183
            }
184
185
            if (\is_a(RefundPaymentHandlerInterface::class, $expectedHandlerType, true)) {
186
                if (empty($appPaymentMethod['refund_url'])) {
187
                    return null;
188
                }
189
            }
190
191
            if (\is_a(RecurringPaymentHandlerInterface::class, $expectedHandlerType, true)) {
192
                if (empty($appPaymentMethod['recurring_url'])) {
193
                    return null;
194
                }
195
            }
196
        }
197
198
        if (empty($appPaymentMethod['finalize_url'])) {
199
            return $this->handlers[AppSyncPaymentHandler::class] ?? null;
200
        }
201
202
        return $this->handlers[AppAsyncPaymentHandler::class] ?? null;
203
    }
204
}
205