diff --git a/classes/gateways/class-wc-paypal.php b/classes/gateways/class-wc-paypal.php index 4cfbba5891a..4a89be628e5 100644 --- a/classes/gateways/class-wc-paypal.php +++ b/classes/gateways/class-wc-paypal.php @@ -1,549 +1,549 @@ -id = 'paypal'; - $this->icon = apply_filters('woocommerce_paypal_icon', $woocommerce->plugin_url() . '/assets/images/icons/paypal.png'); - $this->has_fields = false; - $this->liveurl = 'https://www.paypal.com/webscr'; - $this->testurl = 'https://www.sandbox.paypal.com/webscr'; - $this->method_title = __( 'Paypal', 'woocommerce' ); - - - // Load the form fields. - $this->init_form_fields(); - - // Load the settings. - $this->init_settings(); - - // Define user set variables - $this->title = $this->settings['title']; - $this->description = $this->settings['description']; - $this->email = $this->settings['email']; - $this->testmode = $this->settings['testmode']; - $this->send_shipping= $this->settings['send_shipping']; - $this->debug = $this->settings['debug']; - - // Logs - if ($this->debug=='yes') $this->log = $woocommerce->logger(); - - // Actions - add_action( 'init', array(&$this, 'check_ipn_response') ); - add_action('valid-paypal-standard-ipn-request', array(&$this, 'successful_request') ); - add_action('woocommerce_receipt_paypal', array(&$this, 'receipt_page')); - add_action('woocommerce_update_options_payment_gateways', array(&$this, 'process_admin_options')); - - if ( !$this->is_valid_for_use() ) $this->enabled = false; - } - - /** - * Check if this gateway is enabled and available in the user's country - */ - function is_valid_for_use() { - if (!in_array(get_option('woocommerce_currency'), array('AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP'))) return false; - - return true; - } - - /** - * Admin Panel Options - * - Options for bits like 'title' and availability on a country-by-country basis - * - * @since 1.0.0 - */ - public function admin_options() { - - ?> -

-

- - is_valid_for_use() ) : - - // Generate the HTML For the settings form. - $this->generate_settings_html(); - - else : - - ?> -

:

- -
- form_fields = array( - 'enabled' => array( - 'title' => __( 'Enable/Disable', 'woocommerce' ), - 'type' => 'checkbox', - 'label' => __( 'Enable PayPal standard', 'woocommerce' ), - 'default' => 'yes' - ), - 'title' => array( - 'title' => __( 'Title', 'woocommerce' ), - 'type' => 'text', - 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ), - 'default' => __( 'PayPal', 'woocommerce' ) - ), - 'description' => array( - 'title' => __( 'Description', 'woocommerce' ), - 'type' => 'textarea', - 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce' ), - 'default' => __("Pay via PayPal; you can pay with your credit card if you don't have a PayPal account", 'woocommerce') - ), - 'email' => array( - 'title' => __( 'PayPal Email', 'woocommerce' ), - 'type' => 'text', - 'description' => __( 'Please enter your PayPal email address; this is needed in order to take payment.', 'woocommerce' ), - 'default' => '' - ), - 'send_shipping' => array( - 'title' => __( 'Shipping details', 'woocommerce' ), - 'type' => 'checkbox', - 'label' => __( 'Send shipping details to PayPal. Since PayPal verifies addresses sent to it this can cause errors, therefore we recommend disabling this option.', 'woocommerce' ), - 'default' => 'no' - ), - 'testmode' => array( - 'title' => __( 'PayPal sandbox', 'woocommerce' ), - 'type' => 'checkbox', - 'label' => __( 'Enable PayPal sandbox', 'woocommerce' ), - 'default' => 'yes' - ), - 'debug' => array( - 'title' => __( 'Debug', 'woocommerce' ), - 'type' => 'checkbox', - 'label' => __( 'Enable logging (woocommerce/logs/paypal.txt)', 'woocommerce' ), - 'default' => 'no' - ) - ); - - } // End init_form_fields() - - /** - * There are no payment fields for paypal, but we want to show the description if set. - **/ - function payment_fields() { - if ($this->description) echo wpautop(wptexturize($this->description)); - } - - /** - * Get PayPal Args for passing to PP - **/ - function get_paypal_args( $order ) { - global $woocommerce; - - $order_id = $order->id; - - if ($this->debug=='yes') $this->log->add( 'paypal', 'Generating payment form for order #' . $order_id . '. Notify URL: ' . trailingslashit(home_url()).'?paypalListener=paypal_standard_IPN'); - - if (in_array($order->billing_country, array('US','CA'))) : - $order->billing_phone = str_replace(array('(', '-', ' ', ')'), '', $order->billing_phone); - $phone_args = array( - 'night_phone_a' => substr($order->billing_phone,0,3), - 'night_phone_b' => substr($order->billing_phone,3,3), - 'night_phone_c' => substr($order->billing_phone,6,4), - 'day_phone_a' => substr($order->billing_phone,0,3), - 'day_phone_b' => substr($order->billing_phone,3,3), - 'day_phone_c' => substr($order->billing_phone,6,4) - ); - else : - $phone_args = array( - 'night_phone_b' => $order->billing_phone, - 'day_phone_b' => $order->billing_phone - ); - endif; - - // PayPal Args - $paypal_args = array_merge( - array( - 'cmd' => '_cart', - 'business' => $this->email, - 'no_note' => 1, - 'currency_code' => get_option('woocommerce_currency'), - 'charset' => 'UTF-8', - 'rm' => 2, - 'upload' => 1, - 'return' => $this->get_return_url( $order ), - 'cancel_return' => $order->get_cancel_order_url(), - - // Order key - 'custom' => $order_id, - - // IPN - 'notify_url' => trailingslashit(home_url()).'?paypalListener=paypal_standard_IPN', - - // Billing Address info - 'first_name' => $order->billing_first_name, - 'last_name' => $order->billing_last_name, - 'company' => $order->billing_company, - 'address1' => $order->billing_address_1, - 'address2' => $order->billing_address_2, - 'city' => $order->billing_city, - 'state' => $order->billing_state, - 'zip' => $order->billing_postcode, - 'country' => $order->billing_country, - 'email' => $order->billing_email, - - // Payment Info - 'invoice' => $order->order_key - ), - $phone_args - ); - - // Shipping - if ($this->send_shipping=='yes') : - $paypal_args['no_shipping'] = 0; - $paypal_args['address_override'] = 1; - - // If we are sending shipping, send shipping address instead of billing - $paypal_args['first_name'] = $order->shipping_first_name; - $paypal_args['last_name'] = $order->shipping_last_name; - $paypal_args['company'] = $order->shipping_company; - $paypal_args['address1'] = $order->shipping_address_1; - $paypal_args['address2'] = $order->shipping_address_2; - $paypal_args['city'] = $order->shipping_city; - $paypal_args['state'] = $order->shipping_state; - $paypal_args['zip'] = $order->shipping_postcode; - $paypal_args['country'] = $order->shipping_country; - else : - $paypal_args['no_shipping'] = 1; - endif; - - // If prices include tax or have order discounts, send the whole order - if ( get_option('woocommerce_prices_include_tax')=='yes' || $order->get_order_discount() > 0 ) : - - // Discount - $paypal_args['discount_amount_cart'] = $order->get_order_discount(); - - // Don't pass items - paypal borks tax due to prices including tax. PayPal has no option for tax inclusive pricing sadly. Pass 1 item for the order items overall - $paypal_args['item_name_1'] = sprintf(__('Order #%s' , 'woocommerce'), $order->id); - $paypal_args['quantity_1'] = 1; - $paypal_args['amount_1'] = number_format($order->get_order_total() - $order->get_shipping() + $order->get_order_discount(), 2, '.', ''); - - // Shipping Cost - if ($order->get_shipping()>0) : - $paypal_args['item_name_2'] = __('Shipping via ', 'woocommerce') . ucwords($order->shipping_method_title); - $paypal_args['quantity_2'] = '1'; - $paypal_args['amount_2'] = number_format($order->get_shipping(), 2, '.', ''); - endif; - - else : - - // Tax - $paypal_args['tax_cart'] = $order->get_total_tax(); - - // Cart Contents - $item_loop = 0; - if (sizeof($order->get_items())>0) : foreach ($order->get_items() as $item) : - if ($item['qty']) : - - $item_loop++; - - $product = $order->get_product_from_item($item); - - $item_name = $item['name']; - - $item_meta = new order_item_meta( $item['item_meta'] ); - if ($meta = $item_meta->display( true, true )) : - $item_name .= ' ('.$meta.')'; - endif; - - $paypal_args['item_name_'.$item_loop] = $item_name; - if ($product->get_sku()) $paypal_args['item_number_'.$item_loop] = $product->get_sku(); - $paypal_args['quantity_'.$item_loop] = $item['qty']; - $paypal_args['amount_'.$item_loop] = $order->get_item_total( $item, false ); - - endif; - endforeach; endif; - - // Shipping Cost - if ($order->get_shipping()>0) : - $item_loop++; - $paypal_args['item_name_'.$item_loop] = __('Shipping via ', 'woocommerce') . ucwords($order->shipping_method_title); - $paypal_args['quantity_'.$item_loop] = '1'; - $paypal_args['amount_'.$item_loop] = number_format($order->get_shipping(), 2, '.', ''); - endif; - - endif; - - $paypal_args = apply_filters( 'woocommerce_paypal_args', $paypal_args ); - - return $paypal_args; - } - - /** - * Generate the paypal button link - **/ - function generate_paypal_form( $order_id ) { - global $woocommerce; - - $order = new WC_Order( $order_id ); - - if ( $this->testmode == 'yes' ): - $paypal_adr = $this->testurl . '?test_ipn=1&'; - else : - $paypal_adr = $this->liveurl . '?'; - endif; - - $paypal_args = $this->get_paypal_args( $order ); - - $paypal_args_array = array(); - - foreach ($paypal_args as $key => $value) { - $paypal_args_array[] = ''; - } - - $woocommerce->add_inline_js(' - jQuery("body").block({ - message: "plugin_url() ).'/assets/images/ajax-loader.gif\" alt=\"Redirecting...\" style=\"float:left; margin-right: 10px;\" />'.__('Thank you for your order. We are now redirecting you to PayPal to make payment.', 'woocommerce').'", - overlayCSS: - { - background: "#fff", - opacity: 0.6 - }, - css: { - padding: 20, - textAlign: "center", - color: "#555", - border: "3px solid #aaa", - backgroundColor:"#fff", - cursor: "wait", - lineHeight: "32px" - } - }); - jQuery("#submit_paypal_payment_form").click(); - '); - - return '
- ' . implode('', $paypal_args_array) . ' - '.__('Cancel order & restore cart', 'woocommerce').' -
'; - - } - - /** - * Process the payment and return the result - **/ - function process_payment( $order_id ) { - - $order = new WC_Order( $order_id ); - - $paypal_args = $this->get_paypal_args( $order ); - - if ( $this->testmode == 'yes' ): - $paypal_adr = $this->testurl . '?test_ipn=1&'; - else : - $paypal_adr = $this->liveurl . '?'; - endif; - - return array( - 'result' => 'success', - 'redirect' => $paypal_adr . http_build_query( $paypal_args ) - //'redirect' => add_query_arg('order', $order->id, add_query_arg('key', $order->order_key, get_permalink(woocommerce_get_page_id('pay')))) - ); - - } - - /** - * receipt_page - **/ - function receipt_page( $order ) { - - echo '

