Coder Social home page Coder Social logo

solidusio / solidus_stripe Goto Github PK

View Code? Open in Web Editor NEW
36.0 11.0 61.0 1.21 MB

๐Ÿ’ณ Integrate Solidus with Stripe

Home Page: https://stripe.com

License: BSD 3-Clause "New" or "Revised" License

Ruby 90.73% Shell 2.17% JavaScript 2.31% CSS 0.24% HTML 4.55%
stripe-payment payment-methods solidus solidus-stripe stripe hacktoberfest

solidus_stripe's Introduction

Solidus Stripe

CircleCI codecov yardoc

Installation

Add solidus_stripe to your bundle and run the installation generator:

bundle add solidus_stripe
bin/rails generate solidus_stripe:install

Then set the following environment variables both locally and in production in order to setup the solidus_stripe_env_credentials static preference as defined in the initializer:

SOLIDUS_STRIPE_API_KEY                # will prefill the `api_key` preference
SOLIDUS_STRIPE_PUBLISHABLE_KEY        # will prefill the `publishable_key` preference
SOLIDUS_STRIPE_WEBHOOK_SIGNING_SECRET # will prefill the `webhook_signing_secret` preference

Once those are available you can create a new Stripe payment method in the /admin interface and select the solidus_stripe_env_credentials static preference.

โš ๏ธ Be sure to set the enviroment variables to the values for test mode in your development environment.

Webhooks setup

The webhooks URLs are automatically generated based on the enviroment, by default it will be scoped to live in production and test everywhere else.

Production enviroment

Before going to production, you'll need to register the webhook endpoint with Stripe, and make sure to subscribe to the events listed in the SolidusStripe::Webhook::Event::CORE constant.

So in your Stripe dashboard you'll need to set the webhook URL to:

https://store.example.com/solidus_stripe/live/webhooks

Non-production enviroments

While for development you should use the stripe CLI to forward the webhooks to your local server:

# Please refer to `stripe listen --help` for more options
stripe listen --forward-to http://localhost:3000/solidus_stripe/test/webhooks

Supporting solidus_frontend

If you need support for solidus_frontend please refer to the README of solidus_stripe v4.

Installing on a custom frontend

If 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.

Caveats

Authorization and capture and checkout finalization

Stripe supports two different flows for payments: authorization and capture and immediate payment.

Both 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.

Upgrading from v4

This extension is a complete rewrite of the previous version, and it's not generally compatible with v4.

That being said, if you're upgrading from v4 you can check out this guide to help you with the transition from payment tokens to payment intents: https://stripe.com/docs/payments/payment-intents/migration.

Usage

Showing reusable sources in the checkout

When saving stripe payment methods for future usage the checkout requires a partial for each supported payment method type.

For the full list of types see: https://stripe.com/docs/api/payment_methods/object#payment_method_object-type.

The extension will only install a partial for the card type, located in app/views/checkouts/existing_payment/stripe/_card.html.erb, and fall back to a default partial otherwise (see app/views/checkouts/existing_payment/stripe/_default.html.erb).

As an example, in order to show a wallet source connected to a SEPA Debit payment method the following partial should be added:

app/views/checkouts/existing_payment/stripe/_sepa_debit.html.erb

<% sepa_debit = stripe_payment_method.sepa_debit %>
๐Ÿฆ <%= sepa_debit.bank_code %> / <%= sepa_debit.branch_code %><br>
IBAN: **** **** **** **** **** <%= sepa_debit.last4 %>

Showing reusable sources in the admin interface

Refer to the previous section for information on how to set up a new payment method type. However, it's important to note that if you have to display a wallet source connected to a Stripe Payment Method other than "card" on the admin interface, you must include the partial in:

app/views/spree/admin/payments/source_forms/existing_payment/stripe/

Customizing Webhooks

Solidus Stripe comes with support for a few webhook events, 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.

Each 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.

Here's the list of events that are supported by default:

    payment_intent.succeeded
    payment_intent.payment_failed
    payment_intent.canceled
    charge.refunded

Adding a new event handler

In order to add a new handler you need to register the event you want to listen to, both in Stripe and in your application:

# config/initializers/solidus_stripe.rb
SolidusStripe.configure do |config|
  config.webhook_events = %i[charge.succeeded]
end

That will register a new :"stripe.charge.succeeded" event in the Solidus bus. The Solidus event will be published whenever a matching incoming webhook event is received. You can subscribe to it as usual:

# app/subscribers/update_account_balance_subscriber.rb
class UpdateAccountBalanceSubscriber
  include Omnes::Subscriber

  handle :"stripe.charge.succeeded", with: :call

  def call(event)
    # Please refere to the Stripe gem and API documentation for more details on the
    # structure of the event object. All methods called on `event` will be forwarded
    # to the Stripe event object:
    # - https://www.rubydoc.info/gems/stripe/Stripe/Event
    # - https://stripe.com/docs/webhooks/stripe-events

    Rails.logger.info "Charge succeeded: #{event.data.to_json}"
  end
end

# config/initializers/solidus_stripe.rb
# ...
Rails.application.config.to_prepare do
  UpdateAccountBalanceSubscriber.new.subscribe_to(Spree::Bus)
end

The passed event object is a thin wrapper around the Stripe event and the associated Solidus Stripe payment method. It will delegate all unknown methods to the underlying stripe event object. It can also be used in async adapters, which is recommended as otherwise the response to Stripe will be delayed until subscribers are done.

Configuring the webhook signature tolerance

You can also configure the signature verification tolerance in seconds (it defaults to the same value as Stripe default):

# config/initializers/solidus_stripe.rb
SolidusStripe.configure do |config|
  config.webhook_signature_tolerance = 150
end

Customizing the list of available Stripe payment methods

By default, the extension will show all the payment methods that are supported by Stripe in the current currency and for the merchant country.

You 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 for the full list of supported payment methods.

Non-card payment methods and "auto_capture"

Solidus 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 for more details.

Implementation

Payment state-machine vs. PaymentIntent statuses

When compared to the Payment state machine, Stripe payment intents have different set of states and transitions. The most important difference is that on Stripe a failure is not a final state, rather just a way to start over.

In order to map these concepts SolidusStripe will match states in a slightly unexpected way, as shown below.

Stripe PaymentIntent Status Solidus Payment State
requires_payment_method checkout
requires_action checkout
processing processing
requires_confirmation checkout
requires_capture pending
succeeded completed

Reference:

Deferred payment confirmation

This extensions is using the two-step payment 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.

Development

Retrieve your API Key and Publishable Key from your Stripe testing dashboard. You can get your webhook signing secret executing the stripe listen command.

