DEV Community

Cover image for Chapter 51 — Secure AI Payments, Billing, Subscription Management & Financial Data Protection
Black Shadow Team ©
Black Shadow Team ©

Posted on

Chapter 51 — Secure AI Payments, Billing, Subscription Management & Financial Data Protection

#ai

51.1 Introduction

A production AI platform may eventually need paid subscriptions, usage-based billing, credits, invoices, refunds, promotional plans, organization billing, and payment-provider integrations.

Financial functionality introduces a different class of security requirements because billing data can affect:

  • money;
  • account privileges;
  • subscription status;
  • AI usage limits;
  • credits;
  • invoices;
  • refunds;
  • organizational budgets;
  • payment-provider integrations.

The most important architectural principle is:

The application should not become the primary custodian of sensitive payment-card information unless there is a compelling business and compliance reason to do so.

Whenever possible, sensitive payment information should be handled by a specialized payment provider using appropriate secure integration patterns.


51.2 Billing Architecture

A high-level billing architecture can be:

                    User
                      |
                  AI Platform
                      |
                Billing Service
                      |
             Payment Provider
                      |
              Payment Network
Enter fullscreen mode Exit fullscreen mode

The AI application maintains its own business records such as:

  • customer identity;
  • subscription;
  • plan;
  • entitlement;
  • usage;
  • invoice references;
  • payment-provider customer ID.

The payment provider handles payment processing.


51.3 Separation of Responsibilities

The billing system should separate several concepts:

Payment
Subscription
Plan
Entitlement
Usage
Credit
Invoice
Refund
Transaction
Enter fullscreen mode Exit fullscreen mode

They are related but should not be treated as interchangeable.

For example:

A successful payment does not automatically mean that every application permission should be granted permanently.

Instead:

Payment Event
      |
Validate
      |
Update Billing State
      |
Calculate Entitlements
      |
Update Access
      |
Audit
Enter fullscreen mode Exit fullscreen mode

51.4 Plans

An AI platform may offer plans such as:

Free
Starter
Pro
Business
Enterprise
Enter fullscreen mode Exit fullscreen mode

Each plan can define limits and features.

Example:

type Plan = {
  id: string;
  name: string;
  monthlyPrice: number;
  currency: string;
  limits: {
    imageGenerations: number;
    videoGenerations: number;
    storageBytes: number;
    apiRequests: number;
  };
};
Enter fullscreen mode Exit fullscreen mode

The exact limits should be configurable rather than hard-coded throughout the application.


51.5 Entitlements

A subscription is not necessarily the same thing as an entitlement.

An entitlement answers:

What capabilities is this account currently allowed to use?

For example:

Subscription
    |
    +-- Pro
    |
    +-- Active
    |
    +-- Current Period
          |
          v
Entitlements
    |
    +-- HD Generation
    +-- Increased Storage
    +-- Higher API Limit
Enter fullscreen mode Exit fullscreen mode

This separation makes the architecture more flexible.


51.6 Subscription State Machine

Subscription states should be explicit.

For example:

TRIAL
  |
ACTIVE
  |
PAST_DUE
  |
CANCELED
  |
EXPIRED
Enter fullscreen mode Exit fullscreen mode

Other provider-specific states may also exist.

The application should not assume that every subscription transition happens synchronously during a user's browser request.


51.7 Payment Provider Integration

A secure integration typically looks like:

Client
  |
  | Request Checkout
  v
Application
  |
  | Create Checkout Session
  v
Payment Provider
  |
  | User Completes Payment
  v
Payment Provider
  |
  | Webhook
  v
Application
  |
  | Verify Event
  v
Billing Database
Enter fullscreen mode Exit fullscreen mode

The webhook is especially important.

The browser should not be treated as the final authority for payment success.


51.8 Why Client-Side Payment Success Is Not Enough

A malicious or malfunctioning client could potentially claim:

"Payment successful"
Enter fullscreen mode Exit fullscreen mode

Therefore, application privileges should not be granted merely because the frontend reports success.

Instead:

Browser Result
      |
      v
Informational Only
      |
Provider Event
      |
Server Verification
      |
Billing State
      |
Entitlement
Enter fullscreen mode Exit fullscreen mode

The trusted source should be the validated server-side payment-provider event.


51.9 Webhook Security

Payment webhooks are sensitive because they can modify billing state.

A webhook endpoint should implement:

  • provider signature verification;
  • timestamp/replay protection where supported;
  • event validation;
  • idempotency;
  • strict schema validation;
  • logging;
  • appropriate rate limiting;
  • safe error handling.

