pay 2.6.11 → 3.0.0

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -693
  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 +32 -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 +34 -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 +109 -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/billable_generator.rb +44 -0
  21. data/lib/generators/active_record/merchant_generator.rb +44 -0
  22. data/lib/generators/active_record/templates/billable_migration.rb +17 -0
  23. data/lib/generators/active_record/templates/merchant_migration.rb +12 -0
  24. data/lib/generators/pay/{pay_generator.rb → billable_generator.rb} +2 -3
  25. data/lib/generators/pay/merchant_generator.rb +17 -0
  26. data/lib/generators/pay/orm_helpers.rb +10 -6
  27. data/lib/pay/adapter.rb +22 -0
  28. data/lib/pay/attributes.rb +74 -0
  29. data/lib/pay/billable/sync_customer.rb +30 -0
  30. data/lib/pay/braintree/billable.rb +130 -105
  31. data/lib/pay/braintree/payment_method.rb +33 -0
  32. data/lib/pay/braintree/subscription.rb +9 -12
  33. data/lib/pay/braintree/webhooks/subscription_canceled.rb +1 -1
  34. data/lib/pay/braintree/webhooks/subscription_charged_successfully.rb +4 -4
  35. data/lib/pay/braintree/webhooks/subscription_charged_unsuccessfully.rb +1 -1
  36. data/lib/pay/braintree/webhooks/subscription_expired.rb +1 -1
  37. data/lib/pay/braintree/webhooks/subscription_trial_ended.rb +2 -2
  38. data/lib/pay/braintree/webhooks/subscription_went_active.rb +1 -1
  39. data/lib/pay/braintree/webhooks/subscription_went_past_due.rb +1 -1
  40. data/lib/pay/braintree.rb +3 -2
  41. data/lib/pay/engine.rb +6 -1
  42. data/lib/pay/env.rb +8 -0
  43. data/lib/pay/fake_processor/billable.rb +45 -21
  44. data/lib/pay/fake_processor/payment_method.rb +21 -0
  45. data/lib/pay/fake_processor/subscription.rb +11 -8
  46. data/lib/pay/fake_processor.rb +2 -1
  47. data/lib/pay/merchant.rb +37 -0
  48. data/lib/pay/nano_id.rb +13 -0
  49. data/lib/pay/paddle/billable.rb +18 -48
  50. data/lib/pay/paddle/charge.rb +5 -5
  51. data/lib/pay/paddle/payment_method.rb +58 -0
  52. data/lib/pay/paddle/response.rb +0 -0
  53. data/lib/pay/paddle/subscription.rb +49 -8
  54. data/lib/pay/paddle/webhooks/subscription_cancelled.rb +6 -3
  55. data/lib/pay/paddle/webhooks/subscription_created.rb +1 -40
  56. data/lib/pay/paddle/webhooks/subscription_payment_refunded.rb +3 -3
  57. data/lib/pay/paddle/webhooks/subscription_payment_succeeded.rb +23 -23
  58. data/lib/pay/paddle/webhooks/subscription_updated.rb +2 -2
  59. data/lib/pay/paddle.rb +7 -3
  60. data/lib/pay/payment.rb +1 -1
  61. data/lib/pay/receipts.rb +35 -7
  62. data/lib/pay/stripe/billable.rb +82 -93
  63. data/lib/pay/stripe/charge.rb +65 -4
  64. data/lib/pay/stripe/merchant.rb +66 -0
  65. data/lib/pay/stripe/payment_method.rb +61 -0
  66. data/lib/pay/stripe/subscription.rb +91 -24
  67. data/lib/pay/stripe/webhooks/account_updated.rb +16 -0
  68. data/lib/pay/stripe/webhooks/charge_refunded.rb +2 -7
  69. data/lib/pay/stripe/webhooks/charge_succeeded.rb +2 -8
  70. data/lib/pay/stripe/webhooks/checkout_session_async_payment_succeeded.rb +15 -0
  71. data/lib/pay/stripe/webhooks/checkout_session_completed.rb +15 -0
  72. data/lib/pay/stripe/webhooks/customer_deleted.rb +7 -15
  73. data/lib/pay/stripe/webhooks/customer_updated.rb +10 -3
  74. data/lib/pay/stripe/webhooks/payment_action_required.rb +2 -2
  75. data/lib/pay/stripe/webhooks/payment_intent_succeeded.rb +6 -14
  76. data/lib/pay/stripe/webhooks/payment_method_attached.rb +15 -0
  77. data/lib/pay/stripe/webhooks/payment_method_detached.rb +12 -0
  78. data/lib/pay/stripe/webhooks/payment_method_updated.rb +10 -4
  79. data/lib/pay/stripe/webhooks/subscription_created.rb +1 -35
  80. data/lib/pay/stripe/webhooks/subscription_deleted.rb +2 -9
  81. data/lib/pay/stripe/webhooks/subscription_renewing.rb +14 -6
  82. data/lib/pay/stripe/webhooks/subscription_updated.rb +1 -28
  83. data/lib/pay/stripe.rb +17 -3
  84. data/lib/pay/version.rb +1 -1
  85. data/lib/pay/webhooks/delegator.rb +4 -0
  86. data/lib/pay/webhooks/process_job.rb +9 -0
  87. data/lib/pay/webhooks.rb +1 -0
  88. data/lib/pay.rb +8 -57
  89. metadata +34 -36
  90. data/db/migrate/20170205020145_create_pay_subscriptions.rb +0 -17
  91. data/db/migrate/20170727235816_create_pay_charges.rb +0 -18
  92. data/db/migrate/20190816015720_add_status_to_pay_subscriptions.rb +0 -14
  93. data/db/migrate/20200603134434_add_data_to_pay_models.rb +0 -22
  94. data/db/migrate/20210423235138_add_currency_to_pay_charges.rb +0 -5
  95. data/lib/generators/active_record/pay_generator.rb +0 -58
  96. data/lib/generators/active_record/templates/migration.rb +0 -9
  97. data/lib/pay/billable/sync_email.rb +0 -40
  98. data/lib/pay/billable.rb +0 -168
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c258d50a32d486777f2439f2fd2cd75e6cac1adba558afe630b9eda760c87717
4
- data.tar.gz: 1f079e5382a0f8c3cda2e7b70b56c36162bc32926dae8b9c5226ed1c2e508160
3
+ metadata.gz: 6a85b63ecf485a80f4825041bdfc4d66be639b65060c1836135422f367e0b878
4
+ data.tar.gz: d43a4bf47062f27d6fcdc4771517a2d2911bb3c38298d0c66b883446a42ac8ed
5
5
  SHA512:
