~singpolyma/jmp-pay

810b55cf61b3d1764da885cdb4ed49ed0fe1f3a2 — Stephen Paul Weber 5 days ago 9a50e2d master
Block users who get too many card declines

If a customer has > 2 card declines in 24 hours or an ip has > 4, then treat all
attempts as declines without looking as an anti-fraud measure.
1 files changed, 27 insertions(+), 7 deletions(-)

M config.ru
M config.ru => config.ru +27 -7
@@ 65,6 65,7 @@ class Plan
			"INSERT INTO plan_log VALUES ($1, $2, $3, $4)",
			[customer_id, @plan[:name], Time.now, Date.today >> months]
		)
		true
	end
end



@@ 125,17 126,35 @@ class CreditCardGateway
		)
	end

	def buy_plan(plan_name, months, nonce)
	def decline_guard(ip)
		customer_declines, ip_declines = REDIS.mget(
			"jmp_pay_decline-#{@customer_id}",
			"jmp_pay_decline-#{ip}"
		)
		customer_declines.to_i < 2 && ip_declines.to_i < 4
	end

	def sale(ip:, **kwargs)
		return false unless decline_guard(ip)
		result = @gateway.transaction.sale(**kwargs)
		return true if result.success?

		REDIS.incr("jmp_pay_decline-#{@customer_id}")
		REDIS.expire("jmp_pay_decline-#{@customer_id}", 60 * 60 * 24)
		REDIS.incr("jmp_pay_decline-#{ip}")
		REDIS.expire("jmp_pay_decline-#{ip}", 60 * 60 * 24)
		false
	end

	def buy_plan(plan_name, months, nonce, ip)
		plan = Plan.for(plan_name)
		result = @gateway.transaction.sale(
		sale(
			ip: ip,
			amount: plan.price(months),
			payment_method_nonce: nonce,
			merchant_account_id: plan.merchant_account,
			options: {submit_for_settlement: true}
		)
		return false unless result.success?
		plan.activate(@customer_id, months)
		true
		) && plan.activate(@customer_id, months)
	end

protected


@@ 251,7 270,8 @@ class JmpPay < Roda
						Plan.active?(gateway.customer_id) || gateway.buy_plan(
							request.params["plan_name"],
							5,
							request.params["braintree_nonce"]
							request.params["braintree_nonce"],
							request.ip
						)
					end
					if result