Completed
Push — master ( 9fc190...0178ed )
by Chris
01:26
created

EDU_SveaWebPay::handle_cancelled_payment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
defined( 'ABSPATH' ) or die( 'This plugin must be run within the scope of WordPress.' );
3
4
require_once( __DIR__ . '/class-edu-sveawebpay-config.php' );
5
6
use Svea\WebPay\WebPay;
7
use Svea\WebPay\WebPayItem;
8
use Svea\WebPay\Config\ConfigurationService;
9
use Svea\WebPay\Response\SveaResponse;
10
11
if ( ! class_exists( 'EDU_SveaWebPay' ) ):
12
13
	/**
14
	 * EDU_SveaWebPay integrates EduAdmin-WordPress plugin with SveaWebPay as payment gateway
15
	 */
16
	class EDU_SveaWebPay extends EDU_Integration {
17
		/**
18
		 * Constructor
19
		 */
20
		public function __construct() {
21
			$this->id          = 'eduadmin-sveawebpay';
22
			$this->displayName = __( 'Svea Webpay (Checkout)', 'eduadmin-sveawebpay' );
23
			$this->description = '';
24
			$this->type        = 'payment';
25
26
			$this->init_form_fields();
27
			$this->init_settings();
28
29
			add_action( 'eduadmin-checkpaymentplugins', array( $this, 'intercept_booking' ) );
30
			add_action( 'eduadmin-processbooking', array( $this, 'process_booking' ) );
31
			add_action( 'eduadmin-bookingcompleted', array( $this, 'process_svearesponse' ) );
32
			add_action( 'wp_loaded', array( $this, 'process_paymentstatus' ) );
33
34
			add_shortcode( 'eduadmin-svea-testpage', array( $this, 'test_page' ) );
35
		}
36
37
		/**
38
		 * @param $attributes
39
		 */
40
		public function test_page( $attributes ) {
41
			$attributes = shortcode_atts(
42
				array(
43
					'bookingid'          => 0,
44
					'programmebookingid' => 0,
45
				),
46
				normalize_empty_atts( $attributes ),
47
				'test_page'
48
			);
49
50
			if ( $attributes['bookingid'] > 0 ) {
51
				$event_booking = EDUAPI()->OData->Bookings->GetItem(
52
					$attributes['bookingid'],
53
					null,
54
					'Customer($select=CustomerId;),ContactPerson($select=PersonId;),OrderRows',
55
					false
56
				);
57
			} elseif ( $attributes['programmebookingid'] > 0 ) {
58
				$event_booking = EDUAPI()->OData->ProgrammeBookings->GetItem(
59
					$attributes['programmebookingid'],
60
					null,
61
					'Customer($select=CustomerId;),ContactPerson($select=PersonId;),OrderRows',
62
					false
63
				);
64
			}
65
66
			$_customer = EDUAPI()->OData->Customers->GetItem(
67
				$event_booking['Customer']['CustomerId'],
0 ignored issues
show
Bug introduced by
The variable $event_booking does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
68
				null,
69
				"BillingInfo",
70
				false
71
			);
72
73
			$_contact = EDUAPI()->OData->Persons->GetItem(
74
				$event_booking['ContactPerson']['PersonId'],
75
				null,
76
				null,
77
				false
78
			);
79
80
			$ebi = new EduAdmin_BookingInfo( $event_booking, $_customer, $_contact );
81
82
			if ( ! empty( EDU()->session['svea-order-id'] ) && ! empty( $_GET['svea_order_id'] ) && EDU()->session['svea-order-id'] === $_GET['svea_order_id'] ) {
83
				do_action( 'eduadmin-bookingcompleted', $ebi );
84
			} else {
85
				do_action( 'eduadmin-processbooking', $ebi );
86
			}
87
		}
88
89
90
		/**
91
		 * @param EduAdmin_BookingInfo|null $ebi
92
		 */
93
		public function intercept_booking( $ebi = null ) {
94
			if ( 'no' === $this->get_option( 'enabled', 'no' ) ) {
95
				return;
96
			}
97
98
			if ( ! empty( $_POST['act'] ) && ( 'bookCourse' === $_POST['act'] || 'bookProgramme' === $_POST['act'] ) ) {
99
				$ebi->NoRedirect = true;
100
			}
101
		}
102
103
		/**
104
		 * Initializes the settingsfields
105
		 */
106
		public function init_form_fields() {
107
			$this->setting_fields = array(
108
				'enabled'         => array(
109
					'title'       => __( 'Enabled', 'eduadmin-sveawebpay' ),
110
					'type'        => 'checkbox',
111
					'description' => __( 'Enables/Disables the integration with Svea WebPay', 'eduadmin-sveawebpay' ),
112
					'default'     => 'no',
113
				),
114
				'testrun'         => array(
115
					'title'       => __( 'Sandbox mode', 'eduadmin-sveawebpay' ),
116
					'type'        => 'checkbox',
117
					'description' => __( 'Activate sandbox mode', 'eduadmin-sveawebpay' ),
118
					'default'     => 'no',
119
				),
120
				'merchant_key'    => array(
121
					'title'       => __( 'Merchant key', 'eduadmin-sveawebpay' ),
122
					'type'        => 'text',
123
					'description' => __( 'Please enter your merchant key from Svea WebPay.', 'eduadmin-sveawebpay' ),
124
					'placeholder' => __( 'Merchant key', 'eduadmin-sveawebpay' ),
125
				),
126
				'merchant_secret' => array(
127
					'title'       => __( 'Merchant secret', 'eduadmin-sveawebpay' ),
128
					'type'        => 'password',
129
					'description' => __( 'Please enter your merchant secret from Svea WebPay', 'eduadmin-sveawebpay' ),
130
					'placeholder' => __( 'Merchant secret', 'eduadmin-sveawebpay' ),
131
				),
132
			);
133
		}
134
135
		/**
136
		 *
137
		 */
138
		public function process_svearesponse() {
139
			if ( 'no' === $this->get_option( 'enabled', 'no' ) ) {
140
				return;
141
			}
142
143 View Code Duplication
			if ( isset( $_REQUEST['edu-thankyou'] ) && isset( $_REQUEST['svea'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
				$booking_id           = intval( $_GET['booking_id'] );
145
				$programme_booking_id = intval( $_GET['programme_booking_id'] );
146
147
				$deleted = $this->update_booking( intval( EDU()->session['svea-order-id'] ), $booking_id, $programme_booking_id );
148
149
				EDU()->session['svea-order-id'] = null;
150
151
				if ( $deleted ) {
152
					$this->handle_cancelled_payment();
153
				}
154
			}
155
		}
156
157
		/**
158
		 * @param $ebi EduAdmin_BookingInfo|null $bookingInfo
159
		 */
160
		public function process_booking( $ebi = null ) {
161
			if ( 'no' === $this->get_option( 'enabled', 'no' ) ) {
162
				return;
163
			}
164
165
			$ebi->NoRedirect = true;
166
167
			if ( empty( $_GET['svea_order_id'] ) || empty( EDU()->session['svea-order-id'] ) ) {
168
				$checkout = $this->create_checkout( $ebi );
169
170
				$snippet = $checkout['Gui']['Snippet'];
171
				echo "<div>{$snippet}</div>";
172
			}
173
		}
174
175
		/**
176
		 * @param $ebi EduAdmin_BookingInfo|null
177
		 *
178
		 * @returns array
179
		 */
180
		public function create_checkout( $ebi ) {
181
			$countries = EDUAPI()->OData->Countries->Search()['value'];
182
183
			$selectedCountry = 'SE';
184
			$selectedLocale  = 'sv-SE';
185
186
			$invoiceCountry = $ebi->Customer['BillingInfo']['Country'];
187
			if ( empty( $invoiceCountry ) ) {
188
				$invoiceCountry = $ebi->Customer['Country'];
189
			}
190
191
			foreach ( $countries as $country ) {
192
				if ( $invoiceCountry == $country['CountryName'] ) {
193
					$selectedCountry = $country['CountryCode'];
194
					if ( ! empty( $country['CultureName'] ) ) {
195
						$selectedLocale = $country['CultureName'];
196
					}
197
					break;
198
				}
199
			}
200
201
			$booking_id           = 0;
202
			$programme_booking_id = 0;
203
204
			$reference_id = 0;
205
206
			$_event = null;
0 ignored issues
show
Unused Code introduced by
$_event is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
207
208
			$eventName = '';
209
210 View Code Duplication
			if ( ! empty( $ebi->EventBooking['BookingId'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
211
				$booking_id   = intval( $ebi->EventBooking['BookingId'] );
212
				$reference_id = $booking_id;
213
214
				$_event = EDUAPI()->OData->Events->GetItem( $ebi->EventBooking['EventId'], null );
215
216
				$eventName = $_event['EventName'];
217
			}
218
219 View Code Duplication
			if ( ! empty( $ebi->EventBooking['ProgrammeBookingId'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
220
				$programme_booking_id = intval( $ebi->EventBooking['ProgrammeBookingId'] );
221
				$reference_id         = $programme_booking_id;
222
223
				$_event = EDUAPI()->OData->ProgrammeStarts->GetItem( $ebi->EventBooking['ProgrammeStartId'] );
224
225
				$eventName = $_event['ProgrammeStartName'];
226
			}
227
228
			$currency = EDU()->get_option( 'eduadmin-currency', 'SEK' );
229
230 View Code Duplication
			if ( 'no' !== $this->get_option( 'testrun', 'no' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
231
				$wpConfig = new EduSveaWebPayTestConfig( $this );
232
			} else {
233
				$wpConfig = new EduSveaWebPayProductionConfig( $this );
234
			}
235
236
			$wpOrder = WebPay::checkout( $wpConfig );
237
238
			$orderRow = WebPayItem::orderRow();
239
			$orderRow->setName( $eventName );
240
			$orderRow->setQuantity( 1 );
241
242
			$vatPercent = ( $ebi->EventBooking['VatSum'] / $ebi->EventBooking['TotalPriceExVat'] ) * 100;
243
			$orderRow->setVatPercent( $vatPercent );
244
			$orderRow->setAmountIncVat( (float) $ebi->EventBooking['TotalPriceIncVat'] );
245
246
			$customer = WebPayItem::companyCustomer();
247
248
			$customerName  = ! empty( $ebi->Customer['BillingInfo']['InvoiceName'] ) ? $ebi->Customer['BillingInfo']['InvoiceName'] : $ebi->Customer['CustomerName'];
249
			$streetAddress = ! empty( $ebi->Customer['BillingInfo']['Address'] ) ? $ebi->Customer['BillingInfo']['Address'] : $ebi->Customer['Address'];
250
			$zipCode       = ! empty( $ebi->Customer['BillingInfo']['Zip'] ) ? $ebi->Customer['BillingInfo']['Zip'] : $ebi->Customer['Zip'];
251
			$city          = $ebi->Customer['BillingInfo']['City'] ? $ebi->Customer['BillingInfo']['City'] : $ebi->Customer['City'];
252
			$phone         = $ebi->Customer['Phone'];
253
			$email         = ! empty( $ebi->Customer['BillingInfo']['Email'] ) ? $ebi->Customer['BillingInfo']['Email'] : $ebi->Customer['Email'];
254
255
			$customer->setCompanyName( $customerName );
256
			$customer->setStreetAddress( $streetAddress );
257
			$customer->setZipCode( $zipCode );
258
			$customer->setLocality( $city );
259
260
			if ( ! empty( $phone ) ) {
261
				$customer->setPhoneNumber( $phone );
262
				$phonePreset = WebPayItem::presetValue()
263
				                         ->setTypeName( \Svea\WebPay\Checkout\Model\PresetValue::PHONE_NUMBER )
264
				                         ->setValue( $phone )
265
				                         ->setIsReadonly( false );
266
				$wpOrder->addPresetValue( $phonePreset );
267
			}
268
			$customer->setEmail( $email );
269
270
			$zipPreset = WebPayItem::presetValue()
271
			                       ->setTypeName( \Svea\WebPay\Checkout\Model\PresetValue::POSTAL_CODE )
272
			                       ->setValue( $zipCode )
273
			                       ->setIsReadonly( false );
274
			$wpOrder->addPresetValue( $zipPreset );
275
276
			$emailPreset = WebPayItem::presetValue()
277
			                         ->setTypeName( \Svea\WebPay\Checkout\Model\PresetValue::EMAIL_ADDRESS )
278
			                         ->setValue( $email )
279
			                         ->setIsReadonly( false );
280
			$wpOrder->addPresetValue( $emailPreset );
281
282
			$current_url = esc_url( "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}" );
283
284
			$defaultThankYou = add_query_arg(
285
				array(
286
					'edu-thankyou'         => $reference_id,
287
					'svea'                 => '1',
288
					'booking_id'           => $booking_id,
289
					'programme_booking_id' => $programme_booking_id,
290
					'edu-valid-form'       => wp_create_nonce( 'edu-booking-confirm' ),
291
					'act'                  => 'paymentCompleted',
292
				),
293
				@get_page_link( get_option( 'eduadmin-thankYouPage', '/' ) )
294
			);
295
296
			$defaultCancel = add_query_arg(
297
				array(
298
					'edu-thankyou'         => $reference_id,
299
					'svea'                 => '1',
300
					'booking_id'           => $booking_id,
301
					'programme_booking_id' => $programme_booking_id,
302
					'status'               => 'cancel'
303
				),
304
				$current_url
305
			);
306
307
			$defaultPushUrl = add_query_arg(
308
				array(
309
					'edu-thankyou'         => $reference_id,
310
					'svea'                 => '1',
311
					'booking_id'           => $booking_id,
312
					'programme_booking_id' => $programme_booking_id,
313
					'svea_order_id'        => '{checkout.order.uri}',
314
					'status'               => 'push'
315
				),
316
				$current_url
317
			);
318
319
			$defaultTermsUrl = get_option( 'eduadmin-bookingTermsLink' );
320
321
			$wpBuild = $wpOrder
322
				->setCurrency( $currency )
323
				->setCountryCode( $selectedCountry )
324
				->setClientOrderNumber( $reference_id )
325
				->addOrderRow( $orderRow )
326
				->setLocale( $selectedLocale )
327
				->setTermsUri( $defaultTermsUrl )
328
				->setConfirmationUri( $defaultThankYou )
329
				->setPushUri( $defaultPushUrl )
330
				->setCheckoutUri( $defaultCancel ); // We have no "checkout"-url.. So we just cancel the booking instead.
331
			$wpForm  = $wpBuild->createOrder();
332
333
			EDU()->session['svea-order-id'] = $wpForm['OrderId'];
334
335
			return $wpForm;
336
		}
337
338
		public function process_paymentstatus() {
339
			if ( ! empty( $_GET['svea_order_id'] ) && intval( $_GET['svea_order_id'] ) != 0 && ! empty( $_GET['status'] ) ) {
340
341
				$booking_id           = intval( $_GET['booking_id'] );
342
				$programme_booking_id = intval( $_GET['programme_booking_id'] );
343
344
				$this->update_booking( intval( $_GET['svea_order_id'] ), $booking_id, $programme_booking_id );
345
346
				exit( 0 );
347
			}
348
349 View Code Duplication
			if ( isset( $_REQUEST['edu-thankyou'] ) && isset( $_REQUEST['svea'] ) && ! empty( $_GET['status'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
350
				$booking_id           = intval( $_GET['booking_id'] );
351
				$programme_booking_id = intval( $_GET['programme_booking_id'] );
352
353
				$deleted = $this->update_booking( intval( EDU()->session['svea-order-id'] ), $booking_id, $programme_booking_id );
354
355
				EDU()->session['svea-order-id'] = null;
356
357
				if ( $deleted ) {
358
					$this->handle_cancelled_payment();
359
				}
360
			}
361
		}
362
363
		private function handle_cancelled_payment() {
364
			@wp_redirect( get_home_url() );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
365
			wp_add_inline_script( 'edu-svea-redirecthome', "location.href = '" . esc_js( get_home_url() ) . "';" );
366
			wp_enqueue_script( 'edu-svea-redirecthome', false, array( 'jquery' ) );
367
			exit( 0 );
368
		}
369
370
		/**
371
		 * @param $order_id numeric SVEA WebPay OrderId
372
		 * @param $booking_id
373
		 * @param $programme_booking_id
374
		 *
375
		 * @return bool If the booking was deleted, due to cancellation
376
		 * @throws \Svea\WebPay\BuildOrder\Validator\ValidationException
377
		 */
378
		private function update_booking( $order_id, $booking_id, $programme_booking_id ) {
379 View Code Duplication
			if ( 'no' !== $this->get_option( 'testrun', 'no' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
380
				$wpConfig = new EduSveaWebPayTestConfig( $this );
381
			} else {
382
				$wpConfig = new EduSveaWebPayProductionConfig( $this );
383
			}
384
385
			$wpOrder = WebPay::checkout( $wpConfig );
386
			$wpOrder->setCheckoutOrderId( $order_id );
387
388
			$order = $wpOrder->getOrder();
389
390
			$delete_booking = false;
391
392
			$patch_booking                  = new stdClass();
393
			$patch_booking->PaymentMethodId = 2;
394
395
			if ( 'Cancelled' === $order['Status'] ) {
396
				$patch_booking->Paid = false;
397
				$delete_booking      = true;
398
			} else if ( 'Final' === $order['Status'] ) {
399
				$patch_booking->Paid = true;
400
			} else if ( 'Created' === $order['Status'] ) {
401
				$patch_booking->Paid = false;
402
			}
403
404
			if ( isset( $_GET['status'] ) && 'cancel' === $_GET['status'] ) {
405
				$patch_booking->Paid = false;
406
				$delete_booking      = true;
407
			}
408
409
			if ( $booking_id > 0 ) {
410
				EDUAPI()->REST->Booking->PatchBooking(
411
					$booking_id,
412
					$patch_booking
413
				);
414
415
				if ( $delete_booking ) {
416
					EDUAPI()->REST->Booking->DeleteBooking( $booking_id );
417
				}
418
			}
419
420
			if ( $programme_booking_id > 0 ) {
421
422
				EDUAPI()->REST->ProgrammeBooking->PatchBooking(
423
					$programme_booking_id,
424
					$patch_booking
425
				);
426
427
				if ( $delete_booking ) {
428
					EDUAPI()->REST->ProgrammeBooking->DeleteBooking( $programme_booking_id );
429
				}
430
			}
431
432
			return $delete_booking;
433
		}
434
	}
435
436
endif;
437