Blake Erickson 46759c90cd
FIX: Duplicate payments showing up in discourse UI (#118)
Duplicate payments were showing up in the discourse ui for users. Actual
transactions in stripe were not being duplicated. This fix ensures that
when parsing the api response we don't append any duplicates. Added a
duplicate entry to the specs to test for this.

I do think there can be some improvements made to this controller
endpoint, but I'd like to save those for a different and larger PR and
just get this fix out first.
2022-05-17 09:22:42 -06:00

57 lines
2.1 KiB
Ruby

# frozen_string_literal: true
module DiscourseSubscriptions
module User
class PaymentsController < ::ApplicationController
include DiscourseSubscriptions::Stripe
before_action :set_api_key
requires_login
def index
begin
customer = Customer.where(user_id: current_user.id)
customer_ids = customer.map { |c| c.customer_id } if customer
product_ids = Product.all.pluck(:external_id)
data = []
if customer_ids.present? && product_ids.present?
customer_ids.each do |customer_id|
# lots of matching because the Stripe API doesn't make it easy to match products => payments except from invoices
all_invoices = ::Stripe::Invoice.list(customer: customer_id)
invoices_with_products = parse_invoices(all_invoices, product_ids)
invoice_ids = invoices_with_products.map { |invoice| invoice[:id] }
payments = ::Stripe::PaymentIntent.list(customer: customer_id)
payments_from_invoices = payments[:data].select { |payment| invoice_ids.include?(payment[:invoice]) }
data = data | payments_from_invoices
end
end
data = data.sort_by { |pmt| pmt[:created] }.reverse
render_json_dump data
rescue ::Stripe::InvalidRequestError => e
render_json_error e.message
end
end
private
def parse_invoices(all_invoices, product_ids)
invoices_with_products = all_invoices[:data].select do |invoice|
invoice_lines = invoice[:lines][:data][0] if invoice[:lines] && invoice[:lines][:data]
invoice_product_id = parse_invoice_lines(invoice_lines)
product_ids.include?(invoice_product_id)
end
end
def parse_invoice_lines(invoice_lines)
invoice_product_id = invoice_lines[:price][:product] if invoice_lines[:price] && invoice_lines[:price][:product]
invoice_product_id = invoice_lines[:plan][:product] if invoice_lines[:plan] && invoice_lines[:plan][:product]
invoice_product_id
end
end
end
end