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