blob: 82492d4def9681904d96a78dcfe775665ef3ee5c [file] [log] [blame]
swissChilif0cbdc32023-01-05 17:21:38 -05001<?php
2/**
3 * Class WC_REST_Stripe_Settings_Controller
4 */
5
6defined( 'ABSPATH' ) || exit;
7
8/**
9 * REST controller for settings.
10 */
11class WC_REST_Stripe_Settings_Controller extends WC_Stripe_REST_Base_Controller {
12
13 /**
14 * Endpoint path.
15 *
16 * @var string
17 */
18 protected $rest_base = 'wc_stripe/settings';
19
20 /**
21 * Stripe payment gateway.
22 *
23 * @var WC_Gateway_Stripe
24 */
25 private $gateway;
26
27 /**
28 * Constructor.
29 *
30 * @param WC_Gateway_Stripe $gateway Stripe payment gateway.
31 */
32 public function __construct( WC_Gateway_Stripe $gateway ) {
33 $this->gateway = $gateway;
34 }
35
36 /**
37 * Configure REST API routes.
38 */
39 public function register_routes() {
40 $form_fields = $this->gateway->get_form_fields();
41
42 register_rest_route(
43 $this->namespace,
44 '/' . $this->rest_base,
45 [
46 'methods' => WP_REST_Server::READABLE,
47 'callback' => [ $this, 'get_settings' ],
48 'permission_callback' => [ $this, 'check_permission' ],
49 ]
50 );
51 register_rest_route(
52 $this->namespace,
53 '/' . $this->rest_base,
54 [
55 'methods' => WP_REST_Server::EDITABLE,
56 'callback' => [ $this, 'update_settings' ],
57 'permission_callback' => [ $this, 'check_permission' ],
58 'args' => [
59 'is_stripe_enabled' => [
60 'description' => __( 'If Stripe should be enabled.', 'woocommerce-gateway-stripe' ),
61 'type' => 'boolean',
62 'validate_callback' => 'rest_validate_request_arg',
63 ],
64 'is_test_mode_enabled' => [
65 'description' => __( 'Stripe test mode setting.', 'woocommerce-gateway-stripe' ),
66 'type' => 'boolean',
67 'validate_callback' => 'rest_validate_request_arg',
68 ],
69 'title' => [
70 'description' => __( 'Stripe display title.', 'woocommerce-gateway-stripe' ),
71 'type' => 'string',
72 'validate_callback' => 'rest_validate_request_arg',
73 ],
74 'title_upe' => [
75 'description' => __( 'New checkout experience title.', 'woocommerce-gateway-stripe' ),
76 'type' => 'string',
77 'validate_callback' => 'rest_validate_request_arg',
78 ],
79 'description' => [
80 'description' => __( 'Stripe display description.', 'woocommerce-gateway-stripe' ),
81 'type' => 'string',
82 'validate_callback' => 'rest_validate_request_arg',
83 ],
84 'enabled_payment_method_ids' => [
85 'description' => __( 'Payment method IDs that should be enabled. Other methods will be disabled.', 'woocommerce-gateway-stripe' ),
86 'type' => 'array',
87 'items' => [
88 'type' => 'string',
89 'enum' => $this->gateway->get_upe_available_payment_methods(),
90 ],
91 'validate_callback' => 'rest_validate_request_arg',
92 ],
93 'is_payment_request_enabled' => [
94 'description' => __( 'If Stripe express checkouts should be enabled.', 'woocommerce-gateway-stripe' ),
95 'type' => 'boolean',
96 'validate_callback' => 'rest_validate_request_arg',
97 ],
98 'payment_request_button_type' => [
99 'description' => __( 'Express checkout button types.', 'woocommerce-gateway-stripe' ),
100 'type' => 'string',
101 'enum' => array_keys( $form_fields['payment_request_button_type']['options'] ),
102 'validate_callback' => 'rest_validate_request_arg',
103 ],
104 'payment_request_button_theme' => [
105 'description' => __( 'Express checkout button themes.', 'woocommerce-gateway-stripe' ),
106 'type' => 'string',
107 'enum' => array_keys( $form_fields['payment_request_button_theme']['options'] ),
108 'validate_callback' => 'rest_validate_request_arg',
109 ],
110 'payment_request_button_size' => [
111 'description' => __( 'Express checkout button sizes.', 'woocommerce-gateway-stripe' ),
112 'type' => 'string',
113 // it can happen that `$form_fields['payment_request_button_size']` is empty (in tests) - fixing temporarily.
114 'enum' => array_keys( isset( $form_fields['payment_request_button_size']['options'] ) ? $form_fields['payment_request_button_size']['options'] : [] ),
115 'validate_callback' => 'rest_validate_request_arg',
116 ],
117 'payment_request_button_locations' => [
118 'description' => __( 'Express checkout locations that should be enabled.', 'woocommerce-gateway-stripe' ),
119 'type' => 'array',
120 'items' => [
121 'type' => 'string',
122 'enum' => array_keys( $form_fields['payment_request_button_locations']['options'] ),
123 ],
124 'validate_callback' => 'rest_validate_request_arg',
125 ],
126 'is_manual_capture_enabled' => [
127 'description' => __( 'If manual capture of charges should be enabled.', 'woocommerce-gateway-stripe' ),
128 'type' => 'boolean',
129 'validate_callback' => 'rest_validate_request_arg',
130 ],
131 'is_saved_cards_enabled' => [
132 'description' => __( 'If "Saved cards" should be enabled.', 'woocommerce-gateway-stripe' ),
133 'type' => 'boolean',
134 'validate_callback' => 'rest_validate_request_arg',
135 ],
136 'is_separate_card_form_enabled' => [
137 'description' => __( 'If credit card number field, expiry date field, and CVC field should be separate.', 'woocommerce-gateway-stripe' ),
138 'type' => 'boolean',
139 'validate_callback' => 'rest_validate_request_arg',
140 ],
141 'statement_descriptor' => [
142 'description' => __( 'Bank account descriptor to be displayed in customers\' bank accounts.', 'woocommerce-gateway-stripe' ),
143 'type' => 'string',
144 'validate_callback' => [ $this, 'validate_regular_statement_descriptor' ],
145 ],
146 'is_short_statement_descriptor_enabled' => [
147 'description' => __( 'When enabled, we\'ll include the order number for card and express checkout transactions.', 'woocommerce-gateway-stripe' ),
148 'type' => 'boolean',
149 'validate_callback' => 'rest_validate_request_arg',
150 ],
151 'short_statement_descriptor' => [
152 'description' => __( 'We\'ll use the short version in combination with the customer order number.', 'woocommerce-gateway-stripe' ),
153 'type' => 'string',
154 'validate_callback' => [ $this, 'validate_short_statement_descriptor' ],
155 ],
156 'is_debug_log_enabled' => [
157 'description' => __( 'When enabled, payment error logs will be saved to WooCommerce > Status > Logs.', 'woocommerce-gateway-stripe' ),
158 'type' => 'boolean',
159 'validate_callback' => 'rest_validate_request_arg',
160 ],
161 ],
162 ]
163 );
164 }
165
166 /**
167 * Validate the regular statement descriptor.
168 *
169 * @param mixed $value The value being validated.
170 * @param WP_REST_Request $request The request made.
171 * @param string $param The parameter name, used in error messages.
172 * @return true|WP_Error
173 */
174 public function validate_regular_statement_descriptor( $value, $request, $param ) {
175 return $this->validate_statement_descriptor( $value, $request, $param, 22 );
176 }
177
178 /**
179 * Validate the short statement descriptor.
180 *
181 * @param mixed $value The value being validated.
182 * @param WP_REST_Request $request The request made.
183 * @param string $param The parameter name, used in error messages.
184 * @return true|WP_Error
185 */
186 public function validate_short_statement_descriptor( $value, $request, $param ) {
187 $is_short_account_statement_enabled = $request->get_param( 'is_short_statement_descriptor_enabled' );
188
189 // bypassing validation to avoid errors in the client, it won't be updated under this condition
190 if ( ! $is_short_account_statement_enabled ) {
191 return true;
192 }
193
194 return $this->validate_statement_descriptor( $value, $request, $param, 10 );
195 }
196
197 /**
198 * Validate the statement descriptor argument.
199 *
200 * @since 4.7.0
201 *
202 * @param mixed $value The value being validated.
203 * @param WP_REST_Request $request The request made.
204 * @param string $param The parameter name, used in error messages.
205 * @param int $max_length Maximum statement length.
206 * @return true|WP_Error
207 */
208 public function validate_statement_descriptor( $value, $request, $param, $max_length ) {
209 $string_validation_result = rest_validate_request_arg( $value, $request, $param );
210 if ( true !== $string_validation_result ) {
211 return $string_validation_result;
212 }
213
214 // Relaxing validation because it's blocking the user from saving it when they're on another tab of the settings screen
215 // TODO: work that out with either a UX approach or handling the validations of each tab separately
216 if ( '' === $value ) {
217 return true;
218 }
219
220 try {
221 $this->gateway->validate_account_statement_descriptor_field( $param, $value, $max_length );
222 } catch ( Exception $exception ) {
223 return new WP_Error(
224 'rest_invalid_pattern',
225 $exception->getMessage()
226 );
227 }
228
229 return true;
230 }
231
232 /**
233 * Retrieve settings.
234 *
235 * @return WP_REST_Response
236 */
237 public function get_settings() {
238 return new WP_REST_Response(
239 [
240 /* Settings > General */
241 'is_stripe_enabled' => $this->gateway->is_enabled(),
242 'is_test_mode_enabled' => $this->gateway->is_in_test_mode(),
243 'title' => $this->gateway->get_validated_option( 'title' ),
244 'title_upe' => $this->gateway->get_validated_option( 'title_upe' ),
245 'description' => $this->gateway->get_validated_option( 'description' ),
246
247 /* Settings > Payments accepted on checkout */
248 'enabled_payment_method_ids' => $this->gateway->get_upe_enabled_payment_method_ids(),
249 'available_payment_method_ids' => $this->gateway->get_upe_available_payment_methods(),
250
251 /* Settings > Express checkouts */
252 'is_payment_request_enabled' => 'yes' === $this->gateway->get_option( 'payment_request' ),
253 'payment_request_button_type' => $this->gateway->get_validated_option( 'payment_request_button_type' ),
254 'payment_request_button_theme' => $this->gateway->get_validated_option( 'payment_request_button_theme' ),
255 'payment_request_button_size' => $this->gateway->get_validated_option( 'payment_request_button_size' ),
256 'payment_request_button_locations' => $this->gateway->get_validated_option( 'payment_request_button_locations' ),
257
258 /* Settings > Payments & transactions */
259 'is_manual_capture_enabled' => ! $this->gateway->is_automatic_capture_enabled(),
260 'is_saved_cards_enabled' => 'yes' === $this->gateway->get_option( 'saved_cards' ),
261 'is_separate_card_form_enabled' => 'no' === $this->gateway->get_option( 'inline_cc_form' ),
262 'statement_descriptor' => $this->gateway->get_validated_option( 'statement_descriptor' ),
263 'is_short_statement_descriptor_enabled' => 'yes' === $this->gateway->get_option( 'is_short_statement_descriptor_enabled' ),
264 'short_statement_descriptor' => $this->gateway->get_validated_option( 'short_statement_descriptor' ),
265
266 /* Settings > Advanced settings */
267 'is_debug_log_enabled' => 'yes' === $this->gateway->get_option( 'logging' ),
268 'is_upe_enabled' => WC_Stripe_Feature_Flags::is_upe_checkout_enabled(),
269 ]
270 );
271 }
272
273 /**
274 * Update settings.
275 *
276 * @param WP_REST_Request $request Full data about the request.
277 */
278 public function update_settings( WP_REST_Request $request ) {
279 /* Settings > General */
280 $this->update_is_stripe_enabled( $request );
281 $this->update_title( $request );
282 $this->update_title_upe( $request );
283 $this->update_description( $request );
284 $this->update_is_test_mode_enabled( $request );
285
286 /* Settings > Payments accepted on checkout */
287 $this->update_enabled_payment_methods( $request );
288
289 /* Settings > Express checkouts */
290 $this->update_is_payment_request_enabled( $request );
291 $this->update_payment_request_settings( $request );
292
293 /* Settings > Payments & transactions */
294 $this->update_is_manual_capture_enabled( $request );
295 $this->update_is_saved_cards_enabled( $request );
296 $this->update_is_separate_card_form_enabled( $request );
297 $this->update_account_statement_descriptor( $request );
298 $this->update_is_short_account_statement_enabled( $request );
299 $this->update_short_account_statement_descriptor( $request );
300
301 /* Settings > Advanced settings */
302 $this->update_is_debug_log_enabled( $request );
303 $this->update_is_upe_enabled( $request );
304
305 return new WP_REST_Response( [], 200 );
306 }
307
308 /**
309 * Updates Stripe enabled status.
310 *
311 * @param WP_REST_Request $request Request object.
312 */
313 private function update_is_stripe_enabled( WP_REST_Request $request ) {
314 $is_stripe_enabled = $request->get_param( 'is_stripe_enabled' );
315
316 if ( null === $is_stripe_enabled ) {
317 return;
318 }
319
320 if ( $is_stripe_enabled ) {
321 $this->gateway->enable();
322 } else {
323 $this->gateway->disable();
324 }
325 }
326
327 /**
328 * Updates title.
329 *
330 * @param WP_REST_Request $request Request object.
331 */
332 private function update_title( WP_REST_Request $request ) {
333 $title = $request->get_param( 'title' );
334
335 if ( null === $title ) {
336 return;
337 }
338
339 $this->gateway->update_validated_option( 'title', $title );
340 }
341
342 /**
343 * Updates UPE title.
344 *
345 * @param WP_REST_Request $request Request object.
346 */
347 private function update_title_upe( WP_REST_Request $request ) {
348 $title_upe = $request->get_param( 'title_upe' );
349
350 if ( null === $title_upe ) {
351 return;
352 }
353
354 $this->gateway->update_validated_option( 'title_upe', $title_upe );
355 }
356
357 /**
358 * Updates description.
359 *
360 * @param WP_REST_Request $request Request object.
361 */
362 private function update_description( WP_REST_Request $request ) {
363 $description = $request->get_param( 'description' );
364
365 if ( null === $description ) {
366 return;
367 }
368
369 $this->gateway->update_validated_option( 'description', $description );
370 }
371
372 /**
373 * Updates Stripe test mode.
374 *
375 * @param WP_REST_Request $request Request object.
376 */
377 private function update_is_test_mode_enabled( WP_REST_Request $request ) {
378 $is_test_mode_enabled = $request->get_param( 'is_test_mode_enabled' );
379
380 if ( null === $is_test_mode_enabled ) {
381 return;
382 }
383
384 $this->gateway->update_option( 'testmode', $is_test_mode_enabled ? 'yes' : 'no' );
385 }
386
387 /**
388 * Updates the "payment request" enable/disable settings.
389 *
390 * @param WP_REST_Request $request Request object.
391 */
392 private function update_is_payment_request_enabled( WP_REST_Request $request ) {
393 $is_payment_request_enabled = $request->get_param( 'is_payment_request_enabled' );
394
395 if ( null === $is_payment_request_enabled ) {
396 return;
397 }
398
399 $this->gateway->update_option( 'payment_request', $is_payment_request_enabled ? 'yes' : 'no' );
400 }
401
402 /**
403 * Updates manual capture.
404 *
405 * @param WP_REST_Request $request Request object.
406 */
407 private function update_is_manual_capture_enabled( WP_REST_Request $request ) {
408 $is_manual_capture_enabled = $request->get_param( 'is_manual_capture_enabled' );
409
410 if ( null === $is_manual_capture_enabled ) {
411 return;
412 }
413
414 $this->gateway->update_option( 'capture', $is_manual_capture_enabled ? 'no' : 'yes' );
415 }
416
417 /**
418 * Updates "saved cards" feature.
419 *
420 * @param WP_REST_Request $request Request object.
421 */
422 private function update_is_saved_cards_enabled( WP_REST_Request $request ) {
423 $is_saved_cards_enabled = $request->get_param( 'is_saved_cards_enabled' );
424
425 if ( null === $is_saved_cards_enabled ) {
426 return;
427 }
428
429 $this->gateway->update_option( 'saved_cards', $is_saved_cards_enabled ? 'yes' : 'no' );
430 }
431
432 /**
433 * Updates "saved cards" feature.
434 *
435 * @param WP_REST_Request $request Request object.
436 */
437 private function update_is_separate_card_form_enabled( WP_REST_Request $request ) {
438 $is_separate_card_form_enabled = $request->get_param( 'is_separate_card_form_enabled' );
439
440 if ( null === $is_separate_card_form_enabled ) {
441 return;
442 }
443
444 $this->gateway->update_option( 'inline_cc_form', $is_separate_card_form_enabled ? 'no' : 'yes' );
445 }
446
447 /**
448 * Updates account statement descriptor.
449 *
450 * @param WP_REST_Request $request Request object.
451 */
452 private function update_account_statement_descriptor( WP_REST_Request $request ) {
453 $account_statement_descriptor = $request->get_param( 'statement_descriptor' );
454
455 if ( null === $account_statement_descriptor ) {
456 return;
457 }
458
459 $this->gateway->update_validated_option( 'statement_descriptor', $account_statement_descriptor );
460 }
461
462 /**
463 * Updates whether short account statement should be used.
464 *
465 * @param WP_REST_Request $request Request object.
466 */
467 private function update_is_short_account_statement_enabled( WP_REST_Request $request ) {
468 $is_short_account_statement_enabled = $request->get_param( 'is_short_statement_descriptor_enabled' );
469
470 if ( null === $is_short_account_statement_enabled ) {
471 return;
472 }
473
474 $this->gateway->update_option( 'is_short_statement_descriptor_enabled', $is_short_account_statement_enabled ? 'yes' : 'no' );
475 }
476
477 /**
478 * Updates short account statement descriptor.
479 *
480 * @param WP_REST_Request $request Request object.
481 */
482 private function update_short_account_statement_descriptor( WP_REST_Request $request ) {
483 $is_short_account_statement_enabled = $request->get_param( 'is_short_statement_descriptor_enabled' );
484 $short_account_statement_descriptor = $request->get_param( 'short_statement_descriptor' );
485
486 // since we're bypassing the validation on the same condition, we shouldn't update it
487 if ( ! $is_short_account_statement_enabled ) {
488 return;
489 }
490
491 if ( null === $short_account_statement_descriptor ) {
492 return;
493 }
494
495 $this->gateway->update_validated_option( 'short_statement_descriptor', $short_account_statement_descriptor );
496 }
497
498 /**
499 * Updates whether debug logging is enabled.
500 *
501 * @param WP_REST_Request $request Request object.
502 */
503 private function update_is_debug_log_enabled( WP_REST_Request $request ) {
504 $is_debug_log_enabled = $request->get_param( 'is_debug_log_enabled' );
505
506 if ( null === $is_debug_log_enabled ) {
507 return;
508 }
509
510 $this->gateway->update_option( 'logging', $is_debug_log_enabled ? 'yes' : 'no' );
511
512 }
513
514 /**
515 * Updates whether debug logging is enabled.
516 *
517 * @param WP_REST_Request $request Request object.
518 */
519 private function update_is_upe_enabled( WP_REST_Request $request ) {
520 $is_upe_enabled = $request->get_param( 'is_upe_enabled' );
521
522 if ( null === $is_upe_enabled ) {
523 return;
524 }
525
526 $settings = get_option( 'woocommerce_stripe_settings', [] );
527 $settings[ WC_Stripe_Feature_Flags::UPE_CHECKOUT_FEATURE_ATTRIBUTE_NAME ] = $is_upe_enabled ? 'yes' : 'disabled';
528 update_option( 'woocommerce_stripe_settings', $settings );
529
530 // including the class again because otherwise it's not present.
531 if ( WC_Stripe_Inbox_Notes::are_inbox_notes_supported() ) {
532 require_once WC_STRIPE_PLUGIN_PATH . '/includes/notes/class-wc-stripe-upe-availability-note.php';
533 WC_Stripe_UPE_Availability_Note::possibly_delete_note();
534
535 require_once WC_STRIPE_PLUGIN_PATH . '/includes/notes/class-wc-stripe-upe-stripelink-note.php';
536 WC_Stripe_UPE_StripeLink_Note::possibly_delete_note();
537 }
538 }
539
540 /**
541 * Updates appearance attributes of the payment request button.
542 *
543 * @param WP_REST_Request $request Request object.
544 */
545 private function update_payment_request_settings( WP_REST_Request $request ) {
546 $attributes = [
547 'payment_request_button_type' => 'payment_request_button_type',
548 'payment_request_button_size' => 'payment_request_button_size',
549 'payment_request_button_theme' => 'payment_request_button_theme',
550 'payment_request_button_locations' => 'payment_request_button_locations',
551 ];
552
553 foreach ( $attributes as $request_key => $attribute ) {
554 if ( null === $request->get_param( $request_key ) ) {
555 continue;
556 }
557
558 $value = $request->get_param( $request_key );
559 $this->gateway->update_validated_option( $attribute, $value );
560 }
561 }
562
563 /**
564 * Updates the list of enabled payment methods.
565 *
566 * @param WP_REST_Request $request Request object.
567 */
568 private function update_enabled_payment_methods( WP_REST_Request $request ) {
569 // no need to update the payment methods, if the UPE checkout is not enabled
570 if ( ! WC_Stripe_Feature_Flags::is_upe_checkout_enabled() ) {
571 return;
572 }
573
574 $payment_method_ids_to_enable = $request->get_param( 'enabled_payment_method_ids' );
575
576 if ( null === $payment_method_ids_to_enable ) {
577 return;
578 }
579
580 $available_payment_methods = $this->gateway->get_upe_available_payment_methods();
581
582 $payment_method_ids_to_enable = array_values(
583 array_filter(
584 $payment_method_ids_to_enable,
585 function ( $payment_method ) use ( $available_payment_methods ) {
586 return in_array( $payment_method, $available_payment_methods, true );
587 }
588 )
589 );
590
591 $this->gateway->update_option( 'upe_checkout_experience_accepted_payments', $payment_method_ids_to_enable );
592 }
593}