Gateway::get_supported_payment_methods()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

371
			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...
372
				$data->Services->ServiceList[] = (object) array(
373
					'Action' => 'Pay',
374
					'Name'   => 'bancontactmrcash',
375
				);
376
377
				break;
378
			/**
379
			 * Payment method Maestro.
380
			 * 
381
			 * @link 
382
			 */
383
			case Core_PaymentMethods::MAESTRO:
384
				$data->Services->ServiceList[] = (object) array(
385
					'Action' => 'Pay',
386
					'Name'   => PaymentMethods::MAESTRO,
387
				);
388
389
				break;
390
			/**
391
			 * Payment method Mastercard.
392
			 * 
393
			 * @link 
394
			 */
395
			case Core_PaymentMethods::MASTERCARD:
396
				$data->Services->ServiceList[] = (object) array(
397
					'Action' => 'Pay',
398
					'Name'   => PaymentMethods::MASTERCARD,
399
				);
400
401
				break;
402
			/**
403
			 * Payment method Giropay.
404
			 *
405
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/giropay#pay
406
			 */
407
			case Core_PaymentMethods::GIROPAY:
408
				$data->Services->ServiceList[] = (object) array(
409
					'Action' => 'Pay',
410
					'Name'   => 'giropay',
411
				);
412
413
				break;
414
			/**
415
			 * Payment method PayPal.
416
			 *
417
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/paypal#pay
418
			 */
419
			case Core_PaymentMethods::PAYPAL:
420
				$data->Services->ServiceList[] = (object) array(
421
					'Action' => 'Pay',
422
					'Name'   => 'paypal',
423
				);
424
425
				break;
426
			/**
427
			 * Payment method Sofort.
428
			 *
429
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/sofort#pay
430
			 */
431
			case Core_PaymentMethods::SOFORT:
432
				$data->Services->ServiceList[] = (object) array(
433
					'Action' => 'Pay',
434
					'Name'   => 'sofortueberweisung',
435
				);
436
437
				break;
438
			/**
439
			 * Payment method V PAY.
440
			 * 
441
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/creditcards#top
442
			 */
443
			case Core_PaymentMethods::V_PAY:
444
				$data->Services->ServiceList[] = (object) array(
445
					'Action' => 'Pay',
446
					'Name'   => PaymentMethods::V_PAY,
447
				);
448
449
				break;
450
			/**
451
			 * Payment method Visa.
452
			 * 
453
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/creditcards#top
454
			 */
455
			case Core_PaymentMethods::VISA:
456
				$data->Services->ServiceList[] = (object) array(
457
					'Action' => 'Pay',
458
					'Name'   => PaymentMethods::VISA,
459
				);
460
461
				break;
462
		}
463
464
		/**
465
		 * Request.
466
		 */
467
		$object = $this->request( 'POST', 'Transaction', $data );
468
469
		/**
470
		 * Buckaroo keys.
471
		 *
472
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionResponse
473
		 */
474
		if ( \property_exists( $object, 'Key' ) ) {
475
			$payment->set_transaction_id( $object->Key );
476
		}
477
478
		if ( \property_exists( $object, 'PaymentKey' ) ) {
479
			$payment->set_meta( 'buckaroo_transaction_payment_key', $object->PaymentKey );
480
		}
481
482
		/**
483
		 * Request Errors.
484
		 *
485
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
486
		 */
487
		if ( \property_exists( $object, 'RequestErrors' ) && null !== $object->RequestErrors ) {
488
			$exception = null;
489
490
			foreach ( $object->RequestErrors as $errors ) {
491
				foreach ( $errors as $error ) {
492
					// Add exception.
493
					$exception = new \Exception( $error->ErrorMessage, 0, $exception );
494
				}
495
			}
496
497
			if ( null !== $exception ) {
498
				throw $exception;
499
			}
500
		}
501
502
		/**
503
		 * Required Action.
504
		 */
505
		if ( null !== $object->RequiredAction ) {
506
			if ( 'Redirect' !== $object->RequiredAction->Name ) {
507
				throw new \Exception(
508
					\sprintf(
509
						'Unsupported Buckaroo action: %s',
510
						$object->RequiredAction->Name
511
					)
512
				);
513
			}
514
515
			// Set action URL.
516
			if ( \property_exists( $object->RequiredAction, 'RedirectURL' ) ) {
517
				$payment->set_action_url( $object->RequiredAction->RedirectURL );
518
			}
519
		}
520
521
		// Failure.
522
		if ( \property_exists( $object, 'Status' ) && \property_exists( $object->Status, 'Code' ) ) {
523
			$status = Statuses::transform( (string) $object->Status->Code->Code );
524
525
			if ( PaymentStatus::FAILURE === $status ) {
526
				throw new \Exception(
527
					\sprintf(
528
						/* translators: 1: payment provider name, 2: status message, 3: status sub message*/
529
						__( 'Unable to create payment at gateway: %1$s%2$s', 'pronamic_ideal' ),
530
						$object->Status->Code->Description,
531
						\property_exists( $object->Status, 'SubCode' ) ? ' – ' . $object->Status->SubCode->Description : ''
532
					)
533
				);
534
			}
535
		}