Set SOLIDUS_STRIPE_API_KEY, SOLIDUS_STRIPE_PUBLISHABLE_KEY and SOLIDUS_STRIPE_WEBHOOK_SIGNING_SECRET environment variables (e.g. via direnv), this will trigger the default initializer to create a static preference for SolidusStripe.

Run bin/dev to start both the sandbox rail server and the file watcher through Foreman. That will update the sandbox whenever a file is changed. When using bin/dev you can safely add debugger statements, even if Foreman won't provide a TTY, by connecting to the debugger session through rdbg --attach from another terminal.

Visit /admin/payments and create a new Stripe payment using the static preferences.

See the Webhooks section to learn how to configure Stripe webhooks.

Testing the extension

First bundle your dependencies, then run bin/rake. bin/rake will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using bin/rake extension:test_app.

bin/rake

To run Rubocop static code analysis run

bundle exec rubocop

When testing your application's integration with this extension you may use its factories. Simply add this require statement to your spec/spec_helper.rb:

require 'solidus_stripe/testing_support/factories'

Or, if you are using FactoryBot.definition_file_paths, you can load Solidus core factories along with this extension's factories using this statement:

SolidusDevSupport::TestingSupport::Factories.load_for(SolidusStripe::Engine)

Running the sandbox

To run this extension in a sandboxed Solidus application, you can run bin/sandbox. The path for the sandbox app is ./sandbox and bin/rails will forward any Rails commands to sandbox/bin/rails.

Here's an example:

$ bin/rails server
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
* Listening on tcp://127.0.0.1:3000
Use Ctrl-C to stop

Releasing new versions

Please refer to the dedicated page on Solidus wiki.

License

Copyright (c) 2014 Spree Commerce Inc., released under the New BSD License Copyright (c) 2021 Solidus Team, released under the New BSD License.

solidus_stripe's People

Contributors

adammathys avatar aitbw avatar aldesantis avatar aleph1ow avatar assembled avatar brchristian avatar ccarruitero avatar chrishunt avatar cwise avatar deodad avatar elia avatar filippoliverani avatar futhr avatar geekoncoffee avatar huoxito avatar jdutil avatar jhawthorn avatar kennyadsl avatar loicginoux avatar nofxsk8 avatar radar avatar rainerdema avatar robertoles avatar senjai avatar spaghetticode avatar stuffmatic avatar sumirolabs avatar swcraig avatar tvdeyen avatar waiting-for-dev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

solidus_stripe's Issues

Undefined method `cvv_path'

Hello I use Solidus (3.2.2) with solidus_starter_frontend, I added manually the solidus_stripe's frontend views to the app and I get this error in the checkout payment step

NoMethodError in Spree::Checkout#edit

Showing /home/computer/shop/app/views/spree/checkout/payment/v3/_form_elements.html.erb where line #29 raised:

undefined method `cvv_path' for #<ActionDispatch::Routing::RoutesProxy:0x00000c8ef6aa4ad8 @scope=#<Spree::CheckoutController:0x0000000006dc90>, @routes=#<ActionDispatch::Routing::RouteSet:0x00000c8e63c8a700>, @helpers=#<Module:0x00000c8f1697d428>, @script_namer=#<Proc:0x00000c8e98e82500 /usr/local/lib/ruby/gems/3.1/gems/actionpack-7.0.4/lib/action_dispatch/routing/mapper.rb:653 (lambda)>>



  <%= label_tag "card_cvc", t('spree.card_code') %>
  <div id="card_cvc"></div>
  <%= link_to "(#{t('spree.what_is_this')})", spree.cvv_path, target: '_blank', "data-hook" => "cvv_link", id: "cvv_link" %>
</div>

<div id="card-errors" class='errorExplanation' role="alert" style="display: none"></div>

How to pass zip code when add a Credit Card

We need to send the user's zip code when he adds a credit card to Stripe.
There's a way to do that? or if anyone can point me in the right direction in the code to review the logic?

Thanks!

Stripe Elements submit button stuck in disabled state.

The payment form submit button is created like this in the default _payment.html.erb template

<div class="form-buttons" data-hook="buttons">
  <%= submit_tag t('spree.save_and_continue'), class: 'continue button primary' %>
  <script>Spree.disableSaveOnClick();</script>
</div>

As far as I can tell, Spree.disableSaveOnClick() disables the submit button when the form is submitted, leaving it up to the response handler to re-enable it if the request fails. However, Stripe Elements sometimes seem to invoke the response handler immediately (probably based on cached form state), before Spree.disableSaveOnClick() disables the button, with the effect that the button remains disabled. This can be reproduced like this:

  1. Submit payment form without filling in any fields. This results in an error message and the submit button is re-enabled.
  2. Submit the empty form again.
  3. Fill in valid payment info, try to click the submit button and notice it's disabled.

I tried changing the code that re-enables the submit button in SolidusStripe.Elements.prototype.showError to this

setTimeout(function () {
    this.submitButton.removeAttr('disabled').removeClass('disabled');
}.bind(this), 10)

which seems to solve the problem. It's not very pretty though...

Any ideas about how to proceed with this? Should it be fixed in solidus_stripe?

RFC: Overhauling solidus_stripe

Problem

The current implementation is very old:

  • It's jQuery based
  • it's solidus_frontend based
  • it's supporting 3 types of integrations + configurations with a high number of total combinations
  • no support for non-credit-card payments (e.g. ApplePay, etc)

Proposal

We want to overhaul the extension and at the same time drop support for the legacy frontend, moving to a more scaffolding based installation (vs. view/controller inheritance).

Ruled-out approaches

  • We considered updating the existing extension to work with SSF first, and then cleaning it up, but we concluded that the effort would have increased
  • We considered cleaning up the extension before adding to SSF support, and then switching to the Payment Element, but that too would have needed more effort
  • We considered starting with Stripe Checkout, but that would have disrupted the current setup too much (maybe can be a feature added in the future)*

Plan

  • Start from scratch using the current extension only as a reference and cherry pick code (vs copying everything and then cleaning up)
  • We want to start from the Payment Element which comes with support for multiple payment methods, while still working well in the classic step-based checkout featured in SSF (vs. switching to the fully external Stripe Checkout)
  • The new implementation will be tested with the approach featured in solidusio/solidus_paypal_commerce_platform#166 with a full-fledged dummy-app

*Stripe Checkout is an extremely optimized checkout solution and we might want to add support to it in the future. Since it includes a lot of new required functionality (webhooks, possibly syncing Product and other information with Stripe) we considered this out of scope for the overhaul.

Auto_capture=yes not working

Need to add event logic to make auto_capture flow work .

  order = event.payload[:order]
  order.payments.pending.each do |payment|
    payment.capture!
  end

  Spree::OrderUpdater.new(order).update
end

Maybe it's a needed config feature

Could not find generator 'solidus_stripe:install'

