Test Failed
Push — develop ( 5edab0...b80e50 )
by Reüel
06:00
created

Integration::field_certificate()   B

Complexity

Conditions 8
Paths 15

Size

Total Lines 64
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
cc 8
eloc 41
c 0
b 0
f 0
nc 15
nop 1
dl 0
loc 64
rs 8.0195
ccs 0
cts 1
cp 0
crap 72

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
 * Integration
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2020 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Gateways\Adyen
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Adyen;
12
13
use Pronamic\WordPress\Pay\Dependencies\PhpExtensionDependency;
14
use Pronamic\WordPress\Pay\AbstractGatewayIntegration;
15
use Pronamic\WordPress\Pay\Util as Pay_Util;
16
17
/**
18
 * Integration
19
 *
20
 * @author  Remco Tolsma
21
 * @version 1.0.5
22
 * @since   1.0.0
23
 */
24
class Integration extends AbstractGatewayIntegration {
25
	/**
26
	 * REST route namespace.
27
	 *
28
	 * @var string
29
	 */
30
	const REST_ROUTE_NAMESPACE = 'pronamic-pay/adyen/v1';
31
32
	/**
33
	 * Construct Adyen integration.
34
	 *
35
	 * @param array $args Arguments.
36
	 */
37 5
	public function __construct( $args = array() ) {
38 5
		$args = wp_parse_args(
39 5
			$args,
40
			array(
41 5
				'id'            => 'adyen',
42 5
				'name'          => 'Adyen',
43 5
				'provider'      => 'adyen',
44 5
				'url'           => \__( 'https://www.adyen.com/', 'pronamic_ideal' ),
45 5
				'product_url'   => \__( 'https://www.adyen.com/pricing', 'pronamic_ideal' ),
46
				'dashboard_url' => array(
47 5
					\__( 'test', 'pronamic_ideal' ) => 'https://ca-test.adyen.com/ca/ca/login.shtml',
48 5
					\__( 'live', 'pronamic_ideal' ) => 'https://ca-live.adyen.com/ca/ca/login.shtml',
49
				),
50 5
				'manual_url'    => \__( 'https://www.pronamic.eu/manuals/using-adyen-pronamic-pay/', 'pronamic_ideal' ),
51
				'supports'      => array(
52
					'webhook',
53
					'webhook_log',
54
				),
55
			)
56
		);
57
58 5
		parent::__construct( $args );
59
60
		// Dependencies.
61 5
		$dependencies = $this->get_dependencies();
62
63 5
		$dependencies->add( new PhpExtensionDependency( 'intl' ) );
64 5
	}
65
66
	/**
67
	 * Plugins loaded.
68
	 *
69
	 * @return void
70
	 */
71 1
	public function plugins_loaded() {
72 1
		if ( ! $this->get_dependencies()->are_met() ) {
73
			return;
74
		}
75
76
		// Notifications controller.
77 1
		$notifications_controller = new NotificationsController();
78
79 1
		$notifications_controller->setup();
80
81
		// Payments controller.
82 1
		$payments_controller = new PaymentsController();
83
84 1
		$payments_controller->setup();
85
86
		// Payments result controller.
87 1
		$payments_result_controller = new PaymentsResultController();
88
89 1
		$payments_result_controller->setup();
90
91
		// Site Health controller.
92 1
		$site_healht_controller = new SiteHealthController();
93
94 1
		$site_healht_controller->setup();
95
96
		// Settings.
97 1
		add_action( 'init', array( $this, 'init' ) );
98 1
		add_action( 'admin_init', array( $this, 'admin_init' ) );
99 1
100
		// Actions.
101
		add_action( 'current_screen', array( $this, 'maybe_download_certificate_or_key' ) );
102
	}
103
104
	/**
105
	 * Initialize.
106 1
	 *
107
	 * @return void
108
	 */
109
	public function init() {
110 1
		/*
111 1
		 * Authentication - User Name
112 1
		 */
113
		register_setting(
114 1
			'pronamic_pay',
115
			'pronamic_pay_adyen_notification_authentication_username',
116
			array(
117
				'type'              => 'string',
118
				'sanitize_callback' => 'sanitize_text_field',
119
			)
120
		);
121
122 1
		/*
123 1
		 * Authentication - Password
124 1
		 */
125
		register_setting(
126 1
			'pronamic_pay',
127
			'pronamic_pay_adyen_notification_authentication_password',
128
			array(
129
				'type'              => 'string',
130 1
				'sanitize_callback' => 'sanitize_text_field',
131
			)
132
		);
133
	}
134
135
	/**
136
	 * Admin initialize.
137 1
	 *
138 1
	 * @return void
139 1
	 */
140
	public function admin_init() {
141 1
		add_settings_section(
142 1
			'pronamic_pay_adyen_notification_authentication',
143 1
			/* translators: Translate 'notification' the same as in the Adyen dashboard. */
144
			_x( 'Adyen Notification Authentication', 'Adyen', 'pronamic_ideal' ),
145
			array( $this, 'settings_section_notification_authentication' ),
146 1
			'pronamic_pay'
147 1
		);
148 1
149 1
		add_settings_field(
150 1
			'pronamic_pay_adyen_notification_authentication_username',
151 1
			__( 'User Name', 'pronamic_ideal' ),
152
			array( __CLASS__, 'input_element' ),
153 1
			'pronamic_pay',
154
			'pronamic_pay_adyen_notification_authentication',
155
			array(
156
				'label_for' => 'pronamic_pay_adyen_notification_authentication_username',
157 1
			)
158 1
		);
159 1
160 1
		add_settings_field(
161 1
			'pronamic_pay_adyen_notification_authentication_password',
162 1
			__( 'Password', 'pronamic_ideal' ),
163
			array( __CLASS__, 'input_element' ),
164 1
			'pronamic_pay',
165
			'pronamic_pay_adyen_notification_authentication',
166
			array(
167 1
				'label_for' => 'pronamic_pay_adyen_notification_authentication_password',
168
			)
169
		);
170
	}
171
172
	/**
173
	 * Settings section notification authentication.
174 1
	 *
175 1
	 * @return void
176 1
	 */
177 1
	public function settings_section_notification_authentication() {
178 1
		printf(
179 1
			'<p>%s</p>',
180
			esc_html__(
181
				'Set the user name and password below and in the webhook authentication settings in the Adyen dashboard for increased security (recommended).',
182 1
				'pronamic_ideal'
183
			)
184
		);
185
	}
186
187
	/**
188
	 * Input text.
189
	 *
190 1
	 * @param array<string,string> $args Arguments.
191 1
	 * @return void
192
	 */
193 1
	public static function input_element( $args ) {
194 1
		$name = $args['label_for'];
195
196 1
		$value = get_option( $name );
197 1
		$value = strval( $value );
198 1
199 1
		printf(
200 1
			'<input name="%s" id="%s" value="%s" type="text" class="regular-text" />',
201
			esc_attr( $name ),
202 1
			esc_attr( $name ),
203
			esc_attr( $value )
204
		);
205
	}
206
207
	/**
208
	 * Get settings fields.
209 1
	 *
210 1
	 * @return array<int, array<string, int|string|bool|array<int,string>>>
211
	 */
212
	public function get_settings_fields() {
213 1
		$fields = array();
214 1
215 1
		// Merchant Account.
216 1
		$fields[] = array(
217 1
			'section'  => 'general',
218 1
			'filter'   => FILTER_SANITIZE_STRING,
219
			'meta_key' => '_pronamic_gateway_adyen_merchant_account',
220 1
			'title'    => _x( 'Merchant Account', 'adyen', 'pronamic_ideal' ),
221
			'type'     => 'text',
222
			'classes'  => array( 'regular-text', 'code' ),
223
			'tooltip'  => __( 'The merchant account identifier, with which you want to process the transaction.', 'pronamic_ideal' ),
224 1
		);
225 1
226 1
		// API Key.
227 1
		$fields[] = array(
228 1
			'section'     => 'general',
229 1
			'filter'      => FILTER_SANITIZE_STRING,
230
			'meta_key'    => '_pronamic_gateway_adyen_api_key',
231 1
			'title'       => _x( 'API Key', 'adyen', 'pronamic_ideal' ),
232 1
			'type'        => 'textarea',
233 1
			'classes'     => array( 'code' ),
234 1
			'tooltip'     => __( 'API key as mentioned in the payment provider dashboard.', 'pronamic_ideal' ),
235 1
			'description' => sprintf(
236
				'<a href="%s" target="_blank">%s</a>',
237
				esc_url( 'https://docs.adyen.com/developers/user-management/how-to-get-the-api-key' ),
238
				esc_html__( 'Adyen documentation: "How to get the API key".', 'pronamic_ideal' )
239
			),
240 1
		);
241 1
242 1
		// Live API URL prefix.
243 1
		$fields[] = array(
244 1
			'section'     => 'general',
245 1
			'filter'      => FILTER_SANITIZE_STRING,
246
			'meta_key'    => '_pronamic_gateway_adyen_api_live_url_prefix',
247 1
			'title'       => _x( 'API Live URL Prefix', 'adyen', 'pronamic_ideal' ),
248 1
			'type'        => 'text',
249 1
			'classes'     => array( 'regular-text', 'code' ),
250 1
			'tooltip'     => __( 'The unique prefix for the live API URL, as mentioned at <strong>Account » API URLs</strong> in the Adyen dashboard.', 'pronamic_ideal' ),
251 1
			'description' => sprintf(
252
				'<a href="%s" target="_blank">%s</a>',
253
				esc_url( 'https://docs.adyen.com/developers/development-resources/live-endpoints#liveurlprefix' ),
254
				esc_html__( 'Adyen documentation: "Live URL prefix".', 'pronamic_ideal' )
255
			),
256 1
		);
257 1
258 1
		// Origin Key.
259 1
		$fields[] = array(
260 1
			'section'     => 'general',
261 1
			'filter'      => FILTER_SANITIZE_STRING,
262
			'meta_key'    => '_pronamic_gateway_adyen_origin_key',
263
			'title'       => _x( 'Origin Key', 'adyen', 'pronamic_ideal' ),
264
			'type'        => 'text',
265
			'classes'     => array(
266
				'regular-text',
267 1
				'code',
268 1
				'pronamic-pay-form-control-lg',
269 1
			),
270 1
			'tooltip'     => __( 'An origin key is a client-side key that is used to validate Adyen\'s JavaScript component library. It is required for the Drop-in and Component integrations.', 'pronamic_ideal' ),
271 1
			'description' => sprintf(
272
				'<a href="%s" target="_blank">%s</a>',
273
				esc_url( 'https://docs.adyen.com/user-management/how-to-get-an-origin-key' ),
274
				esc_html__( 'Adyen documentation: "How to get an origin key".', 'pronamic_ideal' )
275
			),
276 1
		);
277 1
278 1
		// Apple Pay - Merchant identifier.
279 1
		$fields[] = array(
280 1
			'section'     => 'advanced',
281 1
			'filter'      => \FILTER_SANITIZE_STRING,
282
			'meta_key'    => '_pronamic_gateway_adyen_apple_pay_merchant_id',
283 1
			'title'       => _x( 'Apple Pay Merchant ID', 'adyen', 'pronamic_ideal' ),
284 1
			'type'        => 'text',
285 1
			'classes'     => array( 'regular-text', 'code' ),
286 1
			'tooltip'     => __( 'Your Apple Pay Merchant ID. Required for accepting live payments.', 'pronamic_ideal' ),
287 1
			'description' => sprintf(
288 1
				'<a href="%s" target="_blank">%s</a><br /><a href="%s" target="_blank">%s</a>',
289 1
				esc_url( 'https://docs.adyen.com/payment-methods/apple-pay/web-drop-in#before-you-begin' ),
290
				esc_html__( 'Adyen documentation: "Apple Pay Drop-in - Before you begin".', 'pronamic_ideal' ),
291
				esc_url( 'https://developer.apple.com/documentation/apple_pay_on_the_web/configuring_your_environment' ),
292
				esc_html__( 'Apple documentation: "Configuring your environment".', 'pronamic_ideal' )
293
			),
294 1
		);
295 1
296 1
		// Apple Pay - Merchant Identity PKCS#12.
297 1
		$fields[] = array(
298 1
			'section'  => 'advanced',
299 1
			'filter'   => \FILTER_SANITIZE_STRING,
300
			'meta_key' => '_pronamic_gateway_adyen_apple_pay_merchant_id_certificate',
301 1
			'title'    => __( 'Apple Pay Merchant Identity Certificate', 'pronamic_ideal' ),
302 1
			'type'     => 'textarea',
303 1
			'callback' => array( $this, 'field_certificate' ),
304 1
			'classes'  => array( 'code' ),
305 1
			'tooltip'  => __( 'The Apple Pay Merchant Identity certificate required for secure communication with Apple.', 'pronamic_ideal' ),
306
			'description' => sprintf(
307
				'<a href="%s" target="_blank">%s</a>',
308
				esc_url( 'https://docs.adyen.com/payment-methods/apple-pay/enable-apple-pay#create-merchant-identity-certificate' ),
309
				esc_html__( 'Adyen documentation: "Enable Apple Pay - Create a merchant identity certificate".', 'pronamic_ideal' )
310 1
			),
311 1
		);
312 1
313 1
		// Apple Pay - Merchant Identity private key.
314 1
		$fields[] = array(
315 1
			'section'  => 'advanced',
316
			'filter'   => \FILTER_SANITIZE_STRING,
317 1
			'meta_key' => '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key',
318 1
			'title'    => __( 'Apple Pay Merchant Identity Private Key', 'pronamic_ideal' ),
319 1
			'type'     => 'textarea',
320 1
			'callback' => array( $this, 'field_private_key' ),
321 1
			'classes'  => array( 'code' ),
322 1
			'tooltip'  => __( 'The private key of the Apple Pay Merchant Identity certificate for secure communication with Apple.', 'pronamic_ideal' ),
323 1
		);
324
325
		// Apple Pay - Merchant Identity certificate private key password.
326
		$fields[] = array(
327
			'section'     => 'advanced',
328 1
			'filter'      => \FILTER_SANITIZE_STRING,
329 1
			'meta_key'    => '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key_password',
330 1
			'title'       => _x( 'Apple Pay Merchant Identity Private Key Password', 'adyen', 'pronamic_ideal' ),
331 1
			'type'        => 'text',
332
			'classes'     => array( 'regular-text', 'code' ),
333 1
			'tooltip'     => __( 'Your Apple Pay Merchant Identity Certificate private key password.', 'pronamic_ideal' ),
334
		);
335 1
336
		// Google Pay - Merchant identifier.
337 1
		$fields[] = array(
338 1
			'section'     => 'advanced',
339 1
			'filter'      => \FILTER_SANITIZE_STRING,
340
			'meta_key'    => '_pronamic_gateway_adyen_google_pay_merchant_identifier',
341 1
			'title'       => _x( 'Google Pay Merchant ID', 'adyen', 'pronamic_ideal' ),
342
			'type'        => 'text',
343
			'classes'     => array( 'regular-text', 'code' ),
344
			'tooltip'     => __( 'Your Google Merchant ID. Required for accepting live payments.', 'pronamic_ideal' ),
345
			'description' => sprintf(
346
				'<a href="%s" target="_blank">%s</a><br /><a href="%s" target="_blank">%s</a>',
347
				esc_url( 'https://docs.adyen.com/payment-methods/google-pay/web-drop-in#test-and-go-live' ),
348
				esc_html__( 'Adyen documentation: "Google Pay Drop-in - Test and go live".', 'pronamic_ideal' ),
349
				esc_url( 'https://developers.google.com/pay/api/web/guides/test-and-deploy/deploy-production-environment' ),
350
				esc_html__( 'Google documentation: "Deploy production environment".', 'pronamic_ideal' )
351 1
			),
352 1
		);
353 1
354 1
		// Webhook URL.
355 1
		$fields[] = array(
356
			'section'  => 'feedback',
357
			'title'    => __( 'Webhook URL', 'pronamic_ideal' ),
358
			'type'     => 'text',
359
			'classes'  => array( 'large-text', 'code' ),
360
			'value'    => rest_url( self::REST_ROUTE_NAMESPACE . '/notifications' ),
361
			'readonly' => true,
362
			'tooltip'  => sprintf(
363
				/* translators: %s: Adyen */
364 1
				__(
365 1
					'Copy the Webhook URL to the %s dashboard to receive automatic transaction status updates.',
366 1
					'pronamic_ideal'
367 1
				),
368 1
				__( 'Adyen', 'pronamic_ideal' )
369
			),
370
		);
371
372 1
		/**
373 1
		 * SSL Version.
374 1
		 *
375 1
		 * @link https://docs.adyen.com/developers/development-resources/notifications/set-up-notifications#step3configurenotificationsinthecustomerarea
376 1
		 * @link https://www.howsmyssl.com/a/check
377 1
		 */
378 1
		$fields[] = array(
379 1
			'section' => 'feedback',
380
			'title'   => __( 'SSL Version', 'pronamic_ideal' ),
381 1
			'type'    => 'description',
382
			'html'    => __( 'Choose the SSL Version of your server on the Adyen Customer Area.', 'pronamic_ideal' ),
383 1
		);
384
385
		/**
386
		 * Method.
387
		 *
388
		 * @link https://docs.adyen.com/developers/development-resources/notifications/set-up-notifications#step3configurenotificationsinthecustomerarea
389 1
		 * @link https://www.howsmyssl.com/a/check
390
		 */
391
		$fields[] = array(
392
			'section' => 'feedback',
393
			'title'   => _x( 'Method', 'adyen notification', 'pronamic_ideal' ),
394
			'type'    => 'description',
395
			'html'    => __( 'JSON', 'pronamic_ideal' ),
396
		);
397
398 1
		// Webhook authentication settings.
399 1
		$fields[] = array(
400
			'section' => 'feedback',
401 1
			'title'   => __( 'Authentication', 'pronamic_ideal' ),
402 1
			'type'    => 'description',
403 1
			'html'    => sprintf(
404 1
				'For webhook authentication settings, please visit <a href="%2$s" title="Settings">%1$s settings</a>.',
405 1
				__( 'Pronamic Pay', 'pronamic_ideal' ),
406 1
				add_query_arg(
407 1
					array(
408 1
						'page' => 'pronamic_pay_settings',
409
					),
410 1
					admin_url( 'admin.php' )
411
				)
412
			),
413
		);
414
415
		// Return fields.
416
		return $fields;
417
	}
418
419 1
	/**
420 1
	 * Field certificate.
421
	 *
422 1
	 * @param array $field Field.
423 1
	 */
424
	public function field_certificate( $field ) {
425
		if ( ! \array_key_exists( 'meta_key', $field ) ) {
426
			return;
427
		}
428
429
		$certificate = get_post_meta( get_the_ID(), $field['meta_key'], true );
0 ignored issues
show
Bug introduced by
It seems like get_the_ID() can also be of type false; however, parameter $post_id of get_post_meta() does only seem to accept integer, 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

429
		$certificate = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), $field['meta_key'], true );
