Architecture · 2026.09.06

Non-custodial payment and Stripe billing architecture

Scope: Solana merchant payments, network fees (target: merchant-paid; today: customer-paid), and Stripe membership billing.

What this document is. It records the target architecture and the decisions behind it, not the system as it runs today. Parts of it are not wired into the live checkout, which behaves differently:
  • Network fees. The target is a merchant-controlled fee payer. Today the fee is signed and paid by the customer’s own wallet (about 0.000005 SOL), which is what the live payment screen tells the customer. No fee-payer signer takes part in the live checkout.
  • Receiving address. The target is a nonce signature proving control. On the live checkout the merchant types the address and it is only checked for being a valid Solana address; control of it is not proven there.
  • Settlement verification. On-chain matching, payment records and signed webhooks do not run on the live checkout; the till screen states that it cannot confirm that a payment arrived.
Verified against the live system on 2026-10-13 by moving a real payment on mainnet.
0%Platform fee
of payment value
10Successful finalized live payments in the trial
USD 9Starter proposal per month
for the United States
SolanaFirst network · verified native
USDC and USDT mints

01 · Locked decisions

The decisions this architecture is built on.

Each row is a settled choice for the first production architecture, not an open option.

TopicDecision
ProductNon-custodial, API-first crypto payment acceptance infrastructure
First networkSolana
Initial payment assetsVerified native USDC and USDT mints on an explicit allowlist
Payment settlementPayer wallet directly to the merchant's verified wallet
Platform fee0% of payment value
Membership billingStripe Checkout and Stripe Billing
Stripe's roleBill the merchant for R-X-ZENITH membership only
Network feePaid directly by a merchant-controlled Solana fee payer
R-X-ZENITH gas sponsorshipProhibited in the selected architecture
R-X-ZENITH custodyNo payment assets, SOL balances, private keys, or seed phrases
Fiat conversionNone
TrialUnlimited test environment plus the first 10 successful finalized live payments
Starter proposalUSD 9/month for the United States; localization and taxes determined per market

02 · Two money rails

Two money rails that must never be mixed.

The on-chain customer payment and the SaaS membership subscription are separate systems that never cross.

Rail separation
ON-CHAIN CUSTOMER PAYMENT

Customer wallet ── exact USDC / USDT ──▶ Merchant receiving wallet
       │                                         ▲
       └── customer transfer signature           │ direct settlement

Merchant fee-payer signer ── actual SOL fee ──▶ Solana network
       └── merchant-controlled key and SOL balance

R-X-ZENITH: creates the Payment Intent and transaction template,
validates policy, observes the chain, and reports status. It does not
receive the token, pay the network fee, or possess either signing key.


SAAS MEMBERSHIP BILLING

Merchant payment method ── monthly membership ──▶ Stripe ──▶ R-X-ZENITH
                                      │
                                      └── signed webhook ──▶ entitlement service

Stripe is not part of the customer-to-merchant crypto payment path.

These rails use different identifiers, ledgers, reconciliation, refunds, and incident procedures. A Stripe subscription event must never be treated as proof of an on-chain customer payment, and an on-chain payment must never change the Stripe subscription ledger.

03 · Non-custodial invariants

Eight conditions the implementation must satisfy.

The following are implementation requirements, not optional marketing language:

  1. Payment tokens move only from the payer's token account to the merchant's verified token account.
  2. R-X-ZENITH cannot independently construct and complete a valid transfer of a payer's or merchant's assets.
  3. R-X-ZENITH never receives, stores, transmits, backs up, recovers, or can derive a payer or merchant private key or seed phrase.
  4. The merchant fee-payer key is generated and retained in a merchant-controlled environment.
  5. The merchant funds the fee-payer wallet with SOL directly. R-X-ZENITH does not accept a merchant SOL deposit and does not refill the wallet.
  6. R-X-ZENITH does not operate an omnibus wallet, internal balance, withdrawal queue, swap, exchange, or fiat conversion.
  7. Browser callbacks and submitted signatures are untrusted. The server verifies the finalized on-chain transaction independently.
  8. Every public claim says “non-custodial design” or describes the actual flow. It must not say “there are no legal issues.”

04 · Merchant-controlled fee payer

The merchant controls the fee-payer key.

On Solana the fee payer signs the transaction, so the merchant needs a separate signer that R-X-ZENITH cannot operate.

4.1

Why a separate signer is required

