WC_AJAX::refund_line_items()
Handle a refund via the edit order screen.
Description Description
Source Source
File: includes/class-wc-ajax.php
public static function refund_line_items() {
ob_start();
check_ajax_referer( 'order-item', 'security' );
if ( ! current_user_can( 'edit_shop_orders' ) ) {
wp_die( -1 );
}
$order_id = isset( $_POST['order_id'] ) ? absint( $_POST['order_id'] ) : 0;
$refund_amount = isset( $_POST['refund_amount'] ) ? wc_format_decimal( sanitize_text_field( wp_unslash( $_POST['refund_amount'] ) ), wc_get_price_decimals() ) : 0;
$refunded_amount = isset( $_POST['refunded_amount'] ) ? wc_format_decimal( sanitize_text_field( wp_unslash( $_POST['refunded_amount'] ) ), wc_get_price_decimals() ) : 0;
$refund_reason = isset( $_POST['refund_reason'] ) ? sanitize_text_field( wp_unslash( $_POST['refund_reason'] ) ) : '';
$line_item_qtys = isset( $_POST['line_item_qtys'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['line_item_qtys'] ) ), true ) : array();
$line_item_totals = isset( $_POST['line_item_totals'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['line_item_totals'] ) ), true ) : array();
$line_item_tax_totals = isset( $_POST['line_item_tax_totals'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['line_item_tax_totals'] ) ), true ) : array();
$api_refund = isset( $_POST['api_refund'] ) && 'true' === $_POST['api_refund'];
$restock_refunded_items = isset( $_POST['restock_refunded_items'] ) && 'true' === $_POST['restock_refunded_items'];
$refund = false;
$response = array();
try {
$order = wc_get_order( $order_id );
$max_refund = wc_format_decimal( $order->get_total() - $order->get_total_refunded(), wc_get_price_decimals() );
if ( ! $refund_amount || $max_refund < $refund_amount || 0 > $refund_amount ) {
throw new Exception( __( 'Invalid refund amount', 'woocommerce' ) );
}
if ( wc_format_decimal( $order->get_total_refunded(), wc_get_price_decimals() ) !== $refunded_amount ) {
throw new Exception( __( 'Error processing refund. Please try again.', 'woocommerce' ) );
}
// Prepare line items which we are refunding.
$line_items = array();
$item_ids = array_unique( array_merge( array_keys( $line_item_qtys ), array_keys( $line_item_totals ) ) );
foreach ( $item_ids as $item_id ) {
$line_items[ $item_id ] = array(
'qty' => 0,
'refund_total' => 0,
'refund_tax' => array(),
);
}
foreach ( $line_item_qtys as $item_id => $qty ) {
$line_items[ $item_id ]['qty'] = max( $qty, 0 );
}
foreach ( $line_item_totals as $item_id => $total ) {
$line_items[ $item_id ]['refund_total'] = wc_format_decimal( $total );
}
foreach ( $line_item_tax_totals as $item_id => $tax_totals ) {
$line_items[ $item_id ]['refund_tax'] = array_filter( array_map( 'wc_format_decimal', $tax_totals ) );
}
// Create the refund object.
$refund = wc_create_refund(
array(
'amount' => $refund_amount,
'reason' => $refund_reason,
'order_id' => $order_id,
'line_items' => $line_items,
'refund_payment' => $api_refund,
'restock_items' => $restock_refunded_items,
)
);
if ( is_wp_error( $refund ) ) {
throw new Exception( $refund->get_error_message() );
}
if ( did_action( 'woocommerce_order_fully_refunded' ) ) {
$response['status'] = 'fully_refunded';
}
} catch ( Exception $e ) {
wp_send_json_error( array( 'error' => $e->getMessage() ) );
}
// wp_send_json_success must be outside the try block not to break phpunit tests.
wp_send_json_success( $response );
}