Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stripe): Save payment_method_data for successful Payments #3230

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/models/payment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def payment_request_succeeded
# payable_type :string default("Invoice"), not null
# payment_type :enum default("provider"), not null
# provider_payment_data :jsonb
# provider_payment_method_data :jsonb not null
# reference :string
# status :string not null
# created_at :datetime not null
Expand Down
27 changes: 2 additions & 25 deletions app/services/payment_providers/stripe/handle_event_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@ module Stripe
class HandleEventService < BaseService
EVENT_MAPPING = {
"setup_intent.succeeded" => PaymentProviders::Stripe::Webhooks::SetupIntentSucceededService,
"payment_intent.succeeded" => PaymentProviders::Stripe::Webhooks::PaymentIntentSucceededService,
"payment_intent.payment_failed" => PaymentProviders::Stripe::Webhooks::PaymentIntentPaymentFailedService,
"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
Expand All @@ -37,18 +34,6 @@ def call
end

case event.type
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,
status:,
stripe_payment: PaymentProviders::StripeProvider::StripePayment.new(
id: event.data.object.id,
status: event.data.object.status,
metadata: event.data.object.metadata.to_h.symbolize_keys
)
).raise_if_error!
when "payment_method.detached"
PaymentProviderCustomers::StripeService
.new
Expand Down Expand Up @@ -81,14 +66,6 @@ def call
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
26 changes: 26 additions & 0 deletions app/services/payment_providers/stripe/webhooks/base_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ def initialize(organization_id:, event:)

attr_reader :organization, :event

PAYMENT_SERVICE_CLASS_MAP = {
"Invoice" => Invoices::Payments::StripeService,
"PaymentRequest" => PaymentRequests::Payments::StripeService
}.freeze

def metadata
@metadata ||= event.data.object.metadata.to_h.symbolize_keys
end
Expand All @@ -30,6 +35,27 @@ def handle_missing_customer

result.not_found_failure!(resource: "stripe_customer")
end

# TODO: Move this to a proper factory
def payment_service_klass
payable_type = metadata[:lago_payable_type] || "Invoice"

PAYMENT_SERVICE_CLASS_MAP.fetch(payable_type) do
raise NameError, "Invalid lago_payable_type: #{payable_type}"
end
end

def update_payment_status!(status)
payment_service_klass.new.update_payment_status(
organization_id: organization.id,
status:,
stripe_payment: PaymentProviders::StripeProvider::StripePayment.new(
id: event.data.object.id,
status: event.data.object.status,
metadata:
)
).raise_if_error!
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module PaymentProviders
module Stripe
module Webhooks
class PaymentIntentPaymentFailedService < BaseService
def call
update_payment_status! "failed"
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module PaymentProviders
module Stripe
module Webhooks
class PaymentIntentSucceededService < BaseService
def call
@result = update_payment_status! "succeeded"
update_provider_payment_method_data
result
end

private

def update_provider_payment_method_data
latest_charge = event.data.object.charges.data.last
data = {
id: event.data.object.payment_method,
type: latest_charge.payment_method_details.type
}
if data[:type] == "card"
data[:brand] = latest_charge.payment_method_details.card.brand
data[:last4] = latest_charge.payment_method_details.card.last4
end

# NOTE: `result.payment was set by the service handling update_payment_status!
result.payment.update(provider_payment_method_data: data)
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddProviderPaymentMethodDataToPayments < ActiveRecord::Migration[7.1]
def change
add_column :payments, :provider_payment_method_data, :jsonb, null: false, default: {}
end
end
3 changes: 2 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

142 changes: 0 additions & 142 deletions spec/fixtures/stripe/charge_event.json

This file was deleted.

Loading