Completed
Push — master ( 394da4...31ec7c )
by Mike
10:43
created

WC_Gateway_Simplify_Commerce::process_standard_payments()   D

Complexity

Conditions 18
Paths 264

Size

Total Lines 68
Code Lines 36

Duplication

Lines 28
Ratio 41.18 %

Importance

Changes 0
Metric Value
cc 18
dl 28
loc 68
rs 4.2723
c 0
b 0
f 0
eloc 36
nc 264
nop 3

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
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * Simplify Commerce Gateway.
9
 *
10
 * @class 		WC_Gateway_Simplify_Commerce
11
 * @extends		WC_Payment_Gateway_CC
12
 * @since       2.2.0
13
 * @version		1.0.0
14
 * @package		WooCommerce/Classes/Payment
15
 * @author 		WooThemes
16
 */
17
class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
18
19
	/**
20
	 * Constructor.
21
	 */
22
	public function __construct() {
23
		$this->id                 = 'simplify_commerce';
24
		$this->method_title       = __( 'Simplify Commerce', 'woocommerce' );
25
		$this->method_description = __( 'Take payments via Simplify Commerce - uses simplify.js to create card tokens and the Simplify Commerce SDK. Requires SSL when sandbox is disabled.', 'woocommerce' );
26
		$this->new_method_label   = __( 'Use a new card', 'woocommerce' );
27
		$this->has_fields         = true;
28
		$this->supports           = array(
29
			'subscriptions',
30
			'products',
31
			'subscription_cancellation',
32
			'subscription_reactivation',
33
			'subscription_suspension',
34
			'subscription_amount_changes',
35
			'subscription_payment_method_change', // Subscriptions 1.n compatibility
36
			'subscription_payment_method_change_customer',
37
			'subscription_payment_method_change_admin',
38
			'subscription_date_changes',
39
			'multiple_subscriptions',
40
			'default_credit_card_form',
41
			'tokenization',
42
			'refunds',
43
			'pre-orders'
44
		);
45
		$this->view_transaction_url = 'https://www.simplify.com/commerce/app#/payment/%s';
46
47
		// Load the form fields
48
		$this->init_form_fields();
49
50
		// Load the settings.
51
		$this->init_settings();
52
53
		// Get setting values
54
		$this->title           = $this->get_option( 'title' );
55
		$this->description     = $this->get_option( 'description' );
56
		$this->enabled         = $this->get_option( 'enabled' );
57
		$this->mode            = $this->get_option( 'mode', 'standard' );
58
		$this->modal_color     = $this->get_option( 'modal_color', '#a46497' );
59
		$this->sandbox         = $this->get_option( 'sandbox' );
60
		$this->public_key      = $this->sandbox == 'no' ? $this->get_option( 'public_key' ) : $this->get_option( 'sandbox_public_key' );
61
		$this->private_key     = $this->sandbox == 'no' ? $this->get_option( 'private_key' ) : $this->get_option( 'sandbox_private_key' );
62
63
		$this->init_simplify_sdk();
64
65
		// Hooks
66
		add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
67
		add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
68
		add_action( 'woocommerce_receipt_' . $this->id, array( $this, 'receipt_page' ) );
69
		add_action( 'woocommerce_api_wc_gateway_simplify_commerce', array( $this, 'return_handler' ) );
70
	}
71
72
	/**
73
	 * Init Simplify SDK.
74
	 */
75
	protected function init_simplify_sdk() {
76
		// Include lib
77
		require_once( 'includes/Simplify.php' );
78
79
		Simplify::$publicKey  = $this->public_key;
80
		Simplify::$privateKey = $this->private_key;
81
		Simplify::$userAgent  = 'WooCommerce/' . WC()->version;
82
	}
83
84
	/**
85
	 * Admin Panel Options.
86
	 * - Options for bits like 'title' and availability on a country-by-country basis.
87
	 */
