withBilling Utility Function
withBilling is a standalone exported higher-order function that wraps any asynchronous operation into a complete "Check → Execute → Charge" flow.
Function Signature
typescript
async function withBilling<T>(
billing: BillingModule, // sdk.billing
action: () => Promise<T>, // The asynchronous operation to execute
options?: BillingConsumeOptions, // consume parameters (optional)
): Promise<WithBillingResult<T>> // { result: T, billing: BillingConsumeResult }Execution Flow
1. billing.check() — Rejects with SdkError(40301) if credits are insufficient.
2. action() — Executes the actual operation (e.g., download / openInStudio).
3. billing.consume() — Deducts charges after the operation succeeds.
- Skips deduction during the free period and returns the cached result directly.
- If `billing.consume()` returns `isBlacklisted=true`, it means the user hit the backend blacklist rule (`20102`).Usage Examples
ESM Method
typescript
import { GeneratorSDK, withBilling } from '@atomm-developer/generator-sdk'
const sdk = GeneratorSDK.init({ appKey: 'app_xxx' })
// Download with billing
try {
const { result, billing } = await withBilling(
sdk.billing,
() => sdk.export.download({ fileName: 'my-design.png' }),
)
console.log('Download successful:', result.fileName)
console.log('Remaining free quota:', billing.freeRemaining)
} catch (err) {
if (err.code === 40301) alert('Insufficient credits, please recharge')
}
// Open in Studio with billing
await withBilling(
sdk.billing,
() => sdk.export.openInStudio(),
)
// Custom operation with billing
await withBilling(
sdk.billing,
() => myCustomAiGenerate(),
{ externalId: 'ai_gen_123' },
)CDN Method
javascript
const withBilling = GeneratorSDK.withBilling
document.getElementById('downloadBtn').onclick = async () => {
try {
await withBilling(sdk.billing, () =>
sdk.export.download({ fileName: 'my-design.png' }),
)
} catch (err) {
if (err.code === 40301) alert('Insufficient credits, please recharge')
}
}