'.__('Thank you for your order, please click the button below to pay with PayPal.', 'woocommerce').'

'; - - echo $this->generate_paypal_form( $order ); - - } - - /** - * Check PayPal IPN validity - **/ - function check_ipn_request_is_valid() { - global $woocommerce; - - if ($this->debug=='yes') $this->log->add( 'paypal', 'Checking IPN response is valid...' ); - - // Get recieved values from post data - $received_values = (array) stripslashes_deep( $_POST ); - - // Add cmd to the post array - $received_values['cmd'] = '_notify-validate'; - - // Send back post vars to paypal - $params = array( - 'body' => $received_values, - 'sslverify' => false, - 'timeout' => 30, - 'user-agent' => 'WooCommerce/'.$woocommerce->version - ); - - // Get url - if ( $this->testmode == 'yes' ): - $paypal_adr = $this->testurl; - else : - $paypal_adr = $this->liveurl; - endif; - - // Post back to get a response - $response = wp_remote_post( $paypal_adr, $params ); - - // check to see if the request was valid - if ( !is_wp_error($response) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 && (strcmp( $response['body'], "VERIFIED") == 0)) { - if ($this->debug=='yes') $this->log->add( 'paypal', 'Received valid response from PayPal' ); - return true; - } - - if ($this->debug=='yes') : - $this->log->add( 'paypal', 'Received invalid response from PayPal' ); - if (is_wp_error($response)) : - $this->log->add( 'paypal', 'Error response: ' . $result->get_error_message() ); - endif; - endif; - - return false; - } - - /** - * Check for PayPal IPN Response - **/ - function check_ipn_response() { - - if (isset($_GET['paypalListener']) && $_GET['paypalListener'] == 'paypal_standard_IPN'): - - @ob_clean(); - - $_POST = stripslashes_deep($_POST); - - if ($this->check_ipn_request_is_valid()) : - - header('HTTP/1.1 200 OK'); - - do_action("valid-paypal-standard-ipn-request", $_POST); - - else : - - wp_die("PayPal IPN Request Failure"); - - endif; - - endif; - - } - - /** - * Successful Payment! - **/ - function successful_request( $posted ) { - - // Custom holds post ID - if ( !empty($posted['custom']) && !empty($posted['invoice']) ) { - - $order = new WC_Order( (int) $posted['custom'] ); - if ($order->order_key!==$posted['invoice']) : - if ($this->debug=='yes') $this->log->add( 'paypal', 'Error: Order Key does not match invoice.' ); - exit; - endif; - - // Lowercase - $posted['payment_status'] = strtolower($posted['payment_status']); - $posted['txn_type'] = strtolower($posted['txn_type']); - - // Sandbox fix - if ($posted['test_ipn']==1 && $posted['payment_status']=='pending') $posted['payment_status'] = 'completed'; - - if ($this->debug=='yes') $this->log->add( 'paypal', 'Payment status: ' . $posted['payment_status'] ); - - // We are here so lets check status and do actions - switch ($posted['payment_status']) : - case 'completed' : - - // Check order not already completed - if ($order->status == 'completed') : - if ($this->debug=='yes') $this->log->add( 'paypal', 'Aborting, Order #' . $posted['custom'] . ' is already complete.' ); - exit; - endif; - - // Check valid txn_type - $accepted_types = array('cart', 'instant', 'express_checkout', 'web_accept', 'masspay', 'send_money'); - if (!in_array($posted['txn_type'], $accepted_types)) : - if ($this->debug=='yes') $this->log->add( 'paypal', 'Aborting, Invalid type:' . $posted['txn_type'] ); - endif; - - // Payment completed - $order->add_order_note( __('IPN payment completed', 'woocommerce') ); - $order->payment_complete(); - - if ($this->debug=='yes') $this->log->add( 'paypal', 'Payment complete.' ); - - // Store PP Details - update_post_meta( (int) $posted['custom'], 'Payer PayPal address', $posted['payer_email']); - update_post_meta( (int) $posted['custom'], 'Transaction ID', $posted['txn_id']); - update_post_meta( (int) $posted['custom'], 'Payer first name', $posted['first_name']); - update_post_meta( (int) $posted['custom'], 'Payer last name', $posted['last_name']); - update_post_meta( (int) $posted['custom'], 'Payment type', $posted['payment_type']); - - break; - case 'denied' : - case 'expired' : - case 'failed' : - case 'voided' : - // Order failed - $order->update_status('failed', sprintf(__('Payment %s via IPN.', 'woocommerce'), strtolower($posted['payment_status']) ) ); - break; - case "refunded" : - case "reversed" : - case "chargeback" : - - // Mark order as refunded - $order->update_status('refunded', sprintf(__('Payment %s via IPN.', 'woocommerce'), strtolower($posted['payment_status']) ) ); - - $message = woocommerce_mail_template( - __('Order refunded/reversed', 'woocommerce'), - sprintf(__('Order #%s has been marked as refunded - PayPal reason code: %s', 'woocommerce'), $order->id, $posted['reason_code'] ) - ); - - // Send the mail - woocommerce_mail( get_option('woocommerce_new_order_email_recipient'), sprintf(__('Payment for order #%s refunded/reversed', 'woocommerce'), $order->id), $message ); - - break; - default: - // No action - break; - endswitch; - - exit; - - } - - } - -} - -/** - * Add the gateway to WooCommerce - **/ -function add_paypal_gateway( $methods ) { - $methods[] = 'WC_Paypal'; return $methods; -} - -add_filter('woocommerce_payment_gateways', 'add_paypal_gateway' ); +id = 'paypal'; + $this->icon = apply_filters('woocommerce_paypal_icon', $woocommerce->plugin_url() . '/assets/images/icons/paypal.png'); + $this->has_fields = false; + $this->liveurl = 'https://www.paypal.com/webscr'; + $this->testurl = 'https://www.sandbox.paypal.com/webscr'; + $this->method_title = __( 'Paypal', 'woocommerce' ); + + + // Load the form fields. + $this->init_form_fields(); + + // Load the settings. + $this->init_settings(); + + // Define user set variables + $this->title = $this->settings['title']; + $this->description = $this->settings['description']; + $this->email = $this->settings['email']; + $this->testmode = $this->settings['testmode']; + $this->send_shipping= $this->settings['send_shipping']; + $this->debug = $this->settings['debug']; + + // Logs + if ($this->debug=='yes') $this->log = $woocommerce->logger(); + + // Actions + add_action( 'init', array(&$this, 'check_ipn_response') ); + add_action('valid-paypal-standard-ipn-request', array(&$this, 'successful_request') ); + add_action('woocommerce_receipt_paypal', array(&$this, 'receipt_page')); + add_action('woocommerce_update_options_payment_gateways', array(&$this, 'process_admin_options')); + + if ( !$this->is_valid_for_use() ) $this->enabled = false; + } + + /** + * Check if this gateway is enabled and available in the user's country + */ + function is_valid_for_use() { + if (!in_array(get_option('woocommerce_currency'), array('AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP'))) return false; + + return true; + } + + /** + * Admin Panel Options + * - Options for bits like 'title' and availability on a country-by-country basis + * + * @since 1.0.0 + */ + public function admin_options() { + + ?> +

