Passed
Push — develop ( 4d0f7f...969851 )
by Reüel
05:00 queued 40s
created

Gateway   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 341
Duplicated Lines 0 %

Test Coverage

Coverage 10.71%

Importance

Changes 0
Metric Value
eloc 146
dl 0
loc 341
ccs 15
cts 140
cp 0.1071
rs 9.92
c 0
b 0
f 0
wmc 31

7 Methods

Rating   Name   Duplication   Size   Complexity  
A get_supported_payment_methods() 0 9 1
A __construct() 0 7 1
A payment_redirect() 0 43 5
A get_available_payment_methods() 0 21 3
B get_issuers() 0 48 9
A update_status() 0 22 3
B start() 0 110 9
1
<?php
2
/**
3
 * Gateway
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 Exception;
14
use InvalidArgumentException;
15
use Locale;
16
use Pronamic\WordPress\Pay\Core\Gateway as Core_Gateway;
17
use Pronamic\WordPress\Pay\Core\PaymentMethods;
18
use Pronamic\WordPress\Pay\Core\Util as Core_Util;
19
use Pronamic\WordPress\Pay\Payments\Payment;
20
use Pronamic\WordPress\Pay\Plugin;
21
use WP_Error;
22
23
/**
24
 * Gateway
25
 *
26
 * @link https://github.com/adyenpayments/php/blob/master/generatepaymentform.php
27
 *
28
 * @author  Remco Tolsma
29
 * @version 1.0.0
30
 * @since   1.0.0
31
 */