88
	public function admin_options() {
89
		?>
90
		<h3><?php _e( 'Simplify Commerce by MasterCard', 'woocommerce' ); ?></h3>
91
92
		<?php if ( empty( $this->public_key ) ) : ?>
93
			<div class="simplify-commerce-banner updated">
94
				<img src="<?php echo WC()->plugin_url() . '/includes/gateways/simplify-commerce/assets/images/logo.png'; ?>" />
95
				<p class="main"><strong><?php _e( 'Getting started', 'woocommerce' ); ?></strong></p>
96
				<p><?php _e( 'Simplify Commerce is your merchant account and payment gateway all rolled into one. Choose Simplify Commerce as your WooCommerce payment gateway to get access to your money quickly with a powerful, secure payment engine backed by MasterCard.', 'woocommerce' ); ?></p>
97
98
				<p><a href="https://www.simplify.com/commerce/partners/woocommerce#/signup" target="_blank" class="button button-primary"><?php _e( 'Sign up for Simplify Commerce', 'woocommerce' ); ?></a> <a href="https://www.simplify.com/commerce/partners/woocommerce#/" target="_blank" class="button"><?php _e( 'Learn more', 'woocommerce' ); ?></a></p>
99
100
			</div>
101
		<?php else : ?>
102
			<p><?php _e( 'Simplify Commerce is your merchant account and payment gateway all rolled into one. Choose Simplify Commerce as your WooCommerce payment gateway to get access to your money quickly with a powerful, secure payment engine backed by MasterCard.', 'woocommerce' ); ?></p>
103
		<?php endif; ?>
104
105
		<?php $this->checks(); ?>
106
107
		<table class="form-table">
108
			<?php $this->generate_settings_html(); ?>
109
			<script type="text/javascript">
110
				jQuery( '#woocommerce_simplify_commerce_sandbox' ).on( 'change', function() {
111
					var sandbox    = jQuery( '#woocommerce_simplify_commerce_sandbox_public_key, #woocommerce_simplify_commerce_sandbox_private_key' ).closest( 'tr' ),
112
						production = jQuery( '#woocommerce_simplify_commerce_public_key, #woocommerce_simplify_commerce_private_key' ).closest( 'tr' );
113
114
					if ( jQuery( this ).is( ':checked' ) ) {
115
						sandbox.show();
116
						production.hide();
117
					} else {
118
						sandbox.hide();
119
						production.show();
120
					}
121
				}).change();
122
123
				jQuery( '#woocommerce_simplify_commerce_mode' ).on( 'change', function() {
124
					var color = jQuery( '#woocommerce_simplify_commerce_modal_color' ).closest( 'tr' );
125
126
					if ( 'standard' === jQuery( this ).val() ) {
127
						color.hide();
128
					} else {
129
						color.show();
130
					}
131
				}).change();
132
			</script>
133
		</table>
134
		<?php
135
	}
136
137
	/**
138
	 * Check if SSL is enabled and notify the user.
139
	 */
140
	public function checks() {
141
		if ( 'no' == $this->enabled ) {
142
			return;
143
		}
144
145
		// PHP Version
146
		if ( version_compare( phpversion(), '5.3', '<' ) ) {
147
			echo '<div class="error"><p>' . sprintf( __( 'Simplify Commerce Error: Simplify commerce requires PHP 5.3 and above. You are using version %s.', 'woocommerce' ), phpversion() ) . '</p></div>';
148
		}
149
150
		// Check required fields
151
		elseif ( ! $this->public_key || ! $this->private_key ) {
152
			echo '<div class="error"><p>' . __( 'Simplify Commerce Error: Please enter your public and private keys', 'woocommerce' ) . '</p></div>';
153
		}
154
155
		// Show message when using standard mode and no SSL on the checkout page
156
		elseif ( 'standard' == $this->mode && ! wc_checkout_is_https() ) {
157
			echo '<div class="error"><p>' . sprintf( __( 'Simplify Commerce is enabled, but the <a href="%s">force SSL option</a> is disabled; your checkout may not be secure! Please enable SSL and ensure your server has a valid SSL certificate - Simplify Commerce will only work in sandbox mode.', 'woocommerce'), admin_url( 'admin.php?page=wc-settings&tab=checkout' ) ) . '</p></div>';
158
		}
159
	}
160
161
	/**
162
	 * Check if this gateway is enabled.
163
	 *
164
	 * @return bool
165
	 */
