Completed
Push — develop ( 689c44...94d907 )
by Reüel
14:41
created

Gateway::checkout_head()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
rs 10
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
		// Supported features.
68 2
		$this->supports = array();
69
70
		// Client.
71
		$this->client = new Client( $config );
72
	}
73
74
	/**
75 1
	 * Get supported payment methods
76
	 *
77 1
	 * @see Core_Gateway::get_supported_payment_methods()
78 1
	 */
79 1
	public function get_supported_payment_methods() {
80 1
		return array(
81 1
			PaymentMethods::BANCONTACT,
82 1
			PaymentMethods::CREDIT_CARD,
83 1
			PaymentMethods::DIRECT_DEBIT,
84 1
			PaymentMethods::GIROPAY,
85
			PaymentMethods::IDEAL,
86
			PaymentMethods::MAESTRO,
87
			PaymentMethods::SOFORT,
88
		);
89
	}
90
91
	/**
92
	 * Start.
93
	 *
94
	 * @see Plugin::start()
95
	 *
96
	 * @param Payment $payment Payment.
97
	 * @return void
98
	 */
99
	public function start( Payment $payment ) {
100
		// Amount.
101
		try {
102
			$amount = AmountTransformer::transform( $payment->get_total_amount() );
103
		} catch ( InvalidArgumentException $e ) {
104
			$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
105
106
			return;
107
		}
108
109
		// Payment method type.
110
		$payment_method_type = PaymentMethodType::transform( $payment->get_method() );
111
112
		// Country.
113
		$locale = get_locale();
114
115
		$customer = $payment->get_customer();
116
117
		if ( null !== $customer ) {
118
			$locale = $customer->get_locale();
119
		}
120
121
		$locale = strval( $locale );
122
123
		$country_code = Locale::getRegion( $locale );
124
125
		// Set country from billing address.
126
		$billing_address = $payment->get_billing_address();
127
128
		if ( null !== $billing_address ) {
129
			$country = $billing_address->get_country_code();
130
131
			if ( ! empty( $country ) ) {
132
				$country_code = $country;
133
			}
134
		}
135
136
		/*
137
		 * API Integration
138
		 *
139
		 * @link https://docs.adyen.com/api-explorer/#/PaymentSetupAndVerificationService/v41/payments
140
		 */
141
		$api_integration_payment_method_types = array(
142
			PaymentMethodType::IDEAL,
143
			PaymentMethodType::DIRECT_EBANKING,
144
		);
145
146
		if ( in_array( $payment_method_type, $api_integration_payment_method_types, true ) ) {
147
			$payment_method = new PaymentMethod( $payment_method_type );
148
149
			if ( PaymentMethodType::IDEAL === $payment_method_type ) {
150
				$payment_method = new PaymentMethodIDeal( $payment_method_type, (string) $payment->get_issuer() );
151
			}
152
153
			// API integration.
154
			$payment_request = new PaymentRequest(
155
				$amount,
156
				$this->config->get_merchant_account(),
157
				strval( $payment->get_id() ),
158
				$payment->get_return_url(),
159
				$payment_method
160
			);
161
162
			$payment_request->set_country_code( $country_code );
163
164
			PaymentRequestHelper::complement( $payment, $payment_request );
165
166
			try {
167
				$payment_response = $this->client->create_payment( $payment_request );
168
			} catch ( Exception $e ) {
169
				$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
170
171
				return;
172
			}
173
174
			$payment->set_transaction_id( $payment_response->get_psp_reference() );
175
176
			$redirect = $payment_response->get_redirect();
177
178
			if ( null !== $redirect ) {
179
				$payment->set_action_url( $redirect->get_url() );
180
			}
181
182
			// Return early so SDK integration code will not be executed for API integration.
183
			return;
184
		}
185
186
		/*
187
		 * SDK Integration
188
		 *
189
		 * @link https://docs.adyen.com/api-explorer/#/PaymentSetupAndVerificationService/v41/paymentSession
190
		 */
191
		$payment_session_request = new PaymentSessionRequest(
192
			$amount,
193
			$this->config->get_merchant_account(),
194
			strval( $payment->get_id() ),
195
			$payment->get_return_url(),
196
			$country_code
197
		);
198
199
		PaymentRequestHelper::complement( $payment, $payment_session_request );
200
201
		// Origin.
202
		$origin = home_url();
203
204
		$origin_url = wp_parse_url( home_url() );
205
206
		if ( is_array( $origin_url ) && isset( $origin_url['scheme'], $origin_url['host'] ) ) {
207
			$origin = sprintf(
208
				'%s://%s',
209
				$origin_url['scheme'],
210
				$origin_url['host']
211
			);
212
		}
213
214
		$payment_session_request->set_origin( $origin );
215
		$payment_session_request->set_sdk_version( self::SDK_VERSION );
216
217
		if ( null !== $payment_method_type ) {
218
			$payment_session_request->set_allowed_payment_methods( array( $payment_method_type ) );
219
		}
220
221
		try {
222
			$payment_session_response = $this->client->create_payment_session( $payment_session_request );
223
		} catch ( Exception $e ) {
224
			$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
225
226
			return;
227
		}
228
229
		$payment->set_meta( 'adyen_sdk_version', self::SDK_VERSION );
230
		$payment->set_meta( 'adyen_payment_session', $payment_session_response->get_payment_session() );
231
232
		$payment->set_action_url( $payment->get_pay_redirect_url() );
233
	}
234
235
	/**
236
	 * Payment redirect.
237
	 *
238
	 * @param Payment $payment Payment.
239
	 *
240
	 * @return void
241
	 */
