Passed
Push — master ( 7c0386...b549f2 )
by Reüel
07:34 queued 19s
created

Client::send_request()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 54
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 5.1777

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 5
eloc 28
c 4
b 0
f 0
nc 5
nop 3
dl 0
loc 54
ccs 21
cts 26
cp 0.8077
crap 5.1777
rs 9.1608

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Mollie client.
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2020 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-2020 Pronamic
20
 * Company: Pronamic
21
 *
22
 * @author  Remco Tolsma
23
 * @version 2.0.9
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 39
	public function __construct( $api_key ) {
55 39
		$this->api_key = $api_key;
56 39
	}
57
58
	/**
59
	 * Set mode
60
	 *
61
	 * @since 1.1.9
62
	 * @param string $mode Mode (test or live).
63
	 */
64 39
	public function set_mode( $mode ) {
65 39
		$this->mode = $mode;
66 39
	}
67
68
	/**
69
	 * Send request with the specified action and parameters
70
	 *
71
	 * @param string $end_point              Requested endpoint.
72
	 * @param string $method                 HTTP method to use.
73
	 * @param array  $data                   Request data.
74
	 * @return object
75
	 * @throws Error Throws Error when Mollie error occurs.
76
	 * @throws \Exception Throws exception when error occurs.
77
	 */
78 9
	private function send_request( $end_point, $method = 'GET', array $data = array() ) {
79
		// Request.
80 9
		$url = self::API_URL . $end_point;
81
82 9
		$response = wp_remote_request(
83 9
			$url,
84
			array(
85 9
				'method'  => $method,
86
				'headers' => array(
87 9
					'Authorization' => 'Bearer ' . $this->api_key,
88
				),
89 9
				'body'    => $data,
90
			)
91
		);
92
93 9
		if ( $response instanceof \WP_Error ) {
94
			throw new \Exception( $response->get_error_message() );
95
		}
96
97
		// Body.
98 9
		$body = wp_remote_retrieve_body( $response );
99
100 9
		$data = json_decode( $body );
101
102
		// JSON error.
103 9
		$json_error = \json_last_error();
104
105 9
		if ( \JSON_ERROR_NONE !== $json_error ) {
106 2
			throw new \Exception(
107 2
				\sprintf( 'JSON: %s', \json_last_error_msg() ),
108
				$json_error
109
			);
110
		}
111
112
		// Object.
113 9
		if ( ! \is_object( $data ) ) {
114
			$code = \wp_remote_retrieve_response_code( $response );
115
116
			throw new \Exception(
117
				\sprintf( 'Could not JSON decode Mollie response to an object (HTTP Status Code: %s).', $code ),
118
				\intval( $code )
119
			);
120
		}
121
122
		// Mollie error from JSON response.
123 9
		if ( isset( $data->status, $data->title, $data->detail ) ) {
124 3
			throw new Error(
125 3
				$data->status,
126 3
				$data->title,
127 3
				$data->detail
128
			);
129
		}
130
131 6
		return $data;
132
	}
133
134
	/**
135
	 * Create payment.
136
	 *
137
	 * @param PaymentRequest $request Payment request.
138
	 * @return object
139
	 */
140
	public function create_payment( PaymentRequest $request ) {
141
		return $this->send_request( 'payments', 'POST', $request->get_array() );
142
	}
143
144
	/**
145
	 * Get payments.
146
	 *
147
	 * @return bool|object
148
	 */
149
	public function get_payments() {
150
		return $this->send_request( 'payments', 'GET' );
151
	}
152
153
	/**
154
	 * Get payment.
155
	 *
156
	 * @param string $payment_id Payment ID.
157
	 *
158
	 * @return object
159
	 * @throws \InvalidArgumentException Throws exception on empty payment ID argument.
160
	 */
161
	public function get_payment( $payment_id ) {
162
		if ( empty( $payment_id ) ) {
163
			throw new \InvalidArgumentException( 'Mollie payment ID can not be empty string.' );
164
		}
165
166
		return $this->send_request( 'payments/' . $payment_id, 'GET' );
167
	}
168
169
	/**
170
	 * Get issuers
171
	 *
172
	 * @return array
173
	 */
174 3
	public function get_issuers() {
175 3
		$response = $this->send_request( 'methods/ideal?include=issuers', 'GET' );
176
177
		$issuers = array();
178
179
		if ( isset( $response->issuers ) ) {
180
			foreach ( $response->issuers as $issuer ) {
181
				$id   = Security::filter( $issuer->id );
182
				$name = Security::filter( $issuer->name );
183
184
				$issuers[ $id ] = $name;
185
			}
186
		}
187
188
		return $issuers;
189
	}
190
191
	/**
192
	 * Get payment methods
193
	 *
194
	 * @param string $sequence_type Sequence type.
195
	 *
196
	 * @return array
197
	 * @throws \Exception Throws exception for methods on failed request or invalid response.
198
	 */
