diff --git a/app/jobs/payment_providers/stripe/handle_event_job.rb b/app/jobs/payment_providers/stripe/handle_event_job.rb index 11a406883a7..1fc3db39b06 100644 --- a/app/jobs/payment_providers/stripe/handle_event_job.rb +++ b/app/jobs/payment_providers/stripe/handle_event_job.rb @@ -9,7 +9,7 @@ class HandleEventJob < ApplicationJob retry_on BaseService::NotFoundFailure def perform(organization:, event:) - result = PaymentProviders::StripeService.new.handle_event( + result = PaymentProviders::Stripe::HandleEventService.call( organization:, event_json: event ) diff --git a/app/services/payment_providers/stripe/handle_event_service.rb b/app/services/payment_providers/stripe/handle_event_service.rb new file mode 100644 index 00000000000..b789e8c2875 --- /dev/null +++ b/app/services/payment_providers/stripe/handle_event_service.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +module PaymentProviders + module Stripe + class HandleEventService < BaseService + EVENT_MAPPING = { + 'setup_intent.succeeded' => PaymentProviders::Stripe::Webhooks::SetupIntentSucceededService, + 'customer.updated' => PaymentProviders::Stripe::Webhooks::CustomerUpdatedService, + 'charge.dispute.closed' => PaymentProviders::Stripe::Webhooks::ChargeDisputeClosedService + }.freeze + + PAYMENT_SERVICE_CLASS_MAP = { + "Invoice" => Invoices::Payments::StripeService, + "PaymentRequest" => PaymentRequests::Payments::StripeService + }.freeze + + def initialize(organization:, event_json:) + @organization = organization + @event_json = event_json + + super + end + + def call + unless PaymentProviders::StripeProvider::WEBHOOKS_EVENTS.include?(event.type) + Rails.logger.warn("Unexpected stripe event type: #{event.type}") + return result + end + + if EVENT_MAPPING[event.type].present? + EVENT_MAPPING[event.type].call( + organization_id: organization.id, + event: + ).raise_if_error! + + return result + end + + case event.type + when 'charge.succeeded' + payment_service_klass(event) + .new.update_payment_status( + organization_id: organization.id, + provider_payment_id: event.data.object.payment_intent, + status: 'succeeded', + metadata: event.data.object.metadata.to_h.symbolize_keys + ).raise_if_error! + when 'payment_intent.payment_failed', 'payment_intent.succeeded' + status = (event.type == 'payment_intent.succeeded') ? 'succeeded' : 'failed' + payment_service_klass(event) + .new.update_payment_status( + organization_id: organization.id, + provider_payment_id: event.data.object.id, + status:, + metadata: event.data.object.metadata.to_h.symbolize_keys + ).raise_if_error! + when 'payment_method.detached' + PaymentProviderCustomers::StripeService + .new + .delete_payment_method( + organization_id: organization.id, + stripe_customer_id: event.data.object.customer, + payment_method_id: event.data.object.id, + metadata: event.data.object.metadata.to_h.symbolize_keys + ).raise_if_error! + when 'charge.refund.updated' + CreditNotes::Refunds::StripeService + .new.update_status( + provider_refund_id: event.data.object.id, + status: event.data.object.status, + metadata: event.data.object.metadata.to_h.symbolize_keys + ) + end + rescue BaseService::NotFoundFailure => e + # NOTE: Error with stripe sandbox should be ignord + raise if event.livemode + + Rails.logger.warn("Stripe resource not found: #{e.message}. JSON: #{event_json}") + BaseService::Result.new # NOTE: Prevents error from being re-raised + end + + private + + attr_reader :organization, :body, :event_json + + def event + @event ||= ::Stripe::Event.construct_from(JSON.parse(event_json)) + end + + def payment_service_klass(event) + payable_type = event.data.object.metadata.to_h[: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 diff --git a/app/services/payment_providers/stripe/webhooks/base_service.rb b/app/services/payment_providers/stripe/webhooks/base_service.rb index cc49656203e..6b548e074f6 100644 --- a/app/services/payment_providers/stripe/webhooks/base_service.rb +++ b/app/services/payment_providers/stripe/webhooks/base_service.rb @@ -4,20 +4,16 @@ module PaymentProviders module Stripe module Webhooks class BaseService < BaseService - def initialize(organization_id:, event_json:) + def initialize(organization_id:, event:) @organization = Organization.find(organization_id) - @event_json = event_json + @event = event super end private - attr_reader :organization, :event_json - - def event - @event ||= ::Stripe::Event.construct_from(JSON.parse(event_json)) - end + attr_reader :organization, :event def metadata @metadata ||= event.data.object.metadata.to_h.symbolize_keys diff --git a/app/services/payment_providers/stripe/webhooks/setup_intent_succeeded_service.rb b/app/services/payment_providers/stripe/webhooks/setup_intent_succeeded_service.rb index 0014e16f45d..b1b03425eca 100644 --- a/app/services/payment_providers/stripe/webhooks/setup_intent_succeeded_service.rb +++ b/app/services/payment_providers/stripe/webhooks/setup_intent_succeeded_service.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module PaymentProviders - module Stripe - module Webhooks + module Stripe + module Webhooks class SetupIntentSucceededService < BaseService include Customers::PaymentProviderFinder diff --git a/app/services/payment_providers/stripe_service.rb b/app/services/payment_providers/stripe_service.rb index 3f1553394a3..340b800f7bb 100644 --- a/app/services/payment_providers/stripe_service.rb +++ b/app/services/payment_providers/stripe_service.rb @@ -2,11 +2,6 @@ module PaymentProviders class StripeService < BaseService - PAYMENT_SERVICE_CLASS_MAP = { - "Invoice" => Invoices::Payments::StripeService, - "PaymentRequest" => PaymentRequests::Payments::StripeService - }.freeze - def create_or_update(**args) payment_provider_result = PaymentProviders::FindService.call( organization_id: args[:organization_id], @@ -84,71 +79,6 @@ def handle_incoming_webhook(organization_id:, params:, signature:, code: nil) result.service_failure!(code: 'webhook_error', message: 'Invalid signature') end - def handle_event(organization:, event_json:) - event = ::Stripe::Event.construct_from(JSON.parse(event_json)) - unless PaymentProviders::StripeProvider::WEBHOOKS_EVENTS.include?(event.type) - Rails.logger.warn("Unexpected stripe event type: #{event.type}") - return result - end - - case event.type - when 'setup_intent.succeeded' - PaymentProviders::Stripe::Webhooks::SetupIntentSucceededService.call( - organization_id: organization.id, - event_json: - ).raise_if_error! - when 'customer.updated' - PaymentProviders::Stripe::Webhooks::CustomerUpdatedService.call( - organization_id: organization.id, - event_json: - ).raise_if_error! - when 'charge.succeeded' - payment_service_klass(event) - .new.update_payment_status( - organization_id: organization.id, - provider_payment_id: event.data.object.payment_intent, - status: 'succeeded', - metadata: event.data.object.metadata.to_h.symbolize_keys - ).raise_if_error! - when 'charge.dispute.closed' - PaymentProviders::Stripe::Webhooks::ChargeDisputeClosedService.call( - organization_id: organization.id, - event_json: - ).raise_if_error! - when 'payment_intent.payment_failed', 'payment_intent.succeeded' - status = (event.type == 'payment_intent.succeeded') ? 'succeeded' : 'failed' - payment_service_klass(event) - .new.update_payment_status( - organization_id: organization.id, - provider_payment_id: event.data.object.id, - status:, - metadata: event.data.object.metadata.to_h.symbolize_keys - ).raise_if_error! - when 'payment_method.detached' - PaymentProviderCustomers::StripeService - .new - .delete_payment_method( - organization_id: organization.id, - stripe_customer_id: event.data.object.customer, - payment_method_id: event.data.object.id, - metadata: event.data.object.metadata.to_h.symbolize_keys - ).raise_if_error! - when 'charge.refund.updated' - CreditNotes::Refunds::StripeService - .new.update_status( - provider_refund_id: event.data.object.id, - status: event.data.object.status, - metadata: event.data.object.metadata.to_h.symbolize_keys - ) - end - rescue BaseService::NotFoundFailure => e - # NOTE: Error with stripe sandbox should be ignord - raise if event.livemode - - Rails.logger.warn("Stripe resource not found: #{e.message}. JSON: #{event_json}") - BaseService::Result.new # NOTE: Prevents error from being re-raised - end - private def unregister_webhook(stripe_provider, api_key) @@ -166,13 +96,5 @@ def unregister_webhook(stripe_provider, api_key) Sentry.capture_exception(e) end - - def payment_service_klass(event) - payable_type = event.data.object.metadata.to_h[:lago_payable_type] || "Invoice" - - PAYMENT_SERVICE_CLASS_MAP.fetch(payable_type) do - raise NameError, "Invalid lago_payable_type: #{payable_type}" - end - end end end diff --git a/spec/jobs/payment_providers/stripe/handle_event_job_spec.rb b/spec/jobs/payment_providers/stripe/handle_event_job_spec.rb index 24f541d1640..b67b014a0ad 100644 --- a/spec/jobs/payment_providers/stripe/handle_event_job_spec.rb +++ b/spec/jobs/payment_providers/stripe/handle_event_job_spec.rb @@ -3,7 +3,6 @@ require 'rails_helper' RSpec.describe PaymentProviders::Stripe::HandleEventJob, type: :job do - let(:stripe_service) { instance_double(PaymentProviders::StripeService) } let(:result) { BaseService::Result.new } let(:organization) { create(:organization) } @@ -12,9 +11,8 @@ end before do - allow(PaymentProviders::StripeService).to receive(:new) - .and_return(stripe_service) - allow(stripe_service).to receive(:handle_event) + allow(PaymentProviders::Stripe::HandleEventService) + .to receive(:call) .and_return(result) end @@ -24,7 +22,6 @@ event: stripe_event ) - expect(PaymentProviders::StripeService).to have_received(:new) - expect(stripe_service).to have_received(:handle_event) + expect(PaymentProviders::Stripe::HandleEventService).to have_received(:call) end end diff --git a/spec/services/payment_providers/stripe/handle_event_service_spec.rb b/spec/services/payment_providers/stripe/handle_event_service_spec.rb new file mode 100644 index 00000000000..dcfb1e8d66a --- /dev/null +++ b/spec/services/payment_providers/stripe/handle_event_service_spec.rb @@ -0,0 +1,267 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe PaymentProviders::Stripe::HandleEventService do + subject(:event_service) { described_class.new(organization:, event_json:) } + + let(:organization) { create(:organization) } + + let(:payment_service) { instance_double(Invoices::Payments::StripeService) } + let(:provider_customer_service) { instance_double(PaymentProviderCustomers::StripeService) } + let(:service_result) { BaseService::Result.new } + + before do + allow(Invoices::Payments::StripeService).to receive(:new) + .and_return(payment_service) + allow(payment_service).to receive(:update_payment_status) + .and_return(service_result) + end + + context 'when payment intent event' do + let(:event_json) do + path = Rails.root.join('spec/fixtures/stripe/payment_intent_event.json') + File.read(path) + end + + it 'routes the event to an other service' do + result = event_service.call + + expect(result).to be_success + + expect(Invoices::Payments::StripeService).to have_received(:new) + expect(payment_service).to have_received(:update_payment_status) + .with( + organization_id: organization.id, + provider_payment_id: 'pi_1JKS2Y2VYugoKSBzNHPFBNj9', + status: 'succeeded', + metadata: { + lago_invoice_id: 'a587e552-36bc-4334-81f2-abcbf034ad3f' + } + ) + end + end + + context "when payment intent event for a payment request" do + let(:payment_service) { instance_double(PaymentRequests::Payments::StripeService) } + + let(:event_json) do + path = Rails.root.join("spec/fixtures/stripe/payment_intent_event_payment_request.json") + File.read(path) + end + + before do + allow(PaymentRequests::Payments::StripeService).to receive(:new) + .and_return(payment_service) + allow(payment_service).to receive(:update_payment_status) + .and_return(service_result) + end + + it "routes the event to an other service" do + result = event_service.call + + expect(result).to be_success + + expect(PaymentRequests::Payments::StripeService).to have_received(:new) + expect(payment_service).to have_received(:update_payment_status) + .with( + organization_id: organization.id, + provider_payment_id: "pi_1JKS2Y2VYugoKSBzNHPFBNj9", + status: "succeeded", + metadata: { + lago_payment_request_id: "a587e552-36bc-4334-81f2-abcbf034ad3f", + lago_payable_type: "PaymentRequest" + } + ) + end + end + + context "when payment intent event with an invalid payable type" do + let(:event_json) do + path = Rails.root.join("spec/fixtures/stripe/payment_intent_event_invalid_payable_type.json") + File.read(path) + end + + it "routes the event to an other service" do + expect { event_service.call }.to raise_error(NameError, "Invalid lago_payable_type: InvalidPayableTypeName") + end + end + + context 'when charge event' do + let(:event_json) do + path = Rails.root.join('spec/fixtures/stripe/charge_event.json') + File.read(path) + end + + it 'routes the event to an other service' do + result = event_service.call + + expect(result).to be_success + + expect(Invoices::Payments::StripeService).to have_received(:new) + expect(payment_service).to have_received(:update_payment_status) + .with( + organization_id: organization.id, + provider_payment_id: 'pi_123456', + status: 'succeeded', + metadata: {} + ) + end + end + + context "when charge event for a payment request" do + let(:payment_service) { instance_double(PaymentRequests::Payments::StripeService) } + + let(:event_json) do + path = Rails.root.join("spec/fixtures/stripe/charge_event_payment_request.json") + File.read(path) + end + + before do + allow(PaymentRequests::Payments::StripeService).to receive(:new) + .and_return(payment_service) + allow(payment_service).to receive(:update_payment_status) + .and_return(service_result) + end + + it "routes the event to an other service" do + result = event_service.call + + expect(result).to be_success + + expect(PaymentRequests::Payments::StripeService).to have_received(:new) + expect(payment_service).to have_received(:update_payment_status) + .with( + organization_id: organization.id, + provider_payment_id: 'pi_123456', + status: "succeeded", + metadata: { + lago_payment_request_id: "a587e552-36bc-4334-81f2-abcbf034ad3f", + lago_payable_type: "PaymentRequest" + } + ) + end + end + + context "when charge event with an invalid payable type" do + let(:event_json) do + path = Rails.root.join("spec/fixtures/stripe/charge_event_invalid_payable_type.json") + File.read(path) + end + + it "routes the event to an other service" do + expect { event_service.call }.to raise_error(NameError, "Invalid lago_payable_type: InvalidPayableTypeName") + end + end + + context 'when setup intent event' do + let(:event_json) do + path = Rails.root.join('spec/fixtures/stripe/setup_intent_event.json') + File.read(path) + end + + before do + allow(PaymentProviders::Stripe::Webhooks::SetupIntentSucceededService).to receive(:call) + .and_return(service_result) + end + + it 'routes the event to an other service' do + result = event_service.call + + expect(result).to be_success + + expect(PaymentProviders::Stripe::Webhooks::SetupIntentSucceededService).to have_received(:call) + end + end + + context 'when customer updated event' do + let(:event_json) do + path = Rails.root.join('spec/fixtures/stripe/customer_updated_event.json') + File.read(path) + end + + before do + allow(PaymentProviders::Stripe::Webhooks::CustomerUpdatedService).to receive(:call) + .and_return(service_result) + end + + it 'routes the event to an other service' do + result = event_service.call + + expect(result).to be_success + + expect(PaymentProviders::Stripe::Webhooks::CustomerUpdatedService).to have_received(:call) + end + end + + context 'when payment method detached event' do + let(:event_json) do + path = Rails.root.join('spec/fixtures/stripe/payment_method_detached_event.json') + File.read(path) + end + + before do + allow(PaymentProviderCustomers::StripeService).to receive(:new) + .and_return(provider_customer_service) + allow(provider_customer_service).to receive(:delete_payment_method) + .and_return(service_result) + end + + it 'routes the event to an other service' do + result = event_service.call + + expect(result).to be_success + + expect(PaymentProviderCustomers::StripeService).to have_received(:new) + expect(provider_customer_service).to have_received(:delete_payment_method) + end + end + + context 'when refund updated event' do + let(:refund_service) { instance_double(CreditNotes::Refunds::StripeService) } + + let(:event_json) do + path = Rails.root.join('spec/fixtures/stripe/charge_refund_updated_event.json') + File.read(path) + end + + before do + allow(CreditNotes::Refunds::StripeService).to receive(:new) + .and_return(refund_service) + allow(refund_service).to receive(:update_status) + .and_return(service_result) + end + + it 'routes the event to an other service' do + result = event_service.call + + expect(result).to be_success + + expect(CreditNotes::Refunds::StripeService).to have_received(:new) + expect(refund_service).to have_received(:update_status) + end + end + + context 'when event does not match an expected event type' do + let(:event_json) do + { + id: 'foo', + type: 'invalid', + data: { + object: {id: 'foo'} + } + }.to_json + end + + it 'returns an empty result' do + result = event_service.call + + aggregate_failures do + expect(result).to be_success + + expect(Invoices::Payments::StripeService).not_to have_received(:new) + expect(payment_service).not_to have_received(:update_payment_status) + end + end + end +end diff --git a/spec/services/payment_providers/stripe/webhooks/charge_dispute_closed_service_spec.rb b/spec/services/payment_providers/stripe/webhooks/charge_dispute_closed_service_spec.rb index a21d37cc7ef..9d9024cd473 100644 --- a/spec/services/payment_providers/stripe/webhooks/charge_dispute_closed_service_spec.rb +++ b/spec/services/payment_providers/stripe/webhooks/charge_dispute_closed_service_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe PaymentProviders::Stripe::Webhooks::ChargeDisputeClosedService, type: :service do - subject(:service) { described_class.new(organization_id:, event_json:) } + subject(:service) { described_class.new(organization_id:, event:) } let(:organization_id) { organization.id } let(:organization) { create(:organization) } @@ -13,6 +13,8 @@ let(:lose_dispute_service) { Invoices::LoseDisputeService.new(invoice:) } let(:invoice) { create(:invoice, customer:, organization:, status:, payment_status: 'succeeded') } + let(:event) { ::Stripe::Event.construct_from(JSON.parse(event_json)) } + describe '#call' do before { payment } diff --git a/spec/services/payment_providers/stripe/webhooks/customer_updated_service_spec.rb b/spec/services/payment_providers/stripe/webhooks/customer_updated_service_spec.rb index a5b70fcfc55..ab16fc99de7 100644 --- a/spec/services/payment_providers/stripe/webhooks/customer_updated_service_spec.rb +++ b/spec/services/payment_providers/stripe/webhooks/customer_updated_service_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe PaymentProviders::Stripe::Webhooks::CustomerUpdatedService, type: :service do - subject(:webhook_service) { described_class.new(organization_id: organization.id, event_json:) } + subject(:webhook_service) { described_class.new(organization_id: organization.id, event:) } let(:organization) { create(:organization) } let(:customer) { create(:customer, organization:) } diff --git a/spec/services/payment_providers/stripe/webhooks/setup_intent_succeeded_service_spec.rb b/spec/services/payment_providers/stripe/webhooks/setup_intent_succeeded_service_spec.rb index ee620e630b5..9eb645da526 100644 --- a/spec/services/payment_providers/stripe/webhooks/setup_intent_succeeded_service_spec.rb +++ b/spec/services/payment_providers/stripe/webhooks/setup_intent_succeeded_service_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe PaymentProviders::Stripe::Webhooks::SetupIntentSucceededService, type: :service do - subject(:webhook_service) { described_class.new(organization_id: organization.id, event_json:) } + subject(:webhook_service) { described_class.new(organization_id: organization.id, event:) } let(:organization) { create(:organization) } let(:customer) { create(:customer, organization:) } diff --git a/spec/services/payment_providers/stripe_service_spec.rb b/spec/services/payment_providers/stripe_service_spec.rb index ae86a69addb..0276baa2e98 100644 --- a/spec/services/payment_providers/stripe_service_spec.rb +++ b/spec/services/payment_providers/stripe_service_spec.rb @@ -225,295 +225,4 @@ end end end - - describe '.handle_event' do - let(:payment_service) { instance_double(Invoices::Payments::StripeService) } - let(:provider_customer_service) { instance_double(PaymentProviderCustomers::StripeService) } - let(:service_result) { BaseService::Result.new } - - before do - allow(Invoices::Payments::StripeService).to receive(:new) - .and_return(payment_service) - allow(payment_service).to receive(:update_payment_status) - .and_return(service_result) - end - - context 'when payment intent event' do - let(:event) do - path = Rails.root.join('spec/fixtures/stripe/payment_intent_event.json') - File.read(path) - end - - it 'routes the event to an other service' do - result = stripe_service.handle_event( - organization:, - event_json: event - ) - - expect(result).to be_success - - expect(Invoices::Payments::StripeService).to have_received(:new) - expect(payment_service).to have_received(:update_payment_status) - .with( - organization_id: organization.id, - provider_payment_id: 'pi_1JKS2Y2VYugoKSBzNHPFBNj9', - status: 'succeeded', - metadata: { - lago_invoice_id: 'a587e552-36bc-4334-81f2-abcbf034ad3f' - } - ) - end - end - - context "when payment intent event for a payment request" do - let(:payment_service) { instance_double(PaymentRequests::Payments::StripeService) } - - let(:event) do - path = Rails.root.join("spec/fixtures/stripe/payment_intent_event_payment_request.json") - File.read(path) - end - - before do - allow(PaymentRequests::Payments::StripeService).to receive(:new) - .and_return(payment_service) - allow(payment_service).to receive(:update_payment_status) - .and_return(service_result) - end - - it "routes the event to an other service" do - result = stripe_service.handle_event( - organization:, - event_json: event - ) - - expect(result).to be_success - - expect(PaymentRequests::Payments::StripeService).to have_received(:new) - expect(payment_service).to have_received(:update_payment_status) - .with( - organization_id: organization.id, - provider_payment_id: "pi_1JKS2Y2VYugoKSBzNHPFBNj9", - status: "succeeded", - metadata: { - lago_payment_request_id: "a587e552-36bc-4334-81f2-abcbf034ad3f", - lago_payable_type: "PaymentRequest" - } - ) - end - end - - context "when payment intent event with an invalid payable type" do - let(:event) do - path = Rails.root.join("spec/fixtures/stripe/payment_intent_event_invalid_payable_type.json") - File.read(path) - end - - it "routes the event to an other service" do - expect { - stripe_service.handle_event(organization:, event_json: event) - }.to raise_error(NameError, "Invalid lago_payable_type: InvalidPayableTypeName") - end - end - - context 'when charge event' do - let(:event) do - path = Rails.root.join('spec/fixtures/stripe/charge_event.json') - File.read(path) - end - - it 'routes the event to an other service' do - result = stripe_service.handle_event( - organization:, - event_json: event - ) - - expect(result).to be_success - - expect(Invoices::Payments::StripeService).to have_received(:new) - expect(payment_service).to have_received(:update_payment_status) - .with( - organization_id: organization.id, - provider_payment_id: 'pi_123456', - status: 'succeeded', - metadata: {} - ) - end - end - - context "when charge event for a payment request" do - let(:payment_service) { instance_double(PaymentRequests::Payments::StripeService) } - - let(:event) do - path = Rails.root.join("spec/fixtures/stripe/charge_event_payment_request.json") - File.read(path) - end - - before do - allow(PaymentRequests::Payments::StripeService).to receive(:new) - .and_return(payment_service) - allow(payment_service).to receive(:update_payment_status) - .and_return(service_result) - end - - it "routes the event to an other service" do - result = stripe_service.handle_event( - organization:, - event_json: event - ) - - expect(result).to be_success - - expect(PaymentRequests::Payments::StripeService).to have_received(:new) - expect(payment_service).to have_received(:update_payment_status) - .with( - organization_id: organization.id, - provider_payment_id: 'pi_123456', - status: "succeeded", - metadata: { - lago_payment_request_id: "a587e552-36bc-4334-81f2-abcbf034ad3f", - lago_payable_type: "PaymentRequest" - } - ) - end - end - - context "when charge event with an invalid payable type" do - let(:event) do - path = Rails.root.join("spec/fixtures/stripe/charge_event_invalid_payable_type.json") - File.read(path) - end - - it "routes the event to an other service" do - expect { - stripe_service.handle_event(organization:, event_json: event) - }.to raise_error(NameError, "Invalid lago_payable_type: InvalidPayableTypeName") - end - end - - context 'when setup intent event' do - let(:event) do - path = Rails.root.join('spec/fixtures/stripe/setup_intent_event.json') - File.read(path) - end - - before do - allow(PaymentProviders::Stripe::Webhooks::SetupIntentSucceededService).to receive(:call) - .and_return(service_result) - end - - it 'routes the event to an other service' do - result = stripe_service.handle_event( - organization:, - event_json: event - ) - - expect(result).to be_success - - expect(PaymentProviders::Stripe::Webhooks::SetupIntentSucceededService).to have_received(:call) - end - end - - context 'when customer updated event' do - let(:event) do - path = Rails.root.join('spec/fixtures/stripe/customer_updated_event.json') - File.read(path) - end - - before do - allow(PaymentProviders::Stripe::Webhooks::CustomerUpdatedService).to receive(:call) - .and_return(service_result) - end - - it 'routes the event to an other service' do - result = stripe_service.handle_event( - organization:, - event_json: event - ) - - expect(result).to be_success - - expect(PaymentProviders::Stripe::Webhooks::CustomerUpdatedService).to have_received(:call) - end - end - - context 'when payment method detached event' do - let(:event) do - path = Rails.root.join('spec/fixtures/stripe/payment_method_detached_event.json') - File.read(path) - end - - before do - allow(PaymentProviderCustomers::StripeService).to receive(:new) - .and_return(provider_customer_service) - allow(provider_customer_service).to receive(:delete_payment_method) - .and_return(service_result) - end - - it 'routes the event to an other service' do - result = stripe_service.handle_event( - organization:, - event_json: event - ) - - expect(result).to be_success - - expect(PaymentProviderCustomers::StripeService).to have_received(:new) - expect(provider_customer_service).to have_received(:delete_payment_method) - end - end - - context 'when refund updated event' do - let(:refund_service) { instance_double(CreditNotes::Refunds::StripeService) } - - let(:event) do - path = Rails.root.join('spec/fixtures/stripe/charge_refund_updated_event.json') - File.read(path) - end - - before do - allow(CreditNotes::Refunds::StripeService).to receive(:new) - .and_return(refund_service) - allow(refund_service).to receive(:update_status) - .and_return(service_result) - end - - it 'routes the event to an other service' do - result = stripe_service.handle_event( - organization:, - event_json: event - ) - - expect(result).to be_success - - expect(CreditNotes::Refunds::StripeService).to have_received(:new) - expect(refund_service).to have_received(:update_status) - end - end - - context 'when event does not match an expected event type' do - let(:event) do - { - id: 'foo', - type: 'invalid', - data: { - object: {id: 'foo'} - } - } - end - - it 'returns an empty result' do - result = stripe_service.handle_event( - organization:, - event_json: event.to_json - ) - - aggregate_failures do - expect(result).to be_success - - expect(Invoices::Payments::StripeService).not_to have_received(:new) - expect(payment_service).not_to have_received(:update_payment_status) - end - end - end - end end