Failed Conditions
Push — develop ( 75281a...7efbd4 )
by Reüel
03:42
created

Client::get_error()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 2
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
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/v40/';
32
33
	/**
34
	 * API endpoint live URL suffix.
35
	 *
36
	 * @var string
37
	 */
38
	const API_URL_LIVE_SUFFIX = '-checkout-live.adyenpayments.com/checkout';
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(
124
			'https://%1$s%2$s',
125
			$this->api_live_url_prefix,
126
			self::API_URL_LIVE_SUFFIX
127
		);
128
	}
129
130
	/**
131
	 * Send request with the specified action and parameters
132
	 *
133
	 * @param string $end_point              Requested endpoint.
134
	 * @param string $method                 HTTP method to use.
135
	 * @param array  $data                   Request data.
136
	 * @param int    $expected_response_code Expected response code.
137
	 *
138
	 * @return bool|object
139
	 */
140
	private function send_request( $end_point, $method = 'GET', array $data = array(), $expected_response_code = 200 ) {
141
		// Request.
142
		$url = $this->get_api_url() . $end_point;
143
144
		$response = wp_remote_request(
145
			$url,
146
			array(
147
				'method'  => $method,
148
				'headers' => array(
149
					'X-API-key'    => $this->api_key,
150
					'Content-Type' => 'application/json',
151
				),
152
				'body'    => wp_json_encode( $data ),
153
			)
154
		);
155
156
		// Response code.
157
		$response_code = wp_remote_retrieve_response_code( $response );
0 ignored issues
show
Bug introduced by
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

157
		$response_code = wp_remote_retrieve_response_code( /** @scrutinizer ignore-type */ $response );
Loading history...
158
159
		if ( $expected_response_code != $response_code ) { // WPCS: loose comparison ok.
160
			$this->error = new WP_Error( 'adyen_error', 'Unexpected response code.' );
161
		}
162
163
		// Body.
164
		$body = wp_remote_retrieve_body( $response );
0 ignored issues
show
Bug introduced by
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

164
		$body = wp_remote_retrieve_body( /** @scrutinizer ignore-type */ $response );
Loading history...
165
166
		$data = json_decode( $body );
167
168
		if ( ! is_object( $data ) ) {
169
			$this->error = new WP_Error( 'adyen_error', 'Could not parse response.' );
170
171
			return false;
172
		}
173
174
		// Adyen error.
175
		if ( isset( $data->errorCode, $data->message ) ) {
176
			$message = sprintf(
177
				'%1$s %2$s - %3$s',
178
				$data->status,
179
				$data->errorCode,
180
				$data->message
181
			);
182
183
			$this->error = new WP_Error( 'adyen_error', $message, $data->errorCode );
184
185
			return false;
186
		}
187
188
		return $data;
189
	}
190
191
	/**
192
	 * Create payment.
193
	 *
194
	 * @param PaymentRequest $request Payment request.
195
	 *
196
	 * @return bool|object
197
	 */
198
	public function create_payment( PaymentRequest $request ) {
199
		return $this->send_request( 'payments/', 'POST', $request->get_array(), 200 );
200
	}
201
202
	/**
203
	 * Get payments.
204
	 *
205
	 * @return bool|object
206
	 */
207
	public function get_payments() {
208
		return $this->send_request( 'payments/', 'GET' );
209
	}
210
211
	/**
212
	 * Get payment details.
213
	 *
214
	 * @param string $payload Payload to get payment details for.
215
	 *
216
	 * @return bool|object
217
	 */
218
	public function get_payment_details( $payload ) {
219
		if ( empty( $payload ) ) {
220
			return false;
221
		}
222
223
		$data = array(
224
			'details' => array(
225
				'payload' => $payload,
226
			),
227
		);
228
229
		return $this->send_request( 'payments/details', 'POST', $data );
230
	}
231
232
	/**
233
	 * Get issuers.
234
	 *
235
	 * @param string $payment_method Payment method.
236
	 *
237
	 * @return array|bool
238
	 */
239
	public function get_issuers( $payment_method = null ) {
240
		// Check payment method.
241
		if ( empty( $payment_method ) ) {
242
			return false;
243
		}
244
245
		// Get issuers.
246
		$methods = $this->get_payment_methods();
247
248
		if ( false === $methods ) {
0 ignored issues
show
introduced by
The condition false === $methods is always true.
Loading history...
249
			return false;
250
		}
251
252
		$issuers = array();
253
254
		foreach ( $methods as $method_type => $method ) {
255
			if ( $payment_method !== $method_type ) {
256
				continue;
257
			}
258
259
			if ( ! isset( $method['details']['issuer'] ) ) {
260
				return false;
261
			}
262
263
			foreach ( $method['details']['issuer']['items'] as $issuer ) {
264
				$id   = Security::filter( $issuer['id'] );
265
				$name = Security::filter( $issuer['name'] );
266
267
				$issuers[ $id ] = $name;
268
			}
269
		}
270
271
		return $issuers;
272
	}
273
274
	/**
275
	 * Get payment methods
276
	 *
277
	 * @param string $recurring_type Recurring type.
278
	 *
279
	 * @return array|bool
280
	 */
281
	public function get_payment_methods() {
282
		$data = array(
283
			'merchantAccount'       => $this->merchant_account,
284
			'allowedPaymentMethods' => array(),
285
		);
286
287
		$response = $this->send_request( 'paymentMethods/', 'POST', $data );
288
289
		if ( false === $response ) {
290
			return false;
291
		}
292
293
		$payment_methods = array();
294
295
		if ( isset( $response->paymentMethods ) ) {
296
			foreach ( $response->paymentMethods as $payment_method ) {
297
				$type = Security::filter( $payment_method->type );
298
				$name = Security::filter( $payment_method->name );
299
300
				$method = array(
301
					'name' => $name,
302
				);
303
304
				if ( isset( $payment_method->details ) ) {
305
					$details = json_decode( wp_json_encode( $payment_method->details ), true );
0 ignored issues
show
Bug introduced by
It seems like wp_json_encode($payment_method->details) can also be of type false; however, parameter $json of json_decode() does only seem to accept string, 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

305
					$details = json_decode( /** @scrutinizer ignore-type */ wp_json_encode( $payment_method->details ), true );
Loading history...
306
307
					foreach ( $details as $detail ) {
308
						$key = $detail['key'];
309
310
						$method['details'][ $key ] = $detail;
311
312
						unset( $method['details'][ $key ]['key'] );
313
					}
314
				}
315
316
				$payment_methods[ $type ] = $method;
317
			}
318
		}
319
320
		return $payment_methods;
321
	}
322
}
323