Failed Conditions
Push — develop ( 8acda5...89cf9b )
by Remco
07:14
created

Gateway::start()   F

Complexity

Conditions 31
Paths 4704

Size

Total Lines 406
Code Lines 142

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 992

Importance

Changes 15
Bugs 0 Features 0
Metric Value
cc 31
eloc 142
c 15
b 0
f 0
nc 4704
nop 1
dl 0
loc 406
ccs 0
cts 182
cp 0
crap 992
rs 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
namespace Pronamic\WordPress\Pay\Gateways\Buckaroo;
4
5
use Pronamic\WordPress\Money\Money;
6
use Pronamic\WordPress\Pay\Banks\BankAccountDetails;
7
use Pronamic\WordPress\Pay\Core\Gateway as Core_Gateway;
8
use Pronamic\WordPress\Pay\Core\PaymentMethods as Core_PaymentMethods;
9
use Pronamic\WordPress\Pay\Core\Server;
10
use Pronamic\WordPress\Pay\Payments\Payment;
11
use Pronamic\WordPress\Pay\Payments\PaymentStatus;
12
13
/**
14
 * Title: Buckaroo gateway
15
 * Description:
16
 * Copyright: 2005-2021 Pronamic
17
 * Company: Pronamic
18
 *
19
 * @author Remco Tolsma
20
 * @version 2.0.4
21
 * @since 1.0.0
22
 */
