Removed web activation form

Stephen Paul Weber created

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.

Change summary

config.ru           | 158 -----------------------------------------------
lib/transaction.rb  |  75 ----------------------
views/activate.slim |  95 ----------------------------
3 files changed, 328 deletions(-)

Detailed changes

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(

lib/transaction.rb 🔗

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

views/activate.slim 🔗

@@ -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();
-				}
-			});
-		});
-	});