Failed Conditions
Push — develop ( 2b83af...4ba08e )
by Remco
04:31
created

src/Integration.php (16 issues)

1
<?php
2
3
namespace Pronamic\WordPress\Pay\Gateways\IDealAdvancedV3;
4
5
use Pronamic\WordPress\Pay\Gateways\IDeal\AbstractIntegration;
6
7
/**
8
 * Title: iDEAL Advanced v3 integration
9
 * Description:
10
 * Copyright: 2005-2019 Pronamic
11
 * Company: Pronamic
12
 *
13
 * @author  Remco Tolsma
14
 * @version 2.0.0
15
 * @since   2.0.0
16
 */
17
class Integration extends AbstractIntegration {
18
	/**
19
	 * Settings constructor.
20
	 */
21
	public function __construct( $args = array() ) {
22
		$args = wp_parse_args( $args, array(
23
			'id'               => 'ideal-advanced-v3',
24
			'name'             => 'iDEAL Advanced v3',
25
			'url'              => __( 'https://www.ideal.nl/en/', 'pronamic_ideal' ),
26
			'product_url'      => __( 'https://www.ideal.nl/en/', 'pronamic_ideal' ),
27
			'dashboard_url'    => null,
28
			'provider'         => null,
29
			'aquirer_url'      => null,
30
			'aquirer_test_url' => null,
31
		) );
32
33
		$this->id            = $args['id'];
34
		$this->name          = $args['name'];
35
		$this->url           = $args['url'];
36
		$this->product_url   = $args['product_url'];
37
		$this->dashboard_url = $args['dashboard_url'];
38
		$this->provider      = $args['provider'];
39
40
		$this->aquirer_url      = $args['aquirer_url'];
0 ignored issues
show
Bug Best Practice introduced by
The property aquirer_url does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
41
		$this->aquirer_test_url = $args['aquirer_test_url'];
0 ignored issues
show
Bug Best Practice introduced by
The property aquirer_test_url does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
42
43
		// Supported features.
44
		$this->supports = array(
0 ignored issues
show
Bug Best Practice introduced by
The property supports does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
45
			'payment_status_request',
46
		);
47
48
		// Actions.
49
		add_action( 'current_screen', array( $this, 'maybe_download_private_certificate' ) );
50
		add_action( 'current_screen', array( $this, 'maybe_download_private_key' ) );
51
	}
52
53
	public function get_settings_fields() {
54
		$fields = parent::get_settings_fields();
0 ignored issues
show
The method get_settings_fields() does not exist on Pronamic\WordPress\Pay\G...eal\AbstractIntegration. Did you maybe mean get_settings()? ( Ignorable by Annotation )

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

54
		/** @scrutinizer ignore-call */ 
55
  $fields = parent::get_settings_fields();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
55
56
		/*
57
		 * Private Key and Certificate
58
		 */
59
60
		// Private key and certificate information.
61
		$fields[] = array(
62
			'section'  => 'general',
63
			'title'    => __( 'Private key and certificate', 'pronamic_ideal' ),
64
			'type'     => 'description',
65
			'callback' => array( $this, 'field_security' ),
66
		);
67
68
		// Organization.
69
		$fields[] = array(
70
			'section'  => 'general',
71
			'filter'   => FILTER_SANITIZE_STRING,
72
			'group'    => 'pk-cert',
73
			'meta_key' => '_pronamic_gateway_organization',
74
			'title'    => __( 'Organization', 'pronamic_ideal' ),
75
			'type'     => 'text',
76
			'tooltip'  => __( 'Organization name, e.g. Pronamic', 'pronamic_ideal' ),
77
		);
78
79
		// Organization Unit.
80
		$fields[] = array(
81
			'section'  => 'general',
82
			'filter'   => FILTER_SANITIZE_STRING,
83
			'group'    => 'pk-cert',
84
			'meta_key' => '_pronamic_gateway_organization_unit',
85
			'title'    => __( 'Organization Unit', 'pronamic_ideal' ),
86
			'type'     => 'text',
87
			'tooltip'  => __( 'Organization unit, e.g. Administration', 'pronamic_ideal' ),
88
		);
89
90
		// Locality.
91
		$fields[] = array(
92
			'section'  => 'general',
93
			'filter'   => FILTER_SANITIZE_STRING,
94
			'group'    => 'pk-cert',
95
			'meta_key' => '_pronamic_gateway_locality',
96
			'title'    => __( 'City', 'pronamic_ideal' ),
97
			'type'     => 'text',
98
			'tooltip'  => __( 'City, e.g. Amsterdam', 'pronamic_ideal' ),
99
		);
100
101
		// State or Province.
102
		$fields[] = array(
103
			'section'  => 'general',
104
			'filter'   => FILTER_SANITIZE_STRING,
105
			'group'    => 'pk-cert',
106
			'meta_key' => '_pronamic_gateway_state_or_province',
107
			'title'    => __( 'State / province', 'pronamic_ideal' ),
108
			'type'     => 'text',
109
			'tooltip'  => __( 'State or province, e.g. Friesland', 'pronamic_ideal' ),
110
		);
111
112
		// Country.
113
		$locale = explode( '_', get_locale() );
114
115
		$locale = array_pop( $locale );
116
117
		$fields[] = array(
118
			'section'     => 'general',
119
			'filter'      => FILTER_SANITIZE_STRING,
120
			'group'       => 'pk-cert',
121
			'meta_key'    => '_pronamic_gateway_country',
122
			'title'       => __( 'Country', 'pronamic_ideal' ),
123
			'type'        => 'text',
124
			'tooltip'     => sprintf(
125
				'%s %s (ISO-3166-1 alpha-2)',
126
				__( '2 letter country code, e.g.', 'pronamic_ideal' ),
127
				strtoupper( $locale )
128
			),
129
			'size'        => 2,
130
			'description' => sprintf(
131
				'%s %s',
132
				__( '2 letter country code, e.g.', 'pronamic_ideal' ),
133
				strtoupper( $locale )
134
			),
135
		);
136
137
		// Email Address.
138
		$fields[] = array(
139
			'section'  => 'general',
140
			'filter'   => FILTER_SANITIZE_STRING,
141
			'group'    => 'pk-cert',
142
			'meta_key' => '_pronamic_gateway_email',
143
			'title'    => __( 'E-mail address', 'pronamic_ideal' ),
144
			'tooltip'  => sprintf(
145
				/* translators: %s: admin email */
146
				__( 'E-mail address, e.g. %s', 'pronamic_ideal' ),
147
				get_option( 'admin_email' )
0 ignored issues
show
It seems like get_option('admin_email') can also be of type false; however, parameter $args of sprintf() 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

147
				/** @scrutinizer ignore-type */ get_option( 'admin_email' )
Loading history...
148
			),
149
			'type'     => 'text',
150
		);
151
152
		// Number Days Valid.
153
		$fields[] = array(
154
			'section'  => 'general',
155
			'filter'   => FILTER_SANITIZE_NUMBER_INT,
156
			'group'    => 'pk-cert',
157
			'meta_key' => '_pronamic_gateway_number_days_valid',
158
			'title'    => __( 'Number Days Valid', 'pronamic_ideal' ),
159
			'type'     => 'text',
160
			'default'  => 1825,
161
			'tooltip'  => __( 'Number of days the generated certificate will be valid for, e.g. 1825 days for the maximum duration of 5 years.', 'pronamic_ideal' ),
162
		);
163
164
		// Private Key Password.
165
		$fields[] = array(
166
			'section'  => 'general',
167
			'filter'   => FILTER_SANITIZE_STRING,
168
			'group'    => 'pk-cert',
169
			'meta_key' => '_pronamic_gateway_ideal_private_key_password',
170
			'title'    => __( 'Private Key Password', 'pronamic_ideal' ),
171
			'type'     => 'text',
172
			'classes'  => array( 'regular-text', 'code' ),
173
			'default'  => wp_generate_password(),
174
			'tooltip'  => __( 'A random password which will be used for the generation of the private key and certificate.', 'pronamic_ideal' ),
175
		);
176
177
		// Private Key.
178
		$fields[] = array(
179
			'section'  => 'general',
180
			'filter'   => FILTER_SANITIZE_STRING,
181
			'group'    => 'pk-cert',
182
			'meta_key' => '_pronamic_gateway_ideal_private_key',
183
			'title'    => __( 'Private Key', 'pronamic_ideal' ),
184
			'type'     => 'textarea',
185
			'callback' => array( $this, 'field_private_key' ),
186
			'classes'  => array( 'code' ),
187
			'tooltip'  => __( 'The private key is used for secure communication with the payment provider. If left empty, the private key will be generated using the given private key password.', 'pronamic_ideal' ),
188
		);
189
190
		// Private Certificate.
191
		$fields[] = array(
192
			'section'  => 'general',
193
			'filter'   => FILTER_SANITIZE_STRING,
194
			'group'    => 'pk-cert',
195
			'meta_key' => '_pronamic_gateway_ideal_private_certificate',
196
			'title'    => __( 'Private Certificate', 'pronamic_ideal' ),
197
			'type'     => 'textarea',
198
			'callback' => array( $this, 'field_private_certificate' ),
199
			'classes'  => array( 'code' ),
200
			'tooltip'  => __( 'The certificate is used for secure communication with the payment provider. If left empty, the certificate will be generated using the private key and given organization details.', 'pronamic_ideal' ),
201
		);
202
203
		// Return.
204
		return $fields;
205
	}
206
207
	/**
208
	 * Field security
209
	 *
210
	 * @param array $field Field.
211
	 */
212
	public function field_security( $field ) {
213
		$certificate = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
0 ignored issues
show
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

213
		$certificate = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
Loading history...
214
215
		?>
216
		<p>
217
			<?php if ( empty( $certificate ) ) : ?>
218
219
				<span
220
					class="dashicons dashicons-no"></span> <?php esc_html_e( 'The private key and certificate have not yet been configured.', 'pronamic_ideal' ); ?>
221
				<br/>
222
223
				<br/>
224
225
				<?php esc_html_e( 'A private key and certificate are required for communication with the payment provider. Enter the organization details from the iDEAL account below to generate these required files.', 'pronamic_ideal' ); ?>
226
227
			<?php else : ?>
228
229
				<span
230
					class="dashicons dashicons-yes"></span> <?php esc_html_e( 'A private key and certificate have been configured. The certificate must be uploaded to the payment provider dashboard to complete configuration.', 'pronamic_ideal' ); ?>
231
				<br/>
232
233
				<br/>
234
235
				<?php
236
237
				submit_button(
238
					__( 'Download certificate', 'pronamic_ideal' ),
239
					'secondary',
240
					'download_private_certificate',
241
					false
242
				);
243
244
				?>
245
246
				<a class="pronamic-pay-btn-link" href="#" id="pk-cert-fields-toggle"><?php esc_html_e( 'Show details…', 'pronamic_ideal' ); ?></a>
247
248
			<?php endif; ?>
249
		</p>
250
		<?php
251
	}
252
253
	/**
254
	 * Field private key.
255
	 *
256
	 * @param array $field Field.
257
	 */
258
	public function field_private_key( $field ) {
259
		$private_key          = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key', true );
0 ignored issues
show
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

259
		$private_key          = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_key', true );
Loading history...
260
		$private_key_password = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key_password', true );
261
		$number_days_valid    = get_post_meta( get_the_ID(), '_pronamic_gateway_number_days_valid', true );
262
263
		$filename = __( 'ideal.key', 'pronamic_ideal' );
264
265
		if ( ! empty( $private_key_password ) && ! empty( $number_days_valid ) ) {
266
			$command = sprintf(
267
				'openssl genrsa -aes128 -out %s -passout pass:%s 2048',
268
				escapeshellarg( $filename ),
269
				escapeshellarg( $private_key_password )
270
			);
271
272
			?>
273
274
			<p><?php esc_html_e( 'OpenSSL command', 'pronamic_ideal' ); ?></p>
275
			<input id="pronamic_ideal_openssl_command_key" name="pronamic_ideal_openssl_command_key" value="<?php echo esc_attr( $command ); ?>" type="text" class="large-text code" readonly="readonly"/>
276
277
			<?php
278
		} else {
279
			printf(
280
				'<p class="pronamic-pay-description description">%s</p>',
281
				esc_html__( 'Leave empty and save the configuration to generate the private key or view the OpenSSL command.', 'pronamic_ideal' )
282
			);
283
		}
284
285
		?>
286
		<p>
287
			<?php
288
289
			if ( ! empty( $private_key ) ) {
290
				submit_button(
291
					__( 'Download', 'pronamic_ideal' ),
292
					'secondary',
293
					'download_private_key',
294
					false
295
				);
296
297
				echo ' ';
298
			}
299
300
			printf(
301
				'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>',
302
				esc_html__( 'Upload', 'pronamic_ideal' ),
303
				'_pronamic_gateway_ideal_private_key_file'
304
			);
305
306
			?>
307
		</p>
308
		<?php
309
	}
310
311
	/**
312
	 * Field private certificate.
313
	 *
314
	 * @param array $field Field.
315
	 */
316
	public function field_private_certificate( $field ) {
317
		$certificate = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
0 ignored issues
show
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

317
		$certificate = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
Loading history...
318
319
		$private_key_password = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key_password', true );
320
		$number_days_valid    = get_post_meta( get_the_ID(), '_pronamic_gateway_number_days_valid', true );
321
322
		$filename_key = __( 'ideal.key', 'pronamic_ideal' );
323
		$filename_cer = __( 'ideal.cer', 'pronamic_ideal' );
324
325
		// @link http://www.openssl.org/docs/apps/req.html
326
		$subj_args = array(
327
			'C'            => get_post_meta( get_the_ID(), '_pronamic_gateway_country', true ),
328
			'ST'           => get_post_meta( get_the_ID(), '_pronamic_gateway_state_or_province', true ),
329
			'L'            => get_post_meta( get_the_ID(), '_pronamic_gateway_locality', true ),
330
			'O'            => get_post_meta( get_the_ID(), '_pronamic_gateway_organization', true ),
331
			'OU'           => get_post_meta( get_the_ID(), '_pronamic_gateway_organization_unit', true ),
332
			'CN'           => get_post_meta( get_the_ID(), '_pronamic_gateway_organization', true ),
333
			'emailAddress' => get_post_meta( get_the_ID(), '_pronamic_gateway_email', true ),
334
		);
335
336
		$subj_args = array_filter( $subj_args );
337
338
		$subj = '';
339
		foreach ( $subj_args as $type => $value ) {
340
			$subj .= '/' . $type . '=' . addslashes( $value );
341
		}
342
343
		if ( ! empty( $subj ) ) {
344
			$command = trim(
345
				sprintf(
346
					'openssl req -x509 -sha256 -new -key %s -passin pass:%s -days %s -out %s %s',
347
					escapeshellarg( $filename_key ),
348
					escapeshellarg( $private_key_password ),
0 ignored issues
show
It seems like $private_key_password can also be of type false; however, parameter $arg of escapeshellarg() 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

348
					escapeshellarg( /** @scrutinizer ignore-type */ $private_key_password ),
Loading history...
349
					escapeshellarg( $number_days_valid ),
350
					escapeshellarg( $filename_cer ),
351
					empty( $subj ) ? '' : sprintf( '-subj %s', escapeshellarg( $subj ) )
352
				)
353
			);
354
355
			?>
356
357
			<p><?php esc_html_e( 'OpenSSL command', 'pronamic_ideal' ); ?></p>
358
			<input id="pronamic_ideal_openssl_command_certificate" name="pronamic_ideal_openssl_command_certificate" value="<?php echo esc_attr( $command ); ?>" type="text" class="large-text code" readonly="readonly"/>
359
360
			<?php
361
		} else {
362
			printf(
363
				'<p class="pronamic-pay-description description">%s</p>',
364
				esc_html__( 'Leave empty and save the configuration to generate the certificate or view the OpenSSL command.', 'pronamic_ideal' )
365
			);
366
		}
367
368
		if ( ! empty( $certificate ) ) {
369
			$fingerprint = Security::get_sha_fingerprint( $certificate );
370
			$fingerprint = str_split( $fingerprint, 2 );
371
			$fingerprint = implode( ':', $fingerprint );
372
373
			echo '<dl>';
374
375
			echo '<dt>', esc_html__( 'SHA Fingerprint', 'pronamic_ideal' ), '</dt>';
376
			echo '<dd>', esc_html( $fingerprint ), '</dd>';
377
378
			$info = openssl_x509_parse( $certificate );
379
380
			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...
381
				$date_format = __( 'M j, Y @ G:i', 'pronamic_ideal' );
382
383
				if ( isset( $info['validFrom_time_t'] ) ) {
384
					echo '<dt>', esc_html__( 'Valid From', 'pronamic_ideal' ), '</dt>';
385
					echo '<dd>', esc_html( date_i18n( $date_format, $info['validFrom_time_t'] ) ), '</dd>';
386
				}
387
388
				if ( isset( $info['validTo_time_t'] ) ) {
389
					echo '<dt>', esc_html__( 'Valid To', 'pronamic_ideal' ), '</dt>';
390
					echo '<dd>', esc_html( date_i18n( $date_format, $info['validTo_time_t'] ) ), '</dd>';
391
				}
392
			}
393
394
			echo '</dl>';
395
		}
396
397
		?>
398
		<p>
399
			<?php
400
401
			if ( ! empty( $certificate ) ) {
402
				submit_button(
403
					__( 'Download', 'pronamic_ideal' ),
404
					'secondary',
405
					'download_private_certificate',
406
					false
407
				);
408
409
				echo ' ';
410
			}
411
412
			printf(
413
				'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>',
414
				esc_html__( 'Upload', 'pronamic_ideal' ),
415
				'_pronamic_gateway_ideal_private_certificate_file'
416
			);
417
418
			?>
419
		</p>
420
		<?php
421
	}
