-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(gocardless): Treat Gocardless webhooks events in separate jobs (#…
…2695) This pull request focuses on improving the GoCardless webhook events management and refactoring the integration by introducing new services for handling webhooks and events using the standard call/Result pattern. The main changes include replacing direct calls to `GocardlessService` with more specific services and updating the logic to treat each webhook events in isolation to avoid failling a batch if a single event is causing an error. ### Refactoring and Service Extraction: * **Refactored Webhook Handling:** - Replaced `GocardlessService.handle_incoming_webhook` with `Gocardless::HandleIncomingWebhookService.call` in `WebhooksController`. (`app/controllers/webhooks_controller.rb`) - Extracted webhook handling logic into a new service `HandleIncomingWebhookService`. (`app/services/payment_providers/gocardless/handle_incoming_webhook_service.rb`) * **Refactored Event Handling:** - Replaced `GocardlessService.handle_event` with `Gocardless::HandleEventService.call` in `HandleEventJob`. (`app/jobs/payment_providers/gocardless/handle_event_job.rb`) - Extracted event handling logic into a new service `HandleEventService`. (`app/services/payment_providers/gocardless/handle_event_service.rb`) - Keep acception the legacy `events_json` input argument in `HandleEventJob` to avoid issues with enqueued/dead jobs for now
- Loading branch information
1 parent
52dff29
commit 787c6ed
Showing
10 changed files
with
299 additions
and
253 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
61 changes: 61 additions & 0 deletions
61
app/services/payment_providers/gocardless/handle_event_service.rb
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# frozen_string_literal: true | ||
|
||
module PaymentProviders | ||
module Gocardless | ||
class HandleEventService < BaseService | ||
PAYMENT_ACTIONS = %w[paid_out failed cancelled customer_approval_denied charged_back].freeze | ||
REFUND_ACTIONS = %w[created funds_returned paid refund_settled failed].freeze | ||
|
||
PAYMENT_SERVICE_CLASS_MAP = { | ||
"Invoice" => Invoices::Payments::GocardlessService, | ||
"PaymentRequest" => PaymentRequests::Payments::GocardlessService | ||
}.freeze | ||
|
||
def initialize(event_json:) | ||
@event_json = event_json | ||
|
||
super | ||
end | ||
|
||
def call | ||
case event.resource_type | ||
when 'payments' | ||
if PAYMENT_ACTIONS.include?(event.action) | ||
payment_service_klass(event) | ||
.new.update_payment_status( | ||
provider_payment_id: event.links.payment, | ||
status: event.action | ||
).raise_if_error! | ||
end | ||
when 'refunds' | ||
if REFUND_ACTIONS.include?(event.action) | ||
CreditNotes::Refunds::GocardlessService | ||
.new.update_status( | ||
provider_refund_id: event.links.refund, | ||
status: event.action, | ||
metadata: event.metadata | ||
).raise_if_error! | ||
end | ||
end | ||
|
||
result | ||
end | ||
|
||
private | ||
|
||
attr_reader :organization, :event_json | ||
|
||
def event | ||
@event ||= GoCardlessPro::Resources::Event.new(JSON.parse(event_json)) | ||
end | ||
|
||
def payment_service_klass(event) | ||
payable_type = event.metadata["lago_payable_type"] || "Invoice" | ||
|
||
PAYMENT_SERVICE_CLASS_MAP.fetch(payable_type) do | ||
raise NameError, "Invalid lago_payable_type: #{payable_type}" | ||
end | ||
end | ||
end | ||
end | ||
end |
48 changes: 48 additions & 0 deletions
48
app/services/payment_providers/gocardless/handle_incoming_webhook_service.rb
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# frozen_string_literal: true | ||
|
||
module PaymentProviders | ||
module Gocardless | ||
class HandleIncomingWebhookService < BaseService | ||
def initialize(organization_id:, body:, signature:, code: nil) | ||
@organization_id = organization_id | ||
@body = body | ||
@signature = signature | ||
@code = code | ||
|
||
super | ||
end | ||
|
||
def call | ||
payment_provider_result = PaymentProviders::FindService.call( | ||
organization_id:, | ||
code:, | ||
payment_provider_type: 'gocardless' | ||
) | ||
return payment_provider_result unless payment_provider_result.success? | ||
|
||
result.events = GoCardlessPro::Webhook.parse( | ||
request_body: body, | ||
signature_header: signature, | ||
webhook_endpoint_secret: payment_provider_result.payment_provider&.webhook_secret | ||
) | ||
|
||
result.events.each do |event| | ||
PaymentProviders::Gocardless::HandleEventJob.perform_later( | ||
organization: payment_provider_result.payment_provider.organization, | ||
event_json: event.to_json | ||
) | ||
end | ||
|
||
result | ||
rescue JSON::ParserError | ||
result.service_failure!(code: 'webhook_error', message: 'Invalid payload') | ||
rescue GoCardlessPro::Webhook::InvalidSignatureError | ||
result.service_failure!(code: 'webhook_error', message: 'Invalid signature') | ||
end | ||
|
||
private | ||
|
||
attr_reader :organization_id, :body, :signature, :code | ||
end | ||
end | ||
end |
This file contains 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
This file contains 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
This file contains 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
Oops, something went wrong.