+

+ + is_valid_for_use() ) : + + // Generate the HTML For the settings form. + $this->generate_settings_html(); + + else : + + ?> +

:

+ +
+ form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce' ), + 'type' => 'checkbox', + 'label' => __( 'Enable PayPal standard', 'woocommerce' ), + 'default' => 'yes' + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce' ), + 'type' => 'text', + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ), + 'default' => __( 'PayPal', 'woocommerce' ) + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce' ), + 'type' => 'textarea', + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce' ), + 'default' => __("Pay via PayPal; you can pay with your credit card if you don't have a PayPal account", 'woocommerce') + ), + 'email' => array( + 'title' => __( 'PayPal Email', 'woocommerce' ), + 'type' => 'text', + 'description' => __( 'Please enter your PayPal email address; this is needed in order to take payment.', 'woocommerce' ), + 'default' => '' + ), + 'send_shipping' => array( + 'title' => __( 'Shipping details', 'woocommerce' ), + 'type' => 'checkbox', + 'label' => __( 'Send shipping details to PayPal. Since PayPal verifies addresses sent to it this can cause errors, therefore we recommend disabling this option.', 'woocommerce' ), + 'default' => 'no' + ), + 'testmode' => array( + 'title' => __( 'PayPal sandbox', 'woocommerce' ), + 'type' => 'checkbox', + 'label' => __( 'Enable PayPal sandbox', 'woocommerce' ), + 'default' => 'yes' + ), + 'debug' => array( + 'title' => __( 'Debug', 'woocommerce' ), + 'type' => 'checkbox', + 'label' => __( 'Enable logging (woocommerce/logs/paypal.txt)', 'woocommerce' ), + 'default' => 'no' + ) + ); + + } // End init_form_fields() + + /** + * There are no payment fields for paypal, but we want to show the description if set. + **/ + function payment_fields() { + if ($this->description) echo wpautop(wptexturize($this->description)); + } + + /** + * Get PayPal Args for passing to PP + **/ + function get_paypal_args( $order ) { + global $woocommerce; + + $order_id = $order->id; + + if ($this->debug=='yes') $this->log->add( 'paypal', 'Generating payment form for order #' . $order_id . '. Notify URL: ' . trailingslashit(home_url()).'?paypalListener=paypal_standard_IPN'); + + if (in_array($order->billing_country, array('US','CA'))) : + $order->billing_phone = str_replace(array('(', '-', ' ', ')'), '', $order->billing_phone); + $phone_args = array( + 'night_phone_a' => substr($order->billing_phone,0,3), + 'night_phone_b' => substr($order->billing_phone,3,3), + 'night_phone_c' => substr($order->billing_phone,6,4), + 'day_phone_a' => substr($order->billing_phone,0,3), + 'day_phone_b' => substr($order->billing_phone,3,3), + 'day_phone_c' => substr($order->billing_phone,6,4) + ); + else : + $phone_args = array( + 'night_phone_b' => $order->billing_phone, + 'day_phone_b' => $order->billing_phone + ); + endif; + + // PayPal Args + $paypal_args = array_merge( + array( + 'cmd' => '_cart', + 'business' => $this->email, + 'no_note' => 1, + 'currency_code' => get_option('woocommerce_currency'), + 'charset' => 'UTF-8', + 'rm' => 2, + 'upload' => 1, + 'return' => $this->get_return_url( $order ), + 'cancel_return' => $order->get_cancel_order_url(), + + // Order key + 'custom' => $order_id, + + // IPN + 'notify_url' => trailingslashit(home_url()).'?paypalListener=paypal_standard_IPN', + + // Billing Address info + 'first_name' => $order->billing_first_name, + 'last_name' => $order->billing_last_name, + 'company' => $order->billing_company, + 'address1' => $order->billing_address_1, + 'address2' => $order->billing_address_2, + 'city' => $order->billing_city, + 'state' => $order->billing_state, + 'zip' => $order->billing_postcode, + 'country' => $order->billing_country, + 'email' => $order->billing_email, + + // Payment Info + 'invoice' => $order->order_key + ), + $phone_args + ); + + // Shipping + if ($this->send_shipping=='yes') : + $paypal_args['no_shipping'] = 0; + $paypal_args['address_override'] = 1; + + // If we are sending shipping, send shipping address instead of billing + $paypal_args['first_name'] = $order->shipping_first_name; + $paypal_args['last_name'] = $order->shipping_last_name; + $paypal_args['company'] = $order->shipping_company; + $paypal_args['address1'] = $order->shipping_address_1; + $paypal_args['address2'] = $order->shipping_address_2; + $paypal_args['city'] = $order->shipping_city; + $paypal_args['state'] = $order->shipping_state; + $paypal_args['zip'] = $order->shipping_postcode; + $paypal_args['country'] = $order->shipping_country; + else : + $paypal_args['no_shipping'] = 1; + endif; + + // If prices include tax or have order discounts, send the whole order + if ( get_option('woocommerce_prices_include_tax')=='yes' || $order->get_order_discount() > 0 ) : + + // Discount + $paypal_args['discount_amount_cart'] = $order->get_order_discount(); + + // Don't pass items - paypal borks tax due to prices including tax. PayPal has no option for tax inclusive pricing sadly. Pass 1 item for the order items overall + $paypal_args['item_name_1'] = sprintf(__('Order #%s' , 'woocommerce'), $order->id); + $paypal_args['quantity_1'] = 1; + $paypal_args['amount_1'] = number_format($order->get_order_total() - $order->get_shipping() + $order->get_order_discount(), 2, '.', ''); + + // Shipping Cost + if ($order->get_shipping()>0) : + $paypal_args['item_name_2'] = __('Shipping via', 'woocommerce') . ucwords($order->shipping_method_title); + $paypal_args['quantity_2'] = '1'; + $paypal_args['amount_2'] = number_format($order->get_shipping(), 2, '.', ''); + endif; + + else : + + // Tax + $paypal_args['tax_cart'] = $order->get_total_tax(); + + // Cart Contents + $item_loop = 0; + if (sizeof($order->get_items())>0) : foreach ($order->get_items() as $item) : + if ($item['qty']) : + + $item_loop++; + + $product = $order->get_product_from_item($item); + + $item_name = $item['name']; + + $item_meta = new order_item_meta( $item['item_meta'] ); + if ($meta = $item_meta->display( true, true )) : + $item_name .= ' ('.$meta.')'; + endif; + + $paypal_args['item_name_'.$item_loop] = $item_name; + if ($product->get_sku()) $paypal_args['item_number_'.$item_loop] = $product->get_sku(); + $paypal_args['quantity_'.$item_loop] = $item['qty']; + $paypal_args['amount_'.$item_loop] = $order->get_item_total( $item, false ); + + endif; + endforeach; endif; + + // Shipping Cost + if ($order->get_shipping()>0) : + $item_loop++; + $paypal_args['item_name_'.$item_loop] = __('Shipping via', 'woocommerce') . ucwords($order->shipping_method_title); + $paypal_args['quantity_'.$item_loop] = '1'; + $paypal_args['amount_'.$item_loop] = number_format($order->get_shipping(), 2, '.', ''); + endif; + + endif; + + $paypal_args = apply_filters( 'woocommerce_paypal_args', $paypal_args ); + + return $paypal_args; + } + + /** + * Generate the paypal button link + **/ + function generate_paypal_form( $order_id ) { + global $woocommerce; + + $order = new WC_Order( $order_id ); + + if ( $this->testmode == 'yes' ): + $paypal_adr = $this->testurl . '?test_ipn=1&'; + else : + $paypal_adr = $this->liveurl . '?'; + endif; + + $paypal_args = $this->get_paypal_args( $order ); + + $paypal_args_array = array(); + + foreach ($paypal_args as $key => $value) { + $paypal_args_array[] = ''; + } + + $woocommerce->add_inline_js(' + jQuery("body").block({ + message: "plugin_url() ).'/assets/images/ajax-loader.gif\" alt=\"Redirecting...\" style=\"float:left; margin-right: 10px;\" />'.__('Thank you for your order. We are now redirecting you to PayPal to make payment.', 'woocommerce').'", + overlayCSS: + { + background: "#fff", + opacity: 0.6 + }, + css: { + padding: 20, + textAlign: "center", + color: "#555", + border: "3px solid #aaa", + backgroundColor:"#fff", + cursor: "wait", + lineHeight: "32px" + } + }); + jQuery("#submit_paypal_payment_form").click(); + '); + + return '
+ ' . implode('', $paypal_args_array) . ' + '.__('Cancel order & restore cart', 'woocommerce').' +
'; + + } + + /** + * Process the payment and return the result + **/ + function process_payment( $order_id ) { + + $order = new WC_Order( $order_id ); + + $paypal_args = $this->get_paypal_args( $order ); + + if ( $this->testmode == 'yes' ): + $paypal_adr = $this->testurl . '?test_ipn=1&'; + else : + $paypal_adr = $this->liveurl . '?'; + endif; + + return array( + 'result' => 'success', + 'redirect' => $paypal_adr . http_build_query( $paypal_args ) + //'redirect' => add_query_arg('order', $order->id, add_query_arg('key', $order->order_key, get_permalink(woocommerce_get_page_id('pay')))) + ); + + } + + /** + * receipt_page + **/ + function receipt_page( $order ) { + + echo '

