@@ 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