OrderPaymentApplePayDirectProvider::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 14
rs 10
cc 1
nc 1
nop 6
1
<?php
2
3
/*
4
 * This file has been created by developers from BitBag.
5
 * Feel free to contact us once you face any issues or want to start
6
 * You can find more information about us on https://bitbag.io and write us
7
 * an email on [email protected].
8
 */
9
10
declare(strict_types=1);
11
12
namespace BitBag\SyliusMolliePlugin\Provider\Order;
13
14
use BitBag\SyliusMolliePlugin\Entity\GatewayConfigInterface;
15
use BitBag\SyliusMolliePlugin\Factory\MollieGatewayFactory;
16
use Payum\Core\Payum;
17
use SM\Factory\FactoryInterface as StateMachineFactoryInterface;
18
use Sylius\AdminOrderCreationPlugin\Provider\PaymentTokenProviderInterface;
19
use Sylius\Component\Core\Model\PaymentInterface;
20
use Sylius\Component\Core\Model\PaymentMethodInterface;
21
use Sylius\Component\Core\Payment\Exception\NotProvidedOrderPaymentException;
22
use Sylius\Component\Order\Model\OrderInterface;
23
use Sylius\Component\Payment\Exception\UnresolvedDefaultPaymentMethodException;
24
use Sylius\Component\Payment\Factory\PaymentFactoryInterface;
25
use Sylius\Component\Payment\PaymentTransitions;
26
use Sylius\Component\Resource\Repository\RepositoryInterface;
27
use Sylius\Component\Resource\StateMachine\StateMachineInterface;
28
use Webmozart\Assert\Assert;
29
30
final class OrderPaymentApplePayDirectProvider implements OrderPaymentApplePayDirectProviderInterface
31
{
32
    /** @var PaymentFactoryInterface */
33
    private $paymentFactory;
34
35
    /** @var StateMachineFactoryInterface */
36
    private $stateMachineFactory;
37
38
    /** @var RepositoryInterface */
39
    private $paymentMethodRepository;
40
41
    /** @var RepositoryInterface */
42
    private $gatewayConfigRepository;
43
44
    /** @var PaymentTokenProviderInterface */
45
    private $paymentTokenProvider;
46
47
    /** @var Payum */
48
    private $payum;
49
50
    public function __construct(
51
        PaymentFactoryInterface $paymentFactory,
52
        StateMachineFactoryInterface $stateMachineFactory,
53
        RepositoryInterface $paymentMethodRepository,
54
        RepositoryInterface $gatewayConfigRepository,
55
        PaymentTokenProviderInterface $paymentTokenProvider,
56
        Payum $payum
57
    ) {
58
        $this->paymentFactory = $paymentFactory;
59
        $this->stateMachineFactory = $stateMachineFactory;
60
        $this->paymentMethodRepository = $paymentMethodRepository;
61
        $this->gatewayConfigRepository = $gatewayConfigRepository;
62
        $this->paymentTokenProvider = $paymentTokenProvider;
63
        $this->payum = $payum;
64
    }
65
66
    public function provideOrderPayment(OrderInterface $order, string $targetState): ?PaymentInterface
67
    {
68
        $order->getPayments()->clear();
0 ignored issues
show
Bug introduced by
The method getPayments() does not exist on Sylius\Component\Order\Model\OrderInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Sylius\Component\Order\Model\Order. Are you sure you never get one of those? ( Ignorable by Annotation )

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

68
        $order->/** @scrutinizer ignore-call */ 
69
                getPayments()->clear();
Loading history...
69
70
        /** @var PaymentInterface $payment */
71
        $payment = $this->paymentFactory->createWithAmountAndCurrencyCode($order->getTotal(), $order->getCurrencyCode());
0 ignored issues
show
Bug introduced by
The method getCurrencyCode() does not exist on Sylius\Component\Order\Model\OrderInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Sylius\Component\Order\Model\Order. Are you sure you never get one of those? ( Ignorable by Annotation )

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

71
        $payment = $this->paymentFactory->createWithAmountAndCurrencyCode($order->getTotal(), $order->/** @scrutinizer ignore-call */ getCurrencyCode());
Loading history...
72
73
        $paymentMethod = $this->getDefaultPaymentMethod($payment, $order);
74
        $lastPayment = $this->getLastPayment($order);
75
76
        if (null !== $lastPayment) {
77
            $paymentMethod = $lastPayment->getMethod();
78
        }
79
80
        if (null === $paymentMethod) {
81
            throw new NotProvidedOrderPaymentException();
82
        }
83
84
        $payment->setMethod($paymentMethod);
85
        $this->applyRequiredTransition($payment, $targetState);
86
87
        $token = $this->paymentTokenProvider->getPaymentToken($payment);
88
89
        $notifyToken = $this->payum->getTokenFactory()->createNotifyToken($token->getGatewayName(), $token->getDetails());
90
        $refundToken = $this->payum->getTokenFactory()->createRefundToken($token->getGatewayName(), $token->getDetails());
91
92
        $payment->setDetails([
93
            'payment_id' => $token->getDetails()->getId(),
94
            'backurl' => $token->getAfterUrl(),
95
            'webhookUrl' => $notifyToken->getTargetUrl(),
96
            'refund_token' => $refundToken->getHash(),
97
        ]);
98
99
        $order->addPayment($payment);
0 ignored issues
show
Bug introduced by
The method addPayment() does not exist on Sylius\Component\Order\Model\OrderInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Sylius\Component\Order\Model\Order. Are you sure you never get one of those? ( Ignorable by Annotation )

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

99
        $order->/** @scrutinizer ignore-call */ 
100
                addPayment($payment);
Loading history...
100
101
        return $payment;
102
    }
103
104
    public function applyRequiredTransition(PaymentInterface $payment, string $targetState): void
105
    {
106
        if ($targetState === $payment->getState()) {
107
            return;
108
        }
109
110
        /** @var StateMachineInterface $stateMachine */
111
        $stateMachine = $this->stateMachineFactory->get($payment, PaymentTransitions::GRAPH);
112
113
        $targetTransition = $stateMachine->getTransitionToState($targetState);
114
115
        if (null !== $targetTransition) {
116
            $stateMachine->apply($targetTransition);
117
        }
118
    }
119
120
    private function getLastPayment(OrderInterface $order): ?PaymentInterface
121
    {
122
        $lastCancelledPayment = $order->getLastPayment(PaymentInterface::STATE_CANCELLED);
0 ignored issues
show
Bug introduced by
The method getLastPayment() does not exist on Sylius\Component\Order\Model\OrderInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Sylius\Component\Order\Model\Order. Are you sure you never get one of those? ( Ignorable by Annotation )

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

122
        /** @scrutinizer ignore-call */ 
123
        $lastCancelledPayment = $order->getLastPayment(PaymentInterface::STATE_CANCELLED);
Loading history...
123
124
        if (null !== $lastCancelledPayment) {
125
            return $lastCancelledPayment;
126
        }
127
128
        return $order->getLastPayment(PaymentInterface::STATE_FAILED);
129
    }
130
131
    private function getDefaultPaymentMethod(PaymentInterface $payment, OrderInterface $order): ?PaymentMethodInterface
132
    {
133
        try {
134
            $payment->setOrder($order);
135
            $gateway = $this->gatewayConfigRepository->findOneBy(['factoryName' => MollieGatewayFactory::FACTORY_NAME]);
136
            Assert::isInstanceOf($gateway, GatewayConfigInterface::class);
137
138
            /** @var PaymentMethodInterface $paymentMethod */
139
            $paymentMethod = $this->paymentMethodRepository->findOneBy([
140
                'gatewayConfig' => $gateway,
141
            ]);
142
143
            return $paymentMethod;
144
        } catch (UnresolvedDefaultPaymentMethodException $exception) {
145
            return null;
146
        }
147
    }
148
}
149