paid_up 0.1.0
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.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +46 -0
- data/LICENSE.txt +20 -0
- data/MIT-LICENSE +20 -0
- data/README.md +64 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/app/controllers/paid_up/paid_up_controller.rb +12 -0
- data/app/controllers/paid_up/plans_controller.rb +7 -0
- data/app/controllers/paid_up/subscriptions_controller.rb +37 -0
- data/app/helpers/paid_up/features_helper.rb +65 -0
- data/app/helpers/paid_up/paid_up_helper.rb +14 -0
- data/app/helpers/paid_up/plans_helper.rb +53 -0
- data/app/helpers/paid_up/subscriptions_helper.rb +21 -0
- data/app/models/ability.rb +37 -0
- data/app/models/paid_up/feature.rb +19 -0
- data/app/models/paid_up/features_plan.rb +14 -0
- data/app/models/paid_up/plan.rb +99 -0
- data/app/views/devise/confirmations/new.html.haml +13 -0
- data/app/views/devise/passwords/edit.html.haml +19 -0
- data/app/views/devise/passwords/new.html.haml +14 -0
- data/app/views/devise/registrations/_new_form.html.haml +23 -0
- data/app/views/devise/registrations/edit.html.haml +39 -0
- data/app/views/devise/registrations/new.html.haml +11 -0
- data/app/views/devise/sessions/_new_form.html.haml +21 -0
- data/app/views/devise/sessions/new.html.haml +11 -0
- data/app/views/devise/shared/_links.html.haml +14 -0
- data/app/views/devise/unlocks/new.html.haml +14 -0
- data/app/views/paid_up/features/_abilities_table.html.haml +22 -0
- data/app/views/paid_up/features/_table.html.haml +16 -0
- data/app/views/paid_up/plans/index.html.haml +18 -0
- data/app/views/paid_up/subscriptions/index.html.haml +16 -0
- data/app/views/paid_up/subscriptions/new.html.haml +101 -0
- data/bin/rails +12 -0
- data/config/initializers/stripe.rb +6 -0
- data/config/locales/en.yml +85 -0
- data/config/routes.rb +7 -0
- data/coverage/.last_run.json +5 -0
- data/coverage/.resultset.json +1488 -0
- data/coverage/.resultset.json.lock +0 -0
- data/db/migrate/20150407105900_create_paid_up_features_plans_table.rb +9 -0
- data/db/migrate/20150407110100_create_paid_up_features_table.rb +11 -0
- data/db/migrate/20150407110101_create_paid_up_plans_table.rb +14 -0
- data/lib/generators/paid_up/install/install_generator.rb +59 -0
- data/lib/generators/paid_up/install/templates/initializer.rb.erb +5 -0
- data/lib/generators/paid_up/utils.rb +16 -0
- data/lib/paid_up/configuration.rb +22 -0
- data/lib/paid_up/engine.rb +17 -0
- data/lib/paid_up/integer.rb +9 -0
- data/lib/paid_up/localization.rb +31 -0
- data/lib/paid_up/mixins.rb +139 -0
- data/lib/paid_up/railtie.rb +4 -0
- data/lib/paid_up/stripe_extensions.rb +17 -0
- data/lib/paid_up/table_validator.rb +9 -0
- data/lib/paid_up/unlimited.rb +17 -0
- data/lib/paid_up/version.rb +7 -0
- data/lib/paid_up.rb +27 -0
- data/paid_up.gemspec +248 -0
- data/spec/controllers/paid_up/plans_spec.rb +26 -0
- data/spec/controllers/paid_up/subscriptions_spec.rb +187 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +16 -0
- data/spec/dummy/app/assets/stylesheets/application.css.scss +16 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/models/group.rb +3 -0
- data/spec/dummy/app/models/user.rb +9 -0
- data/spec/dummy/app/views/layouts/application.html.haml +31 -0
- data/spec/dummy/app/views/pages/index.html.haml +1 -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/bin/setup +29 -0
- data/spec/dummy/config/application.rb +32 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +46 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +45 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/devise.rb +259 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/high_voltage.rb +3 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/paid_up.rb +5 -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/devise.en.yml +60 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20150406154440_create_users_table.rb +7 -0
- data/spec/dummy/db/migrate/20150517175135_create_groups_table.rb +11 -0
- data/spec/dummy/db/migrate/20150518000915_add_devise_to_users.rb +49 -0
- data/spec/dummy/db/migrate/20150518000917_create_paid_up_features_plans_table.paid_up.rb +10 -0
- data/spec/dummy/db/migrate/20150518000918_create_paid_up_features_table.paid_up.rb +12 -0
- data/spec/dummy/db/migrate/20150518000919_create_paid_up_plans_table.paid_up.rb +15 -0
- data/spec/dummy/db/migrate/20150518000920_add_stripe_id_column_to_user.rb +6 -0
- data/spec/dummy/db/schema.rb +75 -0
- data/spec/dummy/db/seeds/features.seeds.rb +19 -0
- data/spec/dummy/db/seeds/features_plans.seeds.rb +51 -0
- data/spec/dummy/db/seeds/plans.seeds.rb +91 -0
- data/spec/dummy/db/seeds.rb +0 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/log/development.log +108393 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/assets/.sprockets-manifest-34b01376fc56586f4f4fd19e7b1c0e35.json +1 -0
- data/spec/dummy/public/assets/application-27f004bb902952dbbaad25f0f28c312f29ffee315c94fa51dea6b5ec6dc993e6.css +13 -0
- data/spec/dummy/public/assets/application-3a226fbacd7ba9a2b9f7972fafdd7b2486c34707d96a60c26f3bbe4579c29ca6.js +116 -0
- data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-13634da87d9e23f8c3ed9108ce1724d183a39ad072e73e1b3d8cbf646d2d0407.eot +0 -0
- data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-42f60659d265c1a3c30f9fa42abcbb56bd4a53af4d83d316d6dd7a36903c43e5.svg +288 -0
- data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-a26394f7ede100ca118eff2eda08596275a9839b959c226e15439557a5a80742.woff +0 -0
- data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-e395044093757d82afcb138957d06a1ea9361bdcf0b442d06a18a8051af57456.ttf +0 -0
- data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-fe185d11a49676890d47bb783312a0cda5a44c4039214094e7957b4c040ef11c.woff2 +0 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/test/controllers/plans_controller_controller_test.rb +7 -0
- data/spec/factories/feature.rb +7 -0
- data/spec/factories/features_plan.rb +7 -0
- data/spec/factories/plan.rb +7 -0
- data/spec/factories/user.rb +7 -0
- data/spec/models/paid_up/feature_spec.rb +21 -0
- data/spec/models/paid_up/features_plan_spec.rb +7 -0
- data/spec/models/paid_up/plan_spec.rb +156 -0
- data/spec/models/user_spec.rb +304 -0
- data/spec/paid_up_spec.rb +7 -0
- data/spec/rails_helper.rb +65 -0
- data/spec/routing/paid_up/plans_spec.rb +11 -0
- data/spec/routing/paid_up/subscription_spec.rb +23 -0
- data/spec/spec_helper.rb +87 -0
- data/spec/support/controller_macros.rb +12 -0
- data/spec/support/factory_girl.rb +3 -0
- data/spec/support/plans_and_features.rb +209 -0
- data/spec/support/stripe.rb +23 -0
- data/spec/support/subscribers.rb +44 -0
- data/spec/views/paid_up/plans_spec.rb +54 -0
- data/spec/views/paid_up/subscriptions_spec.rb +58 -0
- metadata +488 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: 'form-horizontal' }) do |f|
|
|
2
|
+
= devise_error_messages!
|
|
3
|
+
.form-group
|
|
4
|
+
= f.label :email, class: 'col-sm-2 control-label'
|
|
5
|
+
.col-sm-8
|
|
6
|
+
= f.email_field :email, autofocus: true, class: 'col-sm-offset-2 form-control'
|
|
7
|
+
.form-group
|
|
8
|
+
= f.label :password, class: 'col-sm-2 control-label'
|
|
9
|
+
.col-sm-8
|
|
10
|
+
= f.password_field :password, autocomplete: "off", autofocus: true, class: 'col-sm-offset-2 form-control'
|
|
11
|
+
- if @validatable
|
|
12
|
+
.col-sm-8
|
|
13
|
+
.col-sm-offset-2
|
|
14
|
+
%em= :length_characters_minimum.l length: @minimum_password_length
|
|
15
|
+
.form-group
|
|
16
|
+
= f.label :password_confirmation, class: 'col-sm-2 control-label'
|
|
17
|
+
.col-sm-8
|
|
18
|
+
= f.password_field :password_confirmation, autocomplete: "off", class: 'col-sm-offset-2 form-control'
|
|
19
|
+
.form-group
|
|
20
|
+
.col-sm-2
|
|
21
|
+
.col-sm-8
|
|
22
|
+
.col-sm-offset-2
|
|
23
|
+
= f.submit :sign_up.l, class: 'form-control btn btn-primary'
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
- add_title :edit_resource.l resource: resource_name.to_s.humanize
|
|
2
|
+
|
|
3
|
+
= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'form-horizontal' } ) do |f|
|
|
4
|
+
= devise_error_messages!
|
|
5
|
+
.form-group
|
|
6
|
+
= f.label :email, class: 'control-label col-sm-2'
|
|
7
|
+
.col-sm-2
|
|
8
|
+
= f.email_field :email, autofocus: true, class: 'form-control col-sm-offset-2'
|
|
9
|
+
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
|
|
10
|
+
.alert-warning= :currently_awaiting_confirmation_for_resource.l resource: resource.unconfirmed_email
|
|
11
|
+
.form-group
|
|
12
|
+
= f.label :password, class: 'control-label col-sm-2'
|
|
13
|
+
.col-sm-2
|
|
14
|
+
= f.password_field :password, autocomplete: "off", class: 'form-control col-sm-offset-2'
|
|
15
|
+
.col-sm-2
|
|
16
|
+
.col-sm-offset-2
|
|
17
|
+
%i= :leave_blank_if_you_dont_want_to_change_it.l
|
|
18
|
+
.form-group
|
|
19
|
+
= f.label :password_confirmation, class: 'control-label col-sm-2'
|
|
20
|
+
.col-sm-2
|
|
21
|
+
= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control col-sm-offset-2'
|
|
22
|
+
.form-group
|
|
23
|
+
= f.label :current_password, class: 'control-label col-sm-2'
|
|
24
|
+
.col-sm-2
|
|
25
|
+
= f.password_field :current_password, autocomplete: "off", class: 'form-control col-sm-offset-2'
|
|
26
|
+
.col-sm-2
|
|
27
|
+
.col-sm-offset-2
|
|
28
|
+
%i= :we_need_your_current_password_to_confirm_your_changes.l
|
|
29
|
+
.form-group
|
|
30
|
+
.col-sm-2
|
|
31
|
+
.col-sm-2
|
|
32
|
+
.col-sm-offset-2
|
|
33
|
+
= f.submit :update_account.l, class: 'form-control btn btn-primary'
|
|
34
|
+
|
|
35
|
+
%hr
|
|
36
|
+
%h2= :cancel_my_account.l
|
|
37
|
+
%p
|
|
38
|
+
= :unhappy.l
|
|
39
|
+
= button_to :cancel_my_account.l, registration_path(resource_name), data: { confirm: :are_you_sure.l }, method: :delete, class: 'btn btn-danger'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: 'form-horizontal' }) do |f|
|
|
2
|
+
.form-group
|
|
3
|
+
= f.label :email, class: 'col-sm-2 control-label'
|
|
4
|
+
.col-sm-8
|
|
5
|
+
= f.email_field :email, autofocus: true, class: 'col-sm-offset-2 form-control'
|
|
6
|
+
.form-group
|
|
7
|
+
= f.label :password, class: 'col-sm-2 control-label'
|
|
8
|
+
.col-sm-8
|
|
9
|
+
= f.password_field :password, autocomplete: "off", class: 'col-sm-offset-2 form-control'
|
|
10
|
+
- if devise_mapping.rememberable?
|
|
11
|
+
.form-group
|
|
12
|
+
.col-sm-2
|
|
13
|
+
.col-sm-8
|
|
14
|
+
.col-sm-offset-2.checkbox
|
|
15
|
+
= f.check_box :remember_me
|
|
16
|
+
= f.label :remember_me
|
|
17
|
+
.form-group
|
|
18
|
+
.col-sm-2
|
|
19
|
+
.col-sm-8
|
|
20
|
+
.col-sm-offset-2
|
|
21
|
+
= f.submit :sign_in.l, class: 'form-control btn btn-primary'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
= nav_list class: 'nav-stacked nav-pills' do
|
|
2
|
+
- if controller_name != 'sessions'
|
|
3
|
+
= nav_item :sign_in.l, new_session_path(resource_name)
|
|
4
|
+
- if devise_mapping.registerable? && controller_name != 'registrations'
|
|
5
|
+
= nav_item :sign_up.l, new_registration_path(resource_name)
|
|
6
|
+
- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
|
|
7
|
+
= nav_item :forgot_your_password.l, new_password_path(resource_name)
|
|
8
|
+
- if devise_mapping.confirmable? && controller_name != 'confirmations'
|
|
9
|
+
= nav_item :didnt_receive_confirmation_instructions.l, new_confirmation_path(resource_name)
|
|
10
|
+
- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
|
|
11
|
+
= nav_item :didnt_receive_unlock_instructions.l, new_unlock_path(resource_name)
|
|
12
|
+
- if devise_mapping.omniauthable?
|
|
13
|
+
- resource_class.omniauth_providers.each do |provider|
|
|
14
|
+
= nav_item :sign_in_with_provider.l(provider: provider), omniauth_authorize_path(resource_name, provider)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
- add_title :resend_unlock_instructions.l
|
|
2
|
+
= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f|
|
|
3
|
+
= devise_error_messages!
|
|
4
|
+
.form-group
|
|
5
|
+
= f.label :email, class: 'col-sm-2 control-label'
|
|
6
|
+
.col-sm-2
|
|
7
|
+
= f.email_field :email, autofocus: true, class: 'col-sm-offset-2 form-control'
|
|
8
|
+
.form-group
|
|
9
|
+
.col-sm-2
|
|
10
|
+
.col-sm-2
|
|
11
|
+
.col-sm-offset-2
|
|
12
|
+
= f.submit :resend_unlock_instructions.l
|
|
13
|
+
- add_widget do
|
|
14
|
+
= render "devise/shared/links"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
%table.abilities.table.table-bordered{ html_options }
|
|
2
|
+
- for feature in features
|
|
3
|
+
%tr{ id: feature.name + '_ability'}
|
|
4
|
+
%th= feature.title
|
|
5
|
+
%td
|
|
6
|
+
- case feature.setting_type
|
|
7
|
+
- when 'boolean'
|
|
8
|
+
- if can? :use, feature.name.to_sym
|
|
9
|
+
= icon 'ok'
|
|
10
|
+
- else
|
|
11
|
+
= icon 'remove'
|
|
12
|
+
- when 'table_rows'
|
|
13
|
+
- if can? :own, feature.feature_model
|
|
14
|
+
= icon 'ok'
|
|
15
|
+
- else
|
|
16
|
+
= icon 'remove'
|
|
17
|
+
- if current_user.table_rows_unlimited?(feature.name)
|
|
18
|
+
= :unlimited.l
|
|
19
|
+
- else
|
|
20
|
+
= :x_of_y_remaining.l x: current_user.table_rows_remaining(feature.name), y: current_user.table_rows_allowed(feature.name)
|
|
21
|
+
- else
|
|
22
|
+
= :error.l
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
%table.feature_comparison.table.table-bordered{ html_options }
|
|
2
|
+
%tr
|
|
3
|
+
%th= :plan_name.l
|
|
4
|
+
%th= :cost.l
|
|
5
|
+
- for feature in features
|
|
6
|
+
%th= feature.title
|
|
7
|
+
- if should_add_buttons
|
|
8
|
+
%th= :subscribe.l
|
|
9
|
+
- for plan in plans
|
|
10
|
+
%tr{ class: highlight_plan == plan ? 'info' : ''}
|
|
11
|
+
%td= plan.name
|
|
12
|
+
%td= plan_charge_human plan
|
|
13
|
+
- for feature in features
|
|
14
|
+
%td= feature_display feature, plan
|
|
15
|
+
- if should_add_buttons
|
|
16
|
+
%td= plan_button plan
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
- add_title 'Subscription Plan Pricing'
|
|
2
|
+
|
|
3
|
+
.plans.row
|
|
4
|
+
- for plan in @plans
|
|
5
|
+
.plan.col-md-3
|
|
6
|
+
.well
|
|
7
|
+
%h2
|
|
8
|
+
= plan.name
|
|
9
|
+
.small= plan_charge_human plan
|
|
10
|
+
%p= plan.description.html_safe
|
|
11
|
+
%div{class:plan.name.gsub(' ',"_").downcase+'_subscribe_button'}
|
|
12
|
+
= plan_button plan
|
|
13
|
+
%h2= :features.l
|
|
14
|
+
.table-responsive
|
|
15
|
+
- if user_signed_in?
|
|
16
|
+
= features_table highlight: current_user.plan
|
|
17
|
+
- else
|
|
18
|
+
= features_table
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
- add_title :my_subscription_information.l
|
|
2
|
+
|
|
3
|
+
%h2
|
|
4
|
+
= current_user.plan.name
|
|
5
|
+
.small= plan_charge_human current_user.plan
|
|
6
|
+
|
|
7
|
+
= subscription_dl current_user.subscription
|
|
8
|
+
|
|
9
|
+
- if current_user.subscription.cancel_at_period_end
|
|
10
|
+
%h3= :canceled.l
|
|
11
|
+
|
|
12
|
+
%h3= :abilities.l
|
|
13
|
+
= feature_abilities_table
|
|
14
|
+
|
|
15
|
+
%p
|
|
16
|
+
= icon_button_to 'btn-info btn-lg', 'arrow-right', :switch_plans.l, paid_up.plans_path, method: :get
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
- add_title :subscribe_to_plan.l plan_name: @plan.name
|
|
2
|
+
|
|
3
|
+
%p= @plan.description
|
|
4
|
+
= features_table only: @plan, should_add_buttons: false
|
|
5
|
+
|
|
6
|
+
%h2= :select_payment_info.l
|
|
7
|
+
%p= :you_will_be_charged.l charge_amount: plan_charge_human(@plan)
|
|
8
|
+
.row
|
|
9
|
+
.col-md-6
|
|
10
|
+
= form_tag paid_up.plan_subscriptions_path(@plan), class: 'form-horizontal', id: 'payment-form' do
|
|
11
|
+
%script{ src: 'https://js.stripe.com/v2/' }
|
|
12
|
+
%input{ name: 'plan_id', value: @plan.id, type: 'hidden' }
|
|
13
|
+
.payment-errors
|
|
14
|
+
.form-group
|
|
15
|
+
%label.control-label.col-xs-2= :card.l
|
|
16
|
+
.col-md-10
|
|
17
|
+
.group
|
|
18
|
+
- if current_user.cards.count > 0
|
|
19
|
+
- current_user.cards.each_with_index do |card, index|
|
|
20
|
+
.radio
|
|
21
|
+
%label
|
|
22
|
+
- if index == 0
|
|
23
|
+
%input{ type: :radio, name: 'card', value: card.id, checked: 'checked' }
|
|
24
|
+
- else
|
|
25
|
+
%input{ type: :radio, name: 'card', value: card.id }
|
|
26
|
+
= :card_ending_with.l brand: card.brand, last4: card.last4
|
|
27
|
+
.radio
|
|
28
|
+
%label
|
|
29
|
+
- if current_user.cards.count == 0
|
|
30
|
+
%input{ type: :radio, name: 'card', value: 'stripeToken', checked: 'checked' }
|
|
31
|
+
- else
|
|
32
|
+
%input{ type: :radio, name: 'card', value: 'stripeToken' }
|
|
33
|
+
= :enter_new_card.l
|
|
34
|
+
#new-card
|
|
35
|
+
.form-group
|
|
36
|
+
%label.control-label.col-xs-2{for: 'number'}= :card_number.l
|
|
37
|
+
.col-md-10
|
|
38
|
+
%input.form-control#number{ size: '16', data: { stripe: 'number' } }
|
|
39
|
+
.form-group
|
|
40
|
+
%label.control-label.col-xs-2{for: 'cvc'}= :cvc.l
|
|
41
|
+
.col-xs-4
|
|
42
|
+
%input.form-control#cvc{ size: '3', data: { stripe: 'cvc' } }
|
|
43
|
+
.form-group
|
|
44
|
+
%label.control-label.col-xs-2{for: 'exp-month'}
|
|
45
|
+
= :expiration.l
|
|
46
|
+
(MM/YYYY)
|
|
47
|
+
.col-xs-2
|
|
48
|
+
%input.form-control#exp-month{ size: '2', data: { stripe: 'exp-month' } }
|
|
49
|
+
.col-xs-2
|
|
50
|
+
/
|
|
51
|
+
%input.form-control#exp-year.col-xs-1{ size: '4', data: { stripe: 'exp-year' } }
|
|
52
|
+
.form-group
|
|
53
|
+
.col-xs-10.col-xs-offset-2
|
|
54
|
+
%button#submit-button.form-control.btn.btn-info
|
|
55
|
+
=:subscribe.l
|
|
56
|
+
|
|
57
|
+
:javascript
|
|
58
|
+
function stripeResponseHandler(status, response) {
|
|
59
|
+
var $form = $('#payment-form');
|
|
60
|
+
|
|
61
|
+
if (response.error) {
|
|
62
|
+
// Show the errors on the form
|
|
63
|
+
$form.find('.payment-errors').text(response.error.message);
|
|
64
|
+
$('#submit-button').prop('disabled', false);
|
|
65
|
+
} else {
|
|
66
|
+
// response contains id and card, which contains additional card details
|
|
67
|
+
var token = response.id;
|
|
68
|
+
// Insert the token into the form so it gets submitted to the server
|
|
69
|
+
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
|
|
70
|
+
// and submit
|
|
71
|
+
$form.get(0).submit();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
// This identifies your website in the createToken call below
|
|
75
|
+
$('#payment-form').submit(function() {
|
|
76
|
+
// Disable the submit button to prevent repeated clicks
|
|
77
|
+
$('#submit-button').prop('disabled', true);
|
|
78
|
+
|
|
79
|
+
if($("input:radio[name='card']:checked").val() == 'stripeToken') {
|
|
80
|
+
var $form = $(this);
|
|
81
|
+
|
|
82
|
+
Stripe.setPublishableKey('#{Rails.configuration.stripe[:publishable_key]}')
|
|
83
|
+
Stripe.card.createToken($form, stripeResponseHandler);
|
|
84
|
+
|
|
85
|
+
// Prevent the form from submitting with the default action
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
- if current_user.cards.count > 0
|
|
91
|
+
:javascript
|
|
92
|
+
$( document ).ready(function() {
|
|
93
|
+
$("input:radio[name='card']").change(function() {
|
|
94
|
+
if($("input:radio[name='card']:checked").val() == 'stripeToken') {
|
|
95
|
+
$('#new-card').show();
|
|
96
|
+
} else {
|
|
97
|
+
$('#new-card').hide();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
$('#new-card').hide();
|
|
101
|
+
});
|
data/bin/rails
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
|
|
3
|
+
|
|
4
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
|
5
|
+
ENGINE_PATH = File.expand_path('../../lib/paid_up/engine', __FILE__)
|
|
6
|
+
|
|
7
|
+
# Set up gems listed in the Gemfile.
|
|
8
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
|
9
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
|
10
|
+
|
|
11
|
+
require 'rails/all'
|
|
12
|
+
require 'rails/engine/commands'
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Files in the config/locales directory are used for internationalization
|
|
2
|
+
# and are automatically loaded by Rails. If you want to use locales other
|
|
3
|
+
# than English, add the necessary files in this directory.
|
|
4
|
+
#
|
|
5
|
+
# To use the locales, use `I18n.t`:
|
|
6
|
+
#
|
|
7
|
+
# I18n.t 'hello'
|
|
8
|
+
#
|
|
9
|
+
# In views, this is aliased to just `t`:
|
|
10
|
+
#
|
|
11
|
+
# <%= t('hello') %>
|
|
12
|
+
#
|
|
13
|
+
# To use a different locale, set it with `I18n.locale`:
|
|
14
|
+
#
|
|
15
|
+
# I18n.locale = :es
|
|
16
|
+
#
|
|
17
|
+
# This would use the information in config/locales/es.yml.
|
|
18
|
+
#
|
|
19
|
+
# To learn more, please read the Rails Internationalization guide
|
|
20
|
+
# available at http://guides.rubyonrails.org/i18n.html.
|
|
21
|
+
|
|
22
|
+
en:
|
|
23
|
+
abilities: "Abilities"
|
|
24
|
+
already_subscribed: "Already Subscribed"
|
|
25
|
+
are_you_sure: "Are you sure?"
|
|
26
|
+
cancel_my_account: 'Cancel My Account'
|
|
27
|
+
canceled: "Canceled"
|
|
28
|
+
card: 'Card'
|
|
29
|
+
card_ending_with: "%{brand} ending with %{last4}"
|
|
30
|
+
card_number: 'Card Number'
|
|
31
|
+
change_your_password: 'Change your password'
|
|
32
|
+
cost: 'Cost'
|
|
33
|
+
could_not_cancel_subscription: 'Could not cancel subscription'
|
|
34
|
+
could_not_associate_subscription: 'Could not associate subscription'
|
|
35
|
+
could_not_create_subscription: 'Could not create subscription'
|
|
36
|
+
could_not_subscribe_to_plan: "Could not subscribe to %{plan}"
|
|
37
|
+
could_not_update_subscription: 'Could not update subscription'
|
|
38
|
+
currently_awaiting_confirmation_for_resource: "Currently awaiting confirmation for %{resource}"
|
|
39
|
+
cvc: 'CVC'
|
|
40
|
+
default_currency: 'usd'
|
|
41
|
+
default_interval: 'month'
|
|
42
|
+
didnt_receive_confirmation_instructions: "Didn't receive confirmation instructions?"
|
|
43
|
+
didnt_receive_unlock_instructions: "Didn't receive unlock instructions?"
|
|
44
|
+
edit_resource: "Edit %{resource}"
|
|
45
|
+
enter_new_card: 'Enter New Card'
|
|
46
|
+
error: "Error"
|
|
47
|
+
error_handling_feature_setting: "Error handling %{feature} setting"
|
|
48
|
+
expiration: 'Expiration'
|
|
49
|
+
features: 'Features'
|
|
50
|
+
feature_not_found: "Feature Not Found"
|
|
51
|
+
forgot_your_password: 'Forgot your password?'
|
|
52
|
+
leave_blank_if_you_dont_want_to_change_it: "(leave blank if you don't want to change it)"
|
|
53
|
+
length_characters_minimum: "(%{length} characters minimum)"
|
|
54
|
+
my_subscription: 'My Subscription'
|
|
55
|
+
my_subscription_information: 'My Subscription Information'
|
|
56
|
+
no_conversion_of_type_features_to_table_rows: 'No conversion of %{type} Features to table_rows'
|
|
57
|
+
or_sign_in: "Or, Sign In"
|
|
58
|
+
or_sign_up: "Or, Sign Up"
|
|
59
|
+
paid_thru: "Paid Thru"
|
|
60
|
+
plan_name: "Plan Name"
|
|
61
|
+
plans: "Plans"
|
|
62
|
+
pricing: "Pricing"
|
|
63
|
+
resend_confirmation_instructions: 'Resend confirmation instructions'
|
|
64
|
+
resend_unlock_instructions: 'Resend unlock instructions'
|
|
65
|
+
select_payment_info: "Select Payment Info"
|
|
66
|
+
send_me_reset_password_instructions: "Send me reset password instructions"
|
|
67
|
+
sign_in: "Sign In"
|
|
68
|
+
sign_in_with_provider: "Sign in with %{provider}"
|
|
69
|
+
sign_out: "Sign Out"
|
|
70
|
+
sign_up: "Sign Up"
|
|
71
|
+
status: "Status"
|
|
72
|
+
subscribe: "Subscribe"
|
|
73
|
+
subscribe_to_plan: "Subscribe to %{plan_name} Plan"
|
|
74
|
+
switch_plans: "Switch Plans"
|
|
75
|
+
thank_you: "Thank You"
|
|
76
|
+
trial_period: "Trial Period"
|
|
77
|
+
unhappy: "Unhappy?"
|
|
78
|
+
unknown_feature_type: 'Unknown Feature Type'
|
|
79
|
+
unlimited: 'Unlimited'
|
|
80
|
+
update_account: 'Update Account'
|
|
81
|
+
we_need_your_current_password_to_confirm_your_changes: '(we need your current password to confirm your changes)'
|
|
82
|
+
when_using_table_rows_table_must_exist: 'When using table_rows, the table must exist.'
|
|
83
|
+
x_of_y_remaining: '%{x} of %{y} remaining'
|
|
84
|
+
you_are_now_subscribed_to_the_plan: "You are now subscribed to the %{plan_name} Plan"
|
|
85
|
+
you_will_be_charged: "You will be charged %{charge_amount}."
|
data/config/routes.rb
ADDED