6
- metadata.gz: ad9e9b98b5ed50f2e0f6599742b70f3c274afdc994949b445d921a5ae4451fbbaf2afcbad47e8d7d2a2c1b382fbb3ab3f97a85b2640048b937fab4d8dca10920
7
- data.tar.gz: 21eaa1e667271af7f64e3e1f4544c8f1f6e11e32d3dec80e9e70b05159ac0a4ae9dba390b1e4f1a6cac6b8223df547ec8bc87bb7505425a365fe7a06b713c3ea
6
+ metadata.gz: 88701e517c153b29434b56132cc567145f5c6bce65d0e6592c3118cd700147c45616840bb246df12c6d9999940c4e44147d332af7d4857b0ea02dcd2699d0d34
7
+ data.tar.gz: d57a35f69149eb0a49a9417fef01f9e3b70703bc077a3fcc7a2b7c6acb1f5f228570f695942ab75a67fd6f664baee7e6aa58ef7b16e1744b7633a4d7caec31e1
data/README.md CHANGED
@@ -1,716 +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
- [![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)
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
- Make sure you've configured your ActionMailer default_url_options so Pay can generate links to for features like Stripe Checkout.
55
-
56
- ```ruby
57
- # config/application.rb
58
- config.action_mailer.default_url_options = { host: "example.com" }
59
- ```
60
-
61
- #### Migrations
62
-
63
- To add the migrations to your application, run the following migration:
64
-
65
- `bin/rails pay:install:migrations`
66
-
67
- 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.
68
-
69
- `bin/rails g pay User`
70
-
71
- 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.
72
-
73
- Finally, run the migrations
74
-
75
- `rake db:migrate`
76
-
77
- #### Getting NoMethodError?
78
-
79
- `NoMethodError (undefined method 'stripe_customer' for #<User:0x00007fbc34b9bf20>)`
80
-
81
- Fully restart your Rails application `bin/spring stop && rails s`
82
-
83
- ## Usage
84
-
85
- The `Pay::Billable` module should be included in the models you want to make payments and subscriptions.
86
-
87
- ```ruby
88
- # app/models/user.rb
89
- class User < ActiveRecord::Base
90
- include Pay::Billable
91
- end
92
- ```
93
-
94
- An `email` attribute or method on your `Billable` model is required.
95
-
96
- 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.
97
-
98
- ## Configuration
99
-
100
- Need to make some changes to how Pay is used? You can create an initializer `config/initializers/pay.rb`
101
-
102
- ```ruby
103
- Pay.setup do |config|
104
- config.chargeable_class = 'Pay::Charge'
105
- config.chargeable_table = 'pay_charges'
106
-
107
- # For use in the receipt/refund/renewal mailers
108
- config.business_name = "Business Name"
109
- config.business_address = "1600 Pennsylvania Avenue NW"
110
- config.application_name = "My App"
111
- config.support_email = "helpme@example.com"
112
-
113
- config.send_emails = true
114
-
115
- config.default_product_name = "default"
116
- config.default_plan_name = "default"
117
-
118
- config.automount_routes = true
119
- config.routes_path = "/pay" # Only when automount_routes is true
120
- end
121
- ```
122
-
123
- This allows you to create your own Charge class for instance, which could add receipt functionality:
124
-
125
- ```ruby
126
- class Charge < Pay::Charge
127
- def receipts
128
- # do some receipts stuff using the https://github.com/excid3/receipts gem
129
- end
130
- end
131
-
132
- Pay.setup do |config|
133
- config.chargeable_class = 'Charge'
134
- end
135
- ```
136
-
137
- ### Credentials
138
-
139
- You'll need to add your private Stripe API key to your Rails secrets `config/secrets.yml`, credentials `rails credentials:edit`
140
-
141
- ```yaml
142
- development:
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
- For Stripe, you can also use the `STRIPE_PUBLIC_KEY`, `STRIPE_PRIVATE_KEY` and `STRIPE_SIGNING_SECRET` environment variables.
160
- For Braintree, you can also use `BRAINTREE_MERCHANT_ID`, `BRAINTREE_PUBLIC_KEY`, `BRAINTREE_PRIVATE_KEY`, and `BRAINTREE_ENVIRONMENT` environment variables.
161
- For Paddle, you can also use `PADDLE_VENDOR_ID`, `PADDLE_VENDOR_AUTH_CODE`, `PADDLE_PUBLIC_KEY_BASE64` and `PADDLE_ENVIRONMENT` environment variables.
162
-
163
- ### Generators
164
-
165
- If you want to modify the Stripe SCA template or any other views, you can copy over the view files using:
166
-
167
- ```bash
168
- bin/rails generate pay:views
169
- ```
170
-
171
- If you want to modify the email templates, you can copy over the view files using:
172
-
173
- ```bash
174
- bin/rails generate pay:email_views
175
- ```
176
-
177
- ### Emails
178
-
179
- Emails can be enabled/disabled using the `send_emails` configuration option (enabled per default). When enabled, the following emails will be sent:
180
-
181
- - When a charge succeeded
182
- - When a charge was refunded
183
- - When a subscription is about to renew
184
-
185
-
186
- ## Billable API
187
-
188
- #### Trials
189
-
190
- You can check if the user is on a trial by simply asking:
191
-
192
- ```ruby
193
- user = User.find_by(email: 'michael@bluthcompany.co')
194
-
195
- user.on_trial? #=> true or false
196
- ```
197
-
198
- The `on_trial?` method has two optional arguments with default values.
199
-
200
- ```ruby
201
- user = User.find_by(email: 'michael@bluthcompany.co')
202
-
203
- user.on_trial?(name: 'default', plan: 'plan') #=> true or false
204
- ```
205
-
206
- #### Generic Trials
207
-
208
- For trials that don't require cards upfront:
209
-
210
- ```ruby
211
- user = User.create(
212
- email: 'michael@bluthcompany.co',
213
- trial_ends_at: 30.days.from_now
214
- )
215
-
216
- user.on_generic_trial? #=> true
217
- ```
218
-
219
- #### Creating a Charge
220
-
221
- ##### Stripe and Braintree
222
-
223
- ```ruby
224
- user = User.find_by(email: 'michael@bluthcompany.co')
225
-
226
- user.processor = 'stripe'
227
- user.card_token = 'payment_method_id'
228
- user.charge(1500) # $15.00 USD
229
-
230
- user = User.find_by(email: 'michael@bluthcompany.co')
231
-
232
- user.processor = 'braintree'
233
- user.card_token = 'nonce'
234
- user.charge(1500) # $15.00 USD
235
- ```
236
-
237
- The `charge` method takes the amount in cents as the primary argument.
238
-
239
- You may pass optional arguments that will be directly passed on to
240
- either Stripe or Braintree. You can use these options to charge
241
- different currencies, etc.
242
-
243
- On failure, a `Pay::Error` will be raised with details about the payment
244
- failure.
245
-
246
- ##### Paddle
247
- It is only possible to create immediate one-time charges on top of an existing subscription.
248
-
249
- ```ruby
250
- user = User.find_by(email: 'michael@bluthcompany.co')
251
-
252
- user.processor = 'paddle'
253
- user.charge(1500, {charge_name: "Test"}) # $15.00 USD
254
-
255
- ```
256
-
257
- An existing subscription and a charge name are required.
258
-
259
- #### Creating a Subscription
260
-
261
- ##### Stripe and Braintree
262
-
263
- ```ruby
264
- user = User.find_by(email: 'michael@bluthcompany.co')
265
-
266
- user.processor = 'stripe'
267
- user.card_token = 'payment_method_id'
268
- user.subscribe
269
- ```
270
-
271
- A `card_token` must be provided as an attribute.
272
-
273
- The subscribe method has three optional arguments with default values.
274
-
275
- ```ruby
276
- def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options)
277
- ...
278
- end
279
- ```
280
-
281
- For example, you can pass the `quantity` option to subscribe to a plan with for per-seat pricing.
282
-
283
- ```ruby
284
-
285
- user.subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, quantity: 3)
286
- ```
287
-
288
- ###### Name
289
-
290
- Name is an internally used name for the subscription.
291
-
292
- ###### Plan
293
-
294
- Plan is the plan ID or price ID from the payment processor. For example: `plan_xxxxx` or `price_xxxxx`
295
-
296
- ###### Options
297
-
298
- By default, the trial specified on the subscription will be used.
299
-
300
- `trial_period_days: 30` can be set to override and a trial to the subscription. This works the same for Braintree and Stripe.
301
-
302
- ##### Paddle
303
- 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.
304
-
305
- 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).
306
-
307
- Javascript Checkout:
308
- ```javascript
309
- Paddle.Checkout.open({
310
- product: 12345,
311
- passthrough: "<%= Pay::Paddle.passthrough(owner: current_user) %>"
312
- });
313
- ```
314
-
315
- Paddle Button Checkout:
316
- ```html
317
- <a href="#!" class="paddle_button" data-product="12345" data-email="<%= current_user.email %>" data-passthrough="<%= Pay::Paddle.passthrough(owner: current_user) %>"
318
- ```
319
-
320
- ###### Passthrough
321
-
322
- Pay providers a helper method for generating the passthrough JSON object to associate the purchase with the correct Rails model.
323
-
324
- ```ruby
325
- Pay::Paddle.passthrough(owner: current_user, foo: :bar)
326
- #=> { owner_sgid: "xxxxxxxx", foo: "bar" }
327
-
328
- # To generate manually without the helper
329
- #=> { owner_sgid: current_user.to_sgid.to_s, foo: "bar" }.to_json
330
- ```
331
-
332
- Pay parses the passthrough JSON string and verifies the `owner_sgid` hash to match the webhook with the correct billable record.
333
- The passthrough parameter `owner_sgid` is only required for creating a subscription.
334
-
335
- #### Retrieving a Subscription from the Database
336
-
337
- ```ruby
338
- user = User.find_by(email: 'gob@bluthcompany.co')
339
-
340
- user.subscription
341
- ```
342
-
343
- A subscription can be retrieved by name, too.
344
-
345
- ```ruby
346
- user = User.find_by(email: 'gob@bluthcompany.co')
347
-
348
- user.subscription(name: 'bananastand+')
349
- ```
350
-
351
- #### Checking a User's Trial/Subscription Status
352
-
353
- ```ruby
354
- user = User.find_by(email: 'george.senior@bluthcompany.co')
355
- user.on_trial_or_subscribed?
356
- ```
357
-
358
- The `on_trial_or_subscribed?` method has two optional arguments with default values.
359
-
360
- ```ruby
361
- def on_trial_or_subscribed?(name: 'default', plan: nil)
362
- ...
363
- end
364
- ```
365
-
366
- #### Checking a User's Subscription Status
367
-
368
- ```ruby
369
- user = User.find_by(email: 'george.senior@bluthcompany.co')
370
- user.subscribed?
371
- ```
372
-
373
- The `subscribed?` method has two optional arguments with default values.
19
+ ## 🏦 Payment Processors
374
20
 
375
- ```ruby
376
- def subscribed?(name: 'default', plan: nil)
377
- ...
378
- end
379
- ```
380
-
381
- ##### Name
382
-
383
- Name is an internally used name for the subscription.
384
-
385
- ##### Plan
386
-
387
- Plan is the plan ID from the payment processor.
388
-
389
- #### Retrieving a Payment Processor Account
390
-
391
- ##### Stripe and Braintree
392
-
393
- ```ruby
394
- user = User.find_by(email: 'george.michael@bluthcompany.co')
395
-
396
- user.customer #> Stripe or Braintree customer account
397
- ```
398
-
399
- ##### Paddle
400
-
401
- It is currently not possible to retrieve a payment processor account through the API.
402
-
403
- #### Updating a Customer's Credit Card
404
-
405
- ##### Stripe and Braintree
406
-
407
- ```ruby
408
- user = User.find_by(email: 'tobias@bluthcompany.co')
409
-
410
- user.update_card('payment_method_id')
411
- ```
412
-
413
- ##### Paddle
414
-
415
- 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.
416
- ```ruby
417
- user = User.find_by(email: 'tobias@bluthcompany.co')
418
-
419
- user.subscription.paddle_update_url
420
- ```
421
-
422
-
423
-
424
- #### Retrieving a Customer's Subscription from the Processor
425
-
426
- ```ruby
427
- user = User.find_by(email: 'lucille@bluthcompany.co')
428
-
429
- user.processor_subscription(subscription_id) #=> Stripe, Braintree or Paddle Subscription
430
- ```
431
-
432
- ## Subscription API
433
-
434
- #### Checking a Subscription's Trial Status
435
-
436
- ```ruby
437
- user = User.find_by(email: 'lindsay@bluthcompany.co')
438
-
439
- user.subscription.on_trial? #=> true or false
440
- ```
441
-
442
- #### Checking a Subscription's Cancellation Status
443
-
444
- ```ruby
445
- user = User.find_by(email: 'buster@bluthcompany.co')
446
-
447
- user.subscription.cancelled? #=> true or false
448
- ```
449
-
450
- #### Checking a Subscription's Grace Period Status
451
-
452
- ```ruby
453
- user = User.find_by(email: 'her?@bluthcompany.co')
454
-
455
- user.subscription.on_grace_period? #=> true or false
456
- ```
457
-
458
- #### Checking to See If a Subscription Is Active
459
-
460
- ```ruby
461
- user = User.find_by(email: 'carl.weathers@bluthcompany.co')
462
-
463
- user.subscription.active? #=> true or false
464
- ```
465
-
466
- #### Checking to See If a Subscription Is Paused
467
-
468
- ```ruby
469
- user = User.find_by(email: 'carl.weathers@bluthcompany.co')
470
-
471
- user.subscription.paused? #=> true or false
472
- ```
473
-
474
- #### Cancel a Subscription (At End of Billing Cycle)
475
-
476
- ##### Stripe, Braintree and Paddle
477
-
478
- ```ruby
479
- user = User.find_by(email: 'oscar@bluthcompany.co')
480
-
481
- user.subscription.cancel
482
- ```
483
-
484
- ##### Paddle
485
- 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.
486
-
487
- ```ruby
488
- user.subscription.paddle_cancel_url
489
- ```
490
-
491
- #### Cancel a Subscription Immediately
492
-
493
- ```ruby
494
- user = User.find_by(email: 'annyong@bluthcompany.co')
495
-
496
- user.subscription.cancel_now!
497
- ```
498
-
499
- #### Pause a Subscription
500
-
501
- ##### Paddle
502
-
503
- ```ruby
504
- user = User.find_by(email: 'oscar@bluthcompany.co')
505
-
506
- user.subscription.pause
507
- ```
508
-
509
- #### Swap a Subscription to another Plan
510
-
511
- ```ruby
512
- user = User.find_by(email: 'steve.holt@bluthcompany.co')
21
+ Our supported payment processors are:
513
22
 
