Skip to content

Commit

Permalink
Adding admin notices for detached subscriptions (#3863)
Browse files Browse the repository at this point in the history
* Adding admin notices for detached subscriptions

* Removing test line

* Changelog and readme entries

* Creating a private method to retrieve the dettached subscriptions

* Adding cache to avoid wp-admin taking too long to load

* Fix tests

* Additional constant
  • Loading branch information
wjrosa authored Feb 11, 2025
1 parent b44831d commit ecae5a8
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 2 deletions.
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
*** Changelog ***

= 9.2.0 - xxxx-xx-xx =
* Add - Adds a new notice for store admins when there are subscriptions without a payment method attached.
* Fix - Hides "pay" and "cancel" buttons on the order received page when an Amazon Pay order is pending, since it may take a while to be confirmed.
* Dev - Replaces part of the StoreAPI call code for the cart endpoints to use the newly introduced filter.
* Fix - Switch booking products back to using non-StoreAPI add-to-cart methods.
Expand Down
104 changes: 102 additions & 2 deletions includes/admin/class-wc-stripe-admin-notices.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@
* @since 4.1.0
*/
class WC_Stripe_Admin_Notices {
/**
* Transient key for detached subscriptions.
*
* @var string
*/
private const DETACHED_SUBSCRIPTIONS_TRANSIENT_KEY = 'wcstripe_detached_subscriptions';

/**
* Stripe customer page base URL.
*
* @var string
*/
private const STRIPE_CUSTOMER_PAGE_BASE_URL = 'https://dashboard.stripe.com/customers/';

/**
* Notices (array)
*
Expand Down Expand Up @@ -58,6 +72,11 @@ public function admin_notices() {
// All other payment methods.
$this->payment_methods_check_environment();

// Subscription related checks.
if ( class_exists( 'WC_Subscriptions' ) && class_exists( 'WC_Subscription' ) && version_compare( WC_Subscriptions::$version, '2.2.0', '>=' ) ) {
$this->subscriptions_check_environment();
}

foreach ( (array) $this->notices as $notice_key => $notice ) {
echo '<div class="' . esc_attr( $notice['class'] ) . '" style="position:relative;">';

Expand Down Expand Up @@ -379,6 +398,45 @@ public function payment_methods_check_environment() {
}
}

/**
* Environment check for subscriptions.
*
* @return void
*/
public function subscriptions_check_environment() {
$detached_messages = '';
$subscriptions = $this->get_detached_subscriptions();
foreach ( $subscriptions as $subscription ) {
$customer_payment_method_link = sprintf(
'<a href="%s">%s</a>',
esc_url( $subscription['change_payment_method_url'] ),
esc_html(
/* translators: this is a text for a link pointing to the customer's payment method page */
__( 'this link &rarr;', 'woocommerce-gateway-stripe' )
)
);
$customer_stripe_page = sprintf(
'<a href="%s">%s</a>',
esc_url( self::STRIPE_CUSTOMER_PAGE_BASE_URL . $subscription['customer_id'] ),
esc_html(
/* translators: this is a text for a link pointing to the customer's page on Stripe */
__( 'here &rarr;', 'woocommerce-gateway-stripe' )
)
);
$detached_messages .= sprintf(
/* translators: %1$s is the subscription ID. %2$s is a customer payment method page. %3$s is the customer's page on Stripe */
__( 'Subscription #%1$s\'s payment method is missing, <strong>preventing renewals</strong>. Share %2$s with the customer to update it or manually set the <strong>Stripe Payment Method ID</strong> meta field in the subscriptions details "Billing" section to another from %3$s.', 'woocommerce-gateway-stripe' ),
$subscription['id'],
$customer_payment_method_link,
$customer_stripe_page
);
}
$show_notice = get_option( 'wc_stripe_show_subscriptions_notice' );
if ( ! empty( $detached_messages ) && 'no' !== $show_notice ) {
$this->add_admin_notice( 'subscriptions', 'notice notice-error', $detached_messages, true );
}
}

/**
* Hides any admin notices.
*
Expand Down Expand Up @@ -421,8 +479,6 @@ public function hide_notices() {
break;
case 'sofort':
update_option( 'wc_stripe_show_sofort_notice', 'no' );
break;
case 'sofort':
update_option( 'wc_stripe_show_sofort_upe_notice', 'no' );
break;
case 'sca':
Expand All @@ -437,6 +493,9 @@ public function hide_notices() {
case 'upe_payment_methods':
update_option( 'wc_stripe_show_upe_payment_methods_notice', 'no' );
break;
case 'subscriptions':
update_option( 'wc_stripe_show_subscriptions_notice', 'no' );
break;
}
}
}
Expand Down Expand Up @@ -470,6 +529,47 @@ public function stripe_updated() {
update_option( 'wc_stripe_show_sca_notice', 'no' );
}
}

/**
* Returns a list of subscriptions without a payment method attached.
*
* @return array
*/
private function get_detached_subscriptions() {
// Check if we have a cached result.
$cached_subscriptions = get_transient( self::DETACHED_SUBSCRIPTIONS_TRANSIENT_KEY );
if ( ! empty( $cached_subscriptions ) ) {
return $cached_subscriptions;
}

$detached_subscriptions = [];
$subscriptions = wcs_get_subscriptions(
[
'subscriptions_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
'subscription_status' => [ 'active', 'on-hold', 'pending-cancel' ],
]
);
foreach ( $subscriptions as $subscription ) {
$source_id = $subscription->get_meta( '_stripe_source_id' );
if ( $source_id ) {
$payment_method = WC_Stripe_API::get_payment_method( $source_id );
if ( ! $payment_method->customer ) {
$detached_subscriptions[] = [
'id' => $subscription->get_id(),
'customer_id' => $subscription->get_meta( '_stripe_customer_id' ),
'change_payment_method_url' => $subscription->get_change_payment_method_url(),
];
}
}
}

// Cache the result for a day.
set_transient( self::DETACHED_SUBSCRIPTIONS_TRANSIENT_KEY, $detached_subscriptions, DAY_IN_SECONDS );

return $detached_subscriptions;
}
}

new WC_Stripe_Admin_Notices();
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
== Changelog ==

= 9.2.0 - xxxx-xx-xx =
* Add - Adds a new notice for store admins when there are subscriptions without a payment method attached.
* Fix - Hides "pay" and "cancel" buttons on the order received page when an Amazon Pay order is pending, since it may take a while to be confirmed.
* Dev - Replaces part of the StoreAPI call code for the cart endpoints to use the newly introduced filter.
* Fix - Switch booking products back to using non-StoreAPI add-to-cart methods.
Expand Down
20 changes: 20 additions & 0 deletions tests/phpunit/helpers/class-wc-subscriptions-helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ function wcs_get_subscriptions_for_order( $order ) {
return (array) WC_Subscriptions_Helpers::$wcs_get_subscriptions_for_order;
}

/**
* A function to mock wcs_get_subscriptions.
*
* @return array
*/
function wcs_get_subscriptions() {
if ( ! WC_Subscriptions_Helpers::$wcs_get_subscriptions ) {
return [];
}

return (array) WC_Subscriptions_Helpers::$wcs_get_subscriptions;
}

/**
* A helper class for setting up mocks for WC_Subscriptions functions.
*/
Expand All @@ -28,4 +41,11 @@ class WC_Subscriptions_Helpers {
* @var array
*/
public static $wcs_get_subscriptions_for_order = null;

/**
* Mock for wcs_get_subscriptions.
*
* @var array
*/
public static $wcs_get_subscriptions = null;
}

0 comments on commit ecae5a8

Please sign in to comment.