Failed Conditions
Push — develop ( 755a8b...f93ab4 )
by Reüel
08:34
created

Gateway   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 437
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 20
Bugs 1 Features 0
Metric Value
wmc 40
eloc 202
c 20
b 1
f 0
dl 0
loc 437
ccs 0
cts 265
cp 0
rs 9.2

9 Methods

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

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\Payments\PaymentStatus as Core_Statuses;
16
use Pronamic\WordPress\Pay\Payments\Payment;
17
use Pronamic\WordPress\Pay\Payments\PaymentLineType;
18
19
/**
20
 * Title: Sisow gateway
21
 * Description:
22
 * Copyright: 2005-2019 Pronamic
23
 * Company: Pronamic
24
 *
25
 * @author  Remco Tolsma
26
 * @version 2.0.3
27
 * @since   1.0.0
28
 */
29
class Gateway extends Core_Gateway {
30
	/**
31
	 * Client.
32
	 *
33
	 * @var Client
34
	 */
35
	protected $client;
36
37
	/**
38
	 * Constructs and initialize an Sisow gateway
39
	 *
40
	 * @param Config $config Config.
41
	 */
42
	public function __construct( Config $config ) {
43
		parent::__construct( $config );
44
45
		$this->set_method( self::METHOD_HTTP_REDIRECT );
46
47
		// Supported features.
48
		$this->supports = array(
49
			'payment_status_request',
50
			'reservation_payments',
51
		);
52
53
		// Client.
54
		$this->client = new Client( $config->merchant_id, $config->merchant_key );
55
		$this->client->set_test_mode( self::MODE_TEST === $config->mode );
56
	}
57
58
	/**
59
	 * Get issuers
60
	 *
61
	 * @see Core_Gateway::get_issuers()
62
	 */
63
	public function get_issuers() {
64
		$groups = array();
65
66
		$result = $this->client->get_directory();
67
68
		if ( $result ) {
69
			$groups[] = array(
70
				'options' => $result,
71
			);
72
		} else {
73
			$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

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

178
				'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...
179
				'description'  => substr( $payment->get_description(), 0, 32 ),
180
				'testmode'     => ( self::MODE_TEST === $this->config->mode ) ? 'true' : 'false',
181
				'returnurl'    => $payment->get_return_url(),
182
				'cancelurl'    => $payment->get_return_url(),
183
				'notifyurl'    => $payment->get_return_url(),
184
				'callbackurl'  => $payment->get_return_url(),
185
				// Other parameters.
186
				'issuerid'     => $payment->get_issuer(),
187
				'billing_mail' => $payment->get_email(),
188
			)
189
		);
190
191
		// Payment method.
192
		$this->set_payment_method( null === $payment->get_method() ? PaymentMethods::IDEAL : $payment->get_method() );
193
194
		// Additional parameters for payment method.
195
		if ( PaymentMethods::IDEALQR === $payment->get_method() ) {
196
			$request->set_parameter( 'qrcode', 'true' );
197
		}
198
199
		// Customer.
200
		if ( null !== $payment->get_customer() ) {
201
			$customer = $payment->get_customer();
202
203
			$request->merge_parameters(
204
				array(
205
					'ipaddress' => $customer->get_ip_address(),
206
					'gender'    => $customer->get_gender(),
207
				)
208
			);
209
210
			if ( null !== $customer->get_locale() ) {
211
				/*
212
				 * @link https://github.com/wp-pay-gateways/sisow/tree/feature/post-pay/documentation#parameter-locale
213
				 */
214
				$sisow_locale = strtoupper( substr( $customer->get_locale(), -2 ) );
215
216
				$request->set_parameter( 'locale', $sisow_locale );
217
			}
218
219
			if ( null !== $customer->get_birth_date() ) {
220
				$request->set_parameter( 'birthdate', $customer->get_birth_date()->format( 'dmY' ) );
221
			}
222
		}
223
224
		// Billing address.
225
		if ( null !== $payment->get_billing_address() ) {
226
			$address = $payment->get_billing_address();
227
228
			if ( null !== $address->get_name() ) {
229
				$name = $address->get_name();
230
231
				$request->merge_parameters(
232
					array(
233
						'billing_firstname' => $name->get_first_name(),
234
						'billing_lastname'  => $name->get_last_name(),
235
					)
236
				);
237
238
				// Remove accents from first name for AfterPay.
239
				if ( PaymentMethods::AFTERPAY === $payment->get_method() ) {
240
					$request->set_parameter( 'billing_firstname', remove_accents( $name->get_first_name() ) );
241
				}
242
			}
243
244
			$request->merge_parameters(
245
				array(
246
					'billing_mail'        => $address->get_email(),
247
					'billing_company'     => $address->get_company_name(),
248
					'billing_coc'         => $address->get_coc_number(),
249
					'billing_address1'    => $address->get_line_1(),
250
					'billing_address2'    => $address->get_line_2(),
251
					'billing_zip'         => $address->get_postal_code(),
252
					'billing_city'        => $address->get_city(),
253
					'billing_country'     => $address->get_country_name(),
254
					'billing_countrycode' => $address->get_country_code(),
255
					'billing_phone'       => $address->get_phone(),
256
				)
257
			);
258
		}
259
260
		// Shipping address.
261
		if ( null !== $payment->get_shipping_address() ) {
262
			$address = $payment->get_shipping_address();
263
264
			if ( null !== $address->get_name() ) {
265
				$name = $address->get_name();
266
267
				$request->merge_parameters(
268
					array(
269
						'shipping_firstname' => $name->get_first_name(),
270
						'shipping_lastname'  => $name->get_last_name(),
271
					)
272
				);
273
			}
274
275
			$request->merge_parameters(
276
				array(
277
					'shipping_mail'        => $address->get_email(),
278
					'shipping_company'     => $address->get_company_name(),
279
					'shipping_address1'    => $address->get_line_1(),
280
					'shipping_address2'    => $address->get_line_2(),
281
					'shipping_zip'         => $address->get_postal_code(),
282
					'shipping_city'        => $address->get_city(),
283
					'shipping_country'     => $address->get_country_name(),
284
					'shipping_countrycode' => $address->get_country_code(),
285
					'shipping_phone'       => $address->get_phone(),
286
				)
287
			);
288
		}
289
290
		// Lines.
291
		$lines = $payment->get_lines();
292
293
		if ( null !== $lines ) {
294
			$x = 1;
295
296
			foreach ( $lines as $line ) {
297
				// Product ID.
298
				$product_id = $line->get_id();
299
300
				switch ( $line->get_type() ) {
301
					case PaymentLineType::SHIPPING:
302
						$product_id = 'shipping';
303
304
						break;
305
					case PaymentLineType::FEE:
306
						$product_id = 'paymentfee';
307
308
						break;
309
				}
310
311
				// Price.
312
				$unit_price = null;
313
314
				if ( null !== $line->get_unit_price() ) {
315
					$unit_price = $line->get_unit_price()->get_excluding_tax()->get_cents();
316
				}
317
318
				// Request parameters.
319
				$request->merge_parameters(
320
					array(
321
						'product_id_' . $x          => $product_id,
322
						'product_description_' . $x => $line->get_name(),
323
						'product_quantity_' . $x    => $line->get_quantity(),
324
						'product_netprice_' . $x    => $unit_price,
325
						'product_total_' . $x       => $line->get_total_amount()->get_including_tax()->get_cents(),
326
						'product_nettotal_' . $x    => $line->get_total_amount()->get_excluding_tax()->get_cents(),
327
					)
328
				);
329
330
				// Tax request parameters.
331
				$tax_amount = $line->get_tax_amount();
332
333
				if ( null !== $tax_amount ) {
334
					$request->set_parameter( 'product_tax_' . $x, $tax_amount->get_cents() );
335
				}
336
337
				$tax_percentage = $line->get_total_amount()->get_tax_percentage();
338
339
				if ( null !== $tax_percentage ) {
340
					$request->set_parameter( 'product_taxrate_' . $x, $tax_percentage * 100 );
341
				}
342
343
				$x++;
344
			}
345
		}
346
347
		// Create transaction.
348
		$result = $this->client->create_transaction( $request );
349
350
		if ( false !== $result ) {
351
			$payment->set_transaction_id( $result->id );
352
			$payment->set_action_url( $result->issuer_url );
353
		} else {
354
			$this->error = $this->client->get_error();
355
356
			return false;
357
		}
358
	}
