Class: SpreeUberDirect::WebhooksController
- Inherits:
-
ActionController::Base
- Object
- ActionController::Base
- SpreeUberDirect::WebhooksController
- Defined in:
- app/controllers/spree_uber_direct/webhooks_controller.rb
Overview
Receives Uber Direct webhook notifications. HMAC-verified (see SpreeUberDirect::WebhookVerifier) rather than DoorDash's Basic-Auth string-echo. Does the least possible work synchronously: verify, record, ack, hand off to a job — same shape as every sibling WebhooksController in this codebase.
Instance Method Summary collapse
Instance Method Details
#create ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'app/controllers/spree_uber_direct/webhooks_controller.rb', line 15 def create credential = SpreeUberDirect::Credential.find_by(store: Spree::Store.default) raw_body = request.raw_post unless SpreeUberDirect::WebhookVerifier.valid?( signature_header: request.headers['x-uber-signature'], raw_body: raw_body, signing_secret: credential&.webhook_signing_secret ) Rails.logger.warn('[SpreeUberDirect] webhook signature verification failed') return head :unauthorized end payload = JSON.parse(raw_body) # Uber's dashboard lets a webhook subscribe to three event kinds on # this one endpoint: `event.delivery_status` (the only one with a # `status` field — confirmed live), `event.courier_update` (a # courier GPS ping fired every 20s once a courier is assigned — no # `status` field, confirmed live), and `event.refund_request` (fired # when a refund is requested — no `status` field either, confirmed # directly against Uber's own webhook payload docs). Unlike a # courier ping, a refund notification carries real, unrecoverable # data (data.id, currency_code, total_partner_refund, # total_uber_refund, refund_fees, refund_order_items) — worth a # durable record even with no consumer yet, so it's persisted to its # own RefundEvent table before falling into the generic # blank-status drop below. if payload['kind'] == 'event.refund_request' find_or_log_refund_event(raw_body, payload) return head :ok end # WebhookEvent's `status` column is specifically Uber's *delivery* # status (see its own model comment) and requires presence, so # acknowledge and drop anything else that doesn't carry one rather # than letting it fail validation and surface as a 404 to Uber's # webhook delivery system — a courier-location ping needs no # processing from this extension today. if payload['status'].blank? Rails.logger.debug { "[SpreeUberDirect] dropping webhook with no status (kind=#{payload['kind']}, id=#{payload['id']})" } return head :ok end event = find_or_log_event(raw_body, payload) SpreeUberDirect::DeliveryWebhookJob.perform_later(event.id) if event.previously_new_record? head :ok rescue JSON::ParserError head :bad_request end |