saucy 0.1.18 → 0.2.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.
- data/Gemfile +4 -1
- data/Gemfile.lock +12 -2
- data/README.md +75 -0
- data/app/controllers/accounts_controller.rb +2 -0
- data/app/controllers/billings_controller.rb +22 -0
- data/app/controllers/plans_controller.rb +12 -0
- data/app/models/limit.rb +5 -0
- data/app/models/signup.rb +20 -6
- data/app/views/accounts/_tab_bar.html.erb +3 -1
- data/app/views/accounts/edit.html.erb +6 -0
- data/app/views/accounts/new.html.erb +14 -4
- data/app/views/billings/_form.html.erb +8 -0
- data/app/views/billings/edit.html.erb +11 -0
- data/app/views/billings/show.html.erb +3 -0
- data/app/views/plans/_plan.html.erb +2 -0
- data/app/views/plans/edit.html.erb +23 -0
- data/config/routes.rb +2 -0
- data/features/run_features.feature +4 -0
- data/lib/generators/saucy/features/features_generator.rb +4 -0
- data/lib/generators/saucy/features/templates/factories.rb +14 -2
- data/lib/generators/saucy/features/templates/features/manage_account.feature +0 -2
- data/lib/generators/saucy/features/templates/features/manage_billing.feature +119 -0
- data/lib/generators/saucy/features/templates/features/sign_up.feature +2 -0
- data/lib/generators/saucy/features/templates/features/sign_up_paid.feature +76 -0
- data/lib/generators/saucy/features/templates/step_definitions/braintree_steps.rb +7 -0
- data/lib/generators/saucy/features/templates/step_definitions/html_steps.rb +22 -0
- data/lib/generators/saucy/features/templates/step_definitions/plan_steps.rb +9 -0
- data/lib/generators/saucy/features/templates/support/braintree.rb +5 -0
- data/lib/generators/saucy/install/templates/create_saucy_tables.rb +14 -1
- data/lib/generators/saucy/specs/specs_generator.rb +20 -0
- data/lib/generators/saucy/specs/templates/support/braintree.rb +5 -0
- data/lib/saucy/account.rb +134 -1
- data/lib/saucy/braintree.rb +100 -0
- data/lib/saucy/plan.rb +23 -0
- data/spec/controllers/accounts_controller_spec.rb +2 -2
- data/spec/environment.rb +4 -1
- data/spec/models/account_spec.rb +182 -0
- data/spec/models/limit_spec.rb +9 -0
- data/spec/models/plan_spec.rb +54 -0
- data/spec/models/signup_spec.rb +9 -0
- data/spec/support/braintree.rb +5 -0
- metadata +74 -8
- data/README +0 -38
@@ -0,0 +1,119 @@
|
|
1
|
+
Feature: Manage Projects
|
2
|
+
As a admin user
|
3
|
+
I want to be able to manage projects
|
4
|
+
In order to have a project for each of my software applications
|
5
|
+
|
6
|
+
Scenario: Update the billing information on an account with a paid plan
|
7
|
+
Given a paid plan exists with a name of "Paid"
|
8
|
+
And the following account exists:
|
9
|
+
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
10
|
+
| Test | test | name: Paid | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
11
|
+
And I have signed in with "joe@example.com/test"
|
12
|
+
And "joe@example.com" is an admin of the "Test" account
|
13
|
+
When I go to the billing page for the "Test" account
|
14
|
+
Then I should see "card ending in 5555"
|
15
|
+
And I follow "Change" within ".current_credit_card"
|
16
|
+
|
17
|
+
Then the "Cardholder name" field should contain "Joe Smith"
|
18
|
+
And the "Billing email" field should contain "jsmith@example.com"
|
19
|
+
And the "Card number" field should be empty
|
20
|
+
And the "Verification code" field should be empty
|
21
|
+
And the "Expiration month" field should contain "01"
|
22
|
+
And the "Expiration year" field should contain "2015"
|
23
|
+
|
24
|
+
And I fill in "Cardholder name" with "Ralph Robot"
|
25
|
+
And I fill in "Billing email" with "accounting@example.com"
|
26
|
+
And I fill in "Card number" with "4111111111111111"
|
27
|
+
And I fill in "Verification code" with "123"
|
28
|
+
And I select "March" from "Expiration month"
|
29
|
+
And I select "2020" from "Expiration year"
|
30
|
+
And I press "Update"
|
31
|
+
Then I should see "updated successfully"
|
32
|
+
Then I should see "card ending in 1111"
|
33
|
+
|
34
|
+
Scenario: Change the plan to another paid plan on an account with a paid plan
|
35
|
+
Given a paid plan exists with a name of "Basic"
|
36
|
+
And a paid plan exists with a name of "Premium"
|
37
|
+
And the following account exists:
|
38
|
+
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
39
|
+
| Test | test | name: Basic | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
40
|
+
And I have signed in with "joe@example.com/test"
|
41
|
+
And "joe@example.com" is an admin of the "Test" account
|
42
|
+
When I go to the settings page for the "Test" account
|
43
|
+
Then I should see "Your Plan"
|
44
|
+
And I should not see "Billing Information"
|
45
|
+
And I should see "Basic"
|
46
|
+
And I follow "Upgrade"
|
47
|
+
Then I should see "Upgrade Your Plan"
|
48
|
+
When I choose the "Premium" plan
|
49
|
+
And I press "Upgrade"
|
50
|
+
Then I should see "Plan changed successfully"
|
51
|
+
Then I should see "Premium"
|
52
|
+
|
53
|
+
Scenario: Change the plan from free to paid
|
54
|
+
Given a plan exists with a name of "Free"
|
55
|
+
And a paid plan exists with a name of "Basic"
|
56
|
+
And the following account exists:
|
57
|
+
| name | keyword | plan |
|
58
|
+
| Test | test | name: Free |
|
59
|
+
And I have signed in with "joe@example.com/test"
|
60
|
+
And "joe@example.com" is an admin of the "Test" account
|
61
|
+
When I go to the settings page for the "Test" account
|
62
|
+
Then I should not see "Billing" within ".tabs"
|
63
|
+
Then I should see "Your Plan"
|
64
|
+
And I follow "Upgrade"
|
65
|
+
Then I should see "Upgrade Your Plan"
|
66
|
+
When I choose the "Basic" plan
|
67
|
+
Then I should see "Billing Information"
|
68
|
+
And I fill in "Cardholder name" with "Ralph Robot"
|
69
|
+
And I fill in "Billing email" with "accounting@example.com"
|
70
|
+
And I fill in "Card number" with "4111111111111111"
|
71
|
+
And I fill in "Verification code" with "123"
|
72
|
+
And I select "March" from "Expiration month"
|
73
|
+
And I select "2020" from "Expiration year"
|
74
|
+
When I press "Upgrade"
|
75
|
+
Then I should see "Plan changed successfully"
|
76
|
+
And I should see "Basic"
|
77
|
+
And I follow "Billing"
|
78
|
+
Then I should see "card ending in 1111"
|
79
|
+
|
80
|
+
Scenario: Change the plan to a free on an account with a paid plan
|
81
|
+
Given a paid plan exists with a name of "Basic"
|
82
|
+
And a plan exists with a name of "Free"
|
83
|
+
And the following account exists:
|
84
|
+
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
85
|
+
| Test | test | name: Basic | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
86
|
+
And I have signed in with "joe@example.com/test"
|
87
|
+
And "joe@example.com" is an admin of the "Test" account
|
88
|
+
When I go to the settings page for the "Test" account
|
89
|
+
Then I should see "Your Plan"
|
90
|
+
And I should not see "Billing Information"
|
91
|
+
And I should see "Basic"
|
92
|
+
And I follow "Upgrade"
|
93
|
+
Then I should see "Upgrade Your Plan"
|
94
|
+
When I choose the "Free" plan
|
95
|
+
And I press "Upgrade"
|
96
|
+
Then I should see "Plan changed successfully"
|
97
|
+
Then I should see "Free"
|
98
|
+
|
99
|
+
Scenario: Attempting to downgrade when beyond the limits
|
100
|
+
Given a paid plan exists with a name of "Basic"
|
101
|
+
And a plan exists with a name of "Free"
|
102
|
+
And the following account exists:
|
103
|
+
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
104
|
+
| Test | test | name: Basic | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
105
|
+
And the following limits exist:
|
106
|
+
| plan | name | value |
|
107
|
+
| name: Basic | users | 1 |
|
108
|
+
| name: Free | users | 0 |
|
109
|
+
| name: Basic | projects | 5 |
|
110
|
+
| name: Free | projects | 1 |
|
111
|
+
And I have signed in with "joe@example.com/test"
|
112
|
+
And "joe@example.com" is an admin of the "Test" account
|
113
|
+
When I go to the settings page for the "Test" account
|
114
|
+
Then I should see "Your Plan"
|
115
|
+
And I should not see "Billing Information"
|
116
|
+
And I should see "Basic"
|
117
|
+
And I follow "Upgrade"
|
118
|
+
Then I should see "Upgrade Your Plan"
|
119
|
+
And the "Free" plan should be disabled
|
@@ -8,9 +8,11 @@ Feature: Sign up
|
|
8
8
|
|
9
9
|
Scenario: User signs up with invalid data
|
10
10
|
When I go to the sign up page for the "Free" plan
|
11
|
+
Then I should see "Free"
|
11
12
|
And I fill in "Email" with "invalidemail"
|
12
13
|
And I fill in "Password" with "password"
|
13
14
|
And I fill in "Confirm password" with ""
|
15
|
+
And I should not see "Billing Information"
|
14
16
|
And I press "Sign up"
|
15
17
|
Then I should see error messages
|
16
18
|
|
@@ -0,0 +1,76 @@
|
|
1
|
+
Feature: Sign up
|
2
|
+
In order to get access to protected sections of the site
|
3
|
+
A user
|
4
|
+
Should be able to sign up
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given a paid plan exists with a name of "Paid"
|
8
|
+
|
9
|
+
Scenario: User signs up for a paid plan with invalid data
|
10
|
+
When I go to the sign up page for the "Paid" plan
|
11
|
+
And I should see "Paid"
|
12
|
+
And I should see "$1/month"
|
13
|
+
And the "Card number" field should have autocomplete off
|
14
|
+
And the "Verification code" field should have autocomplete off
|
15
|
+
And I fill in "Email" with "invalidemail"
|
16
|
+
And I fill in "Password" with "password"
|
17
|
+
And I fill in "Confirm password" with ""
|
18
|
+
And I should see "Billing Information"
|
19
|
+
And I press "Sign up"
|
20
|
+
Then I should see error messages
|
21
|
+
|
22
|
+
Scenario: User signs up for a paid plan with valid data
|
23
|
+
When I go to the list of plans page
|
24
|
+
And I follow "Paid"
|
25
|
+
And I fill in "Email" with "email@person.com"
|
26
|
+
And I fill in "Password" with "password"
|
27
|
+
And I fill in "Confirm password" with "password"
|
28
|
+
And I fill in "Your name" with "Robot"
|
29
|
+
And I fill in "Company Name" with "Robots, Inc"
|
30
|
+
And I fill in "Keyword" with "robotsinc"
|
31
|
+
And I fill in "Cardholder name" with "Ralph Robot"
|
32
|
+
And I fill in "Billing email" with "accounting@example.com"
|
33
|
+
And I fill in "Card number" with "4111111111111111"
|
34
|
+
And I fill in "Verification code" with "123"
|
35
|
+
And I select "March" from "Expiration month"
|
36
|
+
And I select "2020" from "Expiration year"
|
37
|
+
And I press "Sign up"
|
38
|
+
Then I should see "created"
|
39
|
+
|
40
|
+
Scenario: User signs up for a paid plan with an invalid credit card number
|
41
|
+
Given that the credit card "4111112" is invalid
|
42
|
+
When I go to the list of plans page
|
43
|
+
And I follow "Paid"
|
44
|
+
And I fill in "Email" with "email@person.com"
|
45
|
+
And I fill in "Password" with "password"
|
46
|
+
And I fill in "Confirm password" with "password"
|
47
|
+
And I fill in "Your name" with "Robot"
|
48
|
+
And I fill in "Company Name" with "Robots, Inc"
|
49
|
+
And I fill in "Keyword" with "robotsinc"
|
50
|
+
And I fill in "Cardholder name" with "Ralph Robot"
|
51
|
+
And I fill in "Billing email" with "accounting@example.com"
|
52
|
+
And I fill in "Card number" with "4111112"
|
53
|
+
And I fill in "Verification code" with "123"
|
54
|
+
And I select "March" from "Expiration month"
|
55
|
+
And I select "2020" from "Expiration year"
|
56
|
+
And I press "Sign up"
|
57
|
+
Then "Card number" should have the error "is invalid"
|
58
|
+
|
59
|
+
Scenario: User signs up for a paid plan with a credit card that cannot be processed
|
60
|
+
Given that the credit card "4111111111111111" should not be honored
|
61
|
+
When I go to the list of plans page
|
62
|
+
And I follow "Paid"
|
63
|
+
And I fill in "Email" with "email@person.com"
|
64
|
+
And I fill in "Password" with "password"
|
65
|
+
And I fill in "Confirm password" with "password"
|
66
|
+
And I fill in "Your name" with "Robot"
|
67
|
+
And I fill in "Company Name" with "Robots, Inc"
|
68
|
+
And I fill in "Keyword" with "robotsinc"
|
69
|
+
And I fill in "Cardholder name" with "Ralph Robot"
|
70
|
+
And I fill in "Billing email" with "accounting@example.com"
|
71
|
+
And I fill in "Card number" with "4111111111111111"
|
72
|
+
And I fill in "Verification code" with "123"
|
73
|
+
And I select "March" from "Expiration month"
|
74
|
+
And I select "2020" from "Expiration year"
|
75
|
+
And I press "Sign up"
|
76
|
+
Then "Card number" should have the error "Do Not Honor"
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Given /^that the credit card "([^"]*)" is invalid$/ do |number|
|
2
|
+
FakeBraintree.failures[number] = { "message" => "Credit card number is invalid.", "errors" => { "customer" => { "errors" => [], "credit-card" => { "errors" => [{ "message" => "Credit card number is invalid.", "code" => 81715, "attribute" => :number }] }}}}
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^that the credit card "([^"]*)" should not be honored$/ do |number|
|
6
|
+
FakeBraintree.failures[number] = { "message" => "Do Not Honor", "code" => "2000", "status" => "processor_declined" }
|
7
|
+
end
|
@@ -1,3 +1,25 @@
|
|
1
1
|
Then /^the form should have inline error messages$/ do
|
2
2
|
page.should have_css(".error")
|
3
3
|
end
|
4
|
+
|
5
|
+
When /^the "([^"]*)" field should have autocomplete off$/ do |field|
|
6
|
+
field = page.find_field(field)
|
7
|
+
field["autocomplete"].should == "off"
|
8
|
+
end
|
9
|
+
|
10
|
+
Then /^"([^"]*)" should have the error "([^"]*)"$/ do |field, error|
|
11
|
+
field = page.find_field(field)
|
12
|
+
field.find(:xpath, "following-sibling::p[@class='inline-errors'][contains(text(), '#{error}')]").should_not be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
Then /^the "([^"]*)" field(?: within "([^"]*)")? should be empty$/ do |field, selector|
|
16
|
+
with_scope(selector) do
|
17
|
+
field = find_field(field)
|
18
|
+
field_value = (field.tag_name == 'textarea') ? field.text : field.value
|
19
|
+
if field_value.respond_to? :should
|
20
|
+
field_value.should be_nil
|
21
|
+
else
|
22
|
+
assert_nil(field_value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
When /^I choose the "([^"]*)" plan$/ do |plan_name|
|
2
|
+
input_id = page.find(:xpath, "//label/p[contains(text(),'#{plan_name}')]/../@for").node.value
|
3
|
+
choose(input_id)
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the "([^"]*)" plan should be disabled$/ do |plan_name|
|
7
|
+
input_id = page.find(:xpath, "//label/p[contains(text(),'#{plan_name}')]/../@for").node.value
|
8
|
+
page.should have_css("##{input_id}[disabled='disabled']")
|
9
|
+
end
|
@@ -16,6 +16,8 @@ class CreateSaucyTables < ActiveRecord::Migration
|
|
16
16
|
table.string :keyword
|
17
17
|
table.datetime :created_at
|
18
18
|
table.datetime :updated_at
|
19
|
+
table.string :customer_token
|
20
|
+
table.string :subscription_token
|
19
21
|
end
|
20
22
|
add_index :accounts, :plan_id
|
21
23
|
add_index :accounts, :keyword
|
@@ -56,13 +58,24 @@ class CreateSaucyTables < ActiveRecord::Migration
|
|
56
58
|
|
57
59
|
create_table :plans do |t|
|
58
60
|
t.string :name
|
59
|
-
t.integer :price
|
61
|
+
t.integer :price, :null => false, :default => 0
|
60
62
|
|
61
63
|
t.timestamps
|
62
64
|
end
|
63
65
|
|
64
66
|
add_index :plans, :name
|
65
67
|
|
68
|
+
create_table :limits do |t|
|
69
|
+
t.belongs_to :plan
|
70
|
+
t.string :name
|
71
|
+
t.integer :value, :null => false, :default => 0
|
72
|
+
t.string :value_type, :null => false, :default => "number"
|
73
|
+
|
74
|
+
t.timestamps
|
75
|
+
end
|
76
|
+
|
77
|
+
add_index :limits, :plan_id
|
78
|
+
|
66
79
|
create_table :invitations_projects, :id => false do |table|
|
67
80
|
table.integer :invitation_id, :null => false
|
68
81
|
table.integer :project_id, :null => false
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'generators/saucy/base'
|
2
|
+
|
3
|
+
module Saucy
|
4
|
+
module Generators
|
5
|
+
class SpecsGenerator < Base
|
6
|
+
|
7
|
+
desc <<DESC
|
8
|
+
Description:
|
9
|
+
Copy saucy cucumber spec support files to your application.
|
10
|
+
DESC
|
11
|
+
|
12
|
+
def copy_spec_files
|
13
|
+
directory "support", "spec/support/saucy"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
data/lib/saucy/account.rb
CHANGED
@@ -3,6 +3,14 @@ module Saucy
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
+
CUSTOMER_ATTRIBUTES = { :cardholder_name => :cardholder_name,
|
7
|
+
:billing_email => :email,
|
8
|
+
:card_number => :number,
|
9
|
+
:expiration_month => :expiration_month,
|
10
|
+
:expiration_year => :expiration_year,
|
11
|
+
:verification_code => :cvv }
|
12
|
+
|
13
|
+
extend ActiveSupport::Memoizable
|
6
14
|
has_many :memberships, :dependent => :destroy
|
7
15
|
has_many :users, :through => :memberships
|
8
16
|
has_many :projects, :dependent => :destroy
|
@@ -12,14 +20,23 @@ module Saucy
|
|
12
20
|
|
13
21
|
belongs_to :plan
|
14
22
|
|
23
|
+
delegate :free?, :billed?, :to => :plan
|
24
|
+
|
15
25
|
validates_uniqueness_of :name, :keyword
|
16
|
-
validates_presence_of :name, :keyword
|
26
|
+
validates_presence_of :name, :keyword, :plan_id
|
27
|
+
|
28
|
+
attr_accessor *CUSTOMER_ATTRIBUTES.keys
|
17
29
|
|
18
30
|
attr_accessible :name, :keyword
|
19
31
|
|
20
32
|
validates_format_of :keyword,
|
21
33
|
:with => %r{^[a-z0-9]+$},
|
22
34
|
:message => "must be only lower case letters."
|
35
|
+
|
36
|
+
before_create :create_customer
|
37
|
+
before_create :create_subscription, :if => :billed?
|
38
|
+
|
39
|
+
memoize :customer
|
23
40
|
end
|
24
41
|
|
25
42
|
module InstanceMethods
|
@@ -46,6 +63,122 @@ module Saucy
|
|
46
63
|
def memberships_by_name
|
47
64
|
memberships.by_name
|
48
65
|
end
|
66
|
+
|
67
|
+
def customer
|
68
|
+
Braintree::Customer.find(customer_token) if customer_token
|
69
|
+
end
|
70
|
+
|
71
|
+
def credit_card
|
72
|
+
customer.credit_cards[0] if customer && customer.credit_cards.any?
|
73
|
+
end
|
74
|
+
|
75
|
+
def subscription
|
76
|
+
Braintree::Subscription.find(subscription_token) if subscription_token
|
77
|
+
end
|
78
|
+
|
79
|
+
def save_braintree!(attributes)
|
80
|
+
successful = true
|
81
|
+
self.plan = ::Plan.find(attributes[:plan_id]) if attributes[:plan_id].present?
|
82
|
+
if CUSTOMER_ATTRIBUTES.keys.any? { |attribute| attributes[attribute].present? }
|
83
|
+
CUSTOMER_ATTRIBUTES.keys.each do |attribute|
|
84
|
+
send("#{attribute}=", attributes[attribute]) if attributes[attribute].present?
|
85
|
+
end
|
86
|
+
result = Braintree::Customer.update(customer_token, customer_attributes)
|
87
|
+
successful = result.success?
|
88
|
+
handle_customer_result(result)
|
89
|
+
end
|
90
|
+
if successful && attributes[:plan_id].present?
|
91
|
+
if subscription
|
92
|
+
Braintree::Subscription.update(subscription_token, :plan_id => attributes[:plan_id])
|
93
|
+
else
|
94
|
+
create_subscription
|
95
|
+
end
|
96
|
+
end
|
97
|
+
successful && save
|
98
|
+
end
|
99
|
+
|
100
|
+
def can_change_plan_to?(new_plan)
|
101
|
+
plan.limits.where(:value_type => :number).all? do |limit|
|
102
|
+
new_plan.limit(limit.name).value >= send(limit.name).count
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def customer_attributes
|
109
|
+
{
|
110
|
+
:email => billing_email,
|
111
|
+
:credit_card => credit_card_attributes
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def credit_card_attributes
|
116
|
+
if plan.billed?
|
117
|
+
card_attributes = { :cardholder_name => cardholder_name,
|
118
|
+
:number => card_number,
|
119
|
+
:expiration_month => expiration_month,
|
120
|
+
:expiration_year => expiration_year,
|
121
|
+
:cvv => verification_code }
|
122
|
+
if credit_card
|
123
|
+
card_attributes.merge!(:options => credit_card_options)
|
124
|
+
end
|
125
|
+
card_attributes
|
126
|
+
else
|
127
|
+
{}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def credit_card_options
|
132
|
+
if customer && customer.credit_cards.any?
|
133
|
+
{ :update_existing_token => customer.credit_cards[0].token }
|
134
|
+
else
|
135
|
+
{}
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def create_customer
|
140
|
+
result = Braintree::Customer.create(customer_attributes)
|
141
|
+
handle_customer_result(result)
|
142
|
+
end
|
143
|
+
|
144
|
+
def handle_customer_result(result)
|
145
|
+
if result.success?
|
146
|
+
self.customer_token = result.customer.id
|
147
|
+
flush_cache :customer
|
148
|
+
else
|
149
|
+
verification = result.credit_card_verification
|
150
|
+
if verification && verification.status == "processor_declined"
|
151
|
+
errors[:card_number] << "was denied by the payment processor with the message: #{verification.processor_response_text}"
|
152
|
+
elsif verification && verification.status == "gateway_rejected"
|
153
|
+
errors[:verification_code] << "did not match"
|
154
|
+
elsif result.errors.any?
|
155
|
+
result.errors.each do |error|
|
156
|
+
if error.attribute == "number"
|
157
|
+
errors[:card_number] << error.message.gsub("Credit card number ", "")
|
158
|
+
elsif error.attribute == "CVV"
|
159
|
+
errors[:verification_code] << error.message.gsub("CVV ", "")
|
160
|
+
elsif error.attribute == "expiration_month"
|
161
|
+
errors[:expiration_month] << error.message.gsub("Expiration month ", "")
|
162
|
+
elsif error.attribute == "expiration_year"
|
163
|
+
errors[:expiration_year] << error.message.gsub("Expiration year ", "")
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
result.success?
|
169
|
+
end
|
170
|
+
|
171
|
+
def create_subscription
|
172
|
+
result = Braintree::Subscription.create(
|
173
|
+
:payment_method_token => credit_card.token,
|
174
|
+
:plan_id => plan_id
|
175
|
+
)
|
176
|
+
if result.success?
|
177
|
+
self.subscription_token = result.subscription.id
|
178
|
+
else
|
179
|
+
false
|
180
|
+
end
|
181
|
+
end
|
49
182
|
end
|
50
183
|
end
|
51
184
|
end
|