422
423
	/**
424
	 * Download private certificate
425
	 */
426
	public function maybe_download_private_certificate() {
427
		if ( filter_has_var( INPUT_POST, 'download_private_certificate' ) ) {
428
			$post_id = filter_input( INPUT_POST, 'post_ID', FILTER_SANITIZE_STRING );
429
430
			$filename = sprintf( 'ideal-private-certificate-%s.cer', $post_id );
431
432
			header( 'Content-Description: File Transfer' );
433
			header( 'Content-Disposition: attachment; filename=' . $filename );
434
			header( 'Content-Type: application/x-x509-ca-cert; charset=' . get_option( 'blog_charset' ), true );
0 ignored issues
show
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

434
			header( 'Content-Type: application/x-x509-ca-cert; charset=' . /** @scrutinizer ignore-type */ get_option( 'blog_charset' ), true );
Loading history...
435
436
			echo get_post_meta( $post_id, '_pronamic_gateway_ideal_private_certificate', true ); // xss ok.
0 ignored issues
show
Are you sure get_post_meta($post_id, ...ate_certificate', 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

436
			echo /** @scrutinizer ignore-type */ get_post_meta( $post_id, '_pronamic_gateway_ideal_private_certificate', true ); // xss ok.
Loading history...
437
438
			exit;
439
		}
440
	}
441
442
	/**
443
	 * Download private key
444
	 */
445
	public function maybe_download_private_key() {
446
		if ( filter_has_var( INPUT_POST, 'download_private_key' ) ) {
447
			$post_id = filter_input( INPUT_POST, 'post_ID', FILTER_SANITIZE_STRING );
448
449
			$filename = sprintf( 'ideal-private-key-%s.key', $post_id );
450
451
			header( 'Content-Description: File Transfer' );
452
			header( 'Content-Disposition: attachment; filename=' . $filename );
453
			header( 'Content-Type: application/pgp-keys; charset=' . get_option( 'blog_charset' ), true );
0 ignored issues
show
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

453
			header( 'Content-Type: application/pgp-keys; charset=' . /** @scrutinizer ignore-type */ get_option( 'blog_charset' ), true );
Loading history...
454
455
			echo get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key', true ); // xss ok.
0 ignored issues
show
Are you sure get_post_meta($post_id, ...eal_private_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

455
			echo /** @scrutinizer ignore-type */ get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key', true ); // xss ok.
Loading history...
456
457
			exit;
458
		}
459
	}
460
461
	/**
462
	 * Save post.
463
	 *
464
	 * @param array $data Data.
465
	 */
466
	public function save_post( $data ) {
467
		// Files.
468
		$files = array(
469
			'_pronamic_gateway_ideal_private_key_file' => '_pronamic_gateway_ideal_private_key',
470
			'_pronamic_gateway_ideal_private_certificate_file' => '_pronamic_gateway_ideal_private_certificate',
471
		);
472
473
		foreach ( $files as $name => $meta_key ) {
474
			if ( isset( $_FILES[ $name ] ) && UPLOAD_ERR_OK === $_FILES[ $name ]['error'] ) { // WPCS: input var okay.
475
				$value = file_get_contents( $_FILES[ $name ]['tmp_name'] ); // WPCS: input var okay. // WPCS: sanitization ok.
476
477
				$data[ $meta_key ] = $value;
478
			}
479
		}
480
481
		// Generate private key and certificate.
482
		if ( empty( $data['_pronamic_gateway_ideal_private_key_password'] ) ) {
483
			// Without private key password we can't create private key and certifiate.
484
			return $data;
485
		}
486
487
		if ( ! in_array( 'aes-128-cbc', openssl_get_cipher_methods(), true ) ) {
488
			// Without AES-128-CBC ciphter method we can't create private key and certificate.
489
			return $data;
490
		}
491
492
		// Private key.
493
		$pkey = openssl_pkey_get_private( $data['_pronamic_gateway_ideal_private_key'], $data['_pronamic_gateway_ideal_private_key_password'] );
494
495
		if ( false === $pkey ) {
496
			// If we can't open the private key we will create a new private key and certificate.
497
			if ( defined( 'OPENSSL_CIPHER_AES_128_CBC' ) ) {
498
				$cipher = OPENSSL_CIPHER_AES_128_CBC;
499
			} elseif ( defined( 'OPENSSL_CIPHER_3DES' ) ) {
500
				// @link https://www.pronamic.nl/wp-content/uploads/2011/12/iDEAL_Advanced_PHP_EN_V2.2.pdf
501
				$cipher = OPENSSL_CIPHER_3DES;
502
			} else {
503
				// Unable to create private key without cipher.
504
				return $data;
505
			}
506
507
			$args = array(
508
				'digest_alg'             => 'SHA256',
509
				'private_key_bits'       => 2048,
510
				'private_key_type'       => OPENSSL_KEYTYPE_RSA,
511
				'encrypt_key'            => true,
512
				'encrypt_key_cipher'     => $cipher,
513
				'subjectKeyIdentifier'   => 'hash',
514
				'authorityKeyIdentifier' => 'keyid:always,issuer:always',
515
				'basicConstraints'       => 'CA:true',
516
			);
517
518
			$pkey = openssl_pkey_new( $args );
519
520
			if ( false === $pkey ) {
521
				return $data;
522
			}
523
524
			// Export key.
525
			$result = openssl_pkey_export( $pkey, $private_key, $data['_pronamic_gateway_ideal_private_key_password'], $args );
526
527
			if ( false === $result ) {
528
				return $data;
529
			}
530
531
			$data['_pronamic_gateway_ideal_private_key'] = $private_key;
532
			// Delete private certificate since this is no longer valid.
533
			$data['_pronamic_gateway_ideal_private_certificate'] = null;
534
		}
535
536
		// Certificate.
537
		if ( empty( $data['_pronamic_gateway_ideal_private_certificate'] ) ) {
538
			$required_keys = array(
539
				'countryName',
540
				'stateOrProvinceName',
541
				'localityName',
542
				'organizationName',
543
				'commonName',
544
				'emailAddress',
545
			);
546
547
			$distinguished_name = array(
548
				'countryName'            => $data['_pronamic_gateway_country'],
549
				'stateOrProvinceName'    => $data['_pronamic_gateway_state_or_province'],
550
				'localityName'           => $data['_pronamic_gateway_locality'],
551
				'organizationName'       => $data['_pronamic_gateway_organization'],
552
				'organizationalUnitName' => $data['_pronamic_gateway_organization_unit'],
553
				'commonName'             => $data['_pronamic_gateway_organization'],
554
				'emailAddress'           => $data['_pronamic_gateway_email'],
555
			);
556
557
			$distinguished_name = array_filter( $distinguished_name );
558
559
			/*
560
			 * Create certificate only if distinguished name contains all required elements
561
			 *
562
			 * @link http://stackoverflow.com/questions/13169588/how-to-check-if-multiple-array-keys-exists
563
			 */
564
			if ( count( array_intersect_key( array_flip( $required_keys ), $distinguished_name ) ) === count( $required_keys ) ) {
565
				$csr = openssl_csr_new( $distinguished_name, $pkey );
566
567
				$cert = openssl_csr_sign( $csr, null, $pkey, $data['_pronamic_gateway_number_days_valid'], $args, time() );
568
569
				openssl_x509_export( $cert, $certificate );
570
571
				$data['_pronamic_gateway_ideal_private_certificate'] = $certificate;
572
			}
573
		}
574
575
		return $data;
576
	}
577
578
	public function get_config( $post_id ) {
579
		$mode = get_post_meta( $post_id, '_pronamic_gateway_mode', true );
580
581
		$config = new Config();
582
583
		$config->payment_server_url = $this->aquirer_url;
0 ignored issues
show
The property payment_server_url does not seem to exist on Pronamic\WordPress\Pay\G...\IDealAdvancedV3\Config.
Loading history...
584
585
		if ( 'test' === $mode && null !== $this->aquirer_test_url ) {
586
			$config->payment_server_url = $this->aquirer_test_url;		
587
		}
588
589
		$config->merchant_id = get_post_meta( $post_id, '_pronamic_gateway_ideal_merchant_id', true );
590
		$config->sub_id      = get_post_meta( $post_id, '_pronamic_gateway_ideal_sub_id', true );
591
		$config->purchase_id = get_post_meta( $post_id, '_pronamic_gateway_ideal_purchase_id', true );
0 ignored issues
show
The property purchase_id does not seem to exist on Pronamic\WordPress\Pay\G...\IDealAdvancedV3\Config.
Loading history...
592
593
		$config->private_key          = get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key', true );
594
		$config->private_key_password = get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key_password', true );
595
		$config->private_certificate  = get_post_meta( $post_id, '_pronamic_gateway_ideal_private_certificate', true );
596
597
		return $config;
598
	}
599
600
	/**
601
	 * Get gateway.
602
	 *
603
	 * @param int $post_id Post ID.
604
	 * @return Gateway
605
	 */
606
	public function get_gateway( $post_id ) {
607
		return new Gateway( $this->get_config( $post_id ) );
608
	}
609
}
610