pay 2.7.1 → 3.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.

Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -715
  3. data/app/controllers/pay/webhooks/braintree_controller.rb +10 -3
  4. data/app/controllers/pay/webhooks/paddle_controller.rb +7 -8
  5. data/app/controllers/pay/webhooks/stripe_controller.rb +6 -3
  6. data/app/jobs/pay/{email_sync_job.rb → customer_sync_job.rb} +3 -4
  7. data/app/models/pay/application_record.rb +1 -5
  8. data/app/models/pay/charge.rb +54 -17
  9. data/app/models/pay/customer.rb +87 -0
  10. data/app/models/pay/merchant.rb +19 -0
  11. data/app/models/pay/payment_method.rb +41 -0
  12. data/app/models/pay/subscription.rb +42 -30
  13. data/app/models/pay/webhook.rb +36 -0
  14. data/app/views/layouts/pay/application.html.erb +2 -3
  15. data/app/views/pay/payments/show.html.erb +108 -81
  16. data/app/views/pay/user_mailer/receipt.html.erb +2 -2
  17. data/app/views/pay/user_mailer/refund.html.erb +2 -2
  18. data/config/locales/en.yml +1 -1
  19. data/db/migrate/1_create_pay_tables.rb +72 -0
  20. data/lib/generators/active_record/templates/billable_migration.rb +1 -0
  21. data/lib/pay/attributes.rb +74 -0
  22. data/lib/pay/billable/sync_customer.rb +30 -0
  23. data/lib/pay/braintree/billable.rb +133 -110
  24. data/lib/pay/braintree/payment_method.rb +42 -0
  25. data/lib/pay/braintree/subscription.rb +9 -12
  26. data/lib/pay/braintree/webhooks/subscription_canceled.rb +1 -1
  27. data/lib/pay/braintree/webhooks/subscription_charged_successfully.rb +4 -4
  28. data/lib/pay/braintree/webhooks/subscription_charged_unsuccessfully.rb +1 -1
  29. data/lib/pay/braintree/webhooks/subscription_expired.rb +1 -1
  30. data/lib/pay/braintree/webhooks/subscription_trial_ended.rb +2 -2
  31. data/lib/pay/braintree/webhooks/subscription_went_active.rb +1 -1
  32. data/lib/pay/braintree/webhooks/subscription_went_past_due.rb +1 -1
  33. data/lib/pay/braintree.rb +3 -2
  34. data/lib/pay/engine.rb +6 -1
  35. data/lib/pay/fake_processor/billable.rb +45 -21
  36. data/lib/pay/fake_processor/payment_method.rb +21 -0
  37. data/lib/pay/fake_processor/subscription.rb +11 -8
  38. data/lib/pay/fake_processor.rb +2 -1
  39. data/lib/pay/nano_id.rb +13 -0
  40. data/lib/pay/paddle/billable.rb +18 -48
  41. data/lib/pay/paddle/charge.rb +5 -5
  42. data/lib/pay/paddle/payment_method.rb +60 -0
  43. data/lib/pay/paddle/response.rb +0 -0
  44. data/lib/pay/paddle/subscription.rb +49 -8
  45. data/lib/pay/paddle/webhooks/subscription_cancelled.rb +6 -3
  46. data/lib/pay/paddle/webhooks/subscription_created.rb +1 -40
  47. data/lib/pay/paddle/webhooks/subscription_payment_refunded.rb +3 -3
  48. data/lib/pay/paddle/webhooks/subscription_payment_succeeded.rb +26 -28
  49. data/lib/pay/paddle/webhooks/subscription_updated.rb +2 -2
  50. data/lib/pay/paddle.rb +7 -3
  51. data/lib/pay/payment.rb +1 -1
  52. data/lib/pay/receipts.rb +35 -7
  53. data/lib/pay/stripe/billable.rb +75 -76
  54. data/lib/pay/stripe/charge.rb +44 -17
  55. data/lib/pay/stripe/merchant.rb +10 -10
  56. data/lib/pay/stripe/payment_method.rb +61 -0
  57. data/lib/pay/stripe/subscription.rb +55 -22
  58. data/lib/pay/stripe/webhooks/account_updated.rb +2 -3
  59. data/lib/pay/stripe/webhooks/charge_refunded.rb +1 -1
  60. data/lib/pay/stripe/webhooks/charge_succeeded.rb +2 -2
  61. data/lib/pay/stripe/webhooks/checkout_session_async_payment_succeeded.rb +3 -1
  62. data/lib/pay/stripe/webhooks/checkout_session_completed.rb +3 -1
  63. data/lib/pay/stripe/webhooks/customer_deleted.rb +7 -15
  64. data/lib/pay/stripe/webhooks/customer_updated.rb +10 -3
  65. data/lib/pay/stripe/webhooks/payment_action_required.rb +2 -2
  66. data/lib/pay/stripe/webhooks/payment_intent_succeeded.rb +6 -8
  67. data/lib/pay/stripe/webhooks/payment_method_attached.rb +15 -0
  68. data/lib/pay/stripe/webhooks/payment_method_detached.rb +12 -0
  69. data/lib/pay/stripe/webhooks/payment_method_updated.rb +10 -4
  70. data/lib/pay/stripe/webhooks/subscription_created.rb +1 -1
  71. data/lib/pay/stripe/webhooks/subscription_deleted.rb +2 -1
  72. data/lib/pay/stripe/webhooks/subscription_renewing.rb +12 -2
  73. data/lib/pay/stripe.rb +6 -3
  74. data/lib/pay/version.rb +1 -1
  75. data/lib/pay/webhooks/delegator.rb +4 -0
  76. data/lib/pay/webhooks/process_job.rb +9 -0
  77. data/lib/pay/webhooks.rb +1 -0
  78. data/lib/pay.rb +7 -78
  79. data/lib/tasks/pay.rake +20 -0
  80. metadata +23 -36
  81. data/app/models/pay.rb +0 -5
  82. data/db/migrate/20170205020145_create_pay_subscriptions.rb +0 -17
  83. data/db/migrate/20170727235816_create_pay_charges.rb +0 -18
  84. data/db/migrate/20190816015720_add_status_to_pay_subscriptions.rb +0 -14
  85. data/db/migrate/20200603134434_add_data_to_pay_models.rb +0 -6
  86. data/db/migrate/20210309004259_add_data_to_pay_billable.rb +0 -10
  87. data/db/migrate/20210406215234_add_currency_to_pay_charges.rb +0 -5
  88. data/db/migrate/20210406215506_add_application_fee_to_pay_models.rb +0 -7
  89. data/lib/pay/billable/sync_email.rb +0 -40
  90. data/lib/pay/billable.rb +0 -172
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a90781f9b476b2396d1ab4ea8d1a6317b46ac6289f5c4afef96dc991af035fd0
4
- data.tar.gz: 8d20e7c6edcb13eb62d5ad398c4ab12a353e3be784c7651d795efd9feeb18402
3
+ metadata.gz: 72854ccf4950082b24ff854f6c20b9dfd27ed606af82032ac57edef72c5722a5
4
+ data.tar.gz: dfe726cedf8ac7afd9ff5b4fa87cd96563244f493f1e3f399c749b3492c534d7
5
5
  SHA512:
