Skip to content

Add Safeguard for disabling Square cards#472

Merged
iamdharmesh merged 6 commits intotrunkfrom
SQUARE-247
May 7, 2026
Merged

Add Safeguard for disabling Square cards#472
iamdharmesh merged 6 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/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/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/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-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-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-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-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/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

Comment thread includes/Gateway/API.php Outdated
@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
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 changes @faisal-alvi. Code looks good now (I haven't tested it).

@blogtutor thanks for the suggestion, we will discuss your suggestion but for now you can use the filter to completely disable the remove card from the square side. (cc: @builtbytay - tagging for check on the suggestion)

add_filter( 'woocommerce_square_should_disable_card_on_square', '__return_false');

Thanks.

@qasumitbagthariya qasumitbagthariya requested review from ankitguptaindia and removed request for qasumitbagthariya May 4, 2026 14:51
@ankitguptaindia
Copy link
Copy Markdown
Collaborator

Test Result: Verified ✅

Tested all scenarios mentioned in the PR instructions across staging/non-production, production, customer account removal, and sandbox environments.

Verified that:

  • In staging/non-production with production Square connection, saved payment tokens were removed from WordPress while the card remained active in the Square Dashboard, and the expected “Skipped disabling card on Square…” log entry was generated.
  • In production environment, deleting/removing saved Square payment tokens correctly triggered the Square API call and disabled the card on Square.
  • Customer-side removal from My Account → Payment Methods successfully removed the token from WordPress and disabled the card on Square.
  • In sandbox mode, the safeguard did not block the API request and the Square API call was executed as expected.

All tested scenarios are working as expected. QA Approved ✅

Screenshot 2026-05-07 at 4 54 52 PM
Production- Before user deleation Production After user deleation
image image

@iamdharmesh iamdharmesh added this to the 5.3.3 milestone May 7, 2026
@ankitguptaindia
Copy link
Copy Markdown
Collaborator

Regression Test Report- QA Verified ✅

Testing Environment -

Details
  • WordPress: 6.9.4
  • PHP: 8.4.18
  • Server: nginx/1.26.1
  • Database: mysqli (Server: 8.0.35 / Client: mysqlnd 8.4.18)
  • Browser: Chrome 147.0.0.0
  • OS: macOS
  • Theme: Twenty Twenty-Five 1.4
  • Plugins:
    • WooCommerce 10.7.0
    • WooCommerce Square - Dev version

Testing Scope:

  • Smoke test executed to validate major functionality.
  • Regression checks performed on key user flows related to this task/PR.

Result:

The changes introduced in this PR work as expected during integration testing along with other related fixes.

Please note that due to limitations around repeated usage of the same credit card on the Production environment, regression testing was performed only in the Sandbox environment.

Final Status:

Marked as Ready for Merge 🚀

@iamdharmesh iamdharmesh marked this pull request as ready for review May 7, 2026 17:26
@iamdharmesh iamdharmesh merged commit 7d90df7 into trunk May 7, 2026
5 of 10 checks passed
@iamdharmesh iamdharmesh deleted the SQUARE-247 branch May 7, 2026 17:26
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.

4 participants