I did every step as in the installation instructions, but when I run:
bundle exec rails g solidus_stripe:install
I get:
Could not find generator 'solidus_stripe:install'. Maybe you meant "solidus:auth:install"?

This is my gemfile:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.7.0'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.2', '>= 6.0.2.1'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Active Storage variant
# gem 'image_processing', '~> 1.2'

gem 'solidus'
gem 'solidus_auth_devise'
gem 'solidus_stripe', git: 'https://github.com/solidusio/solidus_stripe'
# gem 'solidus_stripe', '~> 3.0'
# gem 'solidus_stripe'

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers
  gem 'webdrivers'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

rails version: 6.0.3.1

Any help would be appreciated! ๐Ÿ˜ƒ

[ADMIN]ย Order cancel doen't work with Payment Intents captured payments

When trying to cancel an order with an already captured payment made using the Payment Intents API, the application raises an error with the following message from Stripe:

A PaymentIntent object can be canceled when it is in one of these statuses: 
requires_payment_method, requires_capture, requires_confirmation, requires_action

This error can be avoided by refunding the payment (instead of canceling it) during the order canceling process.

Custom stripe element field options (e.g for showing a credit card icon)

When using Stripe Elements, custom options can be passed when creating the cardNumber, cardExpiry and cardCvc fields. Among other things, these options can be used to specify

  • custom input field placeholders
  • custom CSS classes
  • if the a credit card icon should be shown for the cardNumber field

See the Stripe docs for a complete list of options (use the green dropdown menu to switch between field types).

Here's an example of a cardNumber field with a custom placeholder and a credit card brand icon.

cardnumber

It would be nice to add overridable hooks for passing custom options. Maybe something like this:

SolidusStripe.Elements.prototype.cardNumberElementOptions = function () {
  return {
    style: this.baseStyle(),
    showIcon: true,
    placeholder: "I'm a custom placeholder!"
  }
}
this.elements.create('cardNumber', this.cardNumberElementOptions());

I'm happy to create a PR for this, but will wait for feedback on #40 first since it touches the same code.

Fix incorrect charge amount for currencies without fractions

There is an issue with charged amounts in currencies without fractions (e.g. JPY) being divided by 100, which happens here: https://github.com/activemerchant/active_merchant/blob/db0e8d4f042b58aaff4af9fefef232f8e7528b8d/lib/active_merchant/billing/gateway.rb#L279
Perhaps override this method: https://github.com/solidusio/solidus/blob/e878076f2ed670d07654ab6293a16588743f2fa6/core/app/models/spree/payment.rb#L74

Error on Stripe API with fake card in testing mode:
image

Summary
Iโ€™m using the V1 api for a store in Japanese (JPY currency). Amounts are losing two zeros before being sent to the Stripe/Charges API.

Concerned Gems:

gem 'solidus', '~> 3.1'
gem 'solidus_stripe', 4.3'

Config:

  config.static_model_preferences.add(
    Spree::PaymentMethod::StripeCreditCard,
<img width="1478" alt="image" src="https://user-images.githubusercontent.com/7152249/205527744-9e2638e4-1ea4-4034-abbd-579032fa194f.png">

    'stripe_env_credentials',
    secret_key: ENV['STRIPE_SECRET_KEY'],
    publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
    stripe_country: 'JP',
    v3_elements: false,
    v3_intents: false
  )

โ€จโ€จMy Research:
The auth trigger happens here (called by the state machine)
Sent to the gateway here
Money is calculated here
It goes through Monetize / RubyMoney using the 'cents' method. That flows through to here

This can be seen in practice with something like this:
order = Spree::Order.find('ORDER NUMBER HERE')
amount = order.payments.first.amount
currency = order.currency
Spree::Money.new(amount, {currency: currency})
=> #<Spree::Money:0x000000013b0d9f58 @money=#, @options={:sign_before_symbol=>true, :currency=>"JPY"}>
Spree::Money.new(amount, {currency: currency}).money.centsโ€จ=> 14000
โ€จAll looks good so farโ€ฆ
This is then processed by the gateway here
Turned into a post for the Stripe API starting here
The amount for the post is calculated here
The amount is localized here

We can see that JPY is both in the payment (if you interrupt the authorization process to debug, the currency and country and correctly applied), so โ€˜JPYโ€™ triggers currencies without fractions, which are specified here.

This all posts to the /charges/ path of the Stripe API

โ€จโ€จSo, I think the amount is being converted to a float, then divided by 100, and then plugged into the api post. For example I have a product that has tax and shipping included that comes to ยฅ3200. At checkout in dev using a test api key, when going from confirm to complete (as authorize gets called), itโ€™s giving an error that the amount is too low to be chargedโ€”ยฅ32.
โ€จโ€จ
I first brought this up on Slack, and was encouraged to give it a go myself.
I'm still working on trying to fix it myself, but it's proving to be pretty stubborn (almost the same text as here).

about LICENSE

I have some doubts about 3a79c59

I think the copyright notice in README could be Copyright (c) 2020 Solidus Team and contributors or something like these instead Copyright (c) 2020 Spree Commerce Inc., released under the New BSD License.

Also, I think it's ok to add another copyright notice in LICENSE, always that you don't remove the original.

Copyright (c) 2014 Spree Commerce Inc. and other contributors.
Copyright (c) 2020 Solidus Team and other contributors.

What do you think?

Payment Intent creation exception handling with class not present in the gem

After updating the solidus_stripe gem and writing some tests, I had some problems with exception handling during the creation of an intent payment.
In SolidusStripe::IntentsController:

def create_intent
begin
@intent = create_payment_intent
rescue Stripe::CardError => e
render json: { error: e.message }, status: 500
return
end
generate_payment_response
end

The Stripe::CardError class is an integral part of the stripe-ruby gem, which I don't find included here.

From a first analysis, it seems that it's the only point where a stripe-ruby class is used.

Workaround

To overcome this problem, I merely momentarily included the gem in the project.

Additional context

Exception backtrace
NameError (uninitialized constant SolidusStripe::IntentsController::Stripe):

