Payment Intent
internal/api/v1/billing/services/payment-intent.service.js provides two capabilities: reloading OneBalance wallets via Stripe Payment Intents and mirroring the marketplace checkout experience for accounts that require Payment Intent confirmation. It reuses helper utilities from the Charge service to maintain consistent pricing, subscription creation, and queue behaviour.
Primary Controller: payment-intent.controller.js
๐๏ธ Collections & Modelsโ
shared/models/onebalance.jsโ Increments balances after successful reloads.shared/models/onebalance-usage_logs.jsโ Records credit/debit events for audit.shared/models/queues.jsโ Queues post-checkout jobs (subaccount-charge).shared/models/store-price.js/store-cart.jsโ Resolves pricing metadata and cache for previews.shared/models/account.jsโ Validates listing eligibility, resolves parent relationships.shared/models/stripe-key.jsโ Fetches connected account token for Stripe client.
๐ External Servicesโ
- Stripe Payment Intents API โ Used for both balance reloads and checkout charges.
- Currency Utility (
shared/utilities/currency) โ Converts reload amounts into base currency before crediting OneBalance. - Charge Helpers โ
phoneNumQuantity,additionalAction,createMainAccountSubscription,formatPrice.
๐ Data Flowโ
flowchart TD
UI[Billing UI] -->|POST /payment-intent| Controller
Controller --> Service
Service -->|Connected token| Stripe
Service --> Onebalance[(OneBalance)]
Service --> QueueManager
Service --> StoreCart
Stripe --> WebhookService
๐งฉ Functionsโ
payment({ onebalance, amount, currency, payment_source, account })โ
Reloads OneBalance for the parent account.
- Retrieves connected account Stripe key and customer ID.
- Resolves payment source (explicit ID or default card).
- Creates a Payment Intent for
amount * 100in the specified currency. - On success, converts the charged amount back to
BASE_CURRENCYusingCurrencyUtil. - Updates OneBalance balance and clears retry flags.
- Inserts credit log entry indicating
refillevent.
Edge Casesโ
- Throws when Stripe keys missing or customer unlinked.
- Rejects when no default payment source exists.
- Surfaces Stripe connection timeouts via
customerror helper.
checkout({ account, account_id, product_type, type, external_action, card, uid })โ
Imitates the Charge service marketplace checkout but always uses Payment Intents.
- Resolves pricing metadata (including phone number tier handling).
- For
type="preview", upserts a cart item and returnsformatPriceDTO. - For purchase:
- Confirms Payment Intent with amount
Math.ceil(cost). - Creates parent subscription via
createMainAccountSubscription. - Invokes
additionalActionto queue provisioning. - Deletes the temporary cart and enqueues
subaccount-chargelog entry.
- Confirms Payment Intent with amount
- Returns boolean success indicator (controller wraps response payload).
Guards & Validationsโ
- Blocks duplicate listing purchases and unsupported add-ons (
instasite,site). - Requires Stripe customer linkage and funding source.
- Reuses OneBalance rebill configuration to compute internal costs.
๐งช Testing Notesโ
- Reference
tests/customer.test.jsfor end-to-end checkout expectations (shared logic). - When adding new product types, ensure both Charge and Payment Intent fixtures are aligned.
โ ๏ธ Operational Considerationsโ
BASE_CURRENCYenvironment variable must be set for OneBalance balance adjustments.- Controllers should catch
PaymentIntent.status === 'requires_action'to prompt additional authentication. - Preview and purchase flows rely on consistent cart cleanup to avoid stale items.