wc_create_refund( array $args = array() )
Create a new order refund programmatically.
Description Description
Returns a new refund object on success which can then be used to add additional data.
Parameters Parameters
- $args
-
(Optional) New refund arguments.
Default value: array()
Return Return
(WC_Order_Refund|WP_Error)
Source Source
File: includes/wc-order-functions.php
function wc_create_refund( $args = array() ) {
$default_args = array(
'amount' => 0,
'reason' => null,
'order_id' => 0,
'refund_id' => 0,
'line_items' => array(),
'refund_payment' => false,
'restock_items' => false,
);
try {
$args = wp_parse_args( $args, $default_args );
$order = wc_get_order( $args['order_id'] );
if ( ! $order ) {
throw new Exception( __( 'Invalid order ID.', 'woocommerce' ) );
}
$remaining_refund_amount = $order->get_remaining_refund_amount();
$remaining_refund_items = $order->get_remaining_refund_items();
$refund_item_count = 0;
$refund = new WC_Order_Refund( $args['refund_id'] );
if ( 0 > $args['amount'] || $args['amount'] > $remaining_refund_amount ) {
throw new Exception( __( 'Invalid refund amount.', 'woocommerce' ) );
}
$refund->set_currency( $order->get_currency() );
$refund->set_amount( $args['amount'] );
$refund->set_parent_id( absint( $args['order_id'] ) );
$refund->set_refunded_by( get_current_user_id() ? get_current_user_id() : 1 );
$refund->set_prices_include_tax( $order->get_prices_include_tax() );
if ( ! is_null( $args['reason'] ) ) {
$refund->set_reason( $args['reason'] );
}
// Negative line items.
if ( count( $args['line_items'] ) > 0 ) {
$items = $order->get_items( array( 'line_item', 'fee', 'shipping' ) );
foreach ( $items as $item_id => $item ) {
if ( ! isset( $args['line_items'][ $item_id ] ) ) {
continue;
}
$qty = isset( $args['line_items'][ $item_id ]['qty'] ) ? $args['line_items'][ $item_id ]['qty'] : 0;
$refund_total = $args['line_items'][ $item_id ]['refund_total'];
$refund_tax = isset( $args['line_items'][ $item_id ]['refund_tax'] ) ? array_filter( (array) $args['line_items'][ $item_id ]['refund_tax'] ) : array();
if ( empty( $qty ) && empty( $refund_total ) && empty( $args['line_items'][ $item_id ]['refund_tax'] ) ) {
continue;
}
$class = get_class( $item );
$refunded_item = new $class( $item );
$refunded_item->set_id( 0 );
$refunded_item->add_meta_data( '_refunded_item_id', $item_id, true );
$refunded_item->set_total( wc_format_refund_total( $refund_total ) );
$refunded_item->set_taxes(
array(
'total' => array_map( 'wc_format_refund_total', $refund_tax ),
'subtotal' => array_map( 'wc_format_refund_total', $refund_tax ),
)
);
if ( is_callable( array( $refunded_item, 'set_subtotal' ) ) ) {
$refunded_item->set_subtotal( wc_format_refund_total( $refund_total ) );
}
if ( is_callable( array( $refunded_item, 'set_quantity' ) ) ) {
$refunded_item->set_quantity( $qty * -1 );
}
$refund->add_item( $refunded_item );
$refund_item_count += $qty;
}
}
$refund->update_taxes();
$refund->calculate_totals( false );
$refund->set_total( $args['amount'] * -1 );
// this should remain after update_taxes(), as this will save the order, and write the current date to the db
// so we must wait until the order is persisted to set the date.
if ( isset( $args['date_created'] ) ) {
$refund->set_date_created( $args['date_created'] );
}
/**
* Action hook to adjust refund before save.
*
* @since 3.0.0
*/
do_action( 'woocommerce_create_refund', $refund, $args );
if ( $refund->save() ) {
if ( $args['refund_payment'] ) {
$result = wc_refund_payment( $order, $refund->get_amount(), $refund->get_reason() );
if ( is_wp_error( $result ) ) {
$refund->delete();
return $result;
}
$refund->set_refunded_payment( true );
$refund->save();
}
if ( $args['restock_items'] ) {
wc_restock_refunded_items( $order, $args['line_items'] );
}
// Trigger notification emails.
if ( ( $remaining_refund_amount - $args['amount'] ) > 0 || ( $order->has_free_item() && ( $remaining_refund_items - $refund_item_count ) > 0 ) ) {
do_action( 'woocommerce_order_partially_refunded', $order->get_id(), $refund->get_id() );
} else {
do_action( 'woocommerce_order_fully_refunded', $order->get_id(), $refund->get_id() );
$parent_status = apply_filters( 'woocommerce_order_fully_refunded_status', 'refunded', $order->get_id(), $refund->get_id() );
if ( $parent_status ) {
$order->update_status( $parent_status );
}
}
}
do_action( 'woocommerce_refund_created', $refund->get_id(), $args );
do_action( 'woocommerce_order_refunded', $order->get_id(), $refund->get_id() );
} catch ( Exception $e ) {
if ( isset( $refund ) && is_a( $refund, 'WC_Order_Refund' ) ) {
wp_delete_post( $refund->get_id(), true );
}
return new WP_Error( 'error', $e->getMessage() );
}
return $refund;
}
Changelog Changelog
| Version | Description |
|---|---|
| 2.2 | Introduced. |