{"id":14955291,"url":"https://github.com/shey/rails-pay-checkout-demo","last_synced_at":"2025-10-24T07:31:10.069Z","repository":{"id":239663464,"uuid":"800176234","full_name":"shey/rails-pay-checkout-demo","owner":"shey","description":"Subscription Billing via the Pay Gem and Stripe","archived":false,"fork":false,"pushed_at":"2024-05-19T21:34:10.000Z","size":983,"stargazers_count":27,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-29T08:41:42.168Z","etag":null,"topics":["billing","pay","rails","stripe","subscription"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-13T21:03:57.000Z","updated_at":"2025-01-18T21:19:53.000Z","dependencies_parsed_at":"2024-05-19T21:40:23.559Z","dependency_job_id":null,"html_url":"https://github.com/shey/rails-pay-checkout-demo","commit_stats":{"total_commits":20,"total_committers":1,"mean_commits":20.0,"dds":0.0,"last_synced_commit":"6910a399a44d46de10eb9934451af02084c17b5c"},"previous_names":["shey/pay-stripe-rails","shey/rails-pay-checkout-demo"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shey%2Frails-pay-checkout-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shey%2Frails-pay-checkout-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shey%2Frails-pay-checkout-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shey%2Frails-pay-checkout-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shey","download_url":"https://codeload.github.com/shey/rails-pay-checkout-demo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237932070,"owners_count":19389560,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["billing","pay","rails","stripe","subscription"],"created_at":"2024-09-24T13:10:49.519Z","updated_at":"2025-10-24T07:31:10.064Z","avatar_url":"https://github.com/shey.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rails-pay-checkout-demo\n\nStripe integration with Rails and the Pay gem for Subscription Billing.\n\n![Landing Page](docs/demo.png)\n\n## Table of Contents\n\n- [Running The App](#running-the-app)\n- [Stripe Checkout](#stripe-checkout)\n  - [The sequence of events for Stripe Checkout are](#the-sequence-of-events-for-stripe-checkout-are)\n  - [Products and Prices](#products-and-prices)\n- [The Pay Integration](#the-pay-integration)\n  - [Set up your payment processor credentials and initializers](#set-up-your-payment-processor-credentials-and-initializers)\n    - [Stripe Credentials](#stripe-credentials)\n    - [Initializers](#initializers)\n  - [Add the `pay_customer` Class Method to the User Model](#add-the-pay_customer-class-method-to-the-user-model)\n  - [Request a Checkout URL and Redirect the User](#request-a-checkout-url-and-redirect-the-user)\n    - [Checkout URL Generator](#checkout-url-generator)\n  - [Handle Stripe Events](#handle-stripe-events)\n    - [Stripe CLI](#stripe-cli)\n    - [The Payment Succeed Event](#the-payment-succeed-event)\n- [Appendix](#appendix)\n  - [Relevant Files](#relevant-files)\n- [Related Articles](#related-articles)\n\n## Running the App\n\n```bash\nbin/setup     # Installs gems, creates the database, and runs seeds\nbin/dev       # Starts the Rails server with foreman (Procfile.dev)\n```\n\nNote: You’ll need the Stripe CLI running for webhooks to be received\n\n```bash\n$ stripe listen --forward-to localhost:3000/pay/webhooks/stripe\n```\n\n## Stripe Checkout\n\n**Stripe Checkout** Stripe Checkout is a checkout flow where Stripe hosts the payments page that collects the credit card details.\n\n### The sequence of events for Stripe Checkout are:\n\n1. A checkout session is created.\n1. The user is redirected to Stripe's payment page.\n1. The user completed a payment on Stripe's page.\n1. The user is redirected back to the app.\n1. The app receives a \"payment success\" webhook from Stripe.\n\n### Products and Prices\n\n[Products](https://dashboard.stripe.com/products) and prices are used manage subscription billing. In this app, each plan is its own product, and each product has a single [price](app/controllers/checkouts_controller.rb).\n\n![Stripe Product Catalogue Page](docs/product-catalogue.png)\n\n## The Pay Integration\n\nTo complete the integration\n\n1. Set up your payment processor credentials and [initializers](#initializers).\n1. Add the `pay_customer` the [User](#pay_customer) Model.\n1. Request a Checkout URL and [Redirect](#redirect) the User\n1. Handle Stripe [Events](#events)\n\n### Set up your payment processor credentials and initializers {#initializers}\n\n#### Stripe Credentials\n\nFollow Pay's [configuration instructions](https://github.com/pay-rails/pay/blob/main/docs/2_configuration.md#configuring-pay) to set up your Stripe credentials.\n\n#### Initializers\n\n1. Create or update the [stripe.rb](config/initializers/stripe.rb) initializer.\n1. Create the [pay.rb](config/initializers/pay.rb) initializer.\n\n### Add the `pay_customer` Class Method to the User Model\n\n1. **Generate the Pay Models**:\n\n   - Pay is already installed. For a fresh app, run `bin/rails pay:install:migrations` to create the necessary Pay models.\n\n2. **Update the User Model**:\n   - Add `pay_customer` to the User model:\n     ```ruby\n     class User \u003c ApplicationRecord\n       pay_customer\n     end\n     ```\n\nIncluding `pay_customer` in the User model establishes an internal association between the User and the `Pay::Customer` model. This association uses the `owner_type` and `owner_id` fields.\n\n`payment_processor` is the entry point to Pay's functionality. By including pay_customer in the User model, the payment_processor method becomes available on all User instances, providing access to customer, subscription, and charge models.\n\n### Request a Checkout URL and Redirect the User\n\nUsing Pay, request a checkout URL from Stripe and then redirect the user to that URL. Once the transaction is complete, Stripe will return the user to the URL defined by `success_URL`, along with a `session_id`.\n\n#### Checkout URL Generator\n\n```ruby\ndef checkout\n  user.payment_processor.checkout(\n    mode: \"subscription\",\n    line_items: stripe_price_id,\n    success_url: success_url,\n    billing_address_collection: \"auto\",\n    allow_promotion_codes: false,\n  )\nend\n```\n\n### Handle Stripe Events\n\n#### Stripe CLI\n\nThe Pay Gem requires Stripe Webhooks to function properly. When building the Pay integration locally, you'll need to set up the [Stripe CLI](https://docs.stripe.com/stripe-cli) and have it running to forward the events to your app.\n\n```bash\n$ stripe listen --forward-to localhost:3000/pay/webhooks/stripe\n```\n\nUpdate your stripe credentials to include the webhook signing secreted generated by the CLI.\n\n![stripe events](docs/events.png)\n\n#### The Payment Succeed Event\n\nWhen Stripe processes a payment successfully, it triggers the invoice.payment_succeeded [event] (https://github.com/pay-rails/pay/tree/main/test/pay/stripe/webhooks). Use this event to initiate other workflows in Rails. For instance, access a paid feature or a custom receipt.\n\n```ruby\nclass PaymentSucceededHandler\n  def call(event)\n    pay_charge = Pay::Stripe::Charge.sync(\n      event.data.object.charge,\n      stripe_account: event.try(:account)\n    )\n    return if pay_charge.nil?\n\n    adjust_user(pay_charge)\n  end\n\n  def adjust_user(pay_charge)\n    user = pay_charge.customer.owner\n    user.update!(updated_at: Time.zone.now)\n  end\nend\n```\n\n## Appendix\n\n### Relevant Files\n\n1. [user.rb](app/models/user.rb)\n1. [app/controllers/static_controller.rb](app/controllers/static_controller.rb)\n1. [app/controllers/checkouts_controller.rb](app/controllers/checkouts_controller.rb?#L23)\n1. [config/environments/development.rb](config/environments/development.rb?#L78)\n1. [app/services/stripe_checkout.rb](app/services/stripe_checkout.rb)\n1. [app/services/payment_succeded_handler.rb](app/services/payment_succeded_handler.rb)\n1. [config/initializers/pay.rb](config/initializers/pay.rb)\n1. [config/initializers/stripe.rb](config/initializers/stripe.rb)\n\n### Related Articles\n\n1. [Stripe Checkout](https://github.com/pay-rails/pay/blob/main/docs/stripe/8_stripe_checkout.md)\n1. [Routes and Webhooks](https://github.com/pay-rails/pay/blob/main/docs/7_webhooks.md)\n1. [Stripe Webhooks](https://github.com/pay-rails/pay/blob/main/docs/stripe/5_webhooks.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshey%2Frails-pay-checkout-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshey%2Frails-pay-checkout-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshey%2Frails-pay-checkout-demo/lists"}