rest_api_adyen_notifications()   B
last analyzed

Complexity

Conditions 7
Paths 7

Size

Total Lines 59
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 7

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 7
eloc 31
c 5
b 0
f 0
nc 7
nop 1
dl 0
loc 59
ccs 29
cts 29
cp 1
crap 7
rs 8.4906

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Notifications 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\Payments\PaymentStatus as PaymentStatus;
15
use WP_Error;
16
use WP_REST_Request;
17
18
/**
19
 * Notification controller
20
 *
21
 * @link https://docs.adyen.com/developers/api-reference/notifications-api#notificationrequest
22
 *
23
 * @author  Remco Tolsma
24
 * @version 1.0.5
25
 * @since   1.0.0
26
 */
27
class NotificationsController {
28
	/**
29
	 * Setup.
30
	 *
31
	 * @return void
32
	 */
33 7
	public function setup() {
34 7
		add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );
35 7
	}
36
37
	/**
38
	 * REST API init.
39
	 *
40
	 * @link https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
41
	 * @link https://developer.wordpress.org/reference/hooks/rest_api_init/
42
	 *
43
	 * @return void
44
	 */
45 10
	public function rest_api_init() {
46 10
		register_rest_route(
47 10
			Integration::REST_ROUTE_NAMESPACE,
48 10
			'/notifications',
49
			array(
50 10
				'methods'             => 'POST',
51 10
				'callback'            => array( $this, 'rest_api_adyen_notifications' ),
52 10
				'permission_callback' => array( $this, 'rest_api_adyen_permissions_check' ),
53
			)
54
		);
55 10
	}
56
57
	/**
58
	 * REST API Adyen permissions check.
59
	 *
60
	 * @link https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/#permissions-callback
61
	 *
62
	 * @param WP_REST_Request $request Request.
63
	 * @return true|WP_Error
64
	 */
65 6
	public function rest_api_adyen_permissions_check( WP_REST_Request $request ) {
66 6
		$username = get_option( 'pronamic_pay_adyen_notification_authentication_username' );
67 6
		$password = get_option( 'pronamic_pay_adyen_notification_authentication_password' );
68
69 6
		if ( empty( $username ) && empty( $password ) ) {
70 4
			return true;
71
		}
72
73 2
		$authorization = $request->get_header( 'Authorization' );
74
75
		/**
76
		 * Authorization header missing.
77
		 *
78
		 * @link https://basecamp.com/1810084/projects/10966871/todos/403544593
79
		 * @link https://github.com/WordPress/WordPress/blob/5.2/wp-includes/rest-api/class-wp-rest-request.php#L188-L208
80
		 * @link https://www.wp-pay.org/http-authorization-header-missing/
81
		 */
82 2
		if ( null === $authorization ) {
83
			return new WP_Error(
84
				'rest_forbidden_context',
85
				sprintf(
86
					/* translators: %s: Help URL. */
87
					__( 'HTTP Authorization header is missing, read %s for more information.', 'pronamic_ideal' ),
88
					'https://www.wp-pay.org/http-authorization-header-missing/'
89
				),
90
				array( 'status' => rest_authorization_required_code() )
91
			);
92
		}
93
94
		// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- Benign reason.
95 2
		if ( 'Basic ' . base64_encode( $username . ':' . $password ) === $authorization ) {
96 1
			return true;
97
		}
98
99 1
		return new WP_Error(
100 1
			'rest_forbidden_context',
101
			/* translators: Translate 'notification' the same as in the Adyen dashboard. */
102 1
			_x( 'Sorry, you are not allowed to post Adyen notifications.', 'Adyen', 'pronamic_ideal' ),
103 1
			array( 'status' => rest_authorization_required_code() )
104
		);
105
	}
106
107
	/**
108
	 * REST API Adyen notifications handler.
109
	 *
110
	 * @param WP_REST_Request $request Request.
111
	 * @return object
112
	 */
113 5
	public function rest_api_adyen_notifications( WP_REST_Request $request ) {
114 5
		$json = $request->get_body();
115
116 5
		$data = json_decode( $json );
117
118
		try {
119 5
			$notification_request = NotificationRequest::from_object( $data );
120 2
		} catch ( ValidationException $e ) {
121 2
			return new WP_Error(
122 2
				'adyen_invalid_notification',
123
				/* translators: Translate 'notification' the same as in the Adyen dashboard. */
124 2
				_x( 'Cannot parse JSON notification.', 'Adyen', 'pronamic_ideal' ),
125 2
				array( 'status' => 500 )
126
			);
127
		}
128
129 3
		foreach ( $notification_request->get_items() as $item ) {
130 3
			$payment = get_pronamic_payment( $item->get_merchant_reference() );
131
132 3
			if ( null === $payment ) {
133 2
				continue;
134
			}
135
136
			// Add note.
137 1
			$note = sprintf(
138 1
				'<p>%s</p>',
139 1
				sprintf(
140
					/* translators: %s: payment provider name */
141 1
					__( 'Webhook requested by %s.', 'pronamic_ideal' ),
142 1
					__( 'Adyen', 'pronamic_ideal' )
143
				)
144
			);
145
146 1
			$json = wp_json_encode( $item->get_json(), JSON_PRETTY_PRINT );
147
148 1
			if ( false !== $json ) {
149 1
				$note .= sprintf(
150 1
					'<pre>%s</pre>',
151
					$json
152
				);
153
			}
154
155 1
			$payment->add_note( $note );
156
157 1
			do_action( 'pronamic_pay_webhook_log_payment', $payment );
158
159
			// Authorization.
160 1
			if ( EventCode::AUTHORIZATION === $item->get_event_code() ) {
161 1
				$payment->set_status( $item->is_success() ? PaymentStatus::SUCCESS : PaymentStatus::FAILURE );
162
163 1
				$payment->save();
164
			}
165
		}
166
167
		$response = (object) array(
168 3
			'notificationResponse' => '[accepted]',
169
		);
170
171 3
		return $response;
172
	}
173
}
174