Conceptually:

Webhook
   |
Parse
   |
Verify Signature
   |
Validate Event
   |
Check Replay / Idempotency
   |
Process
   |
Record Event
Enter fullscreen mode Exit fullscreen mode

Never process an unverified billing event as trusted input.


51.10 Idempotency

Payment systems frequently deliver events more than once.

For example:

EVENT_123
EVENT_123
EVENT_123
Enter fullscreen mode Exit fullscreen mode

The application should safely recognize duplicate events.

A simple conceptual model:

type ProcessedBillingEvent = {
  eventId: string;
  receivedAt: Date;
  processedAt?: Date;
  status: "processed" | "failed";
};
Enter fullscreen mode Exit fullscreen mode

Before processing an event:

Event ID
   |
Already Processed?
   |
 +--+--+
 |     |
Yes    No
 |     |
Stop  Process
Enter fullscreen mode Exit fullscreen mode

This prevents duplicate subscription changes, credit grants, or other unintended side effects.


51.11 Billing Database

A conceptual schema might contain:

customers
subscriptions
plans
entitlements
invoices
payments
refunds
usage_records
billing_events
credits
Enter fullscreen mode Exit fullscreen mode

These should have clear relationships.

For example:

user
 |
customer
 |
subscription
 |
plan
 |
entitlements
Enter fullscreen mode Exit fullscreen mode

And:

subscription
 |
invoices
 |
payments
 |
refunds
Enter fullscreen mode Exit fullscreen mode

51.12 Customer Mapping

The application should maintain a stable relationship between its internal identity and the payment provider's customer identity.

Example:

type BillingCustomer = {
  userId: string;
  providerCustomerId: string;
  createdAt: Date;
};
Enter fullscreen mode Exit fullscreen mode

This prevents the application from relying on user-controlled values to identify billing accounts.


51.13 Payment Records

Payment records should contain references rather than unnecessary sensitive payment details.

Example:

type PaymentRecord = {
  id: string;
  customerId: string;
  providerPaymentId: string;
  amount: number;
  currency: string;
  status: "pending" | "succeeded" | "failed" | "refunded";
  createdAt: Date;
};
Enter fullscreen mode Exit fullscreen mode

Avoid storing unnecessary card information.


51.14 Card Data Protection

A major security objective is to minimize the application's exposure to cardholder data.

Prefer architectures where:

Payment Card
     |
     v
Payment Provider
     |
     v
Provider Token / Reference
     |
     v
Application
Enter fullscreen mode Exit fullscreen mode

The application generally needs to know the payment-provider reference and business status—not the full card number.


51.15 Never Store CVV

Sensitive authentication data such as card verification codes should not be stored by the application.

The correct architecture is to let the payment provider process payment authentication and card details.


51.16 Payment Tokens

Where supported, payment providers may issue tokens or payment-method identifiers.

These identifiers should still be treated as sensitive.

They should:

  • remain server-controlled;
  • never be exposed unnecessarily;
  • be protected by authorization;
  • be audited when used;
  • be removed when no longer required.

51.17 Checkout Sessions

A secure checkout workflow may look like:

User
 |
Select Plan
 |
Server Validates Plan
 |
Create Checkout Session
 |
Provider Checkout
 |
Payment
 |
Provider Confirmation
 |
Webhook
 |
Update Subscription
Enter fullscreen mode Exit fullscreen mode

The server should determine which plan the user is actually purchasing.

It should not blindly trust a price value sent by the browser.


51.18 Server-Side Price Validation

Suppose the client sends:

{
  "plan": "pro",
  "price": 1
}
Enter fullscreen mode Exit fullscreen mode

The server should not simply accept the supplied price.

Instead:

Client Plan ID
      |
Server Lookup
      |
Trusted Plan Configuration
      |
Provider Price ID
      |
Checkout
Enter fullscreen mode Exit fullscreen mode

The client can request a product or plan, but the trusted server configuration determines the actual commercial terms.


51.19 Subscription Changes

Subscription upgrades and downgrades should be handled through controlled server-side operations.

Example:

Current Plan
     |
Change Request
     |
Authorization
     |
Validate Target Plan
     |
Provider Update
     |
Webhook Confirmation
     |
Update Entitlement
Enter fullscreen mode Exit fullscreen mode

The entitlement state should reflect the validated billing state.


51.20 Cancellation

Cancellation should be explicit.

Possible business rules include:

  • cancel immediately;
  • cancel at period end;
  • pause subscription;
  • downgrade after current period.

