Failed Conditions
Push — develop ( 3c7761...838bc7 )
by Remco
05:37
created

src/PaymentsController.php (2 issues)

Labels
Severity
1
<?php
2
/**
3
 * Payments controller
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 JsonSchema\Exception\ValidationException;
14
use Pronamic\WordPress\Pay\Plugin;
15
use WP_REST_Request;
16
17
/**
18
 * Payments result controller
19
 *
20
 * @link https://docs.adyen.com/developers/checkout/web-sdk/customization/logic#beforecomplete
21
 *
22
 * @author  Reüel van der Steege
23
 * @version 1.1.0
24
 * @since   1.1.0
25
 */
26
class PaymentsController {
27
	/**
28
	 * Setup.
29
	 *
30
	 * @return void
31
	 */
32 1
	public function setup() {
33 1
		add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );
34 1
	}
35
36
	/**
37
	 * REST API init.
38
	 *
39
	 * @link https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
40
	 * @link https://developer.wordpress.org/reference/hooks/rest_api_init/
41
	 *
42
	 * @return void
43
	 */
44 10
	public function rest_api_init() {
45
		// Register REST route `/payments//{payment_id}`.
46 10
		register_rest_route(
47 10
			Integration::REST_ROUTE_NAMESPACE,
48 10
			'/payments/(?P<payment_id>\d+)',
49
			array(
50 10
				'methods'  => 'POST',
51 10
				'callback' => array( $this, 'rest_api_adyen_payments' ),
52
				'args'     => array(
53
					'payment_id' => array(
54 10
						'description' => __( 'Payment ID.', 'pronamic_ideal' ),
55 10
						'type'        => 'integer',
56
					),
57
				),
58
			)
59
		);
60
61
		// Register REST route `/payments/details/{payment_id}`.
62 10
		register_rest_route(
63 10
			Integration::REST_ROUTE_NAMESPACE,
64 10
			'/payments/details/(?P<payment_id>\d+)',
65
			array(
66 10
				'methods'  => 'POST',
67 10
				'callback' => array( $this, 'rest_api_adyen_payment_details' ),
68
				'args'     => array(
69
					'payment_id' => array(
70 10
						'description' => __( 'Payment ID.', 'pronamic_ideal' ),
71 10
						'type'        => 'integer',
72
					),
73
				),
74
			)
75
		);
76 10
	}
77
78
	/**
79
	 * REST API Adyen payments handler.
80
	 *
81
	 * @param WP_REST_Request $request Request.
82
	 * @return object
83
	 * @throws \Exception Throws exception on Adyen service exception response.
84
	 */