199 2
	public function get_payment_methods( $sequence_type = '' ) {
200 2
		$data = array();
201
202 2
		if ( '' !== $sequence_type ) {
203 2
			$data['sequenceType'] = $sequence_type;
204
		}
205
206 2
		$response = $this->send_request( 'methods', 'GET', $data );
207
208 2
		$payment_methods = array();
209
210 2
		if ( ! isset( $response->_embedded ) ) {
211
			throw new \Exception( 'No embedded data in Mollie response.' );
212
		}
213
214 2
		if ( isset( $response->_embedded->methods ) ) {
215 2
			foreach ( $response->_embedded->methods as $payment_method ) {
216 2
				$id   = Security::filter( $payment_method->id );
217 2
				$name = Security::filter( $payment_method->description );
218
219 2
				$payment_methods[ $id ] = $name;
220
			}
221
		}
222
223 2
		return $payment_methods;
224
	}
225
226
	/**
227
	 * Create customer.
228
	 *
229
	 * @since 1.1.6
230
	 *
231
	 * @param string|null $email Customer email address.
232
	 * @param string|null $name  Customer name.
233
	 * @return string|bool
234
	 */
235
	public function create_customer( $email, $name ) {
236
		if ( empty( $email ) ) {
237
			return false;
238
		}
239
240
		$response = $this->send_request(
241
			'customers',
242
			'POST',
243
			array(
244
				'name'  => $name,
245
				'email' => $email,
246
			)
247
		);
248
249
		if ( ! isset( $response->id ) ) {
250
			return false;
251
		}
252
253
		return $response->id;
254
	}
255
256
	/**
257
	 * Get customer.
258
	 *
259
	 * @param string $customer_id Mollie customer ID.
260
	 *
261
	 * @return null|object
262
	 * @throws \InvalidArgumentException Throws exception on empty customer ID argument.
263
	 * @throws Error Throws Error when Mollie error occurs.
264
	 */
265 4
	public function get_customer( $customer_id ) {
266 4
		if ( empty( $customer_id ) ) {
267
			throw new \InvalidArgumentException( 'Mollie customer ID can not be empty string.' );
268
		}
269
270
		try {
271 4
			return $this->send_request( 'customers/' . $customer_id, 'GET' );
272
		} catch ( Error $error ) {
273
			if ( 404 === $error->get_status() ) {
274
				return null;
275
			}
276
277
			throw $error;
278
		}
279
	}
280
281
	/**
282
	 * Get mandates for customer.
283
	 *
284
	 * @param string $customer_id Mollie customer ID.
285
	 *
286
	 * @return object
287
	 * @throws \InvalidArgumentException Throws exception on empty customer ID argument.
288
	 */
289
	public function get_mandates( $customer_id ) {
290
		if ( '' === $customer_id ) {
291
			throw new \InvalidArgumentException( 'Mollie customer ID can not be empty string.' );
292
		}
293
294
		return $this->send_request( 'customers/' . $customer_id . '/mandates?limit=250', 'GET' );
295
	}
296
297
	/**
298
	 * Is there a valid mandate for customer?
299
	 *
300
	 * @param string      $customer_id    Mollie customer ID.
301
	 * @param string|null $payment_method Payment method to find mandates for.
302
	 *
303
	 * @return boolean
304
	 * @throws \Exception Throws exception for mandates on failed request or invalid response.
305
	 */
306
	public function has_valid_mandate( $customer_id, $payment_method = null ) {
307
		$mandates = $this->get_mandates( $customer_id );
308
309
		$mollie_method = Methods::transform( $payment_method );
310
311
		if ( ! isset( $mandates->_embedded ) ) {
312
			throw new \Exception( 'No embedded data in Mollie response.' );
313
		}
314
315
		foreach ( $mandates->_embedded as $mandate ) {
316
			if ( $mollie_method !== $mandate->method ) {
317
				continue;
318
			}
319
320
			if ( 'valid' === $mandate->status ) {
321
				return true;
322
			}
323
		}
324
325
		return false;
326
	}
327
328
	/**
329
	 * Get formatted date and time of first valid mandate.
330
	 *
331
	 * @param string $customer_id    Mollie customer ID.
332
	 * @param string $payment_method Payment method.
333
	 *
334
	 * @return null|DateTime
335
	 * @throws \Exception Throws exception for mandates on failed request or invalid response.
336
	 */
337
	public function get_first_valid_mandate_datetime( $customer_id, $payment_method = null ) {
338
		$mandates = $this->get_mandates( $customer_id );
339
340
		$mollie_method = Methods::transform( $payment_method );
341
342
		if ( ! isset( $mandates->_embedded ) ) {
343
			throw new \Exception( 'No embedded data in Mollie response.' );
344
		}
345
346
		foreach ( $mandates->_embedded as $mandate ) {
347
			if ( $mollie_method !== $mandate->method ) {
348
				continue;
349
			}
350
351
			if ( 'valid' !== $mandate->status ) {
352
				continue;
353
			}
354
355
			if ( ! isset( $valid_mandates ) ) {
356
				$valid_mandates = array();
357
			}
358
359
			// @codingStandardsIgnoreStart
360
			$valid_mandates[ $mandate->createdAt ] = $mandate;
361
			// @codingStandardsIgnoreEnd
362
		}
363
364
		if ( isset( $valid_mandates ) ) {
365
			ksort( $valid_mandates );
366
367
			$mandate = array_shift( $valid_mandates );
368
369
			// @codingStandardsIgnoreStart
370
			$create_date = new DateTime( $mandate->createdAt );
371
			// @codingStandardsIgnoreEnd
372
373
			return $create_date;
374
		}
375
376
		return null;
377
	}
378
}
379