The application should store the actual cancellation state and effective date.

Example:

type Subscription = {
  status: string;
  currentPeriodEnd: Date;
  cancelAtPeriodEnd: boolean;
};
Enter fullscreen mode Exit fullscreen mode

51.21 Failed Payments

A failed payment should not necessarily immediately destroy the user's account.

A more robust lifecycle may be:

Payment Failure
      |
Retry / Provider Recovery
      |
Still Failed?
      |
Past Due
      |
Grace Period
      |
Entitlement Reduction
Enter fullscreen mode Exit fullscreen mode

Business rules should be explicit.


51.22 Credits and AI Usage

AI applications often use credits or usage quotas.

For example:

1 Image Generation = 1 Credit
1 HD Generation = 3 Credits
1 Video Generation = 10 Credits
Enter fullscreen mode Exit fullscreen mode

The billing system should prevent race conditions when credits are consumed.

A conceptual transaction is:

Begin Transaction
      |
Check Available Credits
      |
Reserve / Deduct
      |
Create Usage Record
      |
Commit
Enter fullscreen mode Exit fullscreen mode

51.23 Credit Ledger

Instead of storing only a mutable balance, a ledger can provide better auditability.

Example:

+100 purchase
 -10 video
  -1 image
 +50 promotion
Enter fullscreen mode Exit fullscreen mode

Then:

Current Balance = Sum(Ledger Entries)
Enter fullscreen mode Exit fullscreen mode

A ledger provides a clearer history of why the balance changed.


51.24 Preventing Double-Spend of Credits

Concurrent requests can create problems.

Two generation requests might arrive simultaneously:

Balance = 5

Request A -> checks 5
Request B -> checks 5

Both consume 5
Enter fullscreen mode Exit fullscreen mode

A safe system needs transactional concurrency control.

Conceptually:

Request
   |
Atomic Reservation
   |
Sufficient Balance?
   |
 +--+--+
 |     |
No    Yes
 |     |
Reject Reserve
Enter fullscreen mode Exit fullscreen mode

51.25 Usage Metering

AI platforms may need usage metering based on:

  • tokens;
  • images;
  • video seconds;
  • audio minutes;
  • storage;
  • API requests;
  • compute time.

Usage records should contain enough information to support billing reconciliation.

Example:

type UsageRecord = {
  userId: string;
  resourceType: string;
  quantity: number;
  unit: string;
  providerRequestId?: string;
  timestamp: Date;
};
Enter fullscreen mode Exit fullscreen mode

51.26 Usage Integrity

Usage should preferably be generated from trusted server-side events.

Avoid allowing the browser to simply claim:

"I used 0 tokens."
Enter fullscreen mode Exit fullscreen mode

The AI gateway or backend service should produce authoritative usage records whenever possible.


51.27 AI Provider Cost Tracking

An AI platform may use multiple providers.

For example:

AI Gateway
 |
 +-- Provider A
 |
 +-- Provider B
 |
 +-- Local Model
 |
 +-- Provider C
Enter fullscreen mode Exit fullscreen mode

Each inference request may have:

  • provider;
  • model;
  • input usage;
  • output usage;
  • estimated cost;
  • request ID.

This enables internal cost analysis.


51.28 Cost vs Customer Billing

Internal provider cost and customer billing price are different concepts.

For example:

Provider Cost: $0.01
Customer Charge: $0.05
Enter fullscreen mode Exit fullscreen mode

The system should maintain separate accounting concepts rather than conflating them.

Provider Cost
Customer Revenue
Gross Margin
Enter fullscreen mode Exit fullscreen mode

51.29 Refunds

Refund operations should be privileged.

A refund workflow may be:

Refund Request
      |
Authorization
      |
Validate Payment
      |
Check Refund Policy
      |
Provider Refund
      |
Webhook / Confirmation
      |
Update Record
      |
Audit
Enter fullscreen mode Exit fullscreen mode

Refund endpoints should not allow arbitrary user-controlled amounts.


51.30 Administrative Billing Controls

Administrative billing operations should require stronger authorization.

Examples:

  • issuing refunds;
  • changing plans;
  • granting credits;
  • modifying billing configuration;
  • changing organization ownership.

A useful policy is:

Billing Admin
     |
Billing Operations
     |
Audit Required
Enter fullscreen mode Exit fullscreen mode

Highly sensitive operations may require step-up authentication.


51.31 Promotional Credits

Promotional credits can be abused if implemented carelessly.

Controls should include:

  • unique promotion identifiers;
  • eligibility rules;
  • expiration;
  • redemption limits;
  • organization/account restrictions;
  • audit logging.