Loading history...
430
431
		if ( ! empty( $certificate ) ) {
432
			$fingerprint = Security::get_sha_fingerprint( $certificate );
433
			$fingerprint = str_split( $fingerprint, 2 );
434
			$fingerprint = implode( ':', $fingerprint );
435
436
			echo '<dl>';
437
438
			echo '<dt>', esc_html__( 'SHA Fingerprint', 'pronamic_ideal' ), '</dt>';
439
			echo '<dd>', esc_html( $fingerprint ), '</dd>';
440
441
			$info = openssl_x509_parse( $certificate );
442
443
			if ( $info ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $info of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
444
				$date_format = __( 'M j, Y @ G:i', 'pronamic_ideal' );
445
446
				if ( isset( $info['validFrom_time_t'] ) ) {
447
					echo '<dt>', esc_html__( 'Valid From', 'pronamic_ideal' ), '</dt>';
448
					echo '<dd>', esc_html( date_i18n( $date_format, $info['validFrom_time_t'] ) ), '</dd>';
449
				}
450
451
				if ( isset( $info['validTo_time_t'] ) ) {
452
					echo '<dt>', esc_html__( 'Valid To', 'pronamic_ideal' ), '</dt>';
453
					echo '<dd>', esc_html( date_i18n( $date_format, $info['validTo_time_t'] ) ), '</dd>';
454
				}
455
			}
456
457
			echo '</dl>';
458
		} elseif ( false !== \strpos( $field['meta_key'], 'apple_pay' ) ) {
459
			printf(
460
				'<p class="pronamic-pay-description description">%s</p><p>&nbsp;</p>',
461
				esc_html__( 'Upload an Apple Pay Merchant Identity certificate, which can be exported from Keychain Access on Mac as a PKCS#12 (*.p12) file.', 'pronamic_ideal' )
462
			);
463
		}
