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 |