pay 2.7.0 → 3.0.1

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