85
	public function rest_api_adyen_payments( WP_REST_Request $request ) {
86
		$payment_id = $request->get_param( 'payment_id' );
87
88
		// Payment ID.
89
		if ( null === $payment_id ) {
90
			return new \WP_Error(
91
				'pronamic-pay-adyen-no-payment-id',
92
				__( 'No payment ID given in `payment_id` parameter.', 'pronamic_ideal' )
93
			);
94
		}
95
96
		$payment = \get_pronamic_payment( $payment_id );
97
98
		if ( null === $payment ) {
99
			return new \WP_Error(
100
				'pronamic-pay-adyen-payment-not-found',
101
				sprintf(
102
					/* translators: %s: payment ID */
103
					__( 'Could not find payment with ID `%s`.', 'pronamic_ideal' ),
104
					$payment_id
105
				),
106
				$payment_id
107
			);
108
		}
109
110
		// State data.
111
		$data = \json_decode( $request->get_body() );
112
113
		if ( null === $data ) {
114
			return new \WP_Error(
115
				'pronamic-pay-adyen-no-data',
116
				__( 'No data given in request body.', 'pronamic_ideal' )
117
			);
118
		}
119
120
		// Gateway.
121
		$config_id = $payment->get_config_id();
122
123
		if ( null === $config_id ) {
124
			return new \WP_Error(
125
				'pronamic-pay-adyen-no-config',
126
				__( 'No gateway configuration ID given in payment.', 'pronamic_ideal' )
127
			);
128
		}
129
130
		$gateway = Plugin::get_gateway( $config_id );
131
132
		if ( empty( $gateway ) ) {
133
			return new \WP_Error(
134
				'pronamic-pay-adyen-gateway-not-found',
135
				sprintf(
136
					/* translators: %s: Gateway configuration ID */
137
					__( 'Could not find gateway with ID `%s`.', 'pronamic_ideal' ),
138
					$config_id
139
				),
140
				$config_id
141
			);
142
		}
143
144
		if ( ! isset( $gateway->client ) ) {
145
			return new \WP_Error(
146
				'pronamic-pay-adyen-client-not-found',
147
				sprintf(
148
					/* translators: %s: Gateway configuration ID */
149
					__( 'Could not find client in gateway with ID `%s`.', 'pronamic_ideal' ),
150
					$config_id
151
				),
152
				$config_id
153
			);
154
		}
155
156
		// Create payment.
157
		// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Adyen JSON object.
158
		if ( ! isset( $data->paymentMethod->type ) ) {
159
			return new \WP_Error(
160
				'pronamic-pay-adyen-no-payment-method',
161
				__( 'No payment method given.', 'pronamic_ideal' )
162
			);
163
		}
164
165
		// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Adyen JSON object.
166
		$payment_method = PaymentMethod::from_object( $data->paymentMethod );
167
168
		try {
169
			if ( ! \is_callable( array( $gateway, 'create_payment' ) ) ) {
170
				return (object) array(
171
					'error' => __( 'Gateway does not support method to create payment.', 'pronamic_ideal' ),
172
				);
173
			}
174
175
			try {
176
				$response = $gateway->create_payment( $payment, $payment_method );
0 ignored issues
show
The method create_payment() does not exist on Pronamic\WordPress\Pay\Core\Gateway. It seems like you code against a sub-type of Pronamic\WordPress\Pay\Core\Gateway such as Pronamic\WordPress\Pay\G...ays\Adyen\DropInGateway. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

176
				/** @scrutinizer ignore-call */ 
177
    $response = $gateway->create_payment( $payment, $payment_method );
Loading history...
177
			} catch ( \Pronamic\WordPress\Pay\Gateways\Adyen\ServiceException $service_exception ) {
178
				$message = $service_exception->getMessage();
179
180
				$error_code = $service_exception->get_error_code();
181
182
				if ( ! empty( $error_code ) ) {
183
					$message = sprintf(
184
						/* translators: 1: error message, 2: error code */
185
						__( '%1$s (error %2$s)', 'pronamic_ideal' ),
186
						$service_exception->getMessage(),
187
						$error_code
188
					);
189
				}
190
191
				throw new \Exception( $message );
192
			}
193
		} catch ( \Exception $e ) {
194
			$error = $e->getMessage();
195
196
			$error_code = $e->getCode();
197
198
			if ( ! empty( $error_code ) ) {
199
				$error = sprintf( '%s - %s', $error_code, $e->getMessage() );
200
			}
201
202
			return (object) array( 'error' => $error );
203
		}
204
205
		// Update payment status based on response.
206
		PaymentResponseHelper::update_payment( $payment, $response );
207
208
		$result = array(
209
			'resultCode' => $response->get_result_code(),
210
		);
211
212
		// Return action if available.
213
		$action = $response->get_action();
214
215
		if ( null !== $action ) {
216
			$result['action'] = $action->get_json();
217
		}
218
219
		// Return refusal reason if available.
220
		$refusal_reason = $response->get_refusal_reason();
221
222
		if ( null !== $refusal_reason ) {
223
			$result['refusalReason'] = $refusal_reason;
224
		}
225
226
		return (object) $result;
227
	}
228
229
	/**
230
	 * REST API Adyen payment details handler.
231
	 *
232
	 * @param WP_REST_Request $request Request.
233
	 * @return object
234
	 * @throws \Exception Throws exception on Adyen service exception response.
235
	 */
