PRD: E-invoice provider integration
| Module | Tax & Invoice | PRD ID | PRD-INV-002 |
| Status | Ready to dev | FEAT | INV |
| Epic | — | Plane | BANA-1521 |
| Date | 2026-04-13 | Version | v1.0 |
| Packages | @nx/invoice | URD | INV |
| Surface | Client · Owner/Mgr | ||
| Owner | Phát Nguyễn | ||
TL;DR
Lets a merchant connect a legal Vietnamese e-invoice provider (VNPAY) once, with credentials stored encrypted, then issue numbered e-invoices automatically the moment a payment succeeds. Invoice issuance runs through the e-invoice provider, while seller tax-info lookup is resolved through a separate tax-authority transmission (T-VAN) connection, so every completed sale can become a compliant invoice - captured with its tax-authority code and tracked end-to-end - without manual paperwork.
1. Context & Problem
Merchants selling in Vietnam must issue legal electronic invoices and submit them to the tax authority. Before this increment BANA resolved seller tax info through a direct T-VAN lookup and had no first-class invoicing capability, so there was no way to connect an e-invoice provider per merchant, store its credentials safely, or turn a completed payment into an issued invoice with an auditable status.
This increment stands up a dedicated invoicing capability and the e-invoice provider gateway, connecting a provider per merchant. Seller tax-info lookup continues to run through the dedicated T-VAN connection - consolidating it behind the issuance provider seam was scoped but is not delivered in this increment. This is the foundation for legal e-invoicing - a hard regulatory requirement for the household-business / SME segment BANA targets.
2. Goals & Non-Goals
Goals
- Stand up the invoicing capability and the e-invoice provider gateway; connect a provider per merchant.
- Store provider credentials encrypted and require an explicit client name (no implicit default client).
- Configure issuance per invoice type (serial / category / issuance policy) and route sale channels to a provider configuration, with a guided onboarding flow.
- Drive the issuance lifecycle from a successful payment through an event-driven issuance queue, capturing the invoice number and tax-authority (CQT) code.
- Process inbound provider webhooks (with a per-configuration webhook toggle) to update invoice status.
- Keep seller tax-info lookup on the dedicated T-VAN connection, separate from the e-invoice issuance provider (single-seam consolidation deferred).
Non-Goals
- Multiple invoice providers beyond the current provider set.
- PDF rendering of the invoice (produced provider-side).
- Tax-rate calculation at sale time (owned by the pricing engine).
- Tax declaration / filing automation.
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Issuance coverage | Successful payments that produce an issued invoice in the configured mode |
| Issuance reliability | Issuance success rate after the retry policy; failures land in the audit trail, never silently dropped |
| Credential safety | 100% of provider credentials stored encrypted; zero plaintext at rest |
| Tax-authority capture | Issued invoices that capture an invoice number + CQT code |
| Webhook freshness | Provider webhooks reconcile invoice status without manual intervention |
4. Personas & Use Cases
| Persona | Goal in this feature |
|---|---|
| Owner | Connect a provider, configure issuance per invoice type, route channels, complete onboarding |
| Manager | Monitor issuance status and the audit trail; retry / adjust where allowed |
| Cashier | Trigger manual export for an order's invoice at the counter |
| System (payment) | Emit payment success that queues issuance automatically |
Core scenarios: an owner connects a provider with encrypted credentials and an explicit client name → configures serial / category / policy per invoice type and routes each sale channel → a payment succeeds → the invoice is queued, issued, and its number + CQT code captured → inbound webhooks reconcile status; tax-info lookup runs through the separate T-VAN connection.
5. User Stories
- As an owner, I want to connect an e-invoice provider per merchant with encrypted credentials and an explicit client name, so issuance is secure and unambiguous.
- As an owner, I want a guided onboarding flow to configure serial / category / policy per invoice type and route sale channels, so setup is correct without deep tax knowledge.
- As an owner, I want a completed payment to automatically queue and issue the invoice, so compliant invoices are produced without manual work.
- As a manager, I want issuance failures to retry per policy and be visible in an audit trail, so nothing is silently lost.
- As a cashier, I want to manually export an order's invoice at the counter, so I can issue on demand when needed.
- As an owner, I want one provider connection to drive issuance while seller tax-info lookup runs on its own T-VAN connection, so each integration is configured clearly.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Create a merchant invoice profile linked to the seller tax identity | URD-CFG-001 |
| FR-2 | Connect a provider (VNPAY) per merchant, with credentials stored encrypted and an explicit client name required | URD-CFG-002 |
| FR-3 | Configure per invoice type the serial, category, tax method, and issuance policy | URD-CFG-003 |
| FR-4 | Route each sale channel to the provider configuration that should issue its invoices | URD-CFG-004 |
| FR-5 | Configure a retry policy (max retries + delay schedule) for failed issuance | URD-CFG-005 |
| FR-6 | Share an invoice profile across merchants; guided onboarding wizard for provider setup | URD-CFG-006..007 |
| FR-7 | Queue an invoice for issuance automatically on a successful payment, via the event-driven issuance queue | URD-INV-001 |
| FR-8 | Issue the invoice via the provider and capture its number + tax-authority (CQT) code; track status (pending → processing → success / failed / cancelled) | URD-INV-002..003 |
| FR-9 | Retry a failed issuance per the configured policy; submit the issued invoice to the tax authority (CQT) when enabled | URD-INV-004..005 |
| FR-10 | Record an immutable audit-trail entry for every invoice event | URD-INV-006 |
| FR-11 | Adjust, replace, or cancel an issued invoice with a reason | URD-INV-007..008 |
| FR-12 | Process inbound provider webhooks (per-configuration webhook toggle) to update invoice status | URD-INV-009 |
Full requirement text and acceptance criteria live in the Tax & Invoice URD. This PRD references them rather than restating them.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Credential security | Provider credentials are stored encrypted at rest; no plaintext secrets |
| Data integrity | The invoice audit trail is append-only; status changes are recorded, never overwritten |
| Tenancy & authz | Provider connection and configurations are confined to the user's own merchant; credential changes are owner-gated |
| Resilience | Issuance is driven through an event-driven issuance queue with a configurable retry policy; failures are captured, not dropped |
| Idempotency | Webhook and queue processing tolerate redelivery without double-issuing |
| i18n | User-facing labels / statuses are bilingual (English / Vietnamese) |
8. UX & Flows
Key screens (management app): provider-connection management, the per-invoice-type serial / category / policy editor, channel routing, and the guided invoice onboarding flow.
9. Data & Domain
| Entity | Role |
|---|---|
| Merchant invoice profile | Merchant's invoicing setup, linked to the seller tax identity |
| Invoice provider connection | The connected provider per merchant - vaults encrypted credentials and the client name |
| Provider issuance configuration | Per invoice-type serial / category / policy and retry settings |
| Channel routing | Routes a sale channel to the provider configuration that issues its invoices |
| Invoice | The issued e-invoice - number, CQT code, status |
| Invoice audit trail | Immutable event trail for every invoice state change |
Conceptual only - full schema and invariants in the invoice domain model.
10. Dependencies & Assumptions
Depends on
- Seller tax identity (URD-TAX) - the invoice profile links to the merchant's tax code (MST), name, and address.
- Payment - a successful payment is what queues issuance.
- E-invoice provider gateway - issues the legal invoice and delivers webhooks.
- Tax-authority transmission network (T-VAN) - seller tax-info lookup and invoice-message query (query-only; it does not submit).
- Event-driven issuance queue - the transport between payment success and issuance.
Assumptions
- The merchant has registered a seller tax identity (MST).
- The merchant holds valid provider credentials and a client name for the connection.
- A sale channel is routed to an active provider configuration before issuance.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Provider rejects or times out during issuance | Retry policy (max retries + delay) per configuration; failures recorded in the audit trail |
| Duplicate issuance on queue / webhook redelivery | Idempotent queue and webhook processing; status tracked per invoice |
| Credential leakage | Credentials stored encrypted; changes owner-gated |
| Single provider set | Accepted for this increment; VNPAY is the only connected provider, multi-provider (including VNIS) is a Non-Goal, deferred to P2 |
| Tax-info seam consolidation | Deferred - seller tax-info still resolves through the dedicated T-VAN connection; consolidating it behind the issuance provider is a later increment |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P1 (foundation) - see URD feature catalog for CFG and INV |
| Rollout | All merchants; enabled per merchant on provider connection |
| Migration | None - seller tax-info lookup is unchanged, still resolved through the T-VAN connection (no consolidation in this increment) |
| Launch criteria | Connect provider (encrypted creds + client name) → configure per-type serial / policy → payment success queues + issues an invoice with number + CQT code → webhook reconciles status; tax-info lookup verified on the T-VAN connection |
| Monitoring | Issuance success/failure rate, retry depth, webhook reconciliation lag, queue backlog |
13. FAQ
Does issuing an invoice require manual action? No - by default a successful payment automatically queues and issues the invoice. Manual export at the counter and scheduled batch issuance are additional modes (URD-MOD).
Where are provider credentials stored? Encrypted at rest, confined to the user's own merchant, with an explicit client name - there is no implicit default client.
What happens if the provider rejects an issuance? It is retried per the configured policy (max retries + delay). If it still fails, the status is failed and the failure is recorded in the audit trail.
Is seller tax-info lookup consolidated onto the issuance provider? Not in this increment. Invoice issuance runs through the e-invoice provider, while seller tax-info lookup still resolves through the separate T-VAN connection. Consolidating both behind one seam is planned for a later increment.
Can I use a provider other than VNPAY? Not in this increment - VNPAY is the only connected provider; additional providers (including VNIS) are a Non-Goal, planned for P2.
References
- URD: Tax & Invoice - Invoice Lifecycle (INV) · Invoice Configuration (CFG)
- Builds on: Tax Identity (TAX) · Issuance Modes (MOD)
- Module: Tax & Invoice - URD
- Developer: @nx/invoice · domain model · iiapi · t-van