32
class Gateway extends Core_Gateway {
33
	/**
34
	 * Slug of this gateway.
35
	 *
36
	 * @var string
37
	 */
38
	const SLUG = 'adyen';
39
40
	/**
41
	 * Web SDK version.
42
	 *
43
	 * @link https://docs.adyen.com/developers/checkout/web-sdk/release-notes-web-sdk
44
	 *
45
	 * @var string
46
	 */
47
	const SDK_VERSION = '1.9.2';
48
49
	/**
50
	 * Client.
51
	 *
52
	 * @var Client
53
	 */
54
	public $client;
55
56
	/**
57
	 * Constructs and initializes an Adyen gateway.
58
	 *
59
	 * @param Config $config Config.
60
	 */
61 2
	public function __construct( Config $config ) {
62 2
		parent::__construct( $config );
63
64 2
		$this->set_method( self::METHOD_HTTP_REDIRECT );
65 2
		$this->set_slug( self::SLUG );
66
67 2
		$this->client = new Client( $config );
68 2
	}
69
70
	/**
71
	 * Get supported payment methods
72
	 *
73
	 * @see Core_Gateway::get_supported_payment_methods()
74
	 */
75 1
	public function get_supported_payment_methods() {
76
		return array(
77 1
			PaymentMethods::BANCONTACT,
78 1
			PaymentMethods::CREDIT_CARD,
79 1
			PaymentMethods::DIRECT_DEBIT,
80 1
			PaymentMethods::GIROPAY,
81 1
			PaymentMethods::IDEAL,
82 1
			PaymentMethods::MAESTRO,
83 1
			PaymentMethods::SOFORT,
84 1
		);
85
	}
86
87
	/**
88
	 * Start.
89
	 *
90
	 * @see Plugin::start()
91
	 *
92
	 * @param Payment $payment Payment.
93
	 * @return void
94
	 */
95
	public function start( Payment $payment ) {
96
		// Amount.
97
		try {
98
			$amount = AmountTransformer::transform( $payment->get_total_amount() );
99
		} catch ( InvalidArgumentException $e ) {
100
			$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
101
102
			return;
103
		}
104
105
		// Payment method type.
106
		$payment_method_type = PaymentMethodType::transform( $payment->get_method() );
107
108
		// Country.
109
		$locale = get_locale();
110
111
		$customer = $payment->get_customer();
112
113
		if ( null !== $customer ) {
114
			$locale = $customer->get_locale();
115
		}
116
117
		$locale = strval( $locale );
118
119
		$country_code = Locale::getRegion( $locale );
120
121
		/*
122
		 * API Integration
123
		 *
124
		 * @link https://docs.adyen.com/api-explorer/#/PaymentSetupAndVerificationService/v41/payments
125
		 */
126
		$api_integration_payment_method_types = array(
127
			PaymentMethodType::IDEAL,
128
			PaymentMethodType::DIRECT_EBANKING,
129
		);
130
131
		if ( in_array( $payment_method_type, $api_integration_payment_method_types, true ) ) {
132
			$payment_method = new PaymentMethod( $payment_method_type );
133
134
			if ( PaymentMethodType::IDEAL === $payment_method_type ) {
135
				$payment_method = new PaymentMethodIDeal( $payment_method_type, (string) $payment->get_issuer() );
136
			}
137
138
			// API integration.
139
			$payment_request = new PaymentRequest(
140
				$amount,
141
				$this->config->get_merchant_account(),
142
				strval( $payment->get_id() ),
143
				$payment->get_return_url(),
144
				$payment_method
145
			);
146
147
			$payment_request->set_country_code( $country_code );
148
149
			PaymentRequestHelper::complement( $payment, $payment_request );
150
151
			try {
152
				$payment_response = $this->client->create_payment( $payment_request );
153
			} catch ( Exception $e ) {
154
				$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
155
156
				return;
157
			}
158
159
			$payment->set_transaction_id( $payment_response->get_psp_reference() );
160
161
			$redirect = $payment_response->get_redirect();
162
163
			if ( null !== $redirect ) {
164
				$payment->set_action_url( $redirect->get_url() );
165
			}
166
167
			// Return early so SDK integration code will not be executed for API integration.
168
			return;
169
		}
170
171
		/*
172
		 * SDK Integration
173
		 *
174
		 * @link https://docs.adyen.com/api-explorer/#/PaymentSetupAndVerificationService/v41/paymentSession
175
		 */
176
		$payment_session_request = new PaymentSessionRequest(
177
			$amount,
178
			$this->config->get_merchant_account(),
179
			strval( $payment->get_id() ),
180
			$payment->get_return_url(),
181
			$country_code
182
		);
183
184
		PaymentRequestHelper::complement( $payment, $payment_session_request );
185
186
		$payment_session_request->set_origin( home_url() );
187
		$payment_session_request->set_sdk_version( self::SDK_VERSION );
188
189
		if ( null !== $payment_method_type ) {
190
			$payment_session_request->set_allowed_payment_methods( array( $payment_method_type ) );
191
		}
192
193
		try {
194
			$payment_session_response = $this->client->create_payment_session( $payment_session_request );
195
		} catch ( Exception $e ) {
196
			$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
197
198
			return;
199
		}
200
201
		$payment->set_meta( 'adyen_sdk_version', self::SDK_VERSION );
202
		$payment->set_meta( 'adyen_payment_session', $payment_session_response->get_payment_session() );
203
204
		$payment->set_action_url( $payment->get_pay_redirect_url() );
205
	}
206
207
	/**
208
	 * Payment redirect.
209
	 *
210
	 * @param Payment $payment Payment.
211
	 *
212
	 * @return void
213
	 */
214
	public function payment_redirect( Payment $payment ) {
215
		$sdk_version     = $payment->get_meta( 'adyen_sdk_version' );
216
		$payment_session = $payment->get_meta( 'adyen_payment_session' );
217
218
		if ( empty( $sdk_version ) || empty( $payment_session ) ) {
219
			return;
220
		}
221
222
		$url = sprintf(
223
			'https://checkoutshopper-%s.adyen.com/checkoutshopper/assets/js/sdk/checkoutSDK.%s.min.js',
224
			( self::MODE_TEST === $payment->get_mode() ? 'test' : 'live' ),
225
			$sdk_version
226
		);
227
228
		wp_register_script(
229
			'pronamic-pay-adyen-checkout',
230
			$url,
231
			array(
232
				'jquery',
233
			),
234
			$sdk_version,
235
			false
236
		);
237
238
		wp_localize_script(
239
			'pronamic-pay-adyen-checkout',
240
			'pronamicPayAdyenCheckout',
241
			array(
242
				'paymentsResultUrl' => rest_url( Integration::REST_ROUTE_NAMESPACE . '/payments/result/' . $payment->config_id ),
243
				'paymentReturnUrl'  => $payment->get_return_url(),
244
				'paymentSession'    => $payment_session,
245
				'configObject'      => array(
246
					'context' => ( self::MODE_TEST === $payment->get_mode() ? 'test' : 'live' ),
247
				),
248
			)
249
		);
250
251
		// No cache.
252
		Core_Util::no_cache();
253
254
		require __DIR__ . '/../views/checkout.php';
255
256
		exit;
257
	}
258
259
	/**
260
	 * Update status of the specified payment.
261
	 *
262
	 * @param Payment $payment Payment.
263
	 *
264
	 * @return void
265
	 */
266
	public function update_status( Payment $payment ) {
267
		// Process payload on return.
268
		if ( ! filter_has_var( INPUT_GET, 'payload' ) ) {
269
			return;
270
		}
271
272
		$payload = filter_input( INPUT_GET, 'payload', FILTER_SANITIZE_STRING );
273
274
		$payment_result_request = new PaymentResultRequest( $payload );
275
276
		try {
277
			$payment_result_response = $this->client->get_payment_result( $payment_result_request );
278
279
			PaymentResultHelper::update_payment( $payment, $payment_result_response );
280
		} catch ( Exception $e ) {
281
			$note = sprintf(
282
				/* translators: %s: exception message */
283
				__( 'Error getting payment result: %s', 'pronamic_ideal' ),
284
				$e->getMessage()
285
			);
286
287
			$payment->add_note( $note );
288
		}
289
	}
290
291
	/**
292
	 * Get available payment methods.
293
	 *
294
	 * @see Core_Gateway::get_available_payment_methods()
295
	 */
296
	public function get_available_payment_methods() {
297
		$core_payment_methods = array();
298
299
		try {
300
			$payment_methods_response = $this->client->get_payment_methods();
301
		} catch ( Exception $e ) {
302
			$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
303
304
			return $core_payment_methods;
305
		}
306
307
		foreach ( $payment_methods_response->get_payment_methods() as $payment_method ) {
308
			$core_payment_method = PaymentMethodType::to_wp( $payment_method->get_type() );
309
310
			$core_payment_methods[] = $core_payment_method;
311
		}
312
313
		$core_payment_methods = array_filter( $core_payment_methods );
314
		$core_payment_methods = array_unique( $core_payment_methods );
315
316
		return $core_payment_methods;
317
	}
318
319
	/**
320
	 * Get issuers.
321
	 *
322
	 * @see Pronamic_WP_Pay_Gateway::get_issuers()
323
	 * @return array
324
	 */
325
	public function get_issuers() {
326
		$issuers = array();
327
328
		try {
329
			$payment_methods_response = $this->client->get_payment_methods();
330
		} catch ( Exception $e ) {
331
			$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
332
333
			return $issuers;
334
		}
335
336
		$payment_methods = $payment_methods_response->get_payment_methods();
337
338
		// Limit to iDEAL payment methods.
339
		$payment_methods = array_filter(
340
			$payment_methods,
341
			/**
342
			 * Check if payment method is iDEAL.
343
			 *
344
			 * @param PaymentMethod $payment_method Payment method.
345
			 * @return boolean True if payment method is iDEAL, false otherwise.
346
			 */
347
			function( $payment_method ) {
348
				return ( PaymentMethodType::IDEAL === $payment_method->get_type() );
349
			}
350
		);
351
352
		foreach ( $payment_methods as $payment_method ) {
353
			$details = $payment_method->get_details();
354
355
			if ( is_array( $details ) ) {
356
				foreach ( $details as $detail ) {
357
					if ( 'issuer' === $detail->key && 'select' === $detail->type ) {
358
						foreach ( $detail->items as $item ) {
359
							$issuers[ $item->id ] = $item->name;
360
						}
361
					}
362
				}
363
			}
364
		}
365
366
		if ( empty( $issuers ) ) {
367
			return $issuers;
368
		}
369
370
		return array(
371
			array(
372
				'options' => $issuers,
373
			),
374
		);
375
	}
376
}
377