From 1592e725e686e6f50ecdfe76b7d898bfb905caf8 Mon Sep 17 00:00:00 2001 From: sumaisa-mou Date: Tue, 31 Mar 2026 14:11:10 +0600 Subject: [PATCH 1/7] WIP --- .../Core/Ecommerce/Platforms/WooCommerce.php | 106 ++++++++++++++ .../WooCommerce/SubscriptionResource.php | 133 ++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php diff --git a/includes/Core/Ecommerce/Platforms/WooCommerce.php b/includes/Core/Ecommerce/Platforms/WooCommerce.php index 3c1294c..2ca8de0 100644 --- a/includes/Core/Ecommerce/Platforms/WooCommerce.php +++ b/includes/Core/Ecommerce/Platforms/WooCommerce.php @@ -8,6 +8,7 @@ use WeDevs\WeMail\Rest\Resources\Ecommerce\WooCommerce\CategoryResource; use WeDevs\WeMail\Rest\Resources\Ecommerce\WooCommerce\OrderResource; use WeDevs\WeMail\Rest\Resources\Ecommerce\WooCommerce\ProductResource; +use WeDevs\WeMail\Rest\Resources\Ecommerce\WooCommerce\SubscriptionResource; use WeDevs\WeMail\Traits\Singleton; use WP_Post; @@ -135,6 +136,15 @@ public function register_hooks() { add_action( 'created_product_cat', array( $this, 'handle_category' ), 10, 2 ); add_action( 'edited_product_cat', array( $this, 'handle_category' ), 10, 2 ); add_action( 'delete_product_cat', array( $this, 'handle_category_delete' ), 10, 3 ); + + // WooCommerce Subscriptions hooks + if ( class_exists( 'WC_Subscriptions' ) ) { + add_action( 'woocommerce_subscription_status_updated', array( $this, 'handle_subscription_status_updated' ), 10, 3 ); + add_action( 'woocommerce_subscription_renewal_payment_complete', array( $this, 'handle_subscription_renewal_payment_complete' ), 10, 2 ); + add_action( 'woocommerce_subscription_renewal_payment_failed', array( $this, 'handle_subscription_renewal_payment_failed' ), 10, 2 ); + add_action( 'woocommerce_subscription_trial_end', array( $this, 'handle_subscription_trial_end' ), 10, 1 ); + add_action( 'woocommerce_scheduled_subscription_payment', array( $this, 'handle_scheduled_subscription_payment' ), 10, 1 ); + } } /** @@ -672,4 +682,100 @@ public function handle_category_delete( $term_id, $tt_id, $deleted_term ) { ->categories( $term_id ) ->delete(); } + + /** + * Handle subscription status change + * + * @param \WC_Subscription $subscription Subscription object + * @param string $new_status New status + * @param string $old_status Old status + */ + public function handle_subscription_status_updated( $subscription, $new_status, $old_status ) { + $this->send_subscription_data( $subscription, 'subscription_status_updated', array( + 'previous_status' => $old_status, + ) ); + } + + /** + * Handle subscription renewal payment complete + * + * @param \WC_Subscription $subscription Subscription object + * @param \WC_Order $last_order Last renewal order + */ + public function handle_subscription_renewal_payment_complete( $subscription, $last_order ) { + $this->send_subscription_data( $subscription, 'subscription_renewal_payment_complete', array( + 'renewal_complete' => true, + ) ); + } + + /** + * Handle subscription renewal payment failed + * + * @param \WC_Subscription $subscription Subscription object + * @param \WC_Order $last_order Last renewal order + */ + public function handle_subscription_renewal_payment_failed( $subscription, $last_order ) { + $this->send_subscription_data( $subscription, 'subscription_renewal_payment_failed', array( + 'renewal_complete' => false, + ) ); + } + + /** + * Handle subscription trial end + * + * @param int $subscription_id Subscription ID + */ + public function handle_subscription_trial_end( $subscription_id ) { + $subscription = wcs_get_subscription( $subscription_id ); + + if ( ! $subscription ) { + return; + } + + $this->send_subscription_data( $subscription, 'subscription_trial_end' ); + } + + /** + * Handle scheduled subscription payment (before renewal) + * + * @param int $subscription_id Subscription ID + */ + public function handle_scheduled_subscription_payment( $subscription_id ) { + $subscription = wcs_get_subscription( $subscription_id ); + + if ( ! $subscription ) { + return; + } + + $this->send_subscription_data( $subscription, 'subscription_scheduled_payment' ); + } + + /** + * Send subscription data to weMail API + * + * @param \WC_Subscription $subscription Subscription object + * @param string $event Event type + * @param array $extra Additional payload data + */ + private function send_subscription_data( $subscription, $event, $extra = array() ) { + if ( ! $subscription ) { + return; + } + + if ( ! Settings::instance()->is_enabled() ) { + return; + } + + $payload = SubscriptionResource::single( $subscription ); + $payload['event'] = $event; + $payload = array_merge( $payload, $extra ); + + wemail_set_owner_api_key(); + + wemail()->api + ->send_json() + ->ecommerce() + ->subscriptions( $subscription->get_id() ) + ->put( $payload ); + } } diff --git a/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php b/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php new file mode 100644 index 0000000..04bfe98 --- /dev/null +++ b/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php @@ -0,0 +1,133 @@ +get_items(), function ( $item ) { + return $item->get_product_id(); + } + ); + + return array( + 'id' => (string) $subscription->get_id(), + 'status' => $subscription->get_status(), + 'customer_id' => $this->get_customer_id( $subscription->get_billing_email() ), + 'customer' => $this->customer( $subscription ), + 'total' => floatval( $subscription->get_total() ), + 'product_ids' => $this->get_product_ids( $items ), + 'categories' => $this->get_category_ids( $items ), + 'billing_period' => $subscription->get_billing_period(), + 'billing_interval' => intval( $subscription->get_billing_interval() ), + 'next_payment_date' => $this->format_date( $subscription->get_date( 'next_payment' ) ), + 'created_at' => $subscription->get_date_created() ? $subscription->get_date_created()->setTimezone( new DateTimeZone( 'UTC' ) )->format( self::DATE_FORMAT ) : null, + 'updated_at' => $subscription->get_date_modified() ? $subscription->get_date_modified()->setTimezone( new DateTimeZone( 'UTC' ) )->format( self::DATE_FORMAT ) : null, + ); + } + + /** + * Transform customer data + * + * @param \WC_Subscription $subscription + * + * @return array + */ + protected function customer( $subscription ) { + return array( + 'email' => $subscription->get_billing_email(), + 'first_name' => $subscription->get_billing_first_name(), + ); + } + + /** + * Get customer ID + * + * @param string $email + * + * @return string + */ + protected function get_customer_id( $email ) { + return md5( trim( strtolower( $email ) ) ); + } + + /** + * Get product IDs from subscription items + * + * @param array $items + * + * @return array + */ + protected function get_product_ids( $items ) { + $product_ids = array(); + + foreach ( $items as $item ) { + $product_ids[] = (string) $item->get_product_id(); + } + + return array_unique( $product_ids ); + } + + /** + * Get category IDs from subscription items + * + * @param array $items + * + * @return array + */ + protected function get_category_ids( $items ) { + $category_ids = array(); + + foreach ( $items as $item ) { + $product = $item->get_product(); + + if ( ! $product ) { + continue; + } + + $cats = $product->get_category_ids(); + + foreach ( $cats as $cat_id ) { + $category_ids[] = (string) $cat_id; + } + } + + return array_values( array_unique( $category_ids ) ); + } + + /** + * Format a subscription date string + * + * @param string $date_string + * + * @return string|null + */ + protected function format_date( $date_string ) { + if ( empty( $date_string ) || $date_string === '0' ) { + return null; + } + + try { + $date = new \DateTime( $date_string, new DateTimeZone( 'UTC' ) ); + return $date->format( self::DATE_FORMAT ); + } catch ( \Exception $e ) { + return null; + } + } +} \ No newline at end of file From 7413b2102c1447a4d821b1df4ce058f06ce76100 Mon Sep 17 00:00:00 2001 From: sumaisa-mou Date: Wed, 15 Apr 2026 16:11:11 +0600 Subject: [PATCH 2/7] wooCommerce subscription trigger. --- .../Core/Ecommerce/Platforms/WooCommerce.php | 117 +++++------------- 1 file changed, 32 insertions(+), 85 deletions(-) diff --git a/includes/Core/Ecommerce/Platforms/WooCommerce.php b/includes/Core/Ecommerce/Platforms/WooCommerce.php index 2ca8de0..43264dc 100644 --- a/includes/Core/Ecommerce/Platforms/WooCommerce.php +++ b/includes/Core/Ecommerce/Platforms/WooCommerce.php @@ -114,7 +114,6 @@ public function register_hooks() { add_action( 'woocommerce_add_to_cart', array( $this, 'handle_add_to_cart' ), 10, 6 ); add_action( 'woocommerce_cart_updated', array( $this, 'handle_cart_updated' ), 10, 0 ); add_action( 'woocommerce_remove_cart_item', array( $this, 'handle_remove_cart_item' ), 10, 2 ); - add_action( 'woocommerce_cart_emptied', array( $this, 'handle_cart_emptied' ), 10, 0 ); // New order created hook add_action( 'woocommerce_new_order', array( $this, 'handle_new_order' ), 10, 2 ); @@ -122,9 +121,6 @@ public function register_hooks() { // Order status changed hook (handles pending payment, completed, etc.) add_action( 'woocommerce_order_status_changed', array( $this, 'handle_order_status_changed' ), 10, 4 ); - // Pending payment status specific hook - add_action( 'woocommerce_order_status_pending', array( $this, 'handle_pending_payment' ), 10, 1 ); - add_action( 'woocommerce_order_refunded', array( $this, 'create_order_refund' ), 10, 2 ); add_action( 'woocommerce_refund_deleted', array( $this, 'delete_order_refund' ), 10, 2 ); add_action( 'after_delete_post', array( $this, 'delete' ), 10, 2 ); @@ -138,13 +134,10 @@ public function register_hooks() { add_action( 'delete_product_cat', array( $this, 'handle_category_delete' ), 10, 3 ); // WooCommerce Subscriptions hooks - if ( class_exists( 'WC_Subscriptions' ) ) { - add_action( 'woocommerce_subscription_status_updated', array( $this, 'handle_subscription_status_updated' ), 10, 3 ); - add_action( 'woocommerce_subscription_renewal_payment_complete', array( $this, 'handle_subscription_renewal_payment_complete' ), 10, 2 ); - add_action( 'woocommerce_subscription_renewal_payment_failed', array( $this, 'handle_subscription_renewal_payment_failed' ), 10, 2 ); - add_action( 'woocommerce_subscription_trial_end', array( $this, 'handle_subscription_trial_end' ), 10, 1 ); - add_action( 'woocommerce_scheduled_subscription_payment', array( $this, 'handle_scheduled_subscription_payment' ), 10, 1 ); - } + add_action( 'woocommerce_new_subscription', array( $this, 'handle_new_subscription' ), 10, 1 ); + add_action( 'woocommerce_subscription_status_cancelled', array( $this, 'handle_subscription_cancelled' ), 10, 1 ); + add_action( 'woocommerce_subscription_status_expired', array( $this, 'handle_subscription_expired' ), 10, 1 ); + add_action( 'woocommerce_subscription_renewal_payment_complete', array( $this, 'handle_subscription_renewal_payment_complete' ), 10, 2 ); } /** @@ -328,37 +321,6 @@ private function send_cart_data( $event ) { ->put( $payload ); } - /** - * Handle pending payment status - * - * @param int $order_id Order ID - */ - public function handle_pending_payment( $order_id ) { - $order = wc_get_order( $order_id ); - - if ( ! $order ) { - return; - } - - if ( ! $this->is_valid_order_item( $order->get_type() ) ) { - return; - } - - if ( ! Settings::instance()->is_enabled() ) { - return; - } - - $payload = OrderResource::single( $order ); - - wemail()->api - ->send_json() - ->ecommerce() - ->orders( $order_id ) - ->put( $payload ); - - $this->reset_cart_key(); - } - /** * Handle new order created * @@ -684,72 +646,58 @@ public function handle_category_delete( $term_id, $tt_id, $deleted_term ) { } /** - * Handle subscription status change + * Handle new subscription created * * @param \WC_Subscription $subscription Subscription object - * @param string $new_status New status - * @param string $old_status Old status */ - public function handle_subscription_status_updated( $subscription, $new_status, $old_status ) { - $this->send_subscription_data( $subscription, 'subscription_status_updated', array( - 'previous_status' => $old_status, - ) ); + public function handle_new_subscription( $subscription ) { + if ( is_numeric( $subscription ) ) { + $subscription = wcs_get_subscription( $subscription ); + } + + if ( ! $subscription ) { + return; + } + + $this->send_subscription_data( $subscription, 'subscription_created' ); } /** - * Handle subscription renewal payment complete + * Handle subscription status change * * @param \WC_Subscription $subscription Subscription object - * @param \WC_Order $last_order Last renewal order + * @param string $new_status New status + * @param string $old_status Old status */ - public function handle_subscription_renewal_payment_complete( $subscription, $last_order ) { - $this->send_subscription_data( $subscription, 'subscription_renewal_payment_complete', array( - 'renewal_complete' => true, - ) ); - } - /** - * Handle subscription renewal payment failed + * Handle subscription cancelled * * @param \WC_Subscription $subscription Subscription object - * @param \WC_Order $last_order Last renewal order */ - public function handle_subscription_renewal_payment_failed( $subscription, $last_order ) { - $this->send_subscription_data( $subscription, 'subscription_renewal_payment_failed', array( - 'renewal_complete' => false, - ) ); + public function handle_subscription_cancelled( $subscription ) { + $this->send_subscription_data( $subscription, 'subscription_cancelled' ); } /** - * Handle subscription trial end + * Handle subscription expired * - * @param int $subscription_id Subscription ID + * @param \WC_Subscription $subscription Subscription object */ - public function handle_subscription_trial_end( $subscription_id ) { - $subscription = wcs_get_subscription( $subscription_id ); - - if ( ! $subscription ) { - return; - } - - $this->send_subscription_data( $subscription, 'subscription_trial_end' ); + public function handle_subscription_expired( $subscription ) { + $this->send_subscription_data( $subscription, 'subscription_expired' ); } /** - * Handle scheduled subscription payment (before renewal) + * Handle subscription renewal payment complete * - * @param int $subscription_id Subscription ID + * @param \WC_Subscription $subscription Subscription object + * @param \WC_Order $last_order Last renewal order */ - public function handle_scheduled_subscription_payment( $subscription_id ) { - $subscription = wcs_get_subscription( $subscription_id ); - - if ( ! $subscription ) { - return; - } - - $this->send_subscription_data( $subscription, 'subscription_scheduled_payment' ); + public function handle_subscription_renewal_payment_complete( $subscription, $last_order ) { + $this->send_subscription_data( $subscription, 'subscription_renewal_payment_complete', array( + 'renewal_complete' => true, + ) ); } - /** * Send subscription data to weMail API * @@ -770,7 +718,6 @@ private function send_subscription_data( $subscription, $event, $extra = array() $payload['event'] = $event; $payload = array_merge( $payload, $extra ); - wemail_set_owner_api_key(); wemail()->api ->send_json() From 75dbf3e4046ebc1192ad46a889d0e5bc60b6bd22 Mon Sep 17 00:00:00 2001 From: sumaisa-mou Date: Wed, 15 Apr 2026 17:14:46 +0600 Subject: [PATCH 3/7] Remove unused code --- includes/Core/Ecommerce/Platforms/WooCommerce.php | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/includes/Core/Ecommerce/Platforms/WooCommerce.php b/includes/Core/Ecommerce/Platforms/WooCommerce.php index 43264dc..b905674 100644 --- a/includes/Core/Ecommerce/Platforms/WooCommerce.php +++ b/includes/Core/Ecommerce/Platforms/WooCommerce.php @@ -183,19 +183,6 @@ public function handle_remove_cart_item( $cart_item_key, $cart ) { $this->send_cart_data( 'remove_cart_item' ); } - /** - * Handle cart emptied event - */ - public function handle_cart_emptied() { - if ( $this->is_recovering || ! Settings::instance()->is_enabled() ) { - return; - } - - $this->send_cart_data( 'cart_emptied' ); - - $this->reset_cart_key(); - } - /** * Handle cart recovery from abandoned cart email link */ From d7d9a929cfb86a7c0454b1a75480536dcb7d9eae Mon Sep 17 00:00:00 2001 From: sumaisa-mou Date: Thu, 16 Apr 2026 09:47:21 +0600 Subject: [PATCH 4/7] Add subscriptions_enabled capability flag for WooCommerce Subscriptions detection --- .../Ecommerce/Platforms/AbstractPlatform.php | 4 +++ .../Ecommerce/Platforms/PlatformInterface.php | 2 ++ .../Core/Ecommerce/Platforms/WooCommerce.php | 9 +++++++ includes/Rest/Ecommerce/Ecommerce.php | 27 ++++++++++++++++--- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/includes/Core/Ecommerce/Platforms/AbstractPlatform.php b/includes/Core/Ecommerce/Platforms/AbstractPlatform.php index db3c81d..06cffe4 100644 --- a/includes/Core/Ecommerce/Platforms/AbstractPlatform.php +++ b/includes/Core/Ecommerce/Platforms/AbstractPlatform.php @@ -13,4 +13,8 @@ abstract class AbstractPlatform implements PlatformInterface { public function is_integrated() { return Settings::instance()->is_integrated() && Settings::instance()->platform() === $this->get_name(); } + + public function is_subscriptions_active() { + return false; + } } diff --git a/includes/Core/Ecommerce/Platforms/PlatformInterface.php b/includes/Core/Ecommerce/Platforms/PlatformInterface.php index 2ed79b4..6100b2a 100644 --- a/includes/Core/Ecommerce/Platforms/PlatformInterface.php +++ b/includes/Core/Ecommerce/Platforms/PlatformInterface.php @@ -18,4 +18,6 @@ public function categories( array $args = array() ); public function register_hooks(); public function get_name(); + + public function is_subscriptions_active(); } diff --git a/includes/Core/Ecommerce/Platforms/WooCommerce.php b/includes/Core/Ecommerce/Platforms/WooCommerce.php index b905674..837a1d5 100644 --- a/includes/Core/Ecommerce/Platforms/WooCommerce.php +++ b/includes/Core/Ecommerce/Platforms/WooCommerce.php @@ -529,6 +529,15 @@ public function is_active() { return class_exists( 'WooCommerce' ); } + /** + * Check if WooCommerce Subscriptions is active + * + * @return bool + */ + public function is_subscriptions_active() { + return class_exists( 'WC_Subscription' ); + } + /** * Get integration name * diff --git a/includes/Rest/Ecommerce/Ecommerce.php b/includes/Rest/Ecommerce/Ecommerce.php index 0ec8aff..ef63d3a 100644 --- a/includes/Rest/Ecommerce/Ecommerce.php +++ b/includes/Rest/Ecommerce/Ecommerce.php @@ -20,6 +20,7 @@ class Ecommerce extends RestController { public function register_routes() { $this->post( '/(?Pwoocommerce|edd)/settings', 'settings' ); $this->get( '/(?Pwoocommerce|edd)/(?Pproducts|orders|categories)', 'resource', 'permission' ); + $this->get( '/(?Pwoocommerce)/status', 'status', 'permission' ); $this->post( '/coupons', 'create_coupon', 'permission' ); $this->delete( '/disconnect', 'disconnect', 'permission' ); } @@ -38,9 +39,10 @@ public function settings( $request ) { $body = array_merge( $body, array( - 'currency' => $platform->currency(), - 'currency_symbol' => $platform->currency_symbol(), - 'platform' => $platform->get_name(), + 'currency' => $platform->currency(), + 'currency_symbol' => $platform->currency_symbol(), + 'platform' => $platform->get_name(), + 'subscriptions_enabled' => $platform->is_subscriptions_active(), ) ); // Update settings to wp options @@ -59,6 +61,25 @@ public function settings( $request ) { return new \WP_REST_Response( $response ); } + /** + * Platform status endpoint + * + * @param \WP_REST_Request $request + */ + public function status( $request ) { + $platform = $request->get_param( 'source' ); + + /** @var PlatformInterface $platform */ + $platform = wemail()->ecommerce->platform( $platform ); + + return new \WP_REST_Response( + array( + 'is_active' => $platform->is_active(), + 'subscriptions_enabled' => $platform->is_subscriptions_active(), + ) + ); + } + /** * Access products, orders or customers resource * From 6fa2a9f325caa0f9c8c17d9f5de08784d2ce39fc Mon Sep 17 00:00:00 2001 From: sumaisa-mou Date: Thu, 16 Apr 2026 09:49:43 +0600 Subject: [PATCH 5/7] Fix phpcs --- includes/Core/Ecommerce/Platforms/WooCommerce.php | 9 +++++---- .../Ecommerce/WooCommerce/SubscriptionResource.php | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/includes/Core/Ecommerce/Platforms/WooCommerce.php b/includes/Core/Ecommerce/Platforms/WooCommerce.php index 837a1d5..df85c38 100644 --- a/includes/Core/Ecommerce/Platforms/WooCommerce.php +++ b/includes/Core/Ecommerce/Platforms/WooCommerce.php @@ -690,9 +690,11 @@ public function handle_subscription_expired( $subscription ) { * @param \WC_Order $last_order Last renewal order */ public function handle_subscription_renewal_payment_complete( $subscription, $last_order ) { - $this->send_subscription_data( $subscription, 'subscription_renewal_payment_complete', array( - 'renewal_complete' => true, - ) ); + $this->send_subscription_data( + $subscription, 'subscription_renewal_payment_complete', array( + 'renewal_complete' => true, + ) + ); } /** * Send subscription data to weMail API @@ -714,7 +716,6 @@ private function send_subscription_data( $subscription, $event, $extra = array() $payload['event'] = $event; $payload = array_merge( $payload, $extra ); - wemail()->api ->send_json() ->ecommerce() diff --git a/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php b/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php index 04bfe98..08d5dba 100644 --- a/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php +++ b/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php @@ -130,4 +130,4 @@ protected function format_date( $date_string ) { return null; } } -} \ No newline at end of file +} From 3187790c313f2cca89510813cb3700c993defd03 Mon Sep 17 00:00:00 2001 From: sumaisa-mou Date: Thu, 16 Apr 2026 12:24:50 +0600 Subject: [PATCH 6/7] Add subscription cleanup on disconnect and sync on reconnect. --- .../Core/Ecommerce/Platforms/WooCommerce.php | 49 +++++++++++++++---- includes/Rest/Ecommerce/Ecommerce.php | 1 + .../WooCommerce/SubscriptionResource.php | 6 ++- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/includes/Core/Ecommerce/Platforms/WooCommerce.php b/includes/Core/Ecommerce/Platforms/WooCommerce.php index df85c38..e34c63b 100644 --- a/includes/Core/Ecommerce/Platforms/WooCommerce.php +++ b/includes/Core/Ecommerce/Platforms/WooCommerce.php @@ -69,6 +69,43 @@ public function products( array $args = array() ) { ); } + /** + * Get subscriptions from WooCommerce store + * + * @param array $args + * + * @return array + */ + public function subscriptions( array $args = array() ) { + if ( ! $this->is_subscriptions_active() ) { + return array( + 'data' => array(), + 'total' => 0, + 'current_page' => 1, + 'total_page' => 0, + ); + } + + $args = wp_parse_args( + $args, + array( + 'limit' => isset( $args['limit'] ) ? intval( $args['limit'] ) : 100, + 'page' => isset( $args['page'] ) ? intval( $args['page'] ) : 1, + 'paginate' => true, + 'type' => 'shop_subscription', + ) + ); + + $data = wc_get_orders( $args ); + + return array( + 'data' => SubscriptionResource::collection( $data->orders ), + 'total' => $data->total, + 'current_page' => intval( $args['page'] ), + 'total_page' => $data->max_num_pages, + ); + } + /** * Get orders from WooCommerce store * @@ -137,7 +174,7 @@ public function register_hooks() { add_action( 'woocommerce_new_subscription', array( $this, 'handle_new_subscription' ), 10, 1 ); add_action( 'woocommerce_subscription_status_cancelled', array( $this, 'handle_subscription_cancelled' ), 10, 1 ); add_action( 'woocommerce_subscription_status_expired', array( $this, 'handle_subscription_expired' ), 10, 1 ); - add_action( 'woocommerce_subscription_renewal_payment_complete', array( $this, 'handle_subscription_renewal_payment_complete' ), 10, 2 ); + add_action( 'woocommerce_subscription_renewal_payment_complete', array( $this, 'handle_subscription_renewal_payment_complete' ), 10, 1 ); } /** @@ -658,13 +695,6 @@ public function handle_new_subscription( $subscription ) { $this->send_subscription_data( $subscription, 'subscription_created' ); } - /** - * Handle subscription status change - * - * @param \WC_Subscription $subscription Subscription object - * @param string $new_status New status - * @param string $old_status Old status - */ /** * Handle subscription cancelled * @@ -687,9 +717,8 @@ public function handle_subscription_expired( $subscription ) { * Handle subscription renewal payment complete * * @param \WC_Subscription $subscription Subscription object - * @param \WC_Order $last_order Last renewal order */ - public function handle_subscription_renewal_payment_complete( $subscription, $last_order ) { + public function handle_subscription_renewal_payment_complete( $subscription ) { $this->send_subscription_data( $subscription, 'subscription_renewal_payment_complete', array( 'renewal_complete' => true, diff --git a/includes/Rest/Ecommerce/Ecommerce.php b/includes/Rest/Ecommerce/Ecommerce.php index ef63d3a..df02cd7 100644 --- a/includes/Rest/Ecommerce/Ecommerce.php +++ b/includes/Rest/Ecommerce/Ecommerce.php @@ -20,6 +20,7 @@ class Ecommerce extends RestController { public function register_routes() { $this->post( '/(?Pwoocommerce|edd)/settings', 'settings' ); $this->get( '/(?Pwoocommerce|edd)/(?Pproducts|orders|categories)', 'resource', 'permission' ); + $this->get( '/(?Pwoocommerce)/(?Psubscriptions)', 'resource', 'permission' ); $this->get( '/(?Pwoocommerce)/status', 'status', 'permission' ); $this->post( '/coupons', 'create_coupon', 'permission' ); $this->delete( '/disconnect', 'disconnect', 'permission' ); diff --git a/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php b/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php index 08d5dba..613111a 100644 --- a/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php +++ b/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php @@ -10,7 +10,7 @@ class SubscriptionResource extends JsonResource { /** * Date format */ - const DATE_FORMAT = 'Y-m-d'; + const DATE_FORMAT = 'Y-m-d\TH:i:s'; /** * Structure of subscription @@ -36,7 +36,10 @@ public function blueprint( $subscription ) { 'categories' => $this->get_category_ids( $items ), 'billing_period' => $subscription->get_billing_period(), 'billing_interval' => intval( $subscription->get_billing_interval() ), + 'trial_end_date' => $this->format_date( $subscription->get_date( 'trial_end' ) ), 'next_payment_date' => $this->format_date( $subscription->get_date( 'next_payment' ) ), + 'end_date' => $this->format_date( $subscription->get_date( 'end' ) ), + 'permalink' => $subscription->get_view_order_url(), 'created_at' => $subscription->get_date_created() ? $subscription->get_date_created()->setTimezone( new DateTimeZone( 'UTC' ) )->format( self::DATE_FORMAT ) : null, 'updated_at' => $subscription->get_date_modified() ? $subscription->get_date_modified()->setTimezone( new DateTimeZone( 'UTC' ) )->format( self::DATE_FORMAT ) : null, ); @@ -53,6 +56,7 @@ protected function customer( $subscription ) { return array( 'email' => $subscription->get_billing_email(), 'first_name' => $subscription->get_billing_first_name(), + 'last_name' => $subscription->get_billing_last_name(), ); } From 8b5e650837a19b9224128b90a7b4eddef99e4e5f Mon Sep 17 00:00:00 2001 From: sumaisa-mou Date: Fri, 24 Apr 2026 15:48:10 +0600 Subject: [PATCH 7/7] Update subscriber trigger in subscription tigger. --- .../Ecommerce/WooCommerce/ProductResource.php | 1 + .../WooCommerce/SubscriptionResource.php | 52 ++++++++++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/includes/Rest/Resources/Ecommerce/WooCommerce/ProductResource.php b/includes/Rest/Resources/Ecommerce/WooCommerce/ProductResource.php index d9bc783..1e13ca9 100644 --- a/includes/Rest/Resources/Ecommerce/WooCommerce/ProductResource.php +++ b/includes/Rest/Resources/Ecommerce/WooCommerce/ProductResource.php @@ -23,6 +23,7 @@ public function blueprint( $resource ) { 'permalink' => $resource->get_permalink(), 'thumbnail' => $thumbnail ? $thumbnail : null, 'categories' => $resource->get_category_ids(), + 'type' => $resource->get_type(), 'source' => 'woocommerce', ); } diff --git a/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php b/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php index 613111a..1647441 100644 --- a/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php +++ b/includes/Rest/Resources/Ecommerce/WooCommerce/SubscriptionResource.php @@ -20,8 +20,9 @@ class SubscriptionResource extends JsonResource { * @return array */ public function blueprint( $subscription ) { - $items = array_filter( - $subscription->get_items(), function ( $item ) { + $source = $this->get_billing_source( $subscription ); + $items = array_filter( + $source->get_items(), function ( $item ) { return $item->get_product_id(); } ); @@ -29,7 +30,7 @@ public function blueprint( $subscription ) { return array( 'id' => (string) $subscription->get_id(), 'status' => $subscription->get_status(), - 'customer_id' => $this->get_customer_id( $subscription->get_billing_email() ), + 'customer_id' => $this->get_customer_id( $this->get_billing_email( $subscription ) ), 'customer' => $this->customer( $subscription ), 'total' => floatval( $subscription->get_total() ), 'product_ids' => $this->get_product_ids( $items ), @@ -45,6 +46,36 @@ public function blueprint( $subscription ) { ); } + /** + * Return the authoritative billing source (parent order when available). + * Avoids stale session data that may be on the subscription object when + * woocommerce_new_subscription fires before billing details are persisted. + * + * @param \WC_Subscription $subscription + * + * @return \WC_Order|\WC_Subscription + */ + protected function get_billing_source( $subscription ) { + $parent_order = $subscription->get_parent(); + + if ( $parent_order && $parent_order->get_billing_email() ) { + return $parent_order; + } + + return $subscription; + } + + /** + * Get billing email from the authoritative billing source. + * + * @param \WC_Subscription $subscription + * + * @return string + */ + protected function get_billing_email( $subscription ) { + return $this->get_billing_source( $subscription )->get_billing_email(); + } + /** * Transform customer data * @@ -53,10 +84,19 @@ public function blueprint( $subscription ) { * @return array */ protected function customer( $subscription ) { + $source = $this->get_billing_source( $subscription ); + return array( - 'email' => $subscription->get_billing_email(), - 'first_name' => $subscription->get_billing_first_name(), - 'last_name' => $subscription->get_billing_last_name(), + 'email' => $source->get_billing_email(), + 'first_name' => $source->get_billing_first_name(), + 'last_name' => $source->get_billing_last_name(), + 'address_1' => $source->get_billing_address_1(), + 'address_2' => $source->get_billing_address_2(), + 'city' => $source->get_billing_city(), + 'state' => $source->get_billing_state(), + 'postcode' => $source->get_billing_postcode(), + 'country' => $source->get_billing_country(), + 'phone' => $source->get_billing_phone(), ); }