'.__('Thank you for your order, please click the button below to pay with PayPal.', 'woocommerce').'

'; + + echo $this->generate_paypal_form( $order ); + + } + + /** + * Check PayPal IPN validity + **/ + function check_ipn_request_is_valid() { + global $woocommerce; + + if ($this->debug=='yes') $this->log->add( 'paypal', 'Checking IPN response is valid...' ); + + // Get recieved values from post data + $received_values = (array) stripslashes_deep( $_POST ); + + // Add cmd to the post array + $received_values['cmd'] = '_notify-validate'; + + // Send back post vars to paypal + $params = array( + 'body' => $received_values, + 'sslverify' => false, + 'timeout' => 30, + 'user-agent' => 'WooCommerce/'.$woocommerce->version + ); + + // Get url + if ( $this->testmode == 'yes' ): + $paypal_adr = $this->testurl; + else : + $paypal_adr = $this->liveurl; + endif; + + // Post back to get a response + $response = wp_remote_post( $paypal_adr, $params ); + + // check to see if the request was valid + if ( !is_wp_error($response) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 && (strcmp( $response['body'], "VERIFIED") == 0)) { + if ($this->debug=='yes') $this->log->add( 'paypal', 'Received valid response from PayPal' ); + return true; + } + + if ($this->debug=='yes') : + $this->log->add( 'paypal', 'Received invalid response from PayPal' ); + if (is_wp_error($response)) : + $this->log->add( 'paypal', 'Error response: ' . $result->get_error_message() ); + endif; + endif; + + return false; + } + + /** + * Check for PayPal IPN Response + **/ + function check_ipn_response() { + + if (isset($_GET['paypalListener']) && $_GET['paypalListener'] == 'paypal_standard_IPN'): + + @ob_clean(); + + $_POST = stripslashes_deep($_POST); + + if ($this->check_ipn_request_is_valid()) : + + header('HTTP/1.1 200 OK'); + + do_action("valid-paypal-standard-ipn-request", $_POST); + + else : + + wp_die("PayPal IPN Request Failure"); + + endif; + + endif; + + } + + /** + * Successful Payment! + **/ + function successful_request( $posted ) { + + // Custom holds post ID + if ( !empty($posted['custom']) && !empty($posted['invoice']) ) { + + $order = new WC_Order( (int) $posted['custom'] ); + if ($order->order_key!==$posted['invoice']) : + if ($this->debug=='yes') $this->log->add( 'paypal', 'Error: Order Key does not match invoice.' ); + exit; + endif; + + // Lowercase + $posted['payment_status'] = strtolower($posted['payment_status']); + $posted['txn_type'] = strtolower($posted['txn_type']); + + // Sandbox fix + if ($posted['test_ipn']==1 && $posted['payment_status']=='pending') $posted['payment_status'] = 'completed'; + + if ($this->debug=='yes') $this->log->add( 'paypal', 'Payment status: ' . $posted['payment_status'] ); + + // We are here so lets check status and do actions + switch ($posted['payment_status']) : + case 'completed' : + + // Check order not already completed + if ($order->status == 'completed') : + if ($this->debug=='yes') $this->log->add( 'paypal', 'Aborting, Order #' . $posted['custom'] . ' is already complete.' ); + exit; + endif; + + // Check valid txn_type + $accepted_types = array('cart', 'instant', 'express_checkout', 'web_accept', 'masspay', 'send_money'); + if (!in_array($posted['txn_type'], $accepted_types)) : + if ($this->debug=='yes') $this->log->add( 'paypal', 'Aborting, Invalid type:' . $posted['txn_type'] ); + endif; + + // Payment completed + $order->add_order_note( __('IPN payment completed', 'woocommerce') ); + $order->payment_complete(); + + if ($this->debug=='yes') $this->log->add( 'paypal', 'Payment complete.' ); + + // Store PP Details + update_post_meta( (int) $posted['custom'], 'Payer PayPal address', $posted['payer_email']); + update_post_meta( (int) $posted['custom'], 'Transaction ID', $posted['txn_id']); + update_post_meta( (int) $posted['custom'], 'Payer first name', $posted['first_name']); + update_post_meta( (int) $posted['custom'], 'Payer last name', $posted['last_name']); + update_post_meta( (int) $posted['custom'], 'Payment type', $posted['payment_type']); + + break; + case 'denied' : + case 'expired' : + case 'failed' : + case 'voided' : + // Order failed + $order->update_status('failed', sprintf(__('Payment %s via IPN.', 'woocommerce'), strtolower($posted['payment_status']) ) ); + break; + case "refunded" : + case "reversed" : + case "chargeback" : + + // Mark order as refunded + $order->update_status('refunded', sprintf(__('Payment %s via IPN.', 'woocommerce'), strtolower($posted['payment_status']) ) ); + + $message = woocommerce_mail_template( + __('Order refunded/reversed', 'woocommerce'), + sprintf(__('Order #%s has been marked as refunded - PayPal reason code: %s', 'woocommerce'), $order->id, $posted['reason_code'] ) + ); + + // Send the mail + woocommerce_mail( get_option('woocommerce_new_order_email_recipient'), sprintf(__('Payment for order #%s refunded/reversed', 'woocommerce'), $order->id), $message ); + + break; + default: + // No action + break; + endswitch; + + exit; + + } + + } + +} + +/** + * Add the gateway to WooCommerce + **/ +function add_paypal_gateway( $methods ) { + $methods[] = 'WC_Paypal'; return $methods; +} + +add_filter('woocommerce_payment_gateways', 'add_paypal_gateway' ); diff --git a/widgets/widget-product_categories.php b/widgets/widget-product_categories.php index e9241678afa..e7895e77032 100644 --- a/widgets/widget-product_categories.php +++ b/widgets/widget-product_categories.php @@ -1,248 +1,248 @@ -woo_widget_cssclass = 'widget_product_categories'; - $this->woo_widget_description = __( 'A list or dropdown of product categories.', 'woocommerce' ); - $this->woo_widget_idbase = 'woocommerce_product_categories'; - $this->woo_widget_name = __('WooCommerce Product Categories', 'woocommerce' ); - - /* Widget settings. */ - $widget_ops = array( 'classname' => $this->woo_widget_cssclass, 'description' => $this->woo_widget_description ); - - /* Create the widget. */ - $this->WP_Widget('product_categories', $this->woo_widget_name, $widget_ops); - } - - /** @see WP_Widget */ - function widget( $args, $instance ) { - extract( $args ); - - $title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Product Categories', 'woocommerce' ) : $instance['title'], $instance, $this->id_base); - $c = $instance['count'] ? '1' : '0'; - $h = $instance['hierarchical'] ? '1' : '0'; - $s = (isset($instance['show_children_only']) && $instance['show_children_only']) ? '1' : '0'; - $d = $instance['dropdown'] ? '1' : '0'; - $o = isset($instance['orderby']) ? $instance['orderby'] : 'order'; - - echo $before_widget; - if ( $title ) echo $before_title . $title . $after_title; - - $cat_args = array('show_count' => $c, 'hierarchical' => $h, 'taxonomy' => 'product_cat'); - - if ( $o == 'order' ) { - - $cat_args['menu_order'] = 'asc'; - - } else { - - $cat_args['orderby'] = $o; - - } - - if ( $d ) { - - // Stuck with this until a fix for http://core.trac.wordpress.org/ticket/13258 - woocommerce_product_dropdown_categories( $c, $h ); - - ?> - - current_cat = false; - $this->cat_ancestors = array(); - - if (is_tax('product_cat')) : - - $this->current_cat = $wp_query->queried_object; - $this->cat_ancestors = get_ancestors( $this->current_cat->term_id, 'product_cat' ); - - elseif (is_singular('product')) : - - $product_category = wp_get_post_terms( $post->ID, 'product_cat' ); - - if ($product_category) : - $this->current_cat = end($product_category); - $this->cat_ancestors = get_ancestors( $this->current_cat->term_id, 'product_cat' ); - endif; - - endif; - - echo ''; - - } else { - - echo ''; - } - - echo $after_widget; - } - - function get_children_cats( $parent ) { - $cat_args = array(); - - $cat_args['title_li'] = ''; - $cat_args['hierarchical'] = 1; - $cat_args['child_of'] = 0; - $cat_args['pad_counts'] = 1; - $cat_args['parent'] = $parent; - - return get_terms( 'product_cat', apply_filters('woocommerce_product_categories_widget_subcat_args', $cat_args) ); - } - - function output_children_cats( $children, $c ) { - - echo ''; - } - - /** @see WP_Widget->update */ - function update( $new_instance, $old_instance ) { - $instance = $old_instance; - $instance['title'] = strip_tags($new_instance['title']); - $instance['orderby'] = strip_tags($new_instance['orderby']); - $instance['count'] = !empty($new_instance['count']) ? 1 : 0; - $instance['hierarchical'] = !empty($new_instance['hierarchical']) ? 1 : 0; - $instance['dropdown'] = !empty($new_instance['dropdown']) ? 1 : 0; - $instance['show_children_only'] = !empty($new_instance['show_children_only']) ? 1 : 0; - - return $instance; - } - - /** @see WP_Widget->form */ - function form( $instance ) { - //Defaults - $instance = wp_parse_args( (array) $instance, array( 'title' => '') ); - $title = esc_attr( $instance['title'] ); - $orderby = isset( $instance['orderby'] ) ? $instance['orderby'] : 'order'; - $count = isset($instance['count']) ? (bool) $instance['count'] :false; - $hierarchical = isset( $instance['hierarchical'] ) ? (bool) $instance['hierarchical'] : false; - $dropdown = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false; - $show_children_only = isset( $instance['show_children_only'] ) ? (bool) $instance['show_children_only'] : false; -?> -