242
	public function payment_redirect( Payment $payment ) {
243
		$sdk_version     = $payment->get_meta( 'adyen_sdk_version' );
244
		$payment_session = $payment->get_meta( 'adyen_payment_session' );
245
246
		if ( empty( $sdk_version ) || empty( $payment_session ) ) {
247
			return;
248
		}
249
250
		$url = sprintf(
251
			'https://checkoutshopper-%s.adyen.com/checkoutshopper/assets/js/sdk/checkoutSDK.%s.min.js',
252
			( self::MODE_TEST === $payment->get_mode() ? 'test' : 'live' ),
253
			$sdk_version
254
		);
255
256
		wp_register_script(
257
			'pronamic-pay-adyen-checkout',
258
			$url,
259
			array(
260
				'jquery',
261
			),
262
			$sdk_version,
263
			false
264
		);
265
266
		wp_localize_script(
267
			'pronamic-pay-adyen-checkout',
268
			'pronamicPayAdyenCheckout',
269
			array(
270
				'paymentsResultUrl' => rest_url( Integration::REST_ROUTE_NAMESPACE . '/payments/result/' . $payment->config_id ),
271
				'paymentReturnUrl'  => $payment->get_return_url(),
272
				'paymentSession'    => $payment_session,
273
				'configObject'      => array(
274
					'context' => ( self::MODE_TEST === $payment->get_mode() ? 'test' : 'live' ),
275
				),
276
			)
277
		);
278
279
		// Add checkout head action.
280
		add_action( 'pronamic_pay_adyen_checkout_head', array( $this, 'checkout_head' ) );
281
282
		// No cache.
283
		Core_Util::no_cache();
284
285
		require __DIR__ . '/../views/checkout.php';
286
287
		exit;
288
	}
289
290
	/**
291
	 * Checkout head.
292
	 *
293
	 * @return void
294
	 */
295
	public function checkout_head() {
296
		wp_print_styles( 'pronamic-pay-redirect' );
297
298
		wp_print_scripts( 'pronamic-pay-adyen-checkout' );
299
	}
300
301
	/**
302
	 * Update status of the specified payment.
303
	 *
304
	 * @param Payment $payment Payment.
305
	 *
306
	 * @return void
307
	 */
308
	public function update_status( Payment $payment ) {
309
		// Process payload on return.
310
		if ( ! filter_has_var( INPUT_GET, 'payload' ) ) {
311
			return;
312
		}
313
314
		$payload = filter_input( INPUT_GET, 'payload', FILTER_SANITIZE_STRING );
315
316
		$payment_result_request = new PaymentResultRequest( $payload );
317
318
		try {
319
			$payment_result_response = $this->client->get_payment_result( $payment_result_request );
320
321
			PaymentResultHelper::update_payment( $payment, $payment_result_response );
322
		} catch ( Exception $e ) {
323
			$note = sprintf(
324
				/* translators: %s: exception message */
325
				__( 'Error getting payment result: %s', 'pronamic_ideal' ),
326
				$e->getMessage()
327
			);
328
329
			$payment->add_note( $note );
330
		}
331
	}
332
333
	/**
334
	 * Get available payment methods.
335
	 *
336
	 * @see Core_Gateway::get_available_payment_methods()
337
	 */
338
	public function get_available_payment_methods() {
339
		$core_payment_methods = array();
340
341
		try {
342
			$payment_methods_response = $this->client->get_payment_methods();
343
		} catch ( Exception $e ) {
344
			$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
345
346
			return $core_payment_methods;
347
		}
348
349
		foreach ( $payment_methods_response->get_payment_methods() as $payment_method ) {
350
			$core_payment_method = PaymentMethodType::to_wp( $payment_method->get_type() );
351
352
			$core_payment_methods[] = $core_payment_method;
353
		}
354
355
		$core_payment_methods = array_filter( $core_payment_methods );
356
		$core_payment_methods = array_unique( $core_payment_methods );
357
358
		return $core_payment_methods;
359
	}
360
361
	/**
362
	 * Get issuers.
363
	 *
364
	 * @see Pronamic_WP_Pay_Gateway::get_issuers()
365
	 * @return array
366
	 */
367
	public function get_issuers() {
368
		$issuers = array();
369
370
		try {
371
			$payment_methods_response = $this->client->get_payment_methods();
372
		} catch ( Exception $e ) {
373
			$this->error = new WP_Error( 'adyen_error', $e->getMessage() );
374
375
			return $issuers;
376
		}
377
378
		$payment_methods = $payment_methods_response->get_payment_methods();
379
380
		// Limit to iDEAL payment methods.
381
		$payment_methods = array_filter(
382
			$payment_methods,
383
			/**
384
			 * Check if payment method is iDEAL.
385
			 *
386
			 * @param PaymentMethod $payment_method Payment method.
387
			 * @return boolean True if payment method is iDEAL, false otherwise.
388
			 */
389
			function( $payment_method ) {
390
				return ( PaymentMethodType::IDEAL === $payment_method->get_type() );
391
			}
392
		);
393
394
		foreach ( $payment_methods as $payment_method ) {
395
			$details = $payment_method->get_details();
396
397
			if ( is_array( $details ) ) {
398
				foreach ( $details as $detail ) {
399
					if ( 'issuer' === $detail->key && 'select' === $detail->type ) {
400
						foreach ( $detail->items as $item ) {
401
							$issuers[ $item->id ] = $item->name;
402
						}
403
					}
404
				}
405
			}
406
		}
407
408
		if ( empty( $issuers ) ) {
409
			return $issuers;
410
		}
411
412
		return array(
413
			array(
414
				'options' => $issuers,
415
			),
416
		);
417
	}
418
}
419