Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like WC_Gateway_Simplify_Commerce often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use WC_Gateway_Simplify_Commerce, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
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 & 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 |