~singpolyma/sgx-jmp

36f441c031a5318385ec78d7d2e021a8e2fab186 — Stephen Paul Weber 7 months ago 3b0ae3c + bb9f4f1
Merge branch 'three_d_secure'

* three_d_secure:
  Send 3DS id when making a transaction
M lib/customer_finacials.rb => lib/customer_finacials.rb +11 -2
@@ 11,8 11,11 @@ class CustomerFinancials
				.customer
				.find(@customer_id)
				.catch { OpenStruct.new(payment_methods: []) },
			REDIS.smembers("block_credit_cards")
		]).then { |(braintree, badcards)| PaymentMethods.for(braintree, badcards) }
			REDIS.smembers("block_credit_cards"),
			three_d_secure
		]).then do |(braintree, badcards, three_d)|
			PaymentMethods.for(braintree, badcards, three_d)
		end
	end

	def btc_addresses


@@ 42,6 45,12 @@ class CustomerFinancials
		end
	end

	def three_d_secure
		REDIS.hgetall(
			"jmp_customer_three_d_secure_authentication_id-#{@customer_id}"
		).then { |all| Hash[*all] }
	end

	class TransactionInfo
		value_semantics do
			transaction_id String

A lib/payment_method.rb => lib/payment_method.rb +29 -0
@@ 0,0 1,29 @@
# frozen_string_literal: true

require "delegate"

class PaymentMethod < SimpleDelegator
	def self.for(method, three_d_secure={})
		three_d = three_d_secure[method.token]
		return ThreeDSecure.new(method, three_d) if three_d

		new(method)
	end

	def transaction_details
		{
			payment_method_token: token
		}
	end

	class ThreeDSecure < PaymentMethod
		def initialize(method, three_d)
			super(method)
			@three_d = three_d
		end

		def transaction_details
			super.merge(three_d_secure_authentication_id: @three_d)
		end
	end
end

M lib/payment_methods.rb => lib/payment_methods.rb +4 -2
@@ 1,14 1,16 @@
# frozen_string_literal: true

require_relative "payment_method"

class PaymentMethods
	def self.for(braintree_customer, badcards)
	def self.for(braintree_customer, badcards, three_d_secure)
		methods = braintree_customer.payment_methods.reject { |m|
			badcards.include?(m.unique_number_identifier)
		}
		if methods.empty?
			Empty.new
		else
			new(methods)
			new(methods.map { |m| PaymentMethod.for(m, three_d_secure) })
		end
	end


M lib/transaction.rb => lib/transaction.rb +3 -4
@@ 5,12 5,11 @@ require "bigdecimal"
class Transaction
	def self.sale(customer, amount:, payment_method: nil)
		resolve_payment_method(customer, payment_method).then do |selected_method|
			BRAINTREE.transaction.sale(
			BRAINTREE.transaction.sale(selected_method.transaction_details.merge(
				amount: amount,
				merchant_account_id: customer.merchant_account,
				options: { submit_for_settlement: true },
				payment_method_token: selected_method.token
			).then do |response|
				options: { submit_for_settlement: true }
			)).then do |response|
				new(decline_guard(customer, response))
			end
		end

M test/test_buy_account_credit_form.rb => test/test_buy_account_credit_form.rb +3 -0
@@ 20,6 20,9 @@ class BuyAccountCreditFormTest < Minitest::Test
		braintree_customer = Minitest::Mock.new
		CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer)
		CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"])
		CustomerFinancials::REDIS.expect(
			:hgetall, [], ["jmp_customer_three_d_secure_authentication_id-test"]
		)
		braintree_customer.expect(
			:find,
			EMPromise.resolve(OpenStruct.new(payment_methods: [])),

M test/test_payment_methods.rb => test/test_payment_methods.rb +25 -4
@@ 7,12 7,16 @@ class PaymentMethodsTest < Minitest::Test
	def test_for
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [
			OpenStruct.new(card_type: "Test", last_4: "1234")
			OpenStruct.new(card_type: "Test", last_4: "1234", token: "wut")
		])
		methods = PaymentMethods.for(braintree_customer, [])
		methods = PaymentMethods.for(braintree_customer, [], {})
		assert_kind_of PaymentMethods, methods
		assert_equal 1, methods.to_a.length
		refute methods.empty?
		assert_equal(
			{ payment_method_token: "wut" },
			methods.fetch(0).transaction_details
		)
	end

	def test_for_badcards


@@ 24,16 28,33 @@ class PaymentMethodsTest < Minitest::Test
				unique_number_identifier: "wut"
			)
		])
		methods = PaymentMethods.for(braintree_customer, ["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_three_d_secure
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [
			OpenStruct.new(
				card_type: "Test",
				last_4: "1234",
				token: "wut"
			)
		])
		methods = PaymentMethods.for(braintree_customer, [], { "wut" => "hai" })
		assert_kind_of PaymentMethods, methods
		assert_equal(
			{ payment_method_token: "wut", three_d_secure_authentication_id: "hai" },
			methods.fetch(0).transaction_details
		)
	end

	def test_for_no_methods
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [])
		methods = PaymentMethods.for(braintree_customer, [])
		methods = PaymentMethods.for(braintree_customer, [], {})
		assert_kind_of PaymentMethods, methods
		assert_raises do
			methods.to_list_single

M test/test_registration.rb => test/test_registration.rb +3 -0
@@ 267,6 267,9 @@ class RegistrationTest < Minitest::Test
				braintree_customer
			)
			CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"])
			CustomerFinancials::REDIS.expect(
				:hgetall, [], ["jmp_customer_three_d_secure_authentication_id-test"]
			)
			braintree_customer.expect(
				:find,
				EMPromise.resolve(OpenStruct.new(payment_methods: [])),

M test/test_transaction.rb => test/test_transaction.rb +3 -2
@@ 3,6 3,7 @@
require "test_helper"
require "customer"
require "transaction"
require "payment_method"

Transaction::DB = Minitest::Mock.new
Transaction::BRAINTREE = Minitest::Mock.new


@@ 46,7 47,7 @@ class TransactionTest < Minitest::Test
			Transaction.sale(
				customer(plan_name: "test_usd"),
				amount: 123,
				payment_method: OpenStruct.new(token: "token")
				payment_method: PaymentMethod.for(OpenStruct.new(token: "token"))
			).sync
		end
		assert_mock CustomerFinancials::REDIS


@@ 79,7 80,7 @@ class TransactionTest < Minitest::Test
		result = Transaction.sale(
			customer(plan_name: "test_usd"),
			amount: 123,
			payment_method: OpenStruct.new(token: "token")
			payment_method: PaymentMethod.for(OpenStruct.new(token: "token"))
		).sync
		assert_kind_of Transaction, result
		assert_mock CustomerFinancials::REDIS