jackpot 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. data/.gitignore +16 -0
  2. data/.rspec +1 -0
  3. data/.rvmrc.example +1 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +9 -0
  6. data/Gemfile.lock +181 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +134 -0
  9. data/Rakefile +25 -0
  10. data/app/assets/images/jackpot/.gitkeep +0 -0
  11. data/app/assets/javascripts/jackpot/application.js +5 -0
  12. data/app/assets/javascripts/jackpot/bootstrap.js +32 -0
  13. data/app/assets/javascripts/jackpot/customers.js +2 -0
  14. data/app/assets/javascripts/jackpot/login.js +1 -0
  15. data/app/assets/javascripts/jackpot/payments.js +2 -0
  16. data/app/assets/javascripts/jackpot/subscriptions.js +2 -0
  17. data/app/assets/stylesheets/jackpot/application.css +9 -0
  18. data/app/assets/stylesheets/jackpot/customers.css +4 -0
  19. data/app/assets/stylesheets/jackpot/jackpot.css +10 -0
  20. data/app/controllers/jackpot/application_controller.rb +4 -0
  21. data/app/controllers/jackpot/customers_controller.rb +100 -0
  22. data/app/controllers/jackpot/payments_controller.rb +20 -0
  23. data/app/controllers/jackpot/subscriptions_controller.rb +86 -0
  24. data/app/helpers/jackpot/application_helper.rb +27 -0
  25. data/app/helpers/jackpot/customers_helper.rb +7 -0
  26. data/app/helpers/jackpot/subscriptions_helper.rb +4 -0
  27. data/app/models/jackpot/card.rb +29 -0
  28. data/app/models/jackpot/customer.rb +48 -0
  29. data/app/models/jackpot/gateway.rb +28 -0
  30. data/app/models/jackpot/payment.rb +33 -0
  31. data/app/models/jackpot/subscription.rb +13 -0
  32. data/app/models/jackpot/user.rb +25 -0
  33. data/app/views/jackpot/customers/_credit_card_form.html.erb +42 -0
  34. data/app/views/jackpot/customers/_form.html.erb +17 -0
  35. data/app/views/jackpot/customers/edit.html.erb +13 -0
  36. data/app/views/jackpot/customers/index.html.erb +30 -0
  37. data/app/views/jackpot/customers/new.html.erb +8 -0
  38. data/app/views/jackpot/customers/show.html.erb +32 -0
  39. data/app/views/jackpot/payments/create.html.erb +1 -0
  40. data/app/views/jackpot/payments/index.html.erb +25 -0
  41. data/app/views/jackpot/shared/_flash_messages.html.erb +6 -0
  42. data/app/views/jackpot/shared/_navigation.html.erb +5 -0
  43. data/app/views/jackpot/subscriptions/_form.html.erb +13 -0
  44. data/app/views/jackpot/subscriptions/edit.html.erb +6 -0
  45. data/app/views/jackpot/subscriptions/index.html.erb +29 -0
  46. data/app/views/jackpot/subscriptions/new.html.erb +4 -0
  47. data/app/views/jackpot/subscriptions/show.html.erb +23 -0
  48. data/app/views/layouts/devise.html.erb +22 -0
  49. data/app/views/layouts/jackpot/application.html.erb +39 -0
  50. data/config/initializers/jackpot_devise.rb +226 -0
  51. data/config/locales/devise.en.yml +57 -0
  52. data/config/routes.rb +17 -0
  53. data/db/migrate/20111221002616_create_jackpot_payments.rb +11 -0
  54. data/db/migrate/20111230014003_add_customer_information_to_jackpot_payments.rb +5 -0
  55. data/db/migrate/20120102223341_create_jackpot_subscriptions.rb +10 -0
  56. data/db/migrate/20120103211153_create_jackpot_customers.rb +11 -0
  57. data/db/migrate/20120104164830_add_credit_card_number_to_customer.rb +5 -0
  58. data/db/migrate/20120130173242_add_credit_card_information_to_customers.rb +7 -0
  59. data/db/migrate/20120208191815_add_billing_period_to_jackpot_subscriptions.rb +5 -0
  60. data/db/migrate/20120208191934_add_good_until_date_to_jackpot_customers.rb +6 -0
  61. data/db/migrate/20120209203542_add_subscription_and_customer_to_jackpot_payments.rb +8 -0
  62. data/db/migrate/20120209212043_rename_column_token_in_jackpot_payments.rb +5 -0
  63. data/db/migrate/20120210144038_devise_create_jackpot_users.rb +49 -0
  64. data/jackpot.gemspec +33 -0
  65. data/lib/jackpot.rb +23 -0
  66. data/lib/jackpot/configuration.rb +33 -0
  67. data/lib/jackpot/cron.rb +22 -0
  68. data/lib/jackpot/engine.rb +14 -0
  69. data/lib/jackpot/errors.rb +18 -0
  70. data/lib/jackpot/factory.rb +26 -0
  71. data/lib/jackpot/version.rb +3 -0
  72. data/lib/tasks/jackpot_tasks.rake +38 -0
  73. data/script/rails +6 -0
  74. data/spec/controllers/jackpot/customers_controller_spec.rb +170 -0
  75. data/spec/controllers/jackpot/payments_controller_spec.rb +47 -0
  76. data/spec/controllers/jackpot/subscriptions_controller_spec.rb +153 -0
  77. data/spec/dummy/.gitignore +1 -0
  78. data/spec/dummy/Rakefile +7 -0
  79. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  80. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  81. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  82. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  83. data/spec/dummy/app/mailers/.gitkeep +0 -0
  84. data/spec/dummy/app/models/.gitkeep +0 -0
  85. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  86. data/spec/dummy/config.ru +4 -0
  87. data/spec/dummy/config/application.rb +51 -0
  88. data/spec/dummy/config/boot.rb +10 -0
  89. data/spec/dummy/config/database.yml +17 -0
  90. data/spec/dummy/config/environment.rb +5 -0
  91. data/spec/dummy/config/environments/development.rb +32 -0
  92. data/spec/dummy/config/environments/production.rb +60 -0
  93. data/spec/dummy/config/environments/test.rb +41 -0
  94. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  95. data/spec/dummy/config/initializers/inflections.rb +10 -0
  96. data/spec/dummy/config/initializers/jackpot.rb +13 -0
  97. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  98. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  99. data/spec/dummy/config/initializers/session_store.rb +8 -0
  100. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  101. data/spec/dummy/config/locales/en.yml +5 -0
  102. data/spec/dummy/config/routes.rb +3 -0
  103. data/spec/dummy/db/schema.rb +68 -0
  104. data/spec/dummy/lib/assets/.gitkeep +0 -0
  105. data/spec/dummy/public/404.html +26 -0
  106. data/spec/dummy/public/422.html +26 -0
  107. data/spec/dummy/public/500.html +26 -0
  108. data/spec/dummy/public/favicon.ico +0 -0
  109. data/spec/dummy/public/index.html +5 -0
  110. data/spec/dummy/public/payment.html +36 -0
  111. data/spec/dummy/script/rails +6 -0
  112. data/spec/fixtures/vcr/Create_Customers_To_bill_monthly_my_customers_As_a_user_I_want_to_record_their_billing_information_/assigning_credit_card_information_to_customer.yml +34 -0
  113. data/spec/fixtures/vcr/Jackpot_Customer/_update_credit_card_number/when_card_is_valid/.yml +34 -0
  114. data/spec/fixtures/vcr/Jackpot_Customer/_update_credit_card_number/when_card_is_valid/when_persisting/should_NEVER_persist_in_the_database_the_actual_card_number.yml +34 -0
  115. data/spec/fixtures/vcr/Jackpot_Customer/_update_credit_card_number/when_card_is_valid/when_persisting/should_NEVER_persist_in_the_database_the_verification_value.yml +34 -0
  116. data/spec/fixtures/vcr/Jackpot_Customer/_update_credit_card_number/when_card_is_valid/when_persisting/should_persist_in_the_database_the_ONLY_last_four_digits.yml +34 -0
  117. data/spec/fixtures/vcr/Jackpot_Customer/_update_credit_card_number/when_card_is_valid/when_persisting/should_persist_the_card_information.yml +34 -0
  118. data/spec/fixtures/vcr/Jackpot_Customer/_update_credit_card_number/when_card_is_valid/when_persisting/should_store_this_card_at_the_gateway.yml +34 -0
  119. data/spec/fixtures/vcr/Jackpot_Payment/_create/with_valid_token_information/creates_a_new_payment.yml +96 -0
  120. data/spec/fixtures/vcr/Jackpot_Payment/_create/with_valid_token_information/does_not_persist_credit_card_token_information.yml +96 -0
  121. data/spec/fixtures/vcr/Jackpot_Payment/_create/with_valid_token_information/records_the_payment_transaction_id_for_future_reference.yml +96 -0
  122. data/spec/fixtures/vcr/Jackpot_Payment/_create/with_valid_token_information/records_this_payment_information.yml +96 -0
  123. data/spec/fixtures/vcr/Jackpot_Payment/_customer_name/returns_its_customer_email.yml +96 -0
  124. data/spec/fixtures/vcr/jackpot/customer/updatecard.yml +34 -0
  125. data/spec/fixtures/vcr/jackpot/customer_expiration_date.yml +34 -0
  126. data/spec/fixtures/vcr/jackpot/receiving_payments.yml +96 -0
  127. data/spec/helpers/jackpot/customers_helper_spec.rb +16 -0
  128. data/spec/helpers/jackpot/subscriptions_helper_spec.rb +4 -0
  129. data/spec/lib/cron_spec.rb +39 -0
  130. data/spec/lib/factory_spec.rb +40 -0
  131. data/spec/models/jackpot/card_spec.rb +23 -0
  132. data/spec/models/jackpot/customer_spec.rb +140 -0
  133. data/spec/models/jackpot/gateway_spec.rb +22 -0
  134. data/spec/models/jackpot/payment_spec.rb +74 -0
  135. data/spec/models/jackpot/subscription_spec.rb +19 -0
  136. data/spec/requests/jackpot/jackpot_assign_subscription_to_customer_spec.rb +39 -0
  137. data/spec/requests/jackpot/jackpot_create_customer_spec.rb +73 -0
  138. data/spec/requests/jackpot/jackpot_create_subscriptions_spec.rb +27 -0
  139. data/spec/requests/jackpot/jackpot_receive_payments_spec.rb +34 -0
  140. data/spec/spec_helper.rb +41 -0
  141. data/spec/support/active_merchant.rb +1 -0
  142. data/spec/support/capybara.rb +6 -0
  143. data/spec/support/devise.rb +21 -0
  144. data/spec/support/factories/jackpot_customers.rb +36 -0
  145. data/spec/support/factories/jackpot_payments.rb +7 -0
  146. data/spec/support/factories/jackpot_subscriptions.rb +9 -0
  147. data/spec/support/factories/jackpot_users.rb +9 -0
  148. data/spec/support/helpers.rb +16 -0
  149. data/spec/support/routes.rb +3 -0
  150. data/spec/support/vcr.rb +10 -0
  151. data/vendor/assets/images/twitter/bootstrap/glyphicons-halflings-white.png +0 -0
  152. data/vendor/assets/images/twitter/bootstrap/glyphicons-halflings.png +0 -0
  153. data/vendor/assets/javascripts/twitter/bootstrap.js +12 -0
  154. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-alert.js +91 -0
  155. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-button.js +98 -0
  156. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-carousel.js +154 -0
  157. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-collapse.js +136 -0
  158. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-dropdown.js +92 -0
  159. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-modal.js +209 -0
  160. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-popover.js +95 -0
  161. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-scrollspy.js +125 -0
  162. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-tab.js +130 -0
  163. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-tooltip.js +270 -0
  164. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-transition.js +51 -0
  165. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-typeahead.js +271 -0
  166. data/vendor/assets/stylesheets/twitter/bootstrap/bootstrap-responsive.css +567 -0
  167. data/vendor/assets/stylesheets/twitter/bootstrap/bootstrap.css.erb +3366 -0
  168. metadata +351 -0
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1 @@
1
+ //= jackpot/application
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,9 @@
1
+ /*
2
+ * This is a manifest file that'll automatically include all the stylesheets available in this directory
3
+ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4
+ * the top of the compiled file, but it's generally better to create a new file per style scope.
5
+ *= require formtastic-bootstrap
6
+ *= require_self
7
+ *= require_tree .
8
+
9
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,10 @@
1
+ /*
2
+ *= require twitter/bootstrap/bootstrap
3
+ *= require twitter/bootstrap/bootstrap-responsive
4
+ *= require_self
5
+ */
6
+
7
+ h1 {
8
+ padding-top: 40px;
9
+ }
10
+
@@ -0,0 +1,4 @@
1
+ module Jackpot
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,100 @@
1
+ module Jackpot
2
+ class CustomersController < ApplicationController
3
+ before_filter :authenticate_user!
4
+
5
+ # PUT /customers/37/credit_card
6
+ # Assigns a credit card to the given customer
7
+ def credit_card
8
+ @customer = Customer.find params[:id]
9
+ @customer.update_credit_card Card.new params[:credit_card]
10
+
11
+ respond_to do |format|
12
+ format.html { redirect_to @customer,
13
+ notice: "This customer's card was successfully updated." }
14
+ format.json { head :ok }
15
+ end
16
+ end
17
+
18
+ # GET /customers
19
+ # GET /customers.json
20
+ def index
21
+ @customers = Customer.all
22
+
23
+ respond_to do |format|
24
+ format.html # index.html.erb
25
+ format.json { render json: @customers }
26
+ end
27
+ end
28
+
29
+ # GET /customers/1
30
+ # GET /customers/1.json
31
+ def show
32
+ @customer = Customer.find(params[:id])
33
+
34
+ respond_to do |format|
35
+ format.html # show.html.erb
36
+ format.json { render json: @customer }
37
+ end
38
+ end
39
+
40
+ # GET /customers/new
41
+ # GET /customers/new.json
42
+ def new
43
+ @customer = Customer.new
44
+
45
+ respond_to do |format|
46
+ format.html # new.html.erb
47
+ format.json { render json: @customer }
48
+ end
49
+ end
50
+
51
+ # GET /customers/1/edit
52
+ def edit
53
+ @customer = Customer.find(params[:id])
54
+ end
55
+
56
+ # POST /customers
57
+ # POST /customers.json
58
+ def create
59
+ @customer = Customer.new(params[:customer])
60
+
61
+ respond_to do |format|
62
+ if @customer.save
63
+ format.html { redirect_to @customer, notice: 'Customer was successfully created.' }
64
+ format.json { render json: @customer, status: :created, location: @customer }
65
+ else
66
+ format.html { render action: "new" }
67
+ format.json { render json: @customer.errors, status: :unprocessable_entity }
68
+ end
69
+ end
70
+ end
71
+
72
+ # PUT /customers/1
73
+ # PUT /customers/1.json
74
+ def update
75
+ @customer = Customer.find(params[:id])
76
+
77
+ respond_to do |format|
78
+ if @customer.update_attributes(params[:customer])
79
+ format.html { redirect_to @customer, notice: 'Customer was successfully updated.' }
80
+ format.json { head :ok }
81
+ else
82
+ format.html { render action: "edit" }
83
+ format.json { render json: @customer.errors, status: :unprocessable_entity }
84
+ end
85
+ end
86
+ end
87
+
88
+ # DELETE /customers/1
89
+ # DELETE /customers/1.json
90
+ def destroy
91
+ @customer = Customer.find(params[:id])
92
+ @customer.destroy
93
+
94
+ respond_to do |format|
95
+ format.html { redirect_to customers_url }
96
+ format.json { head :ok }
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,20 @@
1
+ module Jackpot
2
+ class PaymentsController < ApplicationController
3
+ before_filter :authenticate_user!
4
+
5
+ def create
6
+ @customer = Jackpot::Customer.find params[:customer_id]
7
+
8
+ respond_to do |format|
9
+ if @customer.pay_subscription
10
+ format.html { redirect_to(payments_url, notice: "Payment recorded successfully")}
11
+ end
12
+ end
13
+ end
14
+
15
+ def index
16
+ @payments = Payment.all
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,86 @@
1
+ module Jackpot
2
+ class SubscriptionsController < ApplicationController
3
+ before_filter :authenticate_user!
4
+ # GET /subscriptions
5
+ # GET /subscriptions.json
6
+ def index
7
+ @subscriptions = Subscription.all
8
+
9
+ respond_to do |format|
10
+ format.html # index.html.erb
11
+ format.json { render json: @subscriptions }
12
+ end
13
+ end
14
+
15
+ # GET /subscriptions/1
16
+ # GET /subscriptions/1.json
17
+ def show
18
+ @subscription = Subscription.find(params[:id])
19
+
20
+ respond_to do |format|
21
+ format.html # show.html.erb
22
+ format.json { render json: @subscription }
23
+ end
24
+ end
25
+
26
+ # GET /subscriptions/new
27
+ # GET /subscriptions/new.json
28
+ def new
29
+ @subscription = Subscription.new
30
+
31
+ respond_to do |format|
32
+ format.html # new.html.erb
33
+ format.json { render json: @subscription }
34
+ end
35
+ end
36
+
37
+ # GET /subscriptions/1/edit
38
+ def edit
39
+ @subscription = Subscription.find(params[:id])
40
+ end
41
+
42
+ # POST /subscriptions
43
+ # POST /subscriptions.json
44
+ def create
45
+ @subscription = Subscription.new(params[:subscription])
46
+
47
+ respond_to do |format|
48
+ if @subscription.save
49
+ format.html { redirect_to @subscription, notice: 'Subscription was successfully created.' }
50
+ format.json { render json: @subscription, status: :created, location: @subscription }
51
+ else
52
+ format.html { render action: "new" }
53
+ format.json { render json: @subscription.errors, status: :unprocessable_entity }
54
+ end
55
+ end
56
+ end
57
+
58
+ # PUT /subscriptions/1
59
+ # PUT /subscriptions/1.json
60
+ def update
61
+ @subscription = Subscription.find(params[:id])
62
+
63
+ respond_to do |format|
64
+ if @subscription.update_attributes(params[:subscription])
65
+ format.html { redirect_to @subscription, notice: 'Subscription was successfully updated.' }
66
+ format.json { head :ok }
67
+ else
68
+ format.html { render action: "edit" }
69
+ format.json { render json: @subscription.errors, status: :unprocessable_entity }
70
+ end
71
+ end
72
+ end
73
+
74
+ # DELETE /subscriptions/1
75
+ # DELETE /subscriptions/1.json
76
+ def destroy
77
+ @subscription = Subscription.find(params[:id])
78
+ @subscription.destroy
79
+
80
+ respond_to do |format|
81
+ format.html { redirect_to subscriptions_url }
82
+ format.json { head :ok }
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,27 @@
1
+ module Jackpot
2
+ module ApplicationHelper
3
+ def twitterized_type(type)
4
+ case type
5
+ when :alert
6
+ "alert"
7
+ when :error
8
+ "alert alert-error"
9
+ when :notice
10
+ "alert alert-success"
11
+ when :info
12
+ "alert alert-info"
13
+ else
14
+ type.to_s
15
+ end
16
+ end
17
+
18
+ def navbar_entry(name, options = {}, html_options = {}, &block)
19
+ if current_page?(options)
20
+ content_tag("li", class: "active") { link_to(name, options, html_options, &block) }
21
+ else
22
+ content_tag("li") { link_to(name, options, html_options, &block) }
23
+ end
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,7 @@
1
+ module Jackpot
2
+ module CustomersHelper
3
+ def subscription_name_when_available(customer)
4
+ (customer.subscription.present?) ? customer.subscription.name : "-"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ module Jackpot
2
+ module SubscriptionsHelper
3
+ end
4
+ end
@@ -0,0 +1,29 @@
1
+ module Jackpot
2
+
3
+ # A simple decorator to Active Merchant's Card.
4
+ #
5
+ class Card
6
+ def initialize(card_hash)
7
+ @component = ActiveMerchant::Billing::CreditCard.new(HashWithIndifferentAccess.new(card_hash))
8
+ end
9
+
10
+ def method_missing(meth, *args)
11
+ if @component.respond_to?(meth)
12
+ @component.send(meth, *args)
13
+ else
14
+ super
15
+ end
16
+ end
17
+
18
+ def respond_to?(meth)
19
+ unless @component.respond_to?(meth)
20
+ super.respond_to? meth
21
+ end
22
+ end
23
+
24
+ def masquerade_number
25
+ "XXXX-XXXX-XXXX-#{number.last(4)}"
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,48 @@
1
+ module Jackpot
2
+ class Customer < ActiveRecord::Base
3
+ belongs_to :subscription
4
+ has_many :payments, :through => :subscription
5
+ attr_protected :credit_card_number
6
+ attr_protected :credit_card_expiry_year
7
+ attr_protected :credit_card_expiry_month
8
+ attr_protected :credit_card_token
9
+
10
+ scope :due_in , lambda { |number_of_days| where("good_until <= ?",
11
+ number_of_days.days.from_now) }
12
+
13
+ scope :overdue , where("good_until < ? ", Date.today)
14
+
15
+
16
+ attr_accessor :credit_card_verification_value
17
+
18
+ def pay_subscription
19
+ if credit_card_token
20
+ if subscription.charge(self)
21
+ update_attribute(:good_until, Date.today + 1.month)
22
+ end
23
+ else
24
+ raise Jackpot::Errors::CustomerHasNoCardSaved.new
25
+ end
26
+ end
27
+
28
+
29
+ def update_credit_card(card)
30
+ raise Errors::CardIsInvalid unless card.valid?
31
+ write_attribute :credit_card_number , card.masquerade_number
32
+ write_attribute :credit_card_expiry_month , card.month
33
+ write_attribute :credit_card_expiry_year , card.year
34
+
35
+ # This should never be recorded
36
+ self.credit_card_verification_value = card.verification_value
37
+ stored_card_response = Jackpot::Payment.gateway.store(card)
38
+ write_attribute :credit_card_token , stored_card_response.params["customer_vault_id"]
39
+
40
+ save
41
+ end
42
+
43
+ def expiration_date
44
+ "#{credit_card_expiry_month}/#{credit_card_expiry_year}"
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,28 @@
1
+ module Jackpot
2
+
3
+ # Small adapter for Active Merchant gateways Jackpot supports
4
+ class Gateway
5
+
6
+ def initialize(gateway)
7
+ @gateway = gateway
8
+ end
9
+
10
+ def method_missing(meth, *args)
11
+ if @gateway.respond_to?(meth)
12
+ @gateway.send(meth, *args)
13
+ else
14
+ super
15
+ end
16
+ end
17
+
18
+ # TODO: Remove this ugly hack and move to a lighterweight PORO decorator approach
19
+ def capture(money, authorization, options = {})
20
+ @gateway.capture(money, authorization, options)
21
+ end
22
+
23
+ def respond_to?(meth)
24
+ @gateway.respond_to?(meth)
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ module Jackpot
2
+ class Payment < ActiveRecord::Base
3
+ before_create :perform_payment
4
+
5
+ attr_accessor :credit_card
6
+ attr_accessor :credit_card_token
7
+
8
+ belongs_to :subscription
9
+ belongs_to :customer
10
+
11
+ cattr_accessor :gateway
12
+
13
+ def perform_payment
14
+ credit_card_token = customer.credit_card_token
15
+ if credit_card_token
16
+ self.amount = self.subscription.price
17
+ response = Jackpot::Payment.gateway.authorize self.amount, credit_card_token
18
+ if response.success?
19
+ billing_response = Jackpot::Payment.gateway.capture(self.amount,
20
+ response.authorization)
21
+
22
+ self.payment_transaction_token = billing_response.params['transactionid']
23
+ else
24
+ raise Jackpot::Errors::UnauthorizedPayment.new
25
+ end
26
+ end
27
+ end
28
+
29
+ def customer_email
30
+ customer.email
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ module Jackpot
2
+ class Subscription < ActiveRecord::Base
3
+ has_many :customers
4
+ has_many :payments
5
+
6
+ validates_presence_of :name
7
+
8
+
9
+ def charge(customer_to_be_charged)
10
+ payments.create(:customer => customer_to_be_charged)
11
+ end
12
+ end
13
+ end