236
	public function rest_api_adyen_payment_details( WP_REST_Request $request ) {
237
		$payment_id = $request->get_param( 'payment_id' );
238
239
		// Payment ID.
240
		if ( null === $payment_id ) {
241
			return new \WP_Error(
242
				'pronamic-pay-adyen-no-payment-id',
243
				__( 'No payment ID given in `payment_id` parameter.', 'pronamic_ideal' )
244
			);
245
		}
246
247
		$payment = \get_pronamic_payment( $payment_id );
248
249
		if ( null === $payment ) {
250
			return new \WP_Error(
251
				'pronamic-pay-adyen-payment-not-found',
252
				sprintf(
253
					/* translators: %s: payment ID */
254
					__( 'Could not find payment with ID `%s`.', 'pronamic_ideal' ),
255
					$payment_id
256
				),
257
				$payment_id
258
			);
259
		}
260
261
		// State data.
262
		$data = \json_decode( $request->get_body() );
263
264
		if ( null === $data ) {
265
			return new \WP_Error(
266
				'pronamic-pay-adyen-no-data',
267
				__( 'No data given in request body.', 'pronamic_ideal' )
268
			);
269
		}
270
271
		// Gateway.
272
		$config_id = $payment->get_config_id();
273
274
		if ( null === $config_id ) {
275
			return new \WP_Error(
276
				'pronamic-pay-adyen-no-config',
277
				__( 'No gateway configuration ID given in payment.', 'pronamic_ideal' )
278
			);
279
		}
280
281
		$gateway = Plugin::get_gateway( $config_id );
282
283
		if ( empty( $gateway ) ) {
284
			return new \WP_Error(
285
				'pronamic-pay-adyen-gateway-not-found',
286
				sprintf(
287
					/* translators: %s: Gateway configuration ID */
288
					__( 'Could not find gateway with ID `%s`.', 'pronamic_ideal' ),
289
					$config_id
290
				),
291
				$config_id
292
			);
293
		}
294
295
		if ( ! isset( $gateway->client ) ) {
296
			return new \WP_Error(
297
				'pronamic-pay-adyen-client-not-found',
298
				sprintf(
299
					/* translators: %s: Gateway configuration ID */
300
					__( 'Could not find client in gateway with ID `%s`.', 'pronamic_ideal' ),
301
					$config_id
302
				),
303
				$config_id
304
			);
305
		}
306
307
		// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Adyen JSON object.
308
		if ( ! isset( $data->paymentMethod->type ) ) {
309
			return new \WP_Error(
310
				'pronamic-pay-adyen-no-payment-method',
311
				__( 'No payment method given.', 'pronamic_ideal' )
312
			);
313
		}
314
315
		// Send additional payment details.
316
		$payment_details_request = new PaymentDetailsRequest();
317
318
		// Set payment data from original payment response.
319
		$payment_response = $payment->get_meta( 'adyen_payment_response' );
320
321
		if ( is_string( $payment_response ) && '' !== $payment_response ) {
322
			$payment_response = \json_decode( $payment_response );
323
324
			$payment_response = PaymentResponse::from_object( $payment_response );
325
326
			$payment_data = $payment_response->get_payment_data();
327
328
			$payment_details_request->set_payment_data( $payment_data );
329
		}
330
331
		try {
332
			if ( ! \is_callable( array( $gateway, 'send_payment_details' ) ) ) {
333
				return (object) array(
334
					'error' => __( 'Gateway does not support sending additional payment details.', 'pronamic_ideal' ),
335
				);
336
			}
337
338
			try {
339
				$response = $gateway->send_payment_details( $payment_details_request );
0 ignored issues
show
The method send_payment_details() does not exist on Pronamic\WordPress\Pay\Core\Gateway. It seems like you code against a sub-type of Pronamic\WordPress\Pay\Core\Gateway such as Pronamic\WordPress\Pay\G...ays\Adyen\DropInGateway. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

339
				/** @scrutinizer ignore-call */ 
340
    $response = $gateway->send_payment_details( $payment_details_request );
Loading history...
340
			} catch ( \Pronamic\WordPress\Pay\Gateways\Adyen\ServiceException $service_exception ) {
341
				$message = $service_exception->getMessage();
342
343
				$error_code = $service_exception->get_error_code();
344
345
				if ( ! empty( $error_code ) ) {
346
					$message = sprintf(
347
					/* translators: 1: error message, 2: error code */
348
						__( '%1$s (error %2$s)', 'pronamic_ideal' ),
349
						$service_exception->getMessage(),
350
						$error_code
351
					);
352
				}
353
354
				throw new \Exception( $message );
355
			}
356
357
			// Update payment status based on response.
358
			PaymentResponseHelper::update_payment( $payment, $response );
359
		} catch ( \Exception $e ) {
360
			$error = $e->getMessage();
361
362
			$error_code = $e->getCode();
363
364
			if ( ! empty( $error_code ) ) {
365
				$error = sprintf( '%s - %s', $error_code, $e->getMessage() );
366
			}
367
368
			return (object) array( 'error' => $error );
369
		}
370
371
		$result = array(
372
			'resultCode' => $response->get_result_code(),
373
		);
374
375
		// Return action if available.
376
		$action = $response->get_action();
377
378
		if ( null !== $action ) {
379
			$result['action'] = $action->get_json();
380
		}
381
382
		// Return refusal reason if available.
383
		$refusal_reason = $response->get_refusal_reason();
384
385
		if ( null !== $refusal_reason ) {
386
			$result['refusalReason'] = $refusal_reason;
387
		}
388
389
		return (object) $result;
390
	}
391
}
392