Completed
Pull Request — master (#1357)
by
unknown
02:17
created

WC_Stripe_Apple_Pay_Registration::get_option()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
1
<?php
2
/**
3
 * Stripe Apple Pay Registration Class.
4
 *
5
 * @since 4.0.6
6
 */
7
8
if ( ! defined( 'ABSPATH' ) ) {
9
	exit;
10
}
11
12
class WC_Stripe_Apple_Pay_Registration {
13
	/**
14
	 * Enabled.
15
	 *
16
	 * @var
17
	 */
18
	public $stripe_settings;
19
20
	/**
21
	 * Apple Pay Domain Set.
22
	 *
23
	 * @var bool
24
	 */
25
	public $apple_pay_domain_set;
26
27
	/**
28
	 * Stores Apple Pay domain verification issues.
29
	 *
30
	 * @var string
31
	 */
32
	public $apple_pay_verify_notice;
33
34
	public function __construct() {
35
		add_action( 'init', array( $this, 'add_domain_association_rewrite_rule' ) );
36
		add_filter( 'query_vars', array( $this, 'whitelist_domain_association_query_param' ), 10, 1 );
37
		add_action( 'parse_request', array( $this, 'parse_domain_association_request' ), 10, 1 );
38
39
		add_action( 'woocommerce_stripe_updated', array( $this, 'verify_domain_if_configured' ) );
40
		add_action( 'update_option_woocommerce_stripe_settings', array( $this, 'verify_domain_on_settings_change' ), 10, 2 );
41
		add_action( 'admin_notices', array( $this, 'admin_notices' ) );
42
43
		$this->stripe_settings                 = get_option( 'woocommerce_stripe_settings', array() );
44
		$this->apple_pay_domain_set            = 'yes' === $this->get_option( 'apple_pay_domain_set', 'no' );
45
		$this->apple_pay_verify_notice         = '';
46
	}
47
48
	/**
49
	 * Gets the Stripe settings.
50
	 *
51
	 * @since 4.0.6
52
	 * @param string $setting
53
	 * @param string default
54
	 * @return string $setting_value
55
	 */
56
	public function get_option( $setting = '', $default = '' ) {
57
		if ( empty( $this->stripe_settings ) ) {
58
			return $default;
59
		}
60
61
		if ( ! empty( $this->stripe_settings[ $setting ] ) ) {
62
			return $this->stripe_settings[ $setting ];
63
		}
64
65
		return $default;
66
	}
67
68
	/**
69
	 * Whether the gateway and Payment Request Button (prerequisites for Apple Pay) are enabled.
70
	 *
71
	 * @since 4.5.4
72
	 * @return string Whether Apple Pay required settings are enabled.
73
	 */
74
	private function is_enabled() {
75
		$stripe_enabled                 = 'yes' === $this->get_option( 'enabled', 'no' );
76
		$payment_request_button_enabled = 'yes' === $this->get_option( 'payment_request', 'yes' );
77
78
		return $stripe_enabled && $payment_request_button_enabled;
79
	}
80
81
	/**
82
	 * Gets the Stripe secret key for the current mode.
83
	 *
84
	 * @since 4.5.3
85
	 * @return string Secret key.
86
	 */
87
	private function get_secret_key() {
88
		$testmode = 'yes' === $this->get_option( 'testmode', 'no' );
89
		return $testmode ? $this->get_option( 'test_secret_key' ) : $this->get_option( 'secret_key' );
90
	}
91
92
	/**
93
	 * Adds a rewrite rule for serving the domain association file from the proper location.
94
	 */
95
	public function add_domain_association_rewrite_rule() {
96
		$regex    = '^\.well-known\/apple-developer-merchantid-domain-association$';
97
		$redirect = 'index.php?apple-developer-merchantid-domain-association=1';
98
99
		add_rewrite_rule( $regex, $redirect, 'top' );
100
	}
101
102
	/**
103
	 * Add to the list of publicly allowed query variables.
104
	 *
105
	 * @param  array $query_vars - provided public query vars.
106
	 * @return array Updated public query vars.
107
	 */
108
	public function whitelist_domain_association_query_param( $query_vars ) {
109
		$query_vars[] = 'apple-developer-merchantid-domain-association';
110
		return $query_vars;
111
	}
112
113
	/**
114
	 * Serve domain association file when proper query param is provided.
115
	 *
116
	 * @param WP WordPress environment object.
117
	 */
118
	public function parse_domain_association_request( $wp ) {
119
		if (
120
			! isset( $wp->query_vars['apple-developer-merchantid-domain-association'] ) ||
121
			'1' !== $wp->query_vars['apple-developer-merchantid-domain-association']
122
		) {
123
			return;
124
		}
125
126
		$path = WC_STRIPE_PLUGIN_PATH . '/apple-developer-merchantid-domain-association';
127
		header( 'Content-Type: application/octet-stream' );
128
		echo esc_html( file_get_contents( $path ) );
129
		exit;
130
	}
131
132
	/**
133
	 * Makes request to register the domain with Stripe/Apple Pay.
134
	 *
135
	 * @since 3.1.0
136
	 * @version 4.5.4
137
	 * @param string $secret_key
138
	 */
139
	private function make_domain_registration_request( $secret_key ) {
140
		if ( empty( $secret_key ) ) {
141
			throw new Exception( __( 'Unable to verify domain - missing secret key.', 'woocommerce-gateway-stripe' ) );
142
		}
143
144
		$endpoint = 'https://api.stripe.com/v1/apple_pay/domains';
145
146
		$data = array(
147
			'domain_name' => $_SERVER['HTTP_HOST'],
148
		);
149
150
		$headers = array(
151
			'User-Agent'    => 'WooCommerce Stripe Apple Pay',
152
			'Authorization' => 'Bearer ' . $secret_key,
153
		);
154
155
		$response = wp_remote_post(
156
			$endpoint,
157
			array(
158
				'headers' => $headers,
159
				'body'    => http_build_query( $data ),
160
			)
161
		);
162
163
		if ( is_wp_error( $response ) ) {
164
			/* translators: error message */
165
			throw new Exception( sprintf( __( 'Unable to verify domain - %s', 'woocommerce-gateway-stripe' ), $response->get_error_message() ) );
166
		}
167
168
		if ( 200 !== $response['response']['code'] ) {
169
			$parsed_response = json_decode( $response['body'] );
170
171
			$this->apple_pay_verify_notice = $parsed_response->error->message;
172
173
			/* translators: error message */
174
			throw new Exception( sprintf( __( 'Unable to verify domain - %s', 'woocommerce-gateway-stripe' ), $parsed_response->error->message ) );
175
		}
176
	}
177
178
	/**
179
	 * Processes the Apple Pay domain verification.
180
	 *
181
	 * @since 3.1.0
182
	 * @version 4.5.4
183
	 *
184
	 * @param string $secret_key
185
	 */
186
	public function register_domain_with_apple( $secret_key ) {
187
		try {
188
			$this->make_domain_registration_request( $secret_key );
189
190
			// No errors to this point, verification success!
191
			$this->stripe_settings['apple_pay_domain_set'] = 'yes';
192
			$this->apple_pay_domain_set                    = true;
193
194
			update_option( 'woocommerce_stripe_settings', $this->stripe_settings );
195
196
			WC_Stripe_Logger::log( 'Your domain has been verified with Apple Pay!' );
197
198
		} catch ( Exception $e ) {
199
			$this->stripe_settings['apple_pay_domain_set'] = 'no';
200
			$this->apple_pay_domain_set                    = false;
201
202
			update_option( 'woocommerce_stripe_settings', $this->stripe_settings );
203
204
			WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
205
		}
206
	}
207
208
209
	/**
210
	 * Process the Apple Pay domain verification if proper settings are configured.
211
	 *
212
	 * @since 4.5.4
213
	 * @version 4.5.4
214
	 */
215
	public function verify_domain_if_configured() {
216
		$secret_key = $this->get_secret_key();
217
218
		if ( ! $this->is_enabled() || empty( $secret_key ) ) {
219
			return;
220
		}
221
222
		// Ensure that domain association file will be served.
223
		flush_rewrite_rules();
224
225
		// Register the domain with Apple Pay.
226
		$this->register_domain_with_apple( $secret_key );
227
	}
228
229
	/**
230
	 * Conditionally process the Apple Pay domain verification after settings are updated.
231
	 *
232
	 * @since 4.5.3
233
	 * @version 4.5.4
234
	 */
235
	public function verify_domain_on_settings_change( $prev_settings, $settings ) {
236
		// Grab previous state and then update cached settings.
237
		$this->stripe_settings = $prev_settings;
238
		$prev_secret_key       = $this->get_secret_key();
239
		$prev_is_enabled       = $this->is_enabled();
240
		$this->stripe_settings = $settings;
241
242
		// If Stripe or Payment Request Button wasn't enabled (or secret key was different) then might need to verify now.
243
		if ( ! $prev_is_enabled || ( $this->get_secret_key() !== $prev_secret_key ) ) {
244
			$this->verify_domain_if_configured();
245
		}
246
	}
247
248
	/**
249
	 * Display any admin notices to the user.
250
	 *
251
	 * @since 4.0.6
252
	 */
253
	public function admin_notices() {
254
		if ( ! $this->is_enabled() ) {
255
			return;
256
		}
257
258
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
259
			return;
260
		}
261
262
		$empty_notice = empty( $this->apple_pay_verify_notice );
263
		if ( $empty_notice && ( $this->apple_pay_domain_set || empty( $this->secret_key ) ) ) {
0 ignored issues
show
Bug introduced by
The property secret_key does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
264
			return;
265
		}
266
267
		/**
268
		 * Apple pay is enabled by default and domain verification initializes
269
		 * when setting screen is displayed. So if domain verification is not set,
270
		 * something went wrong so lets notify user.
271
		 */
272
		$allowed_html                      = array(
273
			'a' => array(
274
				'href'  => array(),
275
				'title' => array(),
276
			),
277
		);
278
		$verification_failed_without_error = __( 'Apple Pay domain verification failed.', 'woocommerce-gateway-stripe' );
279
		$verification_failed_with_error    = __( 'Apple Pay domain verification failed with the following error:', 'woocommerce-gateway-stripe' );
280
		$check_log_text                    = sprintf(
281
			/* translators: 1) HTML anchor open tag 2) HTML anchor closing tag */
282
			esc_html__( 'Please check the %1$slogs%2$s for more details on this issue. Logging must be enabled to see recorded logs.', 'woocommerce-gateway-stripe' ),
283
			'<a href="' . admin_url( 'admin.php?page=wc-status&tab=logs' ) . '">',
284
			'</a>'
285
		);
286
287
		?>
288
		<div class="error stripe-apple-pay-message">
289
			<?php if ( $empty_notice ) : ?>
290
				<p><?php echo esc_html( $verification_failed_without_error ); ?></p>
291
			<?php else : ?>
292
				<p><?php echo esc_html( $verification_failed_with_error ); ?></p>
293
				<p><i><?php echo wp_kses( make_clickable( esc_html( $this->apple_pay_verify_notice ) ), $allowed_html ); ?></i></p>
294
			<?php endif; ?>
295
			<p><?php echo $check_log_text; ?></p>
296
		</div>
297
		<?php
298
	}
299
}
300
301
new WC_Stripe_Apple_Pay_Registration();
302