Failed Conditions
Push — develop ( 0c4589...6de45b )
by Reüel
24:44 queued 13:15
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
		return $this->send_request( 'paymentSession', 'POST', $request->get_json(), 200 );
207
	}
208
209
	/**
210
	 * Get payments.
211
	 *
212
	 * @return bool|object
213
	 */
214
	public function get_payments() {
215
		return $this->send_request( 'payments/', 'GET' );
216
	}
217
218
	/**
219
	 * Get payment details.
220
	 *
221
	 * @param string $payload Payload to get payment details for.
222
	 *
223
	 * @return bool|object
224
	 */
225
	public function get_payment_details( $payload ) {
226
		if ( empty( $payload ) ) {
227
			return false;
228
		}
229
230
		$data = array(
231
			'details' => array(
232
				'payload' => $payload,
233
			),
234
		);
235
236
		return $this->send_request( 'payments/details', 'POST', $data );
237
	}
238
239
	/**
240
	 * Get payment result.
241
	 *
242
	 * @param string $payload Payload to get payment details for.
243
	 *
244
	 * @return bool|object
245
	 */
246
	public function get_payment_result( $payload ) {
247
		if ( empty( $payload ) ) {
248
			return false;
249
		}
250
251
		$data = array(
252
			'payload' => $payload,
253
		);
254
255
		return $this->send_request( 'payments/result', 'POST', $data );
256
	}
257
258
	/**
259
	 * Get issuers.
260
	 *
261
	 * @param string $payment_method Payment method.
262
	 *
263
	 * @return array|bool
264
	 */
265
	public function get_issuers( $payment_method = null ) {
266
		// Check payment method.
267
		if ( empty( $payment_method ) ) {
268
			return false;
269
		}
270
271
		// Get issuers.
272
		$methods = $this->get_payment_methods();
273
274
		if ( false === $methods ) {
275
			return false;
276
		}
277
278
		$issuers = array();
279
280
		foreach ( $methods as $method_type => $method ) {
281
			if ( $payment_method !== $method_type ) {
282
				continue;
283
			}
284
285
			if ( ! isset( $method['details']['issuer'] ) ) {
286
				return false;
287
			}
288
289
			foreach ( $method['details']['issuer']->items as $issuer ) {
290
				$id   = Security::filter( $issuer->id );
291
				$name = Security::filter( $issuer->name );
292
293
				$issuers[ $id ] = $name;
294
			}
295
		}
296
297
		return $issuers;
298
	}
299
300
	/**
301
	 * Get payment methods.
302
	 *
303
	 * @return array|bool
304
	 */
305
	public function get_payment_methods() {
306
		$data = array(
307
			'merchantAccount'       => $this->merchant_account,
308
			'allowedPaymentMethods' => array(),
309
		);
310
311
		$response = $this->send_request( 'paymentMethods/', 'POST', $data );
312
313
		if ( false === $response ) {
314
			return false;
315
		}
316
317
		$payment_methods = array();
318
319
		if ( isset( $response->paymentMethods ) ) {
320
			foreach ( $response->paymentMethods as $payment_method ) {
321
				$type = Security::filter( $payment_method->type );
322
				$name = Security::filter( $payment_method->name );
323
324
				$method = array(
325
					'name'    => $name,
326
					'details' => array(),
327
				);
328
329
				if ( isset( $payment_method->details ) ) {
330
					foreach ( $payment_method->details as $detail ) {
331
						$key = $detail->key;
332
333
						$method['details'][ $key ] = $detail;
334
335
						unset( $method['details'][ $key ]->key );
336
					}
337
				}
338
339
				$payment_methods[ $type ] = $method;
340
			}
341
		}
342
343
		return $payment_methods;
344
	}
345
}
346