/**
  * Add refund information as class members of WC_Order
  * instance for use in refund transactions.  Standard information includes:
  *
  * $order->refund->amount = refund amount
  * $order->refund->reason = user-entered reason text for the refund
  * $order->refund->trans_id = the ID of the original payment transaction for the order
  *
  * Payment gateway implementations can override this to add their own
  * refund-specific data
  *
  * @since 3.1.0
  * @param WC_Order|int $order order being processed
  * @param float $amount refund amount
  * @param string $reason optional refund reason text
  * @return WC_Order object with refund information attached
  */
 protected function get_order_for_refund($order, $amount, $reason)
 {
     if (is_numeric($order)) {
         $order = SV_WC_Plugin_Compatibility::wc_get_order($order);
     }
     // add refund info
     $order->refund = new stdClass();
     $order->refund->amount = number_format($amount, 2, '.', '');
     $order->refund->reason = $reason ? $reason : sprintf(_x('%s - Refund for Order %s', 'Order refund description', $this->text_domain), esc_html(get_bloginfo('name')), $order->get_order_number());
     // almost all gateways require the original transaction ID, so include it by default
     $order->refund->trans_id = $this->get_order_meta($order->id, 'trans_id');
     return apply_filters('wc_payment_gateway_' . $this->get_id() . '_get_order_for_refund', $order, $this);
 }
 /**
  * Process the payment and return the result
  *
  * @see WC_Payment_Gateway::process_payment()
  * @param int $order_id the order identifier
  */
 public function process_payment($order_id)
 {
     $order = SV_WC_Plugin_Compatibility::wc_get_order($order_id);
     require_once 'class-wc-elavon-vm-api.php';
     // create the elavon vm api client
     $elavon_client = new Elavon_VM_API($this->get_endpoint_url(), $this->get_ssl_merchant_id(), $this->get_ssl_user_id(), $this->get_ssl_pin(), $this->log_enabled());
     $response = $this->transaction_request($elavon_client, $order);
     if ($response) {
         if ($this->log_enabled()) {
             wc_elavon_vm()->log("Response:\n" . print_r($response, true));
         }
         if ('0' == $response->ssl_result) {
             // Successful payment
             // if debug mode load the response into the messages object
             if ($this->is_debug_mode()) {
                 $this->response_debug_message($response, 'message', true);
             }
             // update the order record with success
             $order->add_order_note(sprintf(__('Credit Card Transaction Approved: %s (%s)', WC_Elavon_VM::TEXT_DOMAIN), $response->ssl_card_number, substr($response->ssl_exp_date, 0, 2) . '/' . substr($response->ssl_exp_date, 2)));
             // store the payment reference and card number in the order
             update_post_meta($order->id, '_elavon_txn_id', (string) $response->ssl_txn_id);
             update_post_meta($order->id, '_elavon_card_number', (string) $response->ssl_card_number);
             update_post_meta($order->id, '_elavon_account', (string) $this->account);
             $order->payment_complete();
             WC()->cart->empty_cart();
             // Return thank you redirect
             return array('result' => 'success', 'redirect' => $this->get_return_url($order));
         } else {
             if ($response->ssl_result || $response->ssl_result_message) {
                 $error_note = sprintf(__('Elavon VM Credit Card payment failed (Result: [%s] - "%s").', WC_Elavon_VM::TEXT_DOMAIN), $response->ssl_result, $response->ssl_result_message);
             } else {
                 $error_note = sprintf(__('Elavon VM Credit Card payment failed (Result: [%s] %s - "%s").', WC_Elavon_VM::TEXT_DOMAIN), $response->errorCode, $response->errorName, $response->errorMessage);
             }
             if ('CALL AUTH CENTER' == $response->ssl_result_message || 'CALL REF:' == substr($response->ssl_result_message, 0, 9)) {
                 // voice authorization required
                 $error_note .= __('Voice authorization required to complete transaction, please call your merchant account.', WC_Elavon_VM::TEXT_DOMAIN);
                 $order->update_status('on-hold', $error_note);
             } else {
                 // default behavior
                 $this->order_failed($order, $error_note);
             }
             // default customer message
             $message = __('An error occurred, please try again or try an alternate form of payment', WC_Elavon_VM::TEXT_DOMAIN);
             // specific customer message
             if ('CALL AUTH CENTER' == $response->ssl_result_message || 'CALL REF:' == substr($response->ssl_result_message, 0, 9)) {
                 // voice authorization required
                 $message = __('This transaction request has not been approved. You may elect to use another form of payment to complete this transaction or contact customer service for additional options.', WC_Elavon_VM::TEXT_DOMAIN);
             }
             wc_add_notice($message, 'error');
             // if debug mode load the response into the messages object
             if ($this->is_debug_mode()) {
                 $this->response_debug_message($response, 'error');
             }
         }
     } else {
         if ($this->log_enabled()) {
             wc_elavon_vm()->log("ERROR: No response received");
         }
         wc_add_notice(__('Connection error', WC_Elavon_VM::TEXT_DOMAIN), 'error');
     }
 }
 /**
  * Add Amazon-specific data to the order object
  *
  * @since 2.0
  * @param int $order_id order ID being processed
  * @return \WC_Order instance
  */
 protected function get_order($order_id)
 {
     $order = SV_WC_Plugin_Compatibility::wc_get_order($order_id);
     // set the order total here so it can be modified later by Subscriptions if needed
     $order->amazon_order_total = number_format($order->get_total(), 2, '.', '');
     // set the order ID here so it can be modified for subscription renewal payments, which require a unique ID per transaction
     $order->amazon_caller_reference = $order->id;
     // get the URL that Amazon will redirect customer to after they've authorized the payment
     $order->amazon_return_url = $this->get_return_url($order);
     // set a description, note this can be filtered using the `wc_amazon_fps_cbui_pipeline_parameters` inside the base CBUI class
     $order->amazon_description = sprintf(__('%s - Order %s', WC_Amazon_FPS::TEXT_DOMAIN), esc_html(get_bloginfo('name')), $order->get_order_number());
     // set the IPN URL for each order so customer doesn't need to configure it within their amazon account
     $order->amazon_ipn_url = $this->get_ipn_url();
     return $order;
 }
 /**
  * Gets the payment URL: the checkout pay page
  *
  * @since 2.1.0
  * @param int $order_id the order id
  * @return string the payment URL, or false if unavailable
  */
 protected function get_payment_url($order_id)
 {
     if ($this->use_form_post()) {
         // the checkout pay page
         $order = SV_WC_Plugin_Compatibility::wc_get_order($order_id);
         return $order->get_checkout_payment_url(true);
     } else {
         // setup the order object
         $order = $this->get_order($order_id);
         // direct-redirect, so append the hosted pay page params to the hosted pay page url
         $pay_page_url = $this->get_hosted_pay_page_url($order);
         if ($pay_page_url) {
             return add_query_arg($this->get_hosted_pay_page_params($order), $pay_page_url);
         }
     }
     return false;
 }
 /**
  * Process the 'Capture Charge' custom bulk action on the Orders screen
  * bulk action select
  *
  * @since 2.1.0
  */
 public function process_capture_charge_bulk_order_action()
 {
     global $typenow;
     if ('shop_order' == $typenow) {
         // get the action
         $wp_list_table = _get_list_table('WP_Posts_List_Table');
         $action = $wp_list_table->current_action();
         // bail if not processing a capture
         if ('wc_capture_charge' !== $action) {
             return;
         }
         // security check
         check_admin_referer('bulk-posts');
         // make sure order IDs are submitted
         if (isset($_REQUEST['post'])) {
             $order_ids = array_map('absint', $_REQUEST['post']);
         }
         // return if there are no orders to export
         if (empty($order_ids)) {
             return;
         }
         // give ourselves an unlimited timeout if possible
         @set_time_limit(0);
         foreach ($order_ids as $order_id) {
             $order = SV_WC_Plugin_Compatibility::wc_get_order($order_id);
             $this->maybe_capture_charge($order);
         }
     }
 }
 /**
  * Returns any configured order fields
  *
  * @since 1.0
  * @param int $order_id optional order identifier, if provided any set values are loaded
  * @return array of WC_Custom_Order_Field objects
  */
 public function get_order_fields($order_id = null)
 {
     $order_fields = array();
     // get the order object if we can
     $order = $order_id ? SV_WC_Plugin_Compatibility::wc_get_order($order_id) : null;
     $custom_order_fields = get_option('wc_admin_custom_order_fields');
     if (!is_array($custom_order_fields)) {
         $custom_order_fields = array();
     }
     foreach ($custom_order_fields as $field_id => $field) {
         $order_field = new WC_Custom_Order_Field($field_id, $field);
         // if getting the fields for an order, does the order have a value set?
         if ($order instanceof WC_Order) {
             // WC 2.1+ uses magic methods which already prefix the key with a leading underscore
             // which needs to be removed prior to getting the value
             $meta_key = ltrim($order_field->get_meta_key(), '_');
             if (isset($order->{$meta_key})) {
                 $order_field->set_value(maybe_unserialize($order->{$meta_key}));
             }
         }
         $order_fields[$field_id] = $order_field;
     }
     return $order_fields;
 }
 /**
  * Convenience methods for other plugins to easily get add-ons for a given
  * order
  *
  * @since 1.0
  * @param int $order_id WC_Order ID
  * @return array of WC_Checkout_Add_On objects
  */
 public function get_order_add_ons($order_id)
 {
     $order = SV_WC_Plugin_Compatibility::wc_get_order($order_id);
     $add_ons = get_option('wc_checkout_add_ons', array());
     $order_add_ons = array();
     foreach ($order->get_items('fee') as $fee_id => $fee) {
         // bail for fees that aren't add-ons or deleted add-ons
         if (empty($fee['wc_checkout_add_on_id']) || !isset($add_ons[$fee['wc_checkout_add_on_id']])) {
             continue;
         }
         $add_on = new WC_Checkout_Add_On($fee['wc_checkout_add_on_id'], $add_ons[$fee['wc_checkout_add_on_id']]);
         $order_add_ons[$fee['wc_checkout_add_on_id']] = array('name' => $add_on->name, 'checkout_label' => $add_on->label, 'value' => $fee['wc_checkout_add_on_value'], 'normalized_value' => maybe_unserialize($fee['wc_checkout_add_on_label']), 'total' => $fee['line_total'], 'total_tax' => $fee['line_tax'], 'fee_id' => $fee_id);
     }
     return $order_add_ons;
 }
 /**
  * Manage the order stock (whether restore or reduce) from the order admin
  * returning the true product stock change if this is for a pricing calculator
  * product/item with inventory enabled.  Ie 2 pieces of cloth at 3 ft each
  * we'd want to return 6
  *
  * @since 3.0
  * @param numeric $quantity the new quantity
  * @param string $item_id the order item identifier
  * @return numeric $quantity the measurement quantity
  */
 public function admin_manage_order_stock($quantity, $item_id)
 {
     $order_id = absint($_POST['order_id']);
     $order = SV_WC_Plugin_Compatibility::wc_get_order($order_id);
     $order_items = $order->get_items();
     $product = SV_WC_Plugin_Compatibility::wc_get_product($order_items[$item_id]['product_id']);
     if (WC_Price_Calculator_Product::pricing_calculator_inventory_enabled($product) && isset($order_items[$item_id]['measurement_data'])) {
         $settings = new WC_Price_Calculator_Settings($product);
         $measurement_data = maybe_unserialize($order_items[$item_id]['measurement_data']);
         $total_amount = new WC_Price_Calculator_Measurement($measurement_data['_measurement_needed_unit'], $measurement_data['_measurement_needed']);
         // this is a pricing calculator product so we want to return the
         //  quantity in terms of units, ie 2 pieces of cloth at 3 ft each = 6
         $quantity *= $total_amount->get_value($settings->get_pricing_unit());
     }
     return $quantity;
 }