nocheckout 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9db06290291d396f599cd4480858528a842f818be68f58e154ad7e5f5f8b6299
4
- data.tar.gz: '06974973a6ac44a4c909e48bc82737c3f16639981016d3ee9e4b815c74b38203'
3
+ metadata.gz: 1940078d7a818e06033361f4c961bb23fed76c724f7273d2c9cfc7e24cf509b8
4
+ data.tar.gz: 48a81f066625fd4d946358f5dd010e15703b59ad482e860493c48b28a56c95c4
5
5
  SHA512:
6
- metadata.gz: 4d900112610418b2b15882d3e2b58ba13bd6ced82e6fa01dbcfa84442436a941fb1454a754c8e2b5e76d2ef861bf7abf3653f3b02a4f6ecfc297d5d9e7ab8995
7
- data.tar.gz: 44e17d5ff40f48f7744711871cbb68ef9522248e521a2e0743b66486458f4ae4be6a15b41ab5bc0826b16534c168566234aa94a77d633db91bbb5e7ec7ebd38b
6
+ metadata.gz: 7fb7484da98f62bef30539907231a8429f690419c9d0f0c7ac9cbf78ac9de62630391c82978dd6d1d0a9a89d3b7ffd326d3ff1858c6b7ea19afeda83d93504a9
7
+ data.tar.gz: 7beaf4fe8e90dda879b1107ee8173e0cd16ebf771f2fb1d53de35dcd90abf20f03333335b2443a87c2275f5f92c8704625c300ad40c19c5e651c7dbaf871ed14
data/Gemfile.lock CHANGED
@@ -1,95 +1,108 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nocheckout (0.1.2)
5
- rails (~> 7.0)
4
+ nocheckout (0.1.4)
5
+ rails (>= 7.0)
6
6
  stripe (>= 7.0)
7
7
  zeitwerk (~> 2.0)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actioncable (7.0.8)
13
- actionpack (= 7.0.8)
14
- activesupport (= 7.0.8)
12
+ actioncable (7.2.1)
13
+ actionpack (= 7.2.1)
14
+ activesupport (= 7.2.1)
15
15
  nio4r (~> 2.0)
16
16
  websocket-driver (>= 0.6.1)
17
- actionmailbox (7.0.8)
18
- actionpack (= 7.0.8)
19
- activejob (= 7.0.8)
20
- activerecord (= 7.0.8)
21
- activestorage (= 7.0.8)
22
- activesupport (= 7.0.8)
23
- mail (>= 2.7.1)
24
- net-imap
25
- net-pop
26
- net-smtp
27
- actionmailer (7.0.8)
28
- actionpack (= 7.0.8)
29
- actionview (= 7.0.8)
30
- activejob (= 7.0.8)
31
- activesupport (= 7.0.8)
32
- mail (~> 2.5, >= 2.5.4)
33
- net-imap
34
- net-pop
35
- net-smtp
36
- rails-dom-testing (~> 2.0)
37
- actionpack (7.0.8)
38
- actionview (= 7.0.8)
39
- activesupport (= 7.0.8)
40
- rack (~> 2.0, >= 2.2.4)
17
+ zeitwerk (~> 2.6)
18
+ actionmailbox (7.2.1)
19
+ actionpack (= 7.2.1)
20
+ activejob (= 7.2.1)
21
+ activerecord (= 7.2.1)
22
+ activestorage (= 7.2.1)
23
+ activesupport (= 7.2.1)
24
+ mail (>= 2.8.0)
25
+ actionmailer (7.2.1)
26
+ actionpack (= 7.2.1)
27
+ actionview (= 7.2.1)
28
+ activejob (= 7.2.1)
29
+ activesupport (= 7.2.1)
30
+ mail (>= 2.8.0)
31
+ rails-dom-testing (~> 2.2)
32
+ actionpack (7.2.1)
33
+ actionview (= 7.2.1)
34
+ activesupport (= 7.2.1)
35
+ nokogiri (>= 1.8.5)
36
+ racc
37
+ rack (>= 2.2.4, < 3.2)
38
+ rack-session (>= 1.0.1)
41
39
  rack-test (>= 0.6.3)