536
	}
537
538
	/**
539
	 * JSON API Request.
540
	 *
541
	 * @param string      $method   HTTP request method.
542
	 * @param string      $endpoint JSON API endpoint.
543
	 * @param object|null $data     Data.
544
	 * @return object
545
	 */
546
	public function request( $method, $endpoint, $data = null ) {
547
		$host = 'checkout.buckaroo.nl';
548
549
		if ( self::MODE_TEST === $this->config->mode ) {
550
			$host = 'testcheckout.buckaroo.nl';
551
		}
552
553
		/**
554
		 * Authentication.
555
		 *
556
		 * 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.
557
		 *
558
		 * @link https://dev.buckaroo.nl/Apis/Description/json
559
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Authentication
560
		 */
561
		$website_key         = $this->config->website_key;
562
		$request_http_method = $method;
563
		$request_uri         = $host . '/json/' . $endpoint;
564
		$request_timestamp   = \strval( \time() );
565
		$nonce               = \wp_generate_password( 32 );
566
		$request_content     = null === $data ? '' : \wp_json_encode( $data );
567
568
		$values = \implode(
569
			'',
570
			array(
571
				$website_key,
572
				$request_http_method,
573
				\strtolower( \rawurlencode( $request_uri ) ),
574
				$request_timestamp,
575
				$nonce,
576
				// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
577
				null === $data ? '' : \base64_encode( \md5( (string) $request_content, true ) ),
578
			)
579
		);
580
581
		$hash = \hash_hmac( 'sha256', $values, $this->config->secret_key, true );
582
583
		// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
584
		$hmac = \base64_encode( $hash );
585
586
		$authorization = \sprintf(
587
			'hmac %s:%s:%s:%s',
588
			$this->config->website_key,
589
			$hmac,
590
			$nonce,
591
			$request_timestamp
592
		);
593
594
		$response = \Pronamic\WordPress\Http\Facades\Http::request(
595
			'https://' . $request_uri,
596
			array(
597
				'method'  => $request_http_method,
598
				'headers' => array(
599
					'Authorization' => $authorization,
600
					'Content-Type'  => 'application/json',
601
				),
602
				'body'    => $request_content,
603
			)
604
		);
605
606
		try {
607
			$object = $response->json();
608
		} catch ( \Exception $e ) {
609
			// JSON error.
610
			$json_error = \json_last_error();
611
612
			// Check authorization error.
613
			if ( \JSON_ERROR_NONE !== $json_error && 400 === $response->status() ) {
614
				throw new \Exception( $response->body() );
615
			}
616
617
			// Re-throw original response exception.
618
			throw $e;
619
		}
620
621
		/**
622
		 * OK.
623
		 */
624
		return $object;
625
	}
626
627
	/**
628
	 * Update status of the specified payment
629
	 *
630
	 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/GET-json-Transaction-Status-transactionKey
631
	 * @param Payment $payment Payment.
632
	 */
633
	public function update_status( Payment $payment ) {
634
		$transaction_key = $payment->get_transaction_id();
635
636
		if ( empty( $transaction_key ) ) {
637
			return;
638
		}
639
640
		$result = $this->request( 'GET', 'Transaction/Status/' . $transaction_key );
641
642
		$payment->set_status( Statuses::transform( \strval( $result->Status->Code->Code ) ) );
643
644
		/**
645
		 * Consumer bank details.
646
		 */
647
		$consumer_bank_details = $payment->get_consumer_bank_details();
648
649
		if ( null === $consumer_bank_details ) {
650
			$consumer_bank_details = new BankAccountDetails();
651
652
			$payment->set_consumer_bank_details( $consumer_bank_details );
653
		}
654
655
		/**
656
		 * Services.
657
		 */
658
		foreach ( $result->Services as $service ) {
659
			foreach ( $service->Parameters as $parameter ) {
660
				if ( 'consumerName' === $parameter->Name ) {
661
					$consumer_bank_details->set_name( $parameter->Value );
662
				}
663
664
				if ( \in_array(
665
					$parameter->Name,
666
					array(
667
						/**
668
						 * Payment method iDEAL.
669
						 * 
670
						 * @link https://dev.buckaroo.nl/PaymentMethods/Description/ideal
671
						 */
672
						'consumerIBAN',
673
						/**
674
						 * Payment method Sofort.
675
						 * 
676
						 * @link https://dev.buckaroo.nl/PaymentMethods/Description/sofort
677
						 */
678
						'CustomerIBAN',
679
					),
680
					true
681
				) ) {
682
					$consumer_bank_details->set_iban( $parameter->Value );
683
				}
684
685
				if ( \in_array(
686
					$parameter->Name,
687
					array(
688
						/**
689
						 * Payment method iDEAL.
690
						 * 
691
						 * @link https://dev.buckaroo.nl/PaymentMethods/Description/ideal
692
						 */
693
						'consumerName',
694
						/**
695
						 * Payment method Sofort.
696
						 * 
697
						 * @link https://dev.buckaroo.nl/PaymentMethods/Description/sofort
698
						 */
699
						'CustomerBIC',
700
					),
701
					true
702
				) ) {
703
					$consumer_bank_details->set_bic( $parameter->Value );
704
				}
705
			}
706
		}
707
708
		/**
709
		 * Refunds.
710
		 *
711
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/GET-json-Transaction-RefundInfo-transactionKey
712
		 */
713
		$result = $this->request( 'GET', 'Transaction/RefundInfo/' . $transaction_key );
714
715
		if ( \property_exists( $result, 'RefundedAmount' ) && ! empty( $result->RefundedAmount ) ) {
716
			$refunded_amount = new Money( $result->RefundedAmount, $result->RefundCurrency );
717
718
			$payment->set_refunded_amount( $refunded_amount );
719
		}
720
	}
721
722
	/**
723
	 * Create refund.
724
	 *
725
	 * @param string $transaction_id Transaction ID.
726
	 * @param Money  $amount         Amount to refund.
727
	 * @param string $description    Refund reason.
728
	 * @return null|string
729
	 */
730
	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

730
	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...
731
		$original_transaction = $this->request( 'GET', 'Transaction/Status/' . $transaction_id );
732
733
		if ( ! \is_object( $original_transaction ) ) {
734
			throw new \Exception(
735
				sprintf(
736
					/* translators: %s: transaction key */
737
					__( 'Unable to create refund for transaction with transaction key: %s', 'pronamic_ideal' ),
738
					$transaction_id
739
				)
740
			);
741
		}
742
743
		$service_name = Util::get_transaction_service( $original_transaction );
744
745
		if ( null === $service_name ) {
746
			throw new \Exception(
747
				sprintf(
748
					/* translators: %s: transaction key */
749
					__( 'Unable to create refund for transaction without service name. Transaction key: %s', 'pronamic_ideal' ),
750
					$transaction_id
751
				)
752
			);
753
		}
754
755
		// Invoice.
756
		$payment = \get_pronamic_payment_by_transaction_id( $transaction_id );
757
758
		$invoice = null;
759
760
		if ( null !== $payment ) {
761
			$invoice = Util::get_invoice_number( (string) $this->config->get_invoice_number(), $payment );
762
		}
763
764
		// Refund request.
765
		$data = (object) array(
766
			'Channel'                => 'Web',
767
			'Currency'               => $amount->get_currency()->get_alphabetic_code(),
768
			/**
769
			 * The credit amount for the request. This is in decimal format,
770
			 * with a point as the decimal separator. For example, if the
771
			 * currency is specified as EUR, sending “1” will mean that 1 euro
772
			 * will be paid. “1.00” is also 1 euro. “0.01” means 1 cent.
773
			 * Please note, a transaction must have either a debit amount or a
774
			 * credit amount and it cannot have both.
775
			 *
776
			 * @link https://dev.buckaroo.nl/Apis
777
			 */
778
			'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

778
			'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...
779
			'Invoice'                => $invoice,
780
			'OriginalTransactionKey' => $transaction_id,
781
			'Services'               => array(
782
				'ServiceList' => array(
783
					array(
784
						'Name'   => $service_name,
785
						'Action' => 'Refund',
786
					),
787
				),
788
			),
789
		);
790
791
		$refund = $this->request( 'POST', 'Transaction', $data );
792
793
		// Check refund object.
794
		if ( ! \is_object( $refund ) ) {
795
			return null;
796
		}
797
798
		// Check refund status.
799
		if ( \property_exists( $refund, 'Status' ) && \property_exists( $refund->Status, 'Code' ) ) {
800
			$status = Statuses::transform( (string) $refund->Status->Code->Code );
801
802
			if ( PaymentStatus::SUCCESS !== $status ) {
803
				throw new \Exception(
804
					\sprintf(
805
						/* translators: 1: payment provider name, 2: status message, 3: status sub message*/
806
						__( 'Unable to create refund at %1$s gateway: %2$s%3$s', 'pronamic_ideal' ),
807
						__( 'Buckaroo', 'pronamic_ideal' ),
808
						$refund->Status->Code->Description,
809
						\property_exists( $refund->Status, 'SubCode' ) ? ' – ' . $refund->Status->SubCode->Description : ''
810
					)
811
				);
812
			}
813
		}
814
815
		// Update payment refunded amount.
816
		if ( null !== $payment ) {
817
			$result = $this->request( 'GET', 'Transaction/RefundInfo/' . $transaction_id );
818
819
			if ( \property_exists( $result, 'RefundedAmount' ) && ! empty( $result->RefundedAmount ) ) {
820
				$refunded_amount = new Money( $result->RefundedAmount, $result->RefundCurrency );
821
822
				$payment->set_refunded_amount( $refunded_amount );
823
			}
824
		}
825
826
		// Return.
827
		$refund_id = \property_exists( $refund, 'Key' ) ? $refund->Key : null;
828
829
		return $refund_id;
830
	}
831
}
832