Skip to content

feat: add subscription HMAC verification + backward compat (#154718, #154780) - #25

Merged
ankitottu merged 2 commits into
mainfrom
task/154718
Jun 12, 2026
Merged

ankitottu merged 2 commits into
mainfrom
task/154718

Conversation

@ankitottu

@ankitottu ankitottu commented Jun 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Extends ottu-py webhook 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 (Connect feat/153560+), extending the 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 config change
  • _SUBSCRIPTION_SIGNED_FIELDS is defined as sorted(_SIGNED_FIELDS + [8 new fields]) making the extension relationship explicit in code

Why: betabulk deployed Connect feat/153560 with a new HMAC signer, causing every Fleet inbound webhook to return 401 invalid_signature. Fleet applied a local workaround; this release lets Fleet (and any other consumer) drop it and use verify_signature directly. 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 skipped
  • TestStandardSignature — pins canonical form and unsigned-field exclusion for 18-field algorithm
  • TestSubscriptionGoldenVector — byte-pinned against real betabulk production signatures
  • TestSubscriptionTamperFields — each of the 8 new fields breaks the signature when tampered
  • TestVerifySignature — standard and subscription signatures both accepted; tamper and wrong-key rejected for both

…#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.
@ankitottu ankitottu changed the title feat: dual-scheme webhook HMAC backward compatibility (#154780) feat: add subscription HMAC verification + backward compat (#154718, #154780) 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
@ankitottu
ankitottu merged commit f58dc93 into main Jun 12, 2026
4 checks passed
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.

2 participants