Commit b5e27abaf10 for woocommerce

commit b5e27abaf10685fc73b791000536aa71ac519764
Author: Noruzzaman <noruzzamanrubel@gmail.com>
Date:   Wed Nov 11 16:36:21 2026 +0600

    Revoke downloadable permissions when refunding a product variation line item (#70276)

    * Revoke downloadable permissions when refunding a product variation line item

    * Fix variation refund item type handling

    ---------

    Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com>

diff --git a/plugins/woocommerce/changelog/fix-69452-refund-variation-download-permissions b/plugins/woocommerce/changelog/fix-69452-refund-variation-download-permissions
new file mode 100644
index 00000000000..e621d672dde
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-69452-refund-variation-download-permissions
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Revoke downloadable product permissions when a product variation line item is refunded.
diff --git a/plugins/woocommerce/includes/wc-order-functions.php b/plugins/woocommerce/includes/wc-order-functions.php
index 6da2d728f75..8c3679e9f54 100644
--- a/plugins/woocommerce/includes/wc-order-functions.php
+++ b/plugins/woocommerce/includes/wc-order-functions.php
@@ -640,9 +640,13 @@ function wc_create_refund( $args = array() ) {
 				// later to be used for revoking download permission.
 				// checking if the item is a product, as we only need to revoke download permission for products.
 				if ( $item->is_type( 'line_item' ) ) {
+					$product_id = $item->get_product_id();
+					if ( $item instanceof WC_Order_Item_Product && $item->get_variation_id() ) {
+						$product_id = $item->get_variation_id();
+					}
 					$refunded_order_and_products[ $item_id ] = array(
 						'order_id'   => $order->get_id(),
-						'product_id' => $item->get_product_id(),
+						'product_id' => $product_id,
 					);
 				}

diff --git a/plugins/woocommerce/tests/legacy/unit-tests/order/class-wc-tests-order-functions.php b/plugins/woocommerce/tests/legacy/unit-tests/order/class-wc-tests-order-functions.php
index 11e9a4f787a..07f68d61ed7 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/order/class-wc-tests-order-functions.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/order/class-wc-tests-order-functions.php
@@ -1804,6 +1804,75 @@ class WC_Tests_Order_Functions extends WC_Unit_Test_Case {
 		);
 	}

+	/**
+	 * @testdox Refunding a product variation revokes its customer download permissions.
+	 * @see https://github.com/woocommerce/woocommerce/issues/69452
+	 */
+	public function test_wc_create_refund_revokes_variation_download_permissions() {
+		$variable_product = WC_Helper_Product::create_variation_product();
+		$variation_ids    = $variable_product->get_children();
+		$variation_id     = $variation_ids[0];
+		$variation        = wc_get_product( $variation_id );
+		$variation->set_downloadable( true );
+		$variation->save();
+
+		$order = new WC_Order();
+		$item  = new WC_Order_Item_Product();
+		$item->set_product( $variation );
+		$item->set_quantity( 1 );
+		$item->set_subtotal( 10 );
+		$item->set_total( 10 );
+		$order->add_item( $item );
+		$order->calculate_totals();
+		$order->save();
+
+		// Add customer download permission for the variation.
+		$download = new WC_Customer_Download();
+		$download->set_user_id( 1 );
+		$download->set_order_id( $order->get_id() );
+		$download->set_product_id( $variation->get_id() );
+		$download->set_download_id( wp_generate_uuid4() );
+		$download->save();
+
+		$download_data_store = WC_Data_Store::load( 'customer-download' );
+		$initial_downloads   = $download_data_store->get_downloads(
+			array(
+				'order_id'   => $order->get_id(),
+				'product_id' => $variation->get_id(),
+			)
+		);
+		$this->assertCount( 1, $initial_downloads, 'Download permission should exist prior to refund.' );
+
+		$item_id = $item->get_id();
+
+		$refund = wc_create_refund(
+			array(
+				'amount'     => 10,
+				'order_id'   => $order->get_id(),
+				'line_items' => array(
+					$item_id => array(
+						'qty'          => 1,
+						'refund_total' => 10,
+						'refund_tax'   => array( 1 => 0 ),
+					),
+				),
+			)
+		);
+
+		$this->assertNotWPError( $refund, 'Refund should be created successfully.' );
+
+		$remaining_downloads = $download_data_store->get_downloads(
+			array(
+				'order_id'   => $order->get_id(),
+				'product_id' => $variation->get_id(),
+			)
+		);
+		$this->assertEmpty(
+			$remaining_downloads,
+			'Download permissions for a refunded variation must be revoked.'
+		);
+	}
+
 	/**
 	 * Test wc_sanitize_order_id().
 	 */