Failed Conditions
Push — develop ( 9276f5...e8fded )
by Reüel
06:29
created

Gateway::get_supported_payment_methods()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
c 2
b 0
f 0
nc 1
nop 0
dl 0
loc 9
ccs 0
cts 9
cp 0
crap 2
rs 10
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::BANK_TRANSFER,
85
			Core_PaymentMethods::BANCONTACT,
86
			Core_PaymentMethods::CREDIT_CARD,
87
			Core_PaymentMethods::GIROPAY,
88
			Core_PaymentMethods::IDEAL,
89
			Core_PaymentMethods::PAYPAL,
90
			Core_PaymentMethods::SOFORT,
91
		);
92
	}
93
94
	/**
95
	 * Start
96
	 *
97
	 * @param Payment $payment Payment.
98
	 *
99
	 * @see Core_Gateway::start()
100
	 */
101
	public function start( Payment $payment ) {
102
		/**
103
		 * Currency.
104
		 */
105
		$currency_code = $payment->get_total_amount()->get_currency()->get_alphabetic_code();
106
107
		if ( null === $currency_code ) {
108
			throw new \InvalidArgumentException( 'Can not start payment with empty currency code.' );
109
		}
110
111
		/**
112
		 * Push URL.
113
		 */
114
		$push_url = \rest_url( Integration::REST_ROUTE_NAMESPACE . '/push' );
115
116
		/**
117
		 * Filters the Buckaroo push URL.
118
		 *
119
		 * If you want to debug the Buckaroo report URL you can use this filter
120
		 * to override the push URL. You could for example use a service like
121
		 * https://webhook.site/ to inspect the push requests from Buckaroo.
122
		 *
123
		 * @param string $push_url Buckaroo push URL.
124
		 */
125
		$push_url = \apply_filters( 'pronamic_pay_buckaroo_push_url', $push_url );
126
127
		/**
128
		 * JSON Transaction.
129
		 *
130
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
131
		 */
132
		$data = (object) array(
133
			'Currency'                  => $currency_code,
134
			/**
135
			 * The debit amount for the request. This is in decimal format,
136
			 * with a point as the decimal separator. For example, if the
137
			 * currency is specified as EUR, sending “1” will mean that 1 euro
138
			 * will be paid. “1.00” is also 1 euro. “0.01” means 1 cent.
139
			 * Please note, a transaction must have either a debit amount or a
140
			 * credit amount and it cannot have both.
141
			 *
142
			 * @link https://dev.buckaroo.nl/Apis
143
			 */
144
			'AmountDebit'               => $payment->get_total_amount()->number_format( null, '.', '' ),
0 ignored issues
show
Bug introduced by
The method number_format() does not exist on Pronamic\WordPress\Money\TaxedMoney. Did you maybe mean format()? ( Ignorable by Annotation )

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

144
			'AmountDebit'               => $payment->get_total_amount()->/** @scrutinizer ignore-call */ number_format( null, '.', '' ),

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...
145
			'Description'               => $payment->get_description(),
146
			'Invoice'                   => Util::get_invoice_number( (string) $this->config->get_invoice_number(), $payment ),
147
			'ReturnURL'                 => $payment->get_return_url(),
148
			'ReturnURLCancel'           => \add_query_arg(
149
				'buckaroo_return_url_cancel',
150
				true,
151
				$payment->get_return_url()
152
			),
153
			'ReturnURLError'            => \add_query_arg(
154
				'buckaroo_return_url_error',
155
				true,
156
				$payment->get_return_url()
157
			),
158
			'ReturnURLReject'           => \add_query_arg(
159
				'buckaroo_return_url_reject',
160
				true,
161
				$payment->get_return_url()
162
			),
163
			/**
164
			 * Push URL.
165
			 *
166
			 * When provided, this push URL overrides all the push URLs as configured in the payment plaza under websites for the associated website key
167
			 *
168
			 * @link https://dev.buckaroo.nl/Apis
169
			 */
170
			'PushURL'                   => $push_url,
171
			/**
172
			 * Push URL Failure.
173
			 *
174
			 * 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.
175
			 *
176
			 * @link https://dev.buckaroo.nl/Apis
177
			 */
178
			'PushURLFailure'            => $push_url,
179
			/**
180
			 * Services.
181
			 *
182
			 * Specifies which service (can be a payment method and/or additional service) is being called upon in the request.
183
			 *
184
			 * @link https://dev.buckaroo.nl/Apis
185
			 */
186
			'Services'                  => (object) array(
187
				'ServiceList' => array(),
188
			),
189
			/**
190
			 * Continue On Incomplete.
191
			 *
192
			 * Specifies if a redirecturl to a payment form will be returned to
193
			 * which a customer should be sent if no paymentmethod is selected
194
			 * or if any required parameter which the customer may provide is
195
			 * missing or incorrect. Possible Values:
196
			 *
197
			 * · No: This is the default. The request will fail if not all the
198
			 * needed information is provided.
199
			 *
200
			 * · RedirectToHTML: A redirect to the HTML gateway is provided if
201
			 * a recoverable problems are detected in the request. The customer
202
			 * can then provide the needed information there.
203
			 *
204
			 * @link https://dev.buckaroo.nl/Apis
205
			 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
206
			 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=ContinueOnIncomplete
207
			 */
208
			'ContinueOnIncomplete'      => 'RedirectToHTML',
209
			/**
210
			 * Services Excluded For Client.
211
			 *
212
			 * If no primary service is provided and ContinueOnIncomplete is
213
			 * set, this list of comma separated servicescodes can be used to
214
			 * limit the number of services from which the customer may choose
215
			 * once he is redirected to the payment form. Services which are
216
			 * entered in this field are not selectable.
217
			 * This field is optional.
218
			 *
219
			 * @link https://dev.buckaroo.nl/Apis
220
			 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
221
			 */
222
			'ServicesExcludedForClient' => $this->config->get_excluded_services(),
223
			/**
224
			 * Custom parameters.
225
			 *
226
			 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
227
			 */
228
			'CustomParameters'          => array(
229
				(object) array(
230
					'Name'  => 'pronamic_payment_id',
231
					'Value' => $payment->get_id(),
232
				),
233
			),
234
		);
235
236
		/**
237
		 * Client IP.
238
		 *
239
		 * In this field the IP address of the customer (or employee) for which
240
		 * the action is being performed can be passed. Please note, If this
241
		 * field is not sent to our gateway, your server IP address will be
242
		 * used as the clientIP. This may result in unwanted behaviour for
243
		 * anti-fraud checks. Also, certain payment methods perform checks on
244
		 * the IP address, if an IP address is overused, the request could be
245
		 * blocked. This field is sent in the following format, where
246
		 * type 0 = IPv4 and type 1 = IPv6:
247
		 * "ClientIP": { "Type": 0, "Address": "0.0.0.0" },
248
		 *
249
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
250
		 * @link https://stackoverflow.com/questions/1448871/how-to-know-which-version-of-the-internet-protocol-ip-a-client-is-using-when-c/1448901
251
		 */
252
		$customer = $payment->get_customer();
253
254
		if ( null !== $customer ) {
255
			$ip_address = $customer->get_ip_address();
256
257
			if ( null !== $ip_address ) {
258
				$data->ClientIP = (object) array(
259
					'Type'    => false === \strpos( $ip_address, ':' ) ? 0 : 1,
260
					'Address' => $ip_address,
261
				);
262
			}
263
		}
264
265
		/**
266
		 * Payment method.
267
		 *
268
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
269
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=ServicesRequest
270
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=ServiceRequest
271
		 */
272
		$payment_method = $payment->get_method();
273
274
		switch ( $payment_method ) {
275
			/**
276
			 * Payment method creditcard.
277
			 *
278
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/creditcards#pay
279
			 */
280
			case Core_PaymentMethods::CREDIT_CARD:
281
				$data->Services->ServiceList[] = (object) array(
282
					'Action' => 'Pay',
283
					'Name'   => PaymentMethods::AMERICAN_EXPRESS,
284
				);
285
286
				$data->Services->ServiceList[] = (object) array(
287
					'Action' => 'Pay',
288
					'Name'   => PaymentMethods::MAESTRO,
289
				);
290
291
				$data->Services->ServiceList[] = (object) array(
292
					'Action' => 'Pay',
293
					'Name'   => PaymentMethods::MASTERCARD,
294
				);
295
296
				$data->Services->ServiceList[] = (object) array(
297
					'Action' => 'Pay',
298
					'Name'   => PaymentMethods::VISA,
299
				);
300
301
				break;
302
			/**
303
			 * Payment method iDEAL.
304
			 *
305
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/ideal#pay
306
			 */
307
			case Core_PaymentMethods::IDEAL:
308
				$data->Services->ServiceList[] = (object) array(
309
					'Action'     => 'Pay',
310
					'Name'       => 'ideal',
311
					'Parameters' => array(
312
						array(
313
							'Name'  => 'issuer',
314
							'Value' => $payment->get_issuer(),
315
						),
316
					),
317
				);
318
319
				break;
320
			/**
321
			 * Payment method transfer.
322
			 *
323
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/transfer#pay
324
			 */
325
			case Core_PaymentMethods::BANK_TRANSFER:
326
				$data->Services->ServiceList[] = (object) array(
327
					'Action' => 'Pay',
328
					'Name'   => 'transfer',
329
				);
330
331
				break;
332
			/**
333
			 * Payment method Bancontact.
334
			 *
335
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/bancontact#pay
336
			 */
337
			case Core_PaymentMethods::BANCONTACT:
338
			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

338
			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...
339
				$data->Services->ServiceList[] = (object) array(
340
					'Action' => 'Pay',
341
					'Name'   => 'bancontactmrcash',
342
				);
343
344
				break;
345
			/**
346
			 * Payment method Giropay.
347
			 *
348
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/giropay#pay
349
			 */
350
			case Core_PaymentMethods::GIROPAY:
351
				$data->Services->ServiceList[] = (object) array(
352
					'Action' => 'Pay',
353
					'Name'   => 'giropay',
354
				);
355
356
				break;
357
			/**
358
			 * Payment method PayPal.
359
			 *
360
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/paypal#pay
361
			 */
362
			case Core_PaymentMethods::PAYPAL:
363
				$data->Services->ServiceList[] = (object) array(
364
					'Action' => 'Pay',
365
					'Name'   => 'paypal',
366
				);
367
368
				break;
369
			/**
370
			 * Payment method Sofort.
371
			 *
372
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/sofort#pay
373
			 */
374
			case Core_PaymentMethods::SOFORT:
375
				$data->Services->ServiceList[] = (object) array(
376
					'Action' => 'Pay',
377
					'Name'   => 'sofortueberweisung',
378
				);
379
380
				break;
381
		}
382
383
		/**
384
		 * Request.
385
		 */
386
		$object = $this->request( 'POST', 'Transaction', $data );
387
388
		/**
389
		 * Buckaroo keys.
390
		 *
391
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionResponse
392
		 */
393
		if ( \property_exists( $object, 'Key' ) ) {
394
			$payment->set_transaction_id( $object->Key );
395
		}
396
397
		if ( \property_exists( $object, 'PaymentKey' ) ) {
398
			$payment->set_meta( 'buckaroo_transaction_payment_key', $object->PaymentKey );
399
		}
400
401
		/**
402
		 * Request Errors.
403
		 *
404
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
405
		 */
406
		if ( \property_exists( $object, 'RequestErrors' ) && null !== $object->RequestErrors ) {
407
			$exception = null;
408
409
			foreach ( $object->RequestErrors as $errors ) {
410
				foreach ( $errors as $error ) {
411
					// Add exception.
412
					$exception = new \Exception( $error->ErrorMessage, 0, $exception );
413
				}
414
			}
415
416
			if ( null !== $exception ) {
417
				throw $exception;
418
			}
419
		}
420
421
		/**
422
		 * Required Action.
423
		 */
424
		if ( null !== $object->RequiredAction ) {
425
			if ( 'Redirect' !== $object->RequiredAction->Name ) {
426
				throw new \Exception(
427
					\sprintf(
428
						'Unsupported Buckaroo action: %s',
429
						$object->RequiredAction->Name
430
					)
431
				);
432
			}
433
434
			// Set action URL.
435
			if ( \property_exists( $object->RequiredAction, 'RedirectURL' ) ) {
436
				$payment->set_action_url( $object->RequiredAction->RedirectURL );
437
			}
438
		}
439
440
		// Failure.
441
		if ( \property_exists( $object, 'Status' ) && \property_exists( $object->Status, 'Code' ) ) {
442
			$status = Statuses::transform( (string) $object->Status->Code->Code );
443
444
			if ( PaymentStatus::FAILURE === $status ) {
445
				throw new \Exception(
446
					\sprintf(
447
						/* translators: 1: payment provider name, 2: status message, 3: status sub message*/
448
						__( 'Unable to create payment at gateway: %1$s%2$s', 'pronamic_ideal' ),
449
						$object->Status->Code->Description,
450
						\property_exists( $object->Status, 'SubCode' ) ? ' – ' . $object->Status->SubCode->Description : ''
451
					)
452
				);
453
			}
454
		}
455
	}
456
457
	/**
458
	 * JSON API Request.
459
	 *
460
	 * @param string      $method   HTTP request method.
461
	 * @param string      $endpoint JSON API endpoint.
462
	 * @param object|null $data     Data.
463
	 */
464
	public function request( $method, $endpoint, $data = null ) {
465
		$host = 'checkout.buckaroo.nl';
466
467
		if ( self::MODE_TEST === $this->config->mode ) {
468
			$host = 'testcheckout.buckaroo.nl';
469
		}
470
471
		/**
472
		 * Authentication.
473
		 *
474
		 * 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.
475
		 *
476
		 * @link https://dev.buckaroo.nl/Apis/Description/json
477
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Authentication
478
		 */
479
		$website_key         = $this->config->website_key;
480
		$request_http_method = $method;
481
		$request_uri         = $host . '/json/' . $endpoint;
482
		$request_timestamp   = \strval( \time() );
483
		$nonce               = \wp_generate_password( 32 );
484
		$request_content     = null === $data ? '' : \wp_json_encode( $data );
485
486
		$values = \implode(
487
			'',
488
			array(
489
				$website_key,
490
				$request_http_method,
491
				\strtolower( \rawurlencode( $request_uri ) ),
492
				$request_timestamp,
493
				$nonce,
494
				// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
495
				null === $data ? '' : \base64_encode( \md5( (string) $request_content, true ) ),
496
			)
497
		);
498
499
		$hash = \hash_hmac( 'sha256', $values, $this->config->secret_key, true );
500
501
		// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
502
		$hmac = \base64_encode( $hash );
503
504
		$authorization = \sprintf(
505
			'hmac %s:%s:%s:%s',
506
			$this->config->website_key,
507
			$hmac,
508
			$nonce,
509
			$request_timestamp
510
		);
511
512
		$response = \Pronamic\WordPress\Http\Facades\Http::request(
513
			'https://' . $request_uri,
514
			array(
515
				'method'  => $request_http_method,
516
				'headers' => array(
517
					'Authorization' => $authorization,
518
					'Content-Type'  => 'application/json',
519
				),
520
				'body'    => $request_content,
521
			)
522
		);
523
524
		$object = $response->json();
525
526
		/**
527
		 * OK.
528
		 */
529
		return $object;
530
	}
531
532
	/**
533
	 * Update status of the specified payment
534
	 *
535
	 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/GET-json-Transaction-Status-transactionKey
536
	 * @param Payment $payment Payment.
537
	 */
538
	public function update_status( Payment $payment ) {
539
		$transaction_key = $payment->get_transaction_id();
540
541
		if ( empty( $transaction_key ) ) {
542
			return;
543
		}
544
545
		$result = $this->request( 'GET', 'Transaction/Status/' . $transaction_key );
546
547
		$payment->set_status( Statuses::transform( \strval( $result->Status->Code->Code ) ) );
548
549
		/**
550
		 * Consumer bank details.
551
		 */
552
		$consumer_bank_details = $payment->get_consumer_bank_details();
553
554
		if ( null === $consumer_bank_details ) {
555
			$consumer_bank_details = new BankAccountDetails();
556
557
			$payment->set_consumer_bank_details( $consumer_bank_details );
558
		}
559
560
		/**
561
		 * Services.
562
		 */
563
		foreach ( $result->Services as $service ) {
564
			foreach ( $service->Parameters as $parameter ) {
565
				if ( 'consumerName' === $parameter->Name ) {
566
					$consumer_bank_details->set_name( $parameter->Value );
567
				}
568
569
				if ( 'consumerIBAN' === $parameter->Name ) {
570
					$consumer_bank_details->set_iban( $parameter->Value );
571
				}
572
573
				if ( 'consumerBIC' === $parameter->Name ) {
574
					$consumer_bank_details->set_bic( $parameter->Value );
575
				}
576
			}
577
		}
578
579
		/**
580
		 * Refunds.
581
		 *
582
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/GET-json-Transaction-RefundInfo-transactionKey
583
		 */
584
		$result = $this->request( 'GET', 'Transaction/RefundInfo/' . $transaction_key );
585
586
		if ( \property_exists( $result, 'RefundedAmount' ) && ! empty( $result->RefundedAmount ) ) {
587
			$refunded_amount = new Money( $result->RefundedAmount, $result->RefundCurrency );
588
589
			$payment->set_refunded_amount( $refunded_amount );
590
		}
591
	}
592
593
	/**
594
	 * Create refund.
595
	 *
596
	 * @param string $transaction_id Transaction ID.
597
	 * @param Money  $amount         Amount to refund.
598
	 * @param string $description    Refund reason.
599
	 * @return null|string
600
	 */
601
	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

601
	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...
602
		$original_transaction = $this->request( 'GET', 'Transaction/Status/' . $transaction_id );
603
604
		if ( ! \is_object( $original_transaction ) ) {
605
			throw new \Exception(
606
				sprintf(
607
					/* translators: %s: transaction key */
608
					__( 'Unable to create refund for transaction with transaction key: %s', 'pronamic_ideal' ),
609
					$transaction_id
610
				)
611
			);
612
		}
613
614
		$service_name = Util::get_transaction_service( $original_transaction );
615
616
		if ( null === $service_name ) {
617
			throw new \Exception(
618
				sprintf(
619
					/* translators: %s: transaction key */
620
					__( 'Unable to create refund for transaction without service name. Transaction key: %s', 'pronamic_ideal' ),
621
					$transaction_id
622
				)
623
			);
624
		}
625
626
		// Invoice.
627
		$payment = \get_pronamic_payment_by_transaction_id( $transaction_id );
628
629
		$invoice = null;
630
631
		if ( null !== $payment ) {
632
			$invoice = Util::get_invoice_number( (string) $this->config->get_invoice_number(), $payment );
633
		}
