Failed Conditions
Push — develop ( 612159...14294b )
by Reüel
03:14
created

Gateway::start()   F

Complexity

Conditions 16
Paths 1008

Size

Total Lines 149
Code Lines 82

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 272

Importance

Changes 0
Metric Value
cc 16
eloc 82
nc 1008
nop 1
dl 0
loc 149
ccs 0
cts 100
cp 0
crap 272
rs 1.5127
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 Pronamic\WordPress\Pay\Core\Gateway as Core_Gateway;
14
use Pronamic\WordPress\Pay\Core\Statuses as Core_Statuses;
15
use Pronamic\WordPress\Pay\Core\PaymentMethods;
16
use Pronamic\WordPress\Pay\Core\Util;
17
use Pronamic\WordPress\Pay\Payments\Payment;
18
use Pronamic\WordPress\Pay\Plugin;
19
20
/**
21
 * Gateway
22
 *
23
 * @author  Remco Tolsma
24
 * @version 1.0.0
25
 * @since   1.0.0
26
 * @link    https://github.com/adyenpayments/php/blob/master/generatepaymentform.php
27
 */
28
class Gateway extends Core_Gateway {
29
	/**
30
	 * Slug of this gateway.
31
	 *
32
	 * @var string
33
	 */
34
	const SLUG = 'adyen';
35
36
	/**
37
	 * Client.
38
	 *
39
	 * @var Client
40
	 */
41
	protected $client;
42
43
	/**
44
	 * Constructs and initializes an Adyen gateway.
45
	 *
46
	 * @param Config $config Config.
47
	 */
48
	public function __construct( Config $config ) {
49
		parent::__construct( $config );
50
51
		$this->set_method( self::METHOD_HTTP_REDIRECT );
52
		$this->set_slug( self::SLUG );
53
54
		$this->client = new Client( $config->api_key, $config->api_live_url_prefix );
55
		$this->client->set_merchant_account( $config->merchant_account );
56
		$this->client->set_mode( $config->mode );
57
	}
58
59
	/**
60
	 * Get supported payment methods
61
	 *
62
	 * @see Core_Gateway::get_supported_payment_methods()
63
	 */
64
	public function get_supported_payment_methods() {
65
		return array(
66
			PaymentMethods::BANCONTACT,
67
			PaymentMethods::CREDIT_CARD,
68
			PaymentMethods::DIRECT_DEBIT,
69
			PaymentMethods::GIROPAY,
70
			PaymentMethods::IDEAL,
71
			PaymentMethods::MAESTRO,
72
			PaymentMethods::SOFORT,
73
		);
74
	}
75
76
	/**
77
	 * Start.
78
	 *
79
	 * @param Payment $payment Payment.
80
	 *
81
	 * @see Plugin::start()
82
	 */
83
	public function start( Payment $payment ) {
84
		// Amount.
85
		$amount = new Amount(
86
			$payment->get_total_amount()->get_currency()->get_alphabetic_code(),
87
			$payment->get_total_amount()->get_minor_units()
0 ignored issues
show
Bug introduced by
The method get_minor_units() does not exist on Pronamic\WordPress\Money\TaxedMoney. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

87
			$payment->get_total_amount()->/** @scrutinizer ignore-call */ get_minor_units()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
88
		);
89
90
		// Payment method. Take leap of faith for unknown payment methods.
91
		$type = PaymentMethodType::transform(
92
			$payment->get_method(),
93
			$payment->get_method()
94
		);
95
96
		$payment_method = new PaymentMethod( $type );
97
98
		switch ( $payment->get_method() ) {
99
			case PaymentMethods::IDEAL:
100
				$payment_method->issuer = $payment->get_issuer();
1 ignored issue
show
Bug introduced by
The property issuer does not seem to exist on Pronamic\WordPress\Pay\G...ays\Adyen\PaymentMethod.
Loading history...
101
102
				break;
103
		}
104
105
		// Country.
106
		$locale = get_locale();
107
108
		if ( null !== $payment->get_customer() ) {
109
			$locale = $payment->get_customer()->get_locale();
110
		}
111
112
		$locale = explode( '_', $locale );
113
114
		$country_code = strtoupper( substr( $locale[1], 0, 2 ) );
115
116
		// Create payment or payment session request.
117
		switch ( $payment->get_method() ) {
118
			case PaymentMethods::IDEAL:
119
			case PaymentMethods::SOFORT:
120
				// API integration.
121
				$request = new PaymentRequest(
122
					$amount,
123
					$this->config->merchant_account,
124
					$payment->get_id(),
125
					$payment->get_return_url(),
126
					$payment_method
127
				);
128
129
				$request->set_country_code( $country_code );
130
131
				break;
132
			default:
133
				// Web SDK integration.
134
				$request = new PaymentSessionRequest(
135
					$amount,
136
					$this->config->merchant_account,
137
					$payment->get_id(),
138
					$payment->get_return_url(),
139
					$country_code
140
				);
141
142
				$request->set_origin( home_url() );
143
				$request->set_sdk_version( '1.6.3' );
144
145
				// Set allowed payment methods.
146
				$allowed_methods = array( $type );
147
148
				// Add all available payment methods if no payment method is given.
149
				if ( empty( $type ) ) {
150
					$allowed_methods = array();
151
152
					foreach ( $this->get_available_payment_methods() as $method ) {
153
						$allowed_methods[] = PaymentMethodType::transform( $method );
154
					}
155
				}
156
157
				$request->set_allowed_payment_methods( $allowed_methods );
158
		}
159
160
		// Channel.
161
		$request->set_channel( 'Web' );
162
163
		// Shopper.
164
		$request->set_shopper_statement( $payment->get_description() );
165
166
		if ( null !== $payment->get_customer() ) {
167
			$request->set_shopper_ip( $payment->get_customer()->get_ip_address() );
168
			$request->set_shopper_statement( $payment->get_customer()->get_gender() );
169
			$request->set_shopper_locale( $payment->get_customer()->get_locale() );
170
			$request->set_shopper_reference( $payment->get_customer()->get_user_id() );
171
			$request->set_telephone_number( $payment->get_customer()->get_phone() );
172
173
			if ( null !== $payment->get_customer()->get_name() ) {
174
				$shopper_name = new ShopperName(
175
					$payment->get_customer()->get_name()->get_first_name(),
176
					$payment->get_customer()->get_name()->get_middle_name(),
177
					$payment->get_customer()->get_name()->get_last_name()
178
				);
179
180
				$request->set_shopper_name( $shopper_name );
181
			}
182
		}
183
184
		// Create payment or payment session.
185
		switch ( $payment->get_method() ) {
186
			case PaymentMethods::IDEAL:
187
			case PaymentMethods::SOFORT:
188
				// Create payment.
189
				$result = $this->client->create_payment( $request );
0 ignored issues
show
Bug introduced by
It seems like $request can also be of type Pronamic\WordPress\Pay\G...n\PaymentSessionRequest; however, parameter $request of Pronamic\WordPress\Pay\G...lient::create_payment() does only seem to accept Pronamic\WordPress\Pay\G...ys\Adyen\PaymentRequest, 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

189
				$result = $this->client->create_payment( /** @scrutinizer ignore-type */ $request );
Loading history...
190
191
				break;
192
			default:
193
				// Create payment session.
194
				$result = $this->client->create_payment_session( $request );
0 ignored issues
show
Bug introduced by
It seems like $request can also be of type Pronamic\WordPress\Pay\G...ys\Adyen\PaymentRequest; however, parameter $request of Pronamic\WordPress\Pay\G...reate_payment_session() does only seem to accept Pronamic\WordPress\Pay\G...n\PaymentSessionRequest, 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

194
				$result = $this->client->create_payment_session( /** @scrutinizer ignore-type */ $request );
Loading history...
195
		}
196
197
		if ( ! $result ) {
198
			$this->error = $this->client->get_error();
199
200
			return;
201
		}
202
203
		if ( isset( $result->paymentSession ) ) {
204
			wp_register_script(
205
				'pronamic-pay-adyen-checkout',
206
				'https://checkoutshopper-test.adyen.com/checkoutshopper/assets/js/sdk/checkoutSDK.1.6.3.min.js',
207
				array(),
208
				'1.6.3',
209
				false
210
			);
211
212
			// No cache.
213
			Util::no_cache();
214
215
			$payment_session = $result->paymentSession;
216
217
			$context = ( self::MODE_TEST === $this->config->mode ? 'test' : 'live' );
218
219
			require __DIR__ . '/../views/checkout.php';
220
221
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
222
		}
223
224
		// Set transaction ID.
225
		if ( isset( $result->pspReference ) ) {
226
			$payment->set_transaction_id( $result->pspReference );
227
		}
228
229
		// Set redirect URL.
230
		if ( isset( $result->redirect->url ) ) {
231
			$payment->set_action_url( $result->redirect->url );
232
		}
233
	}
234
235
	/**
236
	 * Update status of the specified payment.
237
	 *
238
	 * @param Payment $payment Payment.
239
	 *
240
	 * @return void
241
	 */
242
	public function update_status( Payment $payment ) {
243
		// Maybe process stored webhook notification.
244
		$this->maybe_handle_notification( $payment );
245
246
		// Process payload on return.
247
		if ( ! filter_has_var( INPUT_GET, 'payload' ) ) {
248
			return;
249
		}
250
251
		$status = null;
252
253
		$payload = filter_input( INPUT_GET, 'payload', FILTER_SANITIZE_STRING );
254
255
		switch ( $payment->get_method() ) {
256
			case PaymentMethods::IDEAL:
257
			case PaymentMethods::SOFORT:
258
				$result = $this->client->get_payment_details( $payload );
259
260
				break;
261
			default:
262
				$result = $this->client->get_payment_result( $payload );
263
		}
264
265
		if ( $result ) {
266
			$status = ResultCode::transform( $result->resultCode );
267
268
			$psp_reference = $result->pspReference;
269
		}
270
271
		// Handle errors.
272
		if ( empty( $status ) ) {
273
			$payment->set_status( Core_Statuses::FAILURE );
274
275
			$this->error = $this->client->get_error();
276
277
			return;
278
		}
279
280
		// Update status.
281
		$payment->set_status( $status );
282
283
		// Update transaction ID.
284
		if ( isset( $psp_reference ) ) {
285
			$payment->set_transaction_id( $psp_reference );
286
		}
287
	}
288
289
	/**
290
	 * Maybe handle notification.
291
	 *
292
	 * @param Payment $payment      Payment.
293
	 */
294
	public function maybe_handle_notification( Payment $payment ) {
295
		$notification = $payment->get_meta( 'adyen_notification' );
296
297
		if ( empty( $notification ) ) {
298
			return;
299
		}
300
301
		$notification = json_decode( $notification );
302
303
		if ( ! is_object( $notification ) ) {
304
			return;
305
		}
306
307
		switch ( $notification->eventCode ) {
308
			case EventCode::AUTHORIZATION:
309
				$this->handle_authorization_event( $payment, $notification );
310
311
				break;
312
		}
313
314
		$payment->set_meta( 'adyen_notification', null );
315
	}
316
317
	/**
318
	 * Handle authorization event.
319
	 *
320
	 * @param Payment $payment      Payment.
321
	 * @param object  $notification Notification.
322
	 */
323
	public function handle_authorization_event( Payment $payment, $notification ) {
324
		if ( ! is_object( $notification ) ) {
325
			return;
326
		}
327
328
		$success = $notification->success;
329
330
		if ( 'true' === $success ) {
331
			$status = Core_Statuses::SUCCESS;
332
		} else {
333
			$status = Core_Statuses::FAILURE;
334
335
			// Add note.
336
			$note = sprintf(
337
				/* translators: %s: failure reason message */
338
				__( 'Failure reason: %s.', 'pronamic_ideal' ),
339
				esc_html( $notification->reason )
340
			);
341
342
			$payment->add_note( $note );
343
		}
344
345
		$payment->set_status( $status );
346
	}
347
348
	/**
349
	 * Get available payment methods.
350
	 *
351
	 * @see Core_Gateway::get_available_payment_methods()
352
	 */
353
	public function get_available_payment_methods() {
354
		$payment_methods = array();
355
356
		// Get active payment methods for Adyen account.
357
		$methods = $this->client->get_payment_methods();
358
359
		if ( ! $methods ) {
0 ignored issues
show
introduced by
The condition $methods is always false.
Loading history...
360
			$this->error = $this->client->get_error();
361
362
			return $payment_methods;
363
		}
364
365
		// Transform to WordPress payment methods.
366
		foreach ( $methods as $method => $details ) {
367
			$payment_method = PaymentMethodType::transform_gateway_method( $method );
368
369
			if ( $payment_method ) {
370
				$payment_methods[] = $payment_method;
371
			}
372
		}
373
374
		$payment_methods = array_unique( $payment_methods );
375
376
		return $payment_methods;
377
	}
378
379
	/**
380
	 * Get issuers.
381
	 *
382
	 * @see Pronamic_WP_Pay_Gateway::get_issuers()
383
	 */
384
	public function get_issuers() {
385
		$groups = array();
386
387
		$payment_method = PaymentMethodType::transform( PaymentMethods::IDEAL );
388
389
		$result = $this->client->get_issuers( $payment_method );
390
391
		if ( ! $result ) {
0 ignored issues
show
introduced by
The condition $result is always false.
Loading history...
392
			$this->error = $this->client->get_error();
393
394
			return $groups;
395
		}
396
397
		$groups[] = array(
398
			'options' => $result,
399
		);
400
401
		return $groups;
402
	}
403
}
404