166
	public function is_available() {
167
		if ( 'yes' !== $this->enabled ) {
168
			return false;
169
		}
170
171
		if ( 'standard' === $this->mode && 'yes' !== $this->sandbox && ! wc_checkout_is_https() ) {
172
			return false;
173
		}
174
175
		if ( ! $this->public_key || ! $this->private_key ) {
176
			return false;
177
		}
178
179
		return true;
180
	}
181
182
	/**
183
	 * Initialise Gateway Settings Form Fields.
184
	 */
185
	public function init_form_fields() {
186
		$this->form_fields = array(
187
			'enabled' => array(
188
				'title'       => __( 'Enable/Disable', 'woocommerce' ),
189
				'label'       => __( 'Enable Simplify Commerce', 'woocommerce' ),
190
				'type'        => 'checkbox',
191
				'description' => '',
192
				'default'     => 'no'
193
			),
194
			'title' => array(
195
				'title'       => __( 'Title', 'woocommerce' ),
196
				'type'        => 'text',
197
				'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
198
				'default'     => __( 'Credit card', 'woocommerce' ),
199
				'desc_tip'    => true
200
			),
201
			'description' => array(
202
				'title'       => __( 'Description', 'woocommerce' ),
203
				'type'        => 'text',
204
				'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce' ),
205
				'default'     => 'Pay with your credit card via Simplify Commerce by MasterCard.',
206
				'desc_tip'    => true
207
			),
208
			'mode' => array(
209
				'title'       => __( 'Payment Mode', 'woocommerce' ),
210
				'label'       => __( 'Enable Hosted Payments', 'woocommerce' ),
211
				'type'        => 'select',
212
				'description' => sprintf( __( 'Standard will display the credit card fields on your store (SSL required). %1$s Hosted Payments will display a Simplify Commerce modal dialog on your store (if SSL) or will redirect the customer to Simplify Commerce hosted page (if not SSL). %1$s Note: Hosted Payments need a new API Key pair with the hosted payments flag selected. %2$sFor more details check the Simplify Commerce docs%3$s.', 'woocommerce' ), '<br />', '<a href="https://simplify.desk.com/customer/portal/articles/1792405-how-do-i-enable-hosted-payments" target="_blank">', '</a>' ),
213
				'default'     => 'standard',
214
				'options'     => array(
215
					'standard' => __( 'Standard', 'woocommerce' ),
216
					'hosted'   => __( 'Hosted Payments', 'woocommerce' )
217
				)
218
			),
219
			'modal_color' => array(
220
				'title'       => __( 'Modal Color', 'woocommerce' ),
221
				'type'        => 'color',
222
				'description' => __( 'Set the color of the buttons and titles on the modal dialog.', 'woocommerce' ),
223
				'default'     => '#a46497',
224
				'desc_tip'    => true
225
			),
226
			'sandbox' => array(
227
				'title'       => __( 'Sandbox', 'woocommerce' ),
228
				'label'       => __( 'Enable Sandbox Mode', 'woocommerce' ),
229
				'type'        => 'checkbox',
230
				'description' => __( 'Place the payment gateway in sandbox mode using sandbox API keys (real payments will not be taken).', 'woocommerce' ),
231
				'default'     => 'yes'
232
			),
233
			'sandbox_public_key' => array(
234
				'title'       => __( 'Sandbox Public Key', 'woocommerce' ),
235
				'type'        => 'text',
236
				'description' => __( 'Get your API keys from your Simplify account: Settings > API Keys.', 'woocommerce' ),
237
				'default'     => '',
238
				'desc_tip'    => true
239
			),
240
			'sandbox_private_key' => array(
241
				'title'       => __( 'Sandbox Private Key', 'woocommerce' ),
242
				'type'        => 'text',
243
				'description' => __( 'Get your API keys from your Simplify account: Settings > API Keys.', 'woocommerce' ),
244
				'default'     => '',
245
				'desc_tip'    => true
246
			),
247
			'public_key' => array(
248
				'title'       => __( 'Public Key', 'woocommerce' ),
249
				'type'        => 'text',
250
				'description' => __( 'Get your API keys from your Simplify account: Settings > API Keys.', 'woocommerce' ),
251
				'default'     => '',
252
				'desc_tip'    => true
253
			),
254
			'private_key' => array(
255
				'title'       => __( 'Private Key', 'woocommerce' ),
256
				'type'        => 'text',
257
				'description' => __( 'Get your API keys from your Simplify account: Settings > API Keys.', 'woocommerce' ),
258
				'default'     => '',
259
				'desc_tip'    => true
260
			),
261
		);
