pay 0.0.2 → 1.0.0.beta2
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 +5 -5
- data/MIT-LICENSE +1 -1
- data/README.md +256 -29
- data/Rakefile +1 -6
- data/app/controllers/pay/webhooks/braintree_controller.rb +56 -0
- data/app/jobs/pay/email_sync_job.rb +12 -0
- data/app/mailers/pay/user_mailer.rb +42 -0
- data/app/models/pay/charge.rb +31 -0
- data/app/models/pay/subscription.rb +77 -0
- data/app/views/pay/user_mailer/receipt.html.erb +20 -0
- data/app/views/pay/user_mailer/refund.html.erb +21 -0
- data/app/views/pay/user_mailer/subscription_renewing.html.erb +6 -0
- data/config/routes.rb +3 -1
- data/db/migrate/20170205020145_create_subscriptions.rb +1 -1
- data/db/migrate/20170503131610_add_fields_to_users.rb +3 -2
- data/db/migrate/20170727235816_create_charges.rb +17 -0
- data/lib/generators/pay/email_views_generator.rb +13 -0
- data/lib/pay.rb +65 -1
- data/lib/pay/billable.rb +54 -24
- data/lib/pay/billable/sync_email.rb +41 -0
- data/lib/pay/braintree.rb +16 -0
- data/lib/pay/braintree/api.rb +30 -0
- data/lib/pay/braintree/billable.rb +219 -0
- data/lib/pay/braintree/charge.rb +27 -0
- data/lib/pay/braintree/subscription.rb +173 -0
- data/lib/pay/engine.rb +14 -1
- data/lib/pay/receipts.rb +37 -0
- data/lib/pay/stripe.rb +17 -0
- data/lib/pay/stripe/api.rb +13 -0
- data/lib/pay/stripe/billable.rb +143 -0
- data/lib/pay/stripe/charge.rb +30 -0
- data/lib/pay/stripe/subscription.rb +48 -0
- data/lib/pay/stripe/webhooks.rb +39 -0
- data/lib/pay/stripe/webhooks/charge_refunded.rb +25 -0
- data/lib/pay/stripe/webhooks/charge_succeeded.rb +47 -0
- data/lib/pay/stripe/webhooks/customer_deleted.rb +31 -0
- data/lib/pay/stripe/webhooks/customer_updated.rb +19 -0
- data/lib/pay/stripe/webhooks/source_deleted.rb +19 -0
- data/lib/pay/stripe/webhooks/subscription_created.rb +46 -0
- data/lib/pay/stripe/webhooks/subscription_deleted.rb +21 -0
- data/lib/pay/stripe/webhooks/subscription_renewing.rb +25 -0
- data/lib/pay/stripe/webhooks/subscription_updated.rb +35 -0
- data/lib/pay/version.rb +1 -1
- metadata +124 -30
- data/app/models/subscription.rb +0 -59
- data/config/initializers/pay.rb +0 -3
- data/config/initializers/stripe.rb +0 -1
- data/db/development.sqlite3 +0 -0
- data/lib/pay/billable/braintree.rb +0 -57
- data/lib/pay/billable/stripe.rb +0 -47
- data/lib/tasks/pay_tasks.rake +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 39a6a209996b8c3b63ddb74f21be8d17077fc6319def22dab795978f5bdf2f35
|
4
|
+
data.tar.gz: 0b27221f94c0dbbb34f4a3931c2fa8b39b1961773069ba28a9979418631ed309
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd5f398491802b0040c20b074941b2848a693d4c85dc1d41ee6cdc60af283dc45b79248e8405acd5cf609efd897f273f1b7e47025f6929d0e22adfa63ca0c96a
|
7
|
+
data.tar.gz: 7daad387da4860cdeb62b67f3d7cec7de2056bf9842d7a9d735f72fa4aa6748112452205f2d0198e0737389b902008aa8cc148597dfb268e06e56ecf81b5454f
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,62 +1,110 @@
|
|
1
|
-
|
2
|
-
[ ![Codeship Status for jasoncharnes/pay](https://img.shields.io/codeship/72941cf0-31a8-0135-af58-3a3212f0f89d/master.svg)](https://app.codeship.com/projects/225793)
|
1
|
+
<p align="center"><img src="logo.png"></p>
|
3
2
|
|
4
|
-
Pay
|
3
|
+
## Pay
|
5
4
|
|
6
|
-
|
5
|
+
### Payments engine for Ruby on Rails
|
6
|
+
|
7
|
+
[![Build Status](https://travis-ci.org/excid3/pay.svg?branch=master)](https://travis-ci.org/excid3/pay)
|
8
|
+
|
9
|
+
Pay is a payments engine for Ruby on Rails 4.2 and higher.
|
7
10
|
|
8
11
|
**Current Payment Providers**
|
9
|
-
* Stripe
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
- Stripe (API version [2018-08-23](https://stripe.com/docs/upgrades#2018-08-23) or higher required)
|
14
|
+
- Braintree
|
13
15
|
|
14
16
|
Want to add a new payment provider? Contributions are welcome and the instructions [are here](https://github.com/jasoncharnes/pay/wiki/New-Payment-Provider).
|
15
17
|
|
16
18
|
## Installation
|
19
|
+
|
17
20
|
Add this line to your application's Gemfile:
|
18
21
|
|
19
22
|
```ruby
|
20
23
|
gem 'pay'
|
24
|
+
|
25
|
+
# To use Stripe, also include:
|
26
|
+
gem 'stripe', '< 5.0', '>= 2.8'
|
27
|
+
gem 'stripe_event', '~> 2.2'
|
28
|
+
|
29
|
+
# To use Braintree + PayPal, also include:
|
30
|
+
gem 'braintree', '< 3.0', '>= 2.92.0'
|
31
|
+
|
32
|
+
# To use Receipts
|
33
|
+
gem 'receipts', '~> 0.2.2'
|
21
34
|
```
|
22
35
|
|
23
36
|
And then execute:
|
37
|
+
|
24
38
|
```bash
|
25
39
|
$ bundle
|
26
40
|
```
|
27
41
|
|
28
42
|
Or install it yourself as:
|
43
|
+
|
29
44
|
```bash
|
30
45
|
$ gem install pay
|
31
46
|
```
|
32
47
|
|
33
48
|
## Setup
|
49
|
+
|
34
50
|
#### Migrations
|
51
|
+
|
35
52
|
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
53
|
|
37
54
|
To add the migrations to your application, run the following migration:
|
38
55
|
|
39
56
|
`$ bin/rails pay:install:migrations`
|
40
57
|
|
41
|
-
This will install
|
42
|
-
|
43
|
-
- db/migrate/
|
58
|
+
This will install three migrations:
|
59
|
+
|
60
|
+
- db/migrate/create_subscriptions.pay.rb
|
61
|
+
- db/migrate/add_fields_to_users.pay.rb
|
62
|
+
- db/migrate/create_charges.pay.rb
|
63
|
+
|
64
|
+
#### The User Model
|
65
|
+
|
66
|
+
If you have a `User` model defined in `app/models/user.rb` Pay will add the fields it needs to the `users` table.
|
67
|
+
|
68
|
+
If you do not have a `User` model defined, Pay will create a `users` table and you will need to add `app/models/user.rb`.
|
44
69
|
|
45
70
|
#### Non-User Model
|
71
|
+
|
46
72
|
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
73
|
|
48
74
|
#### Run the Migrations
|
75
|
+
|
49
76
|
Finally, run the migrations with `$ rake db:migrate`
|
50
77
|
|
78
|
+
#### Getting NoMethodError?
|
79
|
+
|
80
|
+
`NoMethodError (undefined method 'stripe_customer' for #<User:0x00007fbc34b9bf20>)`
|
81
|
+
|
82
|
+
Fully restart your Rails application `bin/spring stop && rails s`
|
83
|
+
|
51
84
|
#### Stripe
|
52
|
-
|
85
|
+
|
86
|
+
You'll need to add your private Stripe API key to your Rails secrets `config/secrets.yml`, credentials `rails credentials:edit`
|
53
87
|
|
54
88
|
```yaml
|
55
89
|
development:
|
56
|
-
|
90
|
+
stripe:
|
91
|
+
private_key: xxxx
|
92
|
+
public_key: yyyy
|
93
|
+
signing_secret: zzzz
|
57
94
|
```
|
58
95
|
|
96
|
+
You can also use the `STRIPE_PRIVATE_KEY` and `STRIPE_SIGNING_SECRET` environment variables.
|
97
|
+
|
98
|
+
**To see how to use Stripe Elements JS & Devise, [click here](https://github.com/jasoncharnes/pay/wiki/Using-Stripe-Elements-and-Devise).**
|
99
|
+
|
100
|
+
#### Background jobs
|
101
|
+
|
102
|
+
If a user's email is updated and they have a `processor_id` set, Pay will enqueue a background job (EmailSyncJob) to sync the email with the payment processor.
|
103
|
+
|
104
|
+
It's important you set a queue_adapter for this to happen. If you don't, the code will be executed immediately upon user update. [More information here](https://guides.rubyonrails.org/v4.2/active_job_basics.html#backends)
|
105
|
+
|
59
106
|
## Usage
|
107
|
+
|
60
108
|
Include the `Pay::Billable` module in the model you want to know about subscriptions.
|
61
109
|
|
62
110
|
```ruby
|
@@ -66,13 +114,125 @@ class User < ActiveRecord::Base
|
|
66
114
|
end
|
67
115
|
```
|
68
116
|
|
69
|
-
|
117
|
+
To sync over customer names, your `Billable` model should respond to the `first_name` and `last_name` methods. Pay will sync these over to your Customer objects in Stripe and Braintree.
|
118
|
+
|
119
|
+
## Configuration
|
120
|
+
|
121
|
+
Need to make some changes to how Pay is used? You can create an initializer `config/initializers/pay.rb`
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
Pay.setup do |config|
|
125
|
+
config.billable_class = 'User'
|
126
|
+
config.billable_table = 'users'
|
127
|
+
|
128
|
+
config.chargeable_class = 'Pay::Charge'
|
129
|
+
config.chargeable_table = 'pay_charges'
|
130
|
+
|
131
|
+
# For use in the receipt/refund/renewal mailers
|
132
|
+
config.business_name = "Business Name"
|
133
|
+
config.business_address = "1600 Pennsylvania Avenue NW"
|
134
|
+
config.application_name = "My App"
|
135
|
+
config.support_email = "helpme@example.com"
|
136
|
+
|
137
|
+
config.send_emails = true
|
138
|
+
end
|
139
|
+
```
|
140
|
+
|
141
|
+
This allows you to create your own Charge class for instance, which could add receipt functionality:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
class Charge < Pay::Charge
|
145
|
+
def receipts
|
146
|
+
# do some receipts stuff using the https://github.com/excid3/receipts gem
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
Pay.setup do |config|
|
151
|
+
config.chargeable_class = 'Charge'
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
### Generators
|
156
|
+
|
157
|
+
#### Email Templates
|
158
|
+
|
159
|
+
If you want to modify the email templates, you can copy over the view files using:
|
160
|
+
|
161
|
+
```
|
162
|
+
$ bin/rails generate pay:email_views
|
163
|
+
```
|
164
|
+
|
165
|
+
## Emails
|
166
|
+
|
167
|
+
### Stripe
|
168
|
+
|
169
|
+
Emails can be enabled/disabled using the `send_emails` configuration option (enabled per default). When enabled, the following emails will be sent:
|
170
|
+
|
171
|
+
- When a charge succeeded
|
172
|
+
- When a charge was refunded
|
173
|
+
- When a subscription is about to renew
|
70
174
|
|
71
175
|
## User API
|
176
|
+
|
177
|
+
#### Trials
|
178
|
+
|
179
|
+
You can check if the user is on a trial by simply asking:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
user = User.find_by(email: 'michael@bluthcompany.co')
|
183
|
+
|
184
|
+
user.on_trial? #=> true or false
|
185
|
+
```
|
186
|
+
|
187
|
+
The `on_trial?` method has two optional arguments with default values.
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
user = User.find_by(email: 'michael@bluthcompany.co')
|
191
|
+
|
192
|
+
user.on_trial?(name: 'default', plan: 'plan') #=> true or false
|
193
|
+
```
|
194
|
+
|
195
|
+
#### Generic Trials
|
196
|
+
|
197
|
+
For trials that don't require cards upfront:
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
user = User.create(
|
201
|
+
email: 'michael@bluthcompany.co',
|
202
|
+
trial_ends_at: 30.days.from_now
|
203
|
+
)
|
204
|
+
|
205
|
+
user.on_generic_trial? #=> true
|
206
|
+
```
|
207
|
+
|
208
|
+
#### Creating a Charge
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
user = User.find_by(email: 'michael@bluthcompany.co')
|
212
|
+
|
213
|
+
user.processor = 'stripe'
|
214
|
+
user.card_token = 'stripe-token'
|
215
|
+
user.charge(1500) # $15.00 USD
|
216
|
+
|
217
|
+
user = User.find_by(email: 'michael@bluthcompany.co')
|
218
|
+
|
219
|
+
user.processor = 'braintree'
|
220
|
+
user.card_token = 'nonce'
|
221
|
+
user.charge(1500) # $15.00 USD
|
222
|
+
```
|
223
|
+
|
224
|
+
The `charge` method takes the amount in cents as the primary argument.
|
225
|
+
|
226
|
+
You may pass optional arguments that will be directly passed on to
|
227
|
+
either Stripe or Braintree. You can use these options to charge
|
228
|
+
different currencies, etc.
|
229
|
+
|
72
230
|
#### Creating a Subscription
|
73
231
|
|
74
232
|
```ruby
|
75
233
|
user = User.find_by(email: 'michael@bluthcompany.co')
|
234
|
+
|
235
|
+
user.processor = 'stripe'
|
76
236
|
user.card_token = 'stripe-token'
|
77
237
|
user.subscribe
|
78
238
|
```
|
@@ -82,23 +242,39 @@ A `card_token` must be provided as an attribute.
|
|
82
242
|
The subscribe method has three optional arguments with default values.
|
83
243
|
|
84
244
|
```ruby
|
85
|
-
def subscribe(name
|
245
|
+
def subscribe(name: 'default', plan: 'default', **options)
|
86
246
|
...
|
87
247
|
end
|
88
248
|
```
|
89
249
|
|
90
250
|
##### Name
|
251
|
+
|
91
252
|
Name is an internally used name for the subscription.
|
92
253
|
|
93
254
|
##### Plan
|
255
|
+
|
94
256
|
Plan is the plan ID from the payment processor.
|
95
257
|
|
258
|
+
##### Options
|
259
|
+
|
260
|
+
They do something?
|
261
|
+
|
96
262
|
#### Retrieving a Subscription from the Database
|
263
|
+
|
97
264
|
```ruby
|
98
265
|
user = User.find_by(email: 'gob@bluthcompany.co')
|
266
|
+
|
99
267
|
user.subscription
|
100
268
|
```
|
101
269
|
|
270
|
+
A subscription can be retrieved by name, too.
|
271
|
+
|
272
|
+
```ruby
|
273
|
+
user = User.find_by(email: 'gob@bluthcompany.co')
|
274
|
+
|
275
|
+
user.subscription(name: 'bananastand+')
|
276
|
+
```
|
277
|
+
|
102
278
|
#### Checking a User's Subscription Status
|
103
279
|
|
104
280
|
```ruby
|
@@ -109,31 +285,32 @@ user.subscribed?
|
|
109
285
|
The `subscribed?` method has two optional arguments with default values.
|
110
286
|
|
111
287
|
```ruby
|
112
|
-
def subscribed?(name
|
288
|
+
def subscribed?(name: 'default', plan: nil)
|
113
289
|
...
|
114
290
|
end
|
115
291
|
```
|
116
292
|
|
117
293
|
##### Name
|
294
|
+
|
118
295
|
Name is an internally used name for the subscription.
|
119
296
|
|
120
297
|
##### Plan
|
121
|
-
Plan is the plan ID from the payment processor.
|
122
298
|
|
123
|
-
|
124
|
-
Processor is the string value of the payment processor subscription. Pay currently only supports Stripe, but other implementations are welcome.
|
299
|
+
Plan is the plan ID from the payment processor.
|
125
300
|
|
126
301
|
#### Retrieving a Payment Processor Account
|
127
302
|
|
128
303
|
```ruby
|
129
304
|
user = User.find_by(email: 'george.michael@bluthcompany.co')
|
130
|
-
|
305
|
+
|
306
|
+
user.customer #> Stripe or Braintree customer account
|
131
307
|
```
|
132
308
|
|
133
309
|
#### Updating a Customer's Credit Card
|
134
310
|
|
135
311
|
```ruby
|
136
312
|
user = User.find_by(email: 'tobias@bluthcompany.co')
|
313
|
+
|
137
314
|
user.update_card('stripe-token')
|
138
315
|
```
|
139
316
|
|
@@ -141,42 +318,49 @@ user.update_card('stripe-token')
|
|
141
318
|
|
142
319
|
```ruby
|
143
320
|
user = User.find_by(email: 'lucille@bluthcompany.co')
|
144
|
-
|
321
|
+
|
322
|
+
user.processor_subscription(subscription_id) #=> Stripe or Braintree Subscription
|
145
323
|
```
|
146
324
|
|
147
325
|
## Subscription API
|
326
|
+
|
148
327
|
#### Checking a Subscription's Trial Status
|
149
328
|
|
150
329
|
```ruby
|
151
330
|
user = User.find_by(email: 'lindsay@bluthcompany.co')
|
152
|
-
|
331
|
+
|
332
|
+
user.subscription.on_trial? #=> true or false
|
153
333
|
```
|
154
334
|
|
155
335
|
#### Checking a Subscription's Cancellation Status
|
156
336
|
|
157
337
|
```ruby
|
158
338
|
user = User.find_by(email: 'buster@bluthcompany.co')
|
159
|
-
|
339
|
+
|
340
|
+
user.subscription.cancelled? #=> true or false
|
160
341
|
```
|
161
342
|
|
162
343
|
#### Checking a Subscription's Grace Period Status
|
163
344
|
|
164
345
|
```ruby
|
165
346
|
user = User.find_by(email: 'her?@bluthcompany.co')
|
166
|
-
|
347
|
+
|
348
|
+
user.subscription.on_grace_period? #=> true or false
|
167
349
|
```
|
168
350
|
|
169
351
|
#### Checking to See If a Subscription Is Active
|
170
352
|
|
171
353
|
```ruby
|
172
354
|
user = User.find_by(email: 'carl.weathers@bluthcompany.co')
|
173
|
-
|
355
|
+
|
356
|
+
user.subscription.active? #=> true or false
|
174
357
|
```
|
175
358
|
|
176
359
|
#### Cancel a Subscription (At End of Billing Cycle)
|
177
360
|
|
178
361
|
```ruby
|
179
362
|
user = User.find_by(email: 'oscar@bluthcompany.co')
|
363
|
+
|
180
364
|
user.subscription.cancel
|
181
365
|
```
|
182
366
|
|
@@ -184,13 +368,23 @@ user.subscription.cancel
|
|
184
368
|
|
185
369
|
```ruby
|
186
370
|
user = User.find_by(email: 'annyong@bluthcompany.co')
|
371
|
+
|
187
372
|
user.subscription.cancel_now!
|
188
373
|
```
|
189
374
|
|
375
|
+
#### Swap a Subscription to another Plan
|
376
|
+
|
377
|
+
```ruby
|
378
|
+
user = User.find_by(email: 'steve.holt@bluthcompany.co')
|
379
|
+
|
380
|
+
user.subscription.swap("yearly")
|
381
|
+
```
|
382
|
+
|
190
383
|
#### Resume a Subscription on a Grace Period
|
191
384
|
|
192
385
|
```ruby
|
193
386
|
user = User.find_by(email: 'steve.holt@bluthcompany.co')
|
387
|
+
|
194
388
|
user.subscription.resume
|
195
389
|
```
|
196
390
|
|
@@ -198,23 +392,56 @@ user.subscription.resume
|
|
198
392
|
|
199
393
|
```ruby
|
200
394
|
user = User.find_by(email: 'lucille2@bluthcompany.co')
|
395
|
+
|
201
396
|
user.subscription.processor_subscription
|
202
397
|
```
|
203
398
|
|
399
|
+
### Customizing Pay Models
|
400
|
+
|
401
|
+
Want to add methods to `Pay::Subscription` or `Pay::Charge`? You can
|
402
|
+
define a concern and simply include it in the model when Rails loads the
|
403
|
+
code.
|
404
|
+
|
405
|
+
Pay uses the `to_prepare` method to allow concerns to be
|
406
|
+
included every time Rails reloads the models in development as well.
|
407
|
+
|
408
|
+
```ruby
|
409
|
+
# app/models/concerns/subscription_extensions.rb
|
410
|
+
module SubscriptionExtensions
|
411
|
+
extend ActiveSupport::Concern
|
412
|
+
|
413
|
+
included do
|
414
|
+
# associations and other class level things go here
|
415
|
+
end
|
416
|
+
|
417
|
+
# instance methods and code go here
|
418
|
+
end
|
419
|
+
```
|
420
|
+
|
421
|
+
```ruby
|
422
|
+
# config/initializers/subscription_extensions.rb
|
423
|
+
|
424
|
+
# Re-include the SubscriptionExtensions every time Rails reloads
|
425
|
+
Rails.application.config.to_prepare do
|
426
|
+
Pay.subscription_model.include SubscriptionExtensions
|
427
|
+
end
|
428
|
+
```
|
429
|
+
|
204
430
|
## Contributors
|
205
|
-
|
206
|
-
|
431
|
+
|
432
|
+
- [Jason Charnes](https://twitter.com/jmcharnes)
|
433
|
+
- [Chris Oliver](https://twitter.com/excid3)
|
207
434
|
|
208
435
|
## Contributing
|
436
|
+
|
209
437
|
👋 Thanks for your interest in contributing. Feel free to fork this repo.
|
210
438
|
|
211
439
|
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
440
|
|
213
441
|
If you'd like to open a PR please make sure the following things pass:
|
214
|
-
* `rake test`
|
215
|
-
* `rubocop`
|
216
442
|
|
217
|
-
|
443
|
+
- `rake test`
|
218
444
|
|
219
445
|
## License
|
446
|
+
|
220
447
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|