/**
  * Takes a heading and normalizes it based on the current importer type
  *
  * @since 1.0.0
  * @param string $heading
  * @return string
  */
 public static function normalize_heading($heading)
 {
     $s_heading = trim($heading);
     // lowercase and replace space with underscores if not a custom meta value
     if (!SV_WC_Helper::str_starts_with($s_heading, 'meta:')) {
         $s_heading = strtolower($heading);
         $s_heading = str_replace(' ', '_', $s_heading);
     }
     return $s_heading;
 }
 /**
  * Convert the request data into XML.
  *
  * @since 4.3.0
  * @return string
  */
 protected function to_xml()
 {
     if (!empty($this->request_xml)) {
         return $this->request_xml;
     }
     $this->xml = new XMLWriter();
     // Create XML document in memory
     $this->xml->openMemory();
     // Set XML version & encoding
     $this->xml->startDocument('1.0', 'UTF-8');
     $request_data = $this->get_request_data();
     SV_WC_Helper::array_to_xml($this->xml, $this->get_root_element(), $request_data[$this->get_root_element()]);
     $this->xml->endDocument();
     return $this->request_xml = $this->xml->outputMemory();
 }
 /**
  * Constructor
  *
  * @access public
  * @since  1.0
  * @param string : $account_sid : required
  * @param string $auth_token : required
  * @param string $from_number : required - number to send SMS messages from
  * @param array $options optional : API options
  * @return \WC_Twilio_SMS_API
  */
 public function __construct($account_sid, $auth_token, $from_number, $options = array())
 {
     $this->account_sid = $account_sid;
     $this->auth_token = $auth_token;
     // don't format to e.164, as the country code is not available
     $this->from_number = preg_replace('[\\D]', '', $from_number);
     // Format the Alphanumeric Sender ID if set
     if (isset($options['asid'])) {
         $asid = preg_replace('/[^a-zA-Z0-9 ]/', '', $options['asid']);
         $asid = SV_WC_Helper::str_truncate($asid, 11);
         $this->asid = $asid;
     }
     // Set Basic HTTP Auth
     $this->wp_remote_http_args['headers']['Authorization'] = sprintf('Basic %s', base64_encode($this->account_sid . ':' . $this->auth_token));
 }
 /**
  * Add free trial status to membership statuses
  *
  * @since 1.0.0
  * @param array $statuses Array of statuses
  * @return array Modified array of statuses
  */
 public function add_free_trial_status($statuses)
 {
     $statuses = SV_WC_Helper::array_insert_after($statuses, 'wcm-active', array('wcm-free_trial' => array('label' => _x('Free Trial', 'Membership Status', WC_Memberships::TEXT_DOMAIN), 'label_count' => _n_noop('Free Trial <span class="count">(%s)</span>', 'Free Trial <span class="count">(%s)</span>', WC_Memberships::TEXT_DOMAIN))));
     return $statuses;
 }
 /**
  * Adds debug messages to the page as a WC message/error, and / or to the WC Error log
  *
  * @since 2.0
  * @param string $message to add
  * @param string $display how to display message, defaults to `message`, options are:
  *   + `message` - display with WC message style, no formatting
  *   + `request` - display with WC message style and <pre> formatting
  *   + `response` - display with WC message style and XML/<pre> formatting
  *   + `error` - display with WC error style, no formatting
  */
 protected function log($message, $display = 'message')
 {
     // do nothing when debug mode is off or blank message
     if ('off' == $this->debug_mode || !$message) {
         return;
     }
     // add message to checkout page
     if ('checkout' === $this->debug_mode || 'both' === $this->debug_mode) {
         switch ($display) {
             case 'message':
                 SV_WC_Helper::wc_add_notice($message);
                 break;
             case 'request':
                 SV_WC_Helper::wc_add_notice(__('API Request: ', WC_Amazon_FPS::TEXT_DOMAIN) . '<br/><pre>' . $message . '</pre>');
                 break;
             case 'response':
                 $dom = new DOMDocument();
                 $dom->loadXML($message);
                 $dom->formatOutput = true;
                 SV_WC_Helper::wc_add_notice(__('API Response: ', WC_Amazon_FPS::TEXT_DOMAIN) . '<br/><pre>' . htmlspecialchars($dom->saveXML()) . '</pre>');
                 break;
             case 'error':
                 SV_WC_Helper::wc_add_notice($message, 'error');
                 break;
         }
     }
     // add message to WC log
     if ('log' === $this->debug_mode || 'both' === $this->debug_mode) {
         $GLOBALS['wc_amazon_fps']->log($message);
     }
 }
 /**
  * Handle any actions from the 'My Payment Methods' section on the
  * 'My Account' page
  *
  * @since 1.0.0
  */
 public function handle_my_payment_methods_actions()
 {
     assert($this->supports_tokenization());
     // pre-conditions
     if (!$this->is_available() || !$this->tokenization_enabled()) {
         return;
     }
     $token = isset($_GET['wc-' . $this->get_id_dasherized() . '-token']) ? trim($_GET['wc-' . $this->get_id_dasherized() . '-token']) : '';
     $action = isset($_GET['wc-' . $this->get_id_dasherized() . '-action']) ? $_GET['wc-' . $this->get_id_dasherized() . '-action'] : '';
     // process payment method actions
     if ($token && $action && !empty($_GET['_wpnonce']) && is_user_logged_in()) {
         // security check
         if (false === wp_verify_nonce($_GET['_wpnonce'], 'wc-' . $this->get_id_dasherized() . '-token-action')) {
             SV_WC_Helper::wc_add_notice(_x('There was an error with your request, please try again.', 'Supports direct payment method tokenization', $this->text_domain), 'error');
             wp_redirect(get_permalink(wc_get_page_id('myaccount')));
             exit;
         }
         // current logged in user
         $user_id = get_current_user_id();
         // handle deletion
         if ('delete' === $action) {
             if (!$this->remove_payment_token($user_id, $token)) {
                 SV_WC_Helper::wc_add_notice(_x('Error removing payment method', 'Supports direct payment method tokenization', $this->text_domain), 'error');
             } else {
                 SV_WC_Helper::wc_add_notice(_x('Payment method deleted.', 'Supports direct payment method tokenization', $this->text_domain));
             }
         }
         // handle default change
         if ('make-default' === $action) {
             $this->set_default_payment_token($user_id, $token);
         }
         // remove the query params
         wp_redirect(get_permalink(wc_get_page_id('myaccount')));
         exit;
     }
 }
 /**
  * Handle payment methods actions, e.g. deleting a payment method or setting
  * one as default
  *
  * @since 4.0.0
  */
 public function handle_payment_method_actions()
 {
     if (!$this->has_tokens) {
         return;
     }
     $token = isset($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-token']) ? trim($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-token']) : '';
     $action = isset($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-action']) ? $_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-action'] : '';
     // process payment method actions
     if ($token && $action && !empty($_GET['_wpnonce']) && is_user_logged_in()) {
         // security check
         if (false === wp_verify_nonce($_GET['_wpnonce'], 'wc-' . $this->get_plugin()->get_id_dasherized() . '-token-action')) {
             SV_WC_Helper::wc_add_notice(esc_html__('Oops, you took too long, please try again.', 'woocommerce-plugin-framework'), 'error');
             $this->redirect_to_my_account();
         }
         // current logged in user
         $user_id = get_current_user_id();
         $gateway = $this->get_plugin()->get_gateway_from_token($user_id, $token);
         // couldn't find an associated gateway for that token
         if (!is_object($gateway)) {
             SV_WC_Helper::wc_add_notice(esc_html__('There was an error with your request, please try again.', 'woocommerce-plugin-framework'), 'error');
             $this->redirect_to_my_account();
         }
         switch ($action) {
             // handle deletion
             case 'delete':
                 if (!$gateway->remove_payment_token($user_id, $token)) {
                     /* translators: Payment method as in a specific credit card, e-check or bank account */
                     SV_WC_Helper::wc_add_notice(esc_html__('Error removing payment method', 'woocommerce-plugin-framework'), 'error');
                 } else {
                     /* translators: Payment method as in a specific credit card, e-check or bank account */
                     SV_WC_Helper::wc_add_notice(esc_html__('Payment method deleted.', 'woocommerce-plugin-framework'));
                 }
                 break;
                 // set default payment method
             // set default payment method
             case 'make-default':
                 $gateway->set_default_payment_token($user_id, $token);
                 /* translators: Payment method as in a specific credit card, e-check or bank account */
                 SV_WC_Helper::wc_add_notice(esc_html__('Default payment method updated.', 'woocommerce-plugin-framework'));
                 break;
                 // custom actions
             // custom actions
             default:
                 /**
                  * My Payment Methods Custom Action.
                  *
                  * Fired when a custom action is requested for a payment method (e.g. other than delete/make default)
                  *
                  * @since 4.0.0
                  * @param \SV_WC_Payment_Gateway_My_Payment_Methods $this instance
                  */
                 do_action('wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_action_' . sanitize_title($action), $this);
                 break;
         }
         $this->redirect_to_my_account();
     }
 }
 /**
  * Adds debug messages to the page as a WC message/error, and/or to the WC Error log
  *
  * @since 1.0.0
  * @param string $message message to add
  * @param string $type how to add the message, options are:
  *     'message' (styled as WC message), 'error' (styled as WC Error)
  */
 public function add_debug_message($message, $type = 'message')
 {
     // do nothing when debug mode is off or no message
     if ('off' == $this->debug_off() || !$message) {
         return;
     }
     // add log message to WC logger if log/both is enabled
     if ($this->debug_log()) {
         $this->get_plugin()->log($message, $this->get_id());
     }
     // avoid adding notices when performing refunds, these occur in the admin as an Ajax call, so checking the current filter
     // is the only reliably way to do so
     if (in_array('wp_ajax_woocommerce_refund_line_items', $GLOBALS['wp_current_filter'])) {
         return;
     }
     // add debug message to woocommerce->errors/messages if checkout or both is enabled, the admin/Ajax check ensures capture charge transactions aren't logged as notices to the front end
     if (($this->debug_checkout() || 'error' === $type && $this->is_test_environment()) && (!is_admin() || is_ajax())) {
         if ('message' === $type) {
             SV_WC_Helper::wc_add_notice(str_replace("\n", "<br/>", htmlspecialchars($message)), 'notice');
         } else {
             // defaults to error message
             SV_WC_Helper::wc_add_notice(str_replace("\n", "<br/>", htmlspecialchars($message)), 'error');
         }
     }
 }
 /**
  * Entry method for the Add Payment Method feature flow. Note this is *not*
  * stubbed in the WC_Payment_Gateway abstract class, but is called if the
  * gateway declares support for it.
  *
  * @since 4.0.0
  */
 public function add_payment_method()
 {
     assert($this->supports_add_payment_method());
     $order = $this->get_order_for_add_payment_method();
     try {
         $result = $this->do_add_payment_method_transaction($order);
     } catch (SV_WC_Plugin_Exception $e) {
         $result = array('message' => sprintf(esc_html__('Oops, adding your new payment method failed: %s', 'woocommerce-plugin-framework'), $e->getMessage()), 'success' => false);
     }
     SV_WC_Helper::wc_add_notice($result['message'], $result['success'] ? 'success' : 'error');
     // if successful, redirect to the newly added method
     if ($result['success']) {
         // if this is WooCommerce 2.5.5 or older, redirect to the My Account page
         if (SV_WC_Plugin_Compatibility::is_wc_version_lt_2_6()) {
             $redirect_url = wc_get_page_permalink('myaccount');
             // otherwise, redirect to the Payment Methods page (WC 2.6+)
         } else {
             $redirect_url = wc_get_account_endpoint_url('payment-methods');
         }
         // otherwise, back to the Add Payment Method page
     } else {
         $redirect_url = wc_get_endpoint_url('add-payment-method');
     }
     wp_safe_redirect($redirect_url);
     exit;
 }
 /**
  * Write the given row to the CSV
  *
  * This is abstracted so the provided data can be matched to the CSV headers set and the CSV delimiter and
  * enclosure can be controlled from a single method
  *
  * @since 3.0
  * @param array $row
  */
 private function write($row)
 {
     $data = array();
     foreach ($this->headers as $header_key => $_) {
         if (!isset($row[$header_key])) {
             $row[$header_key] = '';
         }
         // strict string comparison, as values like '0' are valid
         $value = '' !== $row[$header_key] ? $row[$header_key] : '';
         // escape leading equals sign character with a single quote to prevent CSV injections, see http://www.contextis.com/resources/blog/comma-separated-vulnerabilities/
         if (SV_WC_Helper::str_starts_with($value, '=')) {
             $value = "'" . $value;
         }
         $data[] = $value;
     }
     fputcsv($this->stream, $data, $this->delimiter, $this->enclosure);
 }
 /**
  * Helper method to return the item description, which is composed of item
  * meta flattened into a comma-separated string, if available. Otherwise the
  * product SKU is included.
  *
  * The description is automatically truncated to the 127 char limit.
  *
  * @since 3.0.0
  * @param array $item cart or order item
  * @param \WC_Product $product product data
  * @return string
  */
 private function get_item_description($item, $product)
 {
     if (empty($item['item_meta'])) {
         // cart item
         $item_desc = WC()->cart->get_item_data($item, true);
         $item_desc = str_replace("\n", ', ', rtrim($item_desc));
     } else {
         // order item
         $item_meta = new WC_Order_Item_Meta($item['item_meta']);
         $item_meta = SV_WC_Plugin_Compatibility::get_formatted_item_meta($item_meta);
         if (!empty($item_meta)) {
             $item_desc = array();
             foreach ($item_meta as $meta) {
                 $item_desc[] = sprintf('%s: %s', $meta['label'], $meta['value']);
             }
             $item_desc = implode(', ', $item_desc);
         } else {
             $item_desc = is_callable(array($product, 'get_sku')) && $product->get_sku() ? sprintf(__('SKU: %s', WC_PayPal_Express::TEXT_DOMAIN), $product->get_sku()) : null;
         }
     }
     return SV_WC_Helper::str_truncate($item_desc, 127);
 }
 /**
  * Add any Intuit QBMS specific payment and transaction information as
  * class members of WC_Order instance.  Added members can include:
  *
  * $order->trans_request_id           - an application-supplied value that identifies the transaction
  * $order->intuit_qbms_test_condition - a convenience for testing error conditions while in test mode
  *
  * @since 1.0
  * @see WC_Gateway_Intuit_QBMS::get_order()
  * @param int $order_id order ID being processed
  * @return WC_Order object with payment and transaction information attached
  */
 public function get_order($order_id)
 {
     // add common order members
     $order = parent::get_order($order_id);
     // add intuit credit card-specific order members
     // a convenience for testing error conditions while in test mode, this is passed as the NameOnCard
     if ($this->is_environment('test') && SV_WC_Helper::get_post('wc-intuit-qbms-test-condition')) {
         $order->intuit_qbms_test_condition = SV_WC_Helper::get_post('wc-intuit-qbms-test-condition');
     }
     return $order;
 }
 /**
  * Add custom contribution columns
  *
  * @since 1.0.0
  * @param  array $columns
  * @return array
  */
 public function add_custom_contributions_columns(array $columns)
 {
     $columns = SV_WC_Helper::array_insert_after($columns, 'cb', array('type' => __('Type', WC_Product_Reviews_Pro::TEXT_DOMAIN)));
     $columns = SV_WC_Helper::array_insert_after($columns, 'comment', array('votes' => __('Votes', WC_Product_Reviews_Pro::TEXT_DOMAIN)));
     $columns = SV_WC_Helper::array_insert_after($columns, 'votes', array('flags' => _x('Flags', 'number of times contribution has been flagged', WC_Product_Reviews_Pro::TEXT_DOMAIN)));
     return $columns;
 }
 /**
  * Save the Admin User Edit screen payment token fields, if any
  *
  * @see SV_WC_Payment_Gateway_Plugin::maybe_add_user_profile_tokenization_fields()
  * @param SV_WC_Payment_Gateway $gateway the gateway instance
  * @param int $user_id identifies the user to save the settings for
  */
 protected function save_user_profile_tokenization_fields($gateway, $user_id)
 {
     foreach (array_keys($gateway->get_environments()) as $environment_id) {
         // deleting any payment tokens?
         $payment_tokens_deleted_name = 'wc_' . $gateway->get_id() . '_payment_tokens_deleted_' . $environment_id;
         $delete_payment_tokens = SV_WC_Helper::get_post($payment_tokens_deleted_name) ? explode(',', trim(SV_WC_Helper::get_post($payment_tokens_deleted_name), ',')) : array();
         // see whether we're deleting any
         foreach ($delete_payment_tokens as $token) {
             $gateway->remove_payment_token($user_id, $token, $environment_id);
         }
         // adding a new payment token?
         $payment_token_name = 'wc_' . $gateway->get_id() . '_payment_token_' . $environment_id;
         if (SV_WC_Helper::get_post($payment_token_name)) {
             $exp_date = explode('/', SV_WC_Helper::get_post('wc_' . $gateway->get_id() . '_payment_token_exp_date_' . $environment_id));
             // add the new payment token, making it active if this is the first card
             $gateway->add_payment_token($user_id, $gateway->build_payment_token(SV_WC_Helper::get_post($payment_token_name), array('type' => $gateway->is_credit_card_gateway() ? 'credit_card' : 'check', 'card_type' => SV_WC_Helper::get_post('wc_' . $gateway->get_id() . '_payment_token_type_' . $environment_id), 'last_four' => SV_WC_Helper::get_post('wc_' . $gateway->get_id() . '_payment_token_last_four_' . $environment_id), 'exp_month' => count($exp_date) > 1 ? sprintf('%02s', $exp_date[0]) : null, 'exp_year' => count($exp_date) > 1 ? $exp_date[1] : null)));
         }
     }
 }
 /**
  * Add payment data to the order.
  *
  * @since 2.4.0
  * @param int $order_id the order ID
  * @return \WC_Order
  */
 public function get_order($order_id)
 {
     $order = parent::get_order($order_id);
     if ($this->is_accept_js_enabled() && ($nonce = SV_WC_Helper::get_post('wc-' . $this->get_id_dasherized() . '-payment-nonce'))) {
         // expiry month/year
         list($order->payment->exp_month, $order->payment->exp_year) = array_map('trim', explode('/', SV_WC_Helper::get_post('wc-' . $this->get_id_dasherized() . '-expiry')));
         // card data
         $order->payment->card_type = SV_WC_Helper::get_post('wc-' . $this->get_id_dasherized() . '-card-type');
         $order->payment->account_number = $order->payment->last_four = SV_WC_Helper::get_post('wc-' . $this->get_id_dasherized() . '-last-four');
         // nonce data
         $order->payment->descriptor = SV_WC_Helper::get_post('wc-' . $this->get_id_dasherized() . '-payment-descriptor');
         $order->payment->nonce = $nonce;
     }
     return $order;
 }
 /**
  * Sanitize address fields by removing invalid UTF-8, direct response delimiter,
  * and truncate to field length limits
  *
  * @since 2.0.5
  * @param string $field_name address field name
  * @param array $field field data
  * @return string sanitized field
  */
 protected function sanitize_address_field($field_name, $field)
 {
     if ('phone' === $field_name) {
         $value = preg_replace('/\\D/', '', $field['value']);
     } else {
         // authorize.net claims to support unicode, but not all code points yet.
         // Unrecognized code points will display in their control panel with question marks
         $value = SV_WC_Helper::str_to_sane_utf8($field['value']);
     }
     // remove any usages of our hybrid direct response delimiter so as to not break response parsing
     // see WC_Authorize_Net_CIM_API_Profile_Response::parse_direct_response()
     $value = str_replace(':|:', '', $value);
     // truncate to field limits
     return $value ? SV_WC_Helper::str_truncate($value, $field['limit']) : null;
 }
 /**
  * Search for taxonomy terms and echo json
  *
  * @since 1.0.0
  */
 public function json_search_terms()
 {
     check_ajax_referer('search-terms', 'security');
     $term = (string) wc_clean(stripslashes(SV_WC_Helper::get_request('term')));
     $taxonomy = (string) wc_clean(SV_WC_Helper::get_request('taxonomy'));
     if (empty($term) || empty($taxonomy)) {
         die;
     }
     if (is_numeric($term)) {
         $args = array('hide_empty' => false, 'include' => array(0, $term));
     } else {
         $args = array('hide_empty' => false, 'search' => $term);
     }
     $terms = get_terms(array($taxonomy), $args);
     $found_terms = array();
     if ($terms) {
         foreach ($terms as $term) {
             $found_terms[$term->term_id] = $term->name;
         }
     }
     /**
      * Filter terms found for JSON (AJAX) search
      *
      * @since 1.0.0
      * @param array $found_terms Array of the found terms
      */
     $found_terms = apply_filters('wc_memberships_json_search_found_terms', $found_terms);
     wp_send_json($found_terms);
 }
 /** Create a void for the given $order
  *
  * @since 2.0.0
  * @param WC_Order $order order object
  */
 public function create_void(WC_Order $order)
 {
     $this->order = $order;
     $this->request_data = array('refId' => $order->id, 'transactionRequest' => array('transactionType' => self::VOID, 'refTransId' => $order->refund->trans_id, 'order' => array('invoiceNumber' => ltrim($this->order->get_order_number(), _x('#', 'hash before the order number', 'woocommerce-gateway-authorize-net-cim')), 'description' => SV_WC_Helper::str_truncate($this->order->refund->reason, 255))));
 }
 /**
  * Locates the WooCommerce template files from our templates directory
  *
  * @since 1.0.0
  * @param string $template Already found template
  * @param string $template_name Searchable template name
  * @param string $template_path Template path
  * @return string Search result for the template
  */
 public function locate_template($template, $template_name, $template_path)
 {
     // Only keep looking if no custom theme template was found or if
     // a default WooCommerce template was found.
     if (!$template || SV_WC_Helper::str_starts_with($template, WC()->plugin_path())) {
         // Set the path to our templates directory
         $plugin_path = $this->get_plugin_path() . '/templates/';
         // If a template is found, make it so
         if (is_readable($plugin_path . $template_name)) {
             $template = $plugin_path . $template_name;
         }
     }
     return $template;
 }
 /**
  * Process subscription renewal
  *
  * @since 4.1.0
  * @param float $amount_to_charge subscription amount to charge, could include multiple renewals if they've previously failed and the admin has enabled it
  * @param WC_Order $order original order containing the subscription
  * @param int $product_id the subscription product id
  */
 public function process_renewal_payment_1_5($amount_to_charge, $order, $product_id)
 {
     try {
         // set order defaults
         $order = $this->get_gateway()->get_order($order->id);
         // zero-dollar subscription renewal. weird, but apparently it happens
         if (0 == $amount_to_charge) {
             // add order note
             $order->add_order_note(sprintf(_x('%s0 Subscription Renewal Approved', 'Supports direct credit card subscriptions', $this->get_gateway()->get_text_domain()), get_woocommerce_currency_symbol()));
             // update subscription
             WC_Subscriptions_Manager::process_subscription_payments_on_order($order, $product_id);
             return;
         }
         // set the amount to charge, ensuring that we have a decimal point, even if it's 1.00
         $order->payment_total = SV_WC_Helper::number_format($amount_to_charge);
         // required
         if (!$order->payment->token || !$order->get_user_id()) {
             throw new SV_WC_Payment_Gateway_Exception('Subscription Renewal: Payment Token or User ID is missing/invalid.');
         }
         // get the token, we've already verified it's good
         $token = $this->get_gateway()->get_payment_token($order->get_user_id(), $order->payment->token);
         // perform the transaction
         if ($this->get_gateway()->is_credit_card_gateway()) {
             if ($this->get_gateway()->perform_credit_card_charge()) {
                 $response = $this->get_gateway()->get_api()->credit_card_charge($order);
             } else {
                 $response = $this->get_gateway()->get_api()->credit_card_authorization($order);
             }
         } elseif ($this->get_gateway()->is_echeck_gateway()) {
             $response = $this->get_gateway()->get_api()->check_debit($order);
         }
         // check for success
         if ($response->transaction_approved()) {
             // order note based on gateway type
             if ($this->get_gateway()->is_credit_card_gateway()) {
                 $message = sprintf(_x('%s %s Subscription Renewal Payment Approved: %s ending in %s (expires %s)', 'Supports direct credit card subscriptions', $this->get_gateway()->get_text_domain()), $this->get_gateway()->get_method_title(), $this->get_gateway()->perform_credit_card_authorization() ? 'Authorization' : 'Charge', $token->get_card_type() ? $token->get_type_full() : 'card', $token->get_last_four(), $token->get_exp_month() . '/' . $token->get_exp_year());
             } elseif ($this->get_gateway()->is_echeck_gateway()) {
                 // there may or may not be an account type (checking/savings) available, which is fine
                 $message = sprintf(_x('%s Check Subscription Renewal Payment Approved: %s account ending in %s', 'Supports direct cheque subscriptions', $this->get_gateway()->get_text_domain()), $this->get_gateway()->get_method_title(), $token->get_account_type(), $token->get_last_four());
             }
             // add order note
             $order->add_order_note($message);
             // set transaction ID manually, WCS 1.5.x calls WC_Order::payment_complete() internally
             if ($response->get_transaction_id()) {
                 update_post_meta($order->id, '_transaction_id', $response->get_transaction_id());
             }
             // update subscription
             WC_Subscriptions_Manager::process_subscription_payments_on_order($order, $product_id);
         } else {
             // failure
             throw new SV_WC_Payment_Gateway_Exception(sprintf('%s: %s', $response->get_status_code(), $response->get_status_message()));
         }
     } catch (SV_WC_Plugin_Exception $e) {
         // don't mark the order as failed, Subscriptions will handle marking the renewal order as failed
         $order->add_order_note(sprintf(_x('%s Renewal Payment Failed (%s)', $this->get_gateway()->get_text_domain()), $this->get_gateway()->get_method_title(), $e->getMessage()));
         // update subscription
         WC_Subscriptions_Manager::process_subscription_payment_failure_on_order($order, $product_id);
     }
 }
 /**
  * Returns true if the current page is the admin configuration page for the
  * gateway with class name $gateway_class_name
  *
  * Temporary home for this function, until all payment gateways are brought into the frameworked fold
  *
  * @since 3.0.0
  * @param string $gateway_class_name the gateway class name
  * @return boolean true if the current page is the admin configuration page for the gateway
  */
 public static function is_payment_gateway_configuration_page($gateway_class_name)
 {
     return 'wc-settings' == SV_WC_Helper::get_request('page') && 'checkout' == SV_WC_Helper::get_request('tab') && strtolower($gateway_class_name) == SV_WC_Helper::get_request('section');
 }
 /**
  * Maybe force TLS v1.2 requests.
  *
  * @since 4.4.0
  */
 public function set_tls_1_2_request($handle, $r, $url)
 {
     if (!SV_WC_Helper::str_starts_with($url, 'https://')) {
         return;
     }
     $versions = curl_version();
     $curl_version = $versions['version'];
     // Get the SSL details
     list($ssl_type, $ssl_version) = explode('/', $versions['ssl_version']);
     $ssl_version = substr($ssl_version, 0, -1);
     // If cURL and/or OpenSSL aren't up to the challenge, bail
     if (!version_compare($curl_version, '7.34.0', '>=') || 'OpenSSL' === $ssl_type && !version_compare($ssl_version, '1.0.1', '>=')) {
         return;
     }
     curl_setopt($handle, CURLOPT_SSLVERSION, 6);
 }
    /**
     * Render dropdowns for any filterable checkout add-ons
     *
     * @since 1.0
     */
    public function restrict_orders()
    {
        global $typenow;
        if ('shop_order' != $typenow) {
            return;
        }
        $javascript = '';
        foreach (wc_checkout_add_ons()->get_add_ons() as $add_on) {
            // if the add-on is filterable
            if ($add_on->is_filterable()) {
                if ($add_on->has_options()) {
                    // filterable multi item add-on field (select, multiselect, radio, checkbox), provide a dropdown
                    ?>
					<select name="<?php 
                    echo esc_attr($add_on->get_key());
                    ?>
" id="<?php 
                    echo esc_attr($add_on->get_key());
                    ?>
" class="wc-enhanced-select" data-placeholder="<?php 
                    echo __("Show all ", WC_Checkout_Add_Ons::TEXT_DOMAIN) . $add_on->name;
                    ?>
" data-allow_clear="true" style="min-width:200px;">
						<option value=""></option>
						<?php 
                    foreach ($add_on->get_options() as $option) {
                        if ('' === $option['value'] && '' === $option['label']) {
                            continue;
                        }
                        echo '<option value="' . $option['value'] . '" ' . (isset($_GET[$add_on->get_key()]) ? selected($option['value'], $_GET[$add_on->get_key()]) : '') . '>' . __($option['label'], WC_Checkout_Add_Ons::TEXT_DOMAIN) . '</option>';
                    }
                    ?>
					</select>
					<?php 
                    $javascript .= SV_WC_Plugin_Compatibility::is_wc_version_lt_2_3() ? "if ( \$().chosen ) { \$('select#" . $add_on->get_key() . "').chosen( {  allow_single_deselect: true  } ); }" : "";
                } elseif ($add_on->type == 'text') {
                    if (SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3()) {
                        ?>
						<input type="hidden" class="sv-wc-enhanced-search" name="<?php 
                        echo esc_attr($add_on->get_key());
                        ?>
" style="min-width:200px;"
							data-placeholder="<?php 
                        echo __("Show all ", WC_Checkout_Add_Ons::TEXT_DOMAIN) . $add_on->label;
                        ?>
"
							data-selected="<?php 
                        echo empty($_GET[$add_on->get_key()]) ? '' : $_GET[$add_on->get_key()];
                        ?>
"
							value="<?php 
                        echo empty($_GET[$add_on->get_key()]) ? '' : esc_attr($_GET[$add_on->get_key()]);
                        ?>
"
							data-allow_clear="true"
							data-action="wc_checkout_add_ons_json_search_field"
							data-nonce="<?php 
                        echo wp_create_nonce('search-field');
                        ?>
"
							data-request_data = "<?php 
                        echo esc_attr(json_encode(array('add_on_id' => $add_on->id, 'default' => addslashes(__('Show all ', WC_Checkout_Add_Ons::TEXT_DOMAIN) . $add_on->name))));
                        ?>
"
							/>
						<?php 
                        SV_WC_Helper::render_select2_ajax();
                    } else {
                        // search box dropdown
                        ?>
						<select id="<?php 
                        echo esc_attr($add_on->get_key());
                        ?>
" name="<?php 
                        echo esc_attr($add_on->get_key());
                        ?>
" data-placeholder="<?php 
                        echo __("Show all ", WC_Checkout_Add_Ons::TEXT_DOMAIN) . $add_on->name;
                        ?>
" data-allow_clear="true" style="min-width:200px;">
							<option value=""></option>
							<?php 
                        if (!empty($_GET[$add_on->get_key()])) {
                            echo '<option value="' . esc_attr($_GET[$add_on->get_key()]) . '" ';
                            selected(1, 1);
                            echo '>' . $_GET[$add_on->get_key()] . '</option>';
                        }
                        ?>
						</select>
						<?php 
                        $javascript .= "\n\t\t\t\t\t\t\t\$( 'select#" . $add_on->get_key() . "' ).ajaxChosen( {\n\t\t\t\t\t\t\t\tmethod:         'GET',\n\t\t\t\t\t\t\t\turl:            '" . admin_url('admin-ajax.php') . "',\n\t\t\t\t\t\t\t\tdataType:       'json',\n\t\t\t\t\t\t\t\tafterTypeDelay: '100',\n\t\t\t\t\t\t\t\tminTermLength:  1,\n\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\taction:     'wc_checkout_add_ons_json_search_field',\n\t\t\t\t\t\t\t\t\tsecurity:   '" . wp_create_nonce("search-field") . "',\n\t\t\t\t\t\t\t\t\trequest_data: { 'add_on_id' : '" . $add_on->id . "', 'default' : '" . addslashes(__('Show all ', WC_Checkout_Add_Ons::TEXT_DOMAIN) . $add_on->name) . "' },\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, function ( data ) {\n\n\t\t\t\t\t\t\t\tvar terms = {};\n\n\t\t\t\t\t\t\t\t\$.each( data, function ( i, val ) {\n\t\t\t\t\t\t\t\t\tterms[ i ] = val;\n\t\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t\treturn terms;\n\t\t\t\t\t\t\t}, {  allow_single_deselect: true } );";
                    }
                } elseif ($add_on->type == 'checkbox' || $add_on->type == 'file') {
                    $checked = isset($_GET[$add_on->get_key()]) && $_GET[$add_on->get_key()];
                    ?>
					<label class="wc-checkout-add-on-checkbox-filter">
						<input type="checkbox" id="<?php 
                    echo esc_attr($add_on->get_key());
                    ?>
" name="<?php 
                    echo esc_attr($add_on->get_key());
                    ?>
" value="1" <?php 
                    checked($checked);
                    ?>
>
						<?php 
                    echo $add_on->name;
                    ?>
					</label>
					<?php 
                }
            }
        }
        // filterable dropdown javascript
        wc_enqueue_js($javascript);
    }
 /**
  * Process subscription renewal
  *
  * @since  1.4
  * @param float $amount_to_charge subscription amount to charge, could include
  *              multiple renewals if they've previously failed and the admin
  *              has enabled it
  * @param WC_Order $order original order containing the subscription
  * @param int $product_id the ID of the subscription product
  */
 public function process_renewal_payment($amount_to_charge, $order, $product_id = null)
 {
     require_once 'class-wc-realex-api.php';
     $realex_subscription_count = 0;
     if (is_numeric($order->realex_subscription_count) && $order->realex_subscription_count) {
         $realex_subscription_count = $order->realex_subscription_count;
     }
     // increment the subscription count so we don't get order number clashes
     $realex_subscription_count++;
     update_post_meta($order->id, '_realex_subscription_count', $realex_subscription_count);
     // set custom class member used by the realex gateway
     $order->payment_total = SV_WC_Helper::number_format($amount_to_charge);
     // zero-dollar subscription renewal.  weird, but apparently it happens -- only applicable to Subs 1.5.x
     if (!SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) {
         if (0 == $order->payment_total) {
             // add order note
             $order->add_order_note(sprintf(__('%s0 Subscription Renewal Approved', 'woocommerce-gateway-realex'), get_woocommerce_currency_symbol()));
             // update subscription
             WC_Subscriptions_Manager::process_subscription_payments_on_order($order, $product_id);
             return;
         }
     }
     // This order is missing a tokenized card, lets see whether there's one available for the customer
     if (!get_post_meta($order->id, '_realex_cardref', true)) {
         $credit_cards = get_user_meta($order->get_user_id(), 'woocommerce_realex_cc', true);
         if (is_array($credit_cards)) {
             $card_ref = (object) current($credit_cards);
             $card_ref = $card_ref->ref;
             update_post_meta($order->id, '_realex_cardref', $card_ref);
             if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) {
                 foreach (wcs_get_subscriptions_for_renewal_order($order) as $subscription) {
                     update_post_meta($subscription->id, '_realex_cardref', $card_ref);
                 }
             }
         }
     }
     // create the realex api client
     $realex_client = new Realex_API($this->get_endpoint_url(), $this->get_realvault_endpoint_url(), $this->get_shared_secret());
     // create the customer/cc tokens, and authorize the initial payment amount, if any
     $response = $this->authorize($realex_client, $order);
     if ($response && '00' == $response->result) {
         // add order note
         $order->add_order_note(sprintf(__('Credit Card Subscription Renewal Payment Approved (Payment Reference: %s) ', 'woocommerce-gateway-realex'), $response->pasref));
         // update subscription
         if (SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) {
             $order->payment_complete((string) $response->pasref);
         } else {
             WC_Subscriptions_Manager::process_subscription_payments_on_order($order, $product_id);
         }
     } else {
         // generate the result message
         $message = __('Credit Card Subscription Renewal Payment Failed', 'woocommerce-gateway-realex');
         /* translators: Placeholders: %1$s - result, %2$s - result message */
         if ($response) {
             $message .= sprintf(__(' (Result: %1$s - "%2$s").', 'woocommerce-gateway-realex'), $response->result, $response->message);
         }
         $order->add_order_note($message);
         // update subscription
         if (!SV_WC_Plugin_Compatibility::is_wc_subscriptions_version_gte_2_0()) {
             WC_Subscriptions_Manager::process_subscription_payment_failure_on_order($order, $product_id);
         }
     }
 }
 /**
  * Handle payment methods actions, e.g. deleting a payment method or setting
  * one as default
  *
  * @since 4.0.0
  */
 public function handle_payment_method_actions()
 {
     if (!$this->has_tokens) {
         return;
     }
     $token = isset($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-token']) ? trim($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-token']) : '';
     $action = isset($_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-action']) ? $_GET['wc-' . $this->get_plugin()->get_id_dasherized() . '-action'] : '';
     // process payment method actions
     if ($token && $action && !empty($_GET['_wpnonce']) && is_user_logged_in()) {
         // security check
         if (false === wp_verify_nonce($_GET['_wpnonce'], 'wc-' . $this->get_plugin()->get_id_dasherized() . '-token-action')) {
             SV_WC_Helper::wc_add_notice(_x('Oops, you took too long, please try again.', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()), 'error');
             $this->redirect_to_my_account();
         }
         // current logged in user
         $user_id = get_current_user_id();
         $gateway = $this->get_plugin()->get_gateway_from_token($user_id, $token);
         // couldn't find an associated gateway for that token
         if (!is_object($gateway)) {
             SV_WC_Helper::wc_add_notice(_x('There was an error with your request, please try again.', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()), 'error');
             $this->redirect_to_my_account();
         }
         switch ($action) {
             // handle deletion
             case 'delete':
                 if (!$gateway->remove_payment_token($user_id, $token)) {
                     SV_WC_Helper::wc_add_notice(_x('Error removing payment method', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()), 'error');
                 } else {
                     SV_WC_Helper::wc_add_notice(_x('Payment method deleted.', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()));
                 }
                 break;
                 // set default payment method
             // set default payment method
             case 'make-default':
                 $gateway->set_default_payment_token($user_id, $token);
                 SV_WC_Helper::wc_add_notice(_x('Default payment method updated.', 'Supports my payment method feature', $this->get_plugin()->get_text_domain()));
                 break;
                 // custom actions
             // custom actions
             default:
                 do_action('wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_action_' . sanitize_title($action), $this);
                 break;
         }
         $this->redirect_to_my_account();
     }
 }
 /**
  * Add 'Social Profiles' column to the Users admin table
  *
  * @since 1.3.0
  * @param array $columns user admin table columns
  * @return array $columns columns array with 'Social Profiles'
  */
 public function add_user_columns($columns)
 {
     return SV_WC_Helper::array_insert_after($columns, 'email', array('wc_social_login_profiles' => __('Social Profiles', WC_Social_Login::TEXT_DOMAIN)));
 }
 /**
  * Entry method for the Add Payment Method feature flow. Note this is *not*
  * stubbed in the WC_Payment_Gateway abstract class, but is called if the
  * gateway declares support for it.
  *
  * @since 4.0.0
  */
 public function add_payment_method()
 {
     assert($this->supports_add_payment_method());
     $order = $this->get_order_for_add_payment_method();
     try {
         $result = $this->do_add_payment_method_transaction($order);
     } catch (SV_WC_Plugin_Exception $e) {
         $result = array('message' => sprintf(__('Oops, adding your new payment method failed: %s', $this->text_domain), $e->getMessage()), 'success' => false);
     }
     SV_WC_Helper::wc_add_notice($result['message'], $result['success'] ? 'success' : 'error');
     // redirect to my account on success, or back to Add Payment Method screen on failure so user can try again
     wp_safe_redirect($result['success'] ? SV_WC_Plugin_Compatibility::wc_get_page_permalink('myaccount') : wc_get_endpoint_url('add-payment-method'));
     exit;
 }