42
- rails-dom-testing (~> 2.0)
43
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
44
- actiontext (7.0.8)
45
- actionpack (= 7.0.8)
46
- activerecord (= 7.0.8)
47
- activestorage (= 7.0.8)
48
- activesupport (= 7.0.8)
40
+ rails-dom-testing (~> 2.2)
41
+ rails-html-sanitizer (~> 1.6)
42
+ useragent (~> 0.16)
43
+ actiontext (7.2.1)
44
+ actionpack (= 7.2.1)
45
+ activerecord (= 7.2.1)
46
+ activestorage (= 7.2.1)
47
+ activesupport (= 7.2.1)
49
48
  globalid (>= 0.6.0)
50
49
  nokogiri (>= 1.8.5)
51
- actionview (7.0.8)
52
- activesupport (= 7.0.8)
50
+ actionview (7.2.1)
51
+ activesupport (= 7.2.1)
53
52
  builder (~> 3.1)
54
- erubi (~> 1.4)
55
- rails-dom-testing (~> 2.0)
56
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
57
- activejob (7.0.8)
58
- activesupport (= 7.0.8)
53
+ erubi (~> 1.11)
54
+ rails-dom-testing (~> 2.2)
55
+ rails-html-sanitizer (~> 1.6)
56
+ activejob (7.2.1)
57
+ activesupport (= 7.2.1)
59
58
  globalid (>= 0.3.6)
60
- activemodel (7.0.8)
61
- activesupport (= 7.0.8)
62
- activerecord (7.0.8)
63
- activemodel (= 7.0.8)
64
- activesupport (= 7.0.8)
65
- activestorage (7.0.8)
66
- actionpack (= 7.0.8)
67
- activejob (= 7.0.8)
68
- activerecord (= 7.0.8)
69
- activesupport (= 7.0.8)
59
+ activemodel (7.2.1)
60
+ activesupport (= 7.2.1)
61
+ activerecord (7.2.1)
62
+ activemodel (= 7.2.1)
63
+ activesupport (= 7.2.1)
64
+ timeout (>= 0.4.0)
65
+ activestorage (7.2.1)
66
+ actionpack (= 7.2.1)
67
+ activejob (= 7.2.1)
68
+ activerecord (= 7.2.1)
69
+ activesupport (= 7.2.1)
70
70
  marcel (~> 1.0)
71
- mini_mime (>= 1.1.0)
72
- activesupport (7.0.8)
73
- concurrent-ruby (~> 1.0, >= 1.0.2)
71
+ activesupport (7.2.1)
72
+ base64
73
+ bigdecimal
74
+ concurrent-ruby (~> 1.0, >= 1.3.1)
75
+ connection_pool (>= 2.2.5)
76
+ drb
74
77
  i18n (>= 1.6, < 2)
78
+ logger (>= 1.4.2)
75
79
  minitest (>= 5.1)
76
- tzinfo (~> 2.0)
80
+ securerandom (>= 0.3)
81
+ tzinfo (~> 2.0, >= 2.0.5)
77
82
  ast (2.4.2)
78
- base64 (0.1.1)
79
- builder (3.2.4)
80
- concurrent-ruby (1.2.2)
83
+ base64 (0.2.0)
84
+ bigdecimal (3.1.8)
85
+ builder (3.3.0)
86
+ concurrent-ruby (1.3.4)
87
+ connection_pool (2.4.1)
81
88
  crass (1.0.6)
82
- date (3.3.3)
83
- diff-lcs (1.5.0)
84
- erubi (1.12.0)
89
+ date (3.3.4)
90
+ diff-lcs (1.5.1)
91
+ drb (2.2.1)
92
+ erubi (1.13.0)
85
93
  globalid (1.2.1)
86
94
  activesupport (>= 6.1)
87
- i18n (1.14.1)
95
+ i18n (1.14.6)
88
96
  concurrent-ruby (~> 1.0)
89
- json (2.6.3)
97
+ io-console (0.7.2)
98
+ irb (1.14.1)
99
+ rdoc (>= 4.0.0)
100
+ reline (>= 0.4.2)
101
+ json (2.7.2)
90
102
  language_server-protocol (3.17.0.3)
91
103
  lint_roller (1.1.0)
92
- loofah (2.21.3)
104
+ logger (1.6.1)
105
+ loofah (2.22.0)
93
106
  crass (~> 1.0.2)
94
107
  nokogiri (>= 1.12.0)
95
108
  mail (2.8.1)
@@ -97,46 +110,52 @@ GEM
97
110
  net-imap
98
111
  net-pop
99
112
  net-smtp
100
- marcel (1.0.2)
101
- method_source (1.0.0)
113
+ marcel (1.0.4)
102
114
  mini_mime (1.1.5)
103
- minitest (5.20.0)
104
- net-imap (0.3.7)
115
+ minitest (5.25.1)
116
+ net-imap (0.4.16)
105
117
  date
106
118
  net-protocol
107
119
  net-pop (0.1.2)
108
120
  net-protocol
109
- net-protocol (0.2.1)
121
+ net-protocol (0.2.2)
110
122
  timeout
111
- net-smtp (0.3.3)
123
+ net-smtp (0.5.0)
112
124
  net-protocol
113
- nio4r (2.5.9)
114
- nokogiri (1.15.4-arm64-darwin)
125
+ nio4r (2.7.3)
126
+ nokogiri (1.16.7-arm64-darwin)
115
127
  racc (~> 1.4)
116
- nokogiri (1.15.4-x86_64-linux)
128
+ nokogiri (1.16.7-x86_64-linux)
117
129
  racc (~> 1.4)
118
- parallel (1.23.0)
119
- parser (3.2.2.3)
130
+ parallel (1.26.3)
131
+ parser (3.3.5.0)
120
132
  ast (~> 2.4.1)
121
133
  racc
122
- racc (1.7.1)
123
- rack (2.2.8)
134
+ psych (5.1.2)
135
+ stringio
136
+ racc (1.8.1)
137
+ rack (3.1.7)
138
+ rack-session (2.0.0)
139
+ rack (>= 3.0.0)
124
140
  rack-test (2.1.0)
125
141
  rack (>= 1.3)
126
- rails (7.0.8)
127
- actioncable (= 7.0.8)
128
- actionmailbox (= 7.0.8)
129
- actionmailer (= 7.0.8)
130
- actionpack (= 7.0.8)
131
- actiontext (= 7.0.8)
132
- actionview (= 7.0.8)
133
- activejob (= 7.0.8)
134
- activemodel (= 7.0.8)
135
- activerecord (= 7.0.8)
136
- activestorage (= 7.0.8)
137
- activesupport (= 7.0.8)
142
+ rackup (2.1.0)
143
+ rack (>= 3)
144
+ webrick (~> 1.8)
145
+ rails (7.2.1)
146
+ actioncable (= 7.2.1)
147
+ actionmailbox (= 7.2.1)
148
+ actionmailer (= 7.2.1)
149
+ actionpack (= 7.2.1)
150
+ actiontext (= 7.2.1)
151
+ actionview (= 7.2.1)
152
+ activejob (= 7.2.1)
153
+ activemodel (= 7.2.1)
154
+ activerecord (= 7.2.1)
155
+ activestorage (= 7.2.1)
156
+ activesupport (= 7.2.1)
138
157
  bundler (>= 1.15.0)
139
- railties (= 7.0.8)
158
+ railties (= 7.2.1)
140
159
  rails-dom-testing (2.2.0)
141
160
  activesupport (>= 5.0.0)
142
161
  minitest
@@ -144,73 +163,82 @@ GEM
144
163
  rails-html-sanitizer (1.6.0)
145
164
  loofah (~> 2.21)
146
165
  nokogiri (~> 1.14)
147
- railties (7.0.8)
148
- actionpack (= 7.0.8)
149
- activesupport (= 7.0.8)
150
- method_source
166
+ railties (7.2.1)
167
+ actionpack (= 7.2.1)
168
+ activesupport (= 7.2.1)
169
+ irb (~> 1.13)
170
+ rackup (>= 1.0.0)
151
171
  rake (>= 12.2)
152
- thor (~> 1.0)
153
- zeitwerk (~> 2.5)
172
+ thor (~> 1.0, >= 1.2.2)
173
+ zeitwerk (~> 2.6)
154
174
  rainbow (3.1.1)
