Issuing & Verifying Receipts (JWT / On-chain)
Receipts are the proof-of-license in FX402. They show who paid, what tier was chosen, and how long access is valid.
FX402 supports two main types of receipts:
- JWT Receipts — signed, portable tokens
- On-chain Receipts (optional) — anchored for added permanence
🧩 1. JWT Receipts
JWT receipts are cryptographically signed tokens (using ES256, Ed25519, etc.) issued after payment.
Example JWT Payload:
{
"sub": "user:wallet:SoLWallet111...",
"resource": "nft:solana:mint:9abc...xyz",
"tier_id": "7d",
"valid_from": "2025-10-29T00:00:00Z",
"valid_until": "2025-11-05T00:00:00Z",
"paid": {
"amount": "2.00",
"currency": "USDC",
"tx": "4sJQd2cA...FyW"
},
"issuer": "https://facilitator.fx402.xyz"
}Verification Example:
import { verifyReceipt } from "@fx402/r402";
const valid = await verifyReceipt(jwt);
if (valid) console.log("✅ verified!");Facilitators should expose a
/.well-known/jwks.jsonendpoint for their public keys to allow secure client-side verification.
🧠 2. On-chain Anchors (Optional)
Receipts may also be anchored on-chain (such as via Solana Memo or IPFS).
Example fields:
| Field | Description |
|---|---|
receipt_cid | IPFS CID (content hash) of the signed receipt |
tx | Blockchain transaction anchoring the hash |
Anchoring allows trust-minimized verification—even if the facilitator goes offline.
🔐 3. Caching Strategy
- Cache receipts locally: (IndexedDB, Redis, etc.)
- Re-use receipts: until
valid_untilexpires. - On cache miss: try facilitator re-verification or repurchase if expired.
🧰 4. Verification Endpoints
Facilitators and APIs can expose HTTP endpoints to verify receipts:
GET /verify?jwt=<token>Sample response:
{ "valid": true, "expires_in": 23422 }⚙️ 5. Security Considerations
- Always check
valid_untilagainst server time. - Never trust unsigned JSON receipts in production.
- Rotate signing keys periodically for defense in depth.
- Include
issuerandchainin JWT claims for transparency and auditability.
📚 Next Steps
Last updated on