Example #28
0
 /**
  *
  * @dataProvider provider_test_str_starts_with_false
  */
 public function test_str_starts_with_false($haystack, $needle)
 {
     $this->assertFalse(\SV_WC_Helper::str_starts_with($haystack, $needle));
 }
 /**
  * Helper function to determine whether a plugin is active
  *
  * @since 2.0.0
  * @param string $plugin_name plugin name, as the plugin-filename.php
  * @return boolean true if the named plugin is installed and active
  */
 public function is_plugin_active($plugin_name)
 {
     $active_plugins = (array) get_option('active_plugins', array());
     if (is_multisite()) {
         $active_plugins = array_merge($active_plugins, array_keys(get_site_option('active_sitewide_plugins', array())));
     }
     $plugin_filenames = array();
     foreach ($active_plugins as $plugin) {
         if (SV_WC_Helper::str_exists($plugin, '/')) {
             // normal plugin name (plugin-dir/plugin-filename.php)
             list(, $filename) = explode('/', $plugin);
         } else {
             // no directory, just plugin file
             $filename = $plugin;
         }
         $plugin_filenames[] = $filename;
     }
     return in_array($plugin_name, $plugin_filenames);
 }
 /**
  * Upgrade to the currently installed version
  *
  * @since 2.0.0
  * @param string $installed_version currently installed version
  */
 public function upgrade($installed_version)
 {
     // upgrade to 2.0.0
     if (version_compare($installed_version, '2.0.0', '<')) {
         $this->log('Starting upgrade to 2.0.0');
         /** Upgrade settings */
         $old_cc_settings = get_option('woocommerce_authorize_net_cim_settings');
         $old_echeck_settings = get_option('woocommerce_authorize_net_cim_echeck_settings');
         if ($old_cc_settings) {
             // prior to 2.0.0, there was no settings for tokenization (always on) and enable_customer_decline_messages.
             // eCheck settings were inherited from the credit card gateway by default
             // credit card
             $new_cc_settings = array('enabled' => isset($old_cc_settings['enabled']) && 'yes' === $old_cc_settings['enabled'] ? 'yes' : 'no', 'title' => !empty($old_cc_settings['title']) ? $old_cc_settings['title'] : 'Credit Card', 'description' => !empty($old_cc_settings['description']) ? $old_cc_settings['description'] : 'Pay securely using your credit card.', 'enable_csc' => isset($old_cc_settings['require_cvv']) && 'yes' === $old_cc_settings['require_cvv'] ? 'yes' : 'no', 'transaction_type' => isset($old_cc_settings['transaction_type']) && 'auth_capture' === $old_cc_settings['transaction_type'] ? 'charge' : 'authorization', 'card_types' => !empty($old_cc_settings['card_types']) ? $old_cc_settings['card_types'] : array('VISA', 'MC', 'AMEX', 'DISC'), 'tokenization' => 'yes', 'environment' => isset($old_cc_settings['test_mode']) && 'yes' === $old_cc_settings['test_mode'] ? 'test' : 'production', 'inherit_settings' => 'no', 'api_login_id' => !empty($old_cc_settings['api_login_id']) ? $old_cc_settings['api_login_id'] : '', 'api_transaction_key' => !empty($old_cc_settings['api_transaction_key']) ? $old_cc_settings['api_transaction_key'] : '', 'test_api_login_id' => !empty($old_cc_settings['test_api_login_id']) ? $old_cc_settings['test_api_login_id'] : '', 'test_api_transaction_key' => !empty($old_cc_settings['test_api_transaction_key']) ? $old_cc_settings['test_api_transaction_key'] : '', 'enable_customer_decline_messages' => 'no', 'debug_mode' => !empty($old_cc_settings['debug_mode']) ? $old_cc_settings['debug_mode'] : 'off');
             // eCheck
             $new_echeck_settings = array('enabled' => isset($old_echeck_settings['enabled']) && 'yes' === $old_echeck_settings['enabled'] ? 'yes' : 'no', 'title' => !empty($old_echeck_settings['title']) ? $old_echeck_settings['title'] : 'eCheck', 'description' => !empty($old_echeck_settings['description']) ? $old_echeck_settings['description'] : 'Pay securely using your checking account.', 'tokenization' => 'yes', 'environment' => $new_cc_settings['environment'], 'inherit_settings' => 'yes', 'api_login_id' => '', 'api_transaction_key' => '', 'test_api_login_id' => '', 'test_api_transaction_key' => '', 'enable_customer_decline_messages' => 'no', 'debug_mode' => $new_cc_settings['debug_mode']);
             // save new settings, remove old ones
             update_option('woocommerce_authorize_net_cim_credit_card_settings', $new_cc_settings);
             update_option('woocommerce_authorize_net_cim_echeck_settings', $new_echeck_settings);
             delete_option('woocommerce_authorize_net_cim_settings');
             $this->log('Settings upgraded.');
         }
         /** Update meta key for customer profile ID and shipping profile ID */
         global $wpdb;
         // old key: _wc_authorize_net_cim_profile_id
         // new key: wc_authorize_net_cim_customer_profile_id
         // note that we don't know on a per-user basis what environment the customer ID was set in, so we assume production, just to be safe
         $rows = $wpdb->update($wpdb->usermeta, array('meta_key' => 'wc_authorize_net_cim_customer_profile_id'), array('meta_key' => '_wc_authorize_net_cim_profile_id'));
         $this->log(sprintf('%d users updated for customer profile ID.', $rows));
         // old key: _wc_authorize_net_cim_shipping_profile_id
         // new key: wc_authorize_net_cim_shipping_address_id
         $rows = $wpdb->update($wpdb->usermeta, array('meta_key' => 'wc_authorize_net_cim_shipping_address_id'), array('meta_key' => '_wc_authorize_net_cim_shipping_profile_id'));
         $this->log(sprintf('%d users updated for shipping address ID', $rows));
         /** Update meta values for order payment method & recurring payment method */
         // meta key: _payment_method
         // old value: authorize_net_cim
         // new value: authorize_net_cim_credit_card
         // note that the eCheck method has not changed from 1.x to 2.x
         $rows = $wpdb->update($wpdb->postmeta, array('meta_value' => 'authorize_net_cim_credit_card'), array('meta_key' => '_payment_method', 'meta_value' => 'authorize_net_cim'));
         $this->log(sprintf('%d orders updated for payment method meta', $rows));
         // meta key: _recurring_payment_method
         // old value: authorize_net_cim
         // new value: authorize_net_cim_credit_card
         $rows = $wpdb->update($wpdb->postmeta, array('meta_value' => 'authorize_net_cim_credit_card'), array('meta_key' => '_recurring_payment_method', 'meta_value' => 'authorize_net_cim'));
         $this->log(sprintf('%d orders updated for recurring payment method meta', $rows));
         /** Convert payment profiles stored in legacy format to framework payment token format */
         $this->log('Starting payment profile upgrade.');
         $user_ids = $wpdb->get_col("SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = '_wc_authorize_net_cim_payment_profiles'");
         if ($user_ids) {
             // iterate through each user with a payment profile
             foreach ($user_ids as $user_id) {
                 $customer_profile_id = get_user_meta($user_id, 'wc_authorize_net_cim_customer_profile_id', true);
                 $payment_profiles = get_user_meta($user_id, '_wc_authorize_net_cim_payment_profiles', true);
                 $cc_tokens = $echeck_tokens = array();
                 // iterate through each payment profile
                 foreach ($payment_profiles as $profile_id => $profile) {
                     // bail if corrupted
                     if (!$profile_id || empty($profile['type'])) {
                         continue;
                     }
                     // parse expiry date
                     if (!empty($profile['exp_date']) && SV_WC_Helper::str_exists($profile['exp_date'], '/')) {
                         list($exp_month, $exp_year) = explode('/', $profile['exp_date']);
                     } else {
                         $exp_month = $exp_year = '';
                     }
                     if ('Bank Account' === $profile['type']) {
                         // eCheck tokens
                         $echeck_tokens[$profile_id] = array('type' => 'echeck', 'last_four' => !empty($profile['last_four']) ? $profile['last_four'] : '', 'customer_profile_id' => $customer_profile_id, 'billing_hash' => '', 'payment_hash' => '', 'default' => !empty($profile['active']) && $profile['active'], 'exp_month' => $exp_month, 'exp_year' => $exp_year);
                     } else {
                         // parse card type
                         switch ($profile['type']) {
                             case 'Visa':
                                 $card_type = 'visa';
                                 break;
                             case 'American Express':
                                 $card_type = 'amex';
                                 break;
                             case 'MasterCard':
                                 $card_type = 'mc';
                                 break;
                             case 'Discover':
                                 $card_type = 'disc';
                                 break;
                             case 'Diners Club':
                                 $card_type = 'diners';
                                 break;
                             case 'JCB':
                                 $card_type = 'jcb';
                                 break;
                             default:
                                 $card_type = '';
                         }
                         // credit card tokens
                         $cc_tokens[$profile_id] = array('type' => 'credit_card', 'last_four' => !empty($profile['last_four']) ? $profile['last_four'] : '', 'customer_profile_id' => $customer_profile_id, 'billing_hash' => '', 'payment_hash' => '', 'default' => !empty($profile['active']) && $profile['active'], 'card_type' => $card_type, 'exp_month' => $exp_month, 'exp_year' => $exp_year);
                     }
                 }
                 // update credit card tokens
                 if (!empty($cc_tokens)) {
                     update_user_meta($user_id, '_wc_authorize_net_cim_credit_card_payment_tokens', $cc_tokens);
                 }
                 // update eCheck tokens
                 if (!empty($echeck_tokens)) {
                     update_user_meta($user_id, '_wc_authorize_net_cim_echeck_payment_tokens', $echeck_tokens);
                 }
                 // save the legacy payment profiles in case we need them later
                 update_user_meta($user_id, '_wc_authorize_net_cim_legacy_tokens', $payment_profiles);
                 delete_user_meta($user_id, '_wc_authorize_net_cim_payment_profiles');
                 $this->log(sprintf('Converted payment profile for user ID: %s', $user_id));
             }
         }
         $this->log('Completed payment profile upgrade.');
         $this->log('Completed upgrade for 2.0.0');
     }
     // TODO: remove _wc_authorize_net_cim_legacy_tokens meta in a future version @MR 2015-07
 }