262
	}
263
264
	/**
265
	 * Payment form on checkout page.
266
	 */
267
	public function payment_fields() {
268
		$description = $this->get_description();
269
270
		if ( 'yes' == $this->sandbox ) {
271
			$description .= ' ' . sprintf( __( 'TEST MODE ENABLED. Use a test card: %s', 'woocommerce' ), '<a href="https://www.simplify.com/commerce/docs/tutorial/index#testing">https://www.simplify.com/commerce/docs/tutorial/index#testing</a>' );
272
		}
273
274
		if ( $description ) {
275
			echo wpautop( wptexturize( trim( $description ) ) );
276
		}
277
278
		if ( 'standard' == $this->mode ) {
279
			parent::payment_fields();
280
		}
281
	}
282
283
	/**
284
	 * Outputs scripts used for simplify payment.
285
	 */
286
	public function payment_scripts() {
287
		$load_scripts = false;
288
289
		if ( is_checkout() ) {
290
			$load_scripts = true;
291
		}
292
		if ( $this->is_available() ) {
293
			$load_scripts = true;
294
		}
295
296
		if ( false === $load_scripts ) {
297
			return;
298
		}
299
300
		wp_enqueue_script( 'simplify-commerce', 'https://www.simplify.com/commerce/v1/simplify.js', array( 'jquery' ), WC_VERSION, true );
301
		wp_enqueue_script( 'wc-simplify-commerce', WC()->plugin_url() . '/includes/gateways/simplify-commerce/assets/js/simplify-commerce.js', array( 'simplify-commerce', 'wc-credit-card-form' ), WC_VERSION, true );
302
		wp_localize_script( 'wc-simplify-commerce', 'Simplify_commerce_params', array(
303
			'key'           => $this->public_key,
304
			'card.number'   => __( 'Card Number', 'woocommerce' ),
305
			'card.expMonth' => __( 'Expiry Month', 'woocommerce' ),
306
			'card.expYear'  => __( 'Expiry Year', 'woocommerce' ),
307
			'is_invalid'    => __( 'is invalid', 'woocommerce' ),
308
			'mode'          => $this->mode,
309
			'is_ssl'        => is_ssl()
310
		) );
311
	}
312
313
	public function add_payment_method() {
314
		if ( empty ( $_POST['simplify_token'] ) ) {
315
			wc_add_notice( __( 'There was a problem adding this card.', 'woocommerce' ), 'error' );
316
			return;
317
		}
318
319
		$cart_token     = wc_clean( $_POST['simplify_token'] );
320
		$customer_token = $this->get_users_token();
321
		$current_user   = wp_get_current_user();
322
		$customer_info  = array(
323
			'email' => $current_user->user_email,
324
			'name'  => $current_user->display_name,
325
		);
326
327
		$token = $this->save_token( $customer_token, $cart_token, $customer_info );
328
		if ( is_null( $token ) ) {
329
			wc_add_notice( __( 'There was a problem adding this card.', 'woocommerce' ), 'error' );
330
			return;
331
		}
332
333
		return array(
334
			'result'   => 'success',
335
			'redirect' => wc_get_endpoint_url( 'payment-methods' ),
336
		);
337
	}
338
339
	/**
340
	 * Actualy saves a customer token to the database.
341
	 *
342
	 * @param  WC_Payment_Token   $customer_token Payment Token
343
	 * @param  string             $cart_token     CC Token
344
	 * @param  array              $customer_info  'email', 'name'
345
	 */
346
	public function save_token( $customer_token, $cart_token, $customer_info ) {
347
		if ( ! is_null( $customer_token ) ) {
348
			$customer = Simplify_Customer::findCustomer( $customer_token->get_token() );
349
			$updates = array( 'token' => $cart_token );
350
			$customer->setAll( $updates );
351
			$customer->updateCustomer();
352
			$customer = Simplify_Customer::findCustomer( $customer_token->get_token() ); // get updated customer with new set card
353
			$token = $customer_token;
354
		} else {
355
			$customer = Simplify_Customer::createCustomer( array(
356
				'token'     => $cart_token,
357
				'email'     => $customer_info['email'],
358
				'name'      => $customer_info['name'],
359
			) );
360
			$token = new WC_Payment_Token_CC();
361
			$token->set_token( $customer->id );
362
		}
363
364
		// If we were able to create an save our card, save the data on our side too
365
		if ( is_object( $customer ) && '' != $customer->id ) {
366
			$customer_properties = $customer->getProperties();
367
			$card = $customer_properties['card'];
368
			$token->set_gateway_id( $this->id );
369
			$token->set_card_type( strtolower( $card->type ) );
370
			$token->set_last4( $card->last4 );
371
			$expiry_month = ( 1 === strlen( $card->expMonth ) ? '0' . $card->expMonth : $card->expMonth );
372
			$token->set_expiry_month( $expiry_month );
373
			$token->set_expiry_year( '20' . $card->expYear );
374
			if ( is_user_logged_in() ) {
375
				$token->set_user_id( get_current_user_id() );
376
			}
377
			$token->save();
378
			return $token;
379
		}
380
381
		return null;
382
	}
383
384
	/**
385
	 * Process customer: updating or creating a new customer/saved CC
386
	 *
387
	 * @param  WC_Order           $order          Order object
388
	 * @param  WC_Payment_Token   $customer_token Payment Token
389
	 * @param  string             $cart_token     CC Token
390
	 */
391
	protected function process_customer( $order, $customer_token = null, $cart_token = '' ) {
392
		// Are we saving a new payment method?
393
		if ( is_user_logged_in() && isset( $_POST['wc-simplify_commerce-new-payment-method'] ) && true === (bool) $_POST['wc-simplify_commerce-new-payment-method'] ) {
394
			$customer_info = array(
395
				'email' => $order->billing_email,
396
				'name'  => trim( $order->get_formatted_billing_full_name() ),
397
			);
398
			$token = $this->save_token( $customer_token, $cart_token, $customer_info );
399
			if ( ! is_null( $token ) ) {
400
				$order->add_payment_token( $token );
401
			}
402
		}
403
	}
404
405
	/**
406
	 * Process standard payments.
407
	 *
408
	 * @param  WC_Order $order
409
	 * @param  string   $cart_token
410
	 * @uses   Simplify_ApiException
411
	 * @uses   Simplify_BadRequestException
412
	 * @return array
413
	 */
414
	protected function process_standard_payments( $order, $cart_token = '', $customer_token = '' ) {
415
		try {
416
417
			if ( empty( $cart_token ) && empty( $customer_token ) ) {
418
				$error_msg = __( 'Please make sure your card details have been entered correctly and that your browser supports JavaScript.', 'woocommerce' );
419
420
				if ( 'yes' == $this->sandbox ) {
421
					$error_msg .= ' ' . __( 'Developers: Please make sure that you\'re including jQuery and there are no JavaScript errors on the page.', 'woocommerce' );
422
				}
423
424
				throw new Simplify_ApiException( $error_msg );
425
			}
426
427
			// We need to figure out if we want to charge the card token (new unsaved token, no customer, etc)
428
			// or the customer token (just saved method, previously saved method)
429
			$pass_tokens = array();
430
431
			if ( ! empty ( $cart_token ) ) {
432
				$pass_tokens['token'] = $cart_token;
433
			}
434
435
			if ( ! empty ( $customer_token ) ) {
436
				$pass_tokens['customer'] = $customer_token;
437
				// Use the customer token only, since we already saved the (one time use) card token to the customer
438
				if ( isset( $_POST['wc-simplify_commerce-new-payment-method'] ) && true === (bool) $_POST['wc-simplify_commerce-new-payment-method'] ) {
439
					unset( $pass_tokens['token'] );
440
				}
441
			}
442
443
			// Did we create an account and save a payment method? We might need to use the customer token instead of the card token
444
			if ( isset( $_POST['createaccount'] ) && true === (bool) $_POST['createaccount'] && empty ( $customer_token ) ) {
445
				$user_token = $this->get_users_token();
446
				if ( ! is_null( $user_token ) ) {
447
					$pass_tokens['customer'] = $user_token->get_token();
448
					unset( $pass_tokens['token'] );
449
				}
450
			}
451
452
			$payment_response = $this->do_payment( $order, $order->get_total(), $pass_tokens );
453
454
			if ( is_wp_error( $payment_response ) ) {
455
				throw new Exception( $payment_response->get_error_message() );
456
			} else {
457
				// Remove cart
458
				WC()->cart->empty_cart();
459
460
				// Return thank you page redirect
461
				return array(
462
					'result'   => 'success',
463
					'redirect' => $this->get_return_url( $order )
464
				);
465
			}
466
467
		} catch ( Simplify_ApiException $e ) {
468
			if ( $e instanceof Simplify_BadRequestException && $e->hasFieldErrors() && $e->getFieldErrors() ) {
469
				foreach ( $e->getFieldErrors() as $error ) {
470
					wc_add_notice( $error->getFieldName() . ': "' . $error->getMessage() . '" (' . $error->getErrorCode() . ')', 'error' );
471
				}
472
			} else {
473
				wc_add_notice( $e->getMessage(), 'error' );
474
			}
475
476
			return array(
477
				'result'   => 'fail',
478
				'redirect' => ''
479
			);
480
		}
481
	}
