pay 0.0.0 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pay might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +196 -4
- data/Rakefile +13 -5
- data/app/models/subscription.rb +59 -0
- data/config/initializers/pay.rb +3 -0
- data/config/initializers/stripe.rb +1 -0
- data/db/development.sqlite3 +0 -0
- data/db/migrate/20170205020145_create_subscriptions.rb +16 -0
- data/db/migrate/20170503131610_add_fields_to_users.rb +15 -0
- data/lib/pay.rb +12 -2
- data/lib/pay/billable.rb +79 -0
- data/lib/pay/billable/braintree.rb +57 -0
- data/lib/pay/billable/stripe.rb +47 -0
- data/lib/pay/version.rb +1 -1
- metadata +114 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92f9482ce3c201c076c2717a75c9e0670f412c4b
|
4
|
+
data.tar.gz: cd8a5de08bf9fdf46b71648202967b3202615f9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7383c1f3dcbd887dd185c4cc28277513e4d9f1ab29229ebb042342ffb3301ad2e25e86dd45889c88b85df6a388ee831152c7ba594ccc14aef30f4ee0dae27336
|
7
|
+
data.tar.gz: a8431aee8abb65ff7d8550ed471ebdada798b686de30bfe21830554c1e59d509406e0031fd834236e1bbdd56cfb12f1c67b1c2455fff1a42a0a252da777dcf41
|
data/README.md
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
# Pay
|
2
|
-
|
2
|
+
[ ![Codeship Status for jasoncharnes/pay](https://img.shields.io/codeship/72941cf0-31a8-0135-af58-3a3212f0f89d/master.svg)](https://app.codeship.com/projects/225793)
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
Pay is a subscription engine for Ruby on Rails.
|
5
|
+
|
6
|
+
Supports Ruby on Rails 4.2 and higher.
|
7
|
+
|
8
|
+
**Current Payment Providers**
|
9
|
+
* Stripe
|
10
|
+
|
11
|
+
**Payment Providers In Development**
|
12
|
+
* Braintree
|
13
|
+
|
14
|
+
Want to add a new payment provider? Contributions are welcome and the instructions [are here](https://github.com/jasoncharnes/pay/wiki/New-Payment-Provider).
|
6
15
|
|
7
16
|
## Installation
|
8
17
|
Add this line to your application's Gemfile:
|
@@ -21,8 +30,191 @@ Or install it yourself as:
|
|
21
30
|
$ gem install pay
|
22
31
|
```
|
23
32
|
|
33
|
+
## Setup
|
34
|
+
#### Migrations
|
35
|
+
This engine will create a subscription model and the neccessary migrations for the model you want to make "billable." The most common use case for the billable model is a User.
|
36
|
+
|
37
|
+
To add the migrations to your application, run the following migration:
|
38
|
+
|
39
|
+
`$ bin/rails pay:install:migrations`
|
40
|
+
|
41
|
+
This will install two migrations:
|
42
|
+
- db/migrate/create_subscriptions.rb
|
43
|
+
- db/migrate/add_fields_to_users.rb
|
44
|
+
|
45
|
+
#### Non-User Model
|
46
|
+
If you need to use a model other than `User`, check out the [wiki page](https://github.com/jasoncharnes/pay/wiki/Model-Other-Than-User).
|
47
|
+
|
48
|
+
#### Run the Migrations
|
49
|
+
Finally, run the migrations with `$ rake db:migrate`
|
50
|
+
|
51
|
+
#### Stripe
|
52
|
+
You'll need to add your private Stripe API key to your Rails secrets. `config/secrets.yml`
|
53
|
+
|
54
|
+
```yaml
|
55
|
+
development:
|
56
|
+
stripe_api_key: sk_test_....
|
57
|
+
```
|
58
|
+
|
59
|
+
## Usage
|
60
|
+
Include the `Pay::Billable` module in the model you want to know about subscriptions.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# app/models/user.rb
|
64
|
+
class User < ActiveRecord::Base
|
65
|
+
include Pay::Billable
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
**To see how to use Stripe Elements JS & Devise, [click here](https://github.com/jasoncharnes/pay/wiki/Using-Stripe-Elements-and-Devise).**
|
70
|
+
|
71
|
+
## User API
|
72
|
+
#### Creating a Subscription
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
user = User.find_by(email: 'michael@bluthcompany.co')
|
76
|
+
user.card_token = 'stripe-token'
|
77
|
+
user.subscribe
|
78
|
+
```
|
79
|
+
|
80
|
+
A `card_token` must be provided as an attribute.
|
81
|
+
|
82
|
+
The subscribe method has three optional arguments with default values.
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
def subscribe(name = 'default', plan = 'default', processor = 'stripe')
|
86
|
+
...
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
##### Name
|
91
|
+
Name is an internally used name for the subscription.
|
92
|
+
|
93
|
+
##### Plan
|
94
|
+
Plan is the plan ID from the payment processor.
|
95
|
+
|
96
|
+
#### Retrieving a Subscription from the Database
|
97
|
+
```ruby
|
98
|
+
user = User.find_by(email: 'gob@bluthcompany.co')
|
99
|
+
user.subscription
|
100
|
+
```
|
101
|
+
|
102
|
+
#### Checking a User's Subscription Status
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
user = User.find_by(email: 'george.senior@bluthcompany.co')
|
106
|
+
user.subscribed?
|
107
|
+
```
|
108
|
+
|
109
|
+
The `subscribed?` method has two optional arguments with default values.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
def subscribed?(name = 'default', plan = nil)
|
113
|
+
...
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
##### Name
|
118
|
+
Name is an internally used name for the subscription.
|
119
|
+
|
120
|
+
##### Plan
|
121
|
+
Plan is the plan ID from the payment processor.
|
122
|
+
|
123
|
+
##### Processor
|
124
|
+
Processor is the string value of the payment processor subscription. Pay currently only supports Stripe, but other implementations are welcome.
|
125
|
+
|
126
|
+
#### Retrieving a Payment Processor Account
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
user = User.find_by(email: 'george.michael@bluthcompany.co')
|
130
|
+
user.customer
|
131
|
+
```
|
132
|
+
|
133
|
+
#### Updating a Customer's Credit Card
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
user = User.find_by(email: 'tobias@bluthcompany.co')
|
137
|
+
user.update_card('stripe-token')
|
138
|
+
```
|
139
|
+
|
140
|
+
#### Retrieving a Customer's Subscription from the Processor
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
user = User.find_by(email: 'lucille@bluthcompany.co')
|
144
|
+
user.processor_subscription(subscription_id)
|
145
|
+
```
|
146
|
+
|
147
|
+
## Subscription API
|
148
|
+
#### Checking a Subscription's Trial Status
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
user = User.find_by(email: 'lindsay@bluthcompany.co')
|
152
|
+
user.subscription.on_trial?
|
153
|
+
```
|
154
|
+
|
155
|
+
#### Checking a Subscription's Cancellation Status
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
user = User.find_by(email: 'buster@bluthcompany.co')
|
159
|
+
user.subscription.cancelled?
|
160
|
+
```
|
161
|
+
|
162
|
+
#### Checking a Subscription's Grace Period Status
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
user = User.find_by(email: 'her?@bluthcompany.co')
|
166
|
+
user.subscription.on_grace_period?
|
167
|
+
```
|
168
|
+
|
169
|
+
#### Checking to See If a Subscription Is Active
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
user = User.find_by(email: 'carl.weathers@bluthcompany.co')
|
173
|
+
user.subscription.active?
|
174
|
+
```
|
175
|
+
|
176
|
+
#### Cancel a Subscription (At End of Billing Cycle)
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
user = User.find_by(email: 'oscar@bluthcompany.co')
|
180
|
+
user.subscription.cancel
|
181
|
+
```
|
182
|
+
|
183
|
+
#### Cancel a Subscription Immediately
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
user = User.find_by(email: 'annyong@bluthcompany.co')
|
187
|
+
user.subscription.cancel_now!
|
188
|
+
```
|
189
|
+
|
190
|
+
#### Resume a Subscription on a Grace Period
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
user = User.find_by(email: 'steve.holt@bluthcompany.co')
|
194
|
+
user.subscription.resume
|
195
|
+
```
|
196
|
+
|
197
|
+
#### Retrieving the Subscription from the Processor
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
user = User.find_by(email: 'lucille2@bluthcompany.co')
|
201
|
+
user.subscription.processor_subscription
|
202
|
+
```
|
203
|
+
|
204
|
+
## Contributors
|
205
|
+
* [Jason Charnes](https://twitter.com/jmcharnes)
|
206
|
+
* [Chris Oliver](https://twitter.com/excid3)
|
207
|
+
|
24
208
|
## Contributing
|
25
|
-
|
209
|
+
👋 Thanks for your interest in contributing. Feel free to fork this repo.
|
210
|
+
|
211
|
+
If you have an issue you'd like to submit, please do so using the issue tracker in GitHub. In order for us to help you in the best way possible, please be as detailed as you can.
|
212
|
+
|
213
|
+
If you'd like to open a PR please make sure the following things pass:
|
214
|
+
* `rake test`
|
215
|
+
* `rubocop`
|
216
|
+
|
217
|
+
These will need to be passing in order for a Pull Request to be accepted.
|
26
218
|
|
27
219
|
## License
|
28
220
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -14,14 +14,11 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
14
14
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
15
|
end
|
16
16
|
|
17
|
-
APP_RAKEFILE = File.expand_path(
|
17
|
+
APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
|
18
18
|
load 'rails/tasks/engine.rake'
|
19
19
|
|
20
|
-
|
21
20
|
load 'rails/tasks/statistics.rake'
|
22
21
|
|
23
|
-
|
24
|
-
|
25
22
|
require 'bundler/gem_tasks'
|
26
23
|
|
27
24
|
require 'rake/testtask'
|
@@ -33,5 +30,16 @@ Rake::TestTask.new(:test) do |t|
|
|
33
30
|
t.verbose = false
|
34
31
|
end
|
35
32
|
|
36
|
-
|
37
33
|
task default: :test
|
34
|
+
|
35
|
+
task :console do
|
36
|
+
require 'irb'
|
37
|
+
require 'irb/completion'
|
38
|
+
require 'pay'
|
39
|
+
ARGV.clear
|
40
|
+
IRB.start
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'rubocop/rake_task'
|
44
|
+
|
45
|
+
RuboCop::RakeTask.new
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Subscription < ApplicationRecord
|
2
|
+
# Associations
|
3
|
+
belongs_to :owner, class_name: Pay.billable_class, foreign_key: :owner_id
|
4
|
+
|
5
|
+
# Validations
|
6
|
+
validates :name, presence: true
|
7
|
+
validates :processor, presence: true
|
8
|
+
validates :processor_id, presence: true
|
9
|
+
validates :processor_plan, presence: true
|
10
|
+
validates :quantity, presence: true
|
11
|
+
|
12
|
+
# Scopes
|
13
|
+
scope :for_name, ->(name) { where(name: name) }
|
14
|
+
|
15
|
+
def on_trial?
|
16
|
+
trial_ends_at? && Time.zone.now < trial_ends_at
|
17
|
+
end
|
18
|
+
|
19
|
+
def cancelled?
|
20
|
+
ends_at?
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_grace_period?
|
24
|
+
cancelled? && Time.zone.now < ends_at
|
25
|
+
end
|
26
|
+
|
27
|
+
def active?
|
28
|
+
ends_at.nil? || on_grace_period? || on_trial?
|
29
|
+
end
|
30
|
+
|
31
|
+
def cancel
|
32
|
+
subscription = processor_subscription.delete(at_period_end: true)
|
33
|
+
update(ends_at: Time.at(subscription.current_period_end))
|
34
|
+
end
|
35
|
+
|
36
|
+
def cancel_now!
|
37
|
+
subscription = processor_subscription.delete
|
38
|
+
update(ends_at: Time.at(subscription.current_period_end))
|
39
|
+
end
|
40
|
+
|
41
|
+
def resume
|
42
|
+
unless on_grace_period?
|
43
|
+
raise StandardError,
|
44
|
+
'You can only resume subscriptions within their grace period.'
|
45
|
+
end
|
46
|
+
|
47
|
+
subscription = processor_subscription
|
48
|
+
subscription.plan = processor_plan
|
49
|
+
subscription.trial_end = on_trial? ? trial_ends_at.to_i : 'now'
|
50
|
+
subscription.save
|
51
|
+
|
52
|
+
update(ends_at: nil)
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def processor_subscription
|
57
|
+
owner.processor_subscription(processor_id)
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Stripe.api_key = Rails.application.secrets.stripe_api_key
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateSubscriptions < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :subscriptions do |t|
|
4
|
+
t.references :owner
|
5
|
+
t.string :name, null: false
|
6
|
+
t.string :processor, null: false
|
7
|
+
t.string :processor_id, null: false
|
8
|
+
t.string :processor_plan, null: false
|
9
|
+
t.integer :quantity, default: 1, null: false
|
10
|
+
t.datetime :trial_ends_at
|
11
|
+
t.datetime :ends_at
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class AddFieldsToUsers < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
unless ActiveRecord::Base.connection.table_exists?(Pay.billable_table)
|
4
|
+
create_table Pay.billable_table.to_sym
|
5
|
+
end
|
6
|
+
|
7
|
+
add_column Pay.billable_table, :processor, :string
|
8
|
+
add_column Pay.billable_table, :processor_id, :string
|
9
|
+
add_column Pay.billable_table, :card_token, :string
|
10
|
+
add_column Pay.billable_table, :card_brand, :string
|
11
|
+
add_column Pay.billable_table, :card_last4, :string
|
12
|
+
add_column Pay.billable_table, :card_exp_month, :string
|
13
|
+
add_column Pay.billable_table, :card_exp_year, :string
|
14
|
+
end
|
15
|
+
end
|
data/lib/pay.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
|
-
require
|
1
|
+
require 'stripe'
|
2
|
+
require 'pay/engine'
|
3
|
+
require 'pay/billable'
|
2
4
|
|
3
5
|
module Pay
|
4
|
-
#
|
6
|
+
# Define who owns the subscription
|
7
|
+
mattr_accessor :billable_class
|
8
|
+
mattr_accessor :billable_table
|
9
|
+
@@billable_class = 'User'
|
10
|
+
@@billable_table = @@billable_class.tableize
|
11
|
+
|
12
|
+
def self.setup
|
13
|
+
yield self
|
14
|
+
end
|
5
15
|
end
|
data/lib/pay/billable.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'pay/billable/stripe'
|
2
|
+
require 'pay/billable/braintree'
|
3
|
+
|
4
|
+
module Pay
|
5
|
+
module Billable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
include Pay::Billable::Stripe
|
10
|
+
include Pay::Billable::Braintree
|
11
|
+
|
12
|
+
has_many :subscriptions, foreign_key: :owner_id
|
13
|
+
|
14
|
+
attribute :plan, :string
|
15
|
+
attribute :quantity, :integer
|
16
|
+
attribute :card_token, :string
|
17
|
+
end
|
18
|
+
|
19
|
+
def customer(token = nil)
|
20
|
+
check_for_processor
|
21
|
+
send("#{processor}_customer", token)
|
22
|
+
end
|
23
|
+
|
24
|
+
def subscribe(name = 'default', plan = 'default', processor = 'stripe')
|
25
|
+
self.processor = processor
|
26
|
+
send("create_#{processor}_subscription", name, plan)
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_card(token)
|
30
|
+
check_for_processor
|
31
|
+
send("update_#{processor}_card", token)
|
32
|
+
end
|
33
|
+
|
34
|
+
def processor_subscription(subscription_id)
|
35
|
+
check_for_processor
|
36
|
+
send("#{processor}_subscription", subscription_id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def subscribed?(name = 'default', plan = nil)
|
40
|
+
subscription = subscription(name)
|
41
|
+
|
42
|
+
return false if subscription.nil?
|
43
|
+
return subscription.active? if plan.nil?
|
44
|
+
|
45
|
+
subscription.active? && subscription.plan == plan
|
46
|
+
end
|
47
|
+
|
48
|
+
def subscription(name = 'default')
|
49
|
+
subscriptions.for_name(name).last
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def check_for_processor
|
55
|
+
raise StandardError, 'No processor selected' unless processor
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_subscription(subscription, processor, name, plan, qty = 1)
|
59
|
+
subscriptions.create!(
|
60
|
+
name: name || 'default',
|
61
|
+
processor: processor,
|
62
|
+
processor_id: subscription.id,
|
63
|
+
processor_plan: plan,
|
64
|
+
trial_ends_at: trial_end_date(subscription),
|
65
|
+
quantity: qty,
|
66
|
+
ends_at: nil
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def update_card_on_file(card)
|
71
|
+
update!(
|
72
|
+
card_brand: card.brand,
|
73
|
+
card_last4: card.last4,
|
74
|
+
card_exp_month: card.exp_month,
|
75
|
+
card_exp_year: card.exp_year
|
76
|
+
)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Pay
|
2
|
+
module Billable
|
3
|
+
module Braintree
|
4
|
+
# def braintree_customer(token = nil)
|
5
|
+
# if processor_id?
|
6
|
+
# result = ::Braintree::PaymentMethod.create(
|
7
|
+
# customer_id: processor_id,
|
8
|
+
# payment_method_nonce: token,
|
9
|
+
# options: { make_default: true }
|
10
|
+
# )
|
11
|
+
|
12
|
+
# raise StandardError, result.inspect unless result.success?
|
13
|
+
# ::Braintree::Customer.find(processor_id)
|
14
|
+
# else
|
15
|
+
# result = ::Braintree::Customer.create(
|
16
|
+
# email: email,
|
17
|
+
# payment_method_nonce: token
|
18
|
+
# )
|
19
|
+
|
20
|
+
# raise StandardError, result.inspect unless result.success?
|
21
|
+
# update(processor: 'braintree', processor_id: result.customer.id)
|
22
|
+
|
23
|
+
# result.customer
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
|
27
|
+
# def create_braintree_subscription(name = 'default')
|
28
|
+
# token = braintree_customer.payment_methods.find(&:default?).token
|
29
|
+
|
30
|
+
# result = ::Braintree::Subscription.create(
|
31
|
+
# payment_method_token: token,
|
32
|
+
# plan_id: plan
|
33
|
+
# )
|
34
|
+
|
35
|
+
# if result.success?
|
36
|
+
# subscription = subscriptions.create(
|
37
|
+
# name: name || 'default',
|
38
|
+
# processor: processor,
|
39
|
+
# processor_id: result.subscription.id,
|
40
|
+
# processor_plan: plan,
|
41
|
+
# trial_ends_at: ,
|
42
|
+
# quantity: quantity || 1,
|
43
|
+
# ends_at: nil
|
44
|
+
# )
|
45
|
+
# else
|
46
|
+
# raise StandardError, result.inspect
|
47
|
+
# end
|
48
|
+
|
49
|
+
# subscription
|
50
|
+
# end
|
51
|
+
|
52
|
+
# def update_braintree_card(token)
|
53
|
+
# # Placeholder
|
54
|
+
# end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Pay
|
2
|
+
module Billable
|
3
|
+
module Stripe
|
4
|
+
def stripe_customer
|
5
|
+
if processor_id?
|
6
|
+
customer = ::Stripe::Customer.retrieve(processor_id)
|
7
|
+
else
|
8
|
+
customer = ::Stripe::Customer.create(email: email, source: card_token)
|
9
|
+
update(processor: 'stripe', processor_id: customer.id)
|
10
|
+
end
|
11
|
+
|
12
|
+
customer
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_stripe_subscription(name, plan)
|
16
|
+
stripe_sub = stripe_customer.subscriptions.create(plan: plan)
|
17
|
+
subscription = create_subscription(stripe_sub, 'stripe', name, plan)
|
18
|
+
subscription
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_stripe_card(token)
|
22
|
+
customer = stripe_customer
|
23
|
+
token = ::Stripe::Token.retrieve(token)
|
24
|
+
|
25
|
+
return if token.card.id == customer.default_source
|
26
|
+
save_stripe_card(token, customer)
|
27
|
+
end
|
28
|
+
|
29
|
+
def stripe_subscription(subscription_id)
|
30
|
+
::Stripe::Subscription.retrieve(subscription_id)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def save_stripe_card(token, customer)
|
36
|
+
card = customer.sources.create(source: token.id)
|
37
|
+
customer.default_source = card.id
|
38
|
+
customer.save
|
39
|
+
update_card_on_file(card)
|
40
|
+
end
|
41
|
+
|
42
|
+
def trial_end_date(stripe_sub)
|
43
|
+
stripe_sub.trial_end.present? ? Time.at(stripe_sub.trial_end) : nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/pay/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Charnes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: stripe
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: braintree
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
16
44
|
requirements:
|
17
45
|
- - "~>"
|
18
46
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
47
|
+
version: '2.75'
|
20
48
|
type: :runtime
|
21
49
|
prerelease: false
|
22
50
|
version_requirements: !ruby/object:Gem::Requirement
|
23
51
|
requirements:
|
24
52
|
- - "~>"
|
25
53
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
54
|
+
version: '2.75'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
27
111
|
- !ruby/object:Gem::Dependency
|
28
112
|
name: sqlite3
|
29
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,7 +122,21 @@ dependencies:
|
|
38
122
|
- - ">="
|
39
123
|
- !ruby/object:Gem::Version
|
40
124
|
version: '0'
|
41
|
-
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: stripe-ruby-mock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '2.4'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '2.4'
|
139
|
+
description: A Ruby on Rails subscription engine.
|
42
140
|
email:
|
43
141
|
- jason@thecharnes.com
|
44
142
|
executables: []
|
@@ -56,9 +154,18 @@ files:
|
|
56
154
|
- app/jobs/pay/application_job.rb
|
57
155
|
- app/mailers/pay/application_mailer.rb
|
58
156
|
- app/models/pay/application_record.rb
|
157
|
+
- app/models/subscription.rb
|
59
158
|
- app/views/layouts/pay/application.html.erb
|
159
|
+
- config/initializers/pay.rb
|
160
|
+
- config/initializers/stripe.rb
|
60
161
|
- config/routes.rb
|
162
|
+
- db/development.sqlite3
|
163
|
+
- db/migrate/20170205020145_create_subscriptions.rb
|
164
|
+
- db/migrate/20170503131610_add_fields_to_users.rb
|
61
165
|
- lib/pay.rb
|
166
|
+
- lib/pay/billable.rb
|
167
|
+
- lib/pay/billable/braintree.rb
|
168
|
+
- lib/pay/billable/stripe.rb
|
62
169
|
- lib/pay/engine.rb
|
63
170
|
- lib/pay/version.rb
|
64
171
|
- lib/tasks/pay_tasks.rake
|
@@ -82,8 +189,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
189
|
version: '0'
|
83
190
|
requirements: []
|
84
191
|
rubyforge_project:
|
85
|
-
rubygems_version: 2.6.
|
192
|
+
rubygems_version: 2.6.12
|
86
193
|
signing_key:
|
87
194
|
specification_version: 4
|
88
|
-
summary: A
|
195
|
+
summary: A Ruby on Rails subscription engine.
|
89
196
|
test_files: []
|