{"id":20779135,"url":"https://github.com/solidusio/solidus_stripe","last_synced_at":"2025-04-05T03:12:27.460Z","repository":{"id":36011456,"uuid":"158291995","full_name":"solidusio/solidus_stripe","owner":"solidusio","description":"💳 Integrate Solidus with Stripe","archived":false,"fork":false,"pushed_at":"2024-02-02T18:15:56.000Z","size":1242,"stargazers_count":35,"open_issues_count":37,"forks_count":59,"subscribers_count":11,"default_branch":"main","last_synced_at":"2024-04-26T00:05:54.746Z","etag":null,"topics":["hacktoberfest","payment-methods","solidus","solidus-stripe","stripe","stripe-payment"],"latest_commit_sha":null,"homepage":"https://stripe.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/solidusio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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},"funding":{"open_collective":"solidus"}},"created_at":"2018-11-19T21:24:37.000Z","updated_at":"2024-01-04T18:29:49.000Z","dependencies_parsed_at":"2024-02-24T20:02:53.140Z","dependency_job_id":null,"html_url":"https://github.com/solidusio/solidus_stripe","commit_stats":{"total_commits":748,"total_committers":117,"mean_commits":"6.3931623931623935","dds":0.7660427807486632,"last_synced_commit":"ede6ec937b79ee6098cddfed25d9c6b7da7ea92e"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio%2Fsolidus_stripe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio%2Fsolidus_stripe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio%2Fsolidus_stripe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio%2Fsolidus_stripe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/solidusio","download_url":"https://codeload.github.com/solidusio/solidus_stripe/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247280272,"owners_count":20912967,"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":["hacktoberfest","payment-methods","solidus","solidus-stripe","stripe","stripe-payment"],"created_at":"2024-11-17T13:26:13.207Z","updated_at":"2025-04-05T03:12:27.426Z","avatar_url":"https://github.com/solidusio.png","language":"Ruby","readme":"# Solidus Stripe\n\n[![CircleCI](https://circleci.com/gh/solidusio/solidus_stripe.svg?style=shield)](https://circleci.com/gh/solidusio/solidus_stripe)\n[![codecov](https://codecov.io/gh/solidusio/solidus_stripe/branch/main/graph/badge.svg)](https://codecov.io/gh/solidusio/solidus_stripe)\n[![yardoc](https://img.shields.io/badge/docs-rubydoc.info-informational)](https://rubydoc.info/gems/solidus_stripe)\n\n\u003c!-- Explain what your extension does. --\u003e\n\n## Installation\n\nAdd solidus_stripe to your bundle and run the installation generator:\n\n```shell\nbundle add solidus_stripe\nbin/rails generate solidus_stripe:install\n```\n\nThen set the following environment variables both locally and in production in order\nto setup the `solidus_stripe_env_credentials` static preference as defined in the initializer:\n\n```shell\nSOLIDUS_STRIPE_API_KEY                # will prefill the `api_key` preference\nSOLIDUS_STRIPE_PUBLISHABLE_KEY        # will prefill the `publishable_key` preference\nSOLIDUS_STRIPE_WEBHOOK_SIGNING_SECRET # will prefill the `webhook_signing_secret` preference\n```\n\nOnce those are available you can create a new Stripe payment method in the /admin interface\nand select the `solidus_stripe_env_credentials` static preference.\n\n⚠️ Be sure to set the enviroment variables to the values for test mode in your development environment.\n\n### Webhooks setup\n\nThe webhooks URLs are automatically generated based on the enviroment, \nby default it will be scoped to `live` in production and `test` everywhere else.\n\n#### Production enviroment\n\nBefore going to production, you'll need to [register the webhook endpoint with\nStripe](https://stripe.com/docs/webhooks/go-live), and make sure to subscribe\nto the events listed in [the `SolidusStripe::Webhook::Event::CORE`\nconstant](https://github.com/solidusio/solidus_stripe/blob/main/lib/solidus_stripe/webhook/event.rb).\n\nSo in your Stripe dashboard you'll need to set the webhook URL to:\n\n    https://store.example.com/solidus_stripe/live/webhooks\n\n#### Non-production enviroments\n\nWhile for development [you should use the stripe CLI to forward the webhooks to your local server](https://stripe.com/docs/webhooks/test#webhook-test-cli):\n\n```shell\n# Please refer to `stripe listen --help` for more options\nstripe listen --forward-to http://localhost:3000/solidus_stripe/test/webhooks\n```\n\n### Supporting `solidus_frontend`\n\nIf you need support for `solidus_frontend` please refer to the [README of solidus_stripe v4](https://github.com/solidusio/solidus_stripe/tree/v4#readme).\n\n### Installing on a custom frontend\n\nIf you're using a custom frontend you'll need to adjust the code copied to your application by the installation generator. Given frontend choices can vary wildly, we can't provide a one-size-fits-all solution, but we are providing this simple integration with `solidus_starter_frontend` as a reference implementation. The amount of code is intentionally kept to a minimum, so you can easily adapt it to your needs.\n\n### API support\n\nThe gem includes an API interface with two endpoints: `create_setup_intent` and `create_payment_intent`. \nAfter configuring the gem, both endpoints will be accessible.\n\n#### Create Setup Intent\n\nThis endpoint allows you to create an intent for configuring a saved payment method.\nIt can be executed before making an actual payment to set up a card for future use.\n\n`POST /solidus_stripe/api/create_setup_intent`\n\n**Params**\n\n`payment_method_id`- ID of the `SolidusStripe::PaymentMethod` record\n\n#### Create Payment Intent\n\nThis endpoint creates a payment intent for an order and returns a client secret that\ncan be used to initialize Stripe's widget. Stripe later confirms the payment via a webhook call.\n\n`POST /solidus_stripe/api/create_payment_intent`\n\nThis endpoint loads the last incomplete Spree order via the `last_incomplete_spree_order method`\nfor a logged-in user, or it takes an optional `guest_token` parameter for a guest user.\n\n**Params**\n\n`payment_method_id` - ID of the `SolidusStripe::PaymentMethod` record\n\n`stripe_payment_method_id` - ID of the payment method, obtained by frontend from Stripe\n\n`guest_token` - optional\n\n## Caveats\n\n### Authorization and capture and checkout finalization\n\nStripe supports two different flows for payments: [authorization and capture](https://stripe.com/docs/payments/capture-later) and immediate payment. \n\nBoth flows are supported by this extension, but you should be aware that they will happen before the order finalization, just before the final confirmation. At that moment if the payment method of choice will require additional authentication (e.g. 3D Secure) the extra authentication will be shown to the user.\n\n### Upgrading from v4\n\nThis extension is a complete rewrite of the previous version, and it's not generally compatible with v4.\n\nThat being said, if you're upgrading from v4 you can check out this guide to help you with the transition\nfrom payment tokens to payment intents: https://stripe.com/docs/payments/payment-intents/migration.\n\n## Usage\n\n### Showing reusable sources in the checkout\n\nWhen saving stripe payment methods for future usage the checkout requires\na partial for each supported payment method type.\n\nFor the full list of types see: https://stripe.com/docs/api/payment_methods/object#payment_method_object-type.\n\nThe extension will only install a partial for the `card` type, located in `app/views/checkouts/existing_payment/stripe/_card.html.erb`,\nand fall back to a `default` partial otherwise (see `app/views/checkouts/existing_payment/stripe/_default.html.erb`).\n\nAs an example, in order to show a wallet source connected to a\n[SEPA Debit payment method](https://stripe.com/docs/api/payment_methods/object#payment_method_object-sepa_debit)\nthe following partial should be added:\n\n`app/views/checkouts/existing_payment/stripe/_sepa_debit.html.erb`\n\n```erb\n\u003c% sepa_debit = stripe_payment_method.sepa_debit %\u003e\n🏦 \u003c%= sepa_debit.bank_code %\u003e / \u003c%= sepa_debit.branch_code %\u003e\u003cbr\u003e\nIBAN: **** **** **** **** **** \u003c%= sepa_debit.last4 %\u003e\n```\n\n### Showing reusable sources in the admin interface\n\nRefer to the previous section for information on how to set up a new payment method type.\nHowever, it's important to note that if you have to display a wallet source connected to a\nStripe Payment Method other than \"card\" on the admin interface, you must include the partial in:\n\n`app/views/spree/admin/payments/source_forms/existing_payment/stripe/`\n\n### Customizing Webhooks\n\nSolidus Stripe comes with support for a few [webhook events](https://stripe.com/docs/webhooks), to which there's a default handler. You can customize the behavior of those handlers by or add to their behavior by replacing or adding subscribers in the internal Solidus event bus.\n\nEach event will have the original Stripe name, prefixed by `stripe.`. For example, the `payment_intent.succeeded` event will be published as `stripe.payment_intent.succeeded`.\n\nHere's the list of events that are supported by default:\n\n        payment_intent.succeeded\n        payment_intent.payment_failed\n        payment_intent.canceled\n        charge.refunded\n\n#### Adding a new event handler\n\nIn order to add a new handler you need to register the event you want to listen to, \nboth [in Stripe](https://stripe.com/docs/webhooks/go-live) and in your application:\n\n```ruby\n# config/initializers/solidus_stripe.rb\nSolidusStripe.configure do |config|\n  config.webhook_events = %i[charge.succeeded]\nend\n```\n\nThat will register a new `:\"stripe.charge.succeeded\"` event in the [Solidus\nbus](https://guides.solidus.io/customization/subscribing-to-events). The\nSolidus event will be published whenever a matching incoming webhook event is\nreceived. You can subscribe to it [as usual](https://guides.solidus.io/customization/subscribing-to-events):\n\n```ruby\n# app/subscribers/update_account_balance_subscriber.rb\nclass UpdateAccountBalanceSubscriber\n  include Omnes::Subscriber\n\n  handle :\"stripe.charge.succeeded\", with: :call\n\n  def call(event)\n    # Please refere to the Stripe gem and API documentation for more details on the\n    # structure of the event object. All methods called on `event` will be forwarded\n    # to the Stripe event object:\n    # - https://www.rubydoc.info/gems/stripe/Stripe/Event\n    # - https://stripe.com/docs/webhooks/stripe-events\n\n    Rails.logger.info \"Charge succeeded: #{event.data.to_json}\"\n  end\nend\n\n# config/initializers/solidus_stripe.rb\n# ...\nRails.application.config.to_prepare do\n  UpdateAccountBalanceSubscriber.new.subscribe_to(Spree::Bus)\nend\n```\n\nThe passed event object is a thin wrapper around the [Stripe\nevent](https://www.rubydoc.info/gems/stripe/Stripe/Event) and the associated\nSolidus Stripe payment method. It will delegate all unknown methods to the\nunderlying stripe event object. It can also be used in async [\nadapters](https://github.com/nebulab/omnes#adapters), which is recommended as\notherwise the response to Stripe will be delayed until subscribers are done.\n\n#### Configuring the webhook signature tolerance\n\nYou can also configure the signature verification tolerance in seconds (it\ndefaults to the [same value as Stripe\ndefault](https://stripe.com/docs/webhooks/signatures#replay-attacks)):\n\n```ruby\n# config/initializers/solidus_stripe.rb\nSolidusStripe.configure do |config|\n  config.webhook_signature_tolerance = 150\nend\n```\n\n### Customizing the list of available Stripe payment methods\n\nBy default, the extension will show all the payment methods that are supported by Stripe in the current currency and for the merchant country.\n\nYou can customize the list of available payment methods by overriding the `payment_method_types` option in the `app/views/checkouts/payment/_stripe.html.erb` partial. Please refer to the [Stripe documentation](https://stripe.com/docs/payments/payment-methods) for the full list of supported payment methods.\n\n### Non-card payment methods and \"auto_capture\"\n\nSolidus payment methods are configured with a `auto_capture` option, which is used to determine if the payment should be captured immediately or not. If you intend to use a non-card payment method, it's likely that you'll need to set `auto_capture` to `true` in the payment method configuration. Please refer to the [Stripe documentation](https://stripe.com/docs/payments/payment-methods/integration-options#additional-api-supportability) for more details.\n\n## Implementation\n\n### Payment state-machine vs. PaymentIntent statuses\n\nWhen compared to the Payment state machine, Stripe payment intents have different set of states and transitions.\nThe most important difference is that on Stripe a failure is not a final state, rather just a way to start over.\n\nIn order to map these concepts SolidusStripe will match states in a slightly unexpected way, as shown below.\n\n| Stripe PaymentIntent Status | Solidus Payment State |\n| --------------------------- | --------------------- |\n| requires_payment_method     | checkout              |\n| requires_action             | checkout              |\n| processing                  | processing            |\n| requires_confirmation       | checkout              |\n| requires_capture            | pending               |\n| succeeded                   | completed             |\n\nReference:\n\n- https://stripe.com/docs/payments/intents?intent=payment\n- https://github.com/solidusio/solidus/blob/main/core/lib/spree/core/state_machines/payment.rb\n\n### Deferred payment confirmation\n\nThis extensions is using the [two-step payment confirmation](https://stripe.com/docs/payments/build-a-two-step-confirmation) flow. This means that at the payment step the payment form will just collect the basic payment information (e.g. credit card details) and any additional confirmation is deferred to the confirmation step.\n\n## Development\n\nRetrieve your API Key and Publishable Key from your [Stripe testing dashboard](https://stripe.com/docs/testing). You can\nget your webhook signing secret executing the `stripe listen` command.\n\nSet `SOLIDUS_STRIPE_API_KEY`, `SOLIDUS_STRIPE_PUBLISHABLE_KEY` and `SOLIDUS_STRIPE_WEBHOOK_SIGNING_SECRET` environment\nvariables (e.g. via `direnv`), this will trigger the default initializer to create a static preference for SolidusStripe.\n\nRun `bin/dev` to start both the sandbox rail server and the file watcher through Foreman. That will update the sandbox whenever\na file is changed. When using `bin/dev` you can safely add `debugger` statements, even if Foreman won't provide a TTY, by connecting\nto the debugger session through `rdbg --attach` from another terminal.\n\nVisit `/admin/payments` and create a new Stripe payment using the static preferences.\n\nSee the [Webhooks section](#webhooks) to learn how to configure Stripe webhooks.\n\n### Testing the extension\n\nFirst bundle your dependencies, then run `bin/rake`. `bin/rake` will default to building the dummy\napp if it does not exist, then it will run specs. The dummy app can be regenerated by using\n`bin/rake extension:test_app`.\n\n```shell\nbin/rake\n```\n\nTo run [Rubocop](https://github.com/bbatsov/rubocop) static code analysis run\n\n```shell\nbundle exec rubocop\n```\n\nWhen testing your application's integration with this extension you may use its factories.\nSimply add this require statement to your `spec/spec_helper.rb`:\n\n```ruby\nrequire 'solidus_stripe/testing_support/factories'\n```\n\nOr, if you are using `FactoryBot.definition_file_paths`, you can load Solidus core\nfactories along with this extension's factories using this statement:\n\n```ruby\nSolidusDevSupport::TestingSupport::Factories.load_for(SolidusStripe::Engine)\n```\n\n### Running the sandbox\n\nTo run this extension in a sandboxed Solidus application, you can run `bin/sandbox`. The path for\nthe sandbox app is `./sandbox` and `bin/rails` will forward any Rails commands to\n`sandbox/bin/rails`.\n\nHere's an example:\n\n```\n$ bin/rails server\n=\u003e Booting Puma\n=\u003e Rails 6.0.2.1 application starting in development\n* Listening on tcp://127.0.0.1:3000\nUse Ctrl-C to stop\n```\n\n### Releasing new versions\n\nPlease refer to the dedicated [page](https://github.com/solidusio/solidus/wiki/How-to-release-extensions) on Solidus wiki.\n\n## License\n\nCopyright (c) 2014 Spree Commerce Inc., released under the New BSD License\nCopyright (c) 2021 Solidus Team, released under the New BSD License.\n","funding_links":["https://opencollective.com/solidus"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolidusio%2Fsolidus_stripe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolidusio%2Fsolidus_stripe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolidusio%2Fsolidus_stripe/lists"}