Stripe Integration & Multi-Currency Deposit Refactor
๐ Overview
We integrated Stripe as a payment provider for deposits, refactored our multi-currency deposit flow, and improved our exchange rate caching logic. This ensures robust, auditable, and correct handling of all deposit scenarios, including cross-currency and zero-decimal currencies.
๐ ๏ธ What We Did
๐ฆ Stripe Payment Provider Integration
- ๐ Implemented a
PaymentProvider
interface and a concrete Stripe implementation using the official stripe-go SDK. - ๐ Migrated to the new
stripe.Client
pattern for future-proofing and better testability. - ๐งฉ Injected the payment provider into the handler chain for clean separation of concerns.
๐ Deposit Flow Refactor
- ๐๏ธ The service layer now only emits a deposit event; all business logic is handled in the handler chain.
- โ Added a
PaymentProviderHandler
to the chain, which: - ๐ณ Initiates payments with Stripe.
- ๐ Handles payment IDs and errors.
- ๐ฑ Ensured currency conversion is always performed before crediting the account, using up-to-date exchange rates.
๐ฑ Multi-Currency & Zero-Decimal Currency Handling
- ๐ Fixed a critical bug: previously, JPY deposits were multiplied by 100, resulting in 100x overcharging on Stripe.
- ๐งฎ Now, the amount sent to Stripe is calculated using currency metadata (e.g., decimals for USD vs. JPY).
- ๐ All deposit and conversion logic is fully auditable and testable.
๐๏ธ Exchange Rate Cache Logic
- ๐ Refactored cache lookup to always check both direct and reverse currency pairs, with consistent TTL/freshness logic.
- ๐งน Removed backend-specific logic for more predictable and maintainable caching.
๐ Problems We Faced & Solutions
๐ฑ Currency Conversion Mismatches
- โ Problem: Deposits in a currency different from the accountโs currency were not being converted, leading to accounting errors.
- โ Solution: Enforced conversion in the handler chain, always crediting the account in its own currency.
๐ธ Stripe Amount Calculation for Zero-Decimal Currencies
- โ Problem: JPY and other zero-decimal currencies were incorrectly multiplied by 100, causing 100x overcharging.
- โ Solution: Used currency metadata to determine the correct multiplier for Stripeโs smallest unit.
๐๏ธ Inconsistent Exchange Rate Caching
- โ Problem: Cache logic was inconsistent, sometimes missing valid rates or using stale data.
- โ Solution: Unified cache lookup logic for both direct and reverse pairs, backend-agnostic.
๐งฉ Clean Architecture & Testability
- โ Problem: Payment provider logic was mixed into the service layer, making it hard to test and extend.
- โ Solution: Moved all provider logic into a dedicated handler in the chain, improving modularity and testability.
๐ฎ Next Steps
- ๐ Integrate and test Stripe sandbox webhooks for real-time payment status updates.
- ๐ Document webhook event handling and reconciliation logic.
- ๐งช Continue to add tests and monitoring for all payment and currency flows.
๐ References
- stripe-go SDK
- Stripe API Docs
- Project code:
infra/provider/stripe_payment_provider.go
,pkg/handler/
,pkg/service/account/
,infra/provider/exchange_rates.go