On Solana the fee payer signs the transaction. If the merchant must pay while the customer authorizes the token transfer, both parties have a role in the same transaction:

  • the customer signs as the transfer authority;
  • the merchant-controlled signer signs as the fee payer;
  • R-X-ZENITH signs nothing and holds no signing key.
The often-quoted base fee of 5,000 lamports is per signature, not a universal total. The final cost can also include a priority fee, additional signatures, account creation or rent effects, and fees for failed transactions. Product copy should therefore say “actual Solana network fee,” not promise an exact 5,000-lamport total.

4.2

Supported deployment model

For the first production architecture, provide a small merchant fee-payer connector that runs in an environment controlled by the merchant:

ComponentOwnerHolds
Merchant receiving walletMerchantReceived USDC/USDT and its private key
Merchant fee-payer walletMerchantSmall SOL operating balance and its private key
Fee-payer connector processMerchantAccess to the fee-payer key only
Payment Intent serviceR-X-ZENITHExpected payment metadata; no keys or assets
Chain observerR-X-ZENITHPublic transaction and finality data

The receiving wallet and fee-payer wallet should be separate so the signer cannot move merchant payment assets. The fee-payer wallet should hold only the limited SOL required for operations.

4.3

Signer allowlist

The merchant connector must decode and validate the complete transaction before signing. It rejects the transaction unless all conditions are true:

  • a live, unused R-X-ZENITH Payment Intent exists;
  • cluster, recent blockhash, expiration, and fee payer are correct;
  • the only transfer is the expected approved USDC or USDT mint;
  • recipient token account belongs to the verified merchant wallet;
  • amount in base units exactly matches the Payment Intent;
  • token and system program IDs are allowlisted;
  • no unknown program, additional transfer, authority change, delegate, close-account, swap, or memo payload outside policy is present;
  • compute-unit price and total expected fee are below the merchant's configured ceiling;
  • the intent/reference has not already been signed or paid.

Rate limits apply by merchant, intent, IP/device, time window, and estimated fee. The connector records a tamper-evident audit event without recording key material.

4.4

Failure behavior

If the merchant connector is offline, out of SOL, or rejects the transaction, merchant-paid checkout cannot proceed. The UI must show a merchant-side availability error and must not silently switch R-X-ZENITH into the fee-payer role.

Before activating live payments, onboarding must include:

  • fee-payer connection test;
  • SOL balance and low-balance alert test;
  • transaction-policy test;
  • key backup instructions controlled by the merchant;
  • emergency revoke/rotate procedure;
  • an explicit statement that network fees, including fees for failed submitted transactions, are the merchant's responsibility.

05 · On-chain payment sequence

From Payment Intent to a finalized, reconciled order.

Ten steps, with the signing roles and the verification responsibility named at each one.

StepActorRequired action
1Merchant backend or hosted pageCreates a Payment Intent with an idempotency key, merchant order ID, exact amount, approved mint, recipient, and expiry
2R-X-ZENITHChecks entitlement and merchant configuration; returns the hosted URL/reference
3CustomerOpens by link, QR, NFC, deep link, or merchant integration
4R-X-ZENITHBuilds a short-lived transaction message bound to the Payment Intent
5Merchant connectorValidates the complete message and partially signs as fee payer
6Customer walletDisplays the transaction and signs as token transfer authority
7Customer or RPC relaySubmits the fully signed transaction to Solana
8R-X-ZENITH observerVerifies cluster, signature set, recipient, mint, amount, reference, and transaction outcome
9R-X-ZENITHShows confirmed as provisional and emits the canonical success event only at finalized
10MerchantReceives a signed, replay-resistant payment.finalized webhook and reconciles the order

Recommended state model:

Payment states
created → signing → submitted → confirmed → finalized
    └──────────────→ expired
             └─────→ failed
finalized → refund_pending → refunded

Only finalized payments count toward the 10-payment live trial. A refund is a separate merchant-authorized on-chain transfer linked to the original payment; it is not a reversal of the original chain transaction.

06 · Stripe membership billing

Stripe bills access to R-X-ZENITH.

Stripe bills access to R-X-ZENITH. It does not process, settle, or refund the store's customer purchases.

6.1

Checkout creation

  1. Create Stripe Products and recurring Prices in the Stripe account for each published market/currency.
  2. The pricing page posts the selected plan to an R-X-ZENITH server endpoint.
  3. The server validates the merchant account and maps the internal plan to an allowlisted Stripe Price ID. Never accept a client-supplied arbitrary Price ID.
  4. The server creates a Checkout Session in subscription mode and places only opaque internal merchant/account IDs in metadata.
  5. Secrets remain server-side and outside source control. Public HTML receives no Stripe secret key.
  6. The browser redirects to Stripe Checkout.
