stripe_local 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +35 -0
- data/Rakefile +29 -0
- data/app/assets/javascripts/stripe_local/application.js +13 -0
- data/app/assets/javascripts/stripe_local/cards.js +2 -0
- data/app/assets/javascripts/stripe_local/charges.js +2 -0
- data/app/assets/javascripts/stripe_local/coupons.js +2 -0
- data/app/assets/javascripts/stripe_local/customers.js +2 -0
- data/app/assets/javascripts/stripe_local/discounts.js +2 -0
- data/app/assets/javascripts/stripe_local/invoices.js +2 -0
- data/app/assets/javascripts/stripe_local/line_items.js +2 -0
- data/app/assets/javascripts/stripe_local/plans.js +2 -0
- data/app/assets/javascripts/stripe_local/subscriptions.js +2 -0
- data/app/assets/stylesheets/stripe_local/application.css +13 -0
- data/app/assets/stylesheets/stripe_local/cards.css +4 -0
- data/app/assets/stylesheets/stripe_local/charges.css +4 -0
- data/app/assets/stylesheets/stripe_local/coupons.css +4 -0
- data/app/assets/stylesheets/stripe_local/customers.css +4 -0
- data/app/assets/stylesheets/stripe_local/discounts.css +4 -0
- data/app/assets/stylesheets/stripe_local/invoices.css +4 -0
- data/app/assets/stylesheets/stripe_local/line_items.css +4 -0
- data/app/assets/stylesheets/stripe_local/plans.css +4 -0
- data/app/assets/stylesheets/stripe_local/subscriptions.css +4 -0
- data/app/callbacks/stripe_local/plan_sync.rb +33 -0
- data/app/controllers/stripe_local/application_controller.rb +4 -0
- data/app/controllers/stripe_local/cards_controller.rb +6 -0
- data/app/controllers/stripe_local/charges_controller.rb +6 -0
- data/app/controllers/stripe_local/coupons_controller.rb +6 -0
- data/app/controllers/stripe_local/customers_controller.rb +6 -0
- data/app/controllers/stripe_local/discounts_controller.rb +6 -0
- data/app/controllers/stripe_local/invoices_controller.rb +6 -0
- data/app/controllers/stripe_local/line_items_controller.rb +6 -0
- data/app/controllers/stripe_local/plans_controller.rb +6 -0
- data/app/controllers/stripe_local/subscriptions_controller.rb +6 -0
- data/app/controllers/stripe_local/webhooks_controller.rb +13 -0
- data/app/helpers/stripe_local/application_helper.rb +4 -0
- data/app/helpers/stripe_local/cards_helper.rb +4 -0
- data/app/helpers/stripe_local/charges_helper.rb +4 -0
- data/app/helpers/stripe_local/coupons_helper.rb +4 -0
- data/app/helpers/stripe_local/customers_helper.rb +4 -0
- data/app/helpers/stripe_local/discounts_helper.rb +4 -0
- data/app/helpers/stripe_local/invoices_helper.rb +4 -0
- data/app/helpers/stripe_local/line_items_helper.rb +4 -0
- data/app/helpers/stripe_local/plans_helper.rb +4 -0
- data/app/helpers/stripe_local/subscriptions_helper.rb +4 -0
- data/app/mixins/stripe_local/object_adapter.rb +33 -0
- data/app/mixins/stripe_local/sync_plans.rb +39 -0
- data/app/models/stripe_local/balance.rb +48 -0
- data/app/models/stripe_local/card.rb +39 -0
- data/app/models/stripe_local/charge.rb +63 -0
- data/app/models/stripe_local/coupon.rb +21 -0
- data/app/models/stripe_local/customer.rb +98 -0
- data/app/models/stripe_local/discount.rb +36 -0
- data/app/models/stripe_local/invoice.rb +68 -0
- data/app/models/stripe_local/line_item.rb +56 -0
- data/app/models/stripe_local/plan.rb +41 -0
- data/app/models/stripe_local/subscription.rb +50 -0
- data/app/models/stripe_local/transaction.rb +45 -0
- data/app/models/stripe_local/transfer.rb +48 -0
- data/app/validators/email_pattern_validator.rb +7 -0
- data/app/validators/full_name_pattern_validator.rb +7 -0
- data/app/validators/legal_name_pattern_validator.rb +7 -0
- data/app/validators/phone_pattern_validator.rb +17 -0
- data/app/validators/plan_id_pattern_validator.rb +7 -0
- data/app/validators/slug_pattern_validator.rb +38 -0
- data/app/validators/state_abbreviation_validator.rb +13 -0
- data/app/validators/stripe_type_validator.rb +7 -0
- data/app/validators/zip_type_validator.rb +8 -0
- data/app/views/layouts/stripe_local/application.html.erb +14 -0
- data/config/routes.rb +22 -0
- data/db/migrate/20131122063517_load_stripe_tables.rb +200 -0
- data/lib/stripe_local/engine.rb +7 -0
- data/lib/stripe_local/version.rb +3 -0
- data/lib/stripe_local/webhook/subscriber.rb +34 -0
- data/lib/stripe_local/webhook/types.rb +45 -0
- data/lib/stripe_local/webhook.rb +55 -0
- data/lib/stripe_local/webhooks.rb +20 -0
- data/lib/stripe_local.rb +48 -0
- data/lib/tasks/stripe_local_tasks.rake +4 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/client.rb +4 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +21 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +17 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20131102200937_create_clients.rb +11 -0
- data/spec/dummy/db/migrate/20131122104223_add_stripe_customer_id_to_clients.rb +5 -0
- data/spec/dummy/db/schema.rb +236 -0
- data/spec/dummy/log/development.log +1290 -0
- data/spec/dummy/log/test.log +7041 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/spec/spec_helper.rb +42 -0
- data/spec/fixtures/client_params.json +18 -0
- data/spec/fixtures/credit_card.json +18 -0
- data/spec/fixtures/stripe_local/balance_transactions.yml +25 -0
- data/spec/fixtures/stripe_local/cards.yml +21 -0
- data/spec/fixtures/stripe_local/charges.yml +37 -0
- data/spec/fixtures/stripe_local/coupons.yml +23 -0
- data/spec/fixtures/stripe_local/customers.yml +21 -0
- data/spec/fixtures/stripe_local/discounts.yml +13 -0
- data/spec/fixtures/stripe_local/invoices.yml +37 -0
- data/spec/fixtures/stripe_local/line_items.yml +19 -0
- data/spec/fixtures/stripe_local/plans.yml +17 -0
- data/spec/fixtures/stripe_local/subscriptions.yml +25 -0
- data/spec/fixtures/stripe_local/transfers.yml +17 -0
- data/spec/models/stripe_local/balance_spec.rb +47 -0
- data/spec/models/stripe_local/card_spec.rb +13 -0
- data/spec/models/stripe_local/charge_spec.rb +13 -0
- data/spec/models/stripe_local/customer_spec.rb +17 -0
- data/spec/models/stripe_local/invoice_spec.rb +17 -0
- data/spec/models/stripe_local/plan_spec.rb +33 -0
- data/spec/models/stripe_local/subscription_spec.rb +15 -0
- data/spec/models/stripe_local/transaction_spec.rb +14 -0
- data/spec/models/stripe_local/transfer_spec.rb +13 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/webhook_fixtures/balance_transaction.json +23 -0
- data/spec/webhook_fixtures/charge.succeeded.json +45 -0
- data/spec/webhook_fixtures/customer.created.json +41 -0
- data/spec/webhook_fixtures/customer.subscription.created.json +27 -0
- data/spec/webhook_fixtures/customer_creation_response.json +66 -0
- data/spec/webhook_fixtures/invoice.payment_succeeded.json +55 -0
- data/spec/webhook_fixtures/plan.created.json +12 -0
- data/spec/webhook_fixtures/transfer.json +32 -0
- metadata +403 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
module StripeLocal
|
2
|
+
class Customer < ActiveRecord::Base
|
3
|
+
include ObjectAdapter
|
4
|
+
|
5
|
+
self.primary_key = :id
|
6
|
+
|
7
|
+
has_one :model, inverse_of: :customer, class_name: "::#{StripeLocal::model_class}"
|
8
|
+
|
9
|
+
has_many :cards, inverse_of: :customer
|
10
|
+
|
11
|
+
has_many :invoices, inverse_of: :customer
|
12
|
+
|
13
|
+
has_many :charges, inverse_of: :customer
|
14
|
+
|
15
|
+
has_one :subscription, inverse_of: :customer
|
16
|
+
|
17
|
+
has_one :plan, through: :subscription, source: :plan
|
18
|
+
|
19
|
+
class<<self
|
20
|
+
#=!=#>>>
|
21
|
+
#
|
22
|
+
# this is the primary interface for subscribing.
|
23
|
+
#
|
24
|
+
# [params]
|
25
|
+
# * +card+ (required) -> the token returned by stripe.js
|
26
|
+
# * +plan+ (required) -> the id of the plan being subscribed to
|
27
|
+
# * +email+ (optional) -> the client's email address
|
28
|
+
# * +description+ (optional) -> a description to attach to the stripe object for future reference
|
29
|
+
# * +coupon+ (optional) -> the id of a coupon if the subscription should be discounted
|
30
|
+
# * +lines+ (optional) -> an array of (amount,description) tuples
|
31
|
+
# ```
|
32
|
+
# :card => "tok_abc123",
|
33
|
+
# :plan => "MySaaS",
|
34
|
+
# :email => subscriber.email,
|
35
|
+
# :description => "a one year subscription to our flagship service at $99.00 per month"
|
36
|
+
# :lines => [
|
37
|
+
# [ 20000, "a one time setup fee of $200.00 for new members" ]
|
38
|
+
# ]
|
39
|
+
# ```
|
40
|
+
# *returns:* _Stripe_::_Customer_._id_ which should be assign to the +:stripe_customer_id+
|
41
|
+
# field generated when bootstrapping Engine integration.
|
42
|
+
#
|
43
|
+
#=¡=#>>>
|
44
|
+
def signup params
|
45
|
+
plan = params.delete( :plan )
|
46
|
+
lines = params.delete( :lines ) || []
|
47
|
+
|
48
|
+
customer = Stripe::Customer.create( params )
|
49
|
+
|
50
|
+
lines.each do |item|
|
51
|
+
customer.add_invoice_item( {currency: 'usd'}.merge item )
|
52
|
+
end
|
53
|
+
|
54
|
+
customer.update_subscription({ plan: plan })
|
55
|
+
create( customer ).id
|
56
|
+
end
|
57
|
+
|
58
|
+
def create params
|
59
|
+
super normalize params
|
60
|
+
end
|
61
|
+
|
62
|
+
def normalize params
|
63
|
+
params.each_with_object({}) do |(k,v),h|
|
64
|
+
key = case k.to_sym
|
65
|
+
when :cards then create_each_card( v.data ) and next
|
66
|
+
when :subscription then create_subscript( v ) and next
|
67
|
+
when ->(x){attribute_method? x} then k.to_sym
|
68
|
+
else next
|
69
|
+
end
|
70
|
+
h[key] = v
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_each_card cards
|
75
|
+
cards.each do |card|
|
76
|
+
StripeLocal::Card.create card.to_hash
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_subscript o
|
81
|
+
StripeLocal::Subscription.create( o.to_hash ) unless o.nil?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#=!=>>>
|
86
|
+
# ~<Schema>~
|
87
|
+
# t.string :id
|
88
|
+
# t.integer :account_balance
|
89
|
+
# t.string :default_card
|
90
|
+
# t.boolean :delinquent
|
91
|
+
# t.string :description
|
92
|
+
# t.string :email
|
93
|
+
# t.text :metadata
|
94
|
+
# t.timestamps
|
95
|
+
|
96
|
+
#=¡=>>>
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module StripeLocal
|
2
|
+
class Discount < ActiveRecord::Base
|
3
|
+
include ObjectAdapter
|
4
|
+
|
5
|
+
time_writer :start, :end
|
6
|
+
|
7
|
+
class<<self
|
8
|
+
def create object
|
9
|
+
super normalize object
|
10
|
+
end
|
11
|
+
|
12
|
+
def normalize attrs
|
13
|
+
attrs.each_with_object({}) do |(k,v),h|
|
14
|
+
key = case k.to_sym
|
15
|
+
when :customer then :customer_id
|
16
|
+
when :coupon then h[:coupon_id] = v.id and next
|
17
|
+
when ->(x){ attribute_method? x } then k.to_sym
|
18
|
+
else next
|
19
|
+
end
|
20
|
+
if v.is_a?(Numeric) && v > 1000000000
|
21
|
+
h[key] = Time.at( v )
|
22
|
+
else
|
23
|
+
h[key] = v
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#=!=#>>>
|
30
|
+
# string :coupon_id
|
31
|
+
# string :customer_id
|
32
|
+
# datetime :start
|
33
|
+
# datetime :end
|
34
|
+
#=¡=#>>>
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module StripeLocal
|
2
|
+
class Invoice < ActiveRecord::Base
|
3
|
+
include ObjectAdapter
|
4
|
+
|
5
|
+
has_many :lines, inverse_of: :invoice, class_name: "LineItem"
|
6
|
+
belongs_to :charge, inverse_of: :invoice
|
7
|
+
belongs_to :customer, inverse_of: :invoices
|
8
|
+
|
9
|
+
self.primary_key = :id
|
10
|
+
|
11
|
+
time_writer :date, :period_start, :period_end, :next_payment_attempt
|
12
|
+
|
13
|
+
class<<self
|
14
|
+
def create object
|
15
|
+
super normalize( object )
|
16
|
+
end
|
17
|
+
|
18
|
+
def normalize attrs
|
19
|
+
attrs.each_with_object({}) do |(k,v),h|
|
20
|
+
key = case k.to_sym
|
21
|
+
when :customer then :customer_id
|
22
|
+
when :charge then :charge_id
|
23
|
+
when :lines then v.data.each do |item|
|
24
|
+
StripeLocal::LineItem.create item.to_hash.merge({invoice_id: attrs.id})
|
25
|
+
end and next
|
26
|
+
when ->(x){attribute_method? x} then k.to_sym
|
27
|
+
else next
|
28
|
+
end
|
29
|
+
if v.is_a?(Numeric) && v > 1000000000
|
30
|
+
h[key] = Time.at( v )
|
31
|
+
else
|
32
|
+
h[key] = v
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def succeed inv
|
38
|
+
#TODO: implement this
|
39
|
+
end
|
40
|
+
|
41
|
+
def fail inv
|
42
|
+
#TODO: implement this
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
#=!=#>>>
|
48
|
+
# string :id
|
49
|
+
# string :customer_id
|
50
|
+
# integer :amount_due
|
51
|
+
# integer :subtotal
|
52
|
+
# integer :total
|
53
|
+
# boolean :attempted
|
54
|
+
# integer :attempt_count
|
55
|
+
# boolean :paid
|
56
|
+
# boolean :closed
|
57
|
+
# datetime :date
|
58
|
+
# datetime :period_start
|
59
|
+
# datetime :period_end
|
60
|
+
# string :currency
|
61
|
+
# integer :starting_balance
|
62
|
+
# integer :ending_balance
|
63
|
+
# string :charge_id
|
64
|
+
# integer :discount
|
65
|
+
# datetime :next_payment_attempt
|
66
|
+
#=¡=#>>>
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module StripeLocal
|
2
|
+
class LineItem < ActiveRecord::Base
|
3
|
+
include ObjectAdapter
|
4
|
+
|
5
|
+
self.primary_key = :id
|
6
|
+
|
7
|
+
belongs_to :invoice, inverse_of: :lines
|
8
|
+
|
9
|
+
belongs_to :plan, inverse_of: :line_items
|
10
|
+
|
11
|
+
time_writer :period_start, :period_end
|
12
|
+
|
13
|
+
def metadata= hash
|
14
|
+
MultiJson.dump hash
|
15
|
+
end
|
16
|
+
|
17
|
+
def metadata
|
18
|
+
MultiJson.load read_attribute( :metadata ), symbolize_keys: true
|
19
|
+
end
|
20
|
+
|
21
|
+
class<<self
|
22
|
+
def create attr_hash
|
23
|
+
super normalize( attr_hash )
|
24
|
+
end
|
25
|
+
|
26
|
+
def normalize attrs
|
27
|
+
attrs.each_with_object({}) do |(k,v),h|
|
28
|
+
key = case k.to_sym
|
29
|
+
when :invoice then :invoice_id
|
30
|
+
when :plan then h[:plan_id] = v.id and next
|
31
|
+
when :type then h[:subscription] = (v == "subscription" ? true : false) and next
|
32
|
+
when :period then h[:period_start] = Time.at(v.start) and h[:period_end] = Time.at(v.end) and next
|
33
|
+
when ->(x){attribute_method? x} then k.to_sym
|
34
|
+
else next
|
35
|
+
end
|
36
|
+
h[key] = v
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#=!=#>>>
|
42
|
+
# string :id
|
43
|
+
# string :invoice_id
|
44
|
+
# boolean :subscription
|
45
|
+
# integer :amount
|
46
|
+
# string :currency
|
47
|
+
# boolean :proration
|
48
|
+
# datetime :period_start
|
49
|
+
# datetime :period_end
|
50
|
+
# integer :quantity
|
51
|
+
# string :plan_id
|
52
|
+
# string :description
|
53
|
+
# text :metadata
|
54
|
+
#=¡=#>>>
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module StripeLocal
|
2
|
+
class Plan < ActiveRecord::Base
|
3
|
+
include SyncPlans
|
4
|
+
|
5
|
+
self.primary_key = :id
|
6
|
+
|
7
|
+
has_many :subscriptions, inverse_of: :plan
|
8
|
+
|
9
|
+
class<<self
|
10
|
+
def create object
|
11
|
+
if found = find_by( id: object[:id] )
|
12
|
+
found.update_attributes synced: true
|
13
|
+
else
|
14
|
+
super normalize object
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def normalize attrs
|
19
|
+
attrs.each_with_object({}) do |(k,v),h|
|
20
|
+
key = case k.to_sym
|
21
|
+
when :livemode then h[:synced] = true and next
|
22
|
+
when ->(x){ attribute_method? x } then k.to_sym
|
23
|
+
else next
|
24
|
+
end
|
25
|
+
h[key] = v
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#=!=#>>>
|
31
|
+
# string :id
|
32
|
+
# string :name
|
33
|
+
# integer :amount
|
34
|
+
# string :interval
|
35
|
+
# integer :interval_count
|
36
|
+
# integer :trial_period_days
|
37
|
+
# string :currency
|
38
|
+
# boolean :synced
|
39
|
+
#=¡=#>>>
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module StripeLocal
|
2
|
+
class Subscription < ActiveRecord::Base
|
3
|
+
include ObjectAdapter
|
4
|
+
|
5
|
+
belongs_to :customer, inverse_of: :subscription
|
6
|
+
|
7
|
+
belongs_to :plan, inverse_of: :subscription
|
8
|
+
|
9
|
+
time_writer :start, :canceled_at, :current_period_start,
|
10
|
+
:current_period_end, :trial_start, :trial_end, :ended_at
|
11
|
+
|
12
|
+
|
13
|
+
class<<self
|
14
|
+
def create object
|
15
|
+
super normalize( object )
|
16
|
+
end
|
17
|
+
|
18
|
+
def normalize attrs
|
19
|
+
attrs.each_with_object({}) do |(k,v),h|
|
20
|
+
key = case k.to_sym
|
21
|
+
when :id then next
|
22
|
+
when :customer then :customer_id
|
23
|
+
when :plan then h[:plan_id] = v.id and next
|
24
|
+
when ->(x){attribute_method? x} then k.to_sym
|
25
|
+
else next
|
26
|
+
end
|
27
|
+
if v.is_a?(Numeric) && v > 1000000000
|
28
|
+
h[key] = Time.at( v )
|
29
|
+
else
|
30
|
+
h[key] = v
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
#=!=#>>>
|
38
|
+
# string :customer_id
|
39
|
+
# string :plan_id
|
40
|
+
# string :status
|
41
|
+
# datetime :start
|
42
|
+
# datetime :canceled_at
|
43
|
+
# datetime :ended_at
|
44
|
+
# datetime :current_period_start
|
45
|
+
# datetime :current_period_end
|
46
|
+
# datetime :trial_start
|
47
|
+
# datetime :trial_end
|
48
|
+
#=¡=#>>>
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module StripeLocal
|
2
|
+
class Transaction < ActiveRecord::Base
|
3
|
+
include ObjectAdapter
|
4
|
+
|
5
|
+
self.primary_key = :id
|
6
|
+
|
7
|
+
time_writer :created, :available_on
|
8
|
+
|
9
|
+
class<<self
|
10
|
+
def create object
|
11
|
+
super normalize( object )
|
12
|
+
end
|
13
|
+
|
14
|
+
def normalize attrs
|
15
|
+
attrs.each_with_object({}) do |(k,v),h|
|
16
|
+
key = case k.to_sym
|
17
|
+
when :source then :source_id
|
18
|
+
when :type then :source_type
|
19
|
+
when ->(x){attribute_method? x} then k.to_sym
|
20
|
+
else next
|
21
|
+
end
|
22
|
+
if v.is_a?(Numeric) && v > 1000000000
|
23
|
+
h[key] = Time.at( v )
|
24
|
+
else
|
25
|
+
h[key] = v
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
#=!=#>>>
|
33
|
+
# string :id
|
34
|
+
# integer :amount
|
35
|
+
# datetime :available_on
|
36
|
+
# datetime :created
|
37
|
+
# integer :fee
|
38
|
+
# integer :net
|
39
|
+
# string :source_id
|
40
|
+
# string :source_type
|
41
|
+
# string :status
|
42
|
+
# string :description
|
43
|
+
#=¡=#>>>
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module StripeLocal
|
2
|
+
class Transfer < ActiveRecord::Base
|
3
|
+
include ObjectAdapter
|
4
|
+
|
5
|
+
has_one :transaction, as: :source
|
6
|
+
|
7
|
+
self.primary_key = :id
|
8
|
+
|
9
|
+
time_writer :date
|
10
|
+
|
11
|
+
def metadata= hash
|
12
|
+
MultiJson.dump hash
|
13
|
+
end
|
14
|
+
|
15
|
+
def metadata
|
16
|
+
MultiJson.load read_attribute( :metadata ), symbolize_keys: true
|
17
|
+
end
|
18
|
+
|
19
|
+
class<<self
|
20
|
+
def create object
|
21
|
+
super normalize( object )
|
22
|
+
end
|
23
|
+
|
24
|
+
def normalize attrs
|
25
|
+
attrs.each_with_object({}) do |(k,v),h|
|
26
|
+
key = case k.to_sym
|
27
|
+
when :balance_transaction then :transaction_id
|
28
|
+
when :date then h[:date] = Time.at(v) and next
|
29
|
+
when ->(x){attribute_method? x} then k.to_sym
|
30
|
+
else next
|
31
|
+
end
|
32
|
+
h[key] = v
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
#=!=#>>>
|
39
|
+
# string :id
|
40
|
+
# integer :amount
|
41
|
+
# datetime :date
|
42
|
+
# string :status
|
43
|
+
# string :transaction_id
|
44
|
+
# string :description
|
45
|
+
# text :metadata
|
46
|
+
#=¡=#>>>
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class EmailPatternValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each(record, attribute, value)
|
3
|
+
unless value.match(/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i)
|
4
|
+
record.errors[attribute] << "Not a valid email address"
|
5
|
+
end unless value.blank?
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class LegalNamePatternValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each(record, attribute, value)
|
3
|
+
if value.nil? || !value.match(/\A\S+?\s\S+?(?:\s\S+?)?\Z/i)
|
4
|
+
record.errors[attribute] << "must be in the form \"First Last\", \"First Middle Last\", or \"First M Last\" (no prefixes or suffixes)"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class PhonePatternValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each(record, attribute, value)
|
3
|
+
if !value.blank?
|
4
|
+
first_normalize value
|
5
|
+
unless value.match(/^((\d){10})$/i)
|
6
|
+
record.errors[attribute] << "10 digit phone number, area-code first, no country code please."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def first_normalize number
|
14
|
+
number.to_phone
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class PlanIdPatternValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each record, attribute, value
|
3
|
+
if value.nil? || !value.match(/^(([\w\-]{0,62})?)$/i)
|
4
|
+
record.errors[attribute] << "accepts alphanumeric characters, '-', and '_' only. no spaces"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class SlugPatternValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each record, attribute, value
|
3
|
+
if value.blank?
|
4
|
+
record.errors[attribute] << "cannot be blank"
|
5
|
+
else
|
6
|
+
return string_replaced value
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def string_replaced value
|
11
|
+
email_removal_for_morons value
|
12
|
+
intelligently_de_dot value
|
13
|
+
finish_normalizing value
|
14
|
+
value
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def finish_normalizing str
|
20
|
+
str.gsub!(/\W/,'-')
|
21
|
+
str.gsub!(/(\W\-|\-\W|\-)+/,'-')
|
22
|
+
str.gsub!(/(\A\-|\-\Z)/,'')
|
23
|
+
str
|
24
|
+
end
|
25
|
+
|
26
|
+
def intelligently_de_dot str
|
27
|
+
str.gsub!(/([A-Z])\.([a-z])/,'\1-\2')
|
28
|
+
str.gsub!(/([A-Z])\./,'\1')
|
29
|
+
str
|
30
|
+
end
|
31
|
+
|
32
|
+
def email_removal_for_morons str
|
33
|
+
str.gsub(/^(.*)?@([^@]*)?\.([^@\.]*)$/, '\1' )
|
34
|
+
pattern = ("" == $1) ? '\2-\3' : '\1'
|
35
|
+
str.gsub!(/^(.*)?@([^@]*)?\.([^@\.]*)$/, pattern )
|
36
|
+
str
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class StateAbbreviationValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each record, attribute, value
|
3
|
+
unless value.blank?
|
4
|
+
if value.size > 2
|
5
|
+
value = STATES_HASH.fetch( value.downcase, 'invalid' )
|
6
|
+
record[attribute] = value
|
7
|
+
end
|
8
|
+
unless value.in? STATES_HASH.values
|
9
|
+
record.errors[attribute] << "not a state of this great nation"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>StripeLocal</title>
|
5
|
+
<%= stylesheet_link_tag "stripe_local/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "stripe_local/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
StripeLocal::Engine.routes.draw do
|
2
|
+
resources :charges
|
3
|
+
|
4
|
+
resources :line_items
|
5
|
+
|
6
|
+
resources :invoices
|
7
|
+
|
8
|
+
resources :subscriptions
|
9
|
+
|
10
|
+
resources :discounts
|
11
|
+
|
12
|
+
resources :coupons
|
13
|
+
|
14
|
+
resources :plans
|
15
|
+
|
16
|
+
resources :cards
|
17
|
+
|
18
|
+
resources :customers
|
19
|
+
|
20
|
+
post 'webhook/events', to: 'webhooks#events'
|
21
|
+
|
22
|
+
end
|