Skip to content

fix(stripe-plugin): convert refund amounts for zero-decimal currencies - #53

Open
hayashi7752 wants to merge 1 commit into
vendurehq:mainfrom
hayashi7752:fix/stripe-zero-decimal-refund
Open

fix(stripe-plugin): convert refund amounts for zero-decimal currencies#53
hayashi7752 wants to merge 1 commit into
vendurehq:mainfrom
hayashi7752:fix/stripe-zero-decimal-refund

Conversation

@hayashi7752

@hayashi7752 hayashi7752 commented Aug 18, 2026

Copy link
Copy Markdown

Problem

Refunds fail for zero-decimal currencies (JPY, KRW, …).

Vendure stores money amounts multiplied by 100, and the charge side already converts them for Stripe via getAmountInStripeMinorUnits (which divides by 100 for currencies without a fraction part). StripeService.createRefund, however, passes the raw Vendure amount straight to stripe.refunds.create, so a ¥1,300 refund (stored as 130000) is sent to Stripe as 130000 — 100x the real amount — and rejected:

StripeInvalidRequestError: Refund amount (¥130,000) is greater than charge amount (¥1,300)

This makes all refunds impossible on JPY stores (we hit this in production and have been running with a patched plugin since).

Fix

Apply the same currency check on the refund side so both directions stay symmetric with getAmountInStripeMinorUnits:

  • export currencyHasFractionPart from stripe-utils.ts
  • in createRefund, divide the amount by 100 for currencies without a fraction part

No behavior change for fractional currencies (USD, EUR, …).

Notes

  • Same root cause family as the charge-side issue Stripe plugin sends incorrect amount for JPY vendure#1630, which introduced getAmountInStripeMinorUnits — the refund path was left unconverted.
  • tsc -p tsconfig.build.json passes. Happy to add an e2e case for a zero-decimal channel if you'd like — let me know the preferred setup for switching the fixture currency.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Vendure stores money amounts multiplied by 100 and the charge side already
converts them for Stripe via getAmountInStripeMinorUnits. createRefund,
however, passed the raw Vendure amount straight to stripe.refunds.create,
so refunds in zero-decimal currencies (JPY, KRW, ...) were sent as 100x the
real amount and rejected by Stripe with "Refund amount (...) is greater
than charge amount".

Apply the same currency check on the refund side so both directions stay
symmetric, and export currencyHasFractionPart from stripe-utils for reuse.
@vendure-ci-automation-bot

Copy link
Copy Markdown
Contributor


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant