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