solidus_stripe (4.0.0) app/controllers/solidus_stripe/intents_controller.rb:10:in `rescue in create_intent'
solidus_stripe (4.0.0) app/controllers/solidus_stripe/intents_controller.rb:8:in `create_intent'
actionpack (5.2.4.2) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (5.2.4.2) lib/abstract_controller/base.rb:194:in `process_action'
actionpack (5.2.4.2) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (5.2.4.2) lib/abstract_controller/callbacks.rb:42:in `block in process_action'
activesupport (5.2.4.2) lib/active_support/callbacks.rb:132:in `run_callbacks'
actionpack (5.2.4.2) lib/abstract_controller/callbacks.rb:41:in `process_action'
actionpack (5.2.4.2) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (5.2.4.2) lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
activesupport (5.2.4.2) lib/active_support/notifications.rb:168:in `block in instrument'
activesupport (5.2.4.2) lib/active_support/notifications/instrumenter.rb:23:in `instrument'
activesupport (5.2.4.2) lib/active_support/notifications.rb:168:in `instrument'
actionpack (5.2.4.2) lib/action_controller/metal/instrumentation.rb:32:in `process_action'
actionpack (5.2.4.2) lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
activerecord (5.2.4.2) lib/active_record/railties/controller_runtime.rb:24:in `process_action'
actionpack (5.2.4.2) lib/abstract_controller/base.rb:134:in `process'
actionview (5.2.4.2) lib/action_view/rendering.rb:32:in `process'
actionpack (5.2.4.2) lib/action_controller/metal.rb:191:in `dispatch'
actionpack (5.2.4.2) lib/action_controller/metal.rb:252:in `dispatch'
actionpack (5.2.4.2) lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
actionpack (5.2.4.2) lib/action_dispatch/routing/route_set.rb:34:in `serve'
actionpack (5.2.4.2) lib/action_dispatch/journey/router.rb:52:in `block in serve'
actionpack (5.2.4.2) lib/action_dispatch/journey/router.rb:35:in `each'
actionpack (5.2.4.2) lib/action_dispatch/journey/router.rb:35:in `serve'
actionpack (5.2.4.2) lib/action_dispatch/routing/route_set.rb:840:in `call'
railties (5.2.4.2) lib/rails/engine.rb:524:in `call'
railties (5.2.4.2) lib/rails/railtie.rb:190:in `public_send'
railties (5.2.4.2) lib/rails/railtie.rb:190:in `method_missing'
actionpack (5.2.4.2) lib/action_dispatch/routing/mapper.rb:19:in `block in <class:Constraints>'
actionpack (5.2.4.2) lib/action_dispatch/routing/mapper.rb:48:in `serve'
actionpack (5.2.4.2) lib/action_dispatch/journey/router.rb:52:in `block in serve'
actionpack (5.2.4.2) lib/action_dispatch/journey/router.rb:35:in `each'
actionpack (5.2.4.2) lib/action_dispatch/journey/router.rb:35:in `serve'
actionpack (5.2.4.2) lib/action_dispatch/routing/route_set.rb:840:in `call'
warden (1.2.8) lib/warden/manager.rb:36:in `block in call'
warden (1.2.8) lib/warden/manager.rb:34:in `catch'
warden (1.2.8) lib/warden/manager.rb:34:in `call'
rack (2.2.2) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.2) lib/rack/etag.rb:27:in `call'
rack (2.2.2) lib/rack/conditional_get.rb:40:in `call'
rack (2.2.2) lib/rack/head.rb:12:in `call'
actionpack (5.2.4.2) lib/action_dispatch/http/content_security_policy.rb:18:in `call'
rack (2.2.2) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.2) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (5.2.4.2) lib/action_dispatch/middleware/cookies.rb:670:in `call'
actionpack (5.2.4.2) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (5.2.4.2) lib/active_support/callbacks.rb:98:in `run_callbacks'
actionpack (5.2.4.2) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (5.2.4.2) lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
actionpack (5.2.4.2) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
lograge (0.11.2) lib/lograge/rails_ext/rack/logger.rb:15:in `call_app'
railties (5.2.4.2) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (5.2.4.2) lib/active_support/tagged_logging.rb:71:in `block in tagged'
activesupport (5.2.4.2) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (5.2.4.2) lib/active_support/tagged_logging.rb:71:in `tagged'
railties (5.2.4.2) lib/rails/rack/logger.rb:26:in `call'
actionpack (5.2.4.2) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
request_store (1.4.1) lib/request_store/middleware.rb:19:in `call'
actionpack (5.2.4.2) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.2.2) lib/rack/method_override.rb:24:in `call'
rack (2.2.2) lib/rack/runtime.rb:22:in `call'
actionpack (5.2.4.2) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.4.2) lib/action_dispatch/middleware/static.rb:127:in `call'
rack (2.2.2) lib/rack/sendfile.rb:110:in `call'
railties (5.2.4.2) lib/rails/engine.rb:524:in `call'
rack (2.2.2) lib/rack/urlmap.rb:74:in `block in call'
rack (2.2.2) lib/rack/urlmap.rb:58:in `each'
rack (2.2.2) lib/rack/urlmap.rb:58:in `call'
capybara (3.12.0) lib/capybara/server/middleware.rb:48:in `call'
puma (3.12.4) lib/puma/configuration.rb:227:in `call'
puma (3.12.4) lib/puma/server.rb:675:in `handle_request'
puma (3.12.4) lib/puma/server.rb:476:in `process_client'
puma (3.12.4) lib/puma/server.rb:334:in `block in run'
puma (3.12.4) lib/puma/thread_pool.rb:135:in `block in spawn_thread'

Visa credit card type is blank

I just noticed the mapCC function seems to expect the string Visa for Visa cards, whereas the Stripe API seems to return visa, which causes the cc_type of the Spree::CreditCard to be empty.

The example response in this section of the Stripe API has brand set to visa, which is what I'm seeing. Intrestingly, this section seems to suggest it should be Visa.

I'm using the test Visa card 4242 4242 4242 4242 and have v3_intents set to true. I haven't yet been able to test this for other card types, so I can't suggest a general solution at this point.

Finally, a huge thanks for your work on this gem!

Application can't find gem partials

Hello! For some reason our Solidus application isn't properly adding this gem's partials to the view path. We're running Solidus 2.11.3 and and Solidus Stripe 4.2. Is there any additional configuration other than what's listed in the README?

A token may not be passed in as a PaymentMethod. Instead, create a PaymentMethod or convert your token to a PaymentMethod by setting the `card[token]`

Hello I use solidus_stripe (4.3.0) with v3 Elements and v3 Intents, when I try to make a payment I get (from the Stripe API ?) A token may not be passed in as a PaymentMethod. Instead, create a PaymentMethod or convert your token to a PaymentMethod by setting the 'card[token]'

ENV

Solidus Version: 3.2.2
Frontend: solidus_starter_frontend
Env: development mode
Rails version: 7.0.4

404 on create_intents

Trying to integrate v3 intents , followed the readme but i keep getting thoses errors on js side :

Feature Policy: Skipping unsupported feature name โ€œpaymentโ€. v3:1:78187
Feature Policy: Skipping unsupported feature name โ€œpaymentโ€. v3:1:78325
Feature Policy: Skipping unsupported feature name โ€œpaymentโ€. v3:1:178554

and when i submit the test card informations :

POSThttps://_my_web_site_url.com/stripe/create_intent [HTTP/1.1 404 Not Found 897ms]

I keep searching for what kind of integration error i could've done but nothing , i have the feeling it lack a memeber of the posting url
all mentions in stripe's doc are specifying a version in them .

i'am running
rails 5.2.6 on ruby 2.7 with:
solidus (2.10.5)
solidus_api (= 2.10.5)
solidus_backend (= 2.10.5)
solidus_core (= 2.10.5)
solidus_frontend (= 2.10.5)
solidus_sample (= 2.10.5)
solidus_api (2.10.5)
solidus_stripe (4.2.0)
in Spree config :
config.static_model_preferences.add(
Spree::PaymentMethod::StripeCreditCard,
'stripe_env_credentials',
secret_key:'sk_test_aksdhflkajsgdflkuasgdf',
publishable_key: 'pk_test_kjhga;lihglkashglasd',
stripe_country: 'FR',
v3_elements: false,
v3_intents: true,
)
And the stripe static conf has been selected in the backend 'payment page .

Thanks for all , anyway , and if this is an issue, glad i can help .

Roadmap to remove ActiveMerchant dependency?

It made complete sense that the old solidus_gateway extension was built on top of active_merchant, because both of them are meant to support a large number of gateways with as uniform a style as possible.

However, more recently Solidus has deprecated solidus_gateway in favor of individual extensions that support one gateway each, and hence in the case of Stripe we have the new solidus_stripe extension.

However, because it was extracted from the original solidus_gateway code, solidus_stripe is still built on active_merchant, which has a number of downsides, including:

  • Increasing the number dependencies
  • Increasing the attack surface
  • More code for developers to learn
  • Greater complexity in debugging
  • Inability to take advantage of more Stripe-specific functionality that other gateways lack

I wonder, would there be interest in this community in a PR that would remove the dependency on active_merchant in favor of directly utilizing the official stripe gem?

I'd be happy to help if this would be of interest. :)

Auto capture behavior in v4.0.0

I just tried v4.0.0 of this gem and noticed that payments are not automatically captured, even though I have auto_capture set to true in my config. I also tried setting auto capture to "Yes" via the admin interface without any luck. However, it seems like auto capturing works when using an existing card on file.

I noticed the following passage in the readme

These charges are created uncaptured and will need to be captured in Solidus backend later, after the customer confirms the order

Does this mean that I'll have to implement my own hook for automatically capturing payments when an order is completed? And is the auto capture option not used anymore? It would be great if someone could clarify.

Could not create payment

I'm trying to add stripe payments to our e-commerce, as we need to handle SCA payment flow for EU customers.

Every time I try to pay with one of stripe's test card (3ds cards) confirmation modal is shown and it seems to be going ok, once payment is confirmed on aforementioned modal a "create_payment" request is being sent to

Request URL: http://localhost:3000/stripe/create_payment
Request Method: POST

and it keeps failing with
{"error":"Could not create payment" }

In Stripes' dashboard there are no errors but every payment intent created is confirmed successfully and then instantly cancelled, I'm assuming it's happening once create_payment is called in intents_controller.rb:

def create_payment
        create_payment_service = SolidusStripe::CreateIntentsPaymentService.new(
          params[:stripe_payment_intent_id],
          stripe,
          self
        )
  
        resp = create_payment_service.call
        
        if create_payment_service.call
          render json: { success: true }
        else
          render json: { error: "Could not create payment" }, status: 500
        end
      end

I'm attaching some screenshots from stripe's dashboard.
Screenshot 2021-06-04 at 14 56 27
Screenshot 2021-06-04 at 14 56 19

SolidusStripe::CreateIntentsPaymentService.new(..) is always failing without any meaningful error.
I've already tried searching in your issues section but I haven't found anything related to this.

"You cannot cancel this PaymentIntent because it has a status of canceled" error

I've started seeing an error that I haven't seen before when trying to proceed from the payment step:

Spree::Core::GatewayError (You cannot cancel this PaymentIntent because it has a
status of canceled. Only a PaymentIntent with one of the following statuses may be
canceled: requires_payment_method, requires_capture, requires_confirmation, requires_action.):

As far as I can tell, I haven't made any changes to my code that would explain this and I'm using a test card number that I've successfully used before (4242 4242 4242 4242).

Here's the full stacktrace

I'm using solidus_stripe 4.0.0, solidus 2.10 and rails 6.0.2.2.

Any clues would be greatly appreciated.

Create a supporting branch for the current major + SF

  • Blocked by #143
  • Create a v4 branch and mark it as a protected branch, similarly to what we did with solidus_paypal_commerce_platform

As stated in #135 we're about to reboot this extension with only SSF support. This means that if we need to release patch or minor level updates to the current version (v4.x) we need a branch from which we can release them.

Duplicates charges with Payment Intents

At the moment the Payment Intents implementation creates duplicate charges for each order. This is visible only on the Stripe dashboard page.

The first payment, currently invisible on Solidus (nothing is recorded on the DB) is created and charged instantly as soon as the customer authorizes their credit card. The second one is created after the order is finalized on Solidus backend, like it does for Elements and other payment implementations. This second charge needs to be captured later.

A possible workaround for this issue is proposed in #43, while waiting for a better solution to be prepared.

Reuse Stripe profiles when customer adds a new credit card

When a Spree::User adds a new credit card and that user already has a saved credit card stored we should reuse their existing Stripe customer profile instead of creating a new one.

This is a screenshot from a Stripe test account that shows a single email address with 3 different customer accounts, each with one single credit card:

Schermata 2020-01-30 alle 17 54 59

This can be surely done when using the Stripe official gem, but we need to investigate if ActiveMerchant allows this.

Add support for Apple Pay through Stripe Payment Request Button

We need to add support for Apple Pay, with v3 Elements enabled, by adding support for Payment Request Button.

I did some experiment with @aldesantis today and to display the button it's just matter of adding the following code to the stripe v3 partial currently on master:

diff --git a/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb b/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb
index 2369d82..ce37cc7 100644
--- a/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb
+++ b/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb
@@ -1,3 +1,7 @@
+<div id="payment-request-button">
+  <!-- A Stripe Element will be inserted here. -->
+</div>
+
 <%= image_tag 'credit_cards/credit_card.gif', id: 'credit-card-image' %>
 <% param_prefix = "payment_source[#{payment_method.id}]" %>

@@ -62,14 +66,37 @@
     }
   };

+  var paymentRequest = stripe.paymentRequest({
+    country: 'US',
+    currency: 'usd',
+    total: {
+      label: 'Demo total',
+      amount: 1099,
+    },
+    requestPayerName: true,
+    requestPayerEmail: true,
+  });
+
   var cardNumber = elements.create('cardNumber', {style: style});
   var cardExpiry = elements.create('cardExpiry', {style: style});
   var cardCvc = elements.create('cardCvc', {style: style});
+  var prButton = elements.create('paymentRequestButton', {
+    paymentRequest: paymentRequest,
+  });

   cardNumber.mount('#card_number');
   cardExpiry.mount('#card_expiry');
   cardCvc.mount('#card_cvc');

+  // Check the availability of the Payment Request API first.
+  paymentRequest.canMakePayment().then(function(result) {
+    if (result) {
+      prButton.mount('#payment-request-button');
+    } else {
+      document.getElementById('payment-request-button').style.display = 'none';
+    }
+  });
+
   $(function() {
     var form = Spree.stripePaymentMethod.parents('form');
     var submitButton = form.find('input[type="submit"]');

Of course, it needs to have dynamic data taken from the current order.

The remaining part to be implemented is creating and completing the payment (step 4. of the guide linked above). Since we need Stripe PaymentIntent to create the payment, #19 needs to be closed before starting here.

ActionView::MissingTemplate in Spree::Checkout#edit

Solidus version

3.2.2 with solidus_starter_frontend

Problem

Hello I installed solidus_stripe (4.3.0) but when I go to the route checkout/payment I get

ActionView::MissingTemplate in Spree::Checkout#edit 

 Showing /home/computer/shop/app/views/spree/checkout/steps/payment_step/_payment_method_controls.html.erb where line#4 raised:

  Missing partial spree/checkout/payment/_stripe with {:locale=>[:fr], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder, :haml]}.

Searched in:
  * "/home/computer/shop/app/views"
  * "/usr/local/lib/ruby/gems/3.1/gems/solidus_stripe-4.3.0/lib/views/backend"
  * "/usr/local/lib/ruby/gems/3.1/gems/solidus_stripe-4.3.0/lib/views/api"
  * "/usr/local/lib/ruby/gems/3.1/gems/view_component-2.71.0/app/views"
  * "/usr/local/lib/ruby/gems/3.1/gems/solidus_backend-3.2.2/app/views"
  * "/usr/local/lib/ruby/gems/3.1/gems/kaminari-core-1.2.2/app/views"
  * "/usr/local/lib/ruby/gems/3.1/gems/solidus_api-3.2.2/app/views"
  * "/usr/local/lib/ruby/gems/3.1/gems/solidus_auth_devise-2.5.4/lib/views/backend"
  * "/usr/local/lib/ruby/gems/3.1/gems/devise-4.8.1/app/views"
  * "/usr/local/lib/ruby/gems/3.1/gems/solidus_core-3.2.2/app/views"
  * "/usr/local/lib/ruby/gems/3.1/gems/actiontext-7.0.4/app/views"
  * "/usr/local/lib/ruby/gems/3.1/gems/actionmailbox-7.0.4/app/views"

Did you mean?  spree/api/payments/source_views/stripe
               spree/admin/log_entries/stripe
               spree/admin/payments/source_forms/stripe
               spree/admin/payments/source_views/stripe
               spree/checkout/payment/gateway
               spree/admin/promotions/rules/store
    
  
Extracted source (around line #4):

<% methods.each do |method| %>
     <li id="payment_method_<%= method.id %>">
       <%= render( 
        "spree/checkout/payment/#{method.partial_name}",
        payment_method: method
     ) %>

    
Trace of template inclusion: #<ActionView::Template 
app/views/spree/checkout/steps/_payment_step.html.erb 
locals=["differentiator", "form"]>, #<ActionView::Template 
app/views/spree/checkout/_checkout_step.html.erb locals=["order"]>, 
#<ActionView::Template app/views/spree/checkout/edit.html.erb 
locals=[]>

  
Rails.root: /home/computer/shop

3D Secure Issue - User charged before manual capture

Current Flow: Payment is being processed/charged after user completes 3D secure authentication
(user does not confirm order)
(user is charged before Backend Solidus captures payment manually)

Expected Flow: Payment is processed/charged after user completes/confirms order (after 3D secure)

Facing dependency issue after upgrade solidus 3

I am facing the following issue after upgrade solidus version.

In Gemfile:
    solidus (= 3.0.1) was resolved to 3.0.1, which depends on
      solidus_core (= 3.0.1)

    solidus_stripe was resolved to 4.2.0, which depends on
      solidus_core (>= 2.3, < 3)

In the published solidus_stripe rubygems mentioned as below,

RUNTIME DEPENDENCIES (3):
solidus_core >= 2.3, < 3

Please publish latest version in the rubygems.
cc @kennyadsl

Handle missing shipping method on PrepareOrderForPaymentService

Currently, PrepareOrderForPaymentService assumes the existence of a shipping method param - however, there are circumstances in which this param could be missing. As an example, on a clients checkout flow using google pay, there's a bug (with Stripe?) that sometimes causes this to happen:
Screen Shot 2021-05-12 at 11 40 12 AM
However, it's also possible for a user to hit "pay" before the server responds with shipping rates, which will put the payment iframe in the same state. Also, if the server times on address change for whatever reason, this will happen.

There's a few ways to get into this scenario, but it's not handled - so PrepareOrderForPaymentService will error out, and the user will sit through a spinning screen until the request times out, then get an error.

IMO, if a desired shipping method is not provided, we should just use the default shipping rate that Solidus automatically selects.

Just to provide some code that fixes this issue, here's the prepender I created that solves this issue on the clients app:

# frozen_string_literal: true

module %(scrubbed clients module)
  module SolidusStripe
    module PrepareOrderForPaymentService
      module AddDefaultShippingMethod
        def initialize(address, controller)
          @address = address
          @order = controller.current_order
          @user = controller.spree_current_user
          @email = controller.params[:email]
          @shipping_id = controller.params[:shipping_option][:id] if controller.params[:shipping_option]
        end

        private

        def set_shipping_rate
          return super if shipping_id

          # Solidus selects a default shipping rate when the shipment
          # is generated, and we (currently) only have one shipping
          # method and no way to select different ones. So, instead of
          # breaking because of a missing shipping rate parameter
          # %(scrubbed ticket num), let's just go with the default selected rate.

          true
        end
      end
    end
  end
end

A token may not be passed in as a PaymentMethod. Instead, create a PaymentMethod or convert your token to a PaymentMethod by setting the `card[token]` parameter to

Hi,

currently getting an error
A token may not be passed in as a PaymentMethod. Instead, create a PaymentMethod or convert your token to a PaymentMethod by setting the card[token] parameter to

spree.rb file
config.static_model_preferences.add(
Spree::PaymentMethod::StripeCreditCard,
'stripe_env_credentials',
secret_key: ENV['XXXXXX'],
publishable_key: ENV[โ€˜XXXXXX'],
stripe_country: 'AUS',
v3_elements: true,
v3_intents: true,
server: Rails.env.production? ? 'production' : 'test',
test_mode: !Rails.env.production?
)

Card used as per the test card 4000 0027 6000 3184
stripe admin

Remove Solidus 2.x deprecations

  • Add a method in solidus_support that understands if name should be used combined or not taking into account the Solidus version used and the related preference's value solidusio/solidus_support#58
  • Release a new version of Solidus Support
  • Remove deprecation warnings related to the address' name combined.
  • DEPRECATION WARNING: From Solidus v3.0 onwards, #perform! will need to be explicitly called when creating new refunds. Please, change your code from: Spree::Refund.create(your: attributes) to: Spree::Refund.create(your: attributes, perform_after_create: false).perform! (called from try_void at ~/Code/solidusio/solidus_stripe/app/models/spree/payment_method/stripe_credit_card.rb:90)
  • DEPRECATION WARNING: Please, do not use Spree::Refund @response anymore, use Spree::Refund#perform_response Args: [] (called from record_response at ~/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/bundler/gems/solidus-ed88ebc464d1/core/app/models/spree/payment/processing.rb:206)
  • DEPRECATION WARNING: Please, do not use Spree::Refund @response anymore, use Spree::Refund#perform_response Args: [] (called from handle_void_response at /~/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/bundler/gems/solidus-ed88ebc464d1/core/app/models/spree/payment/processing.rb:132)

cc @rainerdema

Single page checkout doesn't work with v3 form elements

๐Ÿ‘‹ Hey all!

v3 form elements don't work with single page checkouts. It requires a billing_address, and that is set on pageload from the orders existing billing address.

On single page checkout for a new customer, a new billing address is usually built on pageload, but it is not a valid address until the user fills it in - and because v3 form elements loads in the billing address on pageload, it will try to submit an invalid address as the billing address (regardless of what the user filled in), causing validation errors when on payment source creation.

Rather than the payment intent creator just using the payment source address, I think it should first look for the existence of an address in the order params, as that will be more up-to-date, and work with a single page checkout flow.

This is a prepender that fixes this issue on a clients project:

# frozen_string_literal: true

module [scrubbed_client_namespace]
  module SolidusStripe
    module CreateIntentsPaymentService
      module UseAddressParamsForPayment
        # Usually we have a billing address on the payment source in these
        # params because it is populated at pageload, however in single
        # page checkout, this mostly won't be the case. This ensures that
        # we can use the orders ship_address or bill_address params in that
        # case.
        def address_attributes
          if html_order_data["use_shipping"] == "1"
            html_order_data["ship_address_attributes"]
          elsif html_order_data["bill_address_attributes"]
            html_order_data["bill_address_attributes"]
          else
            super
          end
        end

        def html_order_data
          if form_data.is_a?(String)
            data = Rack::Utils.parse_nested_query(form_data)
            data["order"]
          else
            {}
          end
        end
      end
    end
  end
end

Stripe checkout fails when using a stored credit card number

We're using this gem to implement stripe checkout and it works fine the first time the user places an order. But on subsequent checkouts it fails if the user selects the "Use an existing card on file" option on the payments page. It looks to me like the gem expects the user to enter a credit card every time but maybe I'm misreading the code. We get this JS error in the console:

TypeError: element.data is not a function
enableElement (jquery_ujs.self-784a997f6726036b1993eb2217c9cb558e1cbb801c6da88105588c56f13b466a.js?body=1:383)
(anonymous) (payment:363)
setTimeout (async)
(anonymous) (payment:362)
Promise.then (async)
(anonymous) (payment:359)
dispatch (jquery3.self-e200ee796ef24add7054280d843a80de75392557bb4248241e870fac0914c0c1.js?body=1:5238)
elemData.handle (jquery3.self-e200ee796ef24add7054280d843a80de75392557bb4248241e870fac0914c0c1.js?body=1:5045)```

