fix webhook crashes on null custom_data, migrate to SDK Verifier

Paddle sandbox sends lifecycle events (subscription.updated, etc.) with
"custom_data": null. The .get("custom_data", {}) default only applies
when the key is missing, not when the value is explicitly null, causing
AttributeError on the next .get() call. Also guarded subscription.activated
to skip when user_id is absent (was inserting user_id=0 → FK violation).

Replaced manual HMAC verification with paddle_billing.Notifications.Verifier
via a lightweight _WebhookRequest wrapper satisfying the SDK's Request Protocol.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-18 22:43:40 +01:00
parent df8a747463
commit 0b8350c770
3 changed files with 124 additions and 51 deletions

View File

@@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased]
### Fixed
- **Webhook crash on null `custom_data`** — Paddle sends `"custom_data": null`
on lifecycle events (e.g. `subscription.updated`); `.get("custom_data", {})`
returns `None` when the key exists with a null value, causing `AttributeError`
on the next `.get()` call; switched to `or {}` fallback; also guarded
`subscription.activated` to skip when `user_id` is missing (was inserting
`user_id=0` causing FK violation), and applied same `or {}` to
`current_billing_period`
- **Webhook signature verification uses SDK Verifier** — replaced manual HMAC
implementation with `paddle_billing.Notifications.Verifier` via a lightweight
request wrapper; same algorithm, fewer moving parts
### Added
- **Credit system test suite** (`tests/test_credits.py` — 24 tests) — covers
`get_balance`, `add_credits`, `spend_credits`, `compute_credit_cost`,