Test Failed
Push — feature/mollie-connect ( e02179 )
by Reüel
07:33
created

Connect::set_access_token()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 2
rs 10
1
<?php
2
/**
3
 * Mollie Connect.
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2020 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Mollie;
12
13
use Pronamic\WordPress\DateTime\DateTime;
14
15
/**
16
 * Title: Mollie Connect
17
 * Description:
18
 * Copyright: 2005-2020 Pronamic
19
 * Company: Pronamic
20
 *
21
 * @author  Reüel van der Steege
22
 * @version 2.1.0
23
 * @since   2.1.0
24
 */
25
class Connect {
26
	/**
27
	 * WordPress Pay Mollie Connect API URL.
28
	 */
29
	const WP_PAY_MOLLIE_CONNECT_API_URL = 'https://mollie-connect.wp-pay.org/';
30
31
	/**
32
	 * Config ID.
33
	 *
34
	 * @var int
35
	 */
36
	private $config_id;
37
38
	/**
39
	 * Access token.
40
	 *
41
	 * @var string|null
42
	 */
43
	private $access_token;
44
45
	/**
46
	 * Access token valid until.
47
	 *
48
	 * @var string|null
49
	 */
50
	private $access_token_valid_until;
51
52
	/**
53
	 * Refresh token.
54
	 *
55
	 * @var string|null
56
	 */
57
	private $refresh_token;
58
59
	/**
60
	 * Connect constructor.
61
	 *
62
	 * @param int $config_id Config ID.
63
	 */
64
	public function __construct( $config_id ) {
65
		$this->config_id = $config_id;
66
	}
67
68
	/**
69
	 * Get refresh token.
70
	 *
71
	 * @return string
72
	 */
73
	public function get_refresh_token() {
74
		return $this->refresh_token;
75
	}
76
77
	/**
78
	 * Set refresh token.
79
	 *
80
	 * @param string $refresh_token Refresh token.
81
	 * @return void
82
	 */
83
	public function set_refresh_token( $refresh_token ) {
84
		$this->refresh_token = $refresh_token;
85
	}
86
87
	/**
88
	 * Get access token.
89
	 *
90
	 * @return string|null
91
	 */
92
	public function get_access_token() {
93
		return $this->access_token;
94
	}
95
96
	/**
97
	 * Set access token.
98
	 *
99
	 * @param string|null $access_token Access token.
100
	 * @return void
101
	 */
102
	public function set_access_token( $access_token ) {
103
		$this->access_token = $access_token;
104
	}
105
106
	/**
107
	 * Get access token valid until.
108
	 *
109
	 * @return string|null
110
	 */
111
	public function get_access_token_valid_until() {
112
		return $this->access_token_valid_until;
113
	}
114
115
	/**
116
	 * Set access token valid until.
117
	 *
118
	 * @param string|null $access_token_valid_until Access token valid until.
119
	 * @return void
120
	 */
121
	public function set_access_token_valid_until( $access_token_valid_until ) {
122
		$this->access_token_valid_until = $access_token_valid_until;
123
	}
124
125
	/**
126
	 * Check if access token is valid.
127
	 *
128
	 * @return bool True if valid, false otherwise.
129
	 */
130
	public function is_access_token_valid() {
131
		if ( empty( $this->access_token ) ) {
132
			return false;
133
		}
134
135
		return \strtotime( $this->access_token_valid_until ) > \time();
136
	}
137
138
	/**
139
	 * Maybe handle Mollie oAuth authorization.
140
	 *
141
	 * @param string $code       Authorization code.
142
	 * @param object $state_data State data.
143
	 * @return void
144
	 * @throws Error
145
	 */
146
	public function handle_authorization( $code, $state_data ) {
147
		if ( empty( $code ) || empty( $state_data ) ) {
148
			return;
149
		}
150
151
		if ( ! is_object( $state_data ) ) {
152
			return;
153
		}
154
155
		if ( ! isset( $state_data->post_id ) ) {
156
			return;
157
		}
158
159
		$config_id = $state_data->post_id;
160
161
		if ( ! \current_user_can( 'edit_post', $config_id ) ) {
162
			return;
163
		}
164
165
		$data = $this->request_access_token( $code );
166
167
		// Update access token.
168
		if ( isset( $data->access_token ) ) {
169
			\update_post_meta( $config_id, '_pronamic_gateway_mollie_access_token', $data->access_token );
170
		}
171
172
		// Update access token validity.
173
		if ( isset( $data->expires_in ) ) {
174
			$timestamp = time() + $data->expires_in;
175
176
			$access_token_valid_until = gmdate( DateTime::MYSQL, $timestamp );
177
178
			\update_post_meta( $config_id, '_pronamic_gateway_mollie_access_token_valid_until', $access_token_valid_until );
179
		}
180
181
		// Update refresh token.
182
		if ( isset( $data->refresh_token ) ) {
183
			\update_post_meta( $config_id, '_pronamic_gateway_mollie_refresh_token', $data->refresh_token );
184
		}
185
186
		\wp_update_post(
187
			array(
188
				'ID'          => $config_id,
189
				'post_status' => 'publish',
190
			)
191
		);
192
193
		// Redirect.
194
		$url = \get_edit_post_link( $config_id, 'raw' );
195
196
		\wp_safe_redirect( $url );
197
198
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
199
	}
200
201
	/**
202
	 * Get access token.
203
	 *
204
	 * @param string $authorization_code Authorization code.
205
	 * @return object
206
	 * @throws Error Throws Error when Mollie error occurs.
207
	 */
208
	private function request_access_token( $authorization_code ) {
209
		$data = array(
210
			'grant_type' => 'authorization_code',
211
			'code'       => $authorization_code,
212
		);
213
214
		return $this->send_token_request( $data );
215
	}
216
217
	/**
218
	 * Maybe refresh access token.
219
	 *
220
	 * @return void
221
	 */
222
	public function maybe_refresh_access_token() {
223
		if ( $this->is_access_token_valid() ) {
224
			return;
225
		}
226
227
		$refresh_token = $this->get_refresh_token();
228
229
		if ( empty( $refresh_token ) ) {
230
			return;
231
		}
232
233
		$response = $this->refresh_access_token();
234
235
		// Update access token.
236
		if ( isset( $response->access_token ) ) {
237
			$this->set_access_token( $response->access_token );
238
239
			\update_post_meta( $this->config_id, '_pronamic_gateway_mollie_access_token', $this->get_access_token() );
240
		}
241
242
		// Update access token validity.
243
		if ( isset( $response->expires_in ) ) {
244
			$timestamp = time() + $response->expires_in;
245
246
			$access_token_valid_until = gmdate( DateTime::MYSQL, $timestamp );
247
248
			$this->set_access_token_valid_until( $access_token_valid_until );
249
250
			\update_post_meta( $this->config_id, '_pronamic_gateway_mollie_access_token_valid_until', $this->get_access_token_valid_until() );
251
		}
252
	}
253
254
	/**
255
	 * Refresh access token.
256
	 *
257
	 * @return object
258
	 */
259
	private function refresh_access_token() {
260
		// Refresh access token.
261
		$data = array(
262
			'grant_type'    => 'refresh_token',
263
			'refresh_token' => $this->get_refresh_token(),
264
		);
265
266
		return $this->send_token_request( $data );
267
	}
268
269
	/**
270
	 * Send request with the specified action and parameters
271
	 *
272
	 * @param array<string, string|object|null> $data      Request data.
273
	 * @return object
274
	 * @throws Error Throws Error when Mollie error occurs.
275
	 * @throws \Exception Throws exception when error occurs.
276
	 */
277
	private function send_token_request( array $data = array() ) {
278
		// Request.
279
		$url = self::WP_PAY_MOLLIE_CONNECT_API_URL . 'oauth2/tokens';
280
281
		$response = wp_remote_request(
282
			$url,
283
			array(
284
				'method' => 'POST',
285
				'body'   => \wp_json_encode( $data ),
286
			)
287
		);
288
289
		if ( $response instanceof \WP_Error ) {
290
			throw new \Exception( $response->get_error_message() );
291
		}
292
293
		// Body.
294
		$body = wp_remote_retrieve_body( $response );
295
296
		$data = json_decode( $body );
297
298
		// JSON error.
299
		$json_error = \json_last_error();
300
301
		if ( \JSON_ERROR_NONE !== $json_error ) {
302
			throw new \Exception(
303
				\sprintf( 'JSON: %s', \json_last_error_msg() ),
304
				$json_error
305
			);
306
		}
307
308
		// Object.
309
		if ( ! \is_object( $data ) ) {
310
			$code = \wp_remote_retrieve_response_code( $response );
311
312
			throw new \Exception(
313
				\sprintf( 'Could not JSON decode Mollie response to an object (HTTP Status Code: %s).', $code ),
314
				\intval( $code )
315
			);
316
		}
317
318
		// Mollie error from JSON response.
319
		if ( isset( $data->status, $data->title, $data->detail ) ) {
320
			throw new Error(
321
				$data->status,
322
				$data->title,
323
				$data->detail
324
			);
325
		}
326
327
		return $data;
328
	}
329
}
330