Merge pull request #13117 from woocommerce/fix-12973
Moved refund logic
This commit is contained in:
commit
4e653139b6
|
@ -183,7 +183,7 @@ abstract class WC_Abstract_Legacy_Product extends WC_Data {
|
|||
*/
|
||||
public function reduce_stock( $amount = 1 ) {
|
||||
wc_deprecated_function( 'WC_Product::reduce_stock', '2.7', 'wc_update_product_stock' );
|
||||
wc_update_product_stock( $this, $amount, 'decrease' );
|
||||
return wc_update_product_stock( $this, $amount, 'decrease' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,7 +195,7 @@ abstract class WC_Abstract_Legacy_Product extends WC_Data {
|
|||
*/
|
||||
public function increase_stock( $amount = 1 ) {
|
||||
wc_deprecated_function( 'WC_Product::increase_stock', '2.7', 'wc_update_product_stock' );
|
||||
wc_update_product_stock( $this, $amount, 'increase' );
|
||||
return wc_update_product_stock( $this, $amount, 'increase' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -252,43 +252,24 @@ class WC_REST_Order_Refunds_Controller extends WC_REST_Orders_Controller {
|
|||
return new WP_Error( 'woocommerce_rest_invalid_order_refund', __( 'Refund amount must be greater than zero.', 'woocommerce' ), 400 );
|
||||
}
|
||||
|
||||
$api_refund = is_bool( $request['api_refund'] ) ? $request['api_refund'] : true;
|
||||
|
||||
$data = array(
|
||||
'order_id' => $order_data->ID,
|
||||
'amount' => $request['amount'],
|
||||
'reason' => empty( $request['reason'] ) ? null : $request['reason'],
|
||||
'line_items' => $request['line_items'],
|
||||
);
|
||||
|
||||
// Create the refund.
|
||||
$refund = wc_create_refund( $data );
|
||||
$refund = wc_create_refund( array(
|
||||
'order_id' => $order_data->ID,
|
||||
'amount' => $request['amount'],
|
||||
'reason' => empty( $request['reason'] ) ? null : $request['reason'],
|
||||
'line_items' => $request['line_items'],
|
||||
'refund_payment' => is_bool( $request['api_refund'] ) ? $request['api_refund'] : true,
|
||||
'restock_items' => true,
|
||||
) );
|
||||
|
||||
if ( is_wp_error( $refund ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_create_order_refund', $refund->get_error_message(), 500 );
|
||||
}
|
||||
|
||||
if ( ! $refund ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_create_order_refund', __( 'Cannot create order refund, please try again.', 'woocommerce' ), 500 );
|
||||
}
|
||||
|
||||
// Refund via API.
|
||||
if ( $api_refund ) {
|
||||
if ( WC()->payment_gateways() ) {
|
||||
$payment_gateways = WC()->payment_gateways->payment_gateways();
|
||||
}
|
||||
|
||||
$order = wc_get_order( $order_data );
|
||||
|
||||
if ( isset( $payment_gateways[ $order->get_payment_method() ] ) && $payment_gateways[ $order->get_payment_method() ]->supports( 'refunds' ) ) {
|
||||
$result = $payment_gateways[ $order->get_payment_method() ]->process_refund( $order->get_id(), $refund->get_amount(), $refund->get_reason() );
|
||||
|
||||
if ( ! $result || is_wp_error( $result ) ) {
|
||||
$refund->delete();
|
||||
|
||||
$message = is_wp_error( $result ) ? $result : new WP_Error( 'woocommerce_rest_create_order_refund_api_failed', __( 'An error occurred while attempting to create the refund using the payment gateway API.', 'woocommerce' ), 500 );
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$post = get_post( $refund->get_id() );
|
||||
$this->update_additional_fields_for_object( $post, $request );
|
||||
|
||||
|
|
|
@ -1241,7 +1241,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
|||
if ( isset( $request['stock_quantity'] ) ) {
|
||||
$product->set_stock_quantity( wc_stock_amount( $request['stock_quantity'] ) );
|
||||
} elseif ( isset( $request['inventory_delta'] ) ) {
|
||||
$stock_quantity = wc_stock_amount( $product->get_stock_amount() );
|
||||
$stock_quantity = wc_stock_amount( $product->get_stock_quantity() );
|
||||
$stock_quantity += wc_stock_amount( $request['inventory_delta'] );
|
||||
$product->set_stock_quantity( wc_stock_amount( $stock_quantity ) );
|
||||
}
|
||||
|
@ -1446,7 +1446,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
|||
if ( isset( $data['stock_quantity'] ) ) {
|
||||
$variation->set_stock_quantity( $data['stock_quantity'] );
|
||||
} elseif ( isset( $data['inventory_delta'] ) ) {
|
||||
$stock_quantity = wc_stock_amount( $variation->get_stock_amount() );
|
||||
$stock_quantity = wc_stock_amount( $variation->get_stock_quantity() );
|
||||
$stock_quantity += wc_stock_amount( $data['inventory_delta'] );
|
||||
$variation->set_stock_quantity( $stock_quantity );
|
||||
}
|
||||
|
|
|
@ -1618,7 +1618,7 @@ class WC_API_Products extends WC_API_Resource {
|
|||
if ( isset( $data['stock_quantity'] ) ) {
|
||||
$product->set_stock_quantity( wc_stock_amount( $data['stock_quantity'] ) );
|
||||
} elseif ( isset( $data['inventory_delta'] ) ) {
|
||||
$stock_quantity = wc_stock_amount( $product->get_stock_amount() );
|
||||
$stock_quantity = wc_stock_amount( $product->get_stock_quantity() );
|
||||
$stock_quantity += wc_stock_amount( $data['inventory_delta'] );
|
||||
$product->set_stock_quantity( wc_stock_amount( $stock_quantity ) );
|
||||
}
|
||||
|
@ -1845,7 +1845,7 @@ class WC_API_Products extends WC_API_Resource {
|
|||
if ( isset( $data['stock_quantity'] ) ) {
|
||||
$variation->set_stock_quantity( $data['stock_quantity'] );
|
||||
} elseif ( isset( $data['inventory_delta'] ) ) {
|
||||
$stock_quantity = wc_stock_amount( $variation->get_stock_amount() );
|
||||
$stock_quantity = wc_stock_amount( $variation->get_stock_quantity() );
|
||||
$stock_quantity += wc_stock_amount( $data['inventory_delta'] );
|
||||
$variation->set_stock_quantity( $stock_quantity );
|
||||
}
|
||||
|
|
|
@ -1365,73 +1365,24 @@ class WC_AJAX {
|
|||
$line_items[ $item_id ]['refund_tax'] = array_map( 'wc_format_decimal', $tax_totals );
|
||||
}
|
||||
|
||||
// Create the refund object
|
||||
// Create the refund object.
|
||||
$refund = wc_create_refund( array(
|
||||
'amount' => $refund_amount,
|
||||
'reason' => $refund_reason,
|
||||
'order_id' => $order_id,
|
||||
'line_items' => $line_items,
|
||||
'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() );
|
||||
}
|
||||
|
||||
// Refund via API
|
||||
if ( $api_refund ) {
|
||||
if ( WC()->payment_gateways() ) {
|
||||
$payment_gateways = WC()->payment_gateways->payment_gateways();
|
||||
}
|
||||
if ( isset( $payment_gateways[ $order->get_payment_method() ] ) && $payment_gateways[ $order->get_payment_method() ]->supports( 'refunds' ) ) {
|
||||
$result = $payment_gateways[ $order->get_payment_method() ]->process_refund( $order_id, $refund_amount, $refund_reason );
|
||||
|
||||
do_action( 'woocommerce_refund_processed', $refund, $result );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
throw new Exception( $result->get_error_message() );
|
||||
} elseif ( ! $result ) {
|
||||
throw new Exception( __( 'Refund failed', 'woocommerce' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restock items
|
||||
foreach ( $line_item_qtys as $item_id => $qty ) {
|
||||
if ( $restock_refunded_items && $qty && isset( $order_items[ $item_id ] ) ) {
|
||||
$order_item = $order_items[ $item_id ];
|
||||
$_product = $order_item->get_product();
|
||||
|
||||
if ( $_product && $_product->exists() && $_product->managing_stock() ) {
|
||||
$old_stock = wc_stock_amount( $_product->stock );
|
||||
$new_quantity = $_product->increase_stock( $qty );
|
||||
|
||||
$order->add_order_note( sprintf( __( 'Item #%1$s stock increased from %2$s to %3$s.', 'woocommerce' ), $order_item['product_id'], $old_stock, $new_quantity ) );
|
||||
|
||||
do_action( 'woocommerce_restock_refunded_item', $_product->get_id(), $old_stock, $new_quantity, $order, $_product );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger notifications and status changes
|
||||
if ( $order->get_remaining_refund_amount() > 0 || ( $order->has_free_item() && $order->get_remaining_refund_items() > 0 ) ) {
|
||||
/**
|
||||
* woocommerce_order_partially_refunded.
|
||||
*
|
||||
* @since 2.4.0
|
||||
* Note: 3rd arg was added in err. Kept for bw compat. 2.4.3.
|
||||
*/
|
||||
do_action( 'woocommerce_order_partially_refunded', $order_id, $refund->get_id(), $refund->get_id() );
|
||||
} else {
|
||||
do_action( 'woocommerce_order_fully_refunded', $order_id, $refund->get_id() );
|
||||
|
||||
$order->update_status( apply_filters( 'woocommerce_order_fully_refunded_status', 'refunded', $order_id, $refund->get_id() ) );
|
||||
if ( did_action( 'woocommerce_order_fully_refunded' ) ) {
|
||||
$response_data['status'] = 'fully_refunded';
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_order_refunded', $order_id, $refund->get_id() );
|
||||
|
||||
// Clear transients
|
||||
wc_delete_shop_order_transients( $order_id );
|
||||
wp_send_json_success( $response_data );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
|
|
|
@ -1469,11 +1469,13 @@ class WC_Order extends WC_Abstract_Order {
|
|||
* @return array of WC_Order_Refund objects
|
||||
*/
|
||||
public function get_refunds() {
|
||||
$this->refunds = wc_get_orders( array(
|
||||
'type' => 'shop_order_refund',
|
||||
'parent' => $this->get_id(),
|
||||
'limit' => -1,
|
||||
) );
|
||||
if ( empty( $this->refunds ) ) {
|
||||
$this->refunds = wc_get_orders( array(
|
||||
'type' => 'shop_order_refund',
|
||||
'parent' => $this->get_id(),
|
||||
'limit' => -1,
|
||||
) );
|
||||
}
|
||||
return $this->refunds;
|
||||
}
|
||||
|
||||
|
|
|
@ -481,26 +481,31 @@ function wc_ship_to_billing_address_only() {
|
|||
*/
|
||||
function wc_create_refund( $args = array() ) {
|
||||
$default_args = array(
|
||||
'amount' => 0,
|
||||
'reason' => null,
|
||||
'order_id' => 0,
|
||||
'refund_id' => 0,
|
||||
'line_items' => 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'] );
|
||||
$refund = new WC_Order_Refund( $args['refund_id'] );
|
||||
$args = wp_parse_args( $args, $default_args );
|
||||
|
||||
if ( ! $order ) {
|
||||
if ( ! $order = wc_get_order( $args['order_id'] ) ) {
|
||||
throw new Exception( __( 'Invalid order ID.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
// prevent negative refunds
|
||||
if ( 0 > $args['amount'] ) {
|
||||
$args['amount'] = 0;
|
||||
$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'] ) );
|
||||
|
@ -543,6 +548,7 @@ function wc_create_refund( $args = array() ) {
|
|||
}
|
||||
|
||||
$refund->add_item( $refunded_item );
|
||||
$refund_item_count += $qty;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,10 +562,31 @@ function wc_create_refund( $args = array() ) {
|
|||
*/
|
||||
do_action( 'woocommerce_create_refund', $refund, $args );
|
||||
|
||||
$refund->save();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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() );
|
||||
$order->update_status( apply_filters( 'woocommerce_order_fully_refunded_status', 'refunded', $order->get_id(), $refund->get_id() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Backwards compatibility hook.
|
||||
do_action( 'woocommerce_refund_created', $refund->get_id(), $args );
|
||||
do_action( 'woocommerce_order_refunded', $order->get_id(), $refund->get_id() );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
return new WP_Error( 'error', $e->getMessage() );
|
||||
|
@ -568,6 +595,78 @@ function wc_create_refund( $args = array() ) {
|
|||
return $refund;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to refund the payment for an order via the gateway.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Order $order
|
||||
* @param string $amount
|
||||
* @param string $reason
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
function wc_refund_payment( $order, $amount, $reason = '' ) {
|
||||
try {
|
||||
if ( ! is_a( $order, 'WC_Order' ) ) {
|
||||
throw new Exception( __( 'Invalid order.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$gateway_controller = WC_Payment_Gateways::instance();
|
||||
$all_gateways = $gateway_controller->payment_gateways();
|
||||
$payment_method = $order->get_payment_method();
|
||||
$gateway = isset( $all_gateways[ $payment_method ] ) ? $all_gateways[ $payment_method ] : false;
|
||||
|
||||
if ( ! $gateway ) {
|
||||
throw new Exception( __( 'The payment gateway for this order does not exist.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
if ( ! $gateway->supports( 'refunds' ) ) {
|
||||
throw new Exception( __( 'The payment gateway for this order does not support automatic refunds.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$result = $gateway->process_refund( $order->get_id(), $amount, $reason );
|
||||
|
||||
if ( ! $result ) {
|
||||
throw new Exception( __( 'An error occurred while attempting to create the refund using the payment gateway API.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
throw new Exception( $result->get_error_message() );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
return new WP_Error( 'error', $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restock items during refund.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Order $order
|
||||
* @param array $refunded_line_items
|
||||
*/
|
||||
function wc_restock_refunded_items( $order, $refunded_line_items ) {
|
||||
$line_items = $order->get_items();
|
||||
|
||||
foreach ( $line_items as $item_id => $item ) {
|
||||
if ( ! isset( $refunded_line_items[ $item_id ], $refunded_line_items[ $item_id ]['qty'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$product = $item->get_product();
|
||||
|
||||
if ( $product && $product->managing_stock() ) {
|
||||
$old_stock = $product->get_stock_quantity();
|
||||
$new_stock = wc_update_product_stock( $product, $refunded_line_items[ $item_id ]['qty'], 'increase' );
|
||||
|
||||
$order->add_order_note( sprintf( __( 'Item #%1$s stock increased from %2$s to %3$s.', 'woocommerce' ), $product->get_id(), $old_stock, $new_stock ) );
|
||||
|
||||
do_action( 'woocommerce_restock_refunded_item', $product->get_id(), $old_stock, $new_stock, $order, $product );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tax class by tax id.
|
||||
*
|
||||
|
@ -625,8 +724,6 @@ function wc_order_fully_refunded( $order_id ) {
|
|||
'order_id' => $order_id,
|
||||
'line_items' => array(),
|
||||
) );
|
||||
|
||||
wc_delete_shop_order_transients( $order );
|
||||
}
|
||||
add_action( 'woocommerce_order_status_refunded', 'wc_order_fully_refunded' );
|
||||
|
||||
|
|
Loading…
Reference in New Issue