The current static pricing mockups intentionally show a disabled connection point because a live Stripe Product, Price, server endpoint, and domain are not present in this repository.

6.2

Webhook is the source of truth

Do not grant paid membership from the success-page redirect. The billing service consumes the raw request body, verifies the Stripe signature, stores the Stripe event ID for idempotency, and updates access from Stripe's current subscription state.

Stripe eventR-X-ZENITH action
checkout.session.completedLink the Stripe Customer and Subscription IDs to the merchant; do not trust browser state
invoice.paidMark the paid billing period active after validating customer, subscription, price, amount, and currency
invoice.payment_failedNotify the merchant and enter the documented grace/dunning state
customer.subscription.updatedRe-evaluate plan, billing period, cancellation, and status
customer.subscription.deletedEnd paid entitlement according to the documented end-of-period/grace rule

Stripe does not guarantee event delivery order. Handlers must be idempotent, tolerate duplicates, compare object state/timestamps, and retrieve the current Stripe object when necessary. Failed deliveries must be retried and visible in an internal operations log.

Use the Stripe Customer Portal for payment-method updates, invoices, and cancellation unless a reviewed custom flow is needed.

6.3

Entitlement model

Store these separately:

  • internal merchant/account ID;
  • plan code and internal entitlement status;
  • live finalized-payment trial count;
  • Stripe Customer ID;
  • Stripe Subscription ID;
  • Stripe Price ID;
  • subscription status, current period end, and cancel-at-period-end state;
  • last applied Stripe event ID and event creation time.

Never store card details. Stripe hosts their collection.

Recommended access states:

Access states
trial → active → past_due → grace → restricted
          └──────────────→ canceled_at_period_end → restricted

The exact grace period is still an operating-policy decision. The product should warn the merchant before restricting new Payment Intents and should never count failed customer attempts against the trial.

6.4

Stripe cost basis

Stripe is not free to R-X-ZENITH. Checkout is available without an additional Checkout fee on Stripe's standard Payments pricing, but the underlying payment-processing fee still applies, and Stripe Billing has its own fee.

As checked on 2026-09-06, Stripe's public standard pages show:

Stripe account / productPublic standard price used for planning
United States domestic online cards2.9% + USD 0.30 per successful charge
Japan online cards3.6% per successful charge
Stripe Billing pay-as-you-go0.7% of Billing volume

These rates can change and may differ for international cards, currency conversion, taxes, payment methods, account contracts, and country. They are internal unit-economics inputs, not fees added to the merchant's on-chain customer payment. Finance should read applicable Stripe prices from dated configuration or reports rather than hard-code them into entitlement logic.

07 · Pricing contract shown in the design

The working launch behavior behind each plan.

Plan names, prices, and the statements every plan carries.

PlanWorking launch behavior
Developer / TrialUSD 0; unlimited test environment; first 10 successful finalized live payments
StarterUSD 9/month for the US proposal; one store; Solana USDC/USDT; hosted checkout, links, QR, NFC, API, signed webhooks, CSV
PlatformContact; multiple stores and embedded/API use cases

All plans state:

  • 0% platform fee on payment value;
  • actual Solana network fee paid by the merchant-controlled fee payer;
  • local taxes may apply to the membership;
  • no automatic fiat conversion;
  • asset and network availability can change.

08 · Security and operations checklist

Unchecked security and operations requirements.

Every line below is an open item in the source document, not a completed control.

Merchant proves control of each receiving wallet by signing a server nonce.
Receiving-wallet changes require re-authentication, a new signature, an audit log, and notification.
Merchant fee-payer key never reaches R-X-ZENITH systems, logs, analytics, support tools, or Stripe metadata.
Transaction serialization is deterministic and the signer validates the decoded message, not only API fields.
Mints are pinned by network and address; token names and logos are never trusted identifiers.
Payment webhooks use timestamps, signatures, replay windows, retry IDs, and delivery logs.
Stripe webhook signatures are verified from the raw body; event IDs are idempotent.
Test and live Stripe keys, API keys, webhooks, RPC endpoints, and databases are isolated.
Secrets are not committed to Git; .env remains local and ignored.
Chain reorganization, RPC disagreement, expiry, partial failure, signer outage, low SOL, and Stripe outage are exercised before production.
Sanctions, abuse, privacy, tax-record, support, and incident policies are reviewed for each launch market.