I'm trying to create a partial refund for an order programatically. It's important to calculate the tax as well, but so far nothing seems to work correctly and I can't figure why.
I want to press a button and the function "ceb_wc_refund_order" will be called with $order_id, quantity and the reason. $qty is usually 1. The problem is that the order contains always only ONE item, but for example 3 times. Now I want to refund only one of these items.
I know how to do that manually so basically what I want to achieve is the following, but programatically:
At the moment the code seems to create the refund successfully and also the quantity of the item is right. But the refund amount is the item price * quantity and also the tax is not refunded.
I know my code does not lead to my goal so far. I did not find much on the internet about this... Can you help me?
function ceb_wc_refund_order( $order_id, $qty, $refund_reason = '') {
$order = wc_get_order( $order_id );
// If it's something else such as a WC_Order_Refund, we don't want that.
if( ! is_a( $order, 'WC_Order') ) {
return new WP_Error( 'wc-order', __( 'Provided ID is not a WC Order', 'yourtextdomain' ) );
}
if( 'refunded' == $order->get_status() ) {
return new WP_Error( 'wc-order', __( 'Order has been already refunded', 'yourtextdomain' ) );
}
// Get Items
$order_items = $order->get_items();
// Refund Amount
$refund_amount = 0;
// Prepare line items which we are refunding
$line_items = array();
if ( $order_items ) {
foreach( $order_items as $item_id => $item ) {
$item_meta = $order->get_item_meta($item_id);
$tax_data = $item_meta['_line_tax'];
$refund_tax = $tax_data;
$refund_amount = wc_format_decimal($refund_amount) + wc_format_decimal($item_meta['_line_total'][0]);
$line_items[$item_id] = array(
'qty' => $qty,
'refund_total' => wc_format_decimal($item_meta['_line_total'][0]),
'refund_tax' => $refund_tax);
}
}
// ...
$refund = wc_create_refund( array(
'amount' => $refund_amount,
'reason' => $refund_reason,
'order_id' => $order_id,
'line_items' => $line_items,
'refund_payment' => false
));
return $refund;
}