6
- metadata.gz: 11f281fe1df7c9eabfef2d4a0242257001115b3f7eaaa5571d73cbdacb1810891a0a57ab24a23caa01458de399093b3c82a3c251237e9d3d13f993e670f06b04
7
- data.tar.gz: 11d760da77af12107686c4e91fcbec0f7bf4aa91e99d41281f1510bedabc00406146ade7656477ffa5ee4dda4e7b07af55a9dd0ae7675d1e780e8f4f121d6cc5
6
+ metadata.gz: acadc8b9c2de89ff113ef75550fb6f82dc79cb3a4bca20834bdfa6ed47e81397405782cef60462248e98a68ab9833ab4bf61429dbd92b0891642e35825b98348
7
+ data.tar.gz: 709dd5387de015deb67eaaf7a770bd6b23ff2b70159c8f22ee5b2063c0bbda4326af67b24effcc19280604dc98373894b42260e728b00ec1b42c480c3bb27a67
data/README.md CHANGED
@@ -1,739 +1,57 @@
1
1
  <p align="center"><img src="docs/images/logo.svg" height="50px"></p>
2
2
 
3
- ## Pay - Payments engine for Ruby on Rails
3
+ # 💳 Pay - Payments engine for Ruby on Rails
4
4
 
5
5
  [![Build Status](https://github.com/pay-rails/pay/workflows/Tests/badge.svg)](https://github.com/pay-rails/pay/actions) [![Gem Version](https://badge.fury.io/rb/pay.svg)](https://badge.fury.io/rb/pay)
6
6
 
7
7
  <img src="docs/images/stripe_partner_badge.svg" height="26px">
8
8
 
9
- Pay is a payments engine for Ruby on Rails 4.2 and higher.
9
+ Pay is a payments engine for Ruby on Rails 6.0 and higher.
10
10
 
11
- **Current Payment Providers**
11
+ ⚠️ **Upgrading?** Check the [UPGRADE](UPGRADE.md) guide for required changes and/or migration when upgrading from a previous version of Pay.
12
12
 
13
- - Stripe ([SCA Compatible](https://stripe.com/docs/strong-customer-authentication) using API version `2020-08-27`)
14
- - Paddle (SCA Compatible & supports PayPal)
15
- - Braintree (supports PayPal)
16
- - [Fake Processor](docs/fake_processor.md)
17
-
18
- Want to add a new payment provider? Contributions are welcome and the instructions [are here](https://github.com/jasoncharnes/pay/wiki/New-Payment-Provider).
19
-
20
- **Check the CHANGELOG for any required migrations or changes needed if you're upgrading from a previous version of Pay.**
21
-
22
- ## Tutorial
13
+ ## 🧑‍💻 Tutorial
23
14
 
24
15
  Want to see how Pay works? Check out our video getting started guide.
25
16
 
26
17
  <a href="https://www.youtube.com/watch?v=hYlOmqyJIgc" target="_blank"><img width="50%" src="http://i3.ytimg.com/vi/hYlOmqyJIgc/maxresdefault.jpg"></a>
27
18
 
28
- ## Installation
29
-
30
- Add these lines to your application's Gemfile:
31
-
32
- ```ruby
33
- gem 'pay', '~> 2.0'
34
-
35
- # To use Stripe, also include:
36
- gem 'stripe', '< 6.0', '>= 2.8'
37
-
38
- # To use Braintree + PayPal, also include:
39
- gem 'braintree', '< 3.0', '>= 2.92.0'
40
-
41
- # To use Paddle, also include:
42
- gem 'paddle_pay', '~> 0.1'
43
-
44
- # To use Receipts
45
- gem 'receipts', '~> 1.0.0'
46
- ```
47
-
48
- And then execute:
49
-
50
- ```bash
51
- bundle
52
- ```
53
-
54
- Next, we need to add migrations to your application, run the following migration:
55
-
56
- ````bash
57
- bin/rails pay:install:migrations
58
- ````
59
-
60
- >If your models rely on non integer ids (uuids for example) you will need to alter the `create_pay_subscriptions` and `create_pay_charges` migrations.
61
-
62
- We also need to run migrations to add Pay to the User, Account, Team, etc models that we want to make payments in our app.
63
-
64
- ```bash
65
- bin/rails g pay:billable User
66
- ```
67
-
68
- This will generate a migration to add Pay fields to our User model and automatically includes the `Pay::Billable` module in our `User` model. Repeat this for all the models you want to make payments in your app.
69
-
70
- **Note:** An `email` attribute or method on your `Billable` model is required.
71
-
72
- To sync 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.
73
-
74
- Finally, run the migrations
75
-
76
- ```bash
77
- rake db:migrate
78
- ```
79
-
80
- > If you run into `NoMethodError (undefined method 'stripe_customer' for #<User:0x00007fbc34b9bf20>)`, fully restart your Rails application `bin/spring stop && rails s`
81
-
82
- Lastly, make sure you've configured your ActionMailer default_url_options so Pay can generate links to for features like Stripe Checkout.
83
-
84
- ```ruby
85
- # config/application.rb
86
- config.action_mailer.default_url_options = { host: "example.com" }
87
- ```
88
-
89
- ## Configuration
90
-
91
- Need to make some changes to how Pay is used? You can create an initializer `config/initializers/pay.rb`
92
-
93
- ```ruby
94
- Pay.setup do |config|
95
- # config.chargeable_class = 'Pay::Charge'
96
- # config.chargeable_table = 'pay_charges'
97
-
98
- # For use in the receipt/refund/renewal mailers
99
- config.business_name = "Business Name"
100
- config.business_address = "1600 Pennsylvania Avenue NW"
101
- config.application_name = "My App"
102
- config.support_email = "helpme@example.com"
103
-
104
- config.send_emails = true
105
-
106
- config.default_product_name = "default"
107
- config.default_plan_name = "default"
108
-
109
- config.automount_routes = true
110
- config.routes_path = "/pay" # Only when automount_routes is true
111
- end
112
- ```
113
-
114
- This allows you to create your own Charge class for instance, which could add receipt functionality:
115
-
116
- ```ruby
117
- class Charge < Pay::Charge
118
- def receipts
119
- # do some receipts stuff using the https://github.com/excid3/receipts gem
120
- end
121
- end
122
-
123
- Pay.setup do |config|
124
- config.chargeable_class = 'Charge'
125
- end
126
- ```
127
-
128
- ### Credentials
129
-
130
- Pay automatically looks up credentials for each payment provider. We recommend storing them in the Rails credentials.
131
-
132
- ##### Rails Credentials & Secrets
133
-
134
- You'll need to add your API keys to your Rails credentials. You can do this by running:
135
-
136
- ```bash
137
- rails credentials:edit --environment=development
138
- ```
139
-
140
- They should be formatted like the following:
141
-
142
- ```yaml
143
- stripe:
144
- private_key: xxxx
145
- public_key: yyyy
146
- signing_secret: zzzz
147
- braintree:
148
- private_key: xxxx
149
- public_key: yyyy
150
- merchant_id: aaaa
151
- environment: sandbox
152
- paddle:
153
- vendor_id: xxxx
154
- vendor_auth_code: yyyy
155
- public_key_base64: MII...==
156
- environment: sandbox
157
- ```
158
-
159
- You can also nest these credentials under the Rails environment if using a shared credentials file or secrets.
160
-
161
- ```yaml
162
- development:
163
- stripe:
164
- private_key: xxxx
165
- # ...
166
- ```
167
-
168
- ##### Environment Variables
169
-
170
- Pay will also check environment variables for API keys:
171
-
172
- * `STRIPE_PUBLIC_KEY`
173
- * `STRIPE_PRIVATE_KEY`
174
- * `STRIPE_SIGNING_SECRET`
175
- * `BRAINTREE_MERCHANT_ID`
176
- * `BRAINTREE_PUBLIC_KEY`
177
- * `BRAINTREE_PRIVATE_KEY`
178
- * `BRAINTREE_ENVIRONMENT`
179
- * `PADDLE_VENDOR_ID`
180
- * `PADDLE_VENDOR_AUTH_CODE`
181
- * `PADDLE_PUBLIC_KEY_BASE64`
182
- * `PADDLE_ENVIRONMENT`
183
-
184
- ### Generators
185
-
186
- If you want to modify the Stripe SCA template or any other views, you can copy over the view files using:
187
-
188
- ```bash
189
- bin/rails generate pay:views
190
- ```
191
-
192
- If you want to modify the email templates, you can copy over the view files using:
193
-
194
- ```bash
195
- bin/rails generate pay:email_views
196
- ```
197
-
198
- ### Emails
199
-
200
- Emails can be enabled/disabled using the `send_emails` configuration option (enabled by default).
201
-
202
- When enabled, the following emails will be sent when:
203
-
204
- - A charge succeeded
205
- - A charge was refunded
206
- - A subscription is about to renew
207
-
208
-
209
- ## Billable API
210
-
211
- #### Trials
212
-
213
- You can check if the user is on a trial by simply asking:
214
-
215
- ```ruby
216
- user = User.find_by(email: 'michael@bluthcompany.co')
217
-
218
- user.on_trial? #=> true or false
219
- ```
220
-
221
- The `on_trial?` method has two optional arguments with default values.
222
-
223
- ```ruby
224
- user = User.find_by(email: 'michael@bluthcompany.co')
225
-
226
- user.on_trial?(name: 'default', plan: 'plan') #=> true or false
227
- ```
228
-
229
- #### Generic Trials
230
-
231
- For trials that don't require cards upfront:
232
-
233
- ```ruby
234
- user = User.create(
235
- email: 'michael@bluthcompany.co',
236
- trial_ends_at: 30.days.from_now
237
- )
238
-
239
- user.on_generic_trial? #=> true
240
- ```
241
-
242
- #### Creating a Charge
243
-
244
- ##### Stripe and Braintree
245
-
246
- ```ruby
247
- user = User.find_by(email: 'michael@bluthcompany.co')
248
-
249
- user.processor = 'stripe'
250
- user.card_token = 'payment_method_id'
251
- user.charge(1500) # $15.00 USD
252
-
253
- user = User.find_by(email: 'michael@bluthcompany.co')
254
-
255
- user.processor = 'braintree'
256
- user.card_token = 'nonce'
257
- user.charge(1500) # $15.00 USD
258
- ```
259
-
260
- The `charge` method takes the amount in cents as the primary argument.
261
-
262
- You may pass optional arguments that will be directly passed on to
263
- either Stripe or Braintree. You can use these options to charge
264
- different currencies, etc.
265
-
266
- On failure, a `Pay::Error` will be raised with details about the payment
267
- failure.
268
-
269
- ##### Paddle
270
- It is only possible to create immediate one-time charges on top of an existing subscription.
271
-
272
- ```ruby
273
- user = User.find_by(email: 'michael@bluthcompany.co')
274
-
275
- user.processor = 'paddle'
276
- user.charge(1500, {charge_name: "Test"}) # $15.00 USD
277
-
278
- ```
279
-
280
- An existing subscription and a charge name are required.
281
-
282
- #### Creating a Subscription
283
-
284
- ##### Stripe and Braintree
285
-
286
- ```ruby
287
- user = User.find_by(email: 'michael@bluthcompany.co')
288
-
289
- user.processor = 'stripe'
290
- user.card_token = 'payment_method_id'
291
- user.subscribe
292
- ```
293
-
294
- A `card_token` must be provided as an attribute.
295
-
296
- The subscribe method has three optional arguments with default values.
297
-
298
- ```ruby
299
- def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options)
300
- ...
301
- end
302
- ```
303
-
304
- For example, you can pass the `quantity` option to subscribe to a plan with for per-seat pricing.
305
-
306
- ```ruby
307
-
308
- user.subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, quantity: 3)
309
- ```
310
-
311
- ###### Name
312
-
313
- Name is an internally used name for the subscription.
314
-
315
- ###### Plan
316
-
317
- Plan is the plan ID or price ID from the payment processor. For example: `plan_xxxxx` or `price_xxxxx`
318
-
319
- ###### Options
320
-
321
- By default, the trial specified on the subscription will be used.
322
-
323
- `trial_period_days: 30` can be set to override and a trial to the subscription. This works the same for Braintree and Stripe.
324
-
325
- ##### Paddle
326
- It is currently not possible to create a subscription through the API. Instead the subscription in Pay is created by the Paddle Subscription Webhook. In order to be able to assign the subcription to the correct owner, the Paddle [passthrough parameter](https://developer.paddle.com/guides/how-tos/checkout/pass-parameters) has to be used for checkout.
327
-
328
- To ensure that the owner cannot be tampered with, Pay uses a Signed Global ID with a purpose. The purpose string consists of "paddle_" and the subscription plan id (or product id respectively).
329
-
330
- Javascript Checkout:
331
- ```javascript
332
- Paddle.Checkout.open({
333
- product: 12345,
334
- passthrough: "<%= Pay::Paddle.passthrough(owner: current_user) %>"
335
- });
336
- ```
337
-
338
- Paddle Button Checkout:
339
- ```html
340
- <a href="#!" class="paddle_button" data-product="12345" data-email="<%= current_user.email %>" data-passthrough="<%= Pay::Paddle.passthrough(owner: current_user) %>"
341
- ```
342
-
343
- ###### Passthrough
344
-
345
- Pay providers a helper method for generating the passthrough JSON object to associate the purchase with the correct Rails model.
346
-
347
- ```ruby
348
- Pay::Paddle.passthrough(owner: current_user, foo: :bar)
349
- #=> { owner_sgid: "xxxxxxxx", foo: "bar" }
350
-
351
- # To generate manually without the helper
352
- #=> { owner_sgid: current_user.to_sgid.to_s, foo: "bar" }.to_json
353
- ```
354
-
355
- Pay parses the passthrough JSON string and verifies the `owner_sgid` hash to match the webhook with the correct billable record.
356
- The passthrough parameter `owner_sgid` is only required for creating a subscription.
357
-
358
- #### Retrieving a Subscription from the Database
359
-
360
- ```ruby
361
- user = User.find_by(email: 'gob@bluthcompany.co')
362
-
363
- user.subscription
364
- ```
365
-
366
- A subscription can be retrieved by name, too.
367
-
368
- ```ruby
369
- user = User.find_by(email: 'gob@bluthcompany.co')
370
-
371
- user.subscription(name: 'bananastand+')
372
- ```
373
-
374
- #### Checking a User's Trial/Subscription Status
375
-
376
- ```ruby
377
- user = User.find_by(email: 'george.senior@bluthcompany.co')
378
- user.on_trial_or_subscribed?
379
- ```
380
-
381
- The `on_trial_or_subscribed?` method has two optional arguments with default values.
382
-
383
- ```ruby
384
- def on_trial_or_subscribed?(name: 'default', plan: nil)
385
- ...
386
- end
387
- ```
388
-
389
- #### Checking a User's Subscription Status
390
-
391
- ```ruby
392
- user = User.find_by(email: 'george.senior@bluthcompany.co')
393
- user.subscribed?
394
- ```
395
-
396
- The `subscribed?` method has two optional arguments with default values.
397
-
398
- ```ruby
399
- def subscribed?(name: 'default', plan: nil)
400
- ...
401
- end
402
- ```
403
-
404
- ##### Name
405
-
406
- Name is an internally used name for the subscription.
407
-
408
- ##### Plan
409
-
410
- Plan is the plan ID from the payment processor.
411
-
412
- #### Retrieving a Payment Processor Account
413
-
414
- ##### Stripe and Braintree
415
-
416
- ```ruby
417
- user = User.find_by(email: 'george.michael@bluthcompany.co')
418
-
419
- user.customer #> Stripe or Braintree customer account
420
- ```
421
-
422
- ##### Paddle
423
-
424
- It is currently not possible to retrieve a payment processor account through the API.
425
-
426
- #### Updating a Customer's Credit Card
427
-
428
- ##### Stripe and Braintree
429
-
430
- ```ruby
431
- user = User.find_by(email: 'tobias@bluthcompany.co')
432
-
433
- user.update_card('payment_method_id')
434
- ```
435
-
436
- ##### Paddle
437
-
438
- Paddle provides a unique [Update URL](https://developer.paddle.com/guides/how-tos/subscriptions/update-payment-details) for each user, which allows them to update the payment method.
439
- ```ruby
440
- user = User.find_by(email: 'tobias@bluthcompany.co')
441
-
442
- user.subscription.paddle_update_url
443
- ```
444
-
445
-
446
-
447
- #### Retrieving a Customer's Subscription from the Processor
448
-
449
- ```ruby
450
- user = User.find_by(email: 'lucille@bluthcompany.co')
451
-
452
- user.processor_subscription(subscription_id) #=> Stripe, Braintree or Paddle Subscription
453
- ```
454
-
455
- ## Subscription API
456
-
457
- #### Checking a Subscription's Trial Status
458
-
459
- ```ruby
460
- user = User.find_by(email: 'lindsay@bluthcompany.co')
461
-
462
- user.subscription.on_trial? #=> true or false
463
- ```
19
+ ## 🏦 Payment Processors
464
20
 
465
- #### Checking a Subscription's Cancellation Status
21
+ Our supported payment processors are:
466
22
 
467
- ```ruby
468
- user = User.find_by(email: 'buster@bluthcompany.co')
469
-
470
- user.subscription.cancelled? #=> true or false
471
- ```
472
-
473
- #### Checking a Subscription's Grace Period Status
474
-
475
- ```ruby
476
- user = User.find_by(email: 'her?@bluthcompany.co')
477
-
478
- user.subscription.on_grace_period? #=> true or false
479
- ```
480
-
481
- #### Checking to See If a Subscription Is Active
482
-
483
- ```ruby
484
- user = User.find_by(email: 'carl.weathers@bluthcompany.co')
485
-
486
- user.subscription.active? #=> true or false
487
- ```
488
-
489
- #### Checking to See If a Subscription Is Paused
490
-
491
- ```ruby
492
- user = User.find_by(email: 'carl.weathers@bluthcompany.co')
493
-
494
- user.subscription.paused? #=> true or false
495
- ```
496
-
497
- #### Cancel a Subscription (At End of Billing Cycle)
498
-
499
- ##### Stripe, Braintree and Paddle
500
-
501
- ```ruby
502
- user = User.find_by(email: 'oscar@bluthcompany.co')
503
-
504
- user.subscription.cancel
505
- ```
506
-
507
- ##### Paddle
508
- In addition to the API, Paddle provides a subscription [Cancel URL](https://developer.paddle.com/guides/how-tos/subscriptions/cancel-and-pause) that you can redirect customers to cancel their subscription.
509
-
510
- ```ruby
511
- user.subscription.paddle_cancel_url
512
- ```
513
-
514
- #### Cancel a Subscription Immediately
515
-
516
- ```ruby
517
- user = User.find_by(email: 'annyong@bluthcompany.co')
518
-
519
- user.subscription.cancel_now!
520
- ```
521
-
522
- #### Pause a Subscription
523
-
524
- ##### Paddle
525
-
526
- ```ruby
527
- user = User.find_by(email: 'oscar@bluthcompany.co')
528
-
529
- user.subscription.pause
530
- ```
531
-
532
- #### Swap a Subscription to another Plan
533
-
534
- ```ruby
535
- user = User.find_by(email: 'steve.holt@bluthcompany.co')
536
-
537
- user.subscription.swap("yearly")
538
- ```
539
-
540
- #### Resume a Subscription
541
-
542
- ##### Stripe or Braintree Subscription (on Grace Period)
543
-
544
- ```ruby
545
- user = User.find_by(email: 'steve.holt@bluthcompany.co')
546
-
547
- user.subscription.resume
548
- ```
549
-
550
- ##### Paddle (Paused)
551
-
552
- ```ruby
553
- user = User.find_by(email: 'steve.holt@bluthcompany.co')
554
-
555
- user.subscription.resume
556
- ```
557
-
558
- #### Retrieving the Subscription from the Processor
559
-
560
- ```ruby
561
- user = User.find_by(email: 'lucille2@bluthcompany.co')
562
-
563
- user.subscription.processor_subscription
564
- ```
565
-
566
- ### Customizing Pay Models
567
-
568
- Want to add methods to `Pay::Subscription` or `Pay::Charge`? You can
569
- define a concern and simply include it in the model when Rails loads the
570
- code.
571
-
572
- Pay uses the `to_prepare` method to allow concerns to be
573
- included every time Rails reloads the models in development as well.
574
-
575
- ```ruby
576
- # app/models/concerns/subscription_extensions.rb
577
- module SubscriptionExtensions
578
- extend ActiveSupport::Concern
579
-
580
- included do
581
- # associations and other class level things go here
582
- end
583
-
584
- # instance methods and code go here
585
- end
586
- ```
587
-
588
- ```ruby
589
- # config/initializers/subscription_extensions.rb
590
-
591
- # Re-include the SubscriptionExtensions every time Rails reloads
592
- Rails.application.config.to_prepare do
593
- Pay.subscription_model.include SubscriptionExtensions
594
- end
595
- ```
596
-
597
- ## Routes & Webhooks
598
-
599
- Routes are automatically mounted to `/pay` by default.
600
-
601
- We provide a route for confirming SCA payments at `/pay/payments/:payment_intent_id`
602
-
603
- Webhooks are automatically mounted at `/pay/webhooks/{provider}`
604
-
605
- #### Customizing webhook mount path
606
-
607
- If you have a catch all route (for 404s etc) and need to control where/when the webhook endpoints mount, you will need to disable automatic mounting and mount the engine above your catch all route.
608
-
609
- ```ruby
610
- # config/initializers/pay.rb
611
- config.automount_routes = false
612
-
613
- # config/routes.rb
614
- mount Pay::Engine, at: '/secret-webhook-path'
615
- ```
616
-
617
- If you just want to modify where the engine mounts it's routes then you can change the path.
618
-
619
- ```ruby
620
- # config/initializers/pay.rb
621
-
622
- config.routes_path = '/secret-webhook-path'
623
- ```
624
-
625
- ## Payment Providers
626
-
627
- We support Stripe, Braintree and Paddle and make our best attempt to
628
- standardize the three. They function differently so keep that in mind if
629
- you plan on doing more complex payments. It would be best to stick with
630
- a single payment provider in that case so you don't run into
631
- discrepancies.
632
-
633
- #### Braintree
634
-
635
- ```yaml
636
- development:
637
- braintree:
638
- private_key: xxxx
639
- public_key: yyyy
640
- merchant_id: zzzz
641
- environment: sandbox
642
- ```
643
- #### Paddle
644
-
645
- ```yaml
646
- paddle:
647
- vendor_id: xxxx
648
- vendor_auth_code: yyyy
649
- public_key_base64: MII...==
650
- environment: sandbox
651
- ```
652
-
653
- Paddle receipts can be retrieved by a charge receipt URL.
654
- ```ruby
655
- user = User.find_by(email: 'annyong@bluthcompany.co')
656
-
657
- charge = user.charges.first
658
- charge.paddle_receipt_url
659
- ```
660
- #### Stripe
661
-
662
- You'll need to add your private Stripe API key to your Rails secrets `config/secrets.yml`, credentials `rails credentials:edit`
663
-
664
- ```yaml
665
- development:
666
- stripe:
667
- private_key: xxxx
668
- public_key: yyyy
669
- signing_secret: zzzz
670
- ```
671
-
672
- You can also use the `STRIPE_PRIVATE_KEY` and `STRIPE_SIGNING_SECRET` environment variables.
673
-
674
- **To see how to use Stripe Elements JS & Devise, [click here](https://github.com/jasoncharnes/pay/wiki/Using-Stripe-Elements-and-Devise).**
675
-
676
- You need the following event types to trigger the webhook:
677
-
678
- ```
679
- customer.subscription.updated
680
- customer.subscription.deleted
681
- customer.subscription.created
682
- payment_method.updated
683
- invoice.payment_action_required
684
- customer.updated
685
- customer.deleted
686
- charge.succeeded
687
- charge.refunded
688
- ```
689
-
690
- ##### Strong Customer Authentication (SCA)
691
-
692
- Our Stripe integration **requires** the use of Payment Method objects to correctly support Strong Customer Authentication with Stripe. If you've previously been using card tokens, you'll need to upgrade your Javascript integration.
693
-
694
- Subscriptions that require SCA are marked as `incomplete` by default.
695
- Once payment is authenticated, Stripe will send a webhook updating the
696
- status of the subscription. You'll need to use the [Stripe CLI](https://github.com/stripe/stripe-cli) to forward
697
- webhooks to your application to make sure your subscriptions work
698
- correctly for SCA payments.
699
-
700
- ```bash
701
- stripe listen --forward-to localhost:3000/pay/webhooks/stripe
702
- ```
703
-
704
- You should use `stripe.confirmCardSetup` on the client to collect card information anytime you want to save the card and charge them later (adding a card, then charging them on the next page for example). Use `stripe.confirmCardPayment` if you'd like to charge the customer immediately (think checking out of a shopping cart).
705
-
706
- The Javascript also needs to have a PaymentIntent or SetupIntent created server-side and the ID passed into the Javascript to do this. That way it knows how to safely handle the card tokenization if it meets the SCA requirements.
707
-
708
- **Payment Confirmations**
709
-
710
- Sometimes you'll have a payment that requires extra authentication. In this case, Pay provides a webhook and action for handling these payments. It will automatically email the customer and provide a link with the PaymentIntent ID in the url where the customer will be asked to fill out their name and card number to confirm the payment. Once done, they'll be redirected back to your application.
711
-
712
- If you'd like to change the views of the payment confirmation page, you can install the views using the generator and modify the template.
713
-
714
- [<img src="https://d1jfzjx68gj8xs.cloudfront.net/items/2s3Z0J3Z3b1J1v2K2O1a/Screen%20Shot%202019-10-10%20at%2012.56.32%20PM.png?X-CloudApp-Visitor-Id=51470" alt="Stripe SCA Payment Confirmation" style="zoom: 25%;" />](https://d1jfzjx68gj8xs.cloudfront.net/items/2s3Z0J3Z3b1J1v2K2O1a/Screen%20Shot%202019-10-10%20at%2012.56.32%20PM.png)
715
-
716
- If you use the default views for payment confirmations, and also have a Content Security Policy in place for your application, make sure to add the following domains to their respective configurations in your `content_security_policy.rb` (otherwise these views won't load properly):
717
-
718
- * `style_src`: `https://unpkg.com`
719
- * `script_src`: `https://cdn.jsdelivr.net` and `https://js.stripe.com`
720
- * `frame_src`: `https://js.stripe.com`
721
-
722
- #### Background jobs
723
-
724
- 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.
23
+ - Stripe ([SCA Compatible](https://stripe.com/docs/strong-customer-authentication) using API version `2020-08-27`)
24
+ - Paddle (SCA Compatible & supports PayPal)
25
+ - Braintree (supports PayPal)
26
+ - [Fake Processor](docs/fake_processor.md) (used for generic trials without cards, free subscriptions, testing, etc)
725
27
 
726
- 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)
28
+ Want to add a new payment provider? Contributions are welcome.
727
29
 
30
+ > We make our best attempt to standardize the different payment providers. They function differently so keep that in mind if you plan on doing more complex payments. It would be best to stick witha single payment provider in that case so you don't run into discrepancies.
728
31
 
729
- ## Contributors
32
+ ## 📚 Docs
730
33
 
731
- - [Jason Charnes](https://twitter.com/jmcharnes)
732
- - [Chris Oliver](https://twitter.com/excid3)
34
+ * [Installation](docs/1_installation.md)
35
+ * [Configuration](docs/2_configuration.md)
36
+ * **Usage**
37
+ * [Customers](docs/3_customers.md)
38
+ * [Payment Methods](docs/4_payment_methods.md)
39
+ * [Charges](docs/5_charges.md)
40
+ * [Subscriptions](docs/6_subscriptions.md)
41
+ * [Routes & Webhooks](docs/7_webhooks.md)
42
+ * [Customizing Pay Models](docs/8_customizing_models.md)
733
43
 
734
- ## Contributing
44
+ * **Payment Processors**
45
+ * [Stripe](docs/stripe/1_overview.md)
46
+ * [Braintree](docs/braintree/1_overview.md)
47
+ * [Paddle](docs/paddle/1_overview.md)
48
+ * [Fake Processor](docs/fake_processor/1_overview.md)
49
+ * **Marketplaces**
50
+ * [Stripe Connect](docs/marketplaces/stripe_connect.md)
51
+ * **Contributing**
52
+ * [Adding A Payment Processor](docs/contributing/adding_a_payment_processor.md)
735
53
 
736
- 👋 Thanks for your interest in contributing. Feel free to fork this repo.
54
+ ## 🙏 Contributing
737
55
 
738
56
  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.
739
57
 
@@ -742,8 +60,9 @@ If you'd like to open a PR please make sure the following things pass:
742
60
  ```ruby
743
61
  bin/rails db:test:prepare
744
62
  bin/rails test
63
+ bundle exec standardrb
745
64
  ```
746
65
 
747
- ## License
66
+ ## 📝 License
748
67
 
749
68
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).