woocommerce /
woocommerce-gateway-stripe
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | if ( ! defined( 'ABSPATH' ) ) { |
||
| 3 | exit; |
||
| 4 | } |
||
| 5 | |||
| 6 | /** |
||
| 7 | * WC_Gateway_Stripe class. |
||
| 8 | * |
||
| 9 | * @extends WC_Payment_Gateway |
||
| 10 | */ |
||
| 11 | class WC_Gateway_Stripe extends WC_Payment_Gateway { |
||
| 12 | |||
| 13 | /** |
||
| 14 | * Constructor |
||
| 15 | */ |
||
| 16 | public function __construct() { |
||
| 17 | $this->id = 'stripe'; |
||
| 18 | $this->method_title = __( 'Stripe', 'woocommerce-gateway-stripe' ); |
||
| 19 | $this->method_description = __( 'Stripe works by adding credit card fields on the checkout and then sending the details to Stripe for verification.', 'woocommerce-gateway-stripe' ); |
||
| 20 | $this->has_fields = true; |
||
| 21 | $this->view_transaction_url = 'https://dashboard.stripe.com/payments/%s'; |
||
| 22 | $this->supports = array( |
||
| 23 | 'subscriptions', |
||
| 24 | 'products', |
||
| 25 | 'refunds', |
||
| 26 | 'subscription_cancellation', |
||
| 27 | 'subscription_reactivation', |
||
| 28 | 'subscription_suspension', |
||
| 29 | 'subscription_amount_changes', |
||
| 30 | 'subscription_payment_method_change', // Subs 1.n compatibility |
||
| 31 | 'subscription_payment_method_change_customer', |
||
| 32 | 'subscription_payment_method_change_admin', |
||
| 33 | 'subscription_date_changes', |
||
| 34 | 'multiple_subscriptions', |
||
| 35 | 'pre-orders', |
||
| 36 | ); |
||
| 37 | |||
| 38 | // Load the form fields |
||
| 39 | $this->init_form_fields(); |
||
| 40 | |||
| 41 | // Load the settings. |
||
| 42 | $this->init_settings(); |
||
| 43 | |||
| 44 | // Get setting values. |
||
| 45 | $this->title = $this->get_option( 'title' ); |
||
| 46 | $this->description = $this->get_option( 'description' ); |
||
| 47 | $this->enabled = $this->get_option( 'enabled' ); |
||
| 48 | $this->testmode = 'yes' === $this->get_option( 'testmode' ); |
||
| 49 | $this->capture = 'yes' === $this->get_option( 'capture', 'yes' ); |
||
| 50 | $this->stripe_checkout = 'yes' === $this->get_option( 'stripe_checkout' ); |
||
| 51 | $this->stripe_checkout_locale = $this->get_option( 'stripe_checkout_locale' ); |
||
| 52 | $this->stripe_checkout_image = $this->get_option( 'stripe_checkout_image', '' ); |
||
| 53 | $this->saved_cards = 'yes' === $this->get_option( 'saved_cards' ); |
||
| 54 | $this->secret_key = $this->testmode ? $this->get_option( 'test_secret_key' ) : $this->get_option( 'secret_key' ); |
||
| 55 | $this->publishable_key = $this->testmode ? $this->get_option( 'test_publishable_key' ) : $this->get_option( 'publishable_key' ); |
||
| 56 | $this->bitcoin = 'USD' === strtoupper( get_woocommerce_currency() ) && 'yes' === $this->get_option( 'stripe_bitcoin' ); |
||
| 57 | $this->logging = 'yes' === $this->get_option( 'logging' ); |
||
| 58 | |||
| 59 | if ( $this->stripe_checkout ) { |
||
| 60 | $this->order_button_text = __( 'Continue to payment', 'woocommerce-gateway-stripe' ); |
||
| 61 | } |
||
| 62 | |||
| 63 | if ( $this->testmode ) { |
||
| 64 | $this->description .= ' ' . sprintf( __( 'TEST MODE ENABLED. In test mode, you can use the card number 4242424242424242 with any CVC and a valid expiration date or check the documentation "<a href="%s">Testing Stripe</a>" for more card numbers.', 'woocommerce-gateway-stripe' ), 'https://stripe.com/docs/testing' ); |
||
| 65 | $this->description = trim( $this->description ); |
||
| 66 | } |
||
| 67 | |||
| 68 | WC_Stripe_API::set_secret_key( $this->secret_key ); |
||
| 69 | |||
| 70 | // Hooks |
||
| 71 | add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) ); |
||
| 72 | add_action( 'admin_notices', array( $this, 'admin_notices' ) ); |
||
| 73 | add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); |
||
| 74 | } |
||
| 75 | |||
| 76 | /** |
||
| 77 | * get_icon function. |
||
| 78 | * |
||
| 79 | * @access public |
||
| 80 | * @return string |
||
| 81 | */ |
||
| 82 | View Code Duplication | public function get_icon() { |
|
| 83 | $ext = version_compare( WC()->version, '2.6', '>=' ) ? '.svg' : '.png'; |
||
| 84 | $style = version_compare( WC()->version, '2.6', '>=' ) ? 'style="margin-left: 0.3em"' : ''; |
||
| 85 | |||
| 86 | $icon = '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/visa' . $ext ) . '" alt="Visa" width="32" ' . $style . ' />'; |
||
| 87 | $icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/mastercard' . $ext ) . '" alt="Mastercard" width="32" ' . $style . ' />'; |
||
| 88 | $icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/amex' . $ext ) . '" alt="Amex" width="32" ' . $style . ' />'; |
||
| 89 | |||
| 90 | $base_location = wc_get_base_location(); |
||
| 91 | |||
| 92 | if ( 'US' === $base_location['country'] ) { |
||
| 93 | $icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/discover' . $ext ) . '" alt="Discover" width="32" ' . $style . ' />'; |
||
| 94 | $icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/jcb' . $ext ) . '" alt="JCB" width="32" ' . $style . ' />'; |
||
| 95 | $icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/diners' . $ext ) . '" alt="Diners" width="32" ' . $style . ' />'; |
||
| 96 | } |
||
| 97 | |||
| 98 | if ( $this->bitcoin ) { |
||
| 99 | $icon .= '<img src="' . WC_HTTPS::force_https_url( plugins_url( '/assets/images/bitcoin' . $ext, WC_STRIPE_MAIN_FILE ) ) . '" alt="Bitcoin" width="32" ' . $style . ' />'; |
||
| 100 | } |
||
| 101 | |||
| 102 | return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id ); |
||
| 103 | } |
||
| 104 | |||
| 105 | /** |
||
| 106 | * Get Stripe amount to pay |
||
| 107 | * @return float |
||
| 108 | */ |
||
| 109 | View Code Duplication | public function get_stripe_amount( $total, $currency = '' ) { |
|
| 110 | if ( ! $currency ) { |
||
| 111 | $currency = get_woocommerce_currency(); |
||
| 112 | } |
||
| 113 | switch ( strtoupper( $currency ) ) { |
||
| 114 | // Zero decimal currencies |
||
| 115 | case 'BIF' : |
||
| 116 | case 'CLP' : |
||
| 117 | case 'DJF' : |
||
| 118 | case 'GNF' : |
||
| 119 | case 'JPY' : |
||
| 120 | case 'KMF' : |
||
| 121 | case 'KRW' : |
||
| 122 | case 'MGA' : |
||
| 123 | case 'PYG' : |
||
| 124 | case 'RWF' : |
||
| 125 | case 'VND' : |
||
| 126 | case 'VUV' : |
||
| 127 | case 'XAF' : |
||
| 128 | case 'XOF' : |
||
| 129 | case 'XPF' : |
||
| 130 | $total = absint( $total ); |
||
| 131 | break; |
||
| 132 | default : |
||
| 133 | $total = round( $total, 2 ) * 100; // In cents |
||
| 134 | break; |
||
| 135 | } |
||
| 136 | return $total; |
||
| 137 | } |
||
| 138 | |||
| 139 | /** |
||
| 140 | * Check if SSL is enabled and notify the user |
||
| 141 | */ |
||
| 142 | public function admin_notices() { |
||
| 143 | if ( $this->enabled == 'no' ) { |
||
| 144 | return; |
||
| 145 | } |
||
| 146 | |||
| 147 | $addons = ( class_exists( 'WC_Subscriptions_Order' ) || class_exists( 'WC_Pre_Orders_Order' ) ) ? '_addons' : ''; |
||
| 148 | |||
| 149 | // Check required fields |
||
| 150 | if ( ! $this->secret_key ) { |
||
| 151 | echo '<div class="error"><p>' . sprintf( __( 'Stripe error: Please enter your secret key <a href="%s">here</a>', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=wc_gateway_stripe' . $addons ) ) . '</p></div>'; |
||
| 152 | return; |
||
| 153 | |||
| 154 | View Code Duplication | } elseif ( ! $this->publishable_key ) { |
|
|
0 ignored issues
–
show
|
|||
| 155 | echo '<div class="error"><p>' . sprintf( __( 'Stripe error: Please enter your publishable key <a href="%s">here</a>', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=wc_gateway_stripe' . $addons ) ) . '</p></div>'; |
||
| 156 | return; |
||
| 157 | } |
||
| 158 | |||
| 159 | // Simple check for duplicate keys |
||
| 160 | View Code Duplication | if ( $this->secret_key == $this->publishable_key ) { |
|
| 161 | echo '<div class="error"><p>' . sprintf( __( 'Stripe error: Your secret and publishable keys match. Please check and re-enter.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=wc_gateway_stripe' . $addons ) ) . '</p></div>'; |
||
| 162 | return; |
||
| 163 | } |
||
| 164 | |||
| 165 | // Show message if enabled and FORCE SSL is disabled and WordpressHTTPS plugin is not detected |
||
| 166 | View Code Duplication | if ( ( function_exists( 'wc_site_is_https' ) && ! wc_site_is_https() ) && ( 'no' === get_option( 'woocommerce_force_ssl_checkout' ) && ! class_exists( 'WordPressHTTPS' ) ) ) { |
|
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 167 | echo '<div class="error"><p>' . sprintf( __( 'Stripe 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 - Stripe will only work in test mode.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout' ) ) . '</p></div>'; |
||
| 168 | } |
||
| 169 | } |
||
| 170 | |||
| 171 | /** |
||
| 172 | * Check if this gateway is enabled |
||
| 173 | */ |
||
| 174 | View Code Duplication | public function is_available() { |
|
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 175 | if ( 'yes' === $this->enabled ) { |
||
| 176 | if ( ! $this->testmode && is_checkout() && ! is_ssl() ) { |
||
| 177 | return false; |
||
| 178 | } |
||
| 179 | if ( ! $this->secret_key || ! $this->publishable_key ) { |
||
| 180 | return false; |
||
| 181 | } |
||
| 182 | return true; |
||
| 183 | } |
||
| 184 | return false; |
||
| 185 | } |
||
| 186 | |||
| 187 | /** |
||
| 188 | * Initialise Gateway Settings Form Fields |
||
| 189 | */ |
||
| 190 | public function init_form_fields() { |
||
| 191 | $this->form_fields = include( untrailingslashit( plugin_dir_path( WC_STRIPE_MAIN_FILE ) ) . '/includes/settings-stripe.php' ); |
||
| 192 | |||
| 193 | wc_enqueue_js( " |
||
| 194 | jQuery( function( $ ) { |
||
| 195 | $( '#woocommerce_stripe_stripe_checkout' ).change(function(){ |
||
| 196 | if ( $( this ).is( ':checked' ) ) { |
||
| 197 | $( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image' ).closest( 'tr' ).show(); |
||
| 198 | } else { |
||
| 199 | $( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image' ).closest( 'tr' ).hide(); |
||
| 200 | } |
||
| 201 | }).change(); |
||
| 202 | }); |
||
| 203 | " ); |
||
| 204 | } |
||
| 205 | |||
| 206 | /** |
||
| 207 | * Payment form on checkout page |
||
| 208 | */ |
||
| 209 | public function payment_fields() { |
||
| 210 | ?> |
||
| 211 | <fieldset class="stripe-legacy-payment-fields"> |
||
| 212 | <?php |
||
| 213 | if ( $this->description ) { |
||
| 214 | echo apply_filters( 'wc_stripe_description', wpautop( wp_kses_post( $this->description ) ) ); |
||
| 215 | } |
||
| 216 | if ( $this->saved_cards && is_user_logged_in() ) { |
||
| 217 | $stripe_customer = new WC_Stripe_Customer( get_current_user_id() ); |
||
| 218 | ?> |
||
| 219 | <p class="form-row form-row-wide"> |
||
| 220 | <a class="<?php echo apply_filters( 'wc_stripe_manage_saved_cards_class', 'button' ); ?>" style="float:right;" href="<?php echo apply_filters( 'wc_stripe_manage_saved_cards_url', get_permalink( get_option( 'woocommerce_myaccount_page_id' ) ) ); ?>#saved-cards"><?php esc_html_e( 'Manage cards', 'woocommerce-gateway-stripe' ); ?></a> |
||
| 221 | <?php |
||
| 222 | if ( $cards = $stripe_customer->get_cards() ) { |
||
| 223 | $default_card = $cards[0]->id; |
||
| 224 | foreach ( (array) $cards as $card ) { |
||
| 225 | if ( 'card' !== $card->object ) { |
||
| 226 | continue; |
||
| 227 | } |
||
| 228 | ?> |
||
| 229 | <label for="stripe_card_<?php echo $card->id; ?>" class="brand-<?php echo esc_attr( strtolower( $card->brand ) ); ?>"> |
||
| 230 | <input type="radio" id="stripe_card_<?php echo $card->id; ?>" name="wc-stripe-payment-token" value="<?php echo $card->id; ?>" <?php checked( $default_card, $card->id ) ?> /> |
||
| 231 | <?php printf( __( '%s card ending in %s (Expires %s/%s)', 'woocommerce-gateway-stripe' ), $card->brand, $card->last4, $card->exp_month, $card->exp_year ); ?> |
||
| 232 | </label> |
||
| 233 | <?php |
||
| 234 | } |
||
| 235 | } |
||
| 236 | ?> |
||
| 237 | <label for="new"> |
||
| 238 | <input type="radio" id="new" name="wc-stripe-payment-token" value="new" /> |
||
| 239 | <?php _e( 'Use a new credit card', 'woocommerce-gateway-stripe' ); ?> |
||
| 240 | </label> |
||
| 241 | </p> |
||
| 242 | <?php |
||
| 243 | } |
||
| 244 | |||
| 245 | $user = wp_get_current_user(); |
||
| 246 | |||
| 247 | View Code Duplication | if ( $user ) { |
|
| 248 | $user_email = get_user_meta( $user->ID, 'billing_email', true ); |
||
| 249 | $user_email = $user_email ? $user_email : $user->user_email; |
||
| 250 | } else { |
||
| 251 | $user_email = ''; |
||
| 252 | } |
||
| 253 | |||
| 254 | $display = ''; |
||
| 255 | |||
| 256 | if ( $this->stripe_checkout || $this->saved_cards && ! empty( $cards ) ) { |
||
| 257 | $display = 'style="display:none;"'; |
||
| 258 | } |
||
| 259 | |||
| 260 | echo '<div ' . $display . ' id="stripe-payment-data" |
||
| 261 | data-description="" |
||
| 262 | data-email="' . esc_attr( $user_email ) . '" |
||
| 263 | data-amount="' . esc_attr( $this->get_stripe_amount( WC()->cart->total ) ) . '" |
||
| 264 | data-name="' . esc_attr( get_bloginfo( 'name', 'display' ) ) . '" |
||
| 265 | data-currency="' . esc_attr( strtolower( get_woocommerce_currency() ) ) . '" |
||
| 266 | data-image="' . esc_attr( $this->stripe_checkout_image ) . '" |
||
| 267 | data-bitcoin="' . esc_attr( $this->bitcoin ? 'true' : 'false' ) . '" |
||
| 268 | data-locale="' . esc_attr( $this->stripe_checkout_locale ? $this->stripe_checkout_locale : 'en' ) . '">'; |
||
| 269 | |||
| 270 | if ( ! $this->stripe_checkout ) { |
||
| 271 | $this->credit_card_form( array( 'fields_have_names' => false ) ); |
||
| 272 | } |
||
| 273 | |||
| 274 | echo '</div>'; |
||
| 275 | ?> |
||
| 276 | </fieldset> |
||
| 277 | <?php |
||
| 278 | } |
||
| 279 | |||
| 280 | /** |
||
| 281 | * payment_scripts function. |
||
| 282 | * |
||
| 283 | * Outputs scripts used for stripe payment |
||
| 284 | * |
||
| 285 | * @access public |
||
| 286 | */ |
||
| 287 | public function payment_scripts() { |
||
| 288 | if ( $this->stripe_checkout ) { |
||
| 289 | wp_enqueue_script( 'stripe', 'https://checkout.stripe.com/v2/checkout.js', '', '2.0', true ); |
||
| 290 | wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe_checkout.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true ); |
||
| 291 | View Code Duplication | } else { |
|
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 292 | wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true ); |
||
| 293 | wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe.js', WC_STRIPE_MAIN_FILE ), array( 'jquery-payment', 'stripe' ), WC_STRIPE_VERSION, true ); |
||
| 294 | } |
||
| 295 | |||
| 296 | $stripe_params = array( |
||
| 297 | 'key' => $this->publishable_key, |
||
| 298 | 'i18n_terms' => __( 'Please accept the terms and conditions first', 'woocommerce-gateway-stripe' ), |
||
| 299 | 'i18n_required_fields' => __( 'Please fill in required checkout fields first', 'woocommerce-gateway-stripe' ), |
||
| 300 | ); |
||
| 301 | |||
| 302 | // If we're on the pay page we need to pass stripe.js the address of the order. |
||
| 303 | if ( is_checkout_pay_page() && isset( $_GET['order'] ) && isset( $_GET['order_id'] ) ) { |
||
| 304 | $order_key = urldecode( $_GET['order'] ); |
||
| 305 | $order_id = absint( $_GET['order_id'] ); |
||
| 306 | $order = wc_get_order( $order_id ); |
||
| 307 | |||
| 308 | if ( $order->id === $order_id && $order->order_key === $order_key ) { |
||
| 309 | $stripe_params['billing_first_name'] = $order->billing_first_name; |
||
| 310 | $stripe_params['billing_last_name'] = $order->billing_last_name; |
||
| 311 | $stripe_params['billing_address_1'] = $order->billing_address_1; |
||
| 312 | $stripe_params['billing_address_2'] = $order->billing_address_2; |
||
| 313 | $stripe_params['billing_state'] = $order->billing_state; |
||
| 314 | $stripe_params['billing_city'] = $order->billing_city; |
||
| 315 | $stripe_params['billing_postcode'] = $order->billing_postcode; |
||
| 316 | $stripe_params['billing_country'] = $order->billing_country; |
||
| 317 | } |
||
| 318 | } |
||
| 319 | |||
| 320 | wp_localize_script( 'woocommerce_stripe', 'wc_stripe_params', apply_filters( 'wc_stripe_params', $stripe_params ) ); |
||
| 321 | } |
||
| 322 | |||
| 323 | /** |
||
| 324 | * Generate the request for the payment. |
||
| 325 | * @param WC_Order $order |
||
| 326 | * @param object $source |
||
| 327 | * @return array() |
||
| 328 | */ |
||
| 329 | protected function generate_payment_request( $order, $source ) { |
||
| 330 | $post_data = array(); |
||
| 331 | $post_data['currency'] = strtolower( $order->get_order_currency() ? $order->get_order_currency() : get_woocommerce_currency() ); |
||
| 332 | $post_data['amount'] = $this->get_stripe_amount( $order->get_total(), $post_data['currency'] ); |
||
| 333 | $post_data['description'] = sprintf( __( '%s - Order %s', 'woocommerce-gateway-stripe' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $order->get_order_number() ); |
||
| 334 | $post_data['capture'] = $this->capture ? 'true' : 'false'; |
||
| 335 | |||
| 336 | if ( ! empty( $order->billing_email ) && apply_filters( 'wc_stripe_send_stripe_receipt', false ) ) { |
||
| 337 | $post_data['receipt_email'] = $order->billing_email; |
||
| 338 | } |
||
| 339 | |||
| 340 | $post_data['expand[]'] = 'balance_transaction'; |
||
| 341 | |||
| 342 | if ( $source->customer ) { |
||
| 343 | $post_data['customer'] = $source->customer; |
||
| 344 | } |
||
| 345 | |||
| 346 | if ( $source->source ) { |
||
| 347 | $post_data['source'] = $source->source; |
||
| 348 | } |
||
| 349 | |||
| 350 | return apply_filters( 'wc_stripe_generate_payment_request', $post_data, $order, $source ); |
||
| 351 | } |
||
| 352 | |||
| 353 | /** |
||
| 354 | * Get payment source. This can be a new token or existing card. |
||
| 355 | * @param bool $force_customer Should we force customer creation? |
||
| 356 | * @return object |
||
| 357 | */ |
||
| 358 | protected function get_source( $user_id, $force_customer = false ) { |
||
| 359 | $stripe_customer = new WC_Stripe_Customer( $user_id ); |
||
| 360 | $stripe_source = false; |
||
| 361 | $token_id = false; |
||
| 362 | |||
| 363 | // New CC info was entered and we have a new token to process |
||
| 364 | if ( isset( $_POST['stripe_token'] ) ) { |
||
| 365 | $stripe_token = wc_clean( $_POST['stripe_token'] ); |
||
| 366 | $maybe_saved_card = isset( $_POST['wc-stripe-new-payment-method'] ) && ! empty( $_POST['wc-stripe-new-payment-method'] ); |
||
| 367 | |||
| 368 | // This is true if the user wants to store the card to their account. |
||
| 369 | View Code Duplication | if ( ( $user_id && $this->saved_cards && $maybe_saved_card ) || $force_customer ) { |
|
| 370 | $stripe_source = $stripe_customer->add_card( $stripe_token ); |
||
| 371 | |||
| 372 | if ( is_wp_error( $stripe_source ) ) { |
||
| 373 | throw new Exception( $stripe_source->get_error_message() ); |
||
| 374 | } |
||
| 375 | |||
| 376 | } else { |
||
| 377 | // Not saving token, so don't define customer either. |
||
| 378 | $stripe_source = $stripe_token; |
||
| 379 | $stripe_customer = false; |
||
| 380 | } |
||
| 381 | } |
||
| 382 | |||
| 383 | // Use an existing token, and then process the payment |
||
| 384 | elseif ( isset( $_POST['wc-stripe-payment-token'] ) && 'new' !== $_POST['wc-stripe-payment-token'] ) { |
||
| 385 | $stripe_source = wc_clean( $_POST['wc-stripe-payment-token'] ); |
||
| 386 | } |
||
| 387 | |||
| 388 | return (object) array( |
||
| 389 | 'token_id' => $token_id, |
||
| 390 | 'customer' => $stripe_customer ? $stripe_customer->get_id() : false, |
||
| 391 | 'source' => $stripe_source, |
||
| 392 | ); |
||
| 393 | } |
||
| 394 | |||
| 395 | /** |
||
| 396 | * Get payment source from an order. This could be used in the future for |
||
| 397 | * a subscription as an example, therefore using the current user ID would |
||
| 398 | * not work - the customer won't be logged in :) |
||
| 399 | * |
||
| 400 | * Not using 2.6 tokens for this part since we need a customer AND a card |
||
| 401 | * token, and not just one. |
||
| 402 | * |
||
| 403 | * @param object $order |
||
| 404 | * @return object |
||
| 405 | */ |
||
| 406 | protected function get_order_source( $order = null ) { |
||
| 407 | $stripe_customer = new WC_Stripe_Customer(); |
||
| 408 | $stripe_source = false; |
||
| 409 | $token_id = false; |
||
| 410 | |||
| 411 | if ( $order ) { |
||
| 412 | if ( $meta_value = get_post_meta( $order->id, '_stripe_customer_id', true ) ) { |
||
| 413 | $stripe_customer->set_id( $meta_value ); |
||
| 414 | } |
||
| 415 | if ( $meta_value = get_post_meta( $order->id, '_stripe_card_id', true ) ) { |
||
| 416 | $stripe_source = $meta_value; |
||
| 417 | } |
||
| 418 | } |
||
| 419 | |||
| 420 | return (object) array( |
||
| 421 | 'token_id' => $token_id, |
||
| 422 | 'customer' => $stripe_customer ? $stripe_customer->get_id() : false, |
||
| 423 | 'source' => $stripe_source, |
||
| 424 | ); |
||
| 425 | } |
||
| 426 | |||
| 427 | /** |
||
| 428 | * Process the payment |
||
| 429 | */ |
||
| 430 | public function process_payment( $order_id, $retry = true, $force_customer = false ) { |
||
| 431 | try { |
||
| 432 | $order = wc_get_order( $order_id ); |
||
| 433 | $source = $this->get_source( get_current_user_id(), $force_customer ); |
||
| 434 | |||
| 435 | View Code Duplication | if ( empty( $source->source ) && empty( $source->customer ) ) { |
|
| 436 | $error_msg = __( 'Please enter your card details to make a payment.', 'woocommerce-gateway-stripe' ); |
||
| 437 | $error_msg .= ' ' . __( 'Developers: Please make sure that you are including jQuery and there are no JavaScript errors on the page.', 'woocommerce-gateway-stripe' ); |
||
| 438 | throw new Exception( $error_msg ); |
||
| 439 | } |
||
| 440 | |||
| 441 | // Store source to order meta |
||
| 442 | $this->save_source( $order, $source ); |
||
| 443 | |||
| 444 | // Handle payment |
||
| 445 | if ( $order->get_total() > 0 ) { |
||
| 446 | |||
| 447 | View Code Duplication | if ( $order->get_total() * 100 < WC_Stripe::get_minimum_amount() ) { |
|
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 448 | throw new Exception( sprintf( __( 'Sorry, the minimum allowed order total is %1$s to use this payment method.', 'woocommerce-gateway-stripe' ), wc_price( WC_Stripe::get_minimum_amount() / 100 ) ) ); |
||
| 449 | } |
||
| 450 | |||
| 451 | WC_Stripe::log( "Info: Begin processing payment for order $order_id for the amount of {$order->get_total()}" ); |
||
| 452 | |||
| 453 | // Make the request |
||
| 454 | $response = WC_Stripe_API::request( $this->generate_payment_request( $order, $source ) ); |
||
| 455 | |||
| 456 | if ( is_wp_error( $response ) ) { |
||
| 457 | // Customer param wrong? The user may have been deleted on stripe's end. Remove customer_id. Can be retried without. |
||
| 458 | if ( 'customer' === $response->get_error_code() && $retry ) { |
||
| 459 | delete_user_meta( get_current_user_id(), '_stripe_customer_id' ); |
||
| 460 | return $this->process_payment( $order_id, false, $force_customer ); |
||
| 461 | } |
||
| 462 | throw new Exception( $response->get_error_code() . ': ' . $response->get_error_message() ); |
||
| 463 | } |
||
| 464 | |||
| 465 | // Process valid response |
||
| 466 | $this->process_response( $response, $order ); |
||
| 467 | } else { |
||
| 468 | $order->payment_complete(); |
||
| 469 | } |
||
| 470 | |||
| 471 | // Remove cart |
||
| 472 | WC()->cart->empty_cart(); |
||
| 473 | |||
| 474 | // Return thank you page redirect |
||
| 475 | return array( |
||
| 476 | 'result' => 'success', |
||
| 477 | 'redirect' => $this->get_return_url( $order ) |
||
| 478 | ); |
||
| 479 | |||
| 480 | } catch ( Exception $e ) { |
||
| 481 | wc_add_notice( $e->getMessage(), 'error' ); |
||
| 482 | WC()->session->set( 'refresh_totals', true ); |
||
| 483 | WC_Stripe::log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) ); |
||
| 484 | return; |
||
| 485 | } |
||
| 486 | } |
||
| 487 | |||
| 488 | /** |
||
| 489 | * Save source to order. |
||
| 490 | */ |
||
| 491 | protected function save_source( $order, $source ) { |
||
| 492 | // Store source in the order |
||
| 493 | if ( $source->customer ) { |
||
| 494 | update_post_meta( $order->id, '_stripe_customer_id', $source->customer ); |
||
| 495 | } |
||
| 496 | if ( $source->source ) { |
||
| 497 | update_post_meta( $order->id, '_stripe_card_id', $source->source->id ); |
||
| 498 | } |
||
| 499 | } |
||
| 500 | |||
| 501 | /** |
||
| 502 | * Store extra meta data for an order from a Stripe Response. |
||
| 503 | */ |
||
| 504 | public function process_response( $response, $order ) { |
||
| 505 | WC_Stripe::log( "Processing response: " . print_r( $response, true ) ); |
||
| 506 | |||
| 507 | // Store charge data |
||
| 508 | update_post_meta( $order->id, '_stripe_charge_id', $response->id ); |
||
| 509 | update_post_meta( $order->id, '_stripe_charge_captured', $response->captured ? 'yes' : 'no' ); |
||
| 510 | |||
| 511 | // Store other data such as fees |
||
| 512 | if ( isset( $response->balance_transaction ) && isset( $response->balance_transaction->fee ) ) { |
||
| 513 | $fee = number_format( $response->balance_transaction->fee / 100, 2, '.', '' ); |
||
| 514 | update_post_meta( $order->id, 'Stripe Fee', $fee ); |
||
| 515 | update_post_meta( $order->id, 'Net Revenue From Stripe', $order->get_total() - $fee ); |
||
| 516 | } |
||
| 517 | |||
| 518 | if ( $response->captured ) { |
||
| 519 | $order->payment_complete( $response->id ); |
||
| 520 | WC_Stripe::log( "Successful charge: $response->id" ); |
||
| 521 | } else { |
||
| 522 | add_post_meta( $order->id, '_transaction_id', $response->id, true ); |
||
| 523 | |||
| 524 | if ( $order->has_status( array( 'pending', 'failed' ) ) ) { |
||
| 525 | $order->reduce_order_stock(); |
||
| 526 | } |
||
| 527 | |||
| 528 | $order->update_status( 'on-hold', sprintf( __( 'Stripe charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization.', 'woocommerce-gateway-stripe' ), $response->id ) ); |
||
| 529 | WC_Stripe::log( "Successful auth: $response->id" ); |
||
| 530 | } |
||
| 531 | |||
| 532 | return $response; |
||
| 533 | } |
||
| 534 | |||
| 535 | /** |
||
| 536 | * Add payment method via account screen. |
||
| 537 | * We don't store the token locally, but to the Stripe API. |
||
| 538 | * @since 3.0.0 |
||
| 539 | */ |
||
| 540 | public function add_payment_method() { |
||
| 541 | if ( empty( $_POST['stripe_token'] ) || ! is_user_logged_in() ) { |
||
| 542 | wc_add_notice( __( 'There was a problem adding the card.', 'woocommerce-gateway-stripe' ), 'error' ); |
||
| 543 | return; |
||
| 544 | } |
||
| 545 | |||
| 546 | $stripe_customer = new WC_Stripe_Customer( get_current_user_id() ); |
||
| 547 | $result = $stripe_customer->add_card( wc_clean( $_POST['stripe_token'] ) ); |
||
| 548 | |||
| 549 | if ( is_wp_error( $result ) ) { |
||
| 550 | throw new Exception( $result->get_error_message() ); |
||
| 551 | } |
||
| 552 | |||
| 553 | return array( |
||
| 554 | 'result' => 'success', |
||
| 555 | 'redirect' => wc_get_endpoint_url( 'payment-methods' ), |
||
| 556 | ); |
||
| 557 | } |
||
| 558 | |||
| 559 | /** |
||
| 560 | * Refund a charge |
||
| 561 | * @param int $order_id |
||
| 562 | * @param float $amount |
||
| 563 | * @return bool |
||
| 564 | */ |
||
| 565 | public function process_refund( $order_id, $amount = null, $reason = '' ) { |
||
| 566 | $order = wc_get_order( $order_id ); |
||
| 567 | |||
| 568 | if ( ! $order || ! $order->get_transaction_id() ) { |
||
| 569 | return false; |
||
| 570 | } |
||
| 571 | |||
| 572 | $body = array(); |
||
| 573 | |||
| 574 | if ( ! is_null( $amount ) ) { |
||
| 575 | $body['amount'] = $this->get_stripe_amount( $amount ); |
||
| 576 | } |
||
| 577 | |||
| 578 | if ( $reason ) { |
||
| 579 | $body['metadata'] = array( |
||
| 580 | 'reason' => $reason, |
||
| 581 | ); |
||
| 582 | } |
||
| 583 | |||
| 584 | WC_Stripe::log( "Info: Beginning refund for order $order_id for the amount of {$amount}" ); |
||
| 585 | |||
| 586 | $response = WC_Stripe_API::request( $body, 'charges/' . $order->get_transaction_id() . '/refunds' ); |
||
| 587 | |||
| 588 | if ( is_wp_error( $response ) ) { |
||
| 589 | WC_Stripe::log( "Error: " . $response->get_error_message() ); |
||
| 590 | return $response; |
||
| 591 | } elseif ( ! empty( $response->id ) ) { |
||
| 592 | $refund_message = sprintf( __( 'Refunded %s - Refund ID: %s - Reason: %s', 'woocommerce-gateway-stripe' ), wc_price( $response->amount / 100 ), $response->id, $reason ); |
||
| 593 | $order->add_order_note( $refund_message ); |
||
| 594 | WC_Stripe::log( "Success: " . html_entity_decode( strip_tags( $refund_message ) ) ); |
||
| 595 | return true; |
||
| 596 | } |
||
| 597 | } |
||
| 598 | } |
||
| 599 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.