Using static credentials

Hello,

I was asked to leave this issue by Peter as encountered a problem using the static credentials for this gem.

Docs all followed, set to use 'stripe_env_credentials' in the admin panel, with the following set in config/initializers/spree :

  config.static_model_preferences.add(
    Spree::PaymentMethod::StripeCreditCard,
    'stripe_env_credentials',
    secret_key: ENV['STRIPE_SECRET_KEY'],
    publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
    stripe_country: 'US',
    v3_elements: false,
    v3_intents: false,
    server: Rails.env.production? ? 'production' : 'test',
    test_mode: !Rails.env.production?
  )
end

Gives this error when I try to pay using Stripe test card in development:

ArgumentError in Spree::CheckoutController#update
Missing required parameter: login

Error output:

            raise ArgumentError.new("Parameter: #{param.first} must be one of #{valid_options.to_sentence(words_connector: 'or')}") unless valid_options.include?(hash[param.first])
          else
            raise ArgumentError.new("Missing required parameter: #{param}") unless hash.has_key?(param)
          end
        end
      end

Works fine when creds are set in the admin panel...

Hope this helps, let me know if you need more info.

Clearer documentation on how to implement

The current documentation goes over how it install, but not how to actually implement this into a project. Ive been stuck on trying to figure this out for a few days now.

