Test Setup Failed
Push — feature/json-api ( f8df9f...4d01fe )
by Remco
05:23
created

Gateway::update_status()   B

Complexity

Conditions 9
Paths 37

Size

Total Lines 55
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 9
eloc 22
c 3
b 0
f 0
nc 37
nop 1
dl 0
loc 55
ccs 0
cts 0
cp 0
crap 90
rs 8.0555

How to fix   Long Method   

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
12
/**
13
 * Title: Buckaroo gateway
14
 * Description:
15
 * Copyright: 2005-2021 Pronamic
16
 * Company: Pronamic
17
 *
18
 * @author Remco Tolsma
19
 * @version 2.0.4
20
 * @since 1.0.0
21
 */
22
class Gateway extends Core_Gateway {
23
	/**
24
	 * Client.
25
	 *
26
	 * @var Client
27
	 */
28
	protected $client;
29
30
	/**
31
	 * Constructs and initializes an Buckaroo gateway
32
	 *
33
	 * @param Config $config Config.
34
	 */
35
	public function __construct( Config $config ) {
36
		parent::__construct( $config );
37
38
		$this->set_method( self::METHOD_HTTP_REDIRECT );
39
40
		// Supported features.
41
		$this->supports = array(
42
			'payment_status_request',
43
			'refunds',
44
			'webhook',
45
			'webhook_log',
46
			'webhook_no_config',
47
		);
48
49
		$this->client = new Client();
50
		$this->client->set_website_key( $config->get_website_key() );
51
		$this->client->set_secret_key( $config->get_secret_key() );
52
		$this->client->set_excluded_services( $config->get_excluded_services() );
53
		$this->client->set_invoice_number( $config->get_invoice_number() );
54
		$this->client->set_push_url( add_query_arg( 'buckaroo_push', '', home_url( '/' ) ) );
55
56
		if ( self::MODE_TEST === $config->mode ) {
57
			$this->client->set_payment_server_url( Client::GATEWAY_TEST_URL );
58
		}
59
	}
60
61
	/**
62
	 * Get issuers.
63
	 *
64
	 * @since 1.2.4
65
	 * @see Pronamic_WP_Pay_Gateway::get_issuers()
66
	 */
67
	public function get_issuers() {
68
		$groups = array();
69
70
		try {
71
			$result = $this->client->get_issuers();
72
73
			$groups[] = array(
74
				'options' => $result,
75
			);
76
		} catch ( \Exception $e ) {
77
			$this->error = new \WP_Error( 'buckaroo', $e->getMessage() );
78
		}
79
80
		return $groups;
81
	}
82
83
	/**
84
	 * Get supported payment methods
85
	 *
86
	 * @see Pronamic_WP_Pay_Gateway::get_supported_payment_methods()
87
	 */
88
	public function get_supported_payment_methods() {
89
		return array(
90
			Core_PaymentMethods::BANK_TRANSFER,
91
			Core_PaymentMethods::BANCONTACT,
92
			Core_PaymentMethods::CREDIT_CARD,
93
			Core_PaymentMethods::GIROPAY,
94
			Core_PaymentMethods::IDEAL,
95
			Core_PaymentMethods::PAYPAL,
96
			Core_PaymentMethods::SOFORT,
97
		);
98
	}
99
100
	/**
101
	 * Start
102
	 *
103
	 * @param Payment $payment Payment.
104
	 *
105
	 * @see Core_Gateway::start()
106
	 */
107
	public function start( Payment $payment ) {
108
		/**
109
		 * Currency.
110
		 */
111
		$currency_code = $payment->get_total_amount()->get_currency()->get_alphabetic_code();
112
113
		if ( null === $currency_code ) {
114
			throw new \InvalidArgumentException( 'Can not start payment with empty currency code.' );
115
		}
116
117
		/**
118
		 * JSON Transaction.
119
		 *
120
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
121
		 */
122
		$data = (object) array(
123
			'Currency'        => $currency_code,
124
			'AmountDebit'     => $payment->get_total_amount()->get_value(),
125
			'Invoice'         => \sprintf(
126
				'Payment %d',
127
				$payment->get_id()
128
			),
129
			'ReturnURL'       => $payment->get_return_url(),
130
			'ReturnURLCancel' => \add_query_arg(
131
				'buckaroo_return_url_cancel',
132
				true,
133
				$payment->get_return_url()
134
			),
135
			'ReturnURLError'  => \add_query_arg(
136
				'buckaroo_return_url_error',
137
				true,
138
				$payment->get_return_url()
139
			),
140
			'ReturnURLReject' => \add_query_arg(
141
				'buckaroo_return_url_reject',
142
				true,
143
				$payment->get_return_url()
144
			),
145
			/**
146
			 * Push URL.
147
			 * 
148
			 * When provided, this push URL overrides all the push URLs as configured in the payment plaza under websites for the associated website key
149
			 *
150
			 * @link https://dev.buckaroo.nl/Apis
151
			 */
152
			'PushURL'         => \rest_url( Integration::REST_ROUTE_NAMESPACE . '/push' ),
153
			/**
154
			 * Push URL Failure.
155
			 * 
156
			 * 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.
157
			 *
158
			 * @link https://dev.buckaroo.nl/Apis
159
			 */
160
			'PushURLFailure'  => \rest_url( Integration::REST_ROUTE_NAMESPACE . '/push' ),
161
			/**
162
			 * Services.
163
			 *
164
			 * Specifies which service (can be a payment method and/or additional service) is being called upon in the request.
165
			 *
166
			 * @link https://dev.buckaroo.nl/Apis
167
			 */
168
			'Services'        => (object) array(
169
				'ServiceList' => array(
170
					
171
				),
172
			),
173
		);
174
175
		/**
176
		 * Payment method.
177
		 * 
178
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
179
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=ServicesRequest
180
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=ServiceRequest
181
		 */
182
		$payment_method = $payment->get_method();
183
184
		switch ( $payment_method ) {
185
			/**
186
			 * Payment method creditcard.
187
			 * 
188
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/creditcards#pay
189
			 */
190
			case Core_PaymentMethods::CREDIT_CARD:
191
				$data->Services->ServiceList[] = (object) array(
192
					'Action' => 'Pay',
193
					'Name'   => PaymentMethods::AMERICAN_EXPRESS,
194
				);
195
196
				$data->Services->ServiceList[] = (object) array(
197
					'Action' => 'Pay',
198
					'Name'   => PaymentMethods::MAESTRO,
199
				);
200
201
				$data->Services->ServiceList[] = (object) array(
202
					'Action' => 'Pay',
203
					'Name'   => PaymentMethods::MASTERCARD,
204
				);
205
206
				$data->Services->ServiceList[] = (object) array(
207
					'Action' => 'Pay',
208
					'Name'   => PaymentMethods::VISA,
209
				);
210
211
				break;
212
			/**
213
			 * Payment method iDEAL.
214
			 * 
215
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/ideal#pay
216
			 */
217
			case Core_PaymentMethods::IDEAL:
218
				$data->Services->ServiceList[] = (object) array(
219
					'Action'     => 'Pay',
220
					'Name'       => 'ideal',
221
					'Parameters' => array(
222
						array(
223
							'Name'  => 'issuer',
224
							'Value' => $payment->get_issuer(),
225
						),
226
					),
227
				);
228
229
				break;
230
			/**
231
			 * Payment method transfer.
232
			 * 
233
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/transfer#pay
234
			 */
235
			case Core_PaymentMethods::BANK_TRANSFER:
236
				$data->Services->ServiceList[] = (object) array(
237
					'Action'     => 'Pay',
238
					'Name'       => 'transfer',
239
				);
240
241
				break;
242
			/**
243
			 * Payment method Bancontact.
244
			 * 
245
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/bancontact#pay
246
			 */
247
			case Core_PaymentMethods::BANCONTACT:
248
			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

248
			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...
249
				$data->Services->ServiceList[] = (object) array(
250
					'Action'     => 'Pay',
251
					'Name'       => 'bancontactmrcash',
252
				);
253
254
				break;
255
			/**
256
			 * Payment method Giropay.
257
			 * 
258
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/giropay#pay
259
			 */
260
			case Core_PaymentMethods::GIROPAY:
261
				$data->Services->ServiceList[] = (object) array(
262
					'Action'     => 'Pay',
263
					'Name'       => 'giropay',
264
				);
265
266
				break;
267
			/**
268
			 * Payment method PayPal.
269
			 * 
270
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/paypal#pay
271
			 */
272
			case Core_PaymentMethods::PAYPAL:
273
				$data->Services->ServiceList[] = (object) array(
274
					'Action'     => 'Pay',
275
					'Name'       => 'paypal',
276
				);
277
278
				break;
279
			/**
280
			 * Payment method Sofort.
281
			 * 
282
			 * @link https://dev.buckaroo.nl/PaymentMethods/Description/sofort#pay
283
			 */
284
			case Core_PaymentMethods::SOFORT:
285
				$data->Services->ServiceList[] = (object) array(
286
					'Action'     => 'Pay',
287
					'Name'       => 'sofortueberweisung',
288
				);
289
290
				break;
291
		}
292
293
		/**
294
		 * Request.
295
		 */
296
		$object = $this->request( 'POST', 'Transaction', $data );
297
298
		if ( 'Redirect' !== $object->RequiredAction->Name ) {
299
			throw new \Exception(
300
				\sprintf(
301
					'Unsupported Buckaroo required action: %s',
302
					$object->RequiredAction->Name
303
				)
304
			);
305
		}
306
307
		$payment->set_action_url( $object->RequiredAction->RedirectURL );
308
309
		/**
310
		 * Buckaroo keys.
311
		 * 
312
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionResponse
313
		 */
314
		$payment->set_meta( 'buckaroo_transaction_key', $object->Key );
315
		$payment->set_meta( 'buckaroo_transaction_payment_key', $object->PaymentKey );
316
317
		/**
318
		 * Transaction ID.
319
		 *
320
		 * @link https://dev.buckaroo.nl/PaymentMethods/Description/ideal]
321
		 */
322
		foreach ( $object->Services as $service ) {
323
			foreach ( $service->Parameters as $parameter ) {
324
				if ( 'transactionId' === $parameter->Name ) {
325
					$payment->set_transaction_id( $parameter->Value );
326
				}
327
			}
328
		}
329
	}
330
331
	/**
332
	 * Get output HTML
333
	 *
334
	 * @param Payment $payment Payment.
335
	 *
336
	 * @return array
337
	 *
338
	 * @see     Core_Gateway::get_output_html()
339
	 * @since   1.1.1
340
	 * @version 2.0.4
341
	 */
342
	public function get_output_fields( Payment $payment ) {
343
		$payment_method = $payment->get_method();
0 ignored issues
show
Unused Code introduced by
The assignment to $payment_method is dead and can be removed.
Loading history...
344
345
		// Locale.
346
		$culture = null;
347
348
		$customer = $payment->get_customer();
349
350
		if ( null !== $customer ) {
351
			$locale = $customer->get_locale();
352
353
			// Buckaroo uses 'nl-NL' instead of 'nl_NL'.
354
			if ( ! empty( $locale ) ) {
355
				$culture = str_replace( '_', '-', $locale );
356
			}
357
		}
358
359
		$this->client->set_payment_id( (string) $payment->get_id() );
360
		$this->client->set_culture( $culture );
361
		$this->client->set_currency( $payment->get_total_amount()->get_currency()->get_alphabetic_code() );
362
		$this->client->set_description( $payment->get_description() );
363
		$this->client->set_amount( $payment->get_total_amount()->get_value() );
364
		$this->client->set_invoice_number( Util::get_invoice_number( (string) $this->client->get_invoice_number(), $payment ) );
365
		$this->client->set_return_url( $payment->get_return_url() );
366
		$this->client->set_return_cancel_url( $payment->get_return_url() );
367
		$this->client->set_return_error_url( $payment->get_return_url() );
368
		$this->client->set_return_reject_url( $payment->get_return_url() );
369
370
		return $this->client->get_fields();
371
	}
372
373
	/**
374
	 * JSON API Request.
375
	 *
376
	 * @param string      $method   HTTP request method.
377
	 * @param string      $endpoint JSON API endpoint.
378
	 * @param object|null $data     Data.
379
	 */
380
	private function request( $method, $endpoint, $data = null ) {
381
		/**
382
		 * Authentication.
383
		 * 
384
		 * 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.
385
		 *
386
		 * @link https://dev.buckaroo.nl/Apis/Description/json
387
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Authentication
388
		 */
389
		$website_key         = $this->config->website_key;
390
		$request_http_method = $method;
391
		$request_uri         = 'testcheckout.buckaroo.nl/json/' . $endpoint;
392
		$request_timestamp   = \strval( \time() );
393
		$nonce               = \wp_generate_password( 32 );
394
		$request_content     = null === $data ? '' : \json_encode( $data );
395
396
		$values = \implode(
397
			'',
398
			array(
399
				$website_key,
400
				$request_http_method,
401
				\strtolower( \urlencode( $request_uri ) ),
402
				$request_timestamp,
403
				$nonce,
404
				null === $data ? '' : \base64_encode( \md5( $request_content, true ) ),
405
			)
406
		);
407
408
		$hash = \hash_hmac( 'sha256', $values, $this->config->secret_key, true );
409
410
		$hmac = \base64_encode( $hash );
411
412
		$authorization = \sprintf(
413
			'hmac %s:%s:%s:%s',
414
			$this->config->website_key,
415
			$hmac,
416
			$nonce,
417
			$request_timestamp
418
		);
419
420
		$response = \Pronamic\WordPress\Http\Facades\Http::request(
421
			'https://' . $request_uri,
422
			array(
423
				'method'  => $request_http_method,
424
				'headers' => array(
425
					'Authorization' => $authorization,
426
					'Content-Type'  => 'application/json',
427
				),
428
				'body'    => $request_content,
429
			)
430
		);
431
432
		$object = $response->json();
433
434
		/**
435
		 * Request Errors.
436
		 * 
437
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/POST-json-Transaction
438
		 */
439
		$exception = null;
440
441
		/**
442
		 * Channel errors.
443
		 * 
444
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionRequestResponseChannelError
445
		 */
446
		foreach ( $object->RequestErrors->ChannelErrors as $error ) {
447
			$exception = new \Exception( $error->ErrorMessage, 0, $exception );
448
		}
449
450
		/**
451
		 * Service errors.
452
		 * 
453
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionRequestResponseServiceError
454
		 */
455
		foreach ( $object->RequestErrors->ServiceErrors as $error ) {
456
			$exception = new \Exception( $error->ErrorMessage, 0, $exception );
457
		}
458
459
		/**
460
		 * Action errors.
461
		 * 
462
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionRequestResponseActionError
463
		 */
464
		foreach ( $object->RequestErrors->ActionErrors as $error ) {
465
			$exception = new \Exception( $error->ErrorMessage, 0, $exception );
466
		}
467
468
		/**
469
		 * Action errors.
470
		 * 
471
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionRequestResponseParameterError
472
		 */
473
		foreach ( $object->RequestErrors->ParameterErrors as $error ) {
474
			$exception = new \Exception( $error->ErrorMessage, 0, $exception );
475
		}
476
477
		/**
478
		 * Action errors.
479
		 * 
480
		 * @link https://testcheckout.buckaroo.nl/json/Docs/ResourceModel?modelName=TransactionRequestResponseCustomParameterError
481
		 */
482
		foreach ( $object->RequestErrors->CustomParameterErrors as $error ) {
483
			$exception = new \Exception( $error->ErrorMessage, 0, $exception );
484
		}
485
486
		if ( null !== $exception ) {
487
			throw $exception;
488
		}
489
490
		/**
491
		 * OK.
492
		 */
493
		return $object;
494
	}
495
496
	/**
497
	 * Update status of the specified payment
498
	 *
499
	 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/GET-json-Transaction-Status-transactionKey
500
	 * @param Payment $payment Payment.
501
	 */
502
	public function update_status( Payment $payment ) {
503
		$transaction_key = $payment->get_meta( 'buckaroo_transaction_key' );
504
505
		if ( empty( $transaction_key ) ) {
506
			return;
507
		}
508
509
		$result = $this->request( 'GET', 'Transaction/Status/' . $transaction_key );
510
511
		$payment->set_status( Statuses::transform( \strval( $result->Status->Code->Code ) ) );
512
513
		/**
514
		 * Consumer bank details.
515
		 */
516
		$consumer_bank_details = $payment->get_consumer_bank_details();
517
518
		if ( null === $consumer_bank_details ) {
519
			$consumer_bank_details = new BankAccountDetails();
520
521
			$payment->set_consumer_bank_details( $consumer_bank_details );
522
		}
523
524
		/**
525
		 * Services.
526
		 */
527
		foreach ( $result->Services as $service ) {
528
			foreach ( $service->Parameters as $parameter ) {
529
				if ( 'transactionId' === $parameter->Name ) {
530
					$payment->set_transaction_id( $parameter->Value );
531
				}
532
533
				if ( 'consumerName' === $parameter->Name ) {
534
					$consumer_bank_details->set_name( $parameter->Value );
535
				}
536
537
				if ( 'consumerIBAN' === $parameter->Name ) {
538
					$consumer_bank_details->set_iban( $parameter->Value );
539
				}
540
541
				if ( 'consumerBIC' === $parameter->Name ) {
542
					$consumer_bank_details->set_iban( $parameter->Value );
543
				}
544
			}
545
		}
546
547
		/**
548
		 * Refunds.
549
		 *
550
		 * @link https://testcheckout.buckaroo.nl/json/Docs/Api/GET-json-Transaction-RefundInfo-transactionKey
551
		 */
552
		$result = $this->request( 'GET', 'Transaction/RefundInfo/' . $transaction_key );
553
554
		$refunded_amount = new Money( $result->RefundedAmount, $result->RefundCurrency );
555
556
		$payment->set_refunded_amount( $refunded_amount );
557
	}
558
}
559