~singpolyma/jmp-pay

2c77b1d6aa844742ee43a4354fa91b9e1d875005 — Stephen Paul Weber 3 years ago 7c438f8
Notify customer on sucessful BTC deposit

Since BTC transactions can take some time, let the user know when it is done and
how much credit they got for their money.
1 files changed, 53 insertions(+), 9 deletions(-)

M bin/process_pending_btc_transactions
M bin/process_pending_btc_transactions => bin/process_pending_btc_transactions +53 -9
@@ 4,6 4,11 @@
# Usage: bin/process_pending-btc_transactions '{
#        oxr_app_id = "",
#        required_confirmations = 3,
#        notify_using = {
#          jid = "",
#          password = "",
#          target = \(tel: Text) -> "${tel}@cheogram.com"
#        },
#        electrum = env:ELECTRUM_CONFIG,
#        plans = ./plans.dhall
#        }'


@@ 16,11 21,12 @@ require "nokogiri"
require "pg"
require "redis"

require_relative "../lib/blather_notify"
require_relative "../lib/electrum"

CONFIG =
	Dhall::Coder
	.new(safe: Dhall::Coder::JSON_LIKE + [Symbol])
	.new(safe: Dhall::Coder::JSON_LIKE + [Symbol, Proc])
	.load(ARGV[0], transform_keys: :to_sym)

REDIS = Redis.new


@@ 30,6 36,11 @@ DB = PG.connect(dbname: "jmp")
DB.type_map_for_results = PG::BasicTypeMapForResults.new(DB)
DB.type_map_for_queries = PG::BasicTypeMapForQueries.new(DB)

BlatherNotify.start(
	CONFIG[:notify_using][:jid],
	CONFIG[:notify_using][:password]
)

unless (cad_to_usd = REDIS.get("cad_to_usd")&.to_f)
	oxr = Money::Bank::OpenExchangeRatesBank.new(Money::RatesStore::Memory.new)
	oxr.app_id = CONFIG.fetch(:oxr_app_id)


@@ 70,6 81,44 @@ class Plan
	end
end

class Customer
	def initialize(customer_id)
		@customer_id = customer_id
	end

	def notify(body)
		jid = REDIS.get("jmp_customer_jid-#{@customer_id}")
		tel = REDIS.lindex("catapult_cred-#{jid}", 3)
		BlatherNotify.say(
			CONFIG[:notify_using][:target].call(tel.to_s),
			body
		)
	end

	def plan
		Plan.for_customer(@customer_id)
	end

	def add_btc_credit(txid, fiat_amount)
		DB.exec_params(<<-SQL, [@customer_id, txid, fiat_amount])
			INSERT INTO transactions
				(customer_id, transaction_id, amount, note)
			VALUES
					($1, $2, $3, 'Bitcoin payment')
			ON CONFLICT (transaction_id) DO NOTHING
		SQL
		notify_btc_credit(txid, fiat_amount)
	end

	def notify_btc_credit(txid, fiat_amount)
		tx_hash, = txid.split("/", 2)
		notify(
			"Your Bitcoin transaction has been added as $#{'%.4f' % fiat_amount} " \
			"to your account.\n(txhash: #{tx_hash})"
		)
	end
end

REDIS.hgetall("pending_btc_transactions").each do |(txid, customer_id)|
	tx_hash, address = txid.split("/", 2)
	transaction = ELECTRUM.gettransaction(tx_hash)


@@ 80,16 129,11 @@ REDIS.hgetall("pending_btc_transactions").each do |(txid, customer_id)|
		next
	end
	DB.transaction do
		plan = Plan.for_customer(customer_id)
		customer = Customer.new(customer_id)
		plan = customer.plan
		if plan
			amount = btc * btc_sell_price.fetch(plan.currency).round(4, :floor)
			DB.exec_params(<<-SQL, [customer_id, txid, amount])
				INSERT INTO transactions
					(customer_id, transaction_id, amount, note)
				VALUES
						($1, $2, $3, 'Bitcoin payment')
				ON CONFLICT (transaction_id) DO NOTHING
			SQL
			customer.add_btc_credit(txid, amount)
		else
			warn "No plan for #{customer_id} cannot save #{txid}"
		end