The main topics i've been stuck on are...

  1. Do you have to set the source class for Spree::PaymentMethod::StripeCreditCard to Spree::PaymentMethod::StripeCreditCard (it defaults to Spree::CreditCard) or nil?.
  2. What does an example request body look like to the POST orders/{order number}/payments api when sending back a token?

Solidus needs a login parameter?

I'm getting this error when I go to test a payment:

I, [2021-11-29T09:19:19.656205 #19393] INFO -- : [39855e67-587e-4ebe-8f22-143f843806a1] Started PATCH"/checkout/update/payment" for 24.228.203.152 at 2021-11-29 09:19:19 +0100
I, [2021-11-29T09:19:19.658170 #19393] INFO -- : [39855e67-587e-4ebe-8f22-143f843806a1] Proce
ssing by Spree::CheckoutController#update as HTML
I, [2021-11-29T09:19:19.658416 #19393] INFO -- : [39855e67-587e-4ebe-8f22-143f843806a1] Par
ameters: {"authenticity_token"=>"[FILTERED]", "order"=>{"payments_attributes"=>[{"payment_meth
od_id"=>"4"}]}, "payment_source"=>{"2"=>{"name"=>"REDACTED", "number"=>"[FILTERED]", "expir
y"=>"", "verification_value"=>"[FILTERED]", "address_attributes"=>{"name"=>"REDACTED", "com
pany"=>"", "address1"=>"REDATED", "address2"=>"", "city"=>"REDACTED", "country_id"=

"REDACTED", "state_id"=>"REDACTED", "state_name"=>"", "zipcode"=>"REDACTED", "phone"=>"", "alternative_ph
one"=>""}, "cc_type"=>""}, "4"=>{"name"=>"REDACTED", "number"=>"[FILTERED]", "expiry"=>"6/29", "verification_value"=>"[FILTERED]", "address_attributes"=>{"name"=>"REDACTED", "comp
any"=>"", "address1"=>"REDACTED", "address2"=>"", "city"=>"REDACTED", "country_id"=>
"REDACTED", "state_id"=>"REDACTED", "state_name"=>"", "zipcode"=>"REDACTED", "phone"=>"", "alternative_pho
ne"=>""}, "cc_type"=>"visa"}}, "state"=>"payment"}
I, [2021-11-29T09:19:19.778745 #19393] INFO -- : [39855e67-587e-4ebe-8f22-143f843806a1] Compl
eted 500 Internal Server Error in 120ms (ActiveRecord: 47.5ms | Allocations: 38329)
F, [2021-11-29T09:19:19.780714 #19393] FATAL -- : [39855e67-587e-4ebe-8f22-143f843806a1]
[39855e67-587e-4ebe-8f22-143f843806a1] ArgumentError (Missing required parameter: login):
[39855e67-587e-4ebe-8f22-143f843806a1]
[39855e67-587e-4ebe-8f22-143f843806a1] activemerchant (1.124.0) lib/active_merchant/billing/ga
teway.rb:325:in `block in requires!'

What login parameter?!

bundle install
.
.
.
Using solidus_square 0.0.1
.
.
.
Bundle complete! 23 Gemfile dependencies, 152 gems now installed.
Use bundle info [gemname] to see where a bundled gem is installed.
bundle info solidus_square

config/initializers/solidus_square.rb

SolidusSquare.configure do |config|

Elements and Intents

When attempting to use V3 Elements and V3 Intents payment posts successfully but than fails with the attachment

Request:
POST /v1/payment_methods/tok_1GezloGb1nS7u12v8onl6dvqt/attach

Request Body

{
  "customer": "cus_HQQdaU5eAZWzcK"
}

Resposne

{
  "error": {
    "message": "A token may not be passed in as a PaymentMethod. Instead, create a PaymentMethod or convert your token to a PaymentMethod by setting the `card[token]` parameter to tok_1GezloGb1nS7u12v8onl6dvqt.",
    "param": "payment_method",
    "type": "invalid_request_error"
  }
}

Screen Shot 2020-05-05 at 9 22 22 AM

Remove dependency on jQuery

With modern browsers is possible to get away from jquery, still have wide support and stay sane, all without requiring that kind of dependency on the project itself.

Shipping cost payment refund rejected from Stripe API because of negative charge value

Hi there,

I'm about to launch my first production store using Solidus and this solidus_stripe gem. While changing from a paid to a free shipping type after the order was placed, the automatic payment adjustment failed with a message that reads "This value must be greater than or equal to 1" for a charge of -$15. My Stripe account is currently in test mode, and I'm running the latest version of both Solidus and this gem.

Do you have any ideas for how I can resolve this issue? I would expect that the difference between the old price and new price would be applied and charged to the Stripe account on save.

Preference :stripe_country is not defined on Spree::PaymentMethod::StripeCreditCard (RuntimeError)

I'm unable to start my application after installing this payment method.

I am setting up a static configuration to pull the stripe credentials from the env:

  config.static_model_preferences.add(
    Spree::PaymentMethod::StripeCreditCard,
    'stripe_env_credentials',
    secret_key: ENV['STRIPE_SECRET_KEY'],
    publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
    stripe_country: 'SG',
    v3_elements: false,
    v3_intents: false,
    server: Rails.env.production? ? 'production' : 'test',
    test_mode: !Rails.env.production?
  )

On a side note, the installation step says to run

bundle exec rails g solidus_stripe:install

but that did not exist. I instead ran

bundle exec rails solidus_stripe:install:migrations

Javascript don't working after solidus_stripe installation

Solidus Version:
Solidus 3.2.2
solidus_stripe (4.3.0)

To Reproduce

rails new store -d=mysql --skip-javascript
bundle add solidus
rails g solidus:install (solidus_starter_frontend)
bundle add solidus_stripe
rails g solidus_stripe:install

Current behavior

Javascript console:

Uncaught ReferenceError: $ is not defined
    <anonymous> http://localhost:3000/assets/spree/frontend/solidus_starter_frontend-b03c93961bdbee4504f4d86e8e9f075d5c500a1f96043f2187a767f5606603a9.js:1129
    <anonymous> http://localhost:3000/assets/spree/frontend/solidus_starter_frontend-b03c93961bdbee4504f4d86e8e9f075d5c500a1f96043f2187a767f5606603a9.js:1282

Uncaught ReferenceError: Solidus is not defined
    <anonymous> http://localhost:3000/:54

Expected behavior
Javascript working

Screenshots

Desktop (please complete the following information):

  • Rails Version: 7.0.4
  • Ruby Version: 3.1.2
  • Browser: Firefox 100

Initializer fails with uninitialized constant Spree::PaymentMethod

I added this to my spree/solidus initializer:

  config.static_model_preferences.add(
    Spree::PaymentMethod::StripeCreditCard,
    'stripe_env_credentials',
    secret_key: ENV['STRIPE_SECRET_KEY'],
    publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
    stripe_country: 'US',
    v3_elements: false,
    v3_intents: true
  )

But looks like it does not work, looks like the classes are not loaded up and the initializer fails.

Calling the same class on the console after removing it from initializer works fine but not sure how to set the payment method at that step. As a workaround I set it up thru the admin section for now.

Gems:

gem 'rails', '>= 7.0.2.4'
gem "solidus", "~> 3.2"                                                                                                                                                                                                    
gem "solidus_frontend", "~> 3.2"                                                                                                                                                                                           
gem "solidus_stripe", "~> 4.3" 

Pay with Apple Pay from cart page

User's shipping information can be collected directly on Apple Pay, and passed back to Solidus in order to have all the information needed to complete the order bypassing the checkout entirely.

๐Ÿ“– https://stripe.com/docs/stripe-js/elements/payment-request-button#html-js-collecting-shipping-info

We could add an Apple Pay button in the cart via this extension (I'd go with just proving a partial that devs can add to their cart page where they prefer). Once we have the payment information back, we should create/complete the order filling the shipping/billing info that we retrieve back from Apple Pay.

The only gotcha here is that we don't have available shipping rates yet on the cart and we need to pass shipping option to Apple Pay, since users will pick on option directly in there. We could, by default, just pass all the available shipping method to Apple Pay and use a configuration class to allow devs to override the default behavior with their custom logic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.