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.
- data/.gitignore +16 -0
- data/.rspec +1 -0
- data/.rvmrc.example +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +181 -0
- data/MIT-LICENSE +20 -0
- data/README.md +134 -0
- data/Rakefile +25 -0
- data/app/assets/images/jackpot/.gitkeep +0 -0
- data/app/assets/javascripts/jackpot/application.js +5 -0
- data/app/assets/javascripts/jackpot/bootstrap.js +32 -0
- data/app/assets/javascripts/jackpot/customers.js +2 -0
- data/app/assets/javascripts/jackpot/login.js +1 -0
- data/app/assets/javascripts/jackpot/payments.js +2 -0
- data/app/assets/javascripts/jackpot/subscriptions.js +2 -0
- data/app/assets/stylesheets/jackpot/application.css +9 -0
- data/app/assets/stylesheets/jackpot/customers.css +4 -0
- data/app/assets/stylesheets/jackpot/jackpot.css +10 -0
- data/app/controllers/jackpot/application_controller.rb +4 -0
- data/app/controllers/jackpot/customers_controller.rb +100 -0
- data/app/controllers/jackpot/payments_controller.rb +20 -0
- data/app/controllers/jackpot/subscriptions_controller.rb +86 -0
- data/app/helpers/jackpot/application_helper.rb +27 -0
- data/app/helpers/jackpot/customers_helper.rb +7 -0
- data/app/helpers/jackpot/subscriptions_helper.rb +4 -0
- data/app/models/jackpot/card.rb +29 -0
- data/app/models/jackpot/customer.rb +48 -0
- data/app/models/jackpot/gateway.rb +28 -0
- data/app/models/jackpot/payment.rb +33 -0
- data/app/models/jackpot/subscription.rb +13 -0
- data/app/models/jackpot/user.rb +25 -0
- data/app/views/jackpot/customers/_credit_card_form.html.erb +42 -0
- data/app/views/jackpot/customers/_form.html.erb +17 -0
- data/app/views/jackpot/customers/edit.html.erb +13 -0
- data/app/views/jackpot/customers/index.html.erb +30 -0
- data/app/views/jackpot/customers/new.html.erb +8 -0
- data/app/views/jackpot/customers/show.html.erb +32 -0
- data/app/views/jackpot/payments/create.html.erb +1 -0
- data/app/views/jackpot/payments/index.html.erb +25 -0
- data/app/views/jackpot/shared/_flash_messages.html.erb +6 -0
- data/app/views/jackpot/shared/_navigation.html.erb +5 -0
- data/app/views/jackpot/subscriptions/_form.html.erb +13 -0
- data/app/views/jackpot/subscriptions/edit.html.erb +6 -0
- data/app/views/jackpot/subscriptions/index.html.erb +29 -0
- data/app/views/jackpot/subscriptions/new.html.erb +4 -0
- data/app/views/jackpot/subscriptions/show.html.erb +23 -0
- data/app/views/layouts/devise.html.erb +22 -0
- data/app/views/layouts/jackpot/application.html.erb +39 -0
- data/config/initializers/jackpot_devise.rb +226 -0
- data/config/locales/devise.en.yml +57 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20111221002616_create_jackpot_payments.rb +11 -0
- data/db/migrate/20111230014003_add_customer_information_to_jackpot_payments.rb +5 -0
- data/db/migrate/20120102223341_create_jackpot_subscriptions.rb +10 -0
- data/db/migrate/20120103211153_create_jackpot_customers.rb +11 -0
- data/db/migrate/20120104164830_add_credit_card_number_to_customer.rb +5 -0
- data/db/migrate/20120130173242_add_credit_card_information_to_customers.rb +7 -0
- data/db/migrate/20120208191815_add_billing_period_to_jackpot_subscriptions.rb +5 -0
- data/db/migrate/20120208191934_add_good_until_date_to_jackpot_customers.rb +6 -0
- data/db/migrate/20120209203542_add_subscription_and_customer_to_jackpot_payments.rb +8 -0
- data/db/migrate/20120209212043_rename_column_token_in_jackpot_payments.rb +5 -0
- data/db/migrate/20120210144038_devise_create_jackpot_users.rb +49 -0
- data/jackpot.gemspec +33 -0
- data/lib/jackpot.rb +23 -0
- data/lib/jackpot/configuration.rb +33 -0
- data/lib/jackpot/cron.rb +22 -0
- data/lib/jackpot/engine.rb +14 -0
- data/lib/jackpot/errors.rb +18 -0
- data/lib/jackpot/factory.rb +26 -0
- data/lib/jackpot/version.rb +3 -0
- data/lib/tasks/jackpot_tasks.rake +38 -0
- data/script/rails +6 -0
- data/spec/controllers/jackpot/customers_controller_spec.rb +170 -0
- data/spec/controllers/jackpot/payments_controller_spec.rb +47 -0
- data/spec/controllers/jackpot/subscriptions_controller_spec.rb +153 -0
- data/spec/dummy/.gitignore +1 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +51 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +17 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +32 -0
- data/spec/dummy/config/environments/production.rb +60 -0
- data/spec/dummy/config/environments/test.rb +41 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/jackpot.rb +13 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/db/schema.rb +68 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/index.html +5 -0
- data/spec/dummy/public/payment.html +36 -0
- data/spec/dummy/script/rails +6 -0
- 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
- data/spec/fixtures/vcr/Jackpot_Customer/_update_credit_card_number/when_card_is_valid/.yml +34 -0
- 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
- 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
- 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
- data/spec/fixtures/vcr/Jackpot_Customer/_update_credit_card_number/when_card_is_valid/when_persisting/should_persist_the_card_information.yml +34 -0
- 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
- data/spec/fixtures/vcr/Jackpot_Payment/_create/with_valid_token_information/creates_a_new_payment.yml +96 -0
- data/spec/fixtures/vcr/Jackpot_Payment/_create/with_valid_token_information/does_not_persist_credit_card_token_information.yml +96 -0
- data/spec/fixtures/vcr/Jackpot_Payment/_create/with_valid_token_information/records_the_payment_transaction_id_for_future_reference.yml +96 -0
- data/spec/fixtures/vcr/Jackpot_Payment/_create/with_valid_token_information/records_this_payment_information.yml +96 -0
- data/spec/fixtures/vcr/Jackpot_Payment/_customer_name/returns_its_customer_email.yml +96 -0
- data/spec/fixtures/vcr/jackpot/customer/updatecard.yml +34 -0
- data/spec/fixtures/vcr/jackpot/customer_expiration_date.yml +34 -0
- data/spec/fixtures/vcr/jackpot/receiving_payments.yml +96 -0
- data/spec/helpers/jackpot/customers_helper_spec.rb +16 -0
- data/spec/helpers/jackpot/subscriptions_helper_spec.rb +4 -0
- data/spec/lib/cron_spec.rb +39 -0
- data/spec/lib/factory_spec.rb +40 -0
- data/spec/models/jackpot/card_spec.rb +23 -0
- data/spec/models/jackpot/customer_spec.rb +140 -0
- data/spec/models/jackpot/gateway_spec.rb +22 -0
- data/spec/models/jackpot/payment_spec.rb +74 -0
- data/spec/models/jackpot/subscription_spec.rb +19 -0
- data/spec/requests/jackpot/jackpot_assign_subscription_to_customer_spec.rb +39 -0
- data/spec/requests/jackpot/jackpot_create_customer_spec.rb +73 -0
- data/spec/requests/jackpot/jackpot_create_subscriptions_spec.rb +27 -0
- data/spec/requests/jackpot/jackpot_receive_payments_spec.rb +34 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/support/active_merchant.rb +1 -0
- data/spec/support/capybara.rb +6 -0
- data/spec/support/devise.rb +21 -0
- data/spec/support/factories/jackpot_customers.rb +36 -0
- data/spec/support/factories/jackpot_payments.rb +7 -0
- data/spec/support/factories/jackpot_subscriptions.rb +9 -0
- data/spec/support/factories/jackpot_users.rb +9 -0
- data/spec/support/helpers.rb +16 -0
- data/spec/support/routes.rb +3 -0
- data/spec/support/vcr.rb +10 -0
- data/vendor/assets/images/twitter/bootstrap/glyphicons-halflings-white.png +0 -0
- data/vendor/assets/images/twitter/bootstrap/glyphicons-halflings.png +0 -0
- data/vendor/assets/javascripts/twitter/bootstrap.js +12 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-alert.js +91 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-button.js +98 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-carousel.js +154 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-collapse.js +136 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-dropdown.js +92 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-modal.js +209 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-popover.js +95 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-scrollspy.js +125 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-tab.js +130 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-tooltip.js +270 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-transition.js +51 -0
- data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-typeahead.js +271 -0
- data/vendor/assets/stylesheets/twitter/bootstrap/bootstrap-responsive.css +567 -0
- data/vendor/assets/stylesheets/twitter/bootstrap/bootstrap.css.erb +3366 -0
- metadata +351 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//= jackpot/application
|
|
@@ -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,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,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
|