NotifyAction::__invoke()   B
last analyzed

Complexity

Conditions 8
Paths 7

Size

Total Lines 49
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 49
rs 8.4444
cc 8
nc 7
nop 1
1
<?php
2
3
/*
4
 * This file was created by developers working at BitBag
5
 * Do you need more information about us and what we do? Visit our https://bitbag.io website!
6
 * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career
7
*/
8
9
declare(strict_types=1);
10
11
namespace BitBag\SyliusCoinbasePlugin\Controller\Action\Payment;
12
13
use BitBag\SyliusCoinbasePlugin\ApiClient\CoinbaseApiClientInterface;
14
use BitBag\SyliusCoinbasePlugin\CoinbaseGatewayFactory;
15
use BitBag\SyliusCoinbasePlugin\Resolver\PaymentStateResolverInterface;
16
use SM\Factory\FactoryInterface;
17
use Sylius\Component\Core\Model\PaymentInterface;
18
use Sylius\Component\Core\Model\PaymentMethodInterface;
19
use Sylius\Component\Core\Repository\PaymentRepositoryInterface;
20
use Symfony\Component\HttpFoundation\Request;
21
use Symfony\Component\HttpFoundation\Response;
22
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
23
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
24
25
final class NotifyAction
26
{
27
    /** @var PaymentRepositoryInterface */
28
    private $paymentRepository;
29
30
    /** @var FactoryInterface */
31
    private $stateMachineFactory;
32
33
    /** @var CoinbaseApiClientInterface */
34
    private $coinbaseApiClient;
35
36
    /** @var PaymentStateResolverInterface */
37
    private $paymentStateResolver;
38
39
    public function __construct(
40
        PaymentRepositoryInterface $paymentRepository,
41
        FactoryInterface $stateMachineFactory,
42
        CoinbaseApiClientInterface $coinbaseApiClient,
43
        PaymentStateResolverInterface $paymentStateResolver
44
    ) {
45
        $this->paymentRepository = $paymentRepository;
46
        $this->stateMachineFactory = $stateMachineFactory;
47
        $this->coinbaseApiClient = $coinbaseApiClient;
48
        $this->paymentStateResolver = $paymentStateResolver;
49
    }
50
51
    public function __invoke(Request $request): Response
52
    {
53
        $headers = $request->headers;
54
55
        if (!$headers->has(CoinbaseApiClientInterface::WEBHOOK_SIGNATURE_HEADER_NAME)) {
56
            throw new NotFoundHttpException();
57
        }
58
59
        $signatureHeader = $headers->get(CoinbaseApiClientInterface::WEBHOOK_SIGNATURE_HEADER_NAME);
60
61
        $payload = json_decode($request->getContent(), true);
62
63
        if (!isset($payload['event']['data']['metadata']['payment_id'])) {
64
            throw new BadRequestHttpException();
65
        }
66
67
        $paymentId = (int) $payload['event']['data']['metadata']['payment_id'];
68
69
        /** @var PaymentInterface $payment */
70
        $payment = $this->paymentRepository->find($paymentId);
71
72
        /** @var PaymentMethodInterface $paymentMethod */
73
        $paymentMethod = $payment->getMethod();
74
75
        if (CoinbaseGatewayFactory::FACTORY_NAME !== $paymentMethod->getGatewayConfig()->getConfig()['factoryName']) {
76
            throw new BadRequestHttpException();
77
        }
78
79
        $details = $payment->getDetails();
80
81
        if (!(isset($details['payment_id']) && $details['payment_id'] === $payload['event']['data']['id'])) {
82
            throw new BadRequestHttpException();
83
        }
84
85
        $gatewayConfig = $paymentMethod->getGatewayConfig()->getConfig();
86
87
        try {
88
            $event = $this->coinbaseApiClient->buildEvent($request->getContent(), $signatureHeader, $gatewayConfig['webhookSecretKey']);
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() can also be of type resource; however, parameter $payload of BitBag\SyliusCoinbasePlu...Interface::buildEvent() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

88
            $event = $this->coinbaseApiClient->buildEvent(/** @scrutinizer ignore-type */ $request->getContent(), $signatureHeader, $gatewayConfig['webhookSecretKey']);
Loading history...
89
        } catch (\Exception $exception) {
90
            throw new BadRequestHttpException();
91
        }
92
93
        if ('charge:created' === $event->type) {
94
            return new Response('', Response::HTTP_OK);
95
        }
96
97
        $this->paymentStateResolver->resolve($payment);
98
99
        return new Response('', Response::HTTP_OK);
100
    }
101
}
102