diff --git a/modules/ppcp-api-client/src/Endpoint/BillingSubscriptions.php b/modules/ppcp-api-client/src/Endpoint/BillingSubscriptions.php index 8a46506b6..281afe0ec 100644 --- a/modules/ppcp-api-client/src/Endpoint/BillingSubscriptions.php +++ b/modules/ppcp-api-client/src/Endpoint/BillingSubscriptions.php @@ -67,7 +67,7 @@ public function __construct( string $host, Bearer $bearer, LoggerInterface $logg */ public function suspend( string $id ):void { $data = array( - 'reason' => 'Suspended by customer', + 'reason' => sprintf( 'Suspended by %s.', is_admin() ? 'merchant' : 'customer' ), ); $bearer = $this->bearer->bearer(); @@ -107,7 +107,7 @@ public function suspend( string $id ):void { */ public function activate( string $id ): void { $data = array( - 'reason' => 'Reactivated by customer', + 'reason' => sprintf( 'Reactivated by %s.', is_admin() ? 'merchant' : 'customer' ), ); $bearer = $this->bearer->bearer(); @@ -148,7 +148,7 @@ public function activate( string $id ): void { */ public function cancel( string $id ): void { $data = array( - 'reason' => 'Cancelled by customer', + 'reason' => sprintf( 'Cancelled by %s.', is_admin() ? 'merchant' : 'customer' ), ); $bearer = $this->bearer->bearer(); diff --git a/modules/ppcp-paypal-subscriptions/services.php b/modules/ppcp-paypal-subscriptions/services.php index ccd3c1dd1..86fb81376 100644 --- a/modules/ppcp-paypal-subscriptions/services.php +++ b/modules/ppcp-paypal-subscriptions/services.php @@ -43,4 +43,10 @@ 'paypal-subscriptions.renewal-handler' => static function ( ContainerInterface $container ): RenewalHandler { return new RenewalHandler( $container->get( 'woocommerce.logger.woocommerce' ) ); }, + 'paypal-subscriptions.status' => static function ( ContainerInterface $container ): SubscriptionStatus { + return new SubscriptionStatus( + $container->get( 'api.endpoint.billing-subscriptions' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, ); diff --git a/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php index 1319feae9..fd572beb0 100644 --- a/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php +++ b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php @@ -187,6 +187,9 @@ function( $variation_id ) use ( $c ) { 30 ); + /** + * Executed when updating WC Subscription. + */ add_action( 'woocommerce_process_shop_subscription_meta', /** @@ -194,65 +197,41 @@ function( $variation_id ) use ( $c ) { * * @psalm-suppress MissingClosureParamType */ - function( $id, $post ) use ( $c ) { + function( $id ) use ( $c ) { $subscription = wcs_get_subscription( $id ); - if ( ! is_a( $subscription, WC_Subscription::class ) ) { + if ( $subscription === false ) { return; } + $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; if ( ! $subscription_id ) { return; } - $subscriptions_endpoint = $c->get( 'api.endpoint.billing-subscriptions' ); - assert( $subscriptions_endpoint instanceof BillingSubscriptions ); - if ( $subscription->get_status() === 'cancelled' ) { - try { - $subscriptions_endpoint->cancel( $subscription_id ); - } catch ( RuntimeException $exception ) { - $error = $exception->getMessage(); - if ( is_a( $exception, PayPalApiException::class ) ) { - $error = $exception->get_details( $error ); - } - - $logger = $c->get( 'woocommerce.logger.woocommerce' ); - $logger->error( 'Could not cancel subscription product on PayPal. ' . $error ); - } - } + $subscription_status = $c->get( 'paypal-subscriptions.status' ); + assert( $subscription_status instanceof SubscriptionStatus ); - if ( $subscription->get_status() === 'pending-cancel' ) { - try { - $subscriptions_endpoint->suspend( $subscription_id ); - } catch ( RuntimeException $exception ) { - $error = $exception->getMessage(); - if ( is_a( $exception, PayPalApiException::class ) ) { - $error = $exception->get_details( $error ); - } + $subscription_status->update_status( $subscription->get_status(), $subscription_id ); + }, + 20 + ); - $logger = $c->get( 'woocommerce.logger.woocommerce' ); - $logger->error( 'Could not suspend subscription product on PayPal. ' . $error ); - } + /** + * Update subscription status from WC Subscriptions list page action link. + */ + add_action( + 'woocommerce_subscription_status_updated', + function( WC_Subscription $subscription ) use ( $c ) { + $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; + if ( ! $subscription_id ) { + return; } - if ( $subscription->get_status() === 'active' ) { - try { - $current_subscription = $subscriptions_endpoint->subscription( $subscription_id ); - if ( $current_subscription->status === 'SUSPENDED' ) { - $subscriptions_endpoint->activate( $subscription_id ); - } - } catch ( RuntimeException $exception ) { - $error = $exception->getMessage(); - if ( is_a( $exception, PayPalApiException::class ) ) { - $error = $exception->get_details( $error ); - } + $subscription_status = $c->get( 'paypal-subscriptions.status' ); + assert( $subscription_status instanceof SubscriptionStatus ); - $logger = $c->get( 'woocommerce.logger.woocommerce' ); - $logger->error( 'Could not reactivate subscription product on PayPal. ' . $error ); - } - } - }, - 20, - 2 + $subscription_status->update_status( $subscription->get_status(), $subscription_id ); + } ); add_filter( diff --git a/modules/ppcp-paypal-subscriptions/src/SubscriptionStatus.php b/modules/ppcp-paypal-subscriptions/src/SubscriptionStatus.php new file mode 100644 index 000000000..1fbec3926 --- /dev/null +++ b/modules/ppcp-paypal-subscriptions/src/SubscriptionStatus.php @@ -0,0 +1,144 @@ +subscriptions_endpoint = $subscriptions_endpoint; + $this->logger = $logger; + } + + /** + * Updates PayPal subscription status from the given WC Subscription status. + * + * @param string $subscription_status The WC Subscription status. + * @param string $subscription_id The PayPal Subscription ID. + * @return void + */ + public function update_status( string $subscription_status, string $subscription_id ): void { + if ( $subscription_status === 'pending-cancel' || $subscription_status === 'cancelled' ) { + try { + $current_subscription = $this->subscriptions_endpoint->subscription( $subscription_id ); + if ( $current_subscription->status === 'CANCELLED' ) { + return; + } + + $this->logger->info( + sprintf( + 'Canceling PayPal subscription #%s.', + $subscription_id + ) + ); + + $this->subscriptions_endpoint->cancel( $subscription_id ); + } catch ( RuntimeException $exception ) { + $this->logger->error( + sprintf( + 'Could not cancel PayPal subscription #%s. %s', + $subscription_id, + $this->get_error( $exception ) + ) + ); + } + } + + if ( $subscription_status === 'on-hold' ) { + try { + $this->logger->info( + sprintf( + 'Suspending PayPal subscription #%s.', + $subscription_id + ) + ); + + $this->subscriptions_endpoint->suspend( $subscription_id ); + } catch ( RuntimeException $exception ) { + $this->logger->error( + sprintf( + 'Could not suspend PayPal subscription #%s. %s', + $subscription_id, + $this->get_error( $exception ) + ) + ); + } + } + + if ( $subscription_status === 'active' ) { + try { + $current_subscription = $this->subscriptions_endpoint->subscription( $subscription_id ); + if ( $current_subscription->status === 'SUSPENDED' ) { + $this->logger->info( + sprintf( + 'Activating suspended PayPal subscription #%s.', + $subscription_id + ) + ); + + $this->subscriptions_endpoint->activate( $subscription_id ); + } + } catch ( RuntimeException $exception ) { + $this->logger->error( + sprintf( + 'Could not reactivate PayPal subscription #%s. %s', + $subscription_id, + $this->get_error( $exception ) + ) + ); + } + } + } + + /** + * Get error from exception. + * + * @param RuntimeException $exception The exception. + * @return string + */ + private function get_error( RuntimeException $exception ): string { + $error = $exception->getMessage(); + if ( is_a( $exception, PayPalApiException::class ) ) { + $error = $exception->get_details( $error ); + } + + return $error; + } +}