Skip to content

Commit

Permalink
feat(dunning): Add payment_request.payment_failure webhook (#2501)
Browse files Browse the repository at this point in the history
## Roadmap Task

👉
https://getlago.canny.io/feature-requests/p/send-reminders-for-overdue-invoices

## Context

We want to be able to manually request payment of the overdue balance
and send emails for reminders.

## Description

The goal of this change is to add the missing payment request payment
failure webhook.
  • Loading branch information
ancorcruz authored Aug 28, 2024
1 parent 30c1836 commit af0dc41
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/jobs/send_webhook_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class SendWebhookJob < ApplicationJob
'credit_note.provider_refund_failure' => Webhooks::CreditNotes::PaymentProviderRefundFailureService,
'payment_provider.error' => Webhooks::PaymentProviders::ErrorService,
'payment_request.created' => Webhooks::PaymentRequests::CreatedService,
"payment_request.payment_failure" => Webhooks::PaymentProviders::PaymentRequestPaymentFailureService,
'subscription.terminated' => Webhooks::Subscriptions::TerminatedService,
'subscription.started' => Webhooks::Subscriptions::StartedService,
'subscription.termination_alert' => Webhooks::Subscriptions::TerminationAlertService,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module V1
module PaymentProviders
class PaymentRequestPaymentErrorSerializer < ModelSerializer
alias_method :payment_request, :model

def serialize
{
lago_payment_request_id: payment_request.id,
lago_invoice_ids: payment_request.invoice_ids,
lago_customer_id: payment_request.customer.id,
external_customer_id: payment_request.customer.external_id,
provider_customer_id: options[:provider_customer_id],
payment_provider: payment_request.customer.payment_provider,
payment_provider_code: payment_request.customer.payment_provider_code,
provider_error: options[:provider_error]
}
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def initialize(payment_request, params)
end

def call_async
SendWebhookJob.perform_later('payment_request.payment_failure', payment_request, params)
SendWebhookJob.perform_later("payment_request.payment_failure", payment_request, params)

result
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Webhooks
module PaymentProviders
class PaymentRequestPaymentFailureService < Webhooks::BaseService
private

def current_organization
@current_organization ||= object.organization
end

def object_serializer
::V1::PaymentProviders::PaymentRequestPaymentErrorSerializer.new(
object,
root_name: object_type,
provider_error: options[:provider_error],
provider_customer_id: options[:provider_customer_id]
)
end

def webhook_type
"payment_request.payment_failure"
end

def object_type
"payment_provider_payment_request_payment_error"
end
end
end
end
28 changes: 28 additions & 0 deletions spec/jobs/send_webhook_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -473,4 +473,32 @@
expect(webhook_service).to have_received(:call)
end
end

context 'when webhook_type is payment_request.payment_failure' do
let(:webhook_service) { instance_double(Webhooks::PaymentProviders::PaymentRequestPaymentFailureService) }
let(:payment_request) { create(:payment_request) }
let(:webhook_options) do
{
provider_error: {
message: 'message',
error_code: 'code'
}
}
end

before do
allow(Webhooks::PaymentProviders::PaymentRequestPaymentFailureService)
.to receive(:new)
.with(object: payment_request, options: webhook_options)
.and_return(webhook_service)
allow(webhook_service).to receive(:call)
end

it 'calls the webhook payment_request_payment_failure service' do
send_webhook_job.perform_now('payment_request.payment_failure', payment_request, webhook_options)

expect(Webhooks::PaymentProviders::PaymentRequestPaymentFailureService).to have_received(:new)
expect(webhook_service).to have_received(:call)
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe ::V1::PaymentProviders::PaymentRequestPaymentErrorSerializer do
subject(:serializer) { described_class.new(payment_request, options) }

let(:payment_request) { create(:payment_request, organization:, customer:, invoices: [invoice]) }
let(:invoice) { create(:invoice, customer:, organization:) }
let(:customer) { create(:customer, organization:) }
let(:organization) { create(:organization) }
let(:options) do
{
"provider_customer_id" => "customer",
"provider_error" => {
"error_message" => "message",
"error_code" => "code"
}
}.with_indifferent_access
end

it "serializes the object" do
result = JSON.parse(serializer.to_json)

aggregate_failures do
expect(result["data"]["lago_payment_request_id"]).to eq(payment_request.id)
expect(result["data"]["lago_invoice_ids"]).to eq([invoice.id])
expect(result["data"]["lago_customer_id"]).to eq(customer.id)
expect(result["data"]["external_customer_id"]).to eq(customer.external_id)
expect(result["data"]["provider_customer_id"]).to eq(options[:provider_customer_id])
expect(result["data"]["payment_provider"]).to eq(customer.payment_provider)
expect(result["data"]["payment_provider_code"]).to eq(customer.payment_provider_code)
expect(result["data"]["provider_error"]).to eq(options[:provider_error])
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe Webhooks::PaymentProviders::PaymentRequestPaymentFailureService do
subject(:webhook_service) { described_class.new(object: payment_request, options: webhook_options) }

let(:payment_request) { create(:payment_request, organization:, customer:) }
let(:customer) { create(:customer, organization:) }
let(:organization) { create(:organization) }
let(:webhook_options) { {provider_error: {message: "message", error_code: "code"}} }

describe ".call" do
it_behaves_like "creates webhook", "payment_request.payment_failure", "payment_provider_payment_request_payment_error"
end
end

0 comments on commit af0dc41

Please sign in to comment.