M lib/customer_finacials.rb => lib/customer_finacials.rb +7 -5
@@ 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
M lib/payment_methods.rb => lib/payment_methods.rb +4 -2
@@ 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
M lib/transaction.rb => lib/transaction.rb +18 -20
@@ 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)
M test/test_buy_account_credit_form.rb => test/test_buy_account_credit_form.rb +3 -1
@@ 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: [])),
M test/test_payment_methods.rb => test/test_payment_methods.rb +24 -4
@@ 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
M test/test_registration.rb => test/test_registration.rb +1 -0
@@ 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: [])),