~singpolyma/sgx-jmp

b0094db84b7b6b89a4d98a1d86f634dba8961792 — Stephen Paul Weber 3 years ago 221f4dc
Handle credit card decline

Show user error on decline and give the chance to pick another card.
3 files changed, 90 insertions(+), 3 deletions(-)

M lib/registration.rb
M test/test_helper.rb
M test/test_registration.rb
M lib/registration.rb => lib/registration.rb +42 -1
@@ 222,12 222,53 @@ class Registration
						@customer.merchant_account,
						@payment_method,
						CONFIG[:activation_amount]
					).then(&:insert).then {
					).then(
						method(:sold),
						->(_) { declined }
					)
				end

			protected

				def sold(tx)
					tx.insert.then {
						@customer.bill_plan
					}.then do
						Finish.new(@iq, @customer, @tel).write
					end
				end

				DECLINE_MESSAGE =
					"Your bank declined the transaction. " \
					"Often this happens when a person's credit card " \
					"is a US card that does not support international " \
					"transactions, as JMP is not based in the USA, though " \
					"we do support transactions in USD.\n\n" \
					"If you were trying a prepaid card, you may wish to use "\
					"Privacy.com instead, as they do support international " \
					"transactions.\n\n " \
					"You may add another card and then choose next"

				def decline_oob(reply)
					oob = OOB.find_or_create(reply.command)
					oob.url = CONFIG[:credit_card_url].call(
						reply.to.stripped.to_s,
						@customer.customer_id
					)
					oob.desc = DECLINE_MESSAGE
					oob
				end

				def declined
					reply = @iq.reply
					reply_oob = decline_oob(reply)
					reply.allowed_actions = [:next]
					reply.note_type = :error
					reply.note_text = "#{reply_oob.desc}: #{reply_oob.url}"
					COMMAND_MANAGER.write(reply).then do |riq|
						CreditCard.for(riq, @customer, @tel)
					end
				end
			end
		end
	end

M test/test_helper.rb => test/test_helper.rb +6 -2
@@ 81,8 81,12 @@ class Matching
end

class PromiseMock < Minitest::Mock
	def then
		yield self
	def then(succ=nil, _=nil)
		if succ
			succ.call(self)
		else
			yield self
		end
	end
end


M test/test_registration.rb => test/test_registration.rb +42 -0
@@ 205,6 205,8 @@ class RegistrationTest < Minitest::Test
				Minitest::Mock.new
			Registration::Payment::CreditCard::Activate::Transaction =
				Minitest::Mock.new
			Registration::Payment::CreditCard::Activate::COMMAND_MANAGER =
				Minitest::Mock.new

			def test_write
				transaction = PromiseMock.new


@@ 240,8 242,48 @@ class RegistrationTest < Minitest::Test
				Registration::Payment::CreditCard::Activate::Transaction.verify
				transaction.verify
				customer.verify
				Registration::Payment::CreditCard::Activate::Finish.verify
			end
			em :test_write

			def test_write_declines
				Registration::Payment::CreditCard::Activate::Transaction.expect(
					:sale,
					EMPromise.reject("declined"),
					[
						"merchant_usd",
						:test_default_method,
						CONFIG[:activation_amount]
					]
				)
				iq = Blather::Stanza::Iq::Command.new
				iq.from = "test@example.com"
				customer = Minitest::Mock.new(
					Customer.new("test", plan_name: "test_usd")
				)
				result = Minitest::Mock.new
				result.expect(:then, nil)
				Registration::Payment::CreditCard::Activate::COMMAND_MANAGER.expect(
					:write,
					result,
					[Matching.new do |reply|
						assert_equal :error, reply.note_type
						assert_equal(
							Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE +
							": http://creditcard.example.com",
							reply.note.content
						)
					end]
				)
				Registration::Payment::CreditCard::Activate.new(
					iq,
					customer,
					:test_default_method,
					"+15555550000"
				).write.sync
				Registration::Payment::CreditCard::Activate::Transaction.verify
			end
			em :test_write_declines
		end
	end