-

- -

-

- -

/> -
- - /> -
- - /> -
- - /> -

-woo_widget_cssclass = 'widget_product_categories'; + $this->woo_widget_description = __( 'A list or dropdown of product categories.', 'woocommerce' ); + $this->woo_widget_idbase = 'woocommerce_product_categories'; + $this->woo_widget_name = __('WooCommerce Product Categories', 'woocommerce' ); + + /* Widget settings. */ + $widget_ops = array( 'classname' => $this->woo_widget_cssclass, 'description' => $this->woo_widget_description ); + + /* Create the widget. */ + $this->WP_Widget('product_categories', $this->woo_widget_name, $widget_ops); + } + + /** @see WP_Widget */ + function widget( $args, $instance ) { + extract( $args ); + + $title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Product Categories', 'woocommerce' ) : $instance['title'], $instance, $this->id_base); + $c = $instance['count'] ? '1' : '0'; + $h = $instance['hierarchical'] ? '1' : '0'; + $s = (isset($instance['show_children_only']) && $instance['show_children_only']) ? '1' : '0'; + $d = $instance['dropdown'] ? '1' : '0'; + $o = isset($instance['orderby']) ? $instance['orderby'] : 'order'; + + echo $before_widget; + if ( $title ) echo $before_title . $title . $after_title; + + $cat_args = array('show_count' => $c, 'hierarchical' => $h, 'taxonomy' => 'product_cat'); + + if ( $o == 'order' ) { + + $cat_args['menu_order'] = 'asc'; + + } else { + + $cat_args['orderby'] = $o; + + } + + if ( $d ) { + + // Stuck with this until a fix for http://core.trac.wordpress.org/ticket/13258 + woocommerce_product_dropdown_categories( $c, $h ); + + ?> + + current_cat = false; + $this->cat_ancestors = array(); + + if (is_tax('product_cat')) : + + $this->current_cat = $wp_query->queried_object; + $this->cat_ancestors = get_ancestors( $this->current_cat->term_id, 'product_cat' ); + + elseif (is_singular('product')) : + + $product_category = wp_get_post_terms( $post->ID, 'product_cat' ); + + if ($product_category) : + $this->current_cat = end($product_category); + $this->cat_ancestors = get_ancestors( $this->current_cat->term_id, 'product_cat' ); + endif; + + endif; + + echo ''; + + } else { + + echo ''; + } + + echo $after_widget; + } + + function get_children_cats( $parent ) { + $cat_args = array(); + + $cat_args['title_li'] = ''; + $cat_args['hierarchical'] = 1; + $cat_args['child_of'] = 0; + $cat_args['pad_counts'] = 1; + $cat_args['parent'] = $parent; + + return get_terms( 'product_cat', apply_filters('woocommerce_product_categories_widget_subcat_args', $cat_args) ); + } + + function output_children_cats( $children, $c ) { + + echo ''; + } + + /** @see WP_Widget->update */ + function update( $new_instance, $old_instance ) { + $instance = $old_instance; + $instance['title'] = strip_tags($new_instance['title']); + $instance['orderby'] = strip_tags($new_instance['orderby']); + $instance['count'] = !empty($new_instance['count']) ? 1 : 0; + $instance['hierarchical'] = !empty($new_instance['hierarchical']) ? 1 : 0; + $instance['dropdown'] = !empty($new_instance['dropdown']) ? 1 : 0; + $instance['show_children_only'] = !empty($new_instance['show_children_only']) ? 1 : 0; + + return $instance; + } + + /** @see WP_Widget->form */ + function form( $instance ) { + //Defaults + $instance = wp_parse_args( (array) $instance, array( 'title' => '') ); + $title = esc_attr( $instance['title'] ); + $orderby = isset( $instance['orderby'] ) ? $instance['orderby'] : 'order'; + $count = isset($instance['count']) ? (bool) $instance['count'] :false; + $hierarchical = isset( $instance['hierarchical'] ) ? (bool) $instance['hierarchical'] : false; + $dropdown = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false; + $show_children_only = isset( $instance['show_children_only'] ) ? (bool) $instance['show_children_only'] : false; +?> +

+

+ +

+

+ +

/> +
+ + /> +
+ + /> +
+ + /> +

+