482
483
 	/**
484
	 * do payment function.
485
	 *
486
	 * @param WC_order $order
487
	 * @param int $amount (default: 0)
488
	 * @uses  Simplify_BadRequestException
489
	 * @return bool|WP_Error
490
	 */
491
	public function do_payment( $order, $amount = 0, $token = array() ) {
492
		if ( $amount * 100 < 50 ) {
493
			return new WP_Error( 'simplify_error', __( 'Sorry, the minimum allowed order total is 0.50 to use this payment method.', 'woocommerce' ) );
494
		}
495
496
		try {
497
			// Charge the customer
498
			$data = array(
499
				'amount'              => $amount * 100, // In cents.
500
				'description'         => sprintf( __( '%s - Order #%s', 'woocommerce' ), esc_html( get_bloginfo( 'name', 'display' ) ), $order->get_order_number() ),
501
				'currency'            => strtoupper( get_woocommerce_currency() ),
502
				'reference'           => $order->id
503
			);
504
505
			$data = array_merge( $data, $token );
506
			$payment = Simplify_Payment::createPayment( $data );
507
508
		} catch ( Exception $e ) {
509
510
			$error_message = $e->getMessage();
511
512
			if ( $e instanceof Simplify_BadRequestException && $e->hasFieldErrors() && $e->getFieldErrors() ) {
513
				$error_message = '';
514
				foreach ( $e->getFieldErrors() as $error ) {
515
					$error_message .= ' ' . $error->getFieldName() . ': "' . $error->getMessage() . '" (' . $error->getErrorCode() . ')';
516
				}
517
			}
518
519
			$order->add_order_note( sprintf( __( 'Simplify payment error: %s', 'woocommerce' ), $error_message ) );
520
521
			return new WP_Error( 'simplify_payment_declined', $e->getMessage(), array( 'status' => $e->getCode() ) );
522
		}
523
524
		if ( 'APPROVED' == $payment->paymentStatus ) {
525
			// Payment complete
526
			$order->payment_complete( $payment->id );
527
528
			// Add order note
529
			$order->add_order_note( sprintf( __( 'Simplify payment approved (ID: %s, Auth Code: %s)', 'woocommerce' ), $payment->id, $payment->authCode ) );
530
531
			return true;
532
		} else {
533
			$order->add_order_note( __( 'Simplify payment declined', 'woocommerce' ) );
534
535
			return new WP_Error( 'simplify_payment_declined', __( 'Payment was declined - please try another card.', 'woocommerce' ) );
536
		}
537
	}
538
539
	/**
540
	 * Process standard payments.
541
	 *
542
	 * @param WC_Order $order
543
	 * @return array
544
	 */
545
	protected function process_hosted_payments( $order ) {
546
		return array(
547
			'result'   => 'success',
548
			'redirect' => $order->get_checkout_payment_url( true )
549
		);
550
	}
551
552
	protected function get_users_token() {
553
		$customer_token  = null;
554
		if ( is_user_logged_in() ) {
555
			$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id() ) ;
556
			foreach ( $tokens as $token ) {
557
				if ( $token->get_gateway_id() === $this->id ) {
558
					$customer_token = $token;
559
					break;
560
				}
561
			}
562
		}
563
		return $customer_token;
564
	}
565
566
	/**
567
	 * Process the payment.
568
	 *
569
	 * @param int $order_id
570
	 */
571
	public function process_payment( $order_id ) {
572
		$order = wc_get_order( $order_id );
573
574
		// Payment/CC form is hosted on Simplify
575
		if ( 'hosted' === $this->mode ) {
576
			return $this->process_hosted_payments( $order );
577
		}
578
579
		// New CC info was entered
580
		if ( isset( $_POST['simplify_token'] ) ) {
581
			$cart_token           = wc_clean( $_POST['simplify_token'] );
582
			$customer_token       = $this->get_users_token();
583
			$customer_token_value = ( ! is_null( $customer_token ) ? $customer_token->get_token() : '' );
584
			$this->process_customer( $order, $customer_token, $cart_token );
585
			return $this->process_standard_payments( $order, $cart_token, $customer_token_value );
586
		}
587
588
		// Possibly Create (or update) customer/save payment token, use an existing token, and then process the payment
589
		if ( isset( $_POST['wc-simplify_commerce-payment-token'] ) && 'new' !== $_POST['wc-simplify_commerce-payment-token'] ) {
590
			$token_id = wc_clean( $_POST['wc-simplify_commerce-payment-token'] );
591
			$token    = WC_Payment_Tokens::get( $token_id );
592
			if ( $token->get_user_id() !== get_current_user_id() ) {
593
				wc_add_notice( __( 'Please make sure your card details have been entered correctly and that your browser supports JavaScript.', 'woocommerce' ), 'error' );
594
				return;
595
			}
596
			$this->process_customer( $order, $token );
597
			return $this->process_standard_payments( $order, '', $token->get_token() );
598
		}
599
	}
600
601
	/**
602
	 * Hosted payment args.
603
	 *
604
	 * @param  WC_Order $order
605
	 *
606
	 * @return array
607
	 */
608
	protected function get_hosted_payments_args( $order ) {
609
		$args = apply_filters( 'woocommerce_simplify_commerce_hosted_args', array(
610
			'sc-key'          => $this->public_key,
611
			'amount'          => $order->order_total * 100,
612
			'reference'       => $order->id,
613
			'name'            => esc_html( get_bloginfo( 'name', 'display' ) ),
614
			'description'     => sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ),
615
			'receipt'         => 'false',
616
			'color'           => $this->modal_color,
617
			'redirect-url'    => WC()->api_request_url( 'WC_Gateway_Simplify_Commerce' ),
618
			'address'         => $order->billing_address_1 . ' ' . $order->billing_address_2,
619
			'address-city'    => $order->billing_city,
620
			'address-state'   => $order->billing_state,
621
			'address-zip'     => $order->billing_postcode,
622
			'address-country' => $order->billing_country,
623
			'operation'       => 'create.token',
624
		), $order->id );
625
626
		return $args;
627
	}
628
629
	/**
630
	 * Receipt page.
631
	 *
632
	 * @param  int $order_id
633
	 */
634
	public function receipt_page( $order_id ) {
635
		$order = wc_get_order( $order_id );
636
637
		echo '<p>' . __( 'Thank you for your order, please click the button below to pay with credit card using Simplify Commerce by MasterCard.', 'woocommerce' ) . '</p>';
638
639
		$args        = $this->get_hosted_payments_args( $order );
640
		$button_args = array();
641
		foreach ( $args as $key => $value ) {
642
			$button_args[] = 'data-' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
643
		}
644
645
		echo '<script type="text/javascript" src="https://www.simplify.com/commerce/simplify.pay.js"></script>
646
			<button class="button alt" id="simplify-payment-button" ' . implode( ' ', $button_args ) . '>' . __( 'Pay Now', 'woocommerce' ) . '</button> <a class="button cancel" href="' . esc_url( $order->get_cancel_order_url() ) . '">' . __( 'Cancel order &amp; restore cart', 'woocommerce' ) . '</a>
647
			';
648
	}
649
650
	/**
651
	 * Return handler for Hosted Payments.
652
	 */
