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.1.2 |
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<string, array<string>> $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
|
|
|
* Setup gateway integration. |
68
|
|
|
* |
69
|
|
|
* @return void |
70
|
|
|
*/ |
71
|
1 |
|
public function setup() { |
72
|
|
|
// Check if dependencies are met and integration is active. |
73
|
1 |
|
if ( ! $this->is_active() ) { |
74
|
|
|
return; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
// Notifications controller. |
78
|
1 |
|
$notifications_controller = new NotificationsController(); |
79
|
|
|
|
80
|
1 |
|
$notifications_controller->setup(); |
81
|
|
|
|
82
|
|
|
// Payments controller. |
83
|
1 |
|
$payments_controller = new PaymentsController(); |
84
|
|
|
|
85
|
1 |
|
$payments_controller->setup(); |
86
|
|
|
|
87
|
|
|
// Payments result controller. |
88
|
1 |
|
$payments_result_controller = new PaymentsResultController(); |
89
|
|
|
|
90
|
1 |
|
$payments_result_controller->setup(); |
91
|
|
|
|
92
|
|
|
// Site Health controller. |
93
|
1 |
|
$site_healht_controller = new SiteHealthController(); |
94
|
|
|
|
95
|
1 |
|
$site_healht_controller->setup(); |
96
|
|
|
|
97
|
|
|
// Settings. |
98
|
1 |
|
add_action( 'init', array( $this, 'init' ) ); |
99
|
1 |
|
add_action( 'admin_init', array( $this, 'admin_init' ), 15 ); |
100
|
|
|
|
101
|
|
|
// Actions. |
102
|
1 |
|
add_action( 'current_screen', array( $this, 'maybe_download_certificate_or_key' ) ); |
103
|
|
|
|
104
|
1 |
|
\add_filter( 'pronamic_gateway_configuration_display_value_' . $this->get_id(), array( $this, 'gateway_configuration_display_value' ), 10, 2 ); |
105
|
1 |
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Initialize. |
109
|
|
|
* |
110
|
|
|
* @return void |
111
|
|
|
*/ |
112
|
1 |
|
public function init() { |
113
|
|
|
/* |
114
|
|
|
* Authentication - User Name |
115
|
|
|
*/ |
116
|
1 |
|
register_setting( |
117
|
1 |
|
'pronamic_pay', |
118
|
1 |
|
'pronamic_pay_adyen_notification_authentication_username', |
119
|
|
|
array( |
120
|
1 |
|
'type' => 'string', |
121
|
|
|
'sanitize_callback' => 'sanitize_text_field', |
122
|
|
|
) |
123
|
|
|
); |
124
|
|
|
|
125
|
|
|
/* |
126
|
|
|
* Authentication - Password |
127
|
|
|
*/ |
128
|
1 |
|
register_setting( |
129
|
1 |
|
'pronamic_pay', |
130
|
1 |
|
'pronamic_pay_adyen_notification_authentication_password', |
131
|
|
|
array( |
132
|
1 |
|
'type' => 'string', |
133
|
|
|
'sanitize_callback' => 'sanitize_text_field', |
134
|
|
|
) |
135
|
|
|
); |
136
|
1 |
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Admin initialize. |
140
|
|
|
* |
141
|
|
|
* @return void |
142
|
|
|
*/ |
143
|
1 |
|
public function admin_init() { |
144
|
1 |
|
add_settings_section( |
145
|
1 |
|
'pronamic_pay_adyen_notification_authentication', |
146
|
|
|
/* translators: Translate 'notification' the same as in the Adyen dashboard. */ |
147
|
1 |
|
_x( 'Adyen Notification Authentication', 'Adyen', 'pronamic_ideal' ), |
148
|
1 |
|
array( $this, 'settings_section_notification_authentication' ), |
149
|
1 |
|
'pronamic_pay' |
150
|
|
|
); |
151
|
|
|
|
152
|
1 |
|
add_settings_field( |
153
|
1 |
|
'pronamic_pay_adyen_notification_authentication_username', |
154
|
1 |
|
__( 'User Name', 'pronamic_ideal' ), |
155
|
1 |
|
array( __CLASS__, 'input_element' ), |
156
|
1 |
|
'pronamic_pay', |
157
|
1 |
|
'pronamic_pay_adyen_notification_authentication', |
158
|
|
|
array( |
159
|
1 |
|
'label_for' => 'pronamic_pay_adyen_notification_authentication_username', |
160
|
|
|
) |
161
|
|
|
); |
162
|
|
|
|
163
|
1 |
|
add_settings_field( |
164
|
1 |
|
'pronamic_pay_adyen_notification_authentication_password', |
165
|
1 |
|
__( 'Password', 'pronamic_ideal' ), |
166
|
1 |
|
array( __CLASS__, 'input_element' ), |
167
|
1 |
|
'pronamic_pay', |
168
|
1 |
|
'pronamic_pay_adyen_notification_authentication', |
169
|
|
|
array( |
170
|
1 |
|
'label_for' => 'pronamic_pay_adyen_notification_authentication_password', |
171
|
|
|
) |
172
|
|
|
); |
173
|
1 |
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Settings section notification authentication. |
177
|
|
|
* |
178
|
|
|
* @return void |
179
|
|
|
*/ |
180
|
1 |
|
public function settings_section_notification_authentication() { |
181
|
1 |
|
printf( |
182
|
1 |
|
'<p>%s</p>', |
183
|
1 |
|
esc_html__( |
184
|
1 |
|
'Set the user name and password below and in the webhook authentication settings in the Adyen dashboard for increased security (recommended).', |
185
|
1 |
|
'pronamic_ideal' |
186
|
|
|
) |
187
|
|
|
); |
188
|
1 |
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* Input text. |
192
|
|
|
* |
193
|
|
|
* @param array<string,string> $args Arguments. |
194
|
|
|
* @return void |
195
|
|
|
*/ |
196
|
1 |
|
public static function input_element( $args ) { |
197
|
1 |
|
$name = $args['label_for']; |
198
|
|
|
|
199
|
1 |
|
$value = get_option( $name ); |
200
|
1 |
|
$value = strval( $value ); |
201
|
|
|
|
202
|
1 |
|
printf( |
203
|
1 |
|
'<input name="%s" id="%s" value="%s" type="text" class="regular-text" />', |
204
|
1 |
|
esc_attr( $name ), |
205
|
1 |
|
esc_attr( $name ), |
206
|
1 |
|
esc_attr( $value ) |
207
|
|
|
); |
208
|
1 |
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* Get settings fields. |
212
|
|
|
* |
213
|
|
|
* @return array<int, array<string, callable|int|string|bool|array<int|string,int|string>>> |
214
|
|
|
*/ |
215
|
1 |
|
public function get_settings_fields() { |
216
|
1 |
|
$fields = array(); |
217
|
|
|
|
218
|
|
|
// Merchant Account. |
219
|
1 |
|
$fields[] = array( |
220
|
1 |
|
'section' => 'general', |
221
|
1 |
|
'filter' => FILTER_SANITIZE_STRING, |
222
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_merchant_account', |
223
|
1 |
|
'title' => _x( 'Merchant Account', 'adyen', 'pronamic_ideal' ), |
224
|
1 |
|
'type' => 'text', |
225
|
|
|
'classes' => array( 'regular-text', 'code' ), |
226
|
1 |
|
'tooltip' => __( 'The merchant account identifier, with which you want to process the transaction.', 'pronamic_ideal' ), |
227
|
|
|
); |
228
|
|
|
|
229
|
|
|
// API Key. |
230
|
1 |
|
$fields[] = array( |
231
|
1 |
|
'section' => 'general', |
232
|
1 |
|
'filter' => FILTER_SANITIZE_STRING, |
233
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_api_key', |
234
|
1 |
|
'title' => _x( 'API Key', 'adyen', 'pronamic_ideal' ), |
235
|
1 |
|
'type' => 'textarea', |
236
|
|
|
'classes' => array( 'code' ), |
237
|
1 |
|
'tooltip' => __( 'API key as mentioned in the payment provider dashboard.', 'pronamic_ideal' ), |
238
|
1 |
|
'description' => sprintf( |
239
|
1 |
|
'<a href="%s" target="_blank">%s</a>', |
240
|
1 |
|
esc_url( 'https://docs.adyen.com/developers/user-management/how-to-get-the-api-key' ), |
241
|
1 |
|
esc_html__( 'Adyen documentation: "How to get the API key".', 'pronamic_ideal' ) |
242
|
|
|
), |
243
|
|
|
); |
244
|
|
|
|
245
|
|
|
// Live API URL prefix. |
246
|
1 |
|
$fields[] = array( |
247
|
1 |
|
'section' => 'general', |
248
|
1 |
|
'filter' => FILTER_SANITIZE_STRING, |
249
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_api_live_url_prefix', |
250
|
1 |
|
'title' => _x( 'API Live URL Prefix', 'adyen', 'pronamic_ideal' ), |
251
|
1 |
|
'type' => 'text', |
252
|
|
|
'classes' => array( 'regular-text', 'code' ), |
253
|
1 |
|
'tooltip' => __( 'The unique prefix for the live API URL, as mentioned at <strong>Account » API URLs</strong> in the Adyen dashboard.', 'pronamic_ideal' ), |
254
|
1 |
|
'description' => sprintf( |
255
|
1 |
|
'<a href="%s" target="_blank">%s</a>', |
256
|
1 |
|
esc_url( 'https://docs.adyen.com/developers/development-resources/live-endpoints#liveurlprefix' ), |
257
|
1 |
|
esc_html__( 'Adyen documentation: "Live URL prefix".', 'pronamic_ideal' ) |
258
|
|
|
), |
259
|
|
|
); |
260
|
|
|
|
261
|
|
|
// Origin Key. |
262
|
1 |
|
$fields[] = array( |
263
|
1 |
|
'section' => 'general', |
264
|
1 |
|
'filter' => FILTER_SANITIZE_STRING, |
265
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_origin_key', |
266
|
1 |
|
'title' => _x( 'Origin Key', 'adyen', 'pronamic_ideal' ), |
267
|
1 |
|
'type' => 'text', |
268
|
|
|
'classes' => array( |
269
|
|
|
'regular-text', |
270
|
|
|
'code', |
271
|
|
|
'pronamic-pay-form-control-lg', |
272
|
|
|
), |
273
|
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' ), |
274
|
1 |
|
'description' => sprintf( |
275
|
1 |
|
'<a href="%s" target="_blank">%s</a>', |
276
|
1 |
|
esc_url( 'https://docs.adyen.com/user-management/how-to-get-an-origin-key' ), |
277
|
1 |
|
esc_html__( 'Adyen documentation: "How to get an origin key".', 'pronamic_ideal' ) |
278
|
|
|
), |
279
|
|
|
); |
280
|
|
|
|
281
|
|
|
// Merchant Order Reference. |
282
|
1 |
|
$fields[] = array( |
283
|
1 |
|
'section' => 'advanced', |
284
|
|
|
'filter' => array( |
285
|
|
|
'filter' => \FILTER_SANITIZE_STRING, |
286
|
|
|
'flags' => \FILTER_FLAG_NO_ENCODE_QUOTES, |
287
|
|
|
), |
288
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_merchant_order_reference', |
289
|
1 |
|
'title' => __( 'Merchant Order Reference', 'pronamic_ideal' ), |
290
|
1 |
|
'type' => 'text', |
291
|
|
|
'classes' => array( 'regular-text', 'code' ), |
292
|
1 |
|
'tooltip' => \sprintf( |
293
|
|
|
/* translators: %s: <code>parameterName</code> */ |
294
|
1 |
|
\__( 'The Adyen %s parameter.', 'pronamic_ideal' ), |
295
|
1 |
|
\sprintf( '<code>%s</code>', 'merchantOrderReference' ) |
296
|
|
|
), |
297
|
1 |
|
'description' => \sprintf( |
298
|
1 |
|
'%s %s<br />%s', |
299
|
1 |
|
\__( 'Available tags:', 'pronamic_ideal' ), |
300
|
1 |
|
\sprintf( |
301
|
1 |
|
'<code>%s</code> <code>%s</code>', |
302
|
1 |
|
'{order_id}', |
303
|
1 |
|
'{payment_id}' |
304
|
|
|
), |
305
|
1 |
|
\sprintf( |
306
|
|
|
/* translators: %s: default code */ |
307
|
1 |
|
\__( 'Default: <code>%s</code>', 'pronamic_ideal' ), |
308
|
1 |
|
'{payment_id}' |
309
|
|
|
) |
310
|
|
|
), |
311
|
|
|
); |
312
|
|
|
|
313
|
|
|
// Apple Pay - Merchant identifier. |
314
|
1 |
|
$fields[] = array( |
315
|
1 |
|
'section' => 'advanced', |
316
|
|
|
'filter' => \FILTER_SANITIZE_STRING, |
317
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_apple_pay_merchant_id', |
318
|
1 |
|
'title' => _x( 'Apple Pay Merchant ID', 'adyen', 'pronamic_ideal' ), |
319
|
1 |
|
'type' => 'text', |
320
|
|
|
'classes' => array( 'regular-text', 'code' ), |
321
|
1 |
|
'tooltip' => __( 'Your Apple Pay Merchant ID. Required for accepting live payments.', 'pronamic_ideal' ), |
322
|
1 |
|
'description' => sprintf( |
323
|
1 |
|
'<a href="%s" target="_blank">%s</a><br /><a href="%s" target="_blank">%s</a>', |
324
|
1 |
|
esc_url( 'https://docs.adyen.com/payment-methods/apple-pay/web-drop-in#before-you-begin' ), |
325
|
1 |
|
esc_html__( 'Adyen documentation: "Apple Pay Drop-in - Before you begin".', 'pronamic_ideal' ), |
326
|
1 |
|
esc_url( 'https://developer.apple.com/documentation/apple_pay_on_the_web/configuring_your_environment' ), |
327
|
1 |
|
esc_html__( 'Apple documentation: "Configuring your environment".', 'pronamic_ideal' ) |
328
|
|
|
), |
329
|
|
|
); |
330
|
|
|
|
331
|
|
|
// Apple Pay - Merchant Identity PKCS#12. |
332
|
1 |
|
$fields[] = array( |
333
|
1 |
|
'section' => 'advanced', |
334
|
|
|
'filter' => \FILTER_SANITIZE_STRING, |
335
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_apple_pay_merchant_id_certificate', |
336
|
1 |
|
'title' => __( 'Apple Pay Merchant Identity Certificate', 'pronamic_ideal' ), |
337
|
1 |
|
'type' => 'textarea', |
338
|
1 |
|
'callback' => array( $this, 'field_certificate' ), |
339
|
|
|
'classes' => array( 'code' ), |
340
|
1 |
|
'tooltip' => __( 'The Apple Pay Merchant Identity certificate required for secure communication with Apple.', 'pronamic_ideal' ), |
341
|
1 |
|
'description' => sprintf( |
342
|
1 |
|
'<a href="%s" target="_blank">%s</a>', |
343
|
1 |
|
esc_url( 'https://docs.adyen.com/payment-methods/apple-pay/enable-apple-pay#create-merchant-identity-certificate' ), |
344
|
1 |
|
esc_html__( 'Adyen documentation: "Enable Apple Pay - Create a merchant identity certificate".', 'pronamic_ideal' ) |
345
|
|
|
), |
346
|
|
|
); |
347
|
|
|
|
348
|
|
|
// Apple Pay - Merchant Identity private key. |
349
|
1 |
|
$fields[] = array( |
350
|
1 |
|
'section' => 'advanced', |
351
|
|
|
'filter' => \FILTER_SANITIZE_STRING, |
352
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key', |
353
|
1 |
|
'title' => __( 'Apple Pay Merchant Identity Private Key', 'pronamic_ideal' ), |
354
|
1 |
|
'type' => 'textarea', |
355
|
1 |
|
'callback' => array( $this, 'field_private_key' ), |
356
|
|
|
'classes' => array( 'code' ), |
357
|
1 |
|
'tooltip' => __( 'The private key of the Apple Pay Merchant Identity certificate for secure communication with Apple.', 'pronamic_ideal' ), |
358
|
|
|
); |
359
|
|
|
|
360
|
|
|
// Apple Pay - Merchant Identity certificate private key password. |
361
|
1 |
|
$fields[] = array( |
362
|
1 |
|
'section' => 'advanced', |
363
|
|
|
'filter' => \FILTER_SANITIZE_STRING, |
364
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key_password', |
365
|
1 |
|
'title' => _x( 'Apple Pay Merchant Identity Private Key Password', 'adyen', 'pronamic_ideal' ), |
366
|
1 |
|
'type' => 'text', |
367
|
|
|
'classes' => array( 'regular-text', 'code' ), |
368
|
1 |
|
'tooltip' => __( 'Your Apple Pay Merchant Identity Certificate private key password.', 'pronamic_ideal' ), |
369
|
|
|
); |
370
|
|
|
|
371
|
|
|
// Google Pay - Merchant identifier. |
372
|
1 |
|
$fields[] = array( |
373
|
1 |
|
'section' => 'advanced', |
374
|
|
|
'filter' => \FILTER_SANITIZE_STRING, |
375
|
1 |
|
'meta_key' => '_pronamic_gateway_adyen_google_pay_merchant_identifier', |
376
|
1 |
|
'title' => _x( 'Google Pay Merchant ID', 'adyen', 'pronamic_ideal' ), |
377
|
1 |
|
'type' => 'text', |
378
|
|
|
'classes' => array( 'regular-text', 'code' ), |
379
|
1 |
|
'tooltip' => __( 'Your Google Merchant ID. Required for accepting live payments.', 'pronamic_ideal' ), |
380
|
1 |
|
'description' => sprintf( |
381
|
1 |
|
'<a href="%s" target="_blank">%s</a><br /><a href="%s" target="_blank">%s</a>', |
382
|
1 |
|
esc_url( 'https://docs.adyen.com/payment-methods/google-pay/web-drop-in#test-and-go-live' ), |
383
|
1 |
|
esc_html__( 'Adyen documentation: "Google Pay Drop-in - Test and go live".', 'pronamic_ideal' ), |
384
|
1 |
|
esc_url( 'https://developers.google.com/pay/api/web/guides/test-and-deploy/deploy-production-environment' ), |
385
|
1 |
|
esc_html__( 'Google documentation: "Deploy production environment".', 'pronamic_ideal' ) |
386
|
|
|
), |
387
|
|
|
); |
388
|
|
|
|
389
|
|
|
// Webhook URL. |
390
|
1 |
|
$fields[] = array( |
391
|
1 |
|
'section' => 'feedback', |
392
|
1 |
|
'title' => __( 'Webhook URL', 'pronamic_ideal' ), |
393
|
1 |
|
'type' => 'text', |
394
|
|
|
'classes' => array( 'large-text', 'code' ), |
395
|
1 |
|
'value' => rest_url( self::REST_ROUTE_NAMESPACE . '/notifications' ), |
396
|
|
|
'readonly' => true, |
397
|
1 |
|
'tooltip' => sprintf( |
398
|
|
|
/* translators: %s: payment provider name */ |
399
|
1 |
|
__( 'Copy the Webhook URL to the %s dashboard to receive automatic transaction status updates.', 'pronamic_ideal' ), |
400
|
1 |
|
__( 'Adyen', 'pronamic_ideal' ) |
401
|
|
|
), |
402
|
|
|
); |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* SSL Version. |
406
|
|
|
* |
407
|
|
|
* @link https://docs.adyen.com/developers/development-resources/notifications/set-up-notifications#step3configurenotificationsinthecustomerarea |
408
|
|
|
* @link https://www.howsmyssl.com/a/check |
409
|
|
|
*/ |
410
|
1 |
|
$fields[] = array( |
411
|
1 |
|
'section' => 'feedback', |
412
|
1 |
|
'title' => __( 'SSL Version', 'pronamic_ideal' ), |
413
|
1 |
|
'type' => 'description', |
414
|
1 |
|
'html' => __( 'Choose the SSL Version of your server on the Adyen Customer Area.', 'pronamic_ideal' ), |
415
|
|
|
); |
416
|
|
|
|
417
|
|
|
/** |
418
|
|
|
* Method. |
419
|
|
|
* |
420
|
|
|
* @link https://docs.adyen.com/developers/development-resources/notifications/set-up-notifications#step3configurenotificationsinthecustomerarea |
421
|
|
|
* @link https://www.howsmyssl.com/a/check |
422
|
|
|
*/ |
423
|
1 |
|
$fields[] = array( |
424
|
1 |
|
'section' => 'feedback', |
425
|
1 |
|
'title' => _x( 'Method', 'adyen notification', 'pronamic_ideal' ), |
426
|
1 |
|
'type' => 'description', |
427
|
1 |
|
'html' => __( 'JSON', 'pronamic_ideal' ), |
428
|
|
|
); |
429
|
|
|
|
430
|
|
|
// Webhook authentication settings. |
431
|
1 |
|
$fields[] = array( |
432
|
1 |
|
'section' => 'feedback', |
433
|
1 |
|
'title' => __( 'Authentication', 'pronamic_ideal' ), |
434
|
1 |
|
'type' => 'description', |
435
|
1 |
|
'html' => \sprintf( |
436
|
|
|
/* translators: %s: Pronamic Pay settings page URL. */ |
437
|
1 |
|
__( 'Go to the <a href="%s">Pronamic Pay settings page</a> for webhook authentication settings.', 'pronamic_ideal' ), |
438
|
1 |
|
\esc_url( |
439
|
1 |
|
\add_query_arg( |
440
|
|
|
array( |
441
|
1 |
|
'page' => 'pronamic_pay_settings', |
442
|
|
|
), |
443
|
1 |
|
\admin_url( 'admin.php' ) |
444
|
|
|
) |
445
|
|
|
) |
446
|
|
|
), |
447
|
|
|
); |
448
|
|
|
|
449
|
|
|
// Return fields. |
450
|
1 |
|
return $fields; |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
/** |
454
|
|
|
* Field certificate. |
455
|
|
|
* |
456
|
|
|
* @param array<string> $field Field. |
457
|
|
|
* @return void |
458
|
|
|
*/ |
459
|
|
|
public function field_certificate( $field ) { |
460
|
|
|
if ( ! \array_key_exists( 'meta_key', $field ) ) { |
461
|
|
|
return; |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
$post_id = \get_the_ID(); |
465
|
|
|
|
466
|
|
|
if ( false === $post_id ) { |
467
|
|
|
return; |
468
|
|
|
} |
469
|
|
|
|
470
|
|
|
$certificate = \get_post_meta( $post_id, $field['meta_key'], true ); |
471
|
|
|
|
472
|
|
|
if ( ! empty( $certificate ) ) { |
473
|
|
|
$fingerprint = Security::get_sha_fingerprint( $certificate ); |
474
|
|
|
|
475
|
|
|
echo '<dl>'; |
476
|
|
|
|
477
|
|
|
if ( null !== $fingerprint ) { |
478
|
|
|
$fingerprint = \str_split( $fingerprint, 2 ); |
479
|
|
|
$fingerprint = \implode( ':', $fingerprint ); |
|
|
|
|
480
|
|
|
|
481
|
|
|
echo '<dt>', \esc_html__( 'SHA Fingerprint', 'pronamic_ideal' ), '</dt>'; |
482
|
|
|
echo '<dd>', \esc_html( $fingerprint ), '</dd>'; |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
$info = \openssl_x509_parse( $certificate ); |
486
|
|
|
|
487
|
|
|
if ( $info ) { |
|
|
|
|
488
|
|
|
$date_format = __( 'M j, Y @ G:i', 'pronamic_ideal' ); |
489
|
|
|
|
490
|
|
|
if ( isset( $info['validFrom_time_t'] ) ) { |
491
|
|
|
echo '<dt>', \esc_html__( 'Valid From', 'pronamic_ideal' ), '</dt>'; |
492
|
|
|
echo '<dd>', \esc_html( \date_i18n( $date_format, $info['validFrom_time_t'] ) ), '</dd>'; |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
if ( isset( $info['validTo_time_t'] ) ) { |
496
|
|
|
echo '<dt>', \esc_html__( 'Valid To', 'pronamic_ideal' ), '</dt>'; |
497
|
|
|
echo '<dd>', \esc_html( \date_i18n( $date_format, $info['validTo_time_t'] ) ), '</dd>'; |
498
|
|
|
} |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
echo '</dl>'; |
502
|
|
|
} elseif ( false !== \strpos( $field['meta_key'], 'apple_pay' ) ) { |
503
|
|
|
\printf( |
504
|
|
|
'<p class="pronamic-pay-description description">%s</p><p> </p>', |
505
|
|
|
\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' ) |
506
|
|
|
); |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
?> |
510
|
|
|
<p> |
511
|
|
|
<?php |
512
|
|
|
|
513
|
|
|
if ( ! empty( $certificate ) ) { |
514
|
|
|
\submit_button( |
515
|
|
|
__( 'Download', 'pronamic_ideal' ), |
516
|
|
|
'secondary', |
517
|
|
|
'download' . $field['meta_key'], |
518
|
|
|
false |
519
|
|
|
); |
520
|
|
|
|
521
|
|
|
echo ' '; |
522
|
|
|
} |
523
|
|
|
|
524
|
|
|
\printf( |
525
|
|
|
'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>', |
526
|
|
|
\esc_html__( 'Upload', 'pronamic_ideal' ), |
527
|
|
|
\esc_attr( $field['meta_key'] . '_file' ) |
528
|
|
|
); |
529
|
|
|
|
530
|
|
|
?> |
531
|
|
|
</p> |
532
|
|
|
<?php |
533
|
|
|
} |
534
|
|
|
|
535
|
|
|
/** |
536
|
|
|
* Field private key. |
537
|
|
|
* |
538
|
|
|
* @param array<string> $field Field. |
539
|
|
|
* @return void |
540
|
|
|
*/ |
541
|
|
|
public function field_private_key( $field ) { |
542
|
|
|
if ( ! \array_key_exists( 'meta_key', $field ) ) { |
543
|
|
|
return; |
544
|
|
|
} |
545
|
|
|
|
546
|
|
|
$post_id = \get_the_ID(); |
547
|
|
|
|
548
|
|
|
if ( false === $post_id ) { |
549
|
|
|
return; |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
$private_key = \get_post_meta( $post_id, $field['meta_key'], true ); |
553
|
|
|
|
554
|
|
|
?> |
555
|
|
|
<p> |
556
|
|
|
<?php |
557
|
|
|
|
558
|
|
|
if ( ! empty( $private_key ) ) { |
559
|
|
|
\submit_button( |
560
|
|
|
__( 'Download', 'pronamic_ideal' ), |
561
|
|
|
'secondary', |
562
|
|
|
'download' . $field['meta_key'], |
563
|
|
|
false |
564
|
|
|
); |
565
|
|
|
|
566
|
|
|
echo ' '; |
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
if ( empty( $private_key ) && false !== \strpos( $field['meta_key'], 'apple_pay' ) ) { |
570
|
|
|
\printf( |
571
|
|
|
'<p class="pronamic-pay-description description">%s</p><p> </p>', |
572
|
|
|
\esc_html__( 'Leave empty to auto fill when uploading an Apple Pay Merchant Identity PKCS#12 certificate file.', 'pronamic_ideal' ) |
573
|
|
|
); |
574
|
|
|
} |
575
|
|
|
|
576
|
|
|
\printf( |
577
|
|
|
'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>', |
578
|
|
|
\esc_html__( 'Upload', 'pronamic_ideal' ), |
579
|
|
|
\esc_attr( $field['meta_key'] . '_file' ) |
580
|
|
|
); |
581
|
|
|
|
582
|
|
|
?> |
583
|
|
|
</p> |
584
|
|
|
<?php |
585
|
|
|
} |
586
|
|
|
|
587
|
|
|
/** |
588
|
|
|
* Download certificate or key in Privacy Enhanced Mail (PEM) format. |
589
|
|
|
* |
590
|
|
|
* @return void |
591
|
|
|
*/ |
592
|
|
|
public function maybe_download_certificate_or_key() { |
593
|
|
|
// Certificate fields and download filename. |
594
|
|
|
$fields = array( |
595
|
|
|
'_pronamic_gateway_adyen_apple_pay_merchant_id_certificate' => 'apple-pay-merchant-identity-certificate-%s.pem', |
596
|
|
|
'_pronamic_gateway_adyen_apple_pay_merchant_id_private_key' => 'apple-pay-merchant-identity-private-key-%s.pem', |
597
|
|
|
); |
598
|
|
|
|
599
|
|
|
// Check download actions. |
600
|
|
|
$is_download_action = false; |
601
|
|
|
|
602
|
|
|
foreach ( $fields as $meta_key => $filename ) { |
603
|
|
|
if ( \filter_has_var( \INPUT_POST, 'download' . $meta_key ) ) { |
604
|
|
|
$is_download_action = true; |
605
|
|
|
|
606
|
|
|
break; |
607
|
|
|
} |
608
|
|
|
} |
609
|
|
|
|
610
|
|
|
// No valid download action found. |
611
|
|
|
if ( false === $is_download_action ) { |
612
|
|
|
return; |
613
|
|
|
} |
614
|
|
|
|
615
|
|
|
$post_id = filter_input( \INPUT_POST, 'post_ID', \FILTER_SANITIZE_STRING ); |
616
|
|
|
|
617
|
|
|
$filename = sprintf( $filename, $post_id ); |
|
|
|
|
618
|
|
|
|
619
|
|
|
header( 'Content-Description: File Transfer' ); |
620
|
|
|
header( 'Content-Disposition: attachment; filename=' . $filename ); |
621
|
|
|
header( 'Content-Type: application/x-pem-file; charset=' . get_option( 'blog_charset' ), true ); |
622
|
|
|
|
623
|
|
|
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
624
|
|
|
echo get_post_meta( $post_id, $meta_key, true ); |
|
|
|
|
625
|
|
|
|
626
|
|
|
exit; |
|
|
|
|
627
|
|
|
} |
628
|
|
|
|
629
|
|
|
/** |
630
|
|
|
* Gateway configuration display value. |
631
|
|
|
* |
632
|
|
|
* @param string $display_value Display value. |
633
|
|
|
* @param int $post_id Gateway configuration post ID. |
634
|
|
|
* @return string |
635
|
|
|
*/ |
636
|
|
|
public function gateway_configuration_display_value( $display_value, $post_id ) { |
637
|
|
|
$config = $this->get_config( $post_id ); |
638
|
|
|
|
639
|
|
|
return $config->get_merchant_account(); |
640
|
|
|
} |
641
|
|
|
|
642
|
|
|
/** |
643
|
|
|
* Save post. |
644
|
|
|
* |
645
|
|
|
* @param int $post_id Post ID. |
646
|
|
|
* @return void |
647
|
|
|
*/ |
648
|
|
|
public function save_post( $post_id ) { |
649
|
|
|
// Files. |
650
|
|
|
$files = array( |
651
|
|
|
'_pronamic_gateway_adyen_apple_pay_merchant_id_certificate_file' => '_pronamic_gateway_adyen_apple_pay_merchant_id_certificate', |
652
|
|
|
'_pronamic_gateway_adyen_apple_pay_merchant_id_private_key_file' => '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key', |
653
|
|
|
); |
654
|
|
|
|
655
|
|
|
foreach ( $files as $name => $meta_key ) { |
656
|
|
|
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated |
657
|
|
|
if ( isset( $_FILES[ $name ] ) && \UPLOAD_ERR_OK === $_FILES[ $name ]['error'] ) { |
658
|
|
|
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
659
|
|
|
$value = file_get_contents( $_FILES[ $name ]['tmp_name'], true ); |
660
|
|
|
|
661
|
|
|
update_post_meta( $post_id, $meta_key, $value ); |
662
|
|
|
} |
663
|
|
|
} |
664
|
|
|
|
665
|
|
|
// Update Apple Pay Merchant Identity certificate and private key from uploaded PKCS#12 file. |
666
|
|
|
$apple_pay_merchant_id_pkcs12 = get_post_meta( $post_id, '_pronamic_gateway_adyen_apple_pay_merchant_id_certificate', true ); |
667
|
|
|
|
668
|
|
|
if ( ! empty( $apple_pay_merchant_id_pkcs12 ) ) { |
669
|
|
|
// Try to read file without using password. |
670
|
|
|
$pkcs12_read = \openssl_pkcs12_read( $apple_pay_merchant_id_pkcs12, $certs, '' ); |
671
|
|
|
|
672
|
|
|
$password = \get_post_meta( $post_id, '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key_password', true ); |
673
|
|
|
|
674
|
|
|
// Try to read file with private key password. |
675
|
|
|
if ( false === $pkcs12_read ) { |
676
|
|
|
$pkcs12_read = \openssl_pkcs12_read( $apple_pay_merchant_id_pkcs12, $certs, $password ); |
|
|
|
|
677
|
|
|
} |
678
|
|
|
|
679
|
|
|
if ( true === $pkcs12_read ) { |
680
|
|
|
if ( isset( $certs['cert'] ) ) { |
681
|
|
|
\update_post_meta( $post_id, '_pronamic_gateway_adyen_apple_pay_merchant_id_certificate', $certs['cert'] ); |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
if ( isset( $certs['pkey'] ) ) { |
685
|
|
|
$private_key = $certs['pkey']; |
686
|
|
|
|
687
|
|
|
$cipher = null; |
688
|
|
|
|
689
|
|
|
// Try to export the private key encrypted. |
690
|
|
|
if ( defined( 'OPENSSL_CIPHER_AES_128_CBC' ) ) { |
691
|
|
|
$cipher = \OPENSSL_CIPHER_AES_128_CBC; |
692
|
|
|
} elseif ( defined( 'OPENSSL_CIPHER_3DES' ) ) { |
693
|
|
|
$cipher = \OPENSSL_CIPHER_3DES; |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
if ( null !== $cipher && '' !== $password ) { |
697
|
|
|
$args = array( |
698
|
|
|
'digest_alg' => 'SHA256', |
699
|
|
|
'private_key_bits' => 2048, |
700
|
|
|
'private_key_type' => \OPENSSL_KEYTYPE_RSA, |
701
|
|
|
'encrypt_key' => true, |
702
|
|
|
'encrypt_key_cipher' => $cipher, |
703
|
|
|
'subjectKeyIdentifier' => 'hash', |
704
|
|
|
'authorityKeyIdentifier' => 'keyid:always,issuer:always', |
705
|
|
|
'basicConstraints' => 'CA:true', |
706
|
|
|
); |
707
|
|
|
|
708
|
|
|
\openssl_pkey_export( $certs['pkey'], $private_key, $password, $args ); |
|
|
|
|
709
|
|
|
} |
710
|
|
|
|
711
|
|
|
\update_post_meta( $post_id, '_pronamic_gateway_adyen_apple_pay_merchant_id_private_key', $private_key ); |
712
|
|
|
} |
713
|
|
|
} |
714
|
|
|
} |
715
|
|
|
} |
716
|
|
|
|
717
|
|
|
/** |
718
|
|
|
* Get configuration by post ID. |
719
|
|
|
* |
720
|
|
|
* @param int $post_id Post ID. |
721
|
|
|
* @return Config |
722
|
|
|
*/ |
723
|
1 |
|
public function get_config( $post_id ) { |
724
|
1 |
|
$config = new Config(); |
725
|
|
|
|
726
|
1 |
|
$config->mode = $this->get_meta( $post_id, 'mode' ); |
727
|
1 |
|
$config->api_key = $this->get_meta( $post_id, 'adyen_api_key' ); |
728
|
1 |
|
$config->api_live_url_prefix = $this->get_meta( $post_id, 'adyen_api_live_url_prefix' ); |
729
|
1 |
|
$config->merchant_account = $this->get_meta( $post_id, 'adyen_merchant_account' ); |
730
|
1 |
|
$config->origin_key = $this->get_meta( $post_id, 'adyen_origin_key' ); |
731
|
1 |
|
$config->merchant_order_reference = $this->get_meta( $post_id, 'adyen_merchant_order_reference' ); |
732
|
1 |
|
$config->apple_pay_merchant_id = $this->get_meta( $post_id, 'adyen_apple_pay_merchant_id' ); |
733
|
1 |
|
$config->apple_pay_merchant_id_certificate = $this->get_meta( $post_id, 'adyen_apple_pay_merchant_id_certificate' ); |
734
|
1 |
|
$config->apple_pay_merchant_id_private_key = $this->get_meta( $post_id, 'adyen_apple_pay_merchant_id_private_key' ); |
735
|
1 |
|
$config->apple_pay_merchant_id_private_key_password = $this->get_meta( $post_id, 'adyen_apple_pay_merchant_id_private_key_password' ); |
736
|
1 |
|
$config->google_pay_merchant_identifier = $this->get_meta( $post_id, 'adyen_google_pay_merchant_identifier' ); |
737
|
|
|
|
738
|
1 |
|
return $config; |
739
|
|
|
} |
740
|
|
|
|
741
|
|
|
/** |
742
|
|
|
* Get gateway. |
743
|
|
|
* |
744
|
|
|
* @param int $post_id Post ID. |
745
|
|
|
* @return AbstractGateway |
746
|
|
|
*/ |
747
|
1 |
|
public function get_gateway( $post_id ) { |
748
|
1 |
|
$config = $this->get_config( $post_id ); |
749
|
|
|
|
750
|
1 |
|
if ( empty( $config->origin_key ) ) { |
751
|
1 |
|
return new WebSdkGateway( $config ); |
752
|
|
|
} |
753
|
|
|
|
754
|
|
|
return new DropInGateway( $config ); |
755
|
|
|
} |
756
|
|
|
} |
757
|
|
|
|