payola-payments 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +8 -8
  2. data/Rakefile +7 -11
  3. data/app/assets/javascripts/payola.js +1 -0
  4. data/app/assets/javascripts/payola/checkout_button.js +62 -0
  5. data/app/controllers/payola/application_controller.rb +2 -0
  6. data/app/controllers/payola/transactions_controller.rb +48 -58
  7. data/app/helpers/payola/price_helper.rb +7 -0
  8. data/{lib → app/models/concerns}/payola/sellable.rb +11 -1
  9. data/app/models/payola/affiliate.rb +5 -0
  10. data/app/models/payola/coupon.rb +5 -0
  11. data/app/models/payola/sale.rb +15 -4
  12. data/app/models/payola/stripe_webhook.rb +5 -0
  13. data/app/services/payola/charge_card.rb +6 -5
  14. data/app/services/payola/create_sale.rb +9 -5
  15. data/app/views/payola/transactions/_checkout.html.erb +48 -0
  16. data/app/views/payola/transactions/_form.html.erb +141 -0
  17. data/app/views/payola/transactions/iframe.html.erb +2 -0
  18. data/app/views/payola/transactions/new.html.erb +1 -0
  19. data/app/views/payola/transactions/show.html.erb +5 -0
  20. data/app/views/payola/transactions/wait.html.erb +25 -0
  21. data/config/routes.rb +0 -3
  22. data/db/migrate/20141001170138_create_payola_sales.rb +4 -4
  23. data/db/migrate/20141001203541_create_payola_stripe_webhooks.rb +9 -0
  24. data/db/migrate/20141002013618_create_payola_coupons.rb +10 -0
  25. data/db/migrate/20141002013701_create_payola_affiliates.rb +11 -0
  26. data/db/migrate/20141002203725_add_stripe_customer_id_to_sale.rb +6 -0
  27. data/lib/payola.rb +30 -5
  28. data/lib/payola/engine.rb +8 -0
  29. data/lib/payola/version.rb +1 -1
  30. data/lib/payola/worker.rb +22 -4
  31. data/spec/concerns/sellable_spec.rb +32 -0
  32. data/spec/controllers/payola/transactions_controller_spec.rb +7 -0
  33. data/{test → spec}/dummy/README.rdoc +0 -0
  34. data/{test → spec}/dummy/Rakefile +0 -0
  35. data/{test → spec}/dummy/app/assets/javascripts/application.js +1 -0
  36. data/spec/dummy/app/assets/javascripts/buy.js +2 -0
  37. data/{test → spec}/dummy/app/assets/stylesheets/application.css +0 -0
  38. data/spec/dummy/app/assets/stylesheets/buy.css +4 -0
  39. data/{test → spec}/dummy/app/controllers/application_controller.rb +0 -0
  40. data/spec/dummy/app/controllers/buy_controller.rb +7 -0
  41. data/{test → spec}/dummy/app/helpers/application_helper.rb +0 -0
  42. data/spec/dummy/app/helpers/buy_helper.rb +2 -0
  43. data/spec/dummy/app/models/product.rb +7 -0
  44. data/spec/dummy/app/views/buy/index.html.erb +1 -0
  45. data/{test → spec}/dummy/app/views/layouts/application.html.erb +2 -1
  46. data/{test → spec}/dummy/bin/bundle +0 -0
  47. data/{test → spec}/dummy/bin/rails +0 -0
  48. data/{test → spec}/dummy/bin/rake +0 -0
  49. data/{test → spec}/dummy/config.ru +0 -0
  50. data/{test → spec}/dummy/config/application.rb +0 -0
  51. data/{test → spec}/dummy/config/boot.rb +0 -0
  52. data/{test → spec}/dummy/config/database.yml +0 -0
  53. data/{test → spec}/dummy/config/environment.rb +0 -0
  54. data/{test → spec}/dummy/config/environments/development.rb +0 -0
  55. data/{test → spec}/dummy/config/environments/production.rb +0 -0
  56. data/{test → spec}/dummy/config/environments/test.rb +0 -0
  57. data/{test → spec}/dummy/config/initializers/assets.rb +0 -0
  58. data/{test → spec}/dummy/config/initializers/backtrace_silencers.rb +0 -0
  59. data/{test → spec}/dummy/config/initializers/cookies_serializer.rb +0 -0
  60. data/{test → spec}/dummy/config/initializers/filter_parameter_logging.rb +0 -0
  61. data/{test → spec}/dummy/config/initializers/inflections.rb +0 -0
  62. data/{test → spec}/dummy/config/initializers/mime_types.rb +0 -0
  63. data/spec/dummy/config/initializers/payola.rb +5 -0
  64. data/{test → spec}/dummy/config/initializers/session_store.rb +0 -0
  65. data/{test → spec}/dummy/config/initializers/wrap_parameters.rb +0 -0
  66. data/{test → spec}/dummy/config/locales/en.yml +0 -0
  67. data/{test → spec}/dummy/config/routes.rb +1 -1
  68. data/{test → spec}/dummy/config/secrets.yml +0 -0
  69. data/spec/dummy/db/development.sqlite3 +0 -0
  70. data/spec/dummy/db/migrate/20141001230848_create_products.rb +11 -0
  71. data/spec/dummy/db/schema.rb +76 -0
  72. data/spec/dummy/db/test.sqlite3 +0 -0
  73. data/spec/dummy/log/development.log +7452 -0
  74. data/spec/dummy/log/test.log +9849 -0
  75. data/{test → spec}/dummy/public/404.html +0 -0
  76. data/{test → spec}/dummy/public/422.html +0 -0
  77. data/{test → spec}/dummy/public/500.html +0 -0
  78. data/{test → spec}/dummy/public/favicon.ico +0 -0
  79. data/spec/dummy/spec/controllers/buy_controller_spec.rb +5 -0
  80. data/spec/dummy/spec/factories/products.rb +9 -0
  81. data/spec/dummy/tmp/cache/assets/development/sprockets/0e585aeb88c1555ae8f5292f7c7a9068 +0 -0
  82. data/spec/dummy/tmp/cache/assets/development/sprockets/0f0c99469c51f1b2d76b08f481781d09 +0 -0
  83. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  84. data/spec/dummy/tmp/cache/assets/development/sprockets/1b54952339cbc96811097cee5f8923b4 +0 -0
  85. data/spec/dummy/tmp/cache/assets/development/sprockets/1cbc4f4790f2067a2c161c1eb480f276 +0 -0
  86. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  87. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  88. data/spec/dummy/tmp/cache/assets/development/sprockets/5afa4bc970e0bc781b3500c696ba25ff +0 -0
  89. data/spec/dummy/tmp/cache/assets/development/sprockets/664efeb51d1b486dcfc30d142db56f3c +0 -0
  90. data/spec/dummy/tmp/cache/assets/development/sprockets/68a3bbdc64a0729b5896fa1e33fce4b1 +0 -0
  91. data/spec/dummy/tmp/cache/assets/development/sprockets/aea159adbc0944b120d91d5b578612ba +0 -0
  92. data/spec/dummy/tmp/cache/assets/development/sprockets/b83da90cb58011313e13a97a4a41cb6e +0 -0
  93. data/spec/dummy/tmp/cache/assets/development/sprockets/c0b954b40f2881a6d286061bc069643e +0 -0
  94. data/spec/dummy/tmp/cache/assets/development/sprockets/c5b3877d49b39932a7557611cefca9a6 +0 -0
  95. data/spec/dummy/tmp/cache/assets/development/sprockets/ca491e325ff6948be9292f701aa4ce64 +0 -0
  96. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  97. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  98. data/spec/dummy/tmp/cache/assets/development/sprockets/d9856638a3c7b9cfd9d1b884e3b33982 +0 -0
  99. data/spec/dummy/tmp/cache/assets/development/sprockets/ddba6e841f28d3005e828fbfffd18b74 +0 -0
  100. data/spec/dummy/tmp/cache/assets/development/sprockets/df935e399019055729aa968bd7062096 +0 -0
  101. data/spec/dummy/tmp/cache/assets/development/sprockets/ef82c31948061751bb026663b54484e1 +0 -0
  102. data/spec/dummy/tmp/cache/assets/development/sprockets/f0b5d4bea0c6cdd1904e1e9a0a45532f +0 -0
  103. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  104. data/spec/dummy/tmp/cache/assets/development/sprockets/f8018075b7aca72974f4014bbbc75ab5 +0 -0
  105. data/spec/factories/payola_affiliates.rb +9 -0
  106. data/spec/factories/payola_coupons.rb +8 -0
  107. data/spec/factories/product.rb +7 -0
  108. data/spec/factories/sales.rb +7 -0
  109. data/spec/models/payola/sale_spec.rb +71 -0
  110. data/spec/models/payola/stripe_webhook_spec.rb +17 -0
  111. data/spec/payola_spec.rb +93 -0
  112. data/spec/services/payola/charge_card_spec.rb +37 -0
  113. data/spec/services/payola/create_sale_spec.rb +64 -0
  114. data/spec/spec_helper.rb +73 -0
  115. data/spec/worker_spec.rb +36 -0
  116. metadata +275 -81
  117. data/test/fixtures/payola/sales.yml +0 -11
  118. data/test/integration/navigation_test.rb +0 -10
  119. data/test/models/payola/sale_test.rb +0 -9
  120. data/test/payola_test.rb +0 -7
  121. data/test/test_helper.rb +0 -15
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe BuyController do
4
+
5
+ end
@@ -0,0 +1,9 @@
1
+ # Read about factories at https://github.com/thoughtbot/factory_girl
2
+
3
+ FactoryGirl.define do
4
+ factory :product do
5
+ name "MyString"
6
+ permalink "MyString"
7
+ price 1
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # Read about factories at https://github.com/thoughtbot/factory_girl
2
+
3
+ FactoryGirl.define do
4
+ factory :payola_affiliate, :class => 'Payola::Affiliate' do
5
+ code "MyString"
6
+ email "foo@example.com"
7
+ percent 100
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ # Read about factories at https://github.com/thoughtbot/factory_girl
2
+
3
+ FactoryGirl.define do
4
+ factory :payola_coupon, :class => 'Payola::Coupon' do
5
+ code "MyString"
6
+ percent_off 1
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :product do
3
+ name "Foo"
4
+ sequence(:permalink) { |n| "foo-#{n}" }
5
+ price 100
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :sale, class: Payola::Sale do
3
+ email 'test@example.com'
4
+ product
5
+ stripe_token 'tok_test'
6
+ end
7
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ module Payola
4
+ describe Sale do
5
+ describe "validations" do
6
+ it "should validate" do
7
+ sale = build(:sale)
8
+ expect(sale.valid?).to be true
9
+ end
10
+
11
+ it "should validate lack of email" do
12
+ sale = build(:sale, email: nil)
13
+ expect(sale.valid?).to be false
14
+ end
15
+ it "should validate product" do
16
+ sale = build(:sale, product: nil)
17
+ expect(sale.valid?).to be false
18
+ end
19
+ it "should validate stripe_token" do
20
+ sale = build(:sale, stripe_token: nil)
21
+ expect(sale.valid?).to be false
22
+ end
23
+ end
24
+
25
+ describe "#guid" do
26
+ it "should generate a unique guid" do
27
+ sale = create(:sale)
28
+ expect(sale.valid?).to be true
29
+ expect(sale.guid).to_not be_nil
30
+
31
+ sale2 = build(:sale, guid: sale.guid)
32
+ expect(sale2.valid?).to be false
33
+ end
34
+ end
35
+
36
+ describe "#process!" do
37
+ it "should charge the card" do
38
+ Payola::ChargeCard.should_receive(:call)
39
+
40
+ sale = create(:sale)
41
+ sale.process!
42
+ end
43
+ end
44
+
45
+ describe "#finish" do
46
+ it "should instrument finish" do
47
+ sale = create(:sale, state: 'processing')
48
+ Payola.should_receive(:instrument).with('payola.product.sale.finished', sale)
49
+
50
+ sale.finish!
51
+ end
52
+ end
53
+
54
+ describe "#fail" do
55
+ it "should instrument fail" do
56
+ sale = create(:sale, state: 'processing')
57
+ Payola.should_receive(:instrument).with('payola.product.sale.failed', sale)
58
+
59
+ sale.fail!
60
+ end
61
+ end
62
+
63
+ describe "#refund" do
64
+ it "should instrument refund" do
65
+ sale = create(:sale, state: 'finished')
66
+ Payola.should_receive(:instrument).with('payola.product.sale.refunded', sale)
67
+ sale.refund!
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ module Payola
4
+ describe StripeWebhook do
5
+ it "should validate" do
6
+ s = StripeWebhook.new(stripe_id: 'test_id')
7
+ expect(s.valid?).to be true
8
+ end
9
+
10
+ it "should validate stripe_id" do
11
+ s = StripeWebhook.create(stripe_id: 'test_id')
12
+ s2 = StripeWebhook.new(stripe_id: 'test_id')
13
+
14
+ expect(s2.valid?).to be false
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ module Payola
4
+ describe "#configure" do
5
+ it "should pass the class back to the given block" do
6
+ Payola.configure do |payola|
7
+ expect(payola).to eq Payola
8
+ end
9
+ end
10
+ end
11
+
12
+ describe "keys" do
13
+ it "should set publishable key from env" do
14
+ ENV['STRIPE_PUBLISHABLE_KEY'] = 'some_key'
15
+ Payola.reset!
16
+ expect(Payola.publishable_key).to eq 'some_key'
17
+ end
18
+
19
+ it "should set secret key from env" do
20
+ ENV['STRIPE_SECRET_KEY'] = 'some_secret'
21
+ Payola.reset!
22
+ expect(Payola.secret_key).to eq 'some_secret'
23
+ end
24
+ end
25
+
26
+ describe "instrumentation" do
27
+ it "should pass subscribe to StripeEvent" do
28
+ StripeEvent.should_receive(:subscribe)
29
+ Payola.subscribe('foo', 'blah')
30
+ end
31
+ it "should pass instrument to StripeEvent.backend" do
32
+ ActiveSupport::Notifications.should_receive(:instrument)
33
+ Payola.instrument('foo', 'blah')
34
+ end
35
+ it "should pass all to StripeEvent" do
36
+ StripeEvent.should_receive(:all)
37
+ Payola.all('blah')
38
+ end
39
+ end
40
+
41
+ describe "#queue" do
42
+ before do
43
+ Payola.reset!
44
+
45
+ class FakeWorker; end
46
+ Payola::Worker.registry ||= {}
47
+ Payola::Worker.registry[:fake] = FakeWorker
48
+ end
49
+
50
+ describe "with symbol" do
51
+ it "should find the correct background worker" do
52
+ FakeWorker.should_receive(:call)
53
+
54
+ Payola.background_worker = :fake
55
+ Payola.queue!('blah')
56
+ end
57
+
58
+ it "should not find a background worker for an unknown symbol" do
59
+ Payola.background_worker = :another_fake
60
+ expect { Payola.queue!('blah') }.to raise_error(RuntimeError)
61
+ end
62
+ end
63
+
64
+ describe "with callable" do
65
+ it "should call the callable" do
66
+ foo = nil
67
+
68
+ Payola.background_worker = lambda do |sale|
69
+ foo = sale
70
+ end
71
+
72
+ Payola.queue!('blah')
73
+
74
+ expect(foo).to eq 'blah'
75
+ end
76
+ end
77
+
78
+ describe "with nothing" do
79
+ it "should call autofind" do
80
+ FakeWorker.should_receive(:call).and_return(:true)
81
+ Payola::Worker.should_receive(:autofind).and_return(FakeWorker)
82
+ Payola.queue!('blah')
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "#secret_key_retriever" do
88
+ it "should get called" do
89
+ Payola.secret_key_retriever = lambda { |sale| 'foo' }
90
+ expect(Payola.secret_key_for_sale('blah')).to eq 'foo'
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ module Payola
4
+ describe ChargeCard do
5
+ describe "#call" do
6
+ it "should create a customer" do
7
+ sale = create(:sale, state: 'processing')
8
+ ChargeCard.call(sale)
9
+ expect(sale.reload.stripe_customer_id).to_not be_nil
10
+ end
11
+ it "should create a charge" do
12
+ sale = create(:sale, state: 'processing')
13
+ ChargeCard.call(sale)
14
+ expect(sale.reload.stripe_id).to_not be_nil
15
+ expect(sale.reload.card_last4).to_not be_nil
16
+ expect(sale.reload.card_expiration).to_not be_nil
17
+ expect(sale.reload.card_type).to_not be_nil
18
+ end
19
+ it "should get the fee from the balance transaction" do
20
+ sale = create(:sale, state: 'processing')
21
+ ChargeCard.call(sale)
22
+ expect(sale.reload.fee_amount).to_not be_nil
23
+ end
24
+ describe "on error" do
25
+ it "should update the error attribute" do
26
+ StripeMock.prepare_card_error(:card_declined)
27
+ sale = create(:sale, state: 'processing')
28
+ ChargeCard.call(sale)
29
+ expect(sale.reload.error).to_not be_nil
30
+ expect(sale.errored?).to be true
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ module Payola
4
+ describe CreateSale do
5
+ before do
6
+ @product = create(:product)
7
+ end
8
+
9
+ describe "#call" do
10
+ it "should create a sale" do
11
+ sale = CreateSale.call(
12
+ email: 'pete@bugsplat.info',
13
+ stripeToken: 'test_tok',
14
+ product: @product
15
+ )
16
+
17
+ expect(sale.email).to eq 'pete@bugsplat.info'
18
+ expect(sale.stripe_token).to eq 'test_tok'
19
+ expect(sale.product_id).to eq @product.id
20
+ expect(sale.product).to eq @product
21
+ expect(sale.product_type).to eq 'Product'
22
+ end
23
+
24
+ it "should include the affiliate if given" do
25
+ affiliate = create(:payola_affiliate)
26
+ sale = CreateSale.call(
27
+ email: 'pete@bugsplat.info',
28
+ stripeToken: 'test_tok',
29
+ product: @product,
30
+ affiliate: affiliate
31
+ )
32
+
33
+ expect(sale.affiliate).to eq affiliate
34
+ end
35
+
36
+ describe "with coupon" do
37
+ it "should include the coupon" do
38
+ coupon = create(:payola_coupon)
39
+
40
+ sale = CreateSale.call(
41
+ email: 'pete@bugsplat.info',
42
+ stripeToken: 'test_tok',
43
+ product: @product,
44
+ coupon: coupon
45
+ )
46
+
47
+ expect(sale.coupon).to eq coupon
48
+ end
49
+ it "should set the price correctly" do
50
+ coupon = create(:payola_coupon)
51
+
52
+ sale = CreateSale.call(
53
+ email: 'pete@bugsplat.info',
54
+ stripeToken: 'test_tok',
55
+ product: @product,
56
+ coupon: coupon
57
+ )
58
+
59
+ expect(sale.amount).to eq 99
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,73 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV["RAILS_ENV"] ||= 'test'
3
+ require File.expand_path("../dummy/config/environment", __FILE__)
4
+ require 'rspec/rails'
5
+ require 'rspec/autorun'
6
+ require 'factory_girl_rails'
7
+ require 'stripe_mock'
8
+
9
+ # Requires supporting ruby files with custom matchers and macros, etc, in
10
+ # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
11
+ # run as spec files by default. This means that files in spec/support that end
12
+ # in _spec.rb will both be required and run as specs, causing the specs to be
13
+ # run twice. It is recommended that you do not name files matching this glob to
14
+ # end with _spec.rb. You can configure this pattern with with the --pattern
15
+ # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
16
+ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
17
+
18
+ # Checks for pending migrations before tests are run.
19
+ # If you are not using ActiveRecord, you can remove this line.
20
+ ActiveRecord::Migration.maintain_test_schema!
21
+
22
+ RSpec.configure do |config|
23
+ # ## Mock Framework
24
+ #
25
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
26
+ #
27
+ # config.mock_with :mocha
28
+ # config.mock_with :flexmock
29
+ # config.mock_with :rr
30
+
31
+ config.mock_with :rspec
32
+
33
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
34
+ # examples within a transaction, remove the following line or assign false
35
+ # instead of true.
36
+ config.use_transactional_fixtures = true
37
+
38
+ # If true, the base class of anonymous controllers will be inferred
39
+ # automatically. This will be the default behavior in future versions of
40
+ # rspec-rails.
41
+ config.infer_base_class_for_anonymous_controllers = false
42
+
43
+ # Run specs in random order to surface order dependencies. If you find an
44
+ # order dependency and want to debug it, you can fix the order by providing
45
+ # the seed, which is printed after each run.
46
+ # --seed 1234
47
+ config.order = "random"
48
+
49
+ # RSpec Rails can automatically mix in different behaviours to your tests
50
+ # based on their file location, for example enabling you to call `get` and
51
+ # `post` in specs under `spec/controllers`.
52
+ #
53
+ # You can disable this behaviour by removing the line below, and instead
54
+ # explictly tag your specs with their type, e.g.:
55
+ #
56
+ # describe UsersController, :type => :controller do
57
+ # # ...
58
+ # end
59
+ #
60
+ # The different available types are documented in the features, such as in
61
+ # https://relishapp.com/rspec/rspec-rails/v/3-0/docs
62
+ config.infer_spec_type_from_file_location!
63
+
64
+ config.include FactoryGirl::Syntax::Methods
65
+
66
+ config.before(:each) do
67
+ StripeMock.start
68
+ end
69
+
70
+ config.after(:each) do
71
+ StripeMock.stop
72
+ end
73
+ end