Completed
Pull Request — master (#1357)
by
unknown
01:56
created

WC_Stripe_Apple_Pay_Registration::is_enabled()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 6
rs 10
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( 'woocommerce_stripe_updated', array( $this, 'verify_domain_if_configured' ) );
36
		add_action( 'update_option_woocommerce_stripe_settings', array( $this, 'verify_domain_on_settings_change' ), 10, 2 );
37
		add_action( 'admin_notices', array( $this, 'admin_notices' ) );
38
39
		add_action( 'init', array( $this, 'add_domain_association_rewrite_rule' ) );
40
		add_filter( 'query_vars', array( $this, 'whitelist_domain_association_query_param' ), 10, 1 );
41
		add_action( 'parse_request', array( $this, 'parse_domain_association_request' ), 10, 1 );
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 Secret key.
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 = parse_url( WC_STRIPE_PLUGIN_URL, PHP_URL_PATH ) . '/apple-developer-merchantid-domain-association';
98
99
		add_rewrite_rule( $regex, $redirect, 'top' );
100
	}
101
102
	/**
103
	 * Makes request to register the domain with Stripe/Apple Pay.
104
	 *
105
	 * @since 3.1.0
106
	 * @version 4.5.4
107
	 * @param string $secret_key
108
	 */
109
	private function make_domain_registration_request( $secret_key ) {
110
		if ( empty( $secret_key ) ) {
111
			throw new Exception( __( 'Unable to verify domain - missing secret key.', 'woocommerce-gateway-stripe' ) );
112
		}
113
114
		$endpoint = 'https://api.stripe.com/v1/apple_pay/domains';
115
116
		$data = array(
117
			'domain_name' => $_SERVER['HTTP_HOST'],
118
		);
119
120
		$headers = array(
121
			'User-Agent'    => 'WooCommerce Stripe Apple Pay',
122
			'Authorization' => 'Bearer ' . $secret_key,
123
		);
124
125
		$response = wp_remote_post(
126
			$endpoint,
127
			array(
128
				'headers' => $headers,
129
				'body'    => http_build_query( $data ),
130
			)
131
		);
132
133
		if ( is_wp_error( $response ) ) {
134
			/* translators: error message */
135
			throw new Exception( sprintf( __( 'Unable to verify domain - %s', 'woocommerce-gateway-stripe' ), $response->get_error_message() ) );
136
		}
137
138
		if ( 200 !== $response['response']['code'] ) {
139
			$parsed_response = json_decode( $response['body'] );
140
141
			$this->apple_pay_verify_notice = $parsed_response->error->message;
142
143
			/* translators: error message */
144
			throw new Exception( sprintf( __( 'Unable to verify domain - %s', 'woocommerce-gateway-stripe' ), $parsed_response->error->message ) );
145
		}
146
	}
147
148
	/**
149
	 * Processes the Apple Pay domain verification.
150
	 *
151
	 * @since 3.1.0
152
	 * @version 4.5.4
153
	 *
154
	 * @param string $secret_key
155
	 */
156
	public function register_domain_with_apple( $secret_key ) {
157
		try {
158
			$this->make_domain_registration_request( $secret_key );
159
160
			// No errors to this point, verification success!
161
			$this->stripe_settings['apple_pay_domain_set'] = 'yes';
162
			$this->apple_pay_domain_set                    = true;
163
164
			update_option( 'woocommerce_stripe_settings', $this->stripe_settings );
165
166
			WC_Stripe_Logger::log( 'Your domain has been verified with Apple Pay!' );
167
168
		} catch ( Exception $e ) {
169
			$this->stripe_settings['apple_pay_domain_set'] = 'no';
170
			$this->apple_pay_domain_set                    = false;
171
172
			update_option( 'woocommerce_stripe_settings', $this->stripe_settings );
173
174
			WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
175
		}
176
	}
177
178
179
	/**
180
	 * Process the Apple Pay domain verification if proper settings are configured.
181
	 *
182
	 * @since 4.5.4
183
	 * @version 4.5.4
184
	 */
185
	public function verify_domain_if_configured() {
186
		$secret_key = $this->get_secret_key();
187
188
		if ( ! $this->is_enabled() || empty( $secret_key ) ) {
189
			return;
190
		}
191
192
		// Ensure that domain association file will be served.
193
		flush_rewrite_rules();
194
195
		// Register the domain with Apple Pay.
196
		$this->register_domain_with_apple( $secret_key );
197
	}
198
199
	/**
200
	 * Conditionally process the Apple Pay domain verification after settings are updated.
201
	 *
202
	 * @since 4.5.3
203
	 * @version 4.5.4
204
	 */
205
	public function verify_domain_on_settings_change( $prev_settings, $settings ) {
206
		// Grab previous state and then update cached settings.
207
		$this->stripe_settings = $prev_settings;
208
		$prev_secret_key       = $this->get_secret_key();
209
		$prev_is_enabled       = $this->is_enabled();
210
		$this->stripe_settings = $settings;
211
212
		// If Stripe or Payment Request Button wasn't enabled (or secret key was different) then might need to verify now.
213
		if ( ! $prev_is_enabled || ( $this->get_secret_key() !== $prev_secret_key ) ) {
214
			$this->verify_domain_if_configured();
215
		}
216
	}
217
218
	/**
219
	 * Display any admin notices to the user.
220
	 *
221
	 * @since 4.0.6
222
	 */
223
	public function admin_notices() {
224
		if ( ! $this->is_enabled() ) {
225
			return;
226
		}
227
228
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
229
			return;
230
		}
231
232
		$empty_notice = empty( $this->apple_pay_verify_notice );
233
		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...
234
			return;
235
		}
236
237
		/**
238
		 * Apple pay is enabled by default and domain verification initializes
239
		 * when setting screen is displayed. So if domain verification is not set,
240
		 * something went wrong so lets notify user.
241
		 */
242
		$allowed_html                      = array(
243
			'a' => array(
244
				'href'  => array(),
245
				'title' => array(),
246
			),
247
		);
248
		$verification_failed_without_error = __( 'Apple Pay domain verification failed.', 'woocommerce-gateway-stripe' );
249
		$verification_failed_with_error    = __( 'Apple Pay domain verification failed with the following error:', 'woocommerce-gateway-stripe' );
250
		$check_log_text                    = sprintf(
251
			/* translators: 1) HTML anchor open tag 2) HTML anchor closing tag */
252
			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' ),
253
			'<a href="' . admin_url( 'admin.php?page=wc-status&tab=logs' ) . '">',
254
			'</a>'
255
		);
256
257
		?>
258
		<div class="error stripe-apple-pay-message">
259
			<?php if ( $empty_notice ) : ?>
260
				<p><?php echo esc_html( $verification_failed_without_error ); ?></p>
261
			<?php else : ?>
262
				<p><?php echo esc_html( $verification_failed_with_error ); ?></p>
263
				<p><i><?php echo wp_kses( make_clickable( esc_html( $this->apple_pay_verify_notice ) ), $allowed_html ); ?></i></p>
264
			<?php endif; ?>
265
			<p><?php echo $check_log_text; ?></p>
266
		</div>
267
		<?php
268
	}
269
}
270
271
new WC_Stripe_Apple_Pay_Registration();
272