From 4427fdffcfa8c48ea15d10e20fa479e82986b831 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Sun, 5 Dec 2021 22:45:51 -0500 Subject: [PATCH] Removed web activation form No longer used for either registrations or as a hack for payments, everything handled by ad-hoc commands now and nothing links here any longer. --- config.ru | 158 -------------------------------------------- lib/transaction.rb | 75 --------------------- views/activate.slim | 95 -------------------------- 3 files changed, 328 deletions(-) delete mode 100644 lib/transaction.rb delete mode 100644 views/activate.slim diff --git a/config.ru b/config.ru index da5b85f..b5de9c7 100644 --- a/config.ru +++ b/config.ru @@ -25,7 +25,6 @@ end use Sentry::Rack::CaptureExceptions REDIS = Redis.new -PLANS = Dhall.load("env:PLANS").sync BRAINTREE_CONFIG = Dhall.load("env:BRAINTREE_CONFIG").sync ELECTRUM = Electrum.new( **Dhall::Coder.load("env:ELECTRUM_CONFIG", transform_keys: :to_sym) @@ -35,84 +34,6 @@ DB = PG.connect(dbname: "jmp") DB.type_map_for_results = PG::BasicTypeMapForResults.new(DB) DB.type_map_for_queries = PG::BasicTypeMapForQueries.new(DB) -class Plan - def self.for(plan_name) - new(PLANS.find { |p| p[:name].to_s == plan_name }) - end - - def initialize(plan) - @plan = plan - end - - def price(months=1) - (BigDecimal(@plan[:monthly_price].to_i) * months) / 10000 - end - - def currency - @plan[:currency].to_s.to_sym - end - - def merchant_account - BRAINTREE_CONFIG[:merchant_accounts][currency] - end - - def self.active?(customer_id) - DB.exec_params(<<~SQL, [customer_id]).first&.[]("count").to_i.positive? - SELECT count(1) AS count FROM customer_plans - WHERE customer_id=$1 AND expires_at > NOW() - SQL - end - - def bill_plan(customer_id) - DB.transaction do - charge_for_plan(customer_id) - unless activate_plan_starting_now(customer_id) - add_one_month_to_current_plan(customer_id) - end - end - true - end - - def activate_plan_starting_now(customer_id) - DB.exec(<<~SQL, [customer_id, @plan[:name]]).cmd_tuples.positive? - INSERT INTO plan_log - (customer_id, plan_name, date_range) - VALUES ($1, $2, tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + '1 month')) - ON CONFLICT DO NOTHING - SQL - end - -protected - - def charge_for_plan(customer_id) - params = [ - customer_id, - "#{customer_id}-bill-#{@plan[:name]}-at-#{Time.now.to_i}", - -price - ] - DB.exec(<<~SQL, params) - INSERT INTO transactions - (customer_id, transaction_id, created_at, amount) - VALUES ($1, $2, LOCALTIMESTAMP, $3) - SQL - end - - def add_one_month_to_current_plan(customer_id) - DB.exec(<<~SQL, [customer_id]) - UPDATE plan_log SET date_range=range_merge( - date_range, - tsrange( - LOCALTIMESTAMP, - GREATEST(upper(date_range), LOCALTIMESTAMP) + '1 month' - ) - ) - WHERE - customer_id=$1 AND - date_range && tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + '1 month') - SQL - end -end - class CreditCardGateway def initialize(jid, customer_id=nil) @jid = jid @@ -175,38 +96,6 @@ class CreditCardGateway ) end - 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 nil unless decline_guard(ip) - - tx = Transaction.sale(@gateway, **kwargs) - return tx if tx - - 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) - nil - end - - def buy_plan(plan_name, nonce, ip) - plan = Plan.for(plan_name) - sale( - ip: ip, - amount: plan.price(5), - payment_method_nonce: nonce, - merchant_account_id: plan.merchant_account, - options: { submit_for_settlement: true } - )&.insert && plan.bill_plan(@customer_id) - end - protected def redis_key_jid @@ -307,53 +196,6 @@ class JmpPay < Roda gateway = CreditCardGateway.new(jid, params["customer_id"]) topup = "jmp_customer_auto_top_up_amount-#{gateway.customer_id}" - r.on "activate" do - Sentry.configure_scope do |scope| - scope.set_transaction_name("activate") - scope.set_context( - "activate", - plan_name: params["plan_name"] - ) - end - - render = lambda do |l={}| - view( - "activate", - locals: { - token: gateway.client_token, - customer_id: gateway.customer_id, - error: false - }.merge(l) - ) - end - - r.get do - if Plan.active?(gateway.customer_id) - r.redirect params["return_to"], 303 - else - render.call - end - end - - r.post do - result = DB.transaction { - Plan.active?(gateway.customer_id) || gateway.buy_plan( - params["plan_name"], - params["braintree_nonce"], - request.ip - ) - } - if params["auto_top_up_amount"].to_i >= 15 - REDIS.set(topup, params["auto_top_up_amount"].to_i) - end - if result - r.redirect params["return_to"], 303 - else - render.call(error: true) - end - end - end - r.on "credit_cards" do r.get do view( diff --git a/lib/transaction.rb b/lib/transaction.rb deleted file mode 100644 index f8762d8..0000000 --- a/lib/transaction.rb +++ /dev/null @@ -1,75 +0,0 @@ -# frozen_string_literal: true - -require "bigdecimal" - -# Largely copied from sgx-jmp to support web activation more properly -# Goes away when web activation goes away -class Transaction - def self.sale(gateway, **kwargs) - response = gateway.transaction.sale(**kwargs) - response.success? ? new(response.transaction) : nil - end - - attr_reader :amount - - def initialize(braintree_transaction) - @customer_id = braintree_transaction.customer_details.id - @transaction_id = braintree_transaction.id - @created_at = braintree_transaction.created_at - @amount = BigDecimal(braintree_transaction.amount, 4) - end - - def insert - DB.transaction do - insert_tx - insert_bonus - end - true - end - - def bonus - return BigDecimal(0) if amount <= 15 - - amount * - case amount - when (15..29.99) - 0.01 - when (30..139.99) - 0.03 - else - 0.05 - end - end - - def to_s - plus = " + #{'%.4f' % bonus} bonus" - "$#{'%.2f' % amount}#{plus if bonus.positive?}" - end - -protected - - def insert_tx - params = [@customer_id, @transaction_id, @created_at, @amount] - DB.exec(<<~SQL, params) - INSERT INTO transactions - (customer_id, transaction_id, created_at, amount, note) - VALUES - ($1, $2, $3, $4, 'Credit card payment') - SQL - end - - def insert_bonus - return if bonus <= 0 - - params = [ - @customer_id, "bonus_for_#{@transaction_id}", - @created_at, bonus - ] - DB.exec(<<~SQL, params) - INSERT INTO transactions - (customer_id, transaction_id, created_at, amount, note) - VALUES - ($1, $2, $3, $4, 'Credit card payment bonus') - SQL - end -end diff --git a/views/activate.slim b/views/activate.slim deleted file mode 100644 index e3162df..0000000 --- a/views/activate.slim +++ /dev/null @@ -1,95 +0,0 @@ -scss: - html, body { - font-family: sans-serif; - text-align: center; - } - - form { - margin: auto; - max-width: 40em; - - fieldset { - max-width: 25em; - margin: 2em auto; - label { display: block; } - input[type=number] { max-width: 3em; } - small { display: block; } - } - - button { - display: block; - width: 10em; - margin: auto; - } - - } - - .error { - color: red; - max-width: 40em; - margin: 1em auto; - } - -h1 Activate New Account - -- if error - p.error - ' 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. - p.error - ' If you were trying a prepaid card, you may wish to use - a href="https://privacy.com/" Privacy.com - | instead, as they do support international transactions. - -form method="post" action="" - #braintree - | Unfortunately, our credit card processor requires JavaScript. - - fieldset - legend Pay for 5 months of service - label - ' $14.95 USD - input type="radio" name="plan_name" value="usd_beta_unlimited-v20210223" required="required" - label - ' $17.95 CAD - input type="radio" name="plan_name" value="cad_beta_unlimited-v20210223" required="required" - - fieldset - legend Auto top-up when account balance is low? - label - | When balance drops below $5, add $ - input type="number" name="auto_top_up_amount" min="15" value="15" - small Leave blank for no auto top-up. - - input type="hidden" name="customer_id" value=customer_id - input type="hidden" name="braintree_nonce" - -script src="https://js.braintreegateway.com/web/dropin/1.26.0/js/dropin.min.js" -javascript: - document.querySelector("#braintree").innerHTML = ""; - - var button = document.createElement("button"); - button.innerHTML = "Pay Now"; - document.querySelector("form").appendChild(button); - braintree.dropin.create({ - authorization: #{{token.to_json}}, - container: "#braintree", - vaultManager: false - }, function (createErr, instance) { - if(createErr) console.log(createErr); - - document.querySelector("form").addEventListener("submit", function(e) { - e.preventDefault(); - - instance.requestPaymentMethod(function(err, payload) { - if(err) { - console.log(err); - } else { - e.target.braintree_nonce.value = payload.nonce; - e.target.submit(); - } - }); - }); - }); -- 2.38.5