feat: add subscription HMAC verification + backward compat (#154718, #154780) - #25
Merged
Merged
Conversation
…#154780) Extend webhook signature verification to handle both Connect signing algorithms: - calculate_hmac_signature: standard 18-field flat algorithm, default for all merchants (backward compatible with all existing Ottu deployments) - calculate_subscription_hmac_signature: 26-field algorithm for subscription/autopay webhooks (Connect feat/153560+) — extends standard fields with token.*, agreement.id, extra.merchant_id, extra.autopay.subscription_id, session_id, and payment_type - verify_signature: tries standard first, falls back to subscription automatically — betabulk (new signer) and sandbox/older instances (old signer) both verify without any configuration change _SUBSCRIPTION_SIGNED_FIELDS is defined as sorted(_SIGNED_FIELDS + [8 new fields]) to make the extension relationship explicit.
jab3z
approved these changes
Jun 11, 2026
…54718, #154780) - views.py: guard null JSON signature (was TypeError 500, now 401) - webhooks.py: fix falsy-zero skip — use != "" / is None instead of not value - webhooks.py: extract _hmac_digest helper to deduplicate HMAC computation - webhooks.py: remove redundant sorted() on already-sorted _SUBSCRIPTION_SIGNED_FIELDS - tests: add subscription view test + null-signature 401 test - tests: pin zero-string-not-skipped and null-skipped contracts for both algorithms
jab3z
approved these changes
Jun 11, 2026
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.
Summary
Extends
ottu-pywebhook signature verification to handle both Connect signing algorithms without breaking existing merchants.calculate_hmac_signature— standard 18-field flat algorithm, default for all merchants (backward compatible with all existing Ottu deployments)calculate_subscription_hmac_signature— 26-field algorithm for subscription/autopay webhooks (Connectfeat/153560+), extending the standard fields withtoken.*,agreement.id,extra.merchant_id,extra.autopay.subscription_id,session_id, andpayment_typeverify_signature— tries standard first, falls back to subscription automatically; betabulk (new signer) and sandbox/older instances (old signer) both verify without any config change_SUBSCRIPTION_SIGNED_FIELDSis defined assorted(_SIGNED_FIELDS + [8 new fields])making the extension relationship explicit in codeWhy: betabulk deployed Connect
feat/153560with a new HMAC signer, causing every Fleet inbound webhook to return401 invalid_signature. Fleet applied a local workaround; this release lets Fleet (and any other consumer) drop it and useverify_signaturedirectly. The ~100+ merchants on older Ottu instances are unaffected — their signatures still verify via the standard path.Test plan
python3 -m pytest— 255 passed, 2 skippedTestStandardSignature— pins canonical form and unsigned-field exclusion for 18-field algorithmTestSubscriptionGoldenVector— byte-pinned against real betabulk production signaturesTestSubscriptionTamperFields— each of the 8 new fields breaks the signature when tamperedTestVerifySignature— standard and subscription signatures both accepted; tamper and wrong-key rejected for both