Repository navigation
Normalize the activation fingerprint so www/http variants of one site match - #28
Merged
mzakash merged 1 commit intoOct 21, 2026
Conversation
get_site_url() was sent as-is, so https://www.example.com, https://example.com and http://example.com created separate activations for the same site. The scheme also follows the current request via is_ssl(), so one site could send both http and https. Activation::get_fingerprint() now forces https, lowercases the host, drops a leading www. label and a trailing slash, and keeps the port and path. A canonical https non-www URL keeps its exact previous fingerprint. Exposed via the surecart_licensing_fingerprint filter.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Activation::create()andupdate()sendesc_url_raw( get_site_url() )as the activation fingerprint, without normalising it. The API matches fingerprints exactly ("If an activation already exists with the samefingerprintthen it will be updated"), so URL variants of one site become separate activations:https://www.example.comvshttps://example.comhttp://vshttps://.get_site_url()picks the scheme from the current request viais_ssl(), so one site can send both.A customer reported this on a product built on this SDK: "Sometimes I am using SureForms on www.CASP.ca, and sometimes on CASP.ca. Your system somehow decided that these are two separate domains."
Change
New
Activation::get_fingerprint(), used by bothcreate()andupdate(). It:httpsscheme;www.label (wwwexample.comandshop.www.example.comare left alone);surecart_licensing_fingerprint( $fingerprint, $site_url ), following the existingsurecart_licensing_*filter naming.Regression analysis
https, non-www, lowercase URL the fingerprint is byte-identical to today's, so nothing changes for that most common setup. Only sites that were already producing variants get a new value. This is pinned bytest_get_fingerprint_is_unchanged_for_a_canonical_https_url.create()only runs fromLicense::activate(), andupdate()has no callers. The new value is only sent the next time a license is activated.deactivate()deletes the old activation by ID, so the new fingerprint creates a single activation. No duplicate.www/httpsite whose stored activation ID was lost (database restore, migration, reinstall) and that activates again without deactivating first. Today its identical raw fingerprint updates the existing activation. After this change, the old raw-fingerprint activation stays on the server and a new one is created, using a second seat once. It could be removed with an API-side match on the legacy value, or by matching normalised fingerprints server-side. Sites can also restore the old behaviour withadd_filter( 'surecart_licensing_fingerprint', function ( $fp, $url ) { return esc_url_raw( $url ); }, 10, 2 );.src/already uses.wp_parse_url()has been in WordPress since 4.4.php -lpasses on 7.4 and 8.0.Tests
New
tests/unit/ActivationFingerprintTest.php(7 tests):www, scheme, case and trailing-slash variants all map to one value;www.label is stripped;create()sends the normalised value.Results (WordPress test suite, local MySQL):
ActivationFingerprintTest: OK on PHP 7.4.30 (7 tests, 14 assertions) and on PHP 8.4.LicenseActivationTest, the existing suite: unchanged, OK (6 tests, 18 assertions) on 7.4.30 and 8.4.src/Activation.phpreverted,test_create_sends_the_normalized_fingerprintfails ("Failed asserting that two strings are identical"). Before the change all 7 new tests errored on the missing method.phpcs(WPCS, run with PHP 7.4 like CI): clean onsrc/and the new test.Notes (out of scope, not changed)
update()is dead code that would crash if called. It calls$this->client->license()->get_id(), which doesn't exist inLicense. Nothing callsupdate(), so I didn't touch it or test it beyond the shared helper.tests/unit/SettingsTest.phpcrashes before running on current PHPUnit polyfills (setUp()has no: voidreturn type). CI only runs PHPCS, so this isn't caught.Questions for maintainers