653
	public function return_handler() {
654
		@ob_clean();
655
		header( 'HTTP/1.1 200 OK' );
656
657
		if ( isset( $_REQUEST['reference'] ) && isset( $_REQUEST['paymentId'] ) && isset( $_REQUEST['signature'] ) ) {
658
			$signature = strtoupper( md5( $_REQUEST['amount'] . $_REQUEST['reference'] . $_REQUEST['paymentId'] . $_REQUEST['paymentDate'] . $_REQUEST['paymentStatus'] . $this->private_key ) );
659
			$order_id  = absint( $_REQUEST['reference'] );
660
			$order     = wc_get_order( $order_id );
661
662
			if ( $signature === $_REQUEST['signature'] ) {
663
				$order_complete = $this->process_order_status( $order, $_REQUEST['paymentId'], $_REQUEST['paymentStatus'], $_REQUEST['paymentDate'] );
664
665
				if ( ! $order_complete ) {
666
					$order->update_status( 'failed', __( 'Payment was declined by Simplify Commerce.', 'woocommerce' ) );
667
				}
668
669
				wp_redirect( $this->get_return_url( $order ) );
670
				exit();
671
			}
672
		}
673
674
		wp_redirect( wc_get_page_permalink( 'cart' ) );
675
		exit();
676
	}
677
678
	/**
679
	 * Process the order status.
680
	 *
681
	 * @param  WC_Order $order
682
	 * @param  string   $payment_id
683
	 * @param  string   $status
684
	 * @param  string   $auth_code
685
	 *
686
	 * @return bool
687
	 */
688
	public function process_order_status( $order, $payment_id, $status, $auth_code ) {
689
		if ( 'APPROVED' == $status ) {
690
			// Payment complete
691
			$order->payment_complete( $payment_id );
692
693
			// Add order note
694
			$order->add_order_note( sprintf( __( 'Simplify payment approved (ID: %s, Auth Code: %s)', 'woocommerce' ), $payment_id, $auth_code ) );
695
696
			// Remove cart
697
			WC()->cart->empty_cart();
698
699
			return true;
700
		}
701
702
		return false;
703
	}
704
705
	/**
706
	 * Process refunds.
707
	 * WooCommerce 2.2 or later.
708
	 *
709
	 * @param  int $order_id
710
	 * @param  float $amount
711
	 * @param  string $reason
712
	 * @uses   Simplify_ApiException
713
	 * @uses   Simplify_BadRequestException
714
	 * @return bool|WP_Error
715
	 */
716
	public function process_refund( $order_id, $amount = null, $reason = '' ) {
717
		try {
718
			$payment_id = get_post_meta( $order_id, '_transaction_id', true );
719
720
			$refund = Simplify_Refund::createRefund( array(
721
				'amount'    => $amount * 100, // In cents.
722
				'payment'   => $payment_id,
723
				'reason'    => $reason,
724
				'reference' => $order_id
725
			) );
726
727
			if ( 'APPROVED' == $refund->paymentStatus ) {
728
				return true;
729
			} else {
730
				throw new Simplify_ApiException( __( 'Refund was declined.', 'woocommerce' ) );
731
			}
732
733
		} catch ( Simplify_ApiException $e ) {
734
			if ( $e instanceof Simplify_BadRequestException && $e->hasFieldErrors() && $e->getFieldErrors() ) {
735
				foreach ( $e->getFieldErrors() as $error ) {
736
					return new WP_Error( 'simplify_refund_error', $error->getFieldName() . ': "' . $error->getMessage() . '" (' . $error->getErrorCode() . ')' );
737
				}
738
			} else {
739
				return new WP_Error( 'simplify_refund_error', $e->getMessage() );
740
			}
741
		}
742
743
		return false;
744
	}
745
746
	/**
747
	 * Get gateway icon.
748
	 *
749
	 * @access public
750
	 * @return string
751
	 */
752
	public function get_icon() {
753
		$icon  = '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/visa.svg' ) . '" alt="Visa" width="32" />';
754
		$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/mastercard.svg' ) . '" alt="MasterCard" width="32" />';
755
		$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/discover.svg' ) . '" alt="Discover" width="32" />';
756
		$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/amex.svg' ) . '" alt="Amex" width="32" />';
757
		$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/jcb.svg' ) . '" alt="JCB" width="32" />';
758
759
		return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
760
	}
761
}
762