From 86af562f370f9cfb401c5b715392f6d6ae162bb5 Mon Sep 17 00:00:00 2001 From: Bryan Elliott Date: Tue, 22 Oct 2024 21:17:26 -0400 Subject: [PATCH] Add manage purchase/subscription url for My Jetpack products. --- .../components/product-card/action-button.tsx | 7 +-- projects/packages/my-jetpack/global.d.ts | 1 + .../my-jetpack/src/products/class-product.php | 52 +++++++++++++++---- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/product-card/action-button.tsx b/projects/packages/my-jetpack/_inc/components/product-card/action-button.tsx index 27ebd07039d73..f65d67e6e63c0 100644 --- a/projects/packages/my-jetpack/_inc/components/product-card/action-button.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-card/action-button.tsx @@ -47,7 +47,7 @@ const ActionButton: FC< ActionButtonProps > = ( { const [ isDropdownOpen, setIsDropdownOpen ] = useState( false ); const [ currentAction, setCurrentAction ] = useState< ComponentProps< typeof Button > >( {} ); const { detail } = useProduct( slug ); - const { manageUrl, purchaseUrl } = detail; + const { manageUrl, purchaseUrl, managePaidPlanPurchaseUrl } = detail; const isManageDisabled = ! manageUrl; const dropdownRef = useRef( null ); const chevronRef = useRef( null ); @@ -191,7 +191,7 @@ const ActionButton: FC< ActionButtonProps > = ( { case PRODUCT_STATUSES.EXPIRING_SOON: return { ...buttonState, - href: '#/connection', + href: managePaidPlanPurchaseUrl, variant: 'primary', label: __( 'Renew my plan', 'jetpack-my-jetpack' ), ...( primaryActionOverride && @@ -201,7 +201,7 @@ const ActionButton: FC< ActionButtonProps > = ( { case PRODUCT_STATUSES.EXPIRED: return { ...buttonState, - href: '#/connection', + href: managePaidPlanPurchaseUrl, variant: 'primary', label: __( 'Resume my plan', 'jetpack-my-jetpack' ), ...( primaryActionOverride && @@ -227,6 +227,7 @@ const ActionButton: FC< ActionButtonProps > = ( { onManage, primaryActionOverride, isOwned, + managePaidPlanPurchaseUrl, ] ); const allActions = useMemo( diff --git a/projects/packages/my-jetpack/global.d.ts b/projects/packages/my-jetpack/global.d.ts index f302d8567e765..6fc5da6cc0564 100644 --- a/projects/packages/my-jetpack/global.d.ts +++ b/projects/packages/my-jetpack/global.d.ts @@ -154,6 +154,7 @@ interface Window { plugin_slug: string; post_activation_url: string; post_checkout_url?: string; + manage_paid_plan_purchase_url?: string; pricing_for_ui?: { available: boolean; wpcom_product_slug: string; diff --git a/projects/packages/my-jetpack/src/products/class-product.php b/projects/packages/my-jetpack/src/products/class-product.php index eeaf142b379f2..7f519876f8d86 100644 --- a/projects/packages/my-jetpack/src/products/class-product.php +++ b/projects/packages/my-jetpack/src/products/class-product.php @@ -11,6 +11,7 @@ use Automattic\Jetpack\Connection\Manager as Connection_Manager; use Automattic\Jetpack\Modules; use Automattic\Jetpack\Plugins_Installer; +use Automattic\Jetpack\Status; use Jetpack_Options; use WP_Error; @@ -188,6 +189,7 @@ public static function get_info() { 'class' => static::class, 'post_checkout_url' => static::get_post_checkout_url(), 'post_checkout_urls_by_feature' => static::get_post_checkout_urls_by_feature(), + 'manage_paid_plan_purchase_url' => static::get_manage_paid_plan_purchase_url(), ); } @@ -447,11 +449,11 @@ public static function get_paid_bundles_that_include_product() { } /** - * Gets the paid plan's expiry status, or null if: no paid plan, or not expired, or not expiring soon. + * Gets the paid plan's purchase/subsciption info, or null if no paid plan purchases. * - * @return string|null + * @return object|null */ - public static function get_paid_plan_expiration_status() { + public static function get_paid_plan_purchase_for_product() { $paid_plans = array_merge( static::get_paid_plan_product_slugs(), static::get_paid_bundles_that_include_product() @@ -466,17 +468,47 @@ public static function get_paid_plan_expiration_status() { foreach ( $purchases_data as $purchase ) { foreach ( $paid_plans as $plan ) { if ( strpos( $purchase->product_slug, $plan ) !== false ) { - // Check if expired or expiring soon - if ( $purchase->expiry_status === Products::STATUS_EXPIRING_SOON ) { - return Products::STATUS_EXPIRING_SOON; - } - if ( $purchase->expiry_status === Products::STATUS_EXPIRED ) { - return Products::STATUS_EXPIRED; - } + return $purchase; } } } } + + return null; + } + + /** + * Gets the paid plan's expiry status, or null if: no paid plan, or not expired, or not expiring soon. + * + * @return string|null + */ + public static function get_paid_plan_expiration_status() { + $purchase = static::get_paid_plan_purchase_for_product(); + if ( $purchase ) { + if ( $purchase->expiry_status === Products::STATUS_EXPIRING_SOON ) { + return Products::STATUS_EXPIRING_SOON; + } + if ( $purchase->expiry_status === Products::STATUS_EXPIRED ) { + return Products::STATUS_EXPIRED; + } + } + + return null; + } + + /** + * Gets the url to manage the paid plan's purchased subscription (For renewing, canceling). + * + * @return string|null + */ + public static function get_manage_paid_plan_purchase_url() { + $purchase = static::get_paid_plan_purchase_for_product(); + $site_suffix = ( new Status() )->get_site_suffix(); + + if ( $purchase && $site_suffix ) { + return 'https://wordpress.com/me/purchases/' . $site_suffix . '/' . $purchase->ID; + } + return null; }