464
465
		?>
466
		<p>
467
			<?php
468
469
			if ( ! empty( $certificate ) ) {
470
				submit_button(
471
					__( 'Download', 'pronamic_ideal' ),
472
					'secondary',
473
					'download' . $field['meta_key'],
474
					false
475
				);
476
477
				echo ' ';
478
			}
479
480
			printf(
481
				'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>',
482
				esc_html__( 'Upload', 'pronamic_ideal' ),
483
				$field['meta_key'] . '_file'
484
			);
485
486
			?>
487
		</p>
488
		<?php
489
	}
490
491
	/**
492
	 * Field private key.
493
	 *
494
	 * @param array $field Field.
495
	 */
496
	public function field_private_key( $field ) {
497
		if ( ! \array_key_exists( 'meta_key', $field ) ) {
498
			return;
499
		}
500
501
		$private_key = get_post_meta( get_the_ID(), $field['meta_key'], true );
0 ignored issues
show
Bug introduced by
It seems like get_the_ID() can also be of type false; however, parameter $post_id of get_post_meta() does only seem to accept integer, 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

501
		$private_key = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), $field['meta_key'], true );
Loading history...
502
503
		?>
504
        <p>
505
			<?php
506
507
			if ( ! empty( $private_key ) ) {
508
				submit_button(
509
					__( 'Download', 'pronamic_ideal' ),
510
					'secondary',
511
					'download' . $field['meta_key'],
512
					false
513
				);
514
515
				echo ' ';
516
			}
