saucy 0.1.18 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|