1 | <?php |
||
2 | /** |
||
3 | * Mollie client. |
||
4 | * |
||
5 | * @author Pronamic <[email protected]> |
||
6 | * @copyright 2005-2019 Pronamic |
||
7 | * @license GPL-3.0-or-later |
||
8 | * @package Pronamic\WordPress\Pay |
||
9 | */ |
||
10 | |||
11 | namespace Pronamic\WordPress\Pay\Gateways\Mollie; |
||
12 | |||
13 | use Pronamic\WordPress\DateTime\DateTime; |
||
14 | use Pronamic\WordPress\Pay\Core\XML\Security; |
||
15 | |||
16 | /** |
||
17 | * Title: Mollie |
||
18 | * Description: |
||
19 | * Copyright: 2005-2019 Pronamic |
||
20 | * Company: Pronamic |
||
21 | * |
||
22 | * @author Remco Tolsma |
||
23 | * @version 2.1.0 |
||
24 | * @since 1.0.0 |
||
25 | */ |
||
26 | class Client { |
||
27 | /** |
||
28 | * Mollie API endpoint URL |
||
29 | * |
||
30 | * @var string |
||
31 | */ |
||
32 | const API_URL = 'https://api.mollie.com/v2/'; |
||
33 | |||
34 | /** |
||
35 | * Mollie API Key ID |
||
36 | * |
||
37 | * @var string |
||
38 | */ |
||
39 | private $api_key; |
||
40 | |||
41 | /** |
||
42 | * Mode |
||
43 | * |
||
44 | * @since 1.1.9 |
||
45 | * @var string |
||
46 | */ |
||
47 | private $mode; |
||
48 | |||
49 | /** |
||
50 | * Constructs and initializes an Mollie client object |
||
51 | * |
||
52 | * @param string $api_key Mollie API key. |
||
53 | */ |
||
54 | public function __construct( $api_key ) { |
||
55 | $this->api_key = $api_key; |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * Set mode |
||
60 | * |
||
61 | * @since 1.1.9 |
||
62 | 38 | * @param string $mode Mode (test or live). |
|
63 | 38 | */ |
|
64 | 38 | public function set_mode( $mode ) { |
|
65 | $this->mode = $mode; |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * Send request with the specified action and parameters |
||
70 | * |
||
71 | * @param string $end_point Requested endpoint. |
||
72 | 38 | * @param string $method HTTP method to use. |
|
73 | 38 | * @param array $data Request data. |
|
74 | 38 | * @param int $expected_response_code Expected response code. |
|
75 | * @return bool|object |
||
76 | * @throws \Pronamic\WordPress\Pay\GatewayException Throws exception when error occurs. |
||
77 | */ |
||
78 | private function send_request( $end_point, $method = 'GET', array $data = array(), $expected_response_code = 200 ) { |
||
79 | // Request. |
||
80 | $url = self::API_URL . $end_point; |
||
81 | 3 | ||
82 | 3 | $response = wp_remote_request( |
|
83 | $url, |
||
84 | array( |
||
85 | 'method' => $method, |
||
86 | 'headers' => array( |
||
87 | 'Authorization' => 'Bearer ' . $this->api_key, |
||
88 | ), |
||
89 | 'body' => $data, |
||
90 | ) |
||
91 | ); |
||
92 | |||
93 | if ( $response instanceof \WP_Error ) { |
||
94 | throw new \Pronamic\WordPress\Pay\GatewayException( 'mollie', $response->get_error_message() ); |
||
0 ignored issues
–
show
|
|||
95 | 8 | } |
|
96 | |||
97 | 8 | // Response code. |
|
98 | $response_code = wp_remote_retrieve_response_code( $response ); |
||
99 | 8 | ||
100 | 8 | // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison |
|
101 | if ( $expected_response_code != $response_code ) { |
||
102 | 8 | throw new \Pronamic\WordPress\Pay\GatewayException( 'mollie', 'Unexpected response code (' . $response_code . ').' ); |
|
103 | } |
||
104 | 8 | ||
105 | // Body. |
||
106 | 8 | $body = wp_remote_retrieve_body( $response ); |
|
107 | |||
108 | $data = json_decode( $body ); |
||
109 | |||
110 | 8 | // JSON error. |
|
111 | $json_error = \json_last_error(); |
||
112 | |||
113 | if ( \JSON_ERROR_NONE !== $json_error ) { |
||
114 | throw new Pronamic\WordPress\Pay\GatewayException( |
||
0 ignored issues
–
show
The type
Pronamic\WordPress\Pay\G...ss\Pay\GatewayException was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||
115 | 8 | 'mollie', |
|
116 | \sprintf( 'JSON: %s', \json_last_error_msg() ), |
||
117 | $json_error |
||
118 | 8 | ); |
|
119 | 8 | } |
|
120 | |||
121 | // Object. |
||
122 | if ( ! \is_object( $data ) ) { |
||
123 | 8 | $code = \wp_remote_retrieve_response_code( $response ); |
|
124 | |||
125 | 8 | throw new Pronamic\WordPress\Pay\GatewayException( |
|
126 | 'mollie', |
||
127 | \sprintf( 'Could not JSON decode Mollie response to an object (HTTP Status Code: %s).', $code ), |
||
128 | 8 | \intval( $code ) |
|
129 | ); |
||
130 | 8 | } |
|
131 | |||
132 | // Mollie error. |
||
133 | if ( isset( $data->status, $data->title, $data->detail ) ) { |
||
134 | throw new Pronamic\WordPress\Pay\GatewayException( 'mollie', $data->detail, $data ); |
||
135 | } |
||
136 | |||
137 | return $data; |
||
138 | 8 | } |
|
139 | |||
140 | /** |
||
141 | * Create payment. |
||
142 | * |
||
143 | * @param PaymentRequest $request Payment request. |
||
144 | * |
||
145 | * @return bool|object |
||
146 | */ |
||
147 | public function create_payment( PaymentRequest $request ) { |
||
148 | 8 | return $this->send_request( 'payments', 'POST', $request->get_array(), 201 ); |
|
149 | 8 | } |
|
150 | |||
151 | 8 | /** |
|
152 | * Get payments. |
||
153 | * |
||
154 | * @return bool|object |
||
155 | */ |
||
156 | public function get_payments() { |
||
157 | return $this->send_request( 'payments', 'GET' ); |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * Get payment. |
||
162 | * |
||
163 | * @param string $payment_id Payment ID. |
||
164 | * |
||
165 | * @return bool|object |
||
166 | */ |
||
167 | public function get_payment( $payment_id ) { |
||
168 | if ( empty( $payment_id ) ) { |
||
169 | return false; |
||
170 | } |
||
171 | |||
172 | return $this->send_request( 'payments/' . $payment_id, 'GET' ); |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Get issuers |
||
177 | * |
||
178 | * @return array|bool |
||
179 | */ |
||
180 | public function get_issuers() { |
||
181 | $response = $this->send_request( 'methods/ideal?include=issuers', 'GET' ); |
||
182 | |||
183 | $issuers = array(); |
||
184 | |||
185 | if ( isset( $response->issuers ) ) { |
||
186 | foreach ( $response->issuers as $issuer ) { |
||
187 | $id = Security::filter( $issuer->id ); |
||
188 | $name = Security::filter( $issuer->name ); |
||
189 | |||
190 | $issuers[ $id ] = $name; |
||
191 | } |
||
192 | } |
||
193 | |||
194 | return $issuers; |
||
195 | } |
||
196 | |||
197 | 2 | /** |
|
198 | 2 | * Get payment methods |
|
199 | * |
||
200 | 2 | * @param string $sequence_type Sequence type. |
|
201 | 2 | * |
|
202 | * @return array|bool |
||
203 | */ |
||
204 | public function get_payment_methods( $sequence_type = '' ) { |
||
205 | $data = array(); |
||
206 | |||
207 | if ( '' !== $sequence_type ) { |
||
208 | $data['sequenceType'] = $sequence_type; |
||
209 | } |
||
210 | |||
211 | $response = $this->send_request( 'methods', 'GET', $data ); |
||
212 | |||
213 | if ( false === $response ) { |
||
214 | return false; |
||
215 | } |
||
216 | |||
217 | $payment_methods = array(); |
||
218 | |||
219 | if ( isset( $response->_embedded->methods ) ) { |
||
220 | foreach ( $response->_embedded->methods as $payment_method ) { |
||
221 | $id = Security::filter( $payment_method->id ); |
||
222 | $name = Security::filter( $payment_method->description ); |
||
223 | |||
224 | $payment_methods[ $id ] = $name; |
||
225 | 1 | } |
|
226 | 1 | } |
|
227 | |||
228 | 1 | return $payment_methods; |
|
229 | 1 | } |
|
230 | |||
231 | /** |
||
232 | 1 | * Create customer. |
|
233 | * |
||
234 | 1 | * @since 1.1.6 |
|
235 | 1 | * |
|
236 | * @param string $email Customer email address. |
||
237 | * @param string $name Customer name. |
||
238 | * |
||
239 | * @return string|bool |
||
240 | */ |
||
241 | public function create_customer( $email, $name ) { |
||
242 | if ( empty( $email ) ) { |
||
243 | return false; |
||
244 | } |
||
245 | |||
246 | $response = $this->send_request( |
||
247 | 'customers', |
||
248 | 'POST', |
||
249 | array( |
||
250 | 'name' => $name, |
||
251 | 'email' => $email, |
||
252 | ), |
||
253 | 201 |
||
254 | ); |
||
255 | |||
256 | if ( false === $response ) { |
||
257 | return false; |
||
258 | } |
||
259 | |||
260 | if ( ! isset( $response->id ) ) { |
||
261 | return false; |
||
262 | } |
||
263 | |||
264 | return $response->id; |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Get customer. |
||
269 | * |
||
270 | * @param string $customer_id Mollie customer ID. |
||
271 | * |
||
272 | * @since unreleased |
||
273 | * |
||
274 | * @return object|bool |
||
275 | */ |
||
276 | public function get_customer( $customer_id ) { |
||
277 | if ( empty( $customer_id ) ) { |
||
278 | return false; |
||
279 | } |
||
280 | |||
281 | try { |
||
282 | $response = $this->send_request( 'customers/' . $customer_id, 'GET', array(), 200 ); |
||
283 | } catch ( \Pronamic\WordPress\Pay\GatewayException $e ) { |
||
284 | return false; |
||
285 | } |
||
286 | |||
287 | return $response; |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Get mandates for customer. |
||
292 | * |
||
293 | * @param string $customer_id Mollie customer ID. |
||
294 | * |
||
295 | * @return object|bool |
||
296 | */ |
||
297 | 5 | public function get_mandates( $customer_id ) { |
|
298 | 5 | if ( '' === $customer_id ) { |
|
299 | return false; |
||
300 | } |
||
301 | |||
302 | 5 | return $this->send_request( 'customers/' . $customer_id . '/mandates?limit=250', 'GET' ); |
|
303 | } |
||
304 | 5 | ||
305 | 5 | /** |
|
306 | * Is there a valid mandate for customer? |
||
307 | * |
||
308 | * @param string $customer_id Mollie customer ID. |
||
309 | * @param string|null $payment_method Payment method to find mandates for. |
||
310 | * |
||
311 | * @return boolean |
||
312 | */ |
||
313 | public function has_valid_mandate( $customer_id, $payment_method = null ) { |
||
314 | $mandates = $this->get_mandates( $customer_id ); |
||
315 | |||
316 | if ( ! $mandates ) { |
||
317 | return false; |
||
318 | } |
||
319 | |||
320 | $mollie_method = Methods::transform( $payment_method ); |
||
321 | |||
322 | foreach ( $mandates->_embedded as $mandate ) { |
||
323 | if ( $mollie_method !== $mandate->method ) { |
||
324 | continue; |
||
325 | } |
||
326 | |||
327 | if ( 'valid' === $mandate->status ) { |
||
328 | return true; |
||
329 | } |
||
330 | } |
||
331 | |||
332 | return false; |
||
333 | } |
||
334 | |||
335 | /** |
||
336 | * Get formatted date and time of first valid mandate. |
||
337 | * |
||
338 | * @param string $customer_id Mollie customer ID. |
||
339 | * @param string $payment_method Payment method. |
||
340 | * |
||
341 | * @return null|DateTime |
||
342 | */ |
||
343 | public function get_first_valid_mandate_datetime( $customer_id, $payment_method = null ) { |
||
344 | $mandates = $this->get_mandates( $customer_id ); |
||
345 | |||
346 | if ( ! $mandates ) { |
||
347 | return null; |
||
348 | } |
||
349 | |||
350 | $mollie_method = Methods::transform( $payment_method ); |
||
351 | |||
352 | foreach ( $mandates->_embedded as $mandate ) { |
||
353 | if ( $mollie_method !== $mandate->method ) { |
||
354 | continue; |
||
355 | } |
||
356 | |||
357 | if ( 'valid' !== $mandate->status ) { |
||
358 | continue; |
||
359 | } |
||
360 | |||
361 | if ( ! isset( $valid_mandates ) ) { |
||
362 | $valid_mandates = array(); |
||
363 | } |
||
364 | |||
365 | // @codingStandardsIgnoreStart |
||
366 | $valid_mandates[ $mandate->createdAt ] = $mandate; |
||
367 | // @codingStandardsIgnoreEnd |
||
368 | } |
||
369 | |||
370 | if ( isset( $valid_mandates ) ) { |
||
371 | ksort( $valid_mandates ); |
||
372 | |||
373 | $mandate = array_shift( $valid_mandates ); |
||
374 | |||
375 | // @codingStandardsIgnoreStart |
||
376 | $create_date = new DateTime( $mandate->createdAt ); |
||
377 | // @codingStandardsIgnoreEnd |
||
378 | |||
379 | return $create_date; |
||
380 | } |
||
381 | |||
382 | return null; |
||
383 | } |
||
384 | } |
||
385 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths