Failed Conditions
Push — develop ( a45adf...0344f1 )
by Reüel
08:46
created

Gateway   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 469
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 22
Bugs 1 Features 0
Metric Value
wmc 45
eloc 219
c 22
b 1
f 0
dl 0
loc 469
ccs 0
cts 286
cp 0
rs 8.8

9 Methods

Rating   Name   Duplication   Size   Complexity  
B update_status() 0 57 7
A get_issuers() 0 14 2
A cancel_reservation() 0 32 4
A get_available_payment_methods() 0 29 5
A __construct() 0 14 1
A create_invoice() 0 30 3
F start() 0 195 21
A payment_method_is_required() 0 2 1
A get_supported_payment_methods() 0 18 1

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
		} else {
75
			$this->error = $this->client->get_error();
0 ignored issues
show
Bug introduced by
The method get_error() does not exist on Pronamic\WordPress\Pay\Gateways\Sisow\Client. ( Ignorable by Annotation )

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

75
			/** @scrutinizer ignore-call */ 
76
   $this->error = $this->client->get_error();

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...
76
		}
77
78
		return $groups;
79
	}
80
81
	/**
82
	 * Get available payment methods.
83
	 *
84
	 * @see Core_Gateway::get_available_payment_methods()
85
	 */
86
	public function get_available_payment_methods() {
87
		if ( self::MODE_TEST === $this->config->mode ) {
88
			return null;
89
		}
90
91
		$payment_methods = array();
92
93
		// Merchant request.
94
		$request = new MerchantRequest( $this->config->merchant_id );
95
96
		// Get merchant.
97
		try {
98
			$result = $this->client->get_merchant( $request );
99
		} catch ( \Exception $e ) {
100
			$this->error = new \WP_Error( 'sisow_error', $e->getMessage() );
101
102
			return $payment_methods;
103
		}
104
105
		foreach ( $result->payments as $method ) {
106
			// Transform to WordPress payment methods.
107
			$payment_method = Methods::transform_gateway_method( $method );
108
109
			if ( $payment_method ) {
110
				$payment_methods[] = $payment_method;
111
			}
112
		}
113
114
		return $payment_methods;
115
	}
116
117
	/**
118
	 * Get supported payment methods
119
	 *
120
	 * @see Pronamic_WP_Pay_Gateway::get_supported_payment_methods()
121
	 */
122
	public function get_supported_payment_methods() {
123
		return array(
124
			PaymentMethods::AFTERPAY,
125
			PaymentMethods::BANK_TRANSFER,
126
			PaymentMethods::BANCONTACT,
127
			PaymentMethods::BELFIUS,
128
			PaymentMethods::BILLINK,
129
			PaymentMethods::BUNQ,
130
			PaymentMethods::CAPAYABLE,
131
			PaymentMethods::IN3,
132
			PaymentMethods::CREDIT_CARD,
133
			PaymentMethods::FOCUM,
134
			PaymentMethods::GIROPAY,
135
			PaymentMethods::IDEAL,
136
			PaymentMethods::IDEALQR,
137
			PaymentMethods::KLARNA_PAY_LATER,
138
			PaymentMethods::PAYPAL,
139
			PaymentMethods::SOFORT,
140
		);
141
	}
142
143
	/**
144
	 * Is payment method required to start transaction?
145
	 *
146
	 * @see Core_Gateway::payment_method_is_required()
147
	 */
148
	public function payment_method_is_required() {
149
		return true;
150
	}
151
152
	/**
153
	 * Start
154
	 *
155
	 * @param Payment $payment Payment.
156
	 *
157
	 * @throws \Exception Throws exception on transaction error.
158
	 * @see Core_Gateway::start()
159
	 */
160
	public function start( Payment $payment ) {
161
		// Order and purchase ID.
162
		$order_id    = $payment->get_order_id();
163
		$purchase_id = strval( empty( $order_id ) ? $payment->get_id() : $order_id );
164
165
		// Maximum length for purchase ID is 16 characters, otherwise an error will occur:
166
		// ideal_sisow_error - purchaseid too long (16).
167
		$purchase_id = substr( $purchase_id, 0, 16 );
168
169
		// New transaction request.
170
		$request = new TransactionRequest(
171
			$this->config->merchant_id,
172
			$this->config->shop_id
173
		);
174
175
		$request->merge_parameters(
176
			array(
177
				'payment'      => Methods::transform( $payment->get_method(), $payment->get_method() ),
178
				'purchaseid'   => substr( $purchase_id, 0, 16 ),
179
				'entrancecode' => $payment->get_entrance_code(),
180
				'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

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

407
		/** @scrutinizer ignore-call */ 
408
  $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...
408
409
		if ( null === $consumer_details ) {
410
			$consumer_details = new BankAccountDetails();
411
412
			$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

412
			$payment->/** @scrutinizer ignore-call */ 
413
             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...
413
		}
414
415
		$consumer_details->set_name( $result->consumer_name );
416
		$consumer_details->set_account_number( $result->consumer_account );
417
		$consumer_details->set_city( $result->consumer_city );
418
		$consumer_details->set_iban( $result->consumer_iban );
419
		$consumer_details->set_bic( $result->consumer_bic );
420
	}
421
422
	/**
423
	 * Create invoice.
424
	 *
425
	 * @param Payment $payment Payment.
426
	 *
427
	 * @return bool|Invoice
428
	 */
429
	public function create_invoice( $payment ) {
430
		$transaction_id = $payment->get_transaction_id();
431
432
		if ( empty( $transaction_id ) ) {
433
			return false;
434
		}
435
436
		// Invoice request.
437
		$request = new InvoiceRequest(
438
			$this->config->merchant_id,
439
			$this->config->shop_id
440
		);
441
442
		$request->set_parameter( 'trxid', $transaction_id );
443
444
		// Create invoice.
445
		$result = $this->client->create_invoice( $request );
446
447
		// Handle errors.
448
		if ( false === $result ) {
449
			$this->error = $this->client->get_error();
450
451
			return false;
452
		}
453
454
		$payment->set_status( Core_Statuses::SUCCESS );
455
456
		$payment->save();
457
458
		return $result;
459
	}
460
461
	/**
462
	 * Cancel reservation.
463
	 *
464
	 * @param Payment $payment Payment.
465
	 *
466
	 * @return bool|Reservation
467
	 */
468
	public function cancel_reservation( $payment ) {
469
		$transaction_id = $payment->get_transaction_id();
470
471
		if ( empty( $transaction_id ) ) {
472
			return false;
473
		}
474
475
		// Cancel reservation request.
476
		$request = new CancelReservationRequest(
477
			$this->config->merchant_id,
478
			$this->config->shop_id
479
		);
480
481
		$request->set_parameter( 'trxid', $transaction_id );
482
483
		// Cancel reservation.
484
		$result = $this->client->cancel_reservation( $request );
485
486
		// Handle errors.
487
		if ( false === $result ) {
488
			$this->error = $this->client->get_error();
489
490
			return false;
491
		}
492
493
		if ( isset( $result->status ) ) {
494
			$payment->set_status( Statuses::transform( $result->status ) );
495
496
			$payment->save();
497
		}
498
499
		return $result;
500
	}
501
}
502