The server—not the client—should determine eligibility.


51.32 Coupons and Discounts

Discount systems should avoid accepting arbitrary values from the browser.

Instead:

Coupon Code
    |
Server Validation
    |
Eligibility Check
    |
Trusted Discount Rule
    |
Checkout
Enter fullscreen mode Exit fullscreen mode

A client should never be allowed to specify:

{
  "discount": 99
}
Enter fullscreen mode Exit fullscreen mode

and have the server trust it.


51.33 Organization Billing

Business accounts introduce additional complexity.

Organization
 |
Billing Owner
 |
Subscription
 |
Members
 |
Usage
 |
Invoices
Enter fullscreen mode Exit fullscreen mode

The person who can use the AI platform does not necessarily need permission to manage billing.

This is another example of authentication and authorization being separate concerns.


51.34 Billing Authorization

Possible permissions include:

type BillingPermission =
  | "billing:read"
  | "billing:manage"
  | "billing:refund"
  | "billing:credits"
  | "billing:invoices";
Enter fullscreen mode Exit fullscreen mode

These permissions can be assigned to appropriate organizational roles.


51.35 Invoice Security

Invoices can contain sensitive business information.

Access should be controlled by authorization.

Users should not be able to change:

/invoices/123
Enter fullscreen mode Exit fullscreen mode

to:

/invoices/124
Enter fullscreen mode Exit fullscreen mode

and retrieve another customer's invoice.

Every invoice access should verify ownership or organizational authorization.


51.36 Object-Level Authorization

Billing resources require object-level authorization.

For example:

await requirePermission(
  principal,
  "billing:read",
  invoice
);
Enter fullscreen mode Exit fullscreen mode

The application should verify both:

  1. the user has the permission;
  2. the specific invoice belongs to an accessible account.

51.37 Financial Data Encryption

Sensitive financial records should receive appropriate protection.

Possible layers include:

TLS
  |
Application Security
  |
Database Access Control
  |
Encryption at Rest
  |
Key Management
Enter fullscreen mode Exit fullscreen mode

Additional application-level encryption may be appropriate for especially sensitive fields.


51.38 Encryption Key Management

Encryption keys should not be hard-coded.

A secure architecture uses controlled key-management infrastructure.

Application
    |
Key Management Service
    |
Encryption Key
    |
Protected Data
Enter fullscreen mode Exit fullscreen mode

Key access should be restricted by service identity and least privilege.


51.39 Billing Audit Trail

Financial changes should be auditable.

Examples:

SUBSCRIPTION_CREATED
SUBSCRIPTION_CHANGED
SUBSCRIPTION_CANCELED
PAYMENT_SUCCEEDED
PAYMENT_FAILED
REFUND_CREATED
CREDIT_GRANTED
CREDIT_CONSUMED
INVOICE_CREATED
BILLING_ROLE_CHANGED
Enter fullscreen mode Exit fullscreen mode

Audit events should contain enough information to reconstruct the business action without storing unnecessary sensitive data.


51.40 Reconciliation

A robust billing system should periodically compare:

Application Billing Database
             |
             vs
Payment Provider
Enter fullscreen mode Exit fullscreen mode

Differences can occur because of:

  • delayed webhooks;
  • failed processing;
  • network errors;
  • duplicate events;
  • operational mistakes.

Reconciliation helps detect inconsistencies.


51.41 Billing State as an Event-Driven System

A mature architecture may use events:

Payment Provider
       |
     Event
       |
Billing Event Processor
       |
 +-----+-----+
 |     |     |
DB   Ledger  Audit
       |
Entitlements
Enter fullscreen mode Exit fullscreen mode

This provides a clean separation between payment events and application permissions.


51.42 Event Ordering

Events may not always arrive in the expected order.

For example:

Subscription Updated
Payment Succeeded
Subscription Created
Enter fullscreen mode Exit fullscreen mode

Therefore, event handlers should not blindly assume chronological arrival.

The system should use provider event metadata, current provider state where appropriate, and idempotent processing.


51.43 Billing Failure Recovery

If webhook processing fails:

Webhook
   |
Processing Failure
   |
Retry
   |
Retry
   |
Dead-Letter / Investigation
Enter fullscreen mode Exit fullscreen mode

Failed billing events should not simply disappear.

Operational teams should have visibility into unresolved billing events.


51.44 Rate Limiting

Billing endpoints require rate limiting.

Especially sensitive endpoints include:

  • checkout creation;
  • coupon redemption;
  • credit redemption;
  • refund requests;
  • payment-method changes.

