Class: Pay::Webhooks::AbacatepayController
- Inherits:
-
ActionController::API
- Object
- ActionController::API
- Pay::Webhooks::AbacatepayController
- Defined in:
- app/controllers/pay/webhooks/abacatepay_controller.rb
Instance Method Summary collapse
-
#create ⇒ Object
Authenticates a webhook delivery per the official AbacatePay scheme (docs.abacatepay.com/pages/webhooks/security).
Instance Method Details
#create ⇒ Object
Authenticates a webhook delivery per the official AbacatePay scheme (docs.abacatepay.com/pages/webhooks/security).
AbacatePay combines two complementary mechanisms — neither alone is sufficient, but either is enough to mark a delivery as genuine for this gem (we accept the strongest available):
1. **`webhookSecret` query parameter** — AbacatePay appends the
per-webhook secret you configured in the dashboard to the URL:
`?webhookSecret=...`. This authenticates the **origin** because
only AbacatePay knows your secret. Compared against
`Pay::Abacatepay.webhook_secret`.
2. **`X-Webhook-Signature` header (HMAC-SHA256, base64)** — protects
**body integrity**. Computed by AbacatePay over the raw body
using their fixed `PUBLIC_KEY` (in the SDK as a constant). The
key is public, so this alone does NOT prove origin — it only
proves the body wasn't tampered with in transit.
Sandbox compatibility: the current AbacatePay sandbox occasionally delivers ‘webhookSecret` inside the JSON body instead of the URL. We accept that as a third path (compared against the same configured secret) so dev/staging environments work without painel reconfiguration.
The request is rejected with 401 if none of the three pass.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'app/controllers/pay/webhooks/abacatepay_controller.rb', line 29 def create payload = request.body.read unless authenticated?(payload) return head(:unauthorized) end event_hash = JSON.parse(payload) event_type = event_hash["event"] || event_hash["type"] event_id = event_hash["id"] || event_hash.dig("data", "id") return head(:ok) if already_recorded?(event_type, event_id) queue_event(event_type, event_hash) head :ok rescue JSON::ParserError head :bad_request end |