Failed Conditions
Push — develop ( 55d4c9...0925c6 )
by Reüel
05:03
created

Gateway   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 492
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 26
Bugs 2 Features 0
Metric Value
wmc 47
eloc 233
c 26
b 2
f 0
dl 0
loc 492
ccs 0
cts 302
cp 0
rs 8.64

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
B update_status() 0 57 7
A get_issuers() 0 12 2
B get_available_payment_methods() 0 50 6
F start() 0 195 21
A payment_method_is_required() 0 2 1
A get_supported_payment_methods() 0 18 1
A cancel_reservation() 0 33 4
A create_invoice() 0 33 4

How to fix   Complexity   

Complex Class

Complex classes like Gateway often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Gateway, and based on these observations, apply Extract Interface, too.

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\Payments
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Sisow;
12
13
use Pronamic\WordPress\Pay\Core\Gateway as Core_Gateway;
14
use Pronamic\WordPress\Pay\Core\PaymentMethods;
15
use Pronamic\WordPress\Pay\Core\Util as Core_Util;
16
use Pronamic\WordPress\Pay\Payments\BankAccountDetails;
0 ignored issues
show
Bug introduced by
The type Pronamic\WordPress\Pay\Payments\BankAccountDetails was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Pronamic\WordPress\Pay\Payments\PaymentStatus as Core_Statuses;
18
use Pronamic\WordPress\Pay\Payments\Payment;
19
use Pronamic\WordPress\Pay\Payments\PaymentLineType;
20
21
/**
22
 * Title: Sisow gateway
23
 * Description:
24
 * Copyright: 2005-2019 Pronamic
25
 * Company: Pronamic
26
 *
27
 * @author  Remco Tolsma
28
 * @version 2.0.3
29
 * @since   1.0.0
30
 */
31
class Gateway extends Core_Gateway {
32
	/**
33
	 * Client.
34
	 *
35
	 * @var Client
36
	 */
37
	protected $client;
38
39
	/**
40
	 * Constructs and initialize an Sisow gateway
41
	 *
42
	 * @param Config $config Config.
43
	 */
44
	public function __construct( Config $config ) {
45
		parent::__construct( $config );
46
47
		$this->set_method( self::METHOD_HTTP_REDIRECT );
48
49
		// Supported features.
50
		$this->supports = array(
51
			'payment_status_request',
52
			'reservation_payments',
53
		);
54
55
		// Client.
56
		$this->client = new Client( $config->merchant_id, $config->merchant_key );
57
		$this->client->set_test_mode( self::MODE_TEST === $config->mode );
58
	}
59
60
	/**
61
	 * Get issuers
62
	 *
63
	 * @see Core_Gateway::get_issuers()
64
	 */
65
	public function get_issuers() {
66
		$groups = array();
67
68
		$result = $this->client->get_directory();
69
70
		if ( $result ) {
71
			$groups[] = array(
72
				'options' => $result,
73
			);
74
		}
75
76
		return $groups;
77
	}
78
79
	/**
80
	 * Get available payment methods.
81
	 *
82
	 * @see Core_Gateway::get_available_payment_methods()
83
	 */
84
	public function get_available_payment_methods() {
85
		if ( self::MODE_TEST === $this->config->mode ) {
86
			return null;
87
		}
88
89
		$payment_methods = array();
90
91
		// Merchant request.
92
		$request = new MerchantRequest( $this->config->merchant_id );
93
94
		// Get merchant.
95
		try {
96
			$result = $this->client->get_merchant( $request );
97
		} catch ( \Exception $e ) {
98
			$this->error = new \WP_Error( 'sisow_error', $e->getMessage() );
99
100
			return $payment_methods;
101
		}
102
103
		foreach ( $result->payments as $method ) {
104
			// Transform to WordPress payment methods.
105
			$payment_method = Methods::transform_gateway_method( $method );
106
107
			if ( $payment_method ) {
108
				$payment_methods[] = $payment_method;
109
			}
110
		}
111
112
		/**
113
		 * Add active payment methods which are not returned by Sisow in merchant response.
114
		 *
115
		 * @link https://github.com/wp-pay-gateways/sisow/issues/1
116
		 */
117
		if ( false !== \array_search( PaymentMethods::IDEAL, $payment_methods, true ) ) {
118
			$payment_methods[] = PaymentMethods::BANCONTACT;
119
			$payment_methods[] = PaymentMethods::BANK_TRANSFER;
120
			$payment_methods[] = PaymentMethods::BELFIUS;
121
			$payment_methods[] = PaymentMethods::BUNQ;
122
			$payment_methods[] = PaymentMethods::EPS;
123
			$payment_methods[] = PaymentMethods::GIROPAY;
124
			$payment_methods[] = PaymentMethods::KBC;
125
			$payment_methods[] = PaymentMethods::SOFORT;
126
127
			$payment_methods = \array_unique( $payment_methods );
128
129
			// Renumber keys.
130
			$payment_methods = \array_values( $payment_methods );
131
		}
132
133
		return $payment_methods;
134
	}
135
136
	/**
137
	 * Get supported payment methods
138
	 *
139
	 * @see Pronamic_WP_Pay_Gateway::get_supported_payment_methods()
140
	 */
141
	public function get_supported_payment_methods() {
142
		return array(
143
			PaymentMethods::AFTERPAY,
144
			PaymentMethods::BANK_TRANSFER,
145
			PaymentMethods::BANCONTACT,
146
			PaymentMethods::BELFIUS,
147
			PaymentMethods::BILLINK,
148
			PaymentMethods::BUNQ,
149
			PaymentMethods::CAPAYABLE,
150
			PaymentMethods::IN3,
151
			PaymentMethods::CREDIT_CARD,
152
			PaymentMethods::FOCUM,
153
			PaymentMethods::GIROPAY,
154
			PaymentMethods::IDEAL,
155
			PaymentMethods::IDEALQR,
156
			PaymentMethods::KLARNA_PAY_LATER,
157
			PaymentMethods::PAYPAL,
158
			PaymentMethods::SOFORT,
159
		);
160
	}
161
162
	/**
163
	 * Is payment method required to start transaction?
164
	 *
165
	 * @see Core_Gateway::payment_method_is_required()
166
	 */
167
	public function payment_method_is_required() {
168
		return true;
169
	}
170
171
	/**
172
	 * Start
173
	 *
174
	 * @param Payment $payment Payment.
175
	 *
176
	 * @throws \Exception Throws exception on transaction error.
177
	 * @see Core_Gateway::start()
178
	 */
179
	public function start( Payment $payment ) {
180
		// Order and purchase ID.
181
		$order_id    = $payment->get_order_id();
182
		$purchase_id = strval( empty( $order_id ) ? $payment->get_id() : $order_id );
183
184
		// Maximum length for purchase ID is 16 characters, otherwise an error will occur:
185
		// ideal_sisow_error - purchaseid too long (16).
186
		$purchase_id = substr( $purchase_id, 0, 16 );
187
188
		// New transaction request.
189
		$request = new TransactionRequest(
190
			$this->config->merchant_id,
191
			$this->config->shop_id
192
		);
193
194
		$request->merge_parameters(
195
			array(
196
				'payment'      => Methods::transform( $payment->get_method(), $payment->get_method() ),
197
				'purchaseid'   => substr( $purchase_id, 0, 16 ),
198
				'entrancecode' => $payment->get_entrance_code(),
199
				'amount'       => $payment->get_total_amount()->get_cents(),
0 ignored issues
show
Deprecated Code introduced by
The function Pronamic\WordPress\Money\Money::get_cents() has been deprecated: 1.2.2 Use `Money::get_minor_units()` instead. ( Ignorable by Annotation )

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

199
				'amount'       => /** @scrutinizer ignore-deprecated */ $payment->get_total_amount()->get_cents(),

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
200
				'description'  => substr( $payment->get_description(), 0, 32 ),
201
				'testmode'     => ( self::MODE_TEST === $this->config->mode ) ? 'true' : 'false',
202
				'returnurl'    => $payment->get_return_url(),
203
				'cancelurl'    => $payment->get_return_url(),
204
				'notifyurl'    => $payment->get_return_url(),
205
				'callbackurl'  => $payment->get_return_url(),
206
				// Other parameters.
207
				'issuerid'     => $payment->get_issuer(),
208
				'billing_mail' => $payment->get_email(),
209
			)
210
		);
211
212
		// Payment method.
213
		$this->set_payment_method( null === $payment->get_method() ? PaymentMethods::IDEAL : $payment->get_method() );
214
215
		// Additional parameters for payment method.
216
		if ( PaymentMethods::IDEALQR === $payment->get_method() ) {
217
			$request->set_parameter( 'qrcode', 'true' );
218
		}
219
220
		// Customer.
221
		if ( null !== $payment->get_customer() ) {
222
			$customer = $payment->get_customer();
223
224
			$request->merge_parameters(
225
				array(
226
					'ipaddress' => $customer->get_ip_address(),
227
					'gender'    => $customer->get_gender(),
228
				)
229
			);
230
231
			if ( null !== $customer->get_locale() ) {
232
				/*
233
				 * @link https://github.com/wp-pay-gateways/sisow/tree/feature/post-pay/documentation#parameter-locale
234
				 */
235
				$sisow_locale = strtoupper( substr( $customer->get_locale(), -2 ) );
236
237
				$request->set_parameter( 'locale', $sisow_locale );
238
			}
239
240
			if ( null !== $customer->get_birth_date() ) {
241
				$request->set_parameter( 'birthdate', $customer->get_birth_date()->format( 'dmY' ) );
242
			}
243
		}
244
245
		// Billing address.
246
		if ( null !== $payment->get_billing_address() ) {
247
			$address = $payment->get_billing_address();
248
249
			if ( null !== $address->get_name() ) {
250
				$name = $address->get_name();
251
252
				$request->merge_parameters(
253
					array(
254
						'billing_firstname' => $name->get_first_name(),
255
						'billing_lastname'  => $name->get_last_name(),
256
					)
257
				);
258
259
				// Remove accents from first name for AfterPay.
260
				if ( PaymentMethods::AFTERPAY === $payment->get_method() ) {
261
					$request->set_parameter( 'billing_firstname', remove_accents( $name->get_first_name() ) );
262
				}
263
			}
264
265
			$request->merge_parameters(
266
				array(
267
					'billing_mail'        => $address->get_email(),
268
					'billing_company'     => $address->get_company_name(),
269
					'billing_coc'         => $address->get_coc_number(),
270
					'billing_address1'    => $address->get_line_1(),
271
					'billing_address2'    => $address->get_line_2(),
272
					'billing_zip'         => $address->get_postal_code(),
273
					'billing_city'        => $address->get_city(),
274
					'billing_country'     => $address->get_country_name(),
275
					'billing_countrycode' => $address->get_country_code(),
276
					'billing_phone'       => $address->get_phone(),
277
				)
278
			);
279
		}
280
281
		// Shipping address.
282
		if ( null !== $payment->get_shipping_address() ) {
283
			$address = $payment->get_shipping_address();
284
285
			if ( null !== $address->get_name() ) {
286
				$name = $address->get_name();
287
288
				$request->merge_parameters(
289
					array(
290
						'shipping_firstname' => $name->get_first_name(),
291
						'shipping_lastname'  => $name->get_last_name(),
292
					)
293
				);
294
			}
295
296
			$request->merge_parameters(
297
				array(
298
					'shipping_mail'        => $address->get_email(),
299
					'shipping_company'     => $address->get_company_name(),
300
					'shipping_address1'    => $address->get_line_1(),
301
					'shipping_address2'    => $address->get_line_2(),
302
					'shipping_zip'         => $address->get_postal_code(),
303
					'shipping_city'        => $address->get_city(),
304
					'shipping_country'     => $address->get_country_name(),
305
					'shipping_countrycode' => $address->get_country_code(),
306
					'shipping_phone'       => $address->get_phone(),
307
				)
308
			);
309
		}
310
311
		// Lines.
312
		$lines = $payment->get_lines();
313
314
		if ( null !== $lines ) {
315
			$x = 1;
316
317
			foreach ( $lines as $line ) {
318
				// Product ID.
319
				$product_id = $line->get_id();
320
321
				switch ( $line->get_type() ) {
322
					case PaymentLineType::SHIPPING:
323
						$product_id = 'shipping';
324
325
						break;
326
					case PaymentLineType::FEE:
327
						$product_id = 'paymentfee';
328
329
						break;
330
				}
331
332
				// Price.
333
				$unit_price = null;
334
335
				if ( null !== $line->get_unit_price() ) {
336
					$unit_price = $line->get_unit_price()->get_excluding_tax()->get_cents();
337
				}
338
339
				// Request parameters.
340
				$request->merge_parameters(
341
					array(
342
						'product_id_' . $x          => $product_id,
343
						'product_description_' . $x => $line->get_name(),
344
						'product_quantity_' . $x    => $line->get_quantity(),
345
						'product_netprice_' . $x    => $unit_price,
346
						'product_total_' . $x       => $line->get_total_amount()->get_including_tax()->get_cents(),
347
						'product_nettotal_' . $x    => $line->get_total_amount()->get_excluding_tax()->get_cents(),
348
					)
349
				);
350
351
				// Tax request parameters.
352
				$tax_amount = $line->get_tax_amount();
353
354
				if ( null !== $tax_amount ) {
355
					$request->set_parameter( 'product_tax_' . $x, $tax_amount->get_minor_units() );
356
				}
357
358
				$tax_percentage = $line->get_total_amount()->get_tax_percentage();
359
360
				if ( null !== $tax_percentage ) {
361
					$request->set_parameter( 'product_taxrate_' . $x, $tax_percentage * 100 );
362
				}
363
364
				$x++;
365
			}
366
		}
367
368
		// Create transaction.
369
		$result = $this->client->create_transaction( $request );
370
371
		if ( false !== $result ) {
372
			$payment->set_transaction_id( $result->id );
373
			$payment->set_action_url( $result->issuer_url );
374
		}
375
	}
376
377
	/**
378
	 * Update status of the specified payment
379
	 *
380
	 * @param Payment $payment Payment.
381
	 */
382
	public function update_status( Payment $payment ) {
383
		$transaction_id = $payment->get_transaction_id();
384
		$merchant_id    = $this->config->merchant_id;
385
386
		// Process notify and callback requests for payments without transaction ID.
387
		if ( empty( $transaction_id ) && Core_Util::input_has_vars( \INPUT_GET, array( 'trxid', 'ec', 'status', 'sha1' ) ) ) {
388
			$transaction_id = \filter_input( \INPUT_GET, 'trxid' );
389
			$entrance_code  = \filter_input( \INPUT_GET, 'ec' );
390
			$status         = \filter_input( \INPUT_GET, 'status' );
391
			$signature      = \filter_input( \INPUT_GET, 'sha1' );
392
393
			$notify = new NotifyRequest( $transaction_id, $entrance_code, $status, $merchant_id );
394
395
			// Set status if signature validates.
396
			if ( $notify->get_signature( $this->config->merchant_key ) === $signature ) {
397
				$payment->set_status( Statuses::transform( $status ) );
398
			}
399
400
			return;
401
		}
402
403
		// Status request.
404
		$request = new StatusRequest(
405
			$transaction_id,
406
			$merchant_id,
407
			$this->config->shop_id
408
		);
409
410
		try {
411
			$result = $this->client->get_status( $request );
412
413
			if ( false === $result ) {
414
				return;
415
			}
416
		} catch ( \Exception $e ) {
417
			$this->error = new \WP_Error( 'sisow_error', $e->getMessage() );
418
419
			return;
420
		}
421
422
		// Set status.
423
		$payment->set_status( Statuses::transform( $result->status ) );
424
425
		// Set consumer details.
426
		$consumer_details = $payment->get_consumer_bank_details();
0 ignored issues
show
Bug introduced by
The method get_consumer_bank_details() does not exist on Pronamic\WordPress\Pay\Payments\Payment. ( Ignorable by Annotation )

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

426
		/** @scrutinizer ignore-call */ 
427
  $consumer_details = $payment->get_consumer_bank_details();

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...
427
428
		if ( null === $consumer_details ) {
429
			$consumer_details = new BankAccountDetails();
430
431
			$payment->set_consumer_bank_details( $consumer_details );
0 ignored issues
show
Bug introduced by
The method set_consumer_bank_details() does not exist on Pronamic\WordPress\Pay\Payments\Payment. Did you maybe mean set_consumer_bic()? ( Ignorable by Annotation )

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

431
			$payment->/** @scrutinizer ignore-call */ 
432
             set_consumer_bank_details( $consumer_details );

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...
432
		}
433
434
		$consumer_details->set_name( $result->consumer_name );
435
		$consumer_details->set_account_number( $result->consumer_account );
436
		$consumer_details->set_city( $result->consumer_city );
437
		$consumer_details->set_iban( $result->consumer_iban );
438
		$consumer_details->set_bic( $result->consumer_bic );
439
	}
440
441
	/**
442
	 * Create invoice.
443
	 *
444
	 * @param Payment $payment Payment.
445
	 *
446
	 * @return bool
447
	 */
448
	public function create_invoice( $payment ) {
449
		$transaction_id = $payment->get_transaction_id();
450
451
		if ( empty( $transaction_id ) ) {
452
			return false;
453
		}
454
455
		// Invoice request.
456
		$request = new InvoiceRequest(
457
			$this->config->merchant_id,
458
			$this->config->shop_id
459
		);
460
461
		$request->set_parameter( 'trxid', $transaction_id );
462
463
		// Create invoice.
464
		try {
465
			$result = $this->client->create_invoice( $request );
466
		} catch ( \Exception $e ) {
467
			$this->error = new \WP_Error( 'sisow_error', $e->getMessage() );
468
469
			return false;
470
		}
471
472
		if ( $result instanceof \Pronamic\WordPress\Pay\Gateways\Sisow\Reservation ) {
0 ignored issues
show
introduced by
$result is never a sub-type of Pronamic\WordPress\Pay\Gateways\Sisow\Reservation.
Loading history...
473
			$payment->set_status( Core_Statuses::SUCCESS );
474
475
			$payment->save();
476
477
			return true;
478
		}
479
480
		return false;
481
	}
482
483
	/**
484
	 * Cancel reservation.
485
	 *
486
	 * @param Payment $payment Payment.
487
	 *
488
	 * @return bool
489
	 */
490
	public function cancel_reservation( $payment ) {
491
		$transaction_id = $payment->get_transaction_id();
492
493
		if ( empty( $transaction_id ) ) {
494
			return false;
495
		}
496
497
		// Cancel reservation request.
498
		$request = new CancelReservationRequest(
499
			$this->config->merchant_id,
500
			$this->config->shop_id
501
		);
502
503
		$request->set_parameter( 'trxid', $transaction_id );
504
505
		// Cancel reservation.
506
		try {
507
			$result = $this->client->cancel_reservation( $request );
508
		} catch ( \Exception $e ) {
509
			$this->error = new \WP_Error( 'sisow_error', $e->getMessage() );
510
511
			return false;
512
		}
513
514
		if ( isset( $result->status ) ) {
515
			$payment->set_status( Statuses::transform( $result->status ) );
516
517
			$payment->save();
518
519
			return true;
520
		}
521
522
		return false;
523
	}
524
}
525