Rate limiting reduces abuse and accidental overload.


51.45 Billing Threat Model

Important threats include:

Fake Payment Confirmation

Defense:

  • server-side provider verification;
  • signed webhooks.

Duplicate Webhook

Defense:

  • idempotency.

Price Manipulation

Defense:

  • server-side plan lookup.

Credit Manipulation

Defense:

  • transactional ledger;
  • server-side accounting.

Unauthorized Refund

Defense:

  • privileged authorization;
  • audit logging.

Invoice Data Exposure

Defense:

  • object-level authorization.

Subscription Privilege Escalation

Defense:

  • entitlement calculation from trusted billing state.

Webhook Replay

Defense:

  • signature verification;
  • replay protection;
  • event ID tracking.

51.46 Secure Billing Service Interface

A conceptual interface could be:

interface BillingService {
  createCheckout(userId: string, planId: string): Promise<CheckoutSession>;

  getSubscription(userId: string): Promise<Subscription | null>;

  changeSubscription(
    userId: string,
    planId: string
  ): Promise<Subscription>;

  cancelSubscription(
    userId: string
  ): Promise<Subscription>;

  processWebhook(
    payload: string,
    signature: string
  ): Promise<void>;

  getInvoices(userId: string): Promise<Invoice[]>;

  getUsage(userId: string): Promise<UsageSummary>;
}
Enter fullscreen mode Exit fullscreen mode

Implementation details should remain behind this boundary.


51.47 Example Webhook Processing

A conceptual server-side workflow:

async function handleBillingWebhook(
  payload: string,
  signature: string
) {
  const event = verifyProviderEvent(
    payload,
    signature
  );

  if (await eventStore.exists(event.id)) {
    return;
  }

  await billingProcessor.process(event);

  await eventStore.markProcessed(event.id);
}
Enter fullscreen mode Exit fullscreen mode

The actual signature verification mechanism must follow the payment provider's documented protocol.


51.48 Billing Security Architecture

A complete design can be represented as:

                         User
                           |
                        HTTPS
                           |
                     Web Application
                           |
                     Authentication
                           |
                     Authorization
                           |
                    Billing Service
                           |
              +------------+------------+
              |                         |
        Billing Database          Payment Provider
              |                         |
        Usage / Ledger             Payment Network
              |
        Audit / Monitoring
Enter fullscreen mode Exit fullscreen mode

The payment provider remains responsible for payment processing while the application maintains business-level billing state.


51.49 Production Billing Checklist

Before production:

  • [ ] Payment processing is delegated appropriately.
  • [ ] Sensitive card data is minimized.
  • [ ] CVV is never stored.
  • [ ] Provider webhooks are cryptographically verified.
  • [ ] Webhooks are idempotent.
  • [ ] Replay protection is implemented where appropriate.
  • [ ] Prices are determined server-side.
  • [ ] Subscription state is server-controlled.
  • [ ] Entitlements derive from trusted billing state.
  • [ ] Credits use transactional accounting.
  • [ ] Usage is recorded server-side.
  • [ ] Refunds require authorization.
  • [ ] Billing permissions are separated from general permissions.
  • [ ] Invoice access uses object-level authorization.
  • [ ] Billing records are protected.
  • [ ] Financial events are audited.
  • [ ] Reconciliation procedures exist.
  • [ ] Failed events can be retried.
  • [ ] Billing endpoints are rate-limited.
  • [ ] Secrets are stored securely.
  • [ ] Payment-provider credentials can be rotated.
  • [ ] Administrative billing actions receive stronger controls.
  • [ ] Recovery procedures are documented.
  • [ ] Billing state can be reconstructed after failure.

51.50 Final Architecture Principle

The secure billing model is:

Trusted Plan
     |
Trusted Checkout
     |
Trusted Payment Provider
     |
Verified Event
     |
Idempotent Billing Processing
     |
Transactional Ledger
     |
Entitlement Calculation
     |
Authorized AI Access
     |
Audit
Enter fullscreen mode Exit fullscreen mode

The central principle is:

Never allow a client-controlled value to become the authoritative source of financial truth.

The browser can request an action.

The payment provider can process a payment.

But the backend must validate the event, maintain consistent billing state, calculate entitlements, enforce authorization, and preserve an auditable history.

This architecture provides a strong foundation for subscriptions, AI credits, usage-based billing, organizational accounts, invoices, refunds, and future financial functionality without unnecessarily exposing the core AI platform to sensitive payment data.

Top comments (0)