diff --git a/lib/transaction.rb b/lib/transaction.rb index 83e8e158ce158eaa3ccae3fb1dddf0a6de113290..ff8ce7bd5e2bafe2464ec8ceab1e35bab629f8c8 100644 --- a/lib/transaction.rb +++ b/lib/transaction.rb @@ -18,10 +18,12 @@ class Transaction def self.resolve_payment_method(customer, payment_method) EMPromise.all([ + REDIS.exists("jmp_customer_credit_card_lock-#{customer.customer_id}"), customer.declines, payment_method || customer.payment_methods.then(&:default_payment_method) - ]).then do |(declines, selected_method)| + ]).then do |(lock, declines, selected_method)| raise "Declined" if declines >= 2 + raise "Too many payments recently" if lock == 1 raise "No valid payment method on file" unless selected_method selected_method @@ -29,7 +31,14 @@ class Transaction end def self.decline_guard(customer, response) - return response.transaction if response.success? + if response.success? + REDIS.setex( + "jmp_customer_credit_card_lock-#{customer.customer_id}", + 60 * 60 * 24, + "1" + ) + return response.transaction + end customer.mark_decline raise response.message diff --git a/test/test_transaction.rb b/test/test_transaction.rb index 5bb348dd711ad245fa489364f3e3caad42535ab9..e6a02c642b05645ecfdd04b543e75d2ed6ee3751 100644 --- a/test/test_transaction.rb +++ b/test/test_transaction.rb @@ -18,6 +18,11 @@ class TransactionTest < Minitest::Test ) def test_sale_fails + Transaction::REDIS.expect( + :exists, + EMPromise.resolve(0), + ["jmp_customer_credit_card_lock-test"] + ) CustomerFinancials::REDIS.expect( :get, EMPromise.resolve("1"), @@ -50,10 +55,39 @@ class TransactionTest < Minitest::Test ).sync end assert_mock CustomerFinancials::REDIS + assert_mock Transaction::REDIS end em :test_sale_fails + def test_sale_locked + Transaction::REDIS.expect( + :exists, + EMPromise.resolve(1), + ["jmp_customer_credit_card_lock-test"] + ) + CustomerFinancials::REDIS.expect( + :get, + EMPromise.resolve("0"), + ["jmp_pay_decline-test"] + ) + assert_raises("locked") do + Transaction.sale( + customer(plan_name: "test_usd"), + amount: 123, + payment_method: OpenStruct.new(token: "token") + ).sync + end + assert_mock CustomerFinancials::REDIS + assert_mock Transaction::REDIS + end + em :test_sale_locked + def test_sale + Transaction::REDIS.expect( + :exists, + EMPromise.resolve(0), + ["jmp_customer_credit_card_lock-test"] + ) CustomerFinancials::REDIS.expect( :get, EMPromise.resolve("1"), @@ -76,6 +110,11 @@ class TransactionTest < Minitest::Test options: { submit_for_settlement: true } }] ) + Transaction::REDIS.expect( + :setex, + EMPromise.resolve(1), + ["jmp_customer_credit_card_lock-test", 86400, "1"] + ) result = Transaction.sale( customer(plan_name: "test_usd"), amount: 123, @@ -83,6 +122,7 @@ class TransactionTest < Minitest::Test ).sync assert_kind_of Transaction, result assert_mock CustomerFinancials::REDIS + assert_mock Transaction::REDIS end em :test_sale