517
518
			if ( empty( $private_key ) && false !== \strpos( $field['meta_key'], 'apple_pay' ) ) {
519
			    printf(
520
				    '<p class="pronamic-pay-description description">%s</p><p>&nbsp;</p>',
521
				    esc_html__( 'Leave empty to auto fill when uploading an Apple Pay Merchant Identity PKCS#12 certificate file.', 'pronamic_ideal' )
522
			    );
523
			}
524
525
			printf(
526
				'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>',
527
				esc_html__( 'Upload', 'pronamic_ideal' ),
528
				$field['meta_key'] . '_file'
529
			);
530
531
			?>
532
        </p>
533
		<?php
534
	}
535
536
	/**
537
	 * Download certificate or key in Privacy Enhanced Mail (PEM) format.
538
	 */
539
	public function maybe_download_certificate_or_key() {
540
		// Certificate fields and download filename.
541
		$fields = array(
542
			'_pronamic_gateway_adyen_apple_pay_merchant_id_certificate' => 'apple-pay-merchant-identity-certificate-%s.pem',
543
			'_pronamic_gateway_adyen_apple_pay_merchant_id_private_key' => 'apple-pay-merchant-identity-private-key-%s.pem',
544
		);
545
546
		// Check download actions.
547
		$is_download_action = false;
548
549
		foreach ( $fields as $meta_key => $filename ) {
550
			if ( \filter_has_var( \INPUT_POST, 'download' . $meta_key ) ) {
551
				$is_download_action = true;
552
553
				break;
554
			}
555
		}
556
557
		// No valid download action found.
558
		if ( false === $is_download_action ) {
559
			return;
560
		}
561
562
		$post_id = filter_input( \INPUT_POST, 'post_ID', \FILTER_SANITIZE_STRING );
563
564
		$filename = sprintf( $filename, $post_id );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $filename seems to be defined by a foreach iteration on line 549. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
565
566
		header( 'Content-Description: File Transfer' );
567
		header( 'Content-Disposition: attachment; filename=' . $filename );
568
		header( 'Content-Type: application/x-pem-file; charset=' . get_option( 'blog_charset' ), true );
0 ignored issues
show
Bug introduced by
Are you sure get_option('blog_charset') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

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

568
		header( 'Content-Type: application/x-pem-file; charset=' . /** @scrutinizer ignore-type */ get_option( 'blog_charset' ), true );
Loading history...
569
570
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
571
		echo get_post_meta( $post_id, $meta_key, true );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $meta_key seems to be defined by a foreach iteration on line 549. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
Bug introduced by
Are you sure get_post_meta($post_id, $meta_key, true) of type false|mixed|string can be used in echo? ( Ignorable by Annotation )

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

571
		echo /** @scrutinizer ignore-type */ get_post_meta( $post_id, $meta_key, true );
Loading history...
572
573
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
574
	}
575
576
	/**
577
	 * Save post.
578
	 *
579
	 * @param int $post_id Post ID.
580
	 */
581
	public function save_post( $post_id ) {
582
		// Files.
583
		$files = array(
584
			'_pronamic_gateway_adyen_apple_pay_merchant_id_certificate_file' => '_pronamic_gateway_adyen_apple_pay_merchant_id_certificate',
585
			'_pronamic_gateway_adyen_apple_pay_merchant_id_private_key_file' => '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key',
586
		);
587
588
		foreach ( $files as $name => $meta_key ) {
589
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
590
			if ( isset( $_FILES[ $name ] ) && \UPLOAD_ERR_OK === $_FILES[ $name ]['error'] ) {
591
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
592
				$value = file_get_contents( $_FILES[ $name ]['tmp_name'] );
593
594
				if ( '_pronamic_gateway_adyen_apple_pay_merchant_id_certificate' === $meta_key ) {
595
					$apple_pay_merchant_id_pkcs12 = $value;
596
				}
597
598
				update_post_meta( $post_id, $meta_key, $value );
599
			}
600
		}
601
602
		// Update Apple Pay Merchant Identity certificate and private key from uploaded PKCS#12 file.
603
		if ( isset( $apple_pay_merchant_id_pkcs12 ) ) {
604
			// Try to read file without using password.
605
			$pkcs12_read = \openssl_pkcs12_read( $apple_pay_merchant_id_pkcs12, $certs, '' );
606
607
			$password = \get_post_meta( $post_id, '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key_password', true );
608
609
			// Try to read file with private key password.
610
			if ( false === $pkcs12_read ) {
611
				$pkcs12_read = \openssl_pkcs12_read( $apple_pay_merchant_id_pkcs12, $certs, $password );
0 ignored issues
show
Bug introduced by
It seems like $password can also be of type false; however, parameter $pass of openssl_pkcs12_read() does only seem to accept string, 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

611
				$pkcs12_read = \openssl_pkcs12_read( $apple_pay_merchant_id_pkcs12, $certs, /** @scrutinizer ignore-type */ $password );
Loading history...
612
			}
613
614
			if ( true === $pkcs12_read ) {
615
				if ( isset( $certs['cert'] ) ) {
616
					\update_post_meta( $post_id, '_pronamic_gateway_adyen_apple_pay_merchant_id_certificate', $certs['cert'] );
617
				}
618
619
				if ( isset( $certs['pkey'] ) ) {
620
					$private_key = $certs['pkey'];
621
622
					$cipher = null;
623
624
					// Try to export the private key encrypted.
625
					if ( defined( 'OPENSSL_CIPHER_AES_128_CBC' ) ) {
626
						$cipher = \OPENSSL_CIPHER_AES_128_CBC;
627
					} elseif ( defined( 'OPENSSL_CIPHER_3DES' ) ) {
628
						$cipher = \OPENSSL_CIPHER_3DES;
629
					}
630
631
					if ( null !== $cipher && '' !== $password ) {
632
						$args = array(
633
							'digest_alg'             => 'SHA256',
634
							'private_key_bits'       => 2048,
635
							'private_key_type'       => \OPENSSL_KEYTYPE_RSA,
636
							'encrypt_key'            => true,
637
							'encrypt_key_cipher'     => $cipher,
638
							'subjectKeyIdentifier'   => 'hash',
639
							'authorityKeyIdentifier' => 'keyid:always,issuer:always',
640
							'basicConstraints'       => 'CA:true',
641
						);
642
643
						\openssl_pkey_export( $certs['pkey'], $private_key, $password, $args );
0 ignored issues
show
Bug introduced by
It seems like $password can also be of type false; however, parameter $passphrase of openssl_pkey_export() does only seem to accept string, 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

643
						\openssl_pkey_export( $certs['pkey'], $private_key, /** @scrutinizer ignore-type */ $password, $args );
Loading history...
644
					}
645
646
					\update_post_meta( $post_id, '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key', $private_key );
647
				}
648
			}
649
		}
650
	}
