/** * template method that determines the algorithm to send data to and from the shipping * server. This method should be called from the implementing classes calculate shipping * function. */ protected final function calculate_rate() { $services_to_use = $this->filter_services(); $this->has_error = false; // canada post will return all services you have chosen in your online account in the response. // most configurations happen on canada post site. Therefore any other services that do something // similar, we don't want to take the approach that there are services to loop through here. if ($services_to_use) { foreach ($services_to_use as $current_service) { if (!fflcommerce_shipping::show_shipping_calculator() && !(defined('FFLCOMMERCE_CHECKOUT') && FFLCOMMERCE_CHECKOUT)) { $request = ''; $this->set_error_message('Please proceed to checkout to get shipping estimates'); } else { // create request input for shipping service $request = $this->create_mail_request($current_service); } if ($request) { // send to shipping server and get xml back $post_response = $this->send_to_shipping_server($request); // convert xml into an array $xml_response = $this->convert_xml_to_array($post_response); // sums up the rates from flattened array, and generates amounts. $rate = $this->retrieve_rate_from_response($xml_response); if ($this->has_error()) { fflcommerce_log($xml_response, 'fflcommerce_calculable_shipping'); } $this->add_rate($rate, $current_service); } } } else { if (!fflcommerce_shipping::show_shipping_calculator() && !(defined('FFLCOMMERCE_CHECKOUT') && FFLCOMMERCE_CHECKOUT)) { $request = ''; $this->set_error_message('Please proceed to checkout to get shipping estimates'); } else { // create request input for shipping service $request = $this->create_mail_request(); } if ($request) { // send to shipping server and get xml back $post_response = $this->send_to_shipping_server($request); // convert xml into an array $xml_response = $this->convert_xml_to_array($post_response); // services are obtained from response $services = $this->get_services_from_response($xml_response); if (empty($services)) { fflcommerce_log($xml_response, 'fflcommerce_calculable_shipping'); } foreach ($services as $current_service) { $rate = $this->retrieve_rate_from_response($xml_response, $current_service); $this->add_rate($rate, $current_service); } } } // service returned an error since no rates were calculated if (($this->rates == NULL || !$this->rates) && !$this->has_error()) { $this->has_error = true; } }
public function format_option_for_display($item) { $options = FFLCommerce_Base::get_options(); if (!isset($item['id'])) { return ''; } // ensure we have an id to work with $display = ""; // each item builds it's output into this and it's returned for echoing $class = ""; if (isset($item['class'])) { $class = $item['class']; } // display a tooltip if there is one in it's own table data element before the item to display $display .= '<td class="fflcommerce-tooltips">'; if (!empty($item['tip'])) { $display .= '<a href="#" tip="' . esc_attr($item['tip']) . '" class="tips" tabindex="99"></a>'; } $display .= '</td><td class="forminp">'; $disabled = ''; $disabledItems = array(); if (isset($item['extra']) && isset($item['extra']['disabled'])) { if ($item['extra']['disabled'] === true) { $disabled = ' disabled'; } else { if (is_array($item['extra']['disabled'])) { $disabledItems = $item['extra']['disabled']; } } } /* * work off the option type and format output for display for each type */ switch ($item['type']) { case 'user_defined': if (isset($item['display'])) { if (is_callable($item['display'], true)) { $display .= call_user_func($item['display']); } } break; case 'default_gateway': $id = $item['id']; $display .= '<select id="' . $id . '" class="fflcommerce-input fflcommerce-select ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $id . ']"' . $disabled . ' >'; $gateways = fflcommerce_payment_gateways::get_available_payment_gateways(); foreach ($gateways as $slug => $gateway) { $display .= '<option value="' . esc_attr($slug) . '" ' . selected($options->get($id), $slug, false) . disabled(in_array($id, $disabledItems, false)) . ' />' . $gateway->title . '</option>'; } $display .= '</select>'; ?> <script type="text/javascript"> /*<![CDATA[*/ jQuery(function($){ $("#<?php echo $id; ?> ").select2({ width: '250px' }); }); /*]]>*/ </script> <?php break; case 'gateway_options': foreach (fflcommerce_payment_gateways::payment_gateways() as $gateway) { $gateway->admin_options(); } break; case 'shipping_options': foreach (fflcommerce_shipping::get_all_methods() as $shipping_method) { $shipping_method->admin_options(); } break; case 'tax_rates': $display .= $this->format_tax_rates_for_display($item); break; case 'single_select_page': $page_setting = (int) $options->get($item['id']); $args = array('name' => FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']', 'id' => $item['id'], 'sort_order' => 'ASC', 'echo' => 0, 'selected' => $page_setting); if (isset($item['extra'])) { $args = wp_parse_args($item['extra'], $args); } $display .= wp_dropdown_pages($args); $parts = explode('<select', $display); $id = $item['id']; $display = $parts[0] . '<select id="' . $id . '" class="' . $class . '"' . $parts[1]; ?> <script type="text/javascript"> /*<![CDATA[*/ jQuery(function($){ $("#<?php echo $id; ?> ").select2({ width: '250px' }); }); /*]]>*/ </script> <?php break; case 'single_select_country': $country_setting = (string) $options->get($item['id']); $add_empty = false; if (isset($item['options']['add_empty']) && $item['options']['add_empty']) { $add_empty = true; } if (strstr($country_setting, ':')) { $temp = explode(':', $country_setting); $country = current($temp); $state = end($temp); } else { $country = $country_setting; $state = '*'; } $id = $item['id']; $display .= '<select id="' . $id . '" class="single_select_country ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']"' . $disabled . '>'; $display .= fflcommerce_countries::country_dropdown_options($country, $state, true, false, false, $add_empty); $display .= '</select>'; ?> <script type="text/javascript"> /*<![CDATA[*/ jQuery(function($){ $("#<?php echo $id; ?> ").select2({ width: '500px' }); }); /*]]>*/ </script> <?php break; case 'multi_select_countries': $countries = fflcommerce_countries::get_countries(); $selections = (array) $options->get($item['id']); $display .= '<select multiple="multiple" id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-select ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . '][]"' . $disabled . '>'; foreach ($countries as $key => $val) { $display .= '<option value="' . esc_attr($key) . '" ' . selected(in_array($key, $selections), true, false) . disabled(in_array($key, $disabledItems, false)) . ' />' . $val . '</option>'; } $display .= '</select>'; $id = $item['id']; ?> <script type="text/javascript"> /*<![CDATA[*/ jQuery(function($){ $("#<?php echo $id; ?> ").select2({ width: '500px' }); }); /*]]>*/ </script> <?php break; case 'button': if (isset($item['extra'])) { $display .= '<a id="' . $item['id'] . '" class="button ' . $class . '" href="' . esc_attr($item['extra']) . '">' . esc_attr($item['desc']) . '</a>'; } $item['desc'] = ''; // temporarily remove it so it doesn't display twice break; case 'decimal': // decimal numbers are positive or negative 0-9 inclusive, may include decimal $display .= '<input id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-text ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" type="number" step="any" size="20" value="' . esc_attr($options->get($item['id'])) . '"' . $disabled . ' />'; break; case 'integer': // integer numbers are positive or negative 0-9 inclusive // integer numbers are positive or negative 0-9 inclusive case 'natural': // natural numbers are positive 0-9 inclusive $display .= '<input id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-text ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" type="number" size="20" value="' . esc_attr($options->get($item['id'])) . '"' . $disabled . ' />'; break; case 'text': // any character sequence $display .= '<input id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-text ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" type="text" size="20" value="' . esc_attr($options->get($item['id'])) . '"' . $disabled . ' />'; break; case 'midtext': $display .= '<input id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-text ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" type="text" size="40" value="' . esc_attr($options->get($item['id'])) . '"' . $disabled . ' />'; break; case 'longtext': $display .= '<input id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-text ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" type="text" size="80" value="' . esc_attr($options->get($item['id'])) . '"' . $disabled . ' />'; break; case 'email': $display .= '<input id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-text fflcommerce-email ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" type="text" size="40" value="' . esc_attr($options->get($item['id'])) . '"' . $disabled . ' />'; break; case 'codeblock': case 'textarea': $cols = '60'; if (isset($item['choices'])) { $ta_options = $item['choices']; if (isset($ta_options['cols'])) { $cols = $ta_options['cols']; } } $ta_value = stripslashes($options->get($item['id'])); $display .= '<textarea id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-textarea ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" cols="' . $cols . '" rows="4"' . $disabled . '>' . esc_textarea($ta_value) . '</textarea>'; break; case "radio": // default to horizontal display of choices ( 'horizontal' may or may not be defined ) if (!isset($item['extra']) || !in_array('vertical', $item['extra'])) { $display .= '<div class="fflcommerce-radio-horz">'; foreach ($item['choices'] as $option => $name) { $display .= '<input class="fflcommerce-input fflcommerce-radio ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" id="' . $item['id'] . '[' . $option . ']" type="radio" value="' . $option . '" ' . checked($options->get($item['id']), $option, false) . disabled(in_array($option, $disabledItems), true, false) . ' /><label for="' . $item['id'] . '[' . $option . ']">' . $name . '</label>'; } $display .= '</div>'; } else { if (isset($item['extra']) && in_array('vertical', $item['extra'])) { $display .= '<ul class="fflcommerce-radio-vert">'; foreach ($item['choices'] as $option => $name) { $display .= '<li><input class="fflcommerce-input fflcommerce-radio ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" id="' . $item['id'] . '[' . $option . ']" type="radio" value="' . $option . '" ' . checked($options->get($item['id']), $option, false) . disabled(in_array($option, $disabledItems), true, false) . ' /><label for="' . $item['id'] . '[' . $option . ']">' . $name . '</label></li>'; } $display .= '</ul>'; } } break; case 'checkbox': $display .= '<span class="fflcommerce-container"><input id="' . $item['id'] . '" type="checkbox" class="fflcommerce-input fflcommerce-checkbox ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" ' . checked($options->get($item['id']), 'yes', false) . $disabled . ' /><label for="' . $item['id'] . '">' . $item['name'] . '</label></span>'; break; case 'multicheck': $multi_stored = $options->get($item['id']); // default to horizontal display of choices ( 'horizontal' may or may not be defined ) if (!isset($item['extra']) || !in_array('vertical', $item['extra'])) { $display .= '<div class="fflcommerce-multi-checkbox-horz ' . $class . '">'; foreach ($item['choices'] as $key => $option) { $display .= '<input id="' . $item['id'] . '_' . $key . '" class="fflcommerce-input" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . '][' . $key . ']" type="checkbox" ' . checked($multi_stored[$key], true, false) . disabled(in_array($key, $disabledItems, false)) . ' /> <label for="' . $item['id'] . '_' . $key . '">' . $option . '</label>'; } $display .= '</div>'; } else { if (isset($item['extra']) && in_array('vertical', $item['extra'])) { $display .= '<ul class="fflcommerce-multi-checkbox-vert ' . $class . '">'; foreach ($item['choices'] as $key => $option) { $display .= '<li><input id="' . $item['id'] . '_' . $key . '" class="fflcommerce-input" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . '][' . $key . ']" type="checkbox" ' . checked($multi_stored[$key], true, false) . disabled(in_array($key, $disabledItems, false)) . ' /> <label for="' . $item['id'] . '_' . $key . '">' . $option . '</label></li>'; } $display .= '</ul>'; } } break; case 'range': $display .= '<input id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-range ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" type="range" min="' . $item['extra']['min'] . '" max="' . $item['extra']['max'] . '" step="' . $item['extra']['step'] . '" value="' . $options->get($item['id']) . '"' . $disabled . ' />'; break; case 'number': $display .= '<input id="' . $item['id'] . '" class="fflcommerce-input ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']" type="number" value="' . $options->get($item['id']) . '"'; if (isset($item['extra']['min'])) { $display .= ' min="' . $item['extra']['min'] . '"'; } if (isset($item['extra']['max'])) { $display .= ' max="' . $item['extra']['max'] . '"'; } if (isset($item['extra']['step'])) { $display .= ' step="' . $item['extra']['step'] . '"'; } $display .= $disabled . ' />'; break; case 'select': $multiple = !empty($item['multiple']) && $item['multiple'] == true ? 'multiple="multiple"' : ""; $brckt = ""; $width = 250; $selections = (array) $options->get($item['id']); if ($item['multiple']) { $brckt = "[]"; $width = 500; } $display .= '<select id="' . $item['id'] . '" class="fflcommerce-input fflcommerce-select ' . $class . '" name="' . FFLCOMMERCE_OPTIONS . '[' . $item['id'] . ']' . $brckt . '"' . $multiple . $disabled . ' >'; foreach ($item['choices'] as $value => $label) { if (is_array($label)) { $display .= '<optgroup label="' . $value . '">'; foreach ($label as $subValue => $subLabel) { $display .= '<option value="' . esc_attr($subValue) . '" ' . selected(in_array(esc_attr($subValue), $selections), true, false) . disabled(in_array($subValue, $disabledItems), true, false) . ' />' . $subLabel . '</option>'; } $display .= '</optgroup>'; } else { $display .= '<option value="' . esc_attr($value) . '" ' . selected(in_array(esc_attr($value), $selections), true, false) . disabled(in_array($value, $disabledItems), true, false) . ' />' . $label . '</option>'; } } $display .= '</select>'; $id = $item['id']; ?> <script type="text/javascript"> /*<![CDATA[*/ jQuery(function($){ $("#<?php echo $id; ?> ").select2({ width: '<?php echo $width; ?> px' }); }); /*]]>*/ </script> <?php break; default: fflcommerce_log("UNKOWN _type_ in Options parsing"); fflcommerce_log($item); } if ($item['type'] != 'tab') { if (empty($item['desc'])) { $explain_value = ''; } else { $explain_value = $item['desc']; } $display .= '<div class="fflcommerce-explain"><small>' . $explain_value . '</small></div></td>'; } return $display; }
/** * Validate the checkout */ public function validate_checkout() { if (fflcommerce_cart::is_empty()) { fflcommerce::add_error(sprintf(__('Sorry, your session has expired. <a href="%s">Return to homepage →</a>', 'fflcommerce'), home_url())); } // Process Discount Codes if (!empty($_POST['coupon_code'])) { $coupon = sanitize_title($_POST['coupon_code']); fflcommerce_cart::add_discount($coupon); } foreach (fflcommerce_cart::get_coupons() as $coupon) { fflcommerce_cart::is_valid_coupon($coupon); } // Checkout fields $this->posted['shipping_method'] = ''; $this->posted['shipping_service'] = ''; if (isset($_POST['shipping_method'])) { $shipping_method = fflcommerce_clean($_POST['shipping_method']); $shipping_data = explode(':', $shipping_method); $this->posted['shipping_method'] = $shipping_data[0]; $this->posted['shipping_service'] = $shipping_data[1]; } $this->posted['shiptobilling'] = isset($_POST['shiptobilling']) ? fflcommerce_clean($_POST['shiptobilling']) : ''; $this->posted['payment_method'] = isset($_POST['payment_method']) ? fflcommerce_clean($_POST['payment_method']) : ''; $this->posted['order_comments'] = isset($_POST['order_comments']) ? fflcommerce_clean($_POST['order_comments']) : ''; $this->posted['terms'] = isset($_POST['terms']) ? fflcommerce_clean($_POST['terms']) : ''; $this->posted['create_account'] = isset($_POST['create_account']) ? fflcommerce_clean($_POST['create_account']) : ''; $this->posted['account_username'] = isset($_POST['account_username']) ? fflcommerce_clean($_POST['account_username']) : ''; $this->posted['account_password'] = isset($_POST['account_password']) ? fflcommerce_clean($_POST['account_password']) : ''; $this->posted['account_password_2'] = isset($_POST['account_password_2']) ? fflcommerce_clean($_POST['account_password_2']) : ''; if (fflcommerce_cart::get_total(false) == 0) { $this->posted['payment_method'] = 'no_payment'; } // establish customer billing and shipping locations if (fflcommerce_cart::ship_to_billing_address_only()) { $this->posted['shiptobilling'] = 'true'; } $country = isset($_POST['billing_country']) ? fflcommerce_clean($_POST['billing_country']) : ''; $state = isset($_POST['billing_state']) ? fflcommerce_clean($_POST['billing_state']) : ''; $allowed_countries = FFLCommerce_Base::get_options()->get('fflcommerce_allowed_countries'); if ($allowed_countries === 'specific') { $specific_countries = FFLCommerce_Base::get_options()->get('fflcommerce_specific_allowed_countries'); if (!in_array($country, $specific_countries)) { fflcommerce::add_error(__('Invalid billing country.', 'fflcommerce')); return; } } if (fflcommerce_countries::country_has_states($country)) { $states = fflcommerce_countries::get_states($country); if (!in_array($state, array_keys($states))) { fflcommerce::add_error(__('Invalid billing state.', 'fflcommerce')); return; } } $postcode = isset($_POST['billing_postcode']) ? fflcommerce_clean($_POST['billing_postcode']) : ''; $ship_to_billing = FFLCommerce_Base::get_options()->get('fflcommerce_ship_to_billing_address_only') == 'yes'; fflcommerce_customer::set_location($country, $state, $postcode); if (FFLCommerce_Base::get_options()->get('fflcommerce_calc_shipping') == 'yes') { if ($ship_to_billing || !empty($_POST['shiptobilling'])) { fflcommerce_customer::set_shipping_location($country, $state, $postcode); } else { $country = isset($_POST['shipping_country']) ? fflcommerce_clean($_POST['shipping_country']) : ''; $state = isset($_POST['shipping_state']) ? fflcommerce_clean($_POST['shipping_state']) : ''; $postcode = isset($_POST['shipping_postcode']) ? fflcommerce_clean($_POST['shipping_postcode']) : ''; if ($allowed_countries === 'specific') { $specific_countries = FFLCommerce_Base::get_options()->get('fflcommerce_specific_allowed_countries'); if (!in_array($country, $specific_countries)) { fflcommerce::add_error(__('Invalid shipping country.', 'fflcommerce')); return; } } if (fflcommerce_countries::country_has_states($country)) { $states = fflcommerce_countries::get_states($country); if (!in_array($state, array_keys($states))) { fflcommerce::add_error(__('Invalid shipping state.', 'fflcommerce')); return; } } fflcommerce_customer::set_shipping_location($country, $state, $postcode); } } // Billing Information foreach ($this->billing_fields as $field) { $field = apply_filters('fflcommerce_billing_field', $field); $this->posted[$field['name']] = isset($_POST[$field['name']]) ? fflcommerce_clean($_POST[$field['name']]) : ''; // Format if (isset($field['format'])) { switch ($field['format']) { case 'postcode': $this->posted[$field['name']] = strtolower(str_replace(' ', '', $this->posted[$field['name']])); break; } } // Required if ($field['name'] == 'billing_state' && fflcommerce_customer::has_valid_shipping_state()) { $field['required'] = false; } if (isset($field['required']) && $field['required'] && empty($this->posted[$field['name']])) { fflcommerce::add_error($field['label'] . __(' (billing) is a required field.', 'fflcommerce')); } if ($field['name'] == 'billing_euvatno') { $vatno = isset($this->posted['billing_euvatno']) ? $this->posted['billing_euvatno'] : ''; $vatno = str_replace(' ', '', $vatno); $country = fflcommerce_tax::get_customer_country(); // strip any country code from the beginning of the number if (strpos($vatno, $country) === 0) { $vatno = substr($vatno, strlen($country)); } if ($vatno != '') { $url = 'http://isvat.appspot.com/' . $country . '/' . $vatno . '/'; $httpRequest = curl_init(); curl_setopt($httpRequest, CURLOPT_FAILONERROR, true); curl_setopt($httpRequest, CURLOPT_RETURNTRANSFER, true); curl_setopt($httpRequest, CURLOPT_HEADER, false); curl_setopt($httpRequest, CURLOPT_URL, $url); $result = curl_exec($httpRequest); curl_close($httpRequest); if ($result === 'false') { fflcommerce_log('EU VAT validation error with URL: ' . $url); fflcommerce::add_error($field['label'] . __(' (billing) is not a valid VAT Number. Leave it blank to disable VAT validation. (VAT may be charged depending on your location)', 'fflcommerce')); } else { $this->valid_euvatno = fflcommerce_countries::get_base_country() != fflcommerce_tax::get_customer_country() && fflcommerce_countries::is_eu_country(fflcommerce_tax::get_customer_country()); } } } // Validation if (isset($field['validate']) && !empty($this->posted[$field['name']])) { switch ($field['validate']) { case 'phone': if (!fflcommerce_validation::is_phone($this->posted[$field['name']])) { fflcommerce::add_error($field['label'] . __(' (billing) is not a valid number.', 'fflcommerce')); } break; case 'email': if (!fflcommerce_validation::is_email($this->posted[$field['name']])) { fflcommerce::add_error($field['label'] . __(' (billing) is not a valid email address.', 'fflcommerce')); } break; case 'postcode': if (!fflcommerce_validation::is_postcode($this->posted[$field['name']], $_POST['billing_country'])) { fflcommerce::add_error($field['label'] . __(' (billing) is not a valid postcode/ZIP.', 'fflcommerce')); } else { $this->posted[$field['name']] = fflcommerce_validation::format_postcode($this->posted[$field['name']], $_POST['billing_country']); } break; } } } // Shipping Information if (fflcommerce_shipping::is_enabled() && !fflcommerce_cart::ship_to_billing_address_only() && empty($this->posted['shiptobilling'])) { foreach ($this->shipping_fields as $field) { $field = apply_filters('fflcommerce_shipping_field', $field); if (isset($_POST[$field['name']])) { $this->posted[$field['name']] = fflcommerce_clean($_POST[$field['name']]); } else { $this->posted[$field['name']] = ''; } // Format if (isset($field['format'])) { switch ($field['format']) { case 'postcode': $this->posted[$field['name']] = strtolower(str_replace(' ', '', $this->posted[$field['name']])); break; } } // Required if ($field['name'] == 'shipping_state' && fflcommerce_customer::has_valid_shipping_state()) { $field['required'] = false; } if (isset($field['required']) && $field['required'] && empty($this->posted[$field['name']])) { fflcommerce::add_error($field['label'] . __(' (shipping) is a required field.', 'fflcommerce')); } // Validation if (isset($field['validate']) && !empty($this->posted[$field['name']])) { switch ($field['validate']) { case 'postcode': if (!fflcommerce_validation::is_postcode($this->posted[$field['name']], $country)) { fflcommerce::add_error($field['label'] . __(' (shipping) is not a valid postcode/ZIP.', 'fflcommerce')); } else { $this->posted[$field['name']] = fflcommerce_validation::format_postcode($this->posted[$field['name']], $country); } break; } } } } if ($this->must_register && empty($this->posted['create_account'])) { fflcommerce::add_error(__('Sorry, you must agree to creating an account', 'fflcommerce')); } if ($this->must_register || empty($user_id) && $this->posted['create_account']) { if (!$this->show_signup) { fflcommerce::add_error(__('Sorry, the shop owner has disabled guest purchases.', 'fflcommerce')); } if (empty($this->posted['account_username'])) { fflcommerce::add_error(__('Please enter an account username.', 'fflcommerce')); } if (empty($this->posted['account_password'])) { fflcommerce::add_error(__('Please enter an account password.', 'fflcommerce')); } if ($this->posted['account_password_2'] !== $this->posted['account_password']) { fflcommerce::add_error(__('Passwords do not match.', 'fflcommerce')); } // Check the username if (!validate_username($this->posted['account_username'])) { fflcommerce::add_error(__('Invalid email/username.', 'fflcommerce')); } elseif (username_exists($this->posted['account_username'])) { fflcommerce::add_error(__('An account is already registered with that username. Please choose another.', 'fflcommerce')); } // Check the e-mail address if (email_exists($this->posted['billing_email'])) { fflcommerce::add_error(__('An account is already registered with your email address. Please login.', 'fflcommerce')); } } // Terms if (!isset($_POST['update_totals']) && empty($this->posted['terms']) && fflcommerce_get_page_id('terms') > 0) { fflcommerce::add_error(__('You must accept our Terms & Conditions.', 'fflcommerce')); } if (fflcommerce_cart::needs_shipping()) { // Shipping Method $available_methods = fflcommerce_shipping::get_available_shipping_methods(); if (!isset($available_methods[$this->posted['shipping_method']])) { fflcommerce::add_error(__('Invalid shipping method.', 'fflcommerce')); } } }
/** * Successful payment processing * * @param array $posted */ function successful_request($posted) { $posted = stripslashes_deep($posted); // 'custom' holds post ID (Order ID) if (!empty($posted['custom']) && !empty($posted['txn_type']) && !empty($posted['invoice'])) { $accepted_types = array('cart', 'instant', 'express_checkout', 'web_accept', 'masspay', 'send_money', 'subscr_payment'); $order = new fflcommerce_order((int) $posted['custom']); // Sandbox fix if (isset($posted['test_ipn']) && $posted['test_ipn'] == 1 && strtolower($posted['payment_status']) == 'pending') { $posted['payment_status'] = 'completed'; } $merchant = $this->testmode == 'no' ? $this->email : $this->testemail; if ($order->status !== 'completed') { // We are here so lets check status and do actions switch (strtolower($posted['payment_status'])) { case 'completed': if (!in_array(strtolower($posted['txn_type']), $accepted_types)) { // Put this order on-hold for manual checking $order->update_status('on-hold', sprintf(__('PayPal Validation Error: Unknown "txn_type" of "%s" for Order ID: %s.', 'fflcommerce'), $posted['txn_type'], $posted['custom'])); exit; } if ($order->get_order_number() !== $posted['invoice']) { // Put this order on-hold for manual checking $order->update_status('on-hold', sprintf(__('PayPal Validation Error: Order Invoice Number does NOT match PayPal posted invoice (%s) for Order ID: .', 'fflcommerce'), $posted['invoice'], $posted['custom'])); exit; } // Validate Amount if (number_format((double) $order->order_total, $this->decimals, '.', '') != $posted['mc_gross']) { // Put this order on-hold for manual checking $order->update_status('on-hold', sprintf(__('PayPal Validation Error: Payment amounts do not match initial order (gross %s).', 'fflcommerce'), $posted['mc_gross'])); exit; } if (strcasecmp(trim($posted['business']), trim($merchant)) != 0) { // Put this order on-hold for manual checking $order->update_status('on-hold', sprintf(__('PayPal Validation Error: Payment Merchant email received does not match PayPal Gateway settings. (%s)', 'fflcommerce'), $posted['business'])); exit; } if (!in_array($posted['mc_currency'], apply_filters('fflcommerce_multi_currencies_available', array(FFLCommerce_Base::get_options()->get('fflcommerce_currency'))))) { // Put this order on-hold for manual checking $order->update_status('on-hold', sprintf(__('PayPal Validation Error: Payment currency received (%s) does not match Shop currency.', 'fflcommerce'), $posted['mc_currency'])); exit; } $order->add_order_note(__('PayPal Standard payment completed', 'fflcommerce')); $order->payment_complete(); fflcommerce_log('PAYPAL: IPN payment completed for Order ID: ' . $posted['custom']); break; case 'denied': case 'expired': case 'failed': case 'voided': // Failed order $order->update_status('failed', sprintf(__('Payment %s via IPN.', 'fflcommerce'), strtolower($posted['payment_status']))); fflcommerce_log("PAYPAL: failed order with status = " . strtolower($posted['payment_status']) . "for Order ID: " . $posted['custom']); break; case 'refunded': case 'reversed': case 'chargeback': fflcommerce_log("PAYPAL: payment status type - '" . $posted['payment_status'] . "' - not supported for Order ID: " . $posted['custom']); break; } } exit; } else { fflcommerce_log("PAYPAL: function 'successful_request' -- empty initial required values -- EXITING!\n'posted' values = " . print_r($posted, true)); } }
/** * Check WorldPay origins and payment response passwords * Used to log and send emails for possible security errors */ private function validate_response_origins_and_passwords() { $header_ip = $_SERVER['REMOTE_ADDR']; $header_host = gethostbyaddr($header_ip); $callbackPW = $this->get_post('callbackPW'); $validated = false; $error = array(); if (strpos($header_host, 'worldpay.com') !== false) { if (!empty($this->response_pass) && !empty($callbackPW)) { if ($this->response_pass == $callbackPW) { $validated = true; /* both passwords match */ } else { $error['validate_payment_password_error'] = sprintf(__('Your shop payment response password: \'%s\', WorldPay payment response password: \'%s\'. The passwords for Payment Response Password from your FFL Commerce WorldPay gateway settings and your WorldPay Merchant account do NOT match.', 'fflcommerce'), $callbackPW, $this->response_pass); fflcommerce_log($error['validate_payment_password_error'], 'WorldPay Gateway'); } } elseif (empty($this->response_pass) && empty($callbackPW)) { $validated = true; /* skip check if no passwords supplied */ } else { $error['validate_payment_password_missing'] = sprintf(__('Your shop payment response password: \'%s\', WorldPay payment response password: \'%s\'. If you are using a Payment Response Password, make sure it is entered in BOTH the WorldPay Gateway settings in FFL Commerce AND in your WorldPay Merchant Account.', 'fflcommerce'), $callbackPW, $this->response_pass); fflcommerce_log($error['validate_payment_password_missing'], 'WorldPay Gateway'); } } else { $error['validate_origin_error'] = sprintf(__('The Payment response came from IP: %s and Domain: %s -- and this does not appear to be a WorldPay domain.', 'fflcommerce'), $header_ip, $header_host); fflcommerce_log($error['validate_origin_error'], 'WorldPay Gateway'); } if ($this->receive_err_log == 'yes' && !$validated) { $info = sprintf(__('Order #%s ', 'fflcommerce'), $this->get_post('cartId')); $this->email_worldpay_error_logs($error, $_POST, $info); } return $validated; /* currently we don't actually use this */ }
/** * Successful Payment! */ public function successful_request($response, $order) { switch (strtoupper($response['OrderStatusCode'])) { case 'ACCEPTED': $order->add_order_note(__('Payment Authorized', 'fflcommerce')); fflcommerce_log("FuturePay: payment authorized for Order ID: " . $order->id); $order->payment_complete(); break; case 'DECLINED': // Hold order $order->update_status('on-hold', sprintf(__('Payment %s via FuturePay.', 'fflcommerce'), strtolower($response['OrderStatusCode']))); fflcommerce_log("FUTUREPAY: declined order for Order ID: " . $order->id); break; default: // Hold order $order->update_status('on-hold', sprintf(__('Payment %s via FuturePay.', 'fflcommerce'), strtolower($response['OrderStatusCode']))); fflcommerce_log("FUTUREPAY: failed order for Order ID: " . $order->id); break; } }
/** * Lists attributes in a html table * * @return string HTML code with attributes list. **/ public function list_attributes() { // Check that we have some attributes that are visible if (!($this->has_attributes() || $this->has_dimensions() || $this->has_weight())) { return false; } // Start the html output $html = '<table class="shop_attributes">'; // Output weight if we have it if (self::get_options()->get('fflcommerce_enable_weight') == 'yes' && $this->get_weight()) { $html .= '<tr><th>' . __('Weight', 'fflcommerce') . '</th><td>' . $this->get_weight() . self::get_options()->get('fflcommerce_weight_unit') . '</td></tr>'; } // Output dimensions if we have it if (self::get_options()->get('fflcommerce_enable_dimensions') == 'yes') { if ($this->get_length()) { $html .= '<tr><th>' . __('Length', 'fflcommerce') . '</th><td>' . $this->get_length() . self::get_options()->get('fflcommerce_dimension_unit') . '</td></tr>'; } if ($this->get_width()) { $html .= '<tr><th>' . __('Width', 'fflcommerce') . '</th><td>' . $this->get_width() . self::get_options()->get('fflcommerce_dimension_unit') . '</td></tr>'; } if ($this->get_height()) { $html .= '<tr><th>' . __('Height', 'fflcommerce') . '</th><td>' . $this->get_height() . self::get_options()->get('fflcommerce_dimension_unit') . '</td></tr>'; } } $attributes = $this->get_attributes(); foreach ($attributes as $attr) { // If attribute is invisible skip if (empty($attr['visible'])) { continue; } // Get Title & Value from attribute array $name = $this->attribute_label('pa_' . $attr['name']); $value = null; if ((bool) $attr['is_taxonomy']) { // Get the taxonomy terms $product_terms = wp_get_object_terms($this->ID, 'pa_' . sanitize_title($attr['name']), array('orderby' => 'slug')); if (is_wp_error($product_terms)) { fflcommerce_log("product::list_attributes() - Attribute for invalid taxonomy = " . $attr['name']); continue; } // Convert them into a array to be imploded $terms = array(); foreach ($product_terms as $term) { $terms[] = '<span class="val_' . $term->slug . '">' . $term->name . '</span>'; } $value = apply_filters('fflcommerce_product_attribute_value_taxonomy', implode(', ', $terms), $terms, $attr); } else { $value = apply_filters('fflcommerce_product_attribute_value_custom', wptexturize($attr['value']), $attr); } // Generate the remaining html $html .= "\n\t\t\t<tr class=\"attr_" . $attr['name'] . "\">\n\t\t\t\t<th>{$name}</th>\n\t\t\t\t<td>{$value}</td>\n\t\t\t</tr>"; } $html .= '</table>'; return $html; }
/** * Checks for a valid postcode for a country * * @param string postcode * @param string country * @return boolean */ public static function is_postcode($postcode, $country) { if (strlen(trim(preg_replace('/[\\s\\-A-Za-z0-9]/', '', $postcode))) > 0) { return false; } $country = strtoupper(trim($country)); $postcode = strtoupper(trim($postcode)); // Assume that unknown countries has proper postcodes if (!isset(self::$postcodes[$country]) && $country !== 'GB') { return true; } if (FFLCommerce_Base::get_options()->get('fflcommerce_enable_postcode_validating') == 'yes') { switch ($country) { case 'GB': fflcommerce_log("VALIDATE POSTCODE: country = GB"); return self::is_GB_postcode($postcode); default: $regex = '/^' . self::$postcodes[$country] . '$/'; fflcommerce_log("VALIDATE POSTCODE: country = " . $country . " & regex = " . $regex); $match = preg_match($regex, $postcode); if ($match !== 1) { return false; } } } return true; }