Direct Charge Operations
Source: internal/api/v1/store/Controllers/charge.js
Overview
The Charge controller handles direct Stripe charge operations, primarily for OneBalance wallet reloads. It supports manual balance reloads with currency conversion and payment source resolution.
Key Capabilities
- Create one-time charges for wallet reloads
- Automatic payment source resolution (default or provided)
- Currency conversion for OneBalance credits
- Manual charge operations (not subscription-based)
MongoDB Collections
| Collection | Operations | Purpose |
|---|---|---|
onebalance | Update | Balance increments |
onebalance.usage_logs | Create | Transaction logging |
stripe.keys | Read | Parent account Stripe key resolution |
Service Methods
charge
Creates a Stripe charge and optionally updates OneBalance.
Endpoint: POST /store/charge
Request Body:
{
amount: number, // Dollar amount (will be converted to cents)
currency: string, // Currency code (e.g., 'USD')
payment_source: string // Optional: Stripe source/card ID
}
Query Parameters:
{
onebalance: boolean; // Default true, set to false to skip balance update
}
Response:
{
success: true,
message: "Balance updated"
}
Business Logic:
-
Resolve Stripe Instance:
- Main account: Use platform Stripe key
- Sub-account: Lookup parent account's Stripe key from
stripe.keys
-
Convert Amount:
amount * 100(dollars to cents) -
Resolve Payment Source:
- If not provided, fetch customer's
default_source - Error if no default source and none provided
- If not provided, fetch customer's
-
Create Charge:
stripe.charges.create() -
Update OneBalance (if
onebalance !== false):- Convert charge amount to BASE_CURRENCY using CurrencyUtil
- Increment balance:
$inc: { balance: converted_amount } - Log transaction with status 'success'
Currency Conversion:
const currUtil = new CurrencyUtil();
const currData = await currUtil.convert(
account.id,
total_amount, // In cents
currency?.toUpperCase() || BASE_CURRENCY,
BASE_CURRENCY,
);
await Onebalance.updateOne({ account_id: account.id }, { $inc: { balance: currData.amount } });
Edge Cases & Business Rules
1. Parent Account Stripe Key Resolution
Sub-accounts must use parent's Stripe keys:
if (!account.main) {
const stripe_keys = await StripeKey.findOne({
account_id: req.auth.account.parent_account,
});
stripe = Stripe(stripe_keys?.token?.access_token);
}
2. Default Payment Source
If no payment_source provided, uses customer's default:
if (!payment_source) {
const customer = await stripe.customers.retrieve(stripe_customer);
payment_source = customer.default_source;
if (!payment_source) {
throw badRequest('Payment source is not provided.');
}
}
3. OneBalance Optional Update
Can skip balance update by setting onebalance=false:
if (onebalance !== false) {
// Update balance
}
Use Case: Charging without crediting OneBalance (e.g., direct purchases)
Related Documentation
- Payment Intent - OneBalance reloads via PaymentIntent
- Payment Methods - Payment source management
- Customer - Customer information retrieval