Passed
Push — feature/post-pay ( 4607f3...fb86fb )
by Remco
06:19
created

Gateway::start()   C

Complexity

Conditions 12
Paths 40

Size

Total Lines 111
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 156

Importance

Changes 0
Metric Value
cc 12
eloc 50
nc 40
nop 1
dl 0
loc 111
ccs 0
cts 63
cp 0
crap 156
rs 6.9666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
 * Gateway
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2018 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Gateways\OmniKassa2
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\OmniKassa2;
12
13
use Pronamic\WordPress\Pay\Core\Gateway as Core_Gateway;
14
use Pronamic\WordPress\Pay\Core\PaymentMethods;
15
use Pronamic\WordPress\Pay\Payments\Payment;
16
17
/**
18
 * Gateway
19
 *
20
 * @author  Remco Tolsma
21
 * @version 2.0.2
22
 * @since   1.0.0
23
 */
24
class Gateway extends Core_Gateway {
25
	/**
26
	 * Client.
27
	 *
28
	 * @var Client
29
	 */
30
	private $client;
31
32
	/**
33
	 * Constructs and initializes an OmniKassa 2.0 gateway.
34
	 *
35
	 * @param Config $config Config.
36
	 */
37
	public function __construct( Config $config ) {
38
		parent::__construct( $config );
39
40
		$this->set_method( self::METHOD_HTTP_REDIRECT );
41
42
		// Client.
43
		$this->client = new Client();
44
45
		$url = Client::URL_PRODUCTION;
46
47
		if ( self::MODE_TEST === $config->mode ) {
48
			$url = Client::URL_SANDBOX;
49
		}
50
51
		$this->client->set_url( $url );
52
		$this->client->set_refresh_token( $config->refresh_token );
53
		$this->client->set_signing_key( $config->signing_key );
54
	}
55
56
	/**
57
	 * Get supported payment methods.
58
	 *
59
	 * @see \Pronamic_WP_Pay_Gateway::get_supported_payment_methods()
60
	 * @return array
61
	 */
62
	public function get_supported_payment_methods() {
63
		return array(
64
			PaymentMethods::AFTERPAY,
65
			PaymentMethods::BANCONTACT,
66
			PaymentMethods::CREDIT_CARD,
67
			PaymentMethods::IDEAL,
68
			PaymentMethods::MAESTRO,
69
			PaymentMethods::PAYPAL,
70
		);
71
	}
72
73
	/**
74
	 * Start.
75
	 *
76
	 * @see Core_Gateway::start()
77
	 *
78
	 * @param Payment $payment Payment.
79
	 */
80
	public function start( Payment $payment ) {
81
		// Merchant order ID.
82
		$merchant_order_id = $payment->format_string( $this->config->order_id );
83
84
		$payment->set_meta( 'omnikassa_2_merchant_order_id', $merchant_order_id );
85
86
		// New order.
87
		$merchant_return_url = $payment->get_return_url();
88
		$merchant_return_url = apply_filters( 'pronamic_pay_omnikassa_2_merchant_return_url', $merchant_return_url );
89
90
		$order = new Order(
91
			$merchant_order_id,
92
			MoneyTransformer::transform( $payment->get_total_amount() ),
93
			$merchant_return_url
94
		);
95
96
		// Shipping address.
97
		$order->set_shipping_detail( AddressTransformer::transform( $payment->get_shipping_address() ) );
98
99
		// Billing address.
100
		$order->set_billing_detail( AddressTransformer::transform( $payment->get_billing_address() ) );
101
102
		// Customer information.
103
		$customer = $payment->get_customer();
104
105
		if ( null !== $customer ) {
106
			$order->set_language( strtoupper( $customer->get_language() ) );
107
108
			$customer_information = new CustomerInformation();
109
110
			$customer_information->set_email_address( $customer->get_email() );
111
			$customer_information->set_date_of_birth( $customer->get_birth_date() );
112
			$customer_information->set_gender( $customer->get_gender() );
113
			$customer_information->set_telephone_number( $customer->get_phone() );
114
115
			$order->set_customer_information( $customer_information );
116
		}
117
118
		// Payment brand.
119
		$payment_brand = PaymentBrands::transform( $payment->get_method() );
120
121
		$order->set_payment_brand( $payment_brand );
122
123
		if ( null !== $payment_brand ) {
124
			// Payment brand force should only be set if payment brand is not empty.
125
			$order->set_payment_brand_force( PaymentBrandForce::FORCE_ONCE );
126
		}
127
128
		// Description.
129
		$order->set_description( substr( $payment->get_description(), 0, 35 ) );
130
131
		// Lines.
132
		if ( null !== $payment->get_lines() ) {
133
			$order_items = $order->new_items();
134
135
			foreach ( $payment->get_lines() as $line ) {
136
				$item = $order_items->new_item(
137
					$line->get_name(),
138
					$line->get_quantity(),
139
					MoneyTransformer::transform( $line->get_total_amount() ),
140
					ProductCategories::transform( $line->get_type() )
141
				);
142
143
				$item->set_id( $line->get_id() );
144
145
				// Description.
146
				$description = $line->get_description();
147
148
				if ( empty( $description ) && PaymentBrands::AFTERPAY === $payment_brand ) {
149
					/*
150
					 * The `OrderItem.description` field is documentated as `0..1` (optional),
151
					 * but for AfterPay payments it is required.
152
					 *
153
					 * @link https://github.com/wp-pay-gateways/omnikassa-2/tree/feature/post-pay/documentation#error-5024
154
					 */
155
					$description = $line->get_name();
156
				}
157
158
				$item->set_description( $description );
159
160
				if ( null !== $line->get_tax_amount() ) {
161
					$item->set_tax( MoneyTransformer::transform( $line->get_tax_amount() ) );
162
				}
163
			}
164
		}
165
166
		// Maybe update access token.
167
		$this->maybe_update_access_token();
168
169
		// Handle errors.
170
		if ( $this->get_client_error() ) {
171
			return;
172
		}
173
174
		// Announce order.
175
		$response = $this->client->order_announce( $this->config, $order );
176
177
		// Handle errors.
178
		if ( $this->get_client_error() ) {
179
			return;
180
		}
181
182
		if ( false === $response ) {
183
			return;
184
		}
185
186
		if ( ! $response->is_valid( $this->config->signing_key ) ) {
187
			return;
188
		}
189
190
		$payment->set_action_url( $response->get_redirect_url() );
191
	}
192
193
	/**
194
	 * Update status of the specified payment.
195
	 *
196
	 * @param Payment $payment Payment.
197
	 */
198
	public function update_status( Payment $payment ) {
199
		if ( ! ReturnParameters::contains( $_GET ) ) { // WPCS: CSRF ok.
200
			return;
201
		}
202
203
		$parameters = ReturnParameters::from_array( $_GET ); // WPCS: CSRF ok.
204
205
		// Note.
206
		$note_values = array(
207
			'order_id'  => $parameters->get_order_id(),
208
			'status'    => $parameters->get_status(),
209
			'signature' => $parameters->get_signature(),
210
			'valid'     => $parameters->is_valid( $this->config->signing_key ) ? 'true' : 'false',
211
		);
212
213
		$note = '';
214
215
		$note .= '<p>';
216
		$note .= __( 'OmniKassa 2.0 return URL requested:', 'pronamic_ideal' );
217
		$note .= '</p>';
218
219
		$note .= '<dl>';
220
221
		foreach ( $note_values as $key => $value ) {
222
			$note .= sprintf( '<dt>%s</dt>', esc_html( $key ) );
223
			$note .= sprintf( '<dd>%s</dd>', esc_html( $value ) );
224
		}
225
226
		$note .= '</dl>';
227
228
		$payment->add_note( $note );
229
230
		// Validate.
231
		if ( ! $parameters->is_valid( $this->config->signing_key ) ) {
232
			return;
233
		}
234
235
		// Status.
236
		$pronamic_status = Statuses::transform( $parameters->get_status() );
237
238
		if ( null !== $pronamic_status ) {
239
			$payment->set_status( $pronamic_status );
240
		}
241
	}
242
243
	/**
244
	 * Handle notification.
245
	 *
246
	 * @param Notification $notification Notification.
247
	 *
248
	 * @return void
249
	 */
250
	public function handle_notification( Notification $notification ) {
251
		if ( ! $notification->is_valid( $this->config->signing_key ) ) {
252
			return;
253
		}
254
255
		switch ( $notification->get_event_name() ) {
256
			case 'merchant.order.status.changed':
257
				$this->handle_merchant_order_status_changed( $notification );
258
		}
259
	}
260
261
	/**
262
	 * Handle `merchant.order.status.changed` event.
263
	 *
264
	 * @param Notification $notification Notification.
265
	 *
266
	 * @return void
267
	 */
268
	private function handle_merchant_order_status_changed( Notification $notification ) {
269
		do {
270
			$order_results = $this->client->get_order_results( $notification->get_authentication() );
271
272
			if ( ! $order_results || $order_results->is_valid( $this->config->signing_key ) ) {
273
				return;
274
			}
275
276
			foreach ( $order_results as $order_result ) {
277
				$payment = get_pronamic_payment_by_meta( '_pronamic_payment_omnikassa_2_merchant_order_id', $order_result->get_merchant_order_id() );
278
279
				if ( empty( $payment ) ) {
280
					continue;
281
				}
282
283
				$payment->set_transaction_id( $order_result->get_omnikassa_order_id() );
284
285
				$pronamic_status = Statuses::transform( $order_result->get_order_status() );
286
287
				if ( null !== $pronamic_status ) {
288
					$payment->set_status( $pronamic_status );
289
				}
290
291
				// Note.
292
				$note = '';
293
294
				$note .= '<p>';
295
				$note .= __( 'OmniKassa 2.0 webhook URL requested:', 'pronamic_ideal' );
296
				$note .= '</p>';
297
				$note .= '<pre>';
298
				$note .= wp_json_encode( $order_result->get_json(), JSON_PRETTY_PRINT );
299
				$note .= '</pre>';
300
301
				$payment->add_note( $note );
302
303
				$payment->save();
304
			}
305
		} while ( $order_results->more_available() );
306
	}
307
308
	/**
309
	 * Maybe update access token.
310
	 *
311
	 * @return void
312
	 */
313
	private function maybe_update_access_token() {
314
		if ( $this->config->is_access_token_valid() ) {
315
			return;
316
		}
317
318
		$data = $this->client->get_access_token_data();
319
320
		if ( ! is_object( $data ) ) {
321
			return;
322
		}
323
324
		if ( isset( $data->token ) ) {
325
			$this->config->access_token = $data->token;
326
327
			update_post_meta( $this->config->post_id, '_pronamic_gateway_omnikassa_2_access_token', $data->token );
328
		}
329
330
		/*
331
		 * @codingStandardsIgnoreStart
332
		 *
333
		 * Ignore coding standards because of sniff WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
334
		 */
335
		if ( isset( $data->validUntil ) ) {
336
			$this->config->access_token_valid_until = $data->validUntil;
337
338
			update_post_meta(
339
				$this->config->post_id,
340
				'_pronamic_gateway_omnikassa_2_access_token_valid_until',
341
				$data->validUntil
342
			);
343
		}
344
		// @codingStandardsIgnoreEnd
345
	}
346
347
	/**
348
	 * Get client error.
349
	 *
350
	 * @return \WP_Error|bool
351
	 */
352
	private function get_client_error() {
353
		$error = $this->client->get_error();
354
355
		if ( is_wp_error( $error ) ) {
356
			$this->error = $error;
357
358
			return $error;
359
		}
360
361
		return false;
362
	}
363
}
364