Current File : /home/getxxhzo/xpertbee.com/wp-content/plugins/cartflows-pro/classes/class-cartflows-pro-refund.php |
<?php
/**
* Cartflows Admin.
*
* @package cartflows
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
/**
* Class Cartflows_Pro_Refund.
*/
class Cartflows_Pro_Refund {
/**
* Member Variable
*
* @var instance
*/
private static $instance;
/**
* Initiator
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
public function __construct() {
add_action( 'wp_ajax_wcf_admin_refund_offer', array( $this, 'process_cancellation' ) );
/* Add Upsell Refund Metabox in the WooCommerce's Orders page */
add_action( 'add_meta_boxes', array( $this, 'add_offer_refund_meta_box' ) );
// Enqueue refund order script & style.
add_action( 'admin_enqueue_scripts', array( $this, 'add_refund_offer_script' ) );
}
/**
* Process the refund of offer product.
*
* @hook wp_ajax_wcf_admin_refund_offer
* @return void
*/
public function process_cancellation() {
/**
* Check permission
*/
if ( ! current_user_can( 'cartflows_manage_settings' ) ) {
$result['data'] = array(
'error' => __( 'Permission denied!', 'cartflows-pro' ),
);
wp_send_json_error( $result );
}
$result = array(
'success' => false,
'msg' => __( 'Unexpected error occoured', 'cartflows-pro' ),
);
if ( ! class_exists( 'Cartflows_Pro_Gateways' ) ) {
wp_send_json( $result );
}
if ( isset( $_POST['security'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['security'] ) ), 'wcf_admin_refund_offer_nonce' ) ) {
$order_id = isset( $_POST['order_id'] ) ? intval( $_POST['order_id'] ) : 0;
$step_id = isset( $_POST['step_id'] ) ? intval( $_POST['step_id'] ) : 0;
$offer_id = isset( $_POST['offer_id'] ) ? intval( $_POST['offer_id'] ) : 0;
$offer_amount = isset( $_POST['offer_amt'] ) ? floatval( $_POST['offer_amt'] ) : 0;
$transaction_id = isset( $_POST['transaction_id'] ) ? sanitize_text_field( wp_unslash( $_POST['transaction_id'] ) ) : '';
$refund_amount = $offer_amount;
$refund_reason = isset( $_POST['refund_reason'] ) ? sanitize_text_field( wp_unslash( $_POST['refund_reason'] ) ) : '';
$api_refund = filter_input( INPUT_POST, 'api_refund', FILTER_VALIDATE_BOOLEAN );
$restock_refunded_items = filter_input( INPUT_POST, 'restock_refunded_items', FILTER_VALIDATE_BOOLEAN );
$offer_data = array(
'order_id' => $order_id,
'offer_id' => $offer_id,
'transaction_id' => $transaction_id,
'refund_amount' => $refund_amount,
'refund_reason' => $refund_reason,
);
$result = array(
'success' => false,
'msg' => __( 'Refund unsuccessful', 'cartflows-pro' ),
);
// Get order object.
$order = wc_get_order( $order_id );
$payment_method = $order->get_payment_method();
$gateway = wcf_pro()->gateways->load_gateway( $payment_method );
if ( $gateway->is_api_refund() ) {
$refund_txn_id = $gateway->process_offer_refund( $order, $offer_data );
}
if ( false !== $refund_txn_id ) {
// Get Line items.
$cartflows_offers = $order->get_items( 'line_item' );
$offer_item = WC_Order_Factory::get_order_item( $offer_id );
$offer_item = WC_Order_Factory::get_order_item( $offer_id );
// Prepare the line items.
$line_items[ $offer_id ] = array(
'qty' => max( $offer_item->get_quantity(), 0 ),
'refund_total' => wc_format_decimal( $offer_item->get_total() ),
'refund_tax' => array(),
);
$order_taxes = $order->get_taxes();
$tax_data = $offer_item->get_taxes();
$tax_item_total = array();
foreach ( $order_taxes as $tax_item ) {
$tax_item_id = $tax_item->get_rate_id();
$tax_item_total[ $tax_item_id ] = isset( $tax_data['total'][ $tax_item_id ] ) ? $tax_data['total'][ $tax_item_id ] : 0;
}
$line_items[ $offer_id ]['refund_tax'] = array_filter( array_map( 'wc_format_decimal', $tax_item_total ) );
$refund = wc_create_refund(
array(
'amount' => $refund_amount,
'reason' => $refund_reason,
'order_id' => $order_id,
'refund_payment' => false,
'line_items' => $line_items,
'restock_items' => true,
)
);
if ( is_wp_error( $refund ) ) {
$order->add_order_note( 'Refund of amount - ' . wc_format_decimal( $offer_item->get_total() ) . ' - CartFlows Offer ID - ' . $offer_id . ' - failed for order - ' . $order_id . '. Reason - ' . $refund_reason );
$result['success'] = true;
$result['msg'] = __( 'Refund Unsuccessful', 'cartflows-pro' );
} else {
wc_update_order_item_meta( $offer_id, '_cartflows_refunded', 'yes' );
$order->add_order_note( 'Refund of amount - ' . wc_format_decimal( $offer_item->get_total() ) . ' - CartFlows Offer ID - ' . $offer_id . ' - completed for order - ' . $order_id . '. Reason - ' . $refund_reason . ' & Refund ID : ' . $refund_txn_id );
$result['success'] = true;
$result['msg'] = __( 'Refund Successful', 'cartflows-pro' );
}
}
}
wp_send_json( $result );
}
/**
* Metabox to display the Upsell Offer refund settings.
*
* @return void
*/
public function add_offer_refund_meta_box() {
if ( ! class_exists( 'Cartflows_Pro_Gateways' ) ) {
return;
}
if ( ! $this->is_show_refund_metabox() ) {
return;
}
$order_screen_id = $this->is_custom_order_table_controller_available()
? wc_get_page_screen_id( 'shop-order' )
: 'shop_order'; // It will decide whether to show meta box on old order page or new one based on Woo Settings.
// Add the refund offer order metabox.
add_meta_box(
'wcf-offer-refund-metabox',
__( 'CartFlows Refund Offers', 'cartflows-pro' ),
array( $this, 'refund_offer_metabox_callback' ),
$order_screen_id,
'normal'
);
}
/**
* Check if required class and custom order is enabled.
*
* @return bool
*/
public function is_custom_order_table_controller_available() {
return class_exists( 'Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController' ) && wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ? true : false;
}
/**
* Maybe show refund meta box.
*
* @return bool
*/
public function is_show_refund_metabox() {
global $post;
$current_screen_id = get_current_screen()->id;
if ( in_array( $current_screen_id, array( 'shop_order', 'woocommerce_page_wc-orders' ), true ) ) { // 'woocommerce_page_wc-orders' is screen id of the new order page.
$order_id = $post ? $post->ID : 0;
/**
* Reason for PHPCS ignore: Retrieving the order ID from the URL to check the current page is order page,
* and has the flow ID and a valid order placed via CartFlows.
*/
if ( ! $order_id && isset( $_GET['id'] ) && ! empty( $_GET['id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$order_id = intval( wp_unslash( $_GET['id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
if ( ! $order_id ) {
return false;
}
$order = wc_get_order( $order_id );
if ( ! $order ) {
return false;
}
$flow_id = $order->get_meta( '_wcf_flow_id' );
if ( $flow_id < 1 ) {
return false;
}
$is_valid_order = $this->is_valid_order_for_refund( $order );
if ( ! $is_valid_order ) {
return false;
}
return true;
}
return false;
}
/**
* Include HTML view of the refund metabox.
*
* @return void
*/
public function refund_offer_metabox_callback() {
include CARTFLOWS_PRO_DIR . 'admin/views/html-refund-offer.php';
}
/**
* Include HTML view of the refund metabox.
*
* @return void
*/
public function add_refund_offer_script() {
if ( ! is_admin() ) {
return;
}
if ( ! $this->is_show_refund_metabox() ) {
return;
}
// Enqueue meta-box css.
wp_enqueue_style( 'cartflows-refund-offer-metabox', CARTFLOWS_PRO_URL . 'admin/meta-assets/css/refund-offer-meta-box.css', array(), CARTFLOWS_PRO_VER );
// Enqueue meta-box js.
wp_enqueue_script( 'cartflows-refund-offer-metabox', CARTFLOWS_PRO_URL . 'admin/meta-assets/js/refund-offer-meta-box.js', array( 'jquery' ), CARTFLOWS_PRO_VER, true );
}
/**
* Show refund box only for valid orders.
*
* @param WC_Order $order The order object.
* @return bool $show true/false.
*/
public function is_valid_order_for_refund( $order ) {
$is_valid = false;
$is_offer = $this->is_offer_present_in_order( $order );
if ( $is_offer ) {
$payment_method = $order->get_payment_method();
$gateway_obj = wcf_pro()->gateways->load_gateway( $payment_method );
$main_txn_id = $order->get_transaction_id();
// If gateway supported and main transaction id not empty.
if ( $gateway_obj->is_api_refund() && ! empty( $main_txn_id ) ) {
$is_valid = true;
}
}
return $is_valid;
}
/**
* Check for the offer is present.
*
* @param WC_Order $order The order object.
* @return bool $offer_exists true/false.
*/
public function is_offer_present_in_order( $order ) {
$offer_exists = false;
foreach ( $order->get_items() as $item_id => $item_data ) {
$is_upsell = wc_get_order_item_meta( $item_id, '_cartflows_upsell', true );
$is_downsell = wc_get_order_item_meta( $item_id, '_cartflows_downsell', true );
$is_txn_id = wc_get_order_item_meta( $item_id, '_cartflows_offer_txn_id', true );
if ( 'yes' == $is_upsell || 'yes' == $is_downsell && ! empty( $is_txn_id ) ) {
$offer_exists = true;
break;
}
}
return $offer_exists;
}
}
/**
* Prepare if class 'Cartflows_Pro_Refund' exist.
* Kicking this off by calling 'get_instance()' method
*/
Cartflows_Pro_Refund::get_instance();