Failed Conditions
Push — develop ( def963...184746 )
by Remco
02:41
created

src/Client.php (2 issues)

1
<?php
2
/**
3
 * Adyen client
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2019 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Gateways\Adyen
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Adyen;
12
13
use Pronamic\WordPress\Pay\Core\Gateway as Core_Gateway;
14
use Pronamic\WordPress\Pay\Core\XML\Security;
15
use WP_Error;
16
17
/**
18
 * Adyen client
19
 *
20
 * @author  Remco Tolsma
21
 * @version 1.0.0
22
 * @since   1.0.0
23
 * @link    https://github.com/adyenpayments/php/blob/master/generatepaymentform.php
24
 */
25
class Client {
26
	/**
27
	 * API endpoint test URL.
28
	 *
29
	 * @var string
30
	 */
31
	const API_URL_TEST = 'https://checkout-test.adyen.com/v41/';
32
33
	/**
34
	 * API endpoint live URL suffix.
35
	 *
36
	 * @var string
37
	 */
38
	const API_URL_LIVE = 'https://%s-checkout-live.adyenpayments.com/checkout/v41/';
39
40
	/**
41
	 * Mode.
42
	 *
43
	 * @var string
44
	 */
45
	private $mode;
46
47
	/**
48
	 * API Key.
49
	 *
50
	 * @var string
51
	 */
52
	private $api_key;
53
54
	/**
55
	 * API Live URL Prefix.
56
	 *
57
	 * @var string
58
	 */
59
	private $api_live_url_prefix;
60
61
	/**
62
	 * Merchant Account.
63
	 *
64
	 * @var string
65
	 */
66
	private $merchant_account;
67
68
	/**
69
	 * Error
70
	 *
71
	 * @var WP_Error
72
	 */
73
	private $error;
74
75
	/**
76
	 * Constructs and initializes an Adyen client object.
77
	 *
78
	 * @param string $api_key             Adyen API key.
79
	 * @param string $api_live_url_prefix Adyen API live URL prefix.
80
	 */
81
	public function __construct( $api_key, $api_live_url_prefix ) {
82
		$this->api_key             = $api_key;
83
		$this->api_live_url_prefix = $api_live_url_prefix;
84
	}
85
86
	/**
87
	 * Set mode.
88
	 *
89
	 * @param string $mode Mode.
90
	 */
91
	public function set_mode( $mode ) {
92
		$this->mode = $mode;
93
	}
94
95
	/**
96
	 * Set merchant account.
97
	 *
98
	 * @param string $merchant_account Merchant account.
99
	 */
100
	public function set_merchant_account( $merchant_account ) {
101
		$this->merchant_account = $merchant_account;
102
	}
103
104
	/**
105
	 * Error
106
	 *
107
	 * @return WP_Error
108
	 */
109
	public function get_error() {
110
		return $this->error;
111
	}
112
113
	/**
114
	 * Get API URL for current mode.
115
	 *
116
	 * @return string
117
	 */
118
	public function get_api_url() {
119
		if ( Core_Gateway::MODE_TEST === $this->mode ) {
120
			return self::API_URL_TEST;
121
		}
122
123
		return sprintf( self::API_URL_LIVE, $this->api_live_url_prefix );
124
	}
125
126
	/**
127
	 * Send request with the specified action and parameters
128
	 *
129
	 * @param string       $end_point              Requested endpoint.
130
	 * @param string       $method                 HTTP method to use.
131
	 * @param array|object $data                   Request data.
132
	 * @param int          $expected_response_code Expected response code.
133
	 *
134
	 * @return bool|object
135
	 */
136
	private function send_request( $end_point, $method = 'GET', $data = null, $expected_response_code = 200 ) {
137
		// Request.
138
		$url = $this->get_api_url() . $end_point;
139
140
		$response = wp_remote_request(
141
			$url,
142
			array(
143
				'method'  => $method,
144
				'headers' => array(
145
					'X-API-key'    => $this->api_key,
146
					'Content-Type' => 'application/json',
147
				),
148
				'body'    => wp_json_encode( $data ),
149
			)
150
		);
151
152
		// Response code.
153
		$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

153
		$response_code = wp_remote_retrieve_response_code( /** @scrutinizer ignore-type */ $response );
Loading history...
154
155
		if ( $expected_response_code != $response_code ) { // WPCS: loose comparison ok.
156
			$this->error = new WP_Error( 'adyen_error', 'Unexpected response code.' );
157
		}
158
159
		// Body.
160
		$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

160
		$body = wp_remote_retrieve_body( /** @scrutinizer ignore-type */ $response );
Loading history...
161
162
		$data = json_decode( $body );
163
164
		if ( ! is_object( $data ) ) {
165
			$this->error = new WP_Error( 'adyen_error', 'Could not parse response.' );
166
167
			return false;
168
		}
169
170
		// Adyen error.
171
		if ( isset( $data->errorCode, $data->message ) ) {
172
			$message = sprintf(
173
				'%1$s %2$s - %3$s',
174
				$data->status,
175
				$data->errorCode,
176
				$data->message
177
			);
178
179
			$this->error = new WP_Error( 'adyen_error', $message, $data->errorCode );
180
181
			return false;
182
		}
183
184
		return $data;
185
	}
186
187
	/**
188
	 * Create payment.
189
	 *
190
	 * @param PaymentRequest $request Payment request.
191
	 *
192
	 * @return bool|object
193
	 */
194
	public function create_payment( PaymentRequest $request ) {
195
		return $this->send_request( 'payments/', 'POST', $request->get_json(), 200 );
196
	}
197
198
	/**
199
	 * Create payment session.
200
	 *
201
	 * @param PaymentSessionRequest $request Payment session request.
202
	 *
203
	 * @return bool|object
204
	 */
205
	public function create_payment_session( PaymentSessionRequest $request ) {
206
207
		return $this->send_request( 'paymentSession', 'POST', $request->get_json(), 200 );
208
	}
209
210
	/**
211
	 * Get payments.
212
	 *
213
	 * @return bool|object
214
	 */
215
	public function get_payments() {
216
		return $this->send_request( 'payments/', 'GET' );
217
	}
218
219
	/**
220
	 * Get payment details.
221
	 *
222
	 * @param string $payload Payload to get payment details for.
223
	 *
224
	 * @return bool|object
225
	 */
226
	public function get_payment_details( $payload ) {
227
		if ( empty( $payload ) ) {
228
			return false;
229
		}
230
231
		$data = array(
232
			'details' => array(
233
				'payload' => $payload,
234
			),
235
		);
236
237
		return $this->send_request( 'payments/details', 'POST', $data );
238
	}
239
240
	/**
241
	 * Get payment result.
242
	 *
243
	 * @param string $payload Payload to get payment details for.
244
	 *
245
	 * @return bool|object
246
	 */
247
	public function get_payment_result( $payload ) {
248
		if ( empty( $payload ) ) {
249
			return false;
250
		}
251
252
		$data = array(
253
			'payload' => $payload,
254
		);
255
256
		return $this->send_request( 'payments/result', 'POST', $data );
257
	}
258
259
	/**
260
	 * Get issuers.
261
	 *
262
	 * @param string $payment_method Payment method.
263
	 *
264
	 * @return array|bool
265
	 */
266
	public function get_issuers( $payment_method = null ) {
267
		// Check payment method.
268
		if ( empty( $payment_method ) ) {
269
			return false;
270
		}
271
272
		// Get issuers.
273
		$methods = $this->get_payment_methods();
274
275
		if ( false === $methods ) {
276
			return false;
277
		}
278
279
		$issuers = array();
280
281
		foreach ( $methods as $method_type => $method ) {
282
			if ( $payment_method !== $method_type ) {
283
				continue;
284
			}
285
286
			if ( ! isset( $method['details']['issuer'] ) ) {
287
				return false;
288
			}
289
290
			foreach ( $method['details']['issuer']->items as $issuer ) {
291
				$id   = Security::filter( $issuer->id );
292
				$name = Security::filter( $issuer->name );
293
294
				$issuers[ $id ] = $name;
295
			}
296
		}
297
298
		return $issuers;
299
	}
300
301
	/**
302
	 * Get payment methods
303
	 *
304
	 * @param string $recurring_type Recurring type.
305
	 *
306
	 * @return array|bool
307
	 */
308
	public function get_payment_methods() {
309
		$data = array(
310
			'merchantAccount'       => $this->merchant_account,
311
			'allowedPaymentMethods' => array(),
312
		);
313
314
		$response = $this->send_request( 'paymentMethods/', 'POST', $data );
315
316
		if ( false === $response ) {
317
			return false;
318
		}
319
320
		$payment_methods = array();
321
322
		if ( isset( $response->paymentMethods ) ) {
323
			foreach ( $response->paymentMethods as $payment_method ) {
324
				$type = Security::filter( $payment_method->type );
325
				$name = Security::filter( $payment_method->name );
326
327
				$method = array(
328
					'name'    => $name,
329
					'details' => array(),
330
				);
331
332
				if ( isset( $payment_method->details ) ) {
333
					foreach ( $payment_method->details as $detail ) {
334
						$key = $detail->key;
335
336
						$method['details'][ $key ] = $detail;
337
338
						unset( $method['details'][ $key ]->key );
339
					}
340
				}
341
342
				$payment_methods[ $type ] = $method;
343
			}
344
		}
345
346
		return $payment_methods;
347
	}
348
}
349