Skip to content

Fix incorrect charge amount for currencies without fractions #138

Description

@cmbaldwin

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions