Failed Conditions
Push — develop ( 99c6e5...eea765 )
by Reüel
03:14
created

src/Client.php (6 issues)

1
<?php
2
3
namespace Pronamic\WordPress\Pay\Gateways\Buckaroo;
4
5
use WP_Error;
6
7
/**
8
 * Title: Buckaroo client
9
 * Description:
10
 * Copyright: 2005-2019 Pronamic
11
 * Company: Pronamic
12
 *
13
 * @author Remco Tolsma
14
 * @version 2.0.0
15
 * @since 1.0.0
16
 */
17
class Client {
18
	/**
19
	 * Gateway URL
20
	 *
21
	 * @var string
22
	 */
23
	const GATEWAY_URL = 'https://checkout.buckaroo.nl/html/';
24
25
	/**
26
	 * Gateway test URL
27
	 *
28
	 * @var string
29
	 */
30
	const GATEWAY_TEST_URL = 'https://testcheckout.buckaroo.nl/html/';
31
32
	/**
33
	 * Gateway Name-Value-Pair URL
34
	 *
35
	 * @var string
36
	 */
37
	const GATEWAY_NVP_URL = 'https://checkout.buckaroo.nl/nvp/';
38
39
	/**
40
	 * Gateway Name-Value-Pair test URL
41
	 *
42
	 * @var string
43
	 */
44
	const GATEWAY_NVP_TEST_URL = 'https://testcheckout.buckaroo.nl/nvp/';
45
46
	/**
47
	 * Indicator for the iDEAL payment method
48
	 *
49
	 * @var string
50
	 */
51
	const PAYMENT_METHOD_IDEAL = 'ideal';
52
53
	/**
54
	 * The payment server URL
55
	 *
56
	 * @var string
57
	 */
58
	private $payment_server_url;
59
60
	/**
61
	 * The amount
62
	 *
63
	 * @var int
64
	 */
65
	private $amount;
66
67
	/**
68
	 * The website key
69
	 *
70
	 * @var string
71
	 */
72
	private $website_key;
73
74
	/**
75
	 * The secret key
76
	 *
77
	 * @var string
78
	 */
79
	private $secret_key;
80
81
	/**
82
	 * The payment method
83
	 *
84
	 * @var string
85
	 */
86
	private $payment_method;
87
88
	/**
89
	 * The iDEAL issuer
90
	 *
91
	 * @since 1.2.4
92
	 * @var string
93
	 */
94
	private $ideal_issuer;
95
96
	/**
97
	 * The country code (culture)
98
	 *
99
	 * @var string
100
	 */
101
	private $culture;
102
103
	/**
104
	 * The currency
105
	 *
106
	 * @var string
107
	 */
108
	private $currency;
109
110
	/**
111
	 * The invoice number
112
	 *
113
	 * @var string
114
	 */
115
	private $invoice_number;
116
117
	/**
118
	 * The description
119
	 *
120
	 * @var string
121
	 */
122
	private $description;
123
124
	/**
125
	 * The return url
126
	 *
127
	 * @var string
128
	 */
129
	private $return_url;
130
131
	/**
132
	 * The return reject url
133
	 *
134
	 * @var string
135
	 */
136
	private $return_reject_url;
137
138
	/**
139
	 * The return error url
140
	 *
141
	 * @var string
142
	 */
143
	private $return_error_url;
144
145
	/**
146
	 * The return cancel url
147
	 *
148
	 * @var string
149
	 */
150
	private $return_cancel_url;
151
152
	/**
153
	 * Push URL
154
	 *
155
	 * @var string
156
	 */
157
	private $push_url;
158
159
	/**
160
	 * Requested services
161
	 *
162
	 * @var array
163
	 */
164
	private $requested_services;
165
166
	/**
167
	 * Excluded services
168
	 *
169
	 * @var array
170
	 */
171
	private $excluded_services;
172
173
	/**
174
	 * Pronamic payment ID
175
	 *
176
	 * @var array
177
	 */
178
	private $payment_id;
179
180
	/**
181
	 * Error.
182
	 *
183
	 * @since 1.2.6
184
	 * @var WP_Error
185
	 */
186
	private $error;
187
188
	/**
189
	 * Constructs and initialize a iDEAL kassa object
190
	 */
191 1
	public function __construct() {
192 1
		$this->set_payment_server_url( self::GATEWAY_URL );
193
194 1
		$this->requested_services = array();
195 1
	}
196
197
	/**
198
	 * Get error.
199
	 *
200
	 * @since 1.2.6
201
	 * @return WP_Error
202
	 */
203
	public function get_error() {
204
		return $this->error;
205
	}
206
207
	/**
208
	 * Get the payment server URL
209
	 *
210
	 * @return string the payment server URL
211
	 */
212
	public function get_payment_server_url() {
213
		return $this->payment_server_url;
214
	}
215
216
	/**
217
	 * Set the payment server URL
218
	 *
219
	 * @param string $url an URL
220
	 */
221 1
	public function set_payment_server_url( $url ) {
222 1
		$this->payment_server_url = $url;
223 1
	}
224
225 1
	public function get_website_key() {
226 1
		return $this->website_key;
227
	}
228
229 1
	public function set_website_key( $website_key ) {
230 1
		$this->website_key = $website_key;
231 1
	}
232
233 1
	public function get_secret_key() {
234 1
		return $this->secret_key;
235
	}
236
237 1
	public function set_secret_key( $secret_key ) {
238 1
		$this->secret_key = $secret_key;
239 1
	}
240
241
	public function get_payment_method() {
242
		return $this->payment_method;
243
	}
244
245
	public function set_payment_method( $payment_method ) {
246
		$this->payment_method = $payment_method;
247
	}
248
249
	/**
250
	 * Get iDEAL issuer.
251
	 *
252
	 * @since 1.2.4
253
	 * @return string
254
	 */
255
	public function get_ideal_issuer() {
256
		return $this->ideal_issuer;
257
	}
258
259
	/**
260
	 * Set iDEAL issuer.
261
	 *
262
	 * @since 1.2.4
263
	 *
264
	 * @param string $issuer
265
	 */
266
	public function set_ideal_issuer( $issuer ) {
267
		$this->ideal_issuer = $issuer;
268
	}
269
270
	public function get_requested_services() {
271
		return $this->requested_services;
272
	}
273
274
	public function add_requested_service( $service ) {
275
		$this->requested_services[] = $service;
276
	}
277
278
	public function get_excluded_services() {
279
		return $this->excluded_services;
280
	}
281
282
	public function set_excluded_services( $service ) {
283
		$this->excluded_services = $service;
284
	}
285
286
	public function get_culture() {
287
		return $this->culture;
288
	}
289
290
	public function set_culture( $culture ) {
291
		$this->culture = $culture;
292
	}
293
294
	public function get_currency() {
295
		return $this->currency;
296
	}
297
298
	public function set_currency( $currency ) {
299
		$this->currency = $currency;
300
	}
301
302
	public function get_invoice_number() {
303
		return $this->invoice_number;
304
	}
305
306
	public function set_invoice_number( $invoice_number ) {
307
		$this->invoice_number = $invoice_number;
308
	}
309
310
	public function get_description() {
311
		return $this->description;
312
	}
313
314
	public function set_description( $description ) {
315
		$this->description = $description;
316
	}
317
318
	/**
319
	 * Get amount.
320
	 *
321
	 * @return int
322
	 */
323
	public function get_amount() {
324
		return $this->amount;
325
	}
326
327
	/**
328
	 * Set amount.
329
	 *
330
	 * @param int $amount Amount.
331
	 */
332
	public function set_amount( $amount ) {
333
		$this->amount = $amount;
334
	}
335
336
	/**
337
	 * Get return URL
338
	 *
339
	 * @return string
340
	 */
341
	public function get_return_url() {
342
		return $this->return_url;
343
	}
344
345
	/**
346
	 * Set return URL
347
	 *
348
	 * @param string $url Return URL.
349
	 */
350
	public function set_return_url( $url ) {
351
		$this->return_url = $url;
352
	}
353
354
	/**
355
	 * Get return reject URL
356
	 *
357
	 * @return string
358
	 */
359
	public function get_return_reject_url() {
360
		return $this->return_reject_url;
361
	}
362
363
	/**
364
	 * Set return reject URL
365
	 *
366
	 * @param string $url Return reject URL.
367
	 */
368
	public function set_return_reject_url( $url ) {
369
		$this->return_reject_url = $url;
370
	}
371
372
	/**
373
	 * Get return error URL
374
	 *
375
	 * @return string
376
	 */
377
	public function get_return_error_url() {
378
		return $this->return_error_url;
379
	}
380
381
	/**
382
	 * Set return error URL
383
	 *
384
	 * @param string $url Return error URL.
385
	 */
386
	public function set_return_error_url( $url ) {
387
		$this->return_error_url = $url;
388
	}
389
390
	/**
391
	 * Get return cancel URL
392
	 *
393
	 * @return string
394
	 */
395
	public function get_return_cancel_url() {
396
		return $this->return_cancel_url;
397
	}
398
399
	/**
400
	 * Set return cancel URL
401
	 *
402
	 * @param string $url Return cancel URL.
403
	 */
404
	public function set_return_cancel_url( $url ) {
405
		$this->return_cancel_url = $url;
406
	}
407
408
	/**
409
	 * Get push URL
410
	 *
411
	 * @return string
412
	 */
413
	public function get_push_url() {
414
		return $this->push_url;
415
	}
416
417
	/**
418
	 * Set push URL
419
	 *
420
	 * @param string $url Push URL.
421
	 */
422
	public function set_push_url( $url ) {
423
		$this->push_url = $url;
424
	}
425
426
	/**
427
	 * Get Pronamic payment ID
428
	 *
429
	 * @return string
430
	 */
431
	public function get_payment_id() {
432
		return $this->payment_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->payment_id returns the type array which is incompatible with the documented return type string.
Loading history...
433
	}
434
435
	/**
436
	 * Set Pronamic payment ID
437
	 *
438
	 * @param string $payment_id Payment ID.
439
	 */
440
	public function set_payment_id( $payment_id ) {
441
		$this->payment_id = $payment_id;
0 ignored issues
show
Documentation Bug introduced by
It seems like $payment_id of type string is incompatible with the declared type array of property $payment_id.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
442
	}
443
444
	/**
445
	 * Get issuers
446
	 *
447
	 * @since 1.2.4
448
	 * @link http://support.buckaroo.nl/index.php/Service_iDEAL#iDEAL_banken_lijst_opvragen
449
	 * @return array
450
	 */
451 1
	public function get_issuers() {
452 1
		$issuers = array();
453
454 1
		$url = add_query_arg( 'op', 'TransactionRequestSpecification', self::GATEWAY_NVP_TEST_URL );
455
456
		$data = array(
457 1
			'brq_websitekey'        => $this->get_website_key(),
458 1
			'brq_services'          => 'ideal',
459 1
			'brq_latestversiononly' => 'True',
460
		);
461
462 1
		$signature = Security::create_signature( $data, $this->get_secret_key() );
463
464 1
		$data[ Parameters::SIGNATURE ] = $signature;
465
466 1
		$result = wp_remote_post(
467 1
			$url,
468
			array(
469 1
				'body' => http_build_query( $data ),
470
			)
471
		);
472
473 1
		$body = wp_remote_retrieve_body( $result );
0 ignored issues
show
It seems like $result can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

473
		$body = wp_remote_retrieve_body( /** @scrutinizer ignore-type */ $result );
Loading history...
474
475 1
		wp_parse_str( $body, $data );
476
477 1
		$data = Util::transform_flat_response( $data );
478
479 1
		$error_msg = __( 'Unable to retrieve issuers from Buckaroo.', 'pronamic_ideal' );
480
481 1
		if ( 200 !== wp_remote_retrieve_response_code( $result ) ) {
0 ignored issues
show
It seems like $result can also be of type WP_Error; however, parameter $response of wp_remote_retrieve_response_code() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

481
		if ( 200 !== wp_remote_retrieve_response_code( /** @scrutinizer ignore-type */ $result ) ) {
Loading history...
482
			$this->error = new WP_Error( 'buckaroo_error', $error_msg, $data );
483
484
			return $issuers;
485
		}
486
487 1
		if ( isset( $data['BRQ_APIRESULT'] ) && 'Fail' === $data['BRQ_APIRESULT'] ) {
488 1
			if ( isset( $data['BRQ_APIERRORMESSAGE'] ) ) {
489 1
				$error_msg = sprintf( '%s %s', $error_msg, $data['BRQ_APIERRORMESSAGE'] );
490
			}
491
492 1
			$this->error = new WP_Error( 'buckaroo_error', $error_msg, $data );
493
494 1
			return $issuers;
495
		}
496
497
		if ( ! isset( $data['BRQ_SERVICES'] ) ) {
498
			return $issuers;
499
		}
500
501
		foreach ( $data['BRQ_SERVICES'] as $service ) {
502
			if ( ! isset( $service['NAME'], $service['VERSION'], $service['ACTIONDESCRIPTION'] ) ) {
503
				return $issuers;
504
			}
505
506
			if ( PaymentMethods::IDEAL !== $service['NAME'] ) {
507
				continue;
508
			}
509
510
			foreach ( $service['ACTIONDESCRIPTION'] as $action ) {
511
				if ( ! isset( $action['NAME'], $action['REQUESTPARAMETERS'] ) ) {
512
					return $issuers;
513
				}
514
515
				if ( 'Pay' !== $action['NAME'] ) {
516
					continue;
517
				}
518
519
				foreach ( $action['REQUESTPARAMETERS'] as $parameter ) {
520
521
					if ( ! isset( $parameter['NAME'], $parameter['LISTITEMDESCRIPTION'] ) ) {
522
						return $issuers;
523
					}
524
525
					if ( 'issuer' !== $parameter['NAME'] ) {
526
						continue;
527
					}
528
529
					foreach ( $parameter['LISTITEMDESCRIPTION'] as $issuer ) {
530
						$issuers[ $issuer['VALUE'] ] = $issuer['DESCRIPTION'];
531
					}
532
533
					break;
534
				}
535
			}
536
		}
537
538
		return $issuers;
539
	}
540
541
	/**
542
	 * Get HTML fields
543
	 *
544
	 * @since 1.1.1
545
	 * @return string
546
	 */
547
	public function get_fields() {
548
		$data = array(
549
			Parameters::ADD_PRONAMIC_PAYMENT_ID => $this->get_payment_id(),
550
			Parameters::WEBSITE_KEY             => $this->get_website_key(),
551
			Parameters::INVOICE_NUMBER          => $this->get_invoice_number(),
552
			Parameters::AMOUNT                  => number_format( $this->get_amount(), 2, '.', '' ),
553
			Parameters::CURRENCY                => $this->get_currency(),
554
			Parameters::CULTURE                 => $this->get_culture(),
555
			Parameters::DESCRIPTION             => $this->get_description(),
556
			Parameters::PAYMENT_METHOD          => $this->get_payment_method(),
557
			Parameters::RETURN_URL              => $this->get_return_url(),
558
			Parameters::RETURN_REJECT_URL       => $this->get_return_reject_url(),
559
			Parameters::RETURN_ERROR_URL        => $this->get_return_error_url(),
560
			Parameters::RETURN_CANCEL_URL       => $this->get_return_cancel_url(),
561
			Parameters::PUSH_URL                => $this->get_push_url(),
562
			Parameters::PUSH_FAILURE_URL        => $this->get_push_url(),
563
			Parameters::REQUESTED_SERVICES      => implode( ',', $this->get_requested_services() ),
564
			Parameters::EXCLUDED_SERVICES       => $this->get_excluded_services(),
565
			Parameters::IDEAL_ISSUER            => $this->get_ideal_issuer(),
566
		);
567
568
		$signature = Security::create_signature( $data, $this->get_secret_key() );
569
570
		$data[ Parameters::SIGNATURE ] = $signature;
571
572
		return $data;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $data returns the type array<string,array|string> which is incompatible with the documented return type string.
Loading history...
573
	}
574
575
	/**
576
	 * Verify request Buckaroo
577
	 */
578
	public function verify_request( $data ) {
579
		$result = false;
580
581
		$signature = Security::get_signature( $data );
0 ignored issues
show
Are you sure the assignment to $signature is correct as Pronamic\WordPress\Pay\G...y::get_signature($data) targeting Pronamic\WordPress\Pay\G...curity::get_signature() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
582
583
		$signature_check = Security::create_signature( $data, $this->get_secret_key() );
584
585
		if ( 0 === strcasecmp( $signature, $signature_check ) ) {
586
			$data = array_change_key_case( $data, CASE_LOWER );
587
588
			$result = filter_var_array(
589
				$data,
590
				array(
591
					Parameters::ADD_PRONAMIC_PAYMENT_ID    => FILTER_SANITIZE_STRING,
592
					Parameters::PAYMENT                    => FILTER_SANITIZE_STRING,
593
					Parameters::PAYMENT_METHOD             => FILTER_SANITIZE_STRING,
594
					Parameters::STATUS_CODE                => FILTER_VALIDATE_INT,
595
					Parameters::STATUS_CODE_DETAIL         => FILTER_SANITIZE_STRING,
596
					Parameters::STATUS_MESSAGE             => FILTER_SANITIZE_STRING,
597
					Parameters::INVOICE_NUMBER             => FILTER_SANITIZE_STRING,
598
					Parameters::AMOUNT                     => FILTER_VALIDATE_FLOAT,
599
					Parameters::CURRENCY                   => FILTER_SANITIZE_STRING,
600
					Parameters::TIMESTAMP                  => FILTER_SANITIZE_STRING,
601
					Parameters::SERVICE_IDEAL_CONSUMER_ISSUER => FILTER_SANITIZE_STRING,
602
					Parameters::SERVICE_IDEAL_CONSUMER_NAME => FILTER_SANITIZE_STRING,
603
					Parameters::SERVICE_IDEAL_CONSUMER_IBAN => FILTER_SANITIZE_STRING,
604
					Parameters::SERVICE_IDEAL_CONSUMER_BIC => FILTER_SANITIZE_STRING,
605
					Parameters::TRANSACTIONS               => FILTER_SANITIZE_STRING,
606
				)
607
			);
608
		}
609
610
		return $result;
611
	}
612
}
613