155
- rake (13.0.6)
156
- regexp_parser (2.8.1)
157
- rexml (3.2.6)
158
- rspec (3.12.0)
159
- rspec-core (~> 3.12.0)
160
- rspec-expectations (~> 3.12.0)
161
- rspec-mocks (~> 3.12.0)
162
- rspec-core (3.12.2)
163
- rspec-support (~> 3.12.0)
164
- rspec-expectations (3.12.3)
175
+ rake (13.2.1)
176
+ rdoc (6.7.0)
177
+ psych (>= 4.0.0)
178
+ regexp_parser (2.9.2)
179
+ reline (0.5.10)
180
+ io-console (~> 0.5)
181
+ rexml (3.3.8)
182
+ rspec (3.13.0)
183
+ rspec-core (~> 3.13.0)
184
+ rspec-expectations (~> 3.13.0)
185
+ rspec-mocks (~> 3.13.0)
186
+ rspec-core (3.13.1)
187
+ rspec-support (~> 3.13.0)
188
+ rspec-expectations (3.13.3)
165
189
  diff-lcs (>= 1.2.0, < 2.0)
166
- rspec-support (~> 3.12.0)
167
- rspec-mocks (3.12.6)
190
+ rspec-support (~> 3.13.0)
191
+ rspec-mocks (3.13.2)
168
192
  diff-lcs (>= 1.2.0, < 2.0)
169
- rspec-support (~> 3.12.0)
170
- rspec-support (3.12.1)
171
- rubocop (1.56.3)
172
- base64 (~> 0.1.1)
193
+ rspec-support (~> 3.13.0)
194
+ rspec-support (3.13.1)
195
+ rubocop (1.65.1)
173
196
  json (~> 2.3)
174
197
  language_server-protocol (>= 3.17.0)
175
198
  parallel (~> 1.10)
176
- parser (>= 3.2.2.3)
199
+ parser (>= 3.3.0.2)
177
200
  rainbow (>= 2.2.2, < 4.0)
178
- regexp_parser (>= 1.8, < 3.0)
201
+ regexp_parser (>= 2.4, < 3.0)
179
202
  rexml (>= 3.2.5, < 4.0)
180
- rubocop-ast (>= 1.28.1, < 2.0)
203
+ rubocop-ast (>= 1.31.1, < 2.0)
181
204
  ruby-progressbar (~> 1.7)
182
205
  unicode-display_width (>= 2.4.0, < 3.0)
183
- rubocop-ast (1.29.0)
184
- parser (>= 3.2.1.0)
185
- rubocop-performance (1.19.0)
186
- rubocop (>= 1.7.0, < 2.0)
187
- rubocop-ast (>= 0.4.0)
206
+ rubocop-ast (1.32.3)
207
+ parser (>= 3.3.1.0)
208
+ rubocop-performance (1.21.1)
209
+ rubocop (>= 1.48.1, < 2.0)
210
+ rubocop-ast (>= 1.31.1, < 2.0)
188
211
  ruby-progressbar (1.13.0)
189
- standard (1.31.1)
212
+ securerandom (0.3.1)
213
+ standard (1.40.1)
190
214
  language_server-protocol (~> 3.17.0.2)
191
215
  lint_roller (~> 1.0)
192
- rubocop (~> 1.56.2)
216
+ rubocop (~> 1.65.0)
193
217
  standard-custom (~> 1.0.0)
194
- standard-performance (~> 1.2)
218
+ standard-performance (~> 1.4)
195
219
  standard-custom (1.0.2)
196
220
  lint_roller (~> 1.0)
197
221
  rubocop (~> 1.50)
198
- standard-performance (1.2.0)
222
+ standard-performance (1.4.0)
199
223
  lint_roller (~> 1.1)
200
- rubocop-performance (~> 1.19.0)
201
- stripe (9.2.0)
202
- thor (1.2.2)
203
- timeout (0.4.0)
224
+ rubocop-performance (~> 1.21.0)
225
+ stringio (3.1.1)
226
+ stripe (13.0.0)
227
+ thor (1.3.2)
228
+ timeout (0.4.1)
204
229
  tzinfo (2.0.6)