514
- user.subscription.swap("yearly")
515
- ```
516
-
517
- #### Resume a Subscription
518
-
519
- ##### Stripe or Braintree Subscription (on Grace Period)
520
-
521
- ```ruby
522
- user = User.find_by(email: 'steve.holt@bluthcompany.co')
523
-
524
- user.subscription.resume
525
- ```
526
-
527
- ##### Paddle (Paused)
528
-
529
- ```ruby
530
- user = User.find_by(email: 'steve.holt@bluthcompany.co')
531
-
532
- user.subscription.resume
533
- ```
534
-
535
- #### Retrieving the Subscription from the Processor
536
-
537
- ```ruby
538
- user = User.find_by(email: 'lucille2@bluthcompany.co')
539
-
540
- user.subscription.processor_subscription
541
- ```
542
-
543
- ### Customizing Pay Models
544
-
545
- Want to add methods to `Pay::Subscription` or `Pay::Charge`? You can
546
- define a concern and simply include it in the model when Rails loads the
547
- code.
548
-
549
- Pay uses the `to_prepare` method to allow concerns to be
550
- included every time Rails reloads the models in development as well.
551
-
552
- ```ruby
553
- # app/models/concerns/subscription_extensions.rb
554
- module SubscriptionExtensions
555
- extend ActiveSupport::Concern
556
-
557
- included do
558
- # associations and other class level things go here
559
- end
560
-
561
- # instance methods and code go here
562
- end
563
- ```
564
-
565
- ```ruby
566
- # config/initializers/subscription_extensions.rb
567
-
568
- # Re-include the SubscriptionExtensions every time Rails reloads
569
- Rails.application.config.to_prepare do
570
- Pay.subscription_model.include SubscriptionExtensions
571
- end
572
- ```
573
-
574
- ## Routes & Webhooks
575
-
576
- Routes are automatically mounted to `/pay` by default.
577
-
578
- We provide a route for confirming SCA payments at `/pay/payments/:payment_intent_id`
579
-
580
- Webhooks are automatically mounted at `/pay/webhooks/{provider}`
581
-
582
- #### Customizing webhook mount path
583
-
584
- 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.
585
-
586
- ```ruby
587
- # config/initializers/pay.rb
588
- config.automount_routes = false
589
-
590
- # config/routes.rb
591
- mount Pay::Engine, at: '/secret-webhook-path'
592
- ```
593
-
594
- If you just want to modify where the engine mounts it's routes then you can change the path.
595
-
596
- ```ruby
597
- # config/initializers/pay.rb
598
-
599
- config.routes_path = '/secret-webhook-path'
600
- ```
601
-
602
- ## Payment Providers
603
-
604
- We support Stripe, Braintree and Paddle and make our best attempt to
605
- standardize the three. They function differently so keep that in mind if
606
- you plan on doing more complex payments. It would be best to stick with
607
- a single payment provider in that case so you don't run into
608
- discrepancies.
609
-
610
- #### Braintree
611
-
612
- ```yaml
613
- development:
614
- braintree:
615
- private_key: xxxx
616
- public_key: yyyy
617
- merchant_id: zzzz
618
- environment: sandbox
619
- ```
620
- #### Paddle
621
-
622
- ```yaml
623
- paddle:
624
- vendor_id: xxxx
625
- vendor_auth_code: yyyy
626
- public_key_base64: MII...==
627
- environment: sandbox
628
- ```
629
-
630
- Paddle receipts can be retrieved by a charge receipt URL.
631
- ```ruby
632
- user = User.find_by(email: 'annyong@bluthcompany.co')
633
-
634
- charge = user.charges.first
635
- charge.paddle_receipt_url
636
- ```
637
- #### Stripe
638
-
639
- You'll need to add your private Stripe API key to your Rails secrets `config/secrets.yml`, credentials `rails credentials:edit`
640
-
641
- ```yaml
642
- development:
643
- stripe:
644
- private_key: xxxx
645
- public_key: yyyy
646
- signing_secret: zzzz
647
- ```
648
-
649
- You can also use the `STRIPE_PRIVATE_KEY` and `STRIPE_SIGNING_SECRET` environment variables.
650
-
651
- **To see how to use Stripe Elements JS & Devise, [click here](https://github.com/jasoncharnes/pay/wiki/Using-Stripe-Elements-and-Devise).**
652
-
653
- You need the following event types to trigger the webhook:
654
-
655
- ```
656
- customer.subscription.updated
657
- customer.subscription.deleted
658
- customer.subscription.created
659
- payment_method.updated
660
- invoice.payment_action_required
661
- customer.updated
662
- customer.deleted
663
- charge.succeeded
664
- charge.refunded
665
- ```
666
-
667
- ##### Strong Customer Authentication (SCA)
668
-
669
- 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.
670
-
671
- Subscriptions that require SCA are marked as `incomplete` by default.
672
- Once payment is authenticated, Stripe will send a webhook updating the
673
- status of the subscription. You'll need to use the [Stripe CLI](https://github.com/stripe/stripe-cli) to forward
674
- webhooks to your application to make sure your subscriptions work
675
- correctly for SCA payments.
676
-
677
- ```bash
678
- stripe listen --forward-to localhost:3000/pay/webhooks/stripe
679
- ```
680
-
681
- 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).
682
-
683
- 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.
684
-
685
- **Payment Confirmations**
686
-
687
- 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.
688
-
689
- 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.
690
-
691
- [<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)
692
-
693
- 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):
694
-
695
- * `style_src`: `https://unpkg.com`
696
- * `script_src`: `https://cdn.jsdelivr.net` and `https://js.stripe.com`
697
- * `frame_src`: `https://js.stripe.com`
698
-
699
- #### Background jobs
700
-
701
- 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)
702
27
 
703
- 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.
704
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.
705
31
 
706
- ## Contributors
32
+ ## 📚 Docs
707
33
 
708
- - [Jason Charnes](https://twitter.com/jmcharnes)
709
- - [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)
710
43
 
711
- ## 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)
712
53
 
713
- 👋 Thanks for your interest in contributing. Feel free to fork this repo.
54
+ ## 🙏 Contributing
714
55
 
715
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.
716
57
 
@@ -719,8 +60,9 @@ If you'd like to open a PR please make sure the following things pass:
719
60
  ```ruby
720
61
  bin/rails db:test:prepare
721
62
  bin/rails test
63
+ bundle exec standardrb
722
64
  ```
723
65
 
724
- ## License
66
+ ## 📝 License
725
67
 
726
68
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).