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.

Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +256 -29
  4. data/Rakefile +1 -6
  5. data/app/controllers/pay/webhooks/braintree_controller.rb +56 -0
  6. data/app/jobs/pay/email_sync_job.rb +12 -0
  7. data/app/mailers/pay/user_mailer.rb +42 -0
  8. data/app/models/pay/charge.rb +31 -0
  9. data/app/models/pay/subscription.rb +77 -0
  10. data/app/views/pay/user_mailer/receipt.html.erb +20 -0
  11. data/app/views/pay/user_mailer/refund.html.erb +21 -0
  12. data/app/views/pay/user_mailer/subscription_renewing.html.erb +6 -0
  13. data/config/routes.rb +3 -1
  14. data/db/migrate/20170205020145_create_subscriptions.rb +1 -1
  15. data/db/migrate/20170503131610_add_fields_to_users.rb +3 -2
  16. data/db/migrate/20170727235816_create_charges.rb +17 -0
  17. data/lib/generators/pay/email_views_generator.rb +13 -0
  18. data/lib/pay.rb +65 -1
  19. data/lib/pay/billable.rb +54 -24
  20. data/lib/pay/billable/sync_email.rb +41 -0
  21. data/lib/pay/braintree.rb +16 -0
  22. data/lib/pay/braintree/api.rb +30 -0
  23. data/lib/pay/braintree/billable.rb +219 -0
  24. data/lib/pay/braintree/charge.rb +27 -0
  25. data/lib/pay/braintree/subscription.rb +173 -0
  26. data/lib/pay/engine.rb +14 -1
  27. data/lib/pay/receipts.rb +37 -0
  28. data/lib/pay/stripe.rb +17 -0
  29. data/lib/pay/stripe/api.rb +13 -0
  30. data/lib/pay/stripe/billable.rb +143 -0
  31. data/lib/pay/stripe/charge.rb +30 -0
  32. data/lib/pay/stripe/subscription.rb +48 -0
  33. data/lib/pay/stripe/webhooks.rb +39 -0
  34. data/lib/pay/stripe/webhooks/charge_refunded.rb +25 -0
  35. data/lib/pay/stripe/webhooks/charge_succeeded.rb +47 -0
  36. data/lib/pay/stripe/webhooks/customer_deleted.rb +31 -0
  37. data/lib/pay/stripe/webhooks/customer_updated.rb +19 -0
  38. data/lib/pay/stripe/webhooks/source_deleted.rb +19 -0
  39. data/lib/pay/stripe/webhooks/subscription_created.rb +46 -0
  40. data/lib/pay/stripe/webhooks/subscription_deleted.rb +21 -0
  41. data/lib/pay/stripe/webhooks/subscription_renewing.rb +25 -0
  42. data/lib/pay/stripe/webhooks/subscription_updated.rb +35 -0
  43. data/lib/pay/version.rb +1 -1
  44. metadata +124 -30
  45. data/app/models/subscription.rb +0 -59
  46. data/config/initializers/pay.rb +0 -3
  47. data/config/initializers/stripe.rb +0 -1
  48. data/db/development.sqlite3 +0 -0
  49. data/lib/pay/billable/braintree.rb +0 -57
  50. data/lib/pay/billable/stripe.rb +0 -47
  51. data/lib/tasks/pay_tasks.rake +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 92f9482ce3c201c076c2717a75c9e0670f412c4b
4
- data.tar.gz: cd8a5de08bf9fdf46b71648202967b3202615f9c
2
+ SHA256:
3
+ metadata.gz: 39a6a209996b8c3b63ddb74f21be8d17077fc6319def22dab795978f5bdf2f35
4
+ data.tar.gz: 0b27221f94c0dbbb34f4a3931c2fa8b39b1961773069ba28a9979418631ed309
5
5
  SHA512:
6
- metadata.gz: 7383c1f3dcbd887dd185c4cc28277513e4d9f1ab29229ebb042342ffb3301ad2e25e86dd45889c88b85df6a388ee831152c7ba594ccc14aef30f4ee0dae27336
7
- data.tar.gz: a8431aee8abb65ff7d8550ed471ebdada798b686de30bfe21830554c1e59d509406e0031fd834236e1bbdd56cfb12f1c67b1c2455fff1a42a0a252da777dcf41
6
+ metadata.gz: cd5f398491802b0040c20b074941b2848a693d4c85dc1d41ee6cdc60af283dc45b79248e8405acd5cf609efd897f273f1b7e47025f6929d0e22adfa63ca0c96a
7
+ data.tar.gz: 7daad387da4860cdeb62b67f3d7cec7de2056bf9842d7a9d735f72fa4aa6748112452205f2d0198e0737389b902008aa8cc148597dfb268e06e56ecf81b5454f
@@ -1,4 +1,4 @@
1
- Copyright 2017 Jason Charnes
1
+ Copyright 2019 Jason Charnes
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,62 +1,110 @@
1
- # Pay
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 is a subscription engine for Ruby on Rails.
3
+ ## Pay
5
4
 
6
- Supports Ruby on Rails 4.2 and higher.
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
- **Payment Providers In Development**
12
- * Braintree
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 two migrations:
42
- - db/migrate/create_subscriptions.rb
43
- - db/migrate/add_fields_to_users.rb
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
- You'll need to add your private Stripe API key to your Rails secrets. `config/secrets.yml`
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
- stripe_api_key: sk_test_....
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
- **To see how to use Stripe Elements JS & Devise, [click here](https://github.com/jasoncharnes/pay/wiki/Using-Stripe-Elements-and-Devise).**
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 = 'default', plan = 'default', processor = 'stripe')
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 = 'default', plan = nil)
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
- ##### Processor
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
- user.customer
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
- user.processor_subscription(subscription_id)
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
- user.subscription.on_trial?
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
- user.subscription.cancelled?
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
- user.subscription.on_grace_period?
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
- user.subscription.active?
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
- * [Jason Charnes](https://twitter.com/jmcharnes)
206
- * [Chris Oliver](https://twitter.com/excid3)
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
- These will need to be passing in order for a Pull Request to be accepted.
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).