205
230
  concurrent-ruby (~> 1.0)
206
- unicode-display_width (2.4.2)
231
+ unicode-display_width (2.6.0)
232
+ useragent (0.16.10)
233
+ webrick (1.8.2)
207
234
  websocket-driver (0.7.6)
208
235
  websocket-extensions (>= 0.1.0)
209
236
  websocket-extensions (0.1.5)
210
- zeitwerk (2.6.11)
237
+ zeitwerk (2.6.18)
211
238
 
212
239
  PLATFORMS
213
240
  arm64-darwin-22
241
+ arm64-darwin-23
214
242
  x86_64-linux
215
243
 
216
244
  DEPENDENCIES
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # NoCheckout
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/nocheckout.svg)](https://badge.fury.io/rb/nocheckout) [![Tests](https://github.com/rubymonolith/nocheckout/actions/workflows/main.yml/badge.svg)](https://github.com/rubymonolith/nocheckout/actions/workflows/main.yml)
4
+
3
5
  > [!IMPORTANT]
4
6
  > This project is a work in progress. This README was written to better understand the implementation for developers. **Some of the APIs may not have yet been implemented, renamed, or removed**. When the API settles down and is running in production for a while, a 1.0 release will be cut and this notice removed.
5
7
 
@@ -28,11 +30,7 @@ Before you do anything you'll need to go to https://dashboard.stripe.com/test/ap
28
30
  Stripe.api_key = Rails.configuration.stripe[:secret_key]
29
31
  ```
30
32
 
31
- ## Usage
32
-
33
- This library comes with two controllers, both map closely to their respective Stripe docs.
34
-
35
- ### Checkout Sessions Controller
33
+ ## Checkout Sessions Controller
36
34
 
37
35
  [Stripe Checkout Sessions](https://stripe.com/docs/api/checkout/sessions) send users from your website to a branded stripe.com page where they can enter their credit card details and complete the purchase. Once the purchase is complete, the user is redirected back to your website.
38
36
 
@@ -40,19 +38,40 @@ The NoCheckout::CheckoutSessionsController handles the interface between Stripe
40
38
 
41
39
  To get started, create a base CheckoutSessionsController that maps the Users from your application with [Stripe Customers](https://stripe.com/docs/api/customers).
42
40
 
41
+ ### Create user record after checkout is complete
42
+
43
+ This approach creates a new user record after the checkout is complete with the name and email they give during the Stripe checkout process.
44
+
43
45
  ```ruby
44
- class CheckoutSessionsController < NoCheckout::Stripe::CheckoutSessionsController
45
- protected
46
- def customer_id
47
- user.id
48
- end
46
+ class PaymentsController < NoCheckout::Stripe::CheckoutSessionsController
47
+ STRIPE_PRICE = "test_price_..."
48
+
49
+ def show
50
+ # Retrieve info from Stripe
51
+ customer = Stripe::Customer.retrieve checkout_session.customer
52
+ subscription = Stripe::Subscription.retrieve checkout_session.subscription
53
+
54
+ # Do stuff with Stripe info
55
+ user = User.find_or_create_by email: customer.email
56
+ customer.metadata.user_id = user.id
57
+ customer.save
58
+ user.name = customer.name
59
+ user.save!
60
+
61
+ # In this example we set the current user to stripe info. This likely
62
+ # doesn't make sense for your security context, so be careful...
63
+ self.current_user = user
64
+ redirect_to root_url
65
+ end
49
66
 
50
- def create_customer
51
- Stripe::Customer.create(
52
- id: customer_id,
53
- name: user.name,
54
- email: user.email
55
- )
67
+ protected
68
+ def create_checkout_session
69
+ super \
70
+ mode: "subscription",
71
+ line_items: [{
72
+ price: self.class::STRIPE_PRICE,
73
+ quantity: 1
74
+ }]
56
75
  end
57
76
  end
58
77
  ```
@@ -62,20 +81,46 @@ Then, for each product you want to offer, create a controller and inherit the `C
62
81
  ```ruby
63
82
  class PlusCheckoutSessionsController < PaymentsController
64
83
  STRIPE_PRICE = "price_..."
84
+ end
85
+ ```
86
+
87
+ There's a lot of different ways you can wire up the controllers depending on how many Stripe prices are in your application. This README assumes you're selling just a few products, so the prices are hard coded as constants in the controller. This could easily be populated from a database.
88
+
89
+ ### Create a user record before checkout is complete
90
+
91
+ ```ruby
92
+ class PaymentsController < NoCheckout::Stripe::CheckoutSessionsController
93
+ before_action :authorize_user # Loads a current_user
94
+
95
+ STRIPE_PRICE = "test_price_..."
96
+
97
+ def show
98
+ customer = Stripe::Customer.retrieve checkout_session.customer
99
+ subscription = Stripe::Subscription.retrieve checkout_session.subscription
100
+
101
+ # Do stuff with Stripe info
102
+
103
+ redirect_to root_url
104
+ end
65
105
 
66
106
  protected
67
107
  def create_checkout_session
68
- create_stripe_checkout_session line_items: [{
69
- price: STRIPE_PRICE,
70
- quantity: 1
71
- }]
108
+ super \
109
+ mode: "subscription",
110
+ customer: retrieve_or_create_customer(
111
+ id: current_user.id,
112
+ email: current_user.email,
113
+ name: current_user.name
114
+ ),
115
+ line_items: [{
116
+ price: self.class::STRIPE_PRICE,
117
+ quantity: 1
118
+ }]
72
119
  end
73
120
  end
74
121
  ```
75
122
 
76
- There's a lot of different ways you can wire up the controllers depending on how many Stripe prices are in your application. This README assumes you're selling just a few products, so the prices are hard coded as constants in the controller. This could easily be populated from a database.
77
-
78
- ### Webhooks Controller
123
+ ## Webhooks Controller
79
124
 
80
125
  [Stripe Webhooks](https://stripe.com/docs/webhooks) are extensive and keep your application up-to-date with what Stripe. In this example, we'll look at how to handle a subscription that's expiring and update a User record in our database.
81
126
 
@@ -1,42 +1,51 @@
1
1
  module NoCheckout::Stripe
2
2
  class CheckoutSessionsController < ApplicationController
3
+ # Name of the URL parameter stripe uses for the Checkout Session ID.
4
+ CHECKOUT_SESSION_ID_KEY = :checkout_session_id
5
+
3
6
  def new
4
7
  redirect_to checkout_session.url, allow_other_host: true
5
8
  end
6
9
 
7
10
  protected
8
11
  def checkout_session
9
- @checkout_session ||= find_or_create_checkout_session
12
+ @checkout_session ||= retrieve_or_create_checkout_session
10
13
  end
11
14
 
12
- def create_checkout_session
13
- raise "Implement a method here that returns a Stripe::Checkout::Session"
15
+ # Actually creates a Stripe checkout session. The reason I had to create
16
+ # this method is so I could "curry" the values within so the `create_checkout_session`
17
+ # could be a bit more readable and work better with inheritance.
18
+ def create_checkout_session(**attributes)
19
+ Stripe::Checkout::Session.create(**append_callback_urls(**attributes))
14
20
  end
15
21
 
16
- def customer_id
17
- current_user.id
22
+ def append_callback_urls(success_url:, cancel_url:, **attributes)
23
+ attributes.merge \
24
+ success_url: concat_unescaped_stripe_checkout_session_id(success_url),
25
+ cancel_url: concat_unescaped_stripe_checkout_session_id(cancel_url)
18
26
  end
19
27
 
20
- # Actually creates a Stripe checkout session. The reason I had to create
21
- # this method is so I could "curry" the values within so the `create_checkout_session`
22
- # could be a bit more readable and work better with inheritance.
23
- def create_stripe_checkout_session(**attributes)
24
- Stripe::Checkout::Session.create \
25
- mode: "subscription",
26
- customer: stripe_customer,
27
- success_url: success_url,
28
- cancel_url: cancel_url,
29
- **attributes
28
+ def retrieve_checkout_session(id: checkout_session_id)
29
+ Stripe::Checkout::Session.retrieve id
30
+ end
31
+
32
+ def checkout_session_id
33
+ params.fetch CHECKOUT_SESSION_ID_KEY, nil
34
+ end
35
+
36
+ def retrieve_or_create_checkout_session
37
+ if checkout_session_id.present?
38
+ retrieve_checkout_session
39
+ else
40
+ create_checkout_session
41
+ end
30
42
  end
31
43
 
32
- def callback_url(**kwargs)
33
- # Yuck! I have to do the append at the end because rails params escape the `{CHECKOUT_SESSION_ID}` values
34
- # to `session_id=%7BCHECKOUT_SESSION_ID%7D`. This will work though, but its def not pretty and feels a tad
35
- # dangerous.
36
- concat_unescaped_stripe_checkout_session_id url_for(action: :show, only_path: false, **kwargs)
44
+ def callback_url_for(*args, only_path: false, **kwargs)
45
+ url_for(*args, only_path: only_path, **kwargs)
37
46
  end
38
47
 
39
- STRIPE_CALLBACK_PARAMETER = "checkout_session_id={CHECKOUT_SESSION_ID}"
48
+ STRIPE_CALLBACK_PARAMETER = "#{CHECKOUT_SESSION_ID_KEY}={CHECKOUT_SESSION_ID}"
40
49
 
41
50
  # For some reason Stripe decided to not escape the `{CHECKOUT_SESSION_ID}`, if we try to
42
51
  # pass it through Rails URL builders or the URI object, it will URL encode the value and
@@ -51,35 +60,17 @@ module NoCheckout::Stripe
51
60
  end
52
61
  end
53
62
 
54
- def success_url
55
- callback_url(state: :success)
56
- end
57
-
58
- def cancel_url
59
- callback_url(state: :cancel)
60
- end
61
-
62
- def stripe_customer
63
- @stripe_customer ||= find_or_create_customer
64
- end
65
-
66
- def create_customer
67
- Stripe::Customer.create(
68
- id: String(customer_id),
69
- name: current_user.name,
70
- email: current_user.email
71
- )
72
- end
63
+ # def success_url
64
+ # callback_url(state: :success)
65
+ # end
73
66
 
74
- def find_or_create_checkout_session
75
- if params.key? :checkout_session_id
76
- Stripe::Checkout::Session.retrieve params.fetch(:checkout_session_id)
77
- else
78
- create_checkout_session
79
- end
80
- end
67
+ # def cancel_url
68
+ # callback_url(state: :cancel)
69
+ # end
81
70
 
82
- def find_or_create_customer
71
+ # Retrives a customer from Stripe and returns a nil if the customer does not exist (instead)
72
+ # of raising an exception, because this is not exceptional).
73
+ def retrieve_customer(id:)
83
74
  return nil if customer_id.blank?
84
75
 
85
76
  begin
@@ -88,12 +79,23 @@ module NoCheckout::Stripe
88
79
  rescue Stripe::InvalidRequestError => e
89
80
  case e.response.data
90
81
  in error: { code: "resource_missing" }
91
- create_customer
82
+ nil
92
83
  else
93
84
  raise
94
85
  end
95
86
  end
96
87
  end
97
88
 
89
+ # Creates a customer and automatically converts the ID to a string so this
90
+ # thing doesn't explode into oblivion.
91
+ def create_customer(id: nil, **attributes)
92
+ # If an ID is given, stripe insists that its a string.
93
+ id = String(id) unless id.nil?
94
+ Stripe::Customer.create(id: id, **attributes)
95
+ end
96
+
97
+ def retrieve_or_create_customer(id:, **attributes)
98
+ retrieve_customer(id: id) || create_customer(id: id, **attributes)
99
+ end
98
100
  end
99
101
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NoCheckout
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nocheckout
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brad Gessler
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-09-13 00:00:00.000000000 Z
11
+ date: 2024-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -42,14 +42,14 @@ dependencies:
42
42
  name: rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '7.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '7.0'
55
55
  description: Rails controllers for Stripe Checkout Sessions and Webhooks
@@ -102,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  requirements: []
105
- rubygems_version: 3.4.6
105
+ rubygems_version: 3.5.9
106
106
  signing_key:
107
107
  specification_version: 4
108
108
  summary: Rails controllers for Stripe Checkout Sessions and Webhooks