Failed Conditions
Push — master ( 25af54...272cf6 )
by Reüel
09:37 queued 03:46
created

src/Client.php (2 issues)

Labels
Severity
1
<?php
2
3
namespace Pronamic\WordPress\Pay\Gateways\Mollie;
4
5
use Pronamic\WordPress\DateTime\DateTime;
6
use Pronamic\WordPress\Pay\Core\XML\Security;
7
use WP_Error;
8
9
/**
10
 * Title: Mollie
11
 * Description:
12
 * Copyright: 2005-2019 Pronamic
13
 * Company: Pronamic
14
 *
15
 * @author  Remco Tolsma
16
 * @version 2.0.0
17
 * @since   1.0.0
18
 */
19
class Client {
20
	/**
21
	 * Mollie API endpoint URL
22
	 *
23
	 * @var string
24
	 */
25
	const API_URL = 'https://api.mollie.nl/v1/';
26
27
	/**
28
	 * Mollie API Key ID
29
	 *
30
	 * @var string
31
	 */
32
	private $api_key;
33
34
	/**
35
	 * Mode
36
	 *
37
	 * @since 1.1.9
38
	 * @var string
39
	 */
40
	private $mode;
41
42
	/**
43
	 * Error
44
	 *
45
	 * @var WP_Error
46
	 */
47
	private $error;
48
49
	/**
50
	 * Constructs and initializes an Mollie client object
51
	 *
52
	 * @param string $api_key
53
	 */
54 40
	public function __construct( $api_key ) {
55 40
		$this->api_key = $api_key;
56 40
	}
57
58
	/**
59
	 * Set mode
60
	 *
61
	 * @since 1.1.9
62
	 * @param string $mode
63
	 */
64 40
	public function set_mode( $mode ) {
65 40
		$this->mode = $mode;
66 40
	}
67
68
	/**
69
	 * Error
70
	 *
71
	 * @return WP_Error
72
	 */
73 5
	public function get_error() {
74 5
		return $this->error;
75
	}
76
77
	/**
78
	 * Send request with the specified action and parameters
79
	 *
80
	 * @param string $end_point
81
	 * @param string $method
82
	 * @param array $data
83
	 * @param int $expected_response_code
84
	 *
85
	 * @return bool|object
86
	 */
87 10
	private function send_request( $end_point, $method = 'GET', array $data = array(), $expected_response_code = 200 ) {
88
		// Request
89 10
		$url = self::API_URL . $end_point;
90
91 10
		$response = wp_remote_request(
92 10
			$url,
93
			array(
94 10
				'method'  => $method,
95
				'headers' => array(
96 10
					'Authorization' => 'Bearer ' . $this->api_key,
97
				),
98 10
				'body'    => $data,
99
			)
100
		);
101
102
		// Response code
103 10
		$response_code = wp_remote_retrieve_response_code( $response );
0 ignored issues
show
It seems like $response can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_response_code() does only seem to accept array, 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

103
		$response_code = wp_remote_retrieve_response_code( /** @scrutinizer ignore-type */ $response );
Loading history...
104
105 10
		if ( $expected_response_code != $response_code ) { // WPCS: loose comparison ok.
106 10
			$this->error = new WP_Error( 'mollie_error', 'Unexpected response code.' );
107
		}
108
109
		// Body
110 10
		$body = wp_remote_retrieve_body( $response );
0 ignored issues
show
It seems like $response can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_body() does only seem to accept array, 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

110
		$body = wp_remote_retrieve_body( /** @scrutinizer ignore-type */ $response );
Loading history...
111
112 10
		$data = json_decode( $body );
113
114 10
		if ( ! is_object( $data ) ) {
115
			$this->error = new WP_Error( 'mollie_error', 'Could not parse response.' );
116
117
			return false;
118
		}
119
120
		// Mollie error
121 10
		if ( isset( $data->error, $data->error->message ) ) {
122 10
			$this->error = new \WP_Error( 'mollie_error', $data->error->message, $data->error );
123
124 10
			return false;
125
		}
126
127
		return $data;
128
	}
129
130
	public function create_payment( PaymentRequest $request ) {
131
		return $this->send_request( 'payments/', 'POST', $request->get_array(), 201 );
132
	}
133
134
	public function get_payments() {
135
		return $this->send_request( 'payments/', 'GET' );
136
	}
137
138
	public function get_payment( $payment_id ) {
139
		if ( empty( $payment_id ) ) {
140
			return false;
141
		}
142
143
		return $this->send_request( 'payments/' . $payment_id, 'GET' );
144
	}
145
146
	/**
147
	 * Get issuers
148
	 *
149
	 * @return array|bool
150
	 */
151 3
	public function get_issuers() {
152 3
		$response = $this->send_request( 'issuers/', 'GET' );
153
154 3
		if ( false === $response ) {
155 3
			return false;
156
		}
157
158
		$issuers = array();
159
160
		if ( isset( $response->data ) ) {
161
			foreach ( $response->data as $issuer ) {
162
				if ( Methods::IDEAL === $issuer->method ) {
163
					$id   = Security::filter( $issuer->id );
164
					$name = Security::filter( $issuer->name );
165
166
					$issuers[ $id ] = $name;
167
				}
168
			}
169
		}
170
171
		return $issuers;
172
	}
173
174
	/**
175
	 * Get payment methods
176
	 *
177
	 * @param string $recurring_type Recurring type.
178
	 *
179
	 * @return array|bool
180
	 */
181 2
	public function get_payment_methods( $recurring_type = '' ) {
182 2
		$data = array();
183
184 2
		if ( '' !== $recurring_type ) {
185 2
			$data['recurringType'] = $recurring_type;
186
		}
187
188 2
		$response = $this->send_request( 'methods/', 'GET', $data );
189
190 2
		if ( false === $response ) {
191 2
			return false;
192
		}
193
194
		$payment_methods = array();
195
196
		if ( isset( $response->data ) ) {
197
			foreach ( $response->data as $payment_method ) {
198
				$id   = Security::filter( $payment_method->id );
199
				$name = Security::filter( $payment_method->description );
200
201
				$payment_methods[ $id ] = $name;
202
			}
203
		}
204
205
		return $payment_methods;
206
	}
207
208
	/**
209
	 * Create customer.
210
	 *
211
	 * @since 1.1.6
212
	 *
213
	 * @param string $email Customer email address.
214
	 * @param string $name  Customer name.
215
	 *
216
	 * @return string|bool
217
	 */
218
	public function create_customer( $email, $name ) {
219
		if ( empty( $email ) ) {
220
			return false;
221
		}
222
223
		$response = $this->send_request(
224
			'customers/',
225
			'POST',
226
			array(
227
				'name'  => $name,
228
				'email' => $email,
229
			),
230
			201
231
		);
232
233
		if ( false === $response ) {
234
			return false;
235
		}
236
237
		if ( ! isset( $response->id ) ) {
238
			return false;
239
		}
240
241
		return $response->id;
242
	}
243
244
	/**
245
	 * Get customer.
246
	 *
247
	 * @param string $customer_id Mollie customer ID.
248
	 *
249
	 * @since unreleased
250
	 *
251
	 * @return object|bool
252
	 */
253 5
	public function get_customer( $customer_id ) {
254 5
		if ( empty( $customer_id ) ) {
255
			return false;
256
		}
257
258 5
		$response = $this->send_request( 'customers/' . $customer_id, 'GET', array(), 200 );
259
260 5
		if ( false === $response ) {
261 5
			return false;
262
		}
263
264
		if ( is_wp_error( $this->error ) ) {
265
			return false;
266
		}
267
268
		return $response;
269
	}
270
271
	/**
272
	 * Get mandates for customer.
273
	 *
274
	 * @param string $customer_id Mollie customer ID.
275
	 *
276
	 * @return object|bool
277
	 */
278
	public function get_mandates( $customer_id ) {
279
		if ( '' === $customer_id ) {
280
			return false;
281
		}
282
283
		return $this->send_request( 'customers/' . $customer_id . '/mandates?count=250', 'GET' );
284
	}
285
286
	/**
287
	 * Is there a valid mandate for customer?
288
	 *
289
	 * @param string      $customer_id    Mollie customer ID.
290
	 * @param string|null $payment_method Payment method to find mandates for.
291
	 *
292
	 * @return boolean
293
	 */
294
	public function has_valid_mandate( $customer_id, $payment_method = null ) {
295
		$mandates = $this->get_mandates( $customer_id );
296
297
		if ( ! $mandates ) {
298
			return false;
299
		}
300
301
		$mollie_method = Methods::transform( $payment_method );
302
303
		foreach ( $mandates->data as $mandate ) {
304
			if ( $mollie_method !== $mandate->method ) {
305
				continue;
306
			}
307
308
			if ( 'valid' === $mandate->status ) {
309
				return true;
310
			}
311
		}
312
313
		return false;
314
	}
315
316
	/**
317
	 * Get formatted date and time of first valid mandate.
318
	 *
319
	 * @param string $customer_id    Mollie customer ID.
320
	 * @param string $payment_method Payment method.
321
	 *
322
	 * @return null|DateTime
323
	 */
324
	public function get_first_valid_mandate_datetime( $customer_id, $payment_method = null ) {
325
		$mandates = $this->get_mandates( $customer_id );
326
327
		if ( ! $mandates ) {
328
			return null;
329
		}
330
331
		$mollie_method = Methods::transform( $payment_method );
332
333
		foreach ( $mandates->data as $mandate ) {
334
			if ( $mollie_method !== $mandate->method ) {
335
				continue;
336
			}
337
338
			if ( 'valid' !== $mandate->status ) {
339
				continue;
340
			}
341
342
			if ( ! isset( $valid_mandates ) ) {
343
				$valid_mandates = array();
344
			}
345
346
			// @codingStandardsIgnoreStart
347
			$valid_mandates[ $mandate->createdDatetime ] = $mandate;
348
			// @codingStandardsIgnoreEnd
349
		}
350
351
		if ( isset( $valid_mandates ) ) {
352
			ksort( $valid_mandates );
353
354
			$mandate = array_shift( $valid_mandates );
355
356
			// @codingStandardsIgnoreStart
357
			$create_date = new DateTime( $mandate->createdDatetime );
358
			// @codingStandardsIgnoreEnd
359
360
			return $create_date;
361
		}
362
363
		return null;
364
	}
365
}
366