Issues (3)

lib/SaferpayJson/Request/Request.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ticketpark\SaferpayJson\Request;
6
7
use Doctrine\Common\Annotations\AnnotationRegistry;
8
use GuzzleHttp\Exception\ClientException;
9
use GuzzleHttp\Psr7\Response as GuzzleResponse;
10
use JMS\Serializer\Annotation\Exclude;
11
use JMS\Serializer\Annotation\SerializedName;
12
use JMS\Serializer\Annotation\VirtualProperty;
13
use JMS\Serializer\SerializerBuilder;
14
use JMS\Serializer\SerializerInterface;
15
use Ticketpark\SaferpayJson\Request\Exception\HttpRequestException;
16
use Ticketpark\SaferpayJson\Request\Container\RequestHeader;
17
use Ticketpark\SaferpayJson\Request\Exception\SaferpayErrorException;
18
use Ticketpark\SaferpayJson\Response\ErrorResponse;
19
use Ticketpark\SaferpayJson\Response\Response;
20
21
abstract class Request
22
{
23
    private const ROOT_URL = 'https://www.saferpay.com/api/';
24
    private const ROOT_URL_TEST = 'https://test.saferpay.com/api/';
25
    private const ERROR_RESPONSE_CLASS = ErrorResponse::class;
26
27
    /**
28
     * @var RequestConfig
29
     * @Exclude
30
     */
31
    private $requestConfig;
32
33
    /**
34
     * We want the implementation to define the exact return type hint of the response.
35
     * In PHP 7.4 the return type hint here in the abstraction would therefore be Ticketpark\SaferpayJson\Response\Response,
36
     * as all other responses inherit from that class.
37
     * In PHP 7.3 this is not yet allowed. Therefore the return type is omitted and only provided as a PhpDoc in
38
     * order to satisfy static code analysis by PhpStan.
39
     *
40
     * @link https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters
41
     * @link https://stitcher.io/blog/new-in-php-74#improved-type-variance-rfc
42
     * @return mixed
43
     */
44
    abstract public function execute();
45
46
    abstract public function getApiPath(): string;
47
48
    /**
49
     * @phpstan-return  class-string
50
     */
51
    abstract public function getResponseClass(): string;
52
53
    public function __construct(RequestConfig $requestConfig)
54
    {
55
        $this->requestConfig = $requestConfig;
56
    }
57
58
    /**
59
     * @SerializedName("RequestHeader")
60
     * @VirtualProperty
61
     */
62
    public function getRequestHeader(): RequestHeader
63
    {
64
        return new RequestHeader(
65
            $this->requestConfig->getCustomerId()
66
        );
67
    }
68
69
    public function getRequestConfig(): RequestConfig
70
    {
71
        return $this->requestConfig;
72
    }
73
74
    protected function doExecute(): Response
75
    {
76
        try {
77
            /** @var GuzzleResponse $response */
78
            $response = $this->requestConfig->getClient()->post(
79
                $this->getUrl(),
80
                [
81
                    'headers' => $this->getHeaders(),
82
                    'body' => $this->getContent()
83
                ]
84
            );
85
        } catch (\Exception $e) {
86
            if (!$e instanceof ClientException) {
87
                throw new HttpRequestException($e->getMessage());
88
            }
89
90
            /** @var GuzzleResponse $response */
91
            $response = $e->getResponse();
92
        }
93
94
        $statusCode = $response->getStatusCode();
95
96
        if ($statusCode >= 400 && $statusCode < 500) {
97
98
            /** @var ErrorResponse $errorResponse */
99
            $errorResponse = $this->getSerializer()->deserialize(
100
                (string) $response->getBody(),
101
                self::ERROR_RESPONSE_CLASS,
102
                'json'
103
            );
104
105
            throw new SaferpayErrorException($errorResponse);
106
        }
107
108
        if (200 !== $statusCode) {
109
            throw new HttpRequestException(sprintf(
110
                'Unexpected http request response with status code %s.',
111
                $response->getStatusCode()
112
            ));
113
        }
114
115
        /** @var Response $libraryResponse */
116
        $libraryResponse = $this->getSerializer()->deserialize(
117
            (string) $response->getBody(),
118
            $this->getResponseClass(),
119
            'json'
120
        );
121
122
        return $libraryResponse;
123
    }
124
125
    private function getUrl(): string
126
    {
127
        $rootUrl = self::ROOT_URL;
128
129
        if ($this->requestConfig->isTest()) {
130
            $rootUrl = self::ROOT_URL_TEST;
131
        }
132
133
        return $rootUrl . $this->getApiPath();
134
    }
135
136
    private function getHeaders(): array
137
    {
138
        return [
139
            'Content-Type'  => 'application/json; charset=utf-8',
140
            'Accept'        => 'application/json',
141
            'Authorization' => 'Basic ' . base64_encode(
142
                $this->requestConfig->getApiKey()
143
                . ':'
144
                . $this->requestConfig->getApiSecret()
145
            )
146
        ];
147
    }
148
149
    private function getContent(): string
150
    {
151
        return $this->getSerializer()->serialize($this, 'json');
152
    }
153
154
    private function getSerializer(): SerializerInterface
155
    {
156
        AnnotationRegistry::registerLoader('class_exists');
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Common\Annotati...istry::registerLoader() has been deprecated: This method is deprecated and will be removed in doctrine/annotations 2.0. Annotations will be autoloaded in 2.0. ( Ignorable by Annotation )

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

156
        /** @scrutinizer ignore-deprecated */ AnnotationRegistry::registerLoader('class_exists');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
157
158
        return SerializerBuilder::create()->build();
159
    }
160
}
161