359
360
	/**
361
	 * Update status of the specified payment
362
	 *
363
	 * @param Payment $payment Payment.
364
	 */
365
	public function update_status( Payment $payment ) {
366
		$request = new StatusRequest(
367
			$payment->get_transaction_id(),
368
			$this->config->merchant_id,
369
			$this->config->shop_id
370
		);
371
372
		$result = $this->client->get_status( $request );
373
374
		if ( false === $result ) {
375
			$this->error = $this->client->get_error();
376
377
			return;
378
		}
379
380
		$transaction = $result;
381
382
		$payment->set_status( Statuses::transform( $transaction->status ) );
383
		$payment->set_consumer_name( $transaction->consumer_name );
384
		$payment->set_consumer_account_number( $transaction->consumer_account );
385
		$payment->set_consumer_city( $transaction->consumer_city );
386
	}
387
388
	/**
389
	 * Create invoice.
390
	 *
391
	 * @param Payment $payment Payment.
392
	 *
393
	 * @return bool|Invoice
394
	 */
395
	public function create_invoice( $payment ) {
396
		$transaction_id = $payment->get_transaction_id();
397
398
		if ( empty( $transaction_id ) ) {
399
			return false;
400
		}
401
402
		// Invoice request.
403
		$request = new InvoiceRequest(
404
			$this->config->merchant_id,
405
			$this->config->shop_id
406
		);
407
408
		$request->set_parameter( 'trxid', $transaction_id );
409
410
		// Create invoice.
411
		$result = $this->client->create_invoice( $request );
412
413
		// Handle errors.
414
		if ( false === $result ) {
415
			$this->error = $this->client->get_error();
416
417
			return false;
418
		}
419
420
		$payment->set_status( Core_Statuses::SUCCESS );
421
422
		$payment->save();
423
424
		return $result;
425
	}
426
427
	/**
428
	 * Cancel reservation.
429
	 *
430
	 * @param Payment $payment Payment.
431
	 *
432
	 * @return bool|Reservation
433
	 */
434
	public function cancel_reservation( $payment ) {
435
		$transaction_id = $payment->get_transaction_id();
436
437
		if ( empty( $transaction_id ) ) {
438
			return false;
439
		}
440
441
		// Cancel reservation request.
442
		$request = new CancelReservationRequest(
443
			$this->config->merchant_id,
444
			$this->config->shop_id
445
		);
446
447
		$request->set_parameter( 'trxid', $transaction_id );
448
449
		// Cancel reservation.
450
		$result = $this->client->cancel_reservation( $request );
451
452
		// Handle errors.
453
		if ( false === $result ) {
454
			$this->error = $this->client->get_error();
455
456
			return false;
457
		}
458
459
		if ( isset( $result->status ) ) {
460
			$payment->set_status( Statuses::transform( $result->status ) );
461
462
			$payment->save();
463
		}
464
465
		return $result;
466
	}
467
}
468