23
class Gateway extends Core_Gateway {
24
	/**
25
	 * Constructs and initializes an Buckaroo gateway
26
	 *
27
	 * @param Config $config Config.
28
	 */
29
	public function __construct( Config $config ) {
30
		parent::__construct( $config );
31
32
		$this->set_method( self::METHOD_HTTP_REDIRECT );
33
34
		// Supported features.
35
		$this->supports = array(
36
			'payment_status_request',
37
			'refunds',
38
			'webhook',
39
			'webhook_log',
40
			'webhook_no_config',
41
		);
42
	}
43
44
	/**
45
	 * Get issuers.
46
	 *
47
	 * @since 1.2.4
48
	 * @see Core_Gateway::get_issuers()
49
	 */
50
	public function get_issuers() {
51
		$groups = array();
52
53
		$object = $this->request( 'GET', 'Transaction/Specification/ideal?serviceVersion=2' );
54
55
		foreach ( $object->Actions as $action ) {
56
			if ( 'Pay' === $action->Name ) {
57
				foreach ( $action->RequestParameters as $request_parameter ) {
58
					if ( 'issuer' === $request_parameter->Name ) {
59
						foreach ( $request_parameter->ListItemDescriptions as $item ) {
60
							if ( ! array_key_exists( $item->GroupName, $groups ) ) {
61
								$groups[ $item->GroupName ] = array(
62
									'name'    => $item->GroupName,
63
									'options' => array(),
64
								);
65
							}
66
67
							$groups[ $item->GroupName ]['options'][ $item->Value ] = $item->Description;
68
						}
69
					}
70
				}
71
			}
72
		}
73
74
		return $groups;
75
	}
76
77
	/**
78
	 * Get supported payment methods
79
	 *
80
	 * @see Core_Gateway::get_supported_payment_methods()
81
	 */
82
	public function get_supported_payment_methods() {
83
		return array(
84
			Core_PaymentMethods::AMERICAN_EXPRESS,
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\C...thods::AMERICAN_EXPRESS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
85
			Core_PaymentMethods::BANK_TRANSFER,
86
			Core_PaymentMethods::BANCONTACT,
87
			Core_PaymentMethods::CREDIT_CARD,
88
			Core_PaymentMethods::GIROPAY,
89
			Core_PaymentMethods::IDEAL,
90
			Core_PaymentMethods::MAESTRO,
91
			Core_PaymentMethods::MASTERCARD,
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\C...mentMethods::MASTERCARD was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
92
			Core_PaymentMethods::PAYPAL,
93
			Core_PaymentMethods::SOFORT,
94
			Core_PaymentMethods::V_PAY,
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\Core\PaymentMethods::V_PAY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
95
			Core_PaymentMethods::VISA,
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\Core\PaymentMethods::VISA was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
96
		);
97
	}
98
99
	/**
100
	 * Start
101
	 *
102
	 * @param Payment $payment Payment.
103
	 *
104
	 * @see Core_Gateway::start()
105
	 */
106
	public function start( Payment $payment ) {
107
		/**
108
		 * Currency.
109
		 */
110
		$currency_code = $payment->get_total_amount()->get_currency()->get_alphabetic_code();
111
112
		/**
113
		 * Push URL.
114
		 */
115
		$push_url = \rest_url( Integration::REST_ROUTE_NAMESPACE . '/push' );
116
117
		/**
118
		 * Filters the Buckaroo push URL.
119
		 *
120
		 * If you want to debug the Buckaroo report URL you can use this filter
121
		 * to override the push URL. You could for example use a service like
122
		 * https://webhook.site/ to inspect the push requests from Buckaroo.
123
		 *
124
		 * @param string $push_url Buckaroo push URL.
125
		 */
126
		$push_url = \apply_filters( 'pronamic_pay_buckaroo_push_url', $push_url );
127
128
		/**
129
		 * JSON Transaction.
130
		 *
131
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
132
		 */
133
		$data = (object) array(
134
			'Currency'                  => $currency_code,
135
			/**
136
			 * The debit amount for the request. This is in decimal format,
137
			 * with a point as the decimal separator. For example, if the
138
			 * currency is specified as EUR, sending “1” will mean that 1 euro
139
			 * will be paid. “1.00” is also 1 euro. “0.01” means 1 cent.
140
			 * Please note, a transaction must have either a debit amount or a
141
			 * credit amount and it cannot have both.
142
			 *
143
			 * @link https://dev.buckaroo.nl/Apis
144
			 */
145
			'AmountDebit'               => $payment->get_total_amount()->number_format( null, '.', '' ),
146
			'Description'               => $payment->get_description(),
147
			'Invoice'                   => Util::get_invoice_number( (string) $this->config->get_invoice_number(), $payment ),
148
			'ReturnURL'                 => $payment->get_return_url(),
149
			'ReturnURLCancel'           => \add_query_arg(
150
				'buckaroo_return_url_cancel',
151
				true,
152
				$payment->get_return_url()
153
			),
154
			'ReturnURLError'            => \add_query_arg(
155
				'buckaroo_return_url_error',
156
				true,
157
				$payment->get_return_url()
158
			),
159
			'ReturnURLReject'           => \add_query_arg(
160
				'buckaroo_return_url_reject',
161
				true,
162
				$payment->get_return_url()
163
			),
164
			/**
165
			 * Push URL.
166
			 *
167
			 * When provided, this push URL overrides all the push URLs as configured in the payment plaza under websites for the associated website key
168
			 *
169
			 * @link https://dev.buckaroo.nl/Apis
170
			 */
171
			'PushURL'                   => $push_url,
172
			/**
173
			 * Push URL Failure.
174
			 *
175
			 * When provided, this push URL overrides the push URL for failed transactions as configured in the payment plaza under websites for the associated website key.
176
			 *
177
			 * @link https://dev.buckaroo.nl/Apis
178
			 */
179
			'PushURLFailure'            => $push_url,
180
			/**
181
			 * Services.
182
			 *
183
			 * Specifies which service (can be a payment method and/or additional service) is being called upon in the request.
184
			 *
185
			 * @link https://dev.buckaroo.nl/Apis
186
			 */
187
			'Services'                  => (object) array(
188
				'ServiceList' => array(),
189
			),
190
			/**
191
			 * Continue On Incomplete.
192
			 *
193
			 * Specifies if a redirecturl to a payment form will be returned to
194
			 * which a customer should be sent if no paymentmethod is selected
195
			 * or if any required parameter which the customer may provide is
196
			 * missing or incorrect. Possible Values:
197
			 *
198
			 * · No: This is the default. The request will fail if not all the
199
			 * needed information is provided.
200
			 *
201
			 * · RedirectToHTML: A redirect to the HTML gateway is provided if
202
			 * a recoverable problems are detected in the request. The customer
203
			 * can then provide the needed information there.
204
			 *
205
			 * @link https://dev.buckaroo.nl/Apis
206
			 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
207
			 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=ContinueOnIncomplete
208
			 */
209
			'ContinueOnIncomplete'      => 'RedirectToHTML',
210
			/**
211
			 * Services Excluded For Client.
212
			 *
213
			 * If no primary service is provided and ContinueOnIncomplete is
214
			 * set, this list of comma separated servicescodes can be used to
215
			 * limit the number of services from which the customer may choose
216
			 * once he is redirected to the payment form. Services which are
217
			 * entered in this field are not selectable.
218
			 * This field is optional.
219
			 *
220
			 * @link https://dev.buckaroo.nl/Apis
221
			 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
222
			 */
223
			'ServicesExcludedForClient' => $this->config->get_excluded_services(),
224
			/**
225
			 * Custom parameters.
226
			 *
227
			 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
228
			 */
229
			'CustomParameters'          => array(
230
				(object) array(
231
					'Name'  => 'pronamic_payment_id',
232
					'Value' => $payment->get_id(),
233
				),
234
			),
235
		);
236
237
		/**
238
		 * Client IP.
239
		 *
240
		 * In this field the IP address of the customer (or employee) for which
241
		 * the action is being performed can be passed. Please note, If this
242
		 * field is not sent to our gateway, your server IP address will be
243
		 * used as the clientIP. This may result in unwanted behaviour for
244
		 * anti-fraud checks. Also, certain payment methods perform checks on
245
		 * the IP address, if an IP address is overused, the request could be
246
		 * blocked. This field is sent in the following format, where
247
		 * type 0 = IPv4 and type 1 = IPv6:
248
		 * "ClientIP": { "Type": 0, "Address": "0.0.0.0" },
249
		 *
250
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
251
		 * @link https://stackoverflow.com/questions/1448871/how-to-know-which-version-of-the-internet-protocol-ip-a-client-is-using-when-c/1448901
252
		 */
253
		$customer = $payment->get_customer();
254
255
		if ( null !== $customer ) {
256
			$ip_address = $customer->get_ip_address();
257
258
			if ( null !== $ip_address ) {
259
				$data->ClientIP = (object) array(
260
					'Type'    => false === \strpos( $ip_address, ':' ) ? 0 : 1,
261
					'Address' => $ip_address,
262
				);
263
			}
264
		}
265
266
		/**
267
		 * Payment method.
268
		 *
269
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
270
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=ServicesRequest
271
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=ServiceRequest
272
		 */
273
		$payment_method = $payment->get_method();
274
275
		switch ( $payment_method ) {
276
			/**
277
			 * Paymet method American Express.
278
			 * 
279
			 * @link 
280
			 */
281
			case Core_PaymentMethods::AMERICAN_EXPRESS:
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\C...thods::AMERICAN_EXPRESS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
282
				$data->Services->ServiceList[] = (object) array(
283
					'Action' => 'Pay',
284
					'Name'   => PaymentMethods::AMERICAN_EXPRESS,
285
				);
286
287
				break;
288
			/**
289
			 * Payment method creditcard.
290
			 *
291
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/creditcards#pay
292
			 */
293
			case Core_PaymentMethods::CREDIT_CARD:
294
				$data->Services->ServiceList[] = (object) array(
295
					'Action' => 'Pay',
296
					'Name'   => PaymentMethods::AMERICAN_EXPRESS,
297
				);
298
299
				$data->Services->ServiceList[] = (object) array(
300
					'Action' => 'Pay',
301
					'Name'   => PaymentMethods::MAESTRO,
302
				);
303
304
				$data->Services->ServiceList[] = (object) array(
305
					'Action' => 'Pay',
306
					'Name'   => PaymentMethods::MASTERCARD,
307
				);
308
309
				$data->Services->ServiceList[] = (object) array(
310
					'Action' => 'Pay',
311
					'Name'   => PaymentMethods::VISA,
312
				);
313
314
				break;
315
			/**
316
			 * Payment method iDEAL.
317
			 *
318
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/ideal#pay
319
			 */
320
			case Core_PaymentMethods::IDEAL:
321
				$data->Services->ServiceList[] = (object) array(
322
					'Action'     => 'Pay',
323
					'Name'       => 'ideal',
324
					'Parameters' => array(
325
						array(
326
							'Name'  => 'issuer',
327
							'Value' => $payment->get_issuer(),
328
						),
329
					),
330
				);
331
332
				break;
333
			/**
334
			 * Payment method transfer.
335
			 *
336
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/transfer#pay
337
			 */
338
			case Core_PaymentMethods::BANK_TRANSFER:
339
				$data->Services->ServiceList[] = (object) array(
340
					'Action' => 'Pay',
341
					'Name'   => 'transfer',
342
				);
343
344
				break;
345
			/**
346
			 * Payment method Bancontact.
347
			 *
348
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/bancontact#pay
349
			 */
350
			case Core_PaymentMethods::BANCONTACT:
351
			case Core_PaymentMethods::MISTER_CASH:
0 ignored issues
show
Deprecated Code introduced by
The constant Pronamic\WordPress\Pay\C...entMethods::MISTER_CASH has been deprecated: "Bancontact/Mister Cash" was renamed to just "Bancontact". ( Ignorable by Annotation )

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

351
			case /** @scrutinizer ignore-deprecated */ Core_PaymentMethods::MISTER_CASH:

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

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

Loading history...
352
				$data->Services->ServiceList[] = (object) array(
353
					'Action' => 'Pay',
354
					'Name'   => 'bancontactmrcash',
355
				);
356
357
				break;
358
			/**
359
			 * Paymet method Maestro.
360
			 * 
361
			 * @link 
362
			 */
363
			case Core_PaymentMethods::MAESTRO:
364
				$data->Services->ServiceList[] = (object) array(
365
					'Action' => 'Pay',
366
					'Name'   => PaymentMethods::MAESTRO,
367
				);
368
369
				break;
370
			/**
371
			 * Paymet method Mastercard.
372
			 * 
373
			 * @link 
374
			 */
375
			case Core_PaymentMethods::MASTERCARD:
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\C...mentMethods::MASTERCARD was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
376
				$data->Services->ServiceList[] = (object) array(
377
					'Action' => 'Pay',
378
					'Name'   => PaymentMethods::MASTERCARD,
379
				);
380
381
				break;
382
			/**
383
			 * Payment method Giropay.
384
			 *
385
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/giropay#pay
386
			 */
387
			case Core_PaymentMethods::GIROPAY:
388
				$data->Services->ServiceList[] = (object) array(
389
					'Action' => 'Pay',
390
					'Name'   => 'giropay',
391
				);
392
393
				break;
394
			/**
395
			 * Payment method PayPal.
396
			 *
397
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/paypal#pay
398
			 */
399
			case Core_PaymentMethods::PAYPAL:
400
				$data->Services->ServiceList[] = (object) array(
401
					'Action' => 'Pay',
402
					'Name'   => 'paypal',
403
				);
404
405
				break;
406
			/**
407
			 * Payment method Sofort.
408
			 *
409
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/sofort#pay
410
			 */
411
			case Core_PaymentMethods::SOFORT:
412
				$data->Services->ServiceList[] = (object) array(
413
					'Action' => 'Pay',
414
					'Name'   => 'sofortueberweisung',
415
				);
416
417
				break;
418
			/**
419
			 * Paymet method V PAY.
420
			 * 
421
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/creditcards#top
422
			 */
423
			case Core_PaymentMethods::V_PAY:
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\Core\PaymentMethods::V_PAY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
424
				$data->Services->ServiceList[] = (object) array(
425
					'Action' => 'Pay',
426
					'Name'   => PaymentMethods::V_PAY,
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\G...o\PaymentMethods::V_PAY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
427
				);
428
429
				break;
430
			/**
431
			 * Paymet method Visa.
432
			 * 
433
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/creditcards#top
434
			 */
435
			case Core_PaymentMethods::VISA:
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\Core\PaymentMethods::VISA was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
436
				$data->Services->ServiceList[] = (object) array(
437
					'Action' => 'Pay',
438
					'Name'   => PaymentMethods::VISA,
439
				);
440
441
				break;
442
		}
443
444
		/**
445
		 * Request.
446
		 */
447
		$object = $this->request( 'POST', 'Transaction', $data );
448
449
		/**
450
		 * Buckaroo keys.
451
		 *
452
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionResponse
453
		 */
454
		if ( \property_exists( $object, 'Key' ) ) {
455
			$payment->set_transaction_id( $object->Key );
456
		}
457
458
		if ( \property_exists( $object, 'PaymentKey' ) ) {
459
			$payment->set_meta( 'buckaroo_transaction_payment_key', $object->PaymentKey );
460
		}
461
462
		/**
463
		 * Request Errors.
464
		 *
465
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
466
		 */
467
		if ( \property_exists( $object, 'RequestErrors' ) && null !== $object->RequestErrors ) {
468
			$exception = null;
469
470
			foreach ( $object->RequestErrors as $errors ) {
471
				foreach ( $errors as $error ) {
472
					// Add exception.
473
					$exception = new \Exception( $error->ErrorMessage, 0, $exception );
474
				}
475
			}
476
477
			if ( null !== $exception ) {
478
				throw $exception;
479
			}
480
		}
481
482
		/**
483
		 * Required Action.
484
		 */
485
		if ( null !== $object->RequiredAction ) {
486
			if ( 'Redirect' !== $object->RequiredAction->Name ) {
487
				throw new \Exception(
488
					\sprintf(
489
						'Unsupported Buckaroo action: %s',
490
						$object->RequiredAction->Name
491
					)
492
				);
493
			}
494
495
			// Set action URL.
496
			if ( \property_exists( $object->RequiredAction, 'RedirectURL' ) ) {
497
				$payment->set_action_url( $object->RequiredAction->RedirectURL );
498
			}
499
		}
500
501
		// Failure.
502
		if ( \property_exists( $object, 'Status' ) && \property_exists( $object->Status, 'Code' ) ) {
503
			$status = Statuses::transform( (string) $object->Status->Code->Code );
504
505
			if ( PaymentStatus::FAILURE === $status ) {
506
				throw new \Exception(
507
					\sprintf(
508
						/* translators: 1: payment provider name, 2: status message, 3: status sub message*/
509
						__( 'Unable to create payment at gateway: %1$s%2$s', 'pronamic_ideal' ),
510
						$object->Status->Code->Description,
511
						\property_exists( $object->Status, 'SubCode' ) ? ' – ' . $object->Status->SubCode->Description : ''
512
					)
513
				);
514
			}
515
		}
516
	}
517
518
	/**
519
	 * JSON API Request.
520
	 *
521
	 * @param string      $method   HTTP request method.
522
	 * @param string      $endpoint JSON API endpoint.
523
	 * @param object|null $data     Data.
524
	 */
525
	public function request( $method, $endpoint, $data = null ) {
526
		$host = 'checkout.buckaroo.nl';
527
528
		if ( self::MODE_TEST === $this->config->mode ) {
529
			$host = 'testcheckout.buckaroo.nl';
530
		}
531
532
		/**
533
		 * Authentication.
534
		 *
535
		 * The HMAC SHA256 is calculated over a concatenated string (as raw data/binary/bytes) of the following values: WebsiteKey, requestHttpMethod, requestUri, requestTimeStamp, nonce, requestContentBase64String. See the next table for more information about these values. Please note: the Base64 hash should be a string of 44 characters. If yours is longer, it is probably in hexadecimal format.
536
		 *
537
		 * @link https://dev.buckaroo.nl/Apis/Description/json
538
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Authentication
539
		 */
540
		$website_key         = $this->config->website_key;
541
		$request_http_method = $method;
542
		$request_uri         = $host . '/json/' . $endpoint;
543
		$request_timestamp   = \strval( \time() );
544
		$nonce               = \wp_generate_password( 32 );
545
		$request_content     = null === $data ? '' : \wp_json_encode( $data );
546
547
		$values = \implode(
548
			'',
549
			array(
550
				$website_key,
551
				$request_http_method,
552
				\strtolower( \rawurlencode( $request_uri ) ),
553
				$request_timestamp,
554
				$nonce,
555
				// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
556
				null === $data ? '' : \base64_encode( \md5( (string) $request_content, true ) ),
557
			)
558
		);
559
560
		$hash = \hash_hmac( 'sha256', $values, $this->config->secret_key, true );
561
562
		// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
563
		$hmac = \base64_encode( $hash );
564
565
		$authorization = \sprintf(
566
			'hmac %s:%s:%s:%s',
567
			$this->config->website_key,
568
			$hmac,
569
			$nonce,
570
			$request_timestamp
571
		);
572
573
		$response = \Pronamic\WordPress\Http\Facades\Http::request(
574
			'https://' . $request_uri,
575
			array(
576
				'method'  => $request_http_method,
577
				'headers' => array(
578
					'Authorization' => $authorization,
579
					'Content-Type'  => 'application/json',
580
				),
581
				'body'    => $request_content,
582
			)
583
		);
584
585
		$object = $response->json();
586
587
		/**
588
		 * OK.
589
		 */
590
		return $object;
591
	}
592
593
	/**
594
	 * Update status of the specified payment
595
	 *
596
	 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/GET-json-Transaction-Status-transactionKey
597
	 * @param Payment $payment Payment.
598
	 */
599
	public function update_status( Payment $payment ) {
600
		$transaction_key = $payment->get_transaction_id();
601
602
		if ( empty( $transaction_key ) ) {
603
			return;
604
		}
605
606
		$result = $this->request( 'GET', 'Transaction/Status/' . $transaction_key );
607
608
		$payment->set_status( Statuses::transform( \strval( $result->Status->Code->Code ) ) );
609
610
		/**
611
		 * Consumer bank details.
612
		 */
613
		$consumer_bank_details = $payment->get_consumer_bank_details();
614
615
		if ( null === $consumer_bank_details ) {
616
			$consumer_bank_details = new BankAccountDetails();
617
618
			$payment->set_consumer_bank_details( $consumer_bank_details );
619
		}
620
621
		/**
622
		 * Services.
623
		 */
624
		foreach ( $result->Services as $service ) {
625
			foreach ( $service->Parameters as $parameter ) {
626
				if ( 'consumerName' === $parameter->Name ) {
627
					$consumer_bank_details->set_name( $parameter->Value );
628
				}
629
630
				if ( 'consumerIBAN' === $parameter->Name ) {
631
					$consumer_bank_details->set_iban( $parameter->Value );
632
				}
633
634
				if ( 'consumerBIC' === $parameter->Name ) {
635
					$consumer_bank_details->set_bic( $parameter->Value );
636
				}
637
			}
638
		}
639
640
		/**
641
		 * Refunds.
642
		 *
643
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/GET-json-Transaction-RefundInfo-transactionKey
644
		 */
645
		$result = $this->request( 'GET', 'Transaction/RefundInfo/' . $transaction_key );
646
647
		if ( \property_exists( $result, 'RefundedAmount' ) && ! empty( $result->RefundedAmount ) ) {
648
			$refunded_amount = new Money( $result->RefundedAmount, $result->RefundCurrency );
649
650
			$payment->set_refunded_amount( $refunded_amount );
651
		}
652
	}
653
654
	/**
655
	 * Create refund.
656
	 *
657
	 * @param string $transaction_id Transaction ID.
658
	 * @param Money  $amount         Amount to refund.
659
	 * @param string $description    Refund reason.
660
	 * @return null|string
661
	 */
662
	public function create_refund( $transaction_id, Money $amount, $description = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $description is not used and could be removed. ( Ignorable by Annotation )

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

662
	public function create_refund( $transaction_id, Money $amount, /** @scrutinizer ignore-unused */ $description = null ) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
663
		$original_transaction = $this->request( 'GET', 'Transaction/Status/' . $transaction_id );
664
665
		if ( ! \is_object( $original_transaction ) ) {
666
			throw new \Exception(
667
				sprintf(
668
					/* translators: %s: transaction key */
669
					__( 'Unable to create refund for transaction with transaction key: %s', 'pronamic_ideal' ),
670
					$transaction_id
671
				)
672
			);
673
		}
674
675
		$service_name = Util::get_transaction_service( $original_transaction );
676
677
		if ( null === $service_name ) {
678
			throw new \Exception(
679
				sprintf(
680
					/* translators: %s: transaction key */
681
					__( 'Unable to create refund for transaction without service name. Transaction key: %s', 'pronamic_ideal' ),
682
					$transaction_id
683
				)
684
			);
685
		}
686
687
		// Invoice.
688
		$payment = \get_pronamic_payment_by_transaction_id( $transaction_id );
689
690
		$invoice = null;
691
692
		if ( null !== $payment ) {
693
			$invoice = Util::get_invoice_number( (string) $this->config->get_invoice_number(), $payment );
694
		}
695
696
		// Refund request.
697
		$data = (object) array(
698
			'Channel'                => 'Web',
699
			'Currency'               => $amount->get_currency()->get_alphabetic_code(),
700
			/**
701
			 * The credit amount for the request. This is in decimal format,
702
			 * with a point as the decimal separator. For example, if the
703
			 * currency is specified as EUR, sending “1” will mean that 1 euro
704
			 * will be paid. “1.00” is also 1 euro. “0.01” means 1 cent.
705
			 * Please note, a transaction must have either a debit amount or a
706
			 * credit amount and it cannot have both.
707
			 *
708
			 * @link https://dev.buckaroo.nl/Apis
709
			 */
710
			'AmountCredit'           => $amount->format( null, '.', '' ),
0 ignored issues
show
Unused Code introduced by
The call to Pronamic\WordPress\Money\Money::format() has too many arguments starting with '.'. ( Ignorable by Annotation )

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

710
			'AmountCredit'           => $amount->/** @scrutinizer ignore-call */ format( null, '.', '' ),

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
711
			'Invoice'                => $invoice,
712
			'OriginalTransactionKey' => $transaction_id,
713
			'Services'               => array(
714
				'ServiceList' => array(
715
					array(
716
						'Name'   => $service_name,
717
						'Action' => 'Refund',
718
					),
719
				),
720
			),
721
		);
722
723
		$refund = $this->request( 'POST', 'Transaction', $data );
724
725
		// Check refund object.
726
		if ( ! \is_object( $refund ) ) {
727
			return null;
728
		}
729
730
		// Check refund status.
731
		if ( \property_exists( $refund, 'Status' ) && \property_exists( $refund->Status, 'Code' ) ) {
732
			$status = Statuses::transform( (string) $refund->Status->Code->Code );
733
734
			if ( PaymentStatus::SUCCESS !== $status ) {
735
				throw new \Exception(
736
					\sprintf(
737
						/* translators: 1: payment provider name, 2: status message, 3: status sub message*/
738
						__( 'Unable to create refund at %1$s gateway: %2$s%3$s', 'pronamic_ideal' ),
739
						__( 'Buckaroo', 'pronamic_ideal' ),
740
						$refund->Status->Code->Description,
741
						\property_exists( $refund->Status, 'SubCode' ) ? ' – ' . $refund->Status->SubCode->Description : ''
742
					)
743
				);
744
			}
745
		}
746
747
		// Update payment refunded amount.
748
		if ( null !== $payment ) {
749
			$result = $this->request( 'GET', 'Transaction/RefundInfo/' . $transaction_id );
750
751
			if ( \property_exists( $result, 'RefundedAmount' ) && ! empty( $result->RefundedAmount ) ) {
752
				$refunded_amount = new Money( $result->RefundedAmount, $result->RefundCurrency );
753
754
				$payment->set_refunded_amount( $refunded_amount );
755
			}
756
		}
757
758
		// Return.
759
		$refund_id = \property_exists( $refund, 'Key' ) ? $refund->Key : null;
760
761
		return $refund_id;
762
	}
763
}
764