634
635
		// Refund request.
636
		$data = (object) array(
637
			'Channel'                => 'Web',
638
			'Currency'               => $amount->get_currency()->get_alphabetic_code(),
639
			/**
640
			 * The credit amount for the request. This is in decimal format,
641
			 * with a point as the decimal separator. For example, if the
642
			 * currency is specified as EUR, sending “1” will mean that 1 euro
643
			 * will be paid. “1.00” is also 1 euro. “0.01” means 1 cent.
644
			 * Please note, a transaction must have either a debit amount or a
645
			 * credit amount and it cannot have both.
646
			 *
647
			 * @link https://dev.buckaroo.nl/Apis
648
			 */
649
			'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

649
			'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...
650
			'Invoice'                => $invoice,
651
			'OriginalTransactionKey' => $transaction_id,
652
			'Services'               => array(
653
				'ServiceList' => array(
654
					array(
655
						'Name'   => $service_name,
656
						'Action' => 'Refund',
657
					),
658
				),
659
			),
660
		);
661
662
		$refund = $this->request( 'POST', 'Transaction', $data );
663
664
		// Check refund object.
665
		if ( ! \is_object( $refund ) ) {
666
			return null;
667
		}
668
669
		// Check refund status.
670
		if ( \property_exists( $refund, 'Status' ) && \property_exists( $refund->Status, 'Code' ) ) {
671
			$status = Statuses::transform( (string) $refund->Status->Code->Code );
672
673
			if ( PaymentStatus::SUCCESS !== $status ) {
674
				throw new \Exception(
675
					\sprintf(
676
						/* translators: 1: payment provider name, 2: status message, 3: status sub message*/
677
						__( 'Unable to create refund at %1$s gateway: %2$s%3$s', 'pronamic_ideal' ),
678
						__( 'Buckaroo', 'pronamic_ideal' ),
679
						$refund->Status->Code->Description,
680
						\property_exists( $refund->Status, 'SubCode' ) ? ' – ' . $refund->Status->SubCode->Description : ''
681
					)
682
				);
683
			}
684
		}
685
686
		// Update payment refunded amount.
687
		if ( null !== $payment ) {
688
			$result = $this->request( 'GET', 'Transaction/RefundInfo/' . $transaction_id );
689
690
			if ( \property_exists( $result, 'RefundedAmount' ) && ! empty( $result->RefundedAmount ) ) {
691
				$refunded_amount = new Money( $result->RefundedAmount, $result->RefundCurrency );
692
693
				$payment->set_refunded_amount( $refunded_amount );
694
			}
695
		}
696
697
		// Return.
698
		$refund_id = \property_exists( $refund, 'Key' ) ? $refund->Key : null;
699
700
		return $refund_id;
701
	}
702
}
703