README.md in nocheckout-0.1.3 vs README.md in nocheckout-0.1.4
- old
+ new
@@ -1,7 +1,9 @@
# NoCheckout
+[![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)
+
> [!IMPORTANT]
> 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.
NoCheckout is a set of Rails controllers that does the least amount possible to integrate with Stripe. That might sound lazy at first, and it is, but if you try to roll your own signup and payment form and keep your Rails database sync'ed with your payment info, you'll quickly find out there's better things in life to worry about. Its best to delegate as much payment collection, processing, and reporting to your payment processor as you can. Fortunately Stripe does a great job sweating all the details in checkout UX and reporting that I'm OK delegating everything out to them.
@@ -26,57 +28,100 @@
```ruby
# Set the API key in ./config/initializers/stripe.rb
Stripe.api_key = Rails.configuration.stripe[:secret_key]
```
-## Usage
+## Checkout Sessions Controller
-This library comes with two controllers, both map closely to their respective Stripe docs.
-
-### Checkout Sessions Controller
-
[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.
The NoCheckout::CheckoutSessionsController handles the interface between Stripe and your Rails application and tries to be as small as possible.
To get started, create a base CheckoutSessionsController that maps the Users from your application with [Stripe Customers](https://stripe.com/docs/api/customers).
+### Create user record after checkout is complete
+
+This approach creates a new user record after the checkout is complete with the name and email they give during the Stripe checkout process.
+
```ruby
-class CheckoutSessionsController < NoCheckout::Stripe::CheckoutSessionsController
+class PaymentsController < NoCheckout::Stripe::CheckoutSessionsController
+ STRIPE_PRICE = "test_price_..."
+
+ def show
+ # Retrieve info from Stripe
+ customer = Stripe::Customer.retrieve checkout_session.customer
+ subscription = Stripe::Subscription.retrieve checkout_session.subscription
+
+ # Do stuff with Stripe info
+ user = User.find_or_create_by email: customer.email
+ customer.metadata.user_id = user.id
+ customer.save
+ user.name = customer.name
+ user.save!
+
+ # In this example we set the current user to stripe info. This likely
+ # doesn't make sense for your security context, so be careful...
+ self.current_user = user
+ redirect_to root_url
+ end
+
protected
- def customer_id
- user.id
+ def create_checkout_session
+ super \
+ mode: "subscription",
+ line_items: [{
+ price: self.class::STRIPE_PRICE,
+ quantity: 1
+ }]
end
-
- def create_customer
- Stripe::Customer.create(
- id: customer_id,
- name: user.name,
- email: user.email
- )
- end
end
```
Then, for each product you want to offer, create a controller and inherit the `CheckoutSessionsController`.
```ruby
class PlusCheckoutSessionsController < PaymentsController
STRIPE_PRICE = "price_..."
+end
+```
+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.
+
+### Create a user record before checkout is complete
+
+```ruby
+class PaymentsController < NoCheckout::Stripe::CheckoutSessionsController
+ before_action :authorize_user # Loads a current_user
+
+ STRIPE_PRICE = "test_price_..."
+
+ def show
+ customer = Stripe::Customer.retrieve checkout_session.customer
+ subscription = Stripe::Subscription.retrieve checkout_session.subscription
+
+ # Do stuff with Stripe info
+
+ redirect_to root_url
+ end
+
protected
def create_checkout_session
- create_stripe_checkout_session line_items: [{
- price: STRIPE_PRICE,
- quantity: 1
- }]
+ super \
+ mode: "subscription",
+ customer: retrieve_or_create_customer(
+ id: current_user.id,
+ email: current_user.email,
+ name: current_user.name
+ ),
+ line_items: [{
+ price: self.class::STRIPE_PRICE,
+ quantity: 1
+ }]
end
end
```
-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.
-
-### Webhooks Controller
+## Webhooks Controller
[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.
```ruby
class StripesController < NoCheckout::Stripe::WebhooksController