From 72b443688bca16f08858bcb13f6fbc24dd9efeab Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Wed, 13 Apr 2022 14:23:17 -0500 Subject: [PATCH] Credit card blacklist Any card on the list is just treated as though it is not present, preventing it from being used. --- lib/customer_finacials.rb | 12 +++++---- lib/payment_methods.rb | 6 +++-- lib/transaction.rb | 38 +++++++++++++--------------- test/test_buy_account_credit_form.rb | 4 ++- test/test_payment_methods.rb | 28 +++++++++++++++++--- test/test_registration.rb | 1 + 6 files changed, 57 insertions(+), 32 deletions(-) diff --git a/lib/customer_finacials.rb b/lib/customer_finacials.rb index 924030c..07c33ea 100644 --- a/lib/customer_finacials.rb +++ b/lib/customer_finacials.rb @@ -6,11 +6,13 @@ class CustomerFinancials end def payment_methods - BRAINTREE - .customer - .find(@customer_id) - .catch { OpenStruct.new(payment_methods: []) } - .then(PaymentMethods.method(:for_braintree_customer)) + EMPromise.all([ + BRAINTREE + .customer + .find(@customer_id) + .catch { OpenStruct.new(payment_methods: []) }, + REDIS.smembers("block_credit_cards") + ]).then { |(braintree, badcards)| PaymentMethods.for(braintree, badcards) } end def btc_addresses diff --git a/lib/payment_methods.rb b/lib/payment_methods.rb index d8799fd..2bbf08a 100644 --- a/lib/payment_methods.rb +++ b/lib/payment_methods.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true class PaymentMethods - def self.for_braintree_customer(braintree_customer) - methods = braintree_customer.payment_methods + def self.for(braintree_customer, badcards) + methods = braintree_customer.payment_methods.reject { |m| + badcards.include?(m.unique_number_identifier) + } if methods.empty? Empty.new else diff --git a/lib/transaction.rb b/lib/transaction.rb index 2ad52ab..83e8e15 100644 --- a/lib/transaction.rb +++ b/lib/transaction.rb @@ -4,39 +4,37 @@ require "bigdecimal" class Transaction def self.sale(customer, amount:, payment_method: nil) - customer.declines.then do |declines| - raise "too many declines" if declines >= 2 - + resolve_payment_method(customer, payment_method).then do |selected_method| BRAINTREE.transaction.sale( amount: amount, - **sale_args_for(customer, payment_method) + merchant_account_id: customer.merchant_account, + options: { submit_for_settlement: true }, + payment_method_token: selected_method.token ).then do |response| - decline_guard(customer, response) - new(response.transaction) + new(decline_guard(customer, response)) end end end + def self.resolve_payment_method(customer, payment_method) + EMPromise.all([ + customer.declines, + payment_method || customer.payment_methods.then(&:default_payment_method) + ]).then do |(declines, selected_method)| + raise "Declined" if declines >= 2 + raise "No valid payment method on file" unless selected_method + + selected_method + end + end + def self.decline_guard(customer, response) - return if response.success? + return response.transaction if response.success? customer.mark_decline raise response.message end - def self.sale_args_for(customer, payment_method=nil) - { - merchant_account_id: customer.merchant_account, - options: { submit_for_settlement: true } - }.merge( - if payment_method - { payment_method_token: payment_method.token } - else - { customer_id: customer.customer_id } - end - ) - end - attr_reader :amount def initialize(braintree_transaction) diff --git a/test/test_buy_account_credit_form.rb b/test/test_buy_account_credit_form.rb index 0c53008..4b052ef 100644 --- a/test/test_buy_account_credit_form.rb +++ b/test/test_buy_account_credit_form.rb @@ -4,7 +4,8 @@ require "test_helper" require "buy_account_credit_form" require "customer" -Customer::BRAINTREE = Minitest::Mock.new +CustomerFinancials::BRAINTREE = Minitest::Mock.new +CustomerFinancials::REDIS = Minitest::Mock.new class BuyAccountCreditFormTest < Minitest::Test def setup @@ -18,6 +19,7 @@ class BuyAccountCreditFormTest < Minitest::Test def test_for braintree_customer = Minitest::Mock.new CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer) + CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"]) braintree_customer.expect( :find, EMPromise.resolve(OpenStruct.new(payment_methods: [])), diff --git a/test/test_payment_methods.rb b/test/test_payment_methods.rb index 763321d..0971e7b 100644 --- a/test/test_payment_methods.rb +++ b/test/test_payment_methods.rb @@ -4,22 +4,42 @@ require "test_helper" require "payment_methods" class PaymentMethodsTest < Minitest::Test - def test_for_braintree_customer + def test_for braintree_customer = Minitest::Mock.new braintree_customer.expect(:payment_methods, [ OpenStruct.new(card_type: "Test", last_4: "1234") ]) - methods = PaymentMethods.for_braintree_customer(braintree_customer) + methods = PaymentMethods.for(braintree_customer, []) assert_kind_of PaymentMethods, methods + assert_equal 1, methods.to_a.length + refute methods.empty? end - def test_for_braintree_customer_no_methods + def test_for_badcards + braintree_customer = Minitest::Mock.new + braintree_customer.expect(:payment_methods, [ + OpenStruct.new( + card_type: "Test", + last_4: "1234", + unique_number_identifier: "wut" + ) + ]) + methods = PaymentMethods.for(braintree_customer, ["wut"]) + assert_kind_of PaymentMethods, methods + assert_equal 0, methods.to_a.length + assert methods.empty? + end + + def test_for_no_methods braintree_customer = Minitest::Mock.new braintree_customer.expect(:payment_methods, []) - methods = PaymentMethods.for_braintree_customer(braintree_customer) + methods = PaymentMethods.for(braintree_customer, []) + assert_kind_of PaymentMethods, methods assert_raises do methods.to_list_single end + assert_equal 0, methods.to_a.length + assert methods.empty? end def test_default_payment_method diff --git a/test/test_registration.rb b/test/test_registration.rb index 190daeb..fb68154 100644 --- a/test/test_registration.rb +++ b/test/test_registration.rb @@ -266,6 +266,7 @@ class RegistrationTest < Minitest::Test :customer, braintree_customer ) + CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"]) braintree_customer.expect( :find, EMPromise.resolve(OpenStruct.new(payment_methods: [])), -- 2.38.5