diff --git a/app/services/invoices/payments/cashfree_service.rb b/app/services/invoices/payments/cashfree_service.rb index 7640612c828..c7d9331a727 100644 --- a/app/services/invoices/payments/cashfree_service.rb +++ b/app/services/invoices/payments/cashfree_service.rb @@ -75,6 +75,10 @@ def should_process_payment? !!customer&.cashfree_customer&.id end + def increment_payment_attempts + invoice.update!(payment_attempts: invoice.payment_attempts + 1) + end + def client @client ||= LagoHttpClient::Client.new(::PaymentProviders::CashfreeProvider::BASE_URL) end @@ -150,7 +154,7 @@ def update_invoice_payment_status(payment_status:, deliver_webhook: true) def deliver_error_webhook(cashfree_error) DeliverErrorWebhookService.call_async(invoice, { - provider_customer_id: customer.cashfree_customer.provider_customer_id, + provider_customer_id: customer.cashfree_customer.id, provider_error: { message: cashfree_error.error_body, error_code: cashfree_error.error_code diff --git a/app/services/payment_providers/cashfree/payments/create_service.rb b/app/services/payment_providers/cashfree/payments/create_service.rb index 8b508285692..083441f2b5e 100644 --- a/app/services/payment_providers/cashfree/payments/create_service.rb +++ b/app/services/payment_providers/cashfree/payments/create_service.rb @@ -4,7 +4,7 @@ module PaymentProviders module Cashfree module Payments class CreateService < BaseService - include Customers::PaymentProviderFinder + include ::Customers::PaymentProviderFinder PENDING_STATUSES = %w[PARTIALLY_PAID].freeze SUCCESS_STATUSES = %w[PAID].freeze @@ -20,6 +20,10 @@ def initialize(payment:) def call result.payment = payment + + # NOTE: No need to register the payment with Cashfree Payments for the Payment Link feature. + # Simply create a single `Payment` record and update it upon receiving the webhook, which works perfectly fine. + result end diff --git a/app/services/payment_requests/payments/cashfree_service.rb b/app/services/payment_requests/payments/cashfree_service.rb index 792704c5454..d525bc13a40 100644 --- a/app/services/payment_requests/payments/cashfree_service.rb +++ b/app/services/payment_requests/payments/cashfree_service.rb @@ -205,7 +205,7 @@ def create_payment(cashfree_payment) def deliver_error_webhook(cashfree_error) DeliverErrorWebhookService.call_async(payable, { - provider_customer_id: customer.cashfree_customer.provider_customer_id, + provider_customer_id: customer.cashfree_customer.id, provider_error: { message: cashfree_error.error_body, error_code: cashfree_error.error_code diff --git a/schema.json b/schema.json index 411d1af7da8..a9579ffe320 100644 --- a/schema.json +++ b/schema.json @@ -2523,9 +2523,7 @@ "kind": "OBJECT", "name": "CashfreeProvider", "description": null, - "interfaces": [ - - ], + "interfaces": [], "possibleTypes": null, "fields": [ { @@ -2538,9 +2536,7 @@ }, "isDeprecated": false, "deprecationReason": null, - "args": [ - - ] + "args": [] }, { "name": "clientSecret", @@ -2552,9 +2548,7 @@ }, "isDeprecated": false, "deprecationReason": null, - "args": [ - - ] + "args": [] }, { "name": "code", @@ -2570,9 +2564,7 @@ }, "isDeprecated": false, "deprecationReason": null, - "args": [ - - ] + "args": [] }, { "name": "id", @@ -2588,9 +2580,7 @@ }, "isDeprecated": false, "deprecationReason": null, - "args": [ - - ] + "args": [] }, { "name": "name", @@ -2606,9 +2596,7 @@ }, "isDeprecated": false, "deprecationReason": null, - "args": [ - - ] + "args": [] }, { "name": "successRedirectUrl", @@ -2620,9 +2608,7 @@ }, "isDeprecated": false, "deprecationReason": null, - "args": [ - - ] + "args": [] } ], "inputFields": null, @@ -11856,9 +11842,7 @@ }, "isDeprecated": false, "deprecationReason": null, - "args": [ - - ] + "args": [] }, { "name": "city", diff --git a/spec/services/invoices/payments/cashfree_service_spec.rb b/spec/services/invoices/payments/cashfree_service_spec.rb index 8a8624a83da..07c45ef7cc4 100644 --- a/spec/services/invoices/payments/cashfree_service_spec.rb +++ b/spec/services/invoices/payments/cashfree_service_spec.rb @@ -24,82 +24,6 @@ ) end - describe ".call" do - before do - cashfree_payment_provider - cashfree_customer - - allow(Invoices::PrepaidCreditJob).to receive(:perform_later) - end - - it "creates a cashfree payment", aggregate_failure: true do - result = cashfree_service.call - - expect(result).to be_success - - expect(result.invoice).to be_payment_pending - expect(result.invoice.payment_attempts).to eq(1) - expect(result.invoice.reload.ready_for_payment_processing).to eq(true) - - expect(result.payment.id).to be_present - expect(result.payment.payable).to eq(invoice) - expect(result.payment.payment_provider).to eq(cashfree_payment_provider) - expect(result.payment.payment_provider_customer).to eq(cashfree_customer) - expect(result.payment.amount_cents).to eq(invoice.total_amount_cents) - expect(result.payment.amount_currency).to eq(invoice.currency) - expect(result.payment.status).to eq("pending") - end - - it_behaves_like "syncs payment" do - let(:service_call) { cashfree_service.call } - end - - context "with no payment provider" do - let(:cashfree_payment_provider) { nil } - - it "does not creates a payment", aggregate_failure: true do - result = cashfree_service.call - - expect(result).to be_success - expect(result.invoice).to eq(invoice) - expect(result.payment).to be_nil - end - end - - context "with 0 amount" do - let(:invoice) do - create( - :invoice, - organization:, - customer:, - total_amount_cents: 0, - currency: "EUR" - ) - end - - it "does not creates a payment", aggregate_failure: true do - result = cashfree_service.call - - expect(result).to be_success - expect(result.invoice).to eq(invoice) - expect(result.payment).to be_nil - expect(result.invoice).to be_payment_succeeded - end - end - - context "when customer does not exists" do - let(:cashfree_customer) { nil } - - it "does not creates a adyen payment", aggregate_failure: true do - result = cashfree_service.call - - expect(result).to be_success - expect(result.invoice).to eq(invoice) - expect(result.payment).to be_nil - end - end - end - describe ".update_payment_status" do let(:payment) do create( diff --git a/spec/services/payment_providers/cashfree/payments/create_service_spec.rb b/spec/services/payment_providers/cashfree/payments/create_service_spec.rb new file mode 100644 index 00000000000..aad4123748c --- /dev/null +++ b/spec/services/payment_providers/cashfree/payments/create_service_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe PaymentProviders::Cashfree::Payments::CreateService, type: :service do + subject(:create_service) { described_class.new(payment:) } + + let(:customer) { create(:customer, payment_provider_code: code) } + let(:organization) { customer.organization } + let(:chasfree_payment_provider) { create(:cashfree_provider, organization:, code:) } + let(:cashfree_customer) { create(:cashfree_customer, customer:, payment_provider: chasfree_payment_provider) } + let(:code) { "stripe_1" } + + let(:invoice) do + create( + :invoice, + organization:, + customer:, + total_amount_cents: 200, + currency: "EUR", + ready_for_payment_processing: true + ) + end + + let(:payment) do + create( + :payment, + payable: invoice, + status: "pending", + payable_payment_status: "pending", + payment_provider: chasfree_payment_provider, + payment_provider_customer: cashfree_customer, + amount_cents: invoice.total_amount_cents, + amount_currency: invoice.currency + ) + end + + describe ".call" do + before do + chasfree_payment_provider + cashfree_customer + end + + it "returns the payment and keeps it pending" do + result = create_service.call + + expect(result).to be_success + + expect(result.payment.id).to be_present + expect(result.payment.payable).to eq(invoice) + expect(result.payment.payment_provider).to eq(chasfree_payment_provider) + expect(result.payment.payment_provider_customer).to eq(cashfree_customer) + expect(result.payment.amount_cents).to eq(invoice.total_amount_cents) + expect(result.payment.amount_currency).to eq(invoice.currency) + expect(result.payment.status).to eq("pending") + expect(result.payment.payable_payment_status).to eq("pending") + end + end +end