@devly-cl/billing-fintoc
v0.1.0
Published
Fintoc billing adapter with injected transport and host policy.
Readme
@devly-cl/billing-fintoc
Fintoc billing adapter for Node 24+. Depends only on @devly-cl/billing-core; CommonJS, ESM consumers and NodeNext declarations share the same provider and core error constructors. Published releases are installed from npm; local npm pack only creates a candidate tarball.
Install
npm install @devly-cl/billing-core @devly-cl/billing-fintocPublic API
The runtime entry exports FintocBillingProvider. Type exports are FintocBillingProviderOptions, FintocRequestContext and FintocTransport. Import operation inputs, results, capabilities and SubscriptionGatewayError from @devly-cl/billing-core. The HTTP client, subscription mapper and parsers are internal; deep imports are blocked.
Construct the provider with a fixed environment (test or live) and getters getSecretKey(), getWebhookSecret() and getReturnUrl(kind) (success or cancel). Construction does not validate credentials or contact Fintoc. Getters run when the operation requires them; credential rotation never changes the instance's environment. Binding and capability values are frozen.
Optional transport(url, init) replaces native fetch and now() supplies milliseconds since epoch for webhook expiry. The declaration includes fetch platform types explicitly and does not require Nest, TypeORM or implicit Node type dependencies in consumers.
The host implements beforeRequest({ method, path, collection }) for sales policy. New mutations have collection: true; GET and subscription cancellation have collection: false. Throw a safe core error to block an operation before dispatch. Environment-specific approval checks can live in the secret getter. Selection, legacy fallback, secret storage and authorization remain host responsibilities.
assertReady() and assertReady('subscriptionCheckout') preserve credential-only readiness. assertReady('paymentMethodSetup') additionally checks collection policy and both return URLs. Checkout and setup operations always validate their actual return URLs. General availability therefore does not promise that a hosted setup can start.
Behavior
Subscription checkout, canonical subscription/invoice reads, cancellation, recurring terms, one-off draft/finalize invoices and payment-method setup/change implement the core provider port. Mutations carry Idempotency-Key; wire calls use /v2, Fintoc-Version: 2026-02-01, a 15-second timeout, JSON and redirect rejection. Each call makes one attempt. Transport/JSON failures and mutation HTTP 408/409/429/5xx remain uncertain; successful mutation responses with invalid canonical evidence are also uncertain. No response body, URL or transport cause is attached to errors.
verifyEvent(rawBody, signature) verifies the original bytes, HMAC, timestamp within 300 seconds, multiple rotation signatures and pinned mode. Webhooks are capped at 1 MiB; invoice pages at 50 entries. Verification returns a canonical event hint, not payment confirmation. Durable inboxes, retries, tenant ownership, database transactions, RBAC and audit stay in the host; the package does not persist state or retry automatically.
Integration example
The host supplies credentials and policy; the declarations below are integration requirements, not working credentials. Constructing the adapter and checking readiness make no provider request.
import { SubscriptionGatewayError } from '@devly-cl/billing-core';
import { FintocBillingProvider } from '@devly-cl/billing-fintoc';
declare const host: {
testSecretKey(): string;
testWebhookSecret(): string;
returnUrl(kind: 'success' | 'cancel'): string;
collectionEnabled(): boolean;
};
const provider = new FintocBillingProvider({
environment: 'test',
getSecretKey: () => host.testSecretKey(),
getWebhookSecret: () => host.testWebhookSecret(),
getReturnUrl: (kind) => host.returnUrl(kind),
beforeRequest: ({ collection }) => {
if (collection && !host.collectionEnabled()) {
throw new SubscriptionGatewayError('BILLING_PROVIDER_DISABLED');
}
},
});
provider.assertReady('paymentMethodSetup');Use a separate instance and credential getters for live. Implement environment approval in those getters when required by the host. Keep maintenance reads/cancellation and new collection policy distinct; retain stricter existing live gates when migrating an application. For webhooks, pass the original bytes to verifyEvent and durably enqueue the verified event before acknowledging HTTP; later reconciliation must establish canonical invoice evidence.
Validation
Build from this repository root with npm run build:packages. Run npm run test:packages, npm run test:package-boundaries and npm run test:package-artifacts. The artifact consumer installs only Fintoc and core tarballs offline, verifies a synthetic operation/signature and CJS/ESM/NodeNext compatibility. These checks do not demonstrate a real PSP transaction or production credential readiness.
During development, run npm run build:packages after changing package sources, then restart Nest. start:dev builds packages once at startup; automatic package hot reload has not been validated.
