1# frozen_string_literal: true
2
3require "braintree"
4require "delegate"
5require "dhall"
6require "redis"
7require "roda"
8
9REDIS = Redis.new
10BRAINTREE_CONFIG = Dhall.load("env:BRAINTREE_CONFIG").sync
11
12class CreditCardGateway
13 def initialize(jid, customer_id=nil)
14 @jid = jid
15 @customer_id = customer_id
16
17 @gateway = Braintree::Gateway.new(
18 environment: BRAINTREE_CONFIG[:environment].to_s,
19 merchant_id: BRAINTREE_CONFIG[:merchant_id].to_s,
20 public_key: BRAINTREE_CONFIG[:public_key].to_s,
21 private_key: BRAINTREE_CONFIG[:private_key].to_s
22 )
23 end
24
25 def check_customer_id(cid)
26 return cid unless ENV["RACK_ENV"] == "production"
27
28 raise "customer_id does not match" unless @customer_id == cid
29
30 cid
31 end
32
33 def customer_id
34 customer_id = REDIS.get(redis_key)
35 return customer_id if check_customer_id(customer_id)
36
37 cresult = @gateway.customer.create
38 raise "Braintree customer create failed" unless cresult.success?
39
40 result = REDIS.set(redis_key, cresult.customer.id)
41 raise "Saving new customer to redis failed" unless result == "OK"
42
43 cresult.customer.id
44 end
45
46 def client_token
47 @gateway.client_token.generate(customer_id: customer_id)
48 end
49
50 def default_payment_method=(nonce)
51 @gateway.payment_method.create(
52 customer_id: customer_id,
53 payment_method_nonce: nonce,
54 options: {
55 make_default: true
56 }
57 )
58 end
59
60protected
61
62 def redis_key
63 "jmp_customer_id-#{@jid}"
64 end
65end
66
67class JmpPay < Roda
68 plugin :render, engine: "slim"
69 plugin :common_logger, $stdout
70
71 route do |r|
72 r.on :jid do |jid|
73 r.on "credit_cards" do
74 gateway = CreditCardGateway.new(
75 jid,
76 request.params["customer_id"]
77 )
78
79 r.get do
80 view(
81 "credit_cards",
82 locals: {
83 token: gateway.client_token,
84 customer_id: gateway.customer_id
85 }
86 )
87 end
88
89 r.post do
90 gateway.default_payment_method = request.params["braintree_nonce"]
91 "OK"
92 end
93 end
94 end
95 end
96end
97
98run JmpPay.freeze.app