651
652
	/**
653
	 * Get configuration by post ID.
654
	 *
655
	 * @param int $post_id Post ID.
656
	 * @return Config
657
	 */
658
	public function get_config( $post_id ) {
659
		$config = new Config();
660
661
		$config->mode                                       = $this->get_meta( $post_id, 'mode' );
662
		$config->api_key                                    = $this->get_meta( $post_id, 'adyen_api_key' );
663
		$config->api_live_url_prefix                        = $this->get_meta( $post_id, 'adyen_api_live_url_prefix' );
664
		$config->merchant_account                           = $this->get_meta( $post_id, 'adyen_merchant_account' );
665
		$config->origin_key                                 = $this->get_meta( $post_id, 'adyen_origin_key' );
666
		$config->apple_pay_merchant_id                      = $this->get_meta( $post_id, 'adyen_apple_pay_merchant_id' );
667
		$config->apple_pay_merchant_id_certificate          = $this->get_meta( $post_id, 'adyen_apple_pay_merchant_id_certificate' );
668
		$config->apple_pay_merchant_id_private_key          = $this->get_meta( $post_id, 'adyen_apple_pay_merchant_id_private_key' );
669
		$config->apple_pay_merchant_id_private_key_password = $this->get_meta( $post_id, 'adyen_apple_pay_merchant_id_private_key_password' );
670
		$config->google_pay_merchant_identifier             = $this->get_meta( $post_id, 'adyen_google_pay_merchant_identifier' );
671
672
		return $config;
673
	}
674
675
	/**
676
	 * Get gateway.
677
	 *
678
	 * @param int $post_id Post ID.
679
	 * @return AbstractGateway
680
	 */
681
	public function get_gateway( $post_id ) {
682
		$config = $this->get_config( $post_id );
683
684
		if ( empty( $config->origin_key ) ) {
685
			return new WebSdkGateway( $config );
686
		}
687
688
		return new DropInGateway( $config );
689
	}
690
}
691