Skip to content

Add Safeguard for disabling Square cards#472

Draft
faisal-alvi wants to merge 4 commits intotrunkfrom
SQUARE-247
Draft

Add Safeguard for disabling Square cards#472
faisal-alvi wants to merge 4 commits intotrunkfrom
SQUARE-247

Conversation

@faisal-alvi
Copy link
Copy Markdown
Collaborator

@faisal-alvi faisal-alvi commented Mar 17, 2026

All Submissions:

  • Does your code follow the WooCommerce Sniffs variant of WordPress coding standards?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully run tests with your changes locally?
  • Will this change require new documentation or changes to existing documentation?

Changes proposed in this Pull Request

Prevents staging/local/development sites (or WooCommerce Subscriptions duplicate sites) that use production Square credentials from calling the Square API to disable customer cards when payment tokens are removed via admin/CLI/cron (e.g. user deletion, privacy erasure). Customer-initiated removal (e.g. My Account → delete payment method) still calls Square so cards are disabled when the customer removes them.

Note

When the safeguard skips the API call, the token is still deleted in WordPress (WooCommerce token store). Only the Square-side “disable card” request is skipped so live customer cards are not affected.

Closes https://linear.app/a8c/issue/SQUARE-247/cards-disabled-from-staging-site.

Steps to test the changes in this Pull Request

  1. Staging/non-production + production Square: Set WP_ENVIRONMENT_TYPE to staging (or use a WCS duplicate site). Ensure Square is connected in production mode. As an admin, delete a WordPress user who has saved Square payment tokens (or run a privacy erasure for a user with tokens). Confirm the token is removed in WordPress and that the Square log shows “Skipped disabling card on Square…”. Confirm the same card is still enabled in the Square Dashboard (live account).
  2. Production site: Set WP_ENVIRONMENT_TYPE to production (or leave unset). Delete a user (or remove a token via admin) who has saved Square tokens. Confirm the Square API is called and the card is disabled on Square.
  3. Customer removal (My Account): On any environment, as a logged-in customer, go to My Account → Payment methods and delete a saved Square card. Confirm the card is disabled on Square and removed in WordPress (safeguard does not block this).
  4. Sandbox: With Square in sandbox mode, delete a user with tokens (or remove token via admin). Confirm the Square API is still called (safeguard does not block sandbox).

Changelog entry

Fix - Add safeguard to skip disabling cards on Square when removing tokens from staging/non-production sites

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 17, 2026

🔍 WordPress Plugin Check Report

❌ Status: Failed

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
8 8 0

❌ Errors (8)

📁 includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php (1 error)
📍 Line 🔖 Check 💬 Message
0 missing_direct_file_access_protection PHP file should prevent direct access. Add a check like: if ( ! defined( 'ABSPATH' ) ) exit;
📁 includes/Framework/PaymentGateway/Admin/views/html-user-profile-section.php (1 error)
📍 Line 🔖 Check 💬 Message
0 missing_direct_file_access_protection PHP file should prevent direct access. Add a check like: if ( ! defined( 'ABSPATH' ) ) exit;
📁 includes/Framework/PaymentGateway/Admin/views/html-user-payment-token-editor.php (1 error)
📍 Line 🔖 Check 💬 Message
0 missing_direct_file_access_protection PHP file should prevent direct access. Add a check like: if ( ! defined( 'ABSPATH' ) ) exit;
📁 includes/Framework/PaymentGateway/Admin/views/html-user-profile-field-customer-id.php (1 error)
📍 Line 🔖 Check 💬 Message
0 missing_direct_file_access_protection PHP file should prevent direct access. Add a check like: if ( ! defined( 'ABSPATH' ) ) exit;
📁 includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php (1 error)
📍 Line 🔖 Check 💬 Message
0 missing_direct_file_access_protection PHP file should prevent direct access. Add a check like: if ( ! defined( 'ABSPATH' ) ) exit;
📁 includes/Framework/PaymentGateway/Admin/views/html-user-payment-token-editor-token.php (1 error)
📍 Line 🔖 Check 💬 Message
0 missing_direct_file_access_protection PHP file should prevent direct access. Add a check like: if ( ! defined( 'ABSPATH' ) ) exit;
📁 includes/WC_Payments_Compatibility.php (1 error)
📍 Line 🔖 Check 💬 Message
0 missing_direct_file_access_protection PHP file should prevent direct access. Add a check like: if ( ! defined( 'ABSPATH' ) ) exit;
📁 includes/Admin/Product_Editor_Compatibility.php (1 error)
📍 Line 🔖 Check 💬 Message
0 missing_direct_file_access_protection PHP file should prevent direct access. Add a check like: if ( ! defined( 'ABSPATH' ) ) exit;

🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

@faisal-alvi faisal-alvi self-assigned this Mar 17, 2026
@faisal-alvi faisal-alvi requested a review from iamdharmesh March 17, 2026 10:28
@blogtutor
Copy link
Copy Markdown

Thanks for this update. As the user who was recently impacted by this lack of protection, I'm grateful to see it moving forward.

I would also strongly encourage you not to delete production data in Square upon WordPress user deletion, whether the user is being deleted on staging or production.

There can be many reasons why someone would want to delete a WP User and still keep the customer/payment information on file. If they want to be sure they're deleting that information they can use the data deletion tool instead.

For example, perhaps transferred an existing Woo Subscription to another WP user (this happens often enough, such as when the billing contact at a company changes). If we then delete the first WP user, that could also delete a card on file when we don't want it to!

As another example: I acquired a plugin a few years ago, and it was one of several plugins the seller owned and sold through the same WordPress setup. We had to split out only the user/payment info for people who were paying for that specific plugin, but not their others. If the seller then cleaned up their old user data, we could have lost the valid payment information as well!

Or imagine if someone were moving from WooCommerce to Shopify (sorry) and wanted to transfer their customer data over. They should have the right to do this without the WooCommerce Square plugin deleting any of their external data (even if they decide to "clean up" old WordPress user accounts).

Bottom line for me is that when you delete Users in WordPress it should only delete data in WordPress -- nowhere else. Anything else is unexpected by users and the consequences, as I have experienced (and continue to try to recover from), can be severe.

Copy link
Copy Markdown
Collaborator

@iamdharmesh iamdharmesh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @faisal-alvi. I haven't tested it, but this looks good overall. I just added a request to add filter support if any merchant wants to completely disable removing the card from the Square side.

Side note: If we delete a user with all content is attributed to another user, will it still remove the card data on the Square or WP side? Not directly related to this PR but wanted to get an idea overall to check how it works in that scenario.

Image

Thanks

@faisal-alvi
Copy link
Copy Markdown
Collaborator Author

@iamdharmesh Thanks, appreciate the review.

Filter: Added woocommerce_square_should_disable_card_on_square so merchants can override whether we call Square when a saved method is removed.

User delete + “attribute all content to another user”: That reassignment only affects things like posts/authorship, not WooCommerce saved payment methods. On delete_user, WooCommerce still deletes that user’s rows in woocommerce_payment_tokens, so the card references are removed in WordPress either way.

For Square, deleting those tokens fires woocommerce_payment_token_deleted, which goes through our token handler and normally calls the API to disable the card - unless this PR’s safeguard applies, in which case we skip the Square call and only remove locally, or a merchant uses the new filter to change that behavior.

@faisal-alvi
Copy link
Copy Markdown
Collaborator Author

@blogtutor Thanks for the detailed context and examples.

This PR has a specific, narrow scope: prevent live cards from being disabled when token removal runs from admin, CLI, or cron in non-production environments. It doesn't touch the broader rule that removing a saved method can still sync to Square in other contexts.

What you're describing is a larger product/behavior decision - one that touches subscriptions, migrations, multi-plugin setups, and the tradeoff between merchant expectations and shopper privacy. That deserves its own dedicated discussion.

Would you mind opening a new issue (feature request) with the relevant details?

We can reference this PR there for context. In the meantime, the filter added in this PR is available for merchants who need custom behavior in their own setup.

@faisal-alvi faisal-alvi requested a review from iamdharmesh April 8, 2026 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants