a402-sdk
v0.1.0
Published
Express middleware SDK for 402 Payment Required protocol
Maintainers
Readme
A402 SDK
Express middleware SDK for implementing the 402 Payment Required protocol with Aptos blockchain.
Installation
npm install @a402/sdkQuick Start
import express from "express";
import A402 from "@a402/sdk";
const app = express();
// Initialize the SDK
const a402 = new A402({
contractAddress: "0x...", // Your deployed smart contract
backendUrl: "http://localhost:3001", // Your backend API
secret: process.env.A402_SECRET, // JWT secret
});
// Apply CORS middleware
app.use(a402.cors());
// Protect routes with payment requirements
app.use("/api/protected/*", a402.protect({
resource: "api-access",
tier: "premium",
priceUSD: 0.01,
}));
app.listen(3000);Configuration
Required Options
contractAddress: Aptos smart contract addressbackendUrl: Backend API URL for payment session managementsecret: JWT secret for token generation
Optional Options
nodeUrl: Aptos node URL (default: testnet)tokenTTL: Token time-to-live in seconds (default: 3600)allowedOrigins: CORS allowed origins (default: ["*"])paymentBaseUrl: Base URL for payment UI (default: "http://localhost:3000/pay")
Usage Examples
Basic Protection
// Protect a single route
app.get("/api/data",
a402.protect({
resource: "data-access",
priceUSD: 0.001,
}),
(req, res) => {
res.json({ data: "Protected content" });
}
);Tiered Access
// Different pricing tiers
app.use("/api/basic/*", a402.protect({
resource: "api",
tier: "basic",
priceUSD: 0.001,
}));
app.use("/api/premium/*", a402.protect({
resource: "api",
tier: "premium",
priceUSD: 0.01,
}));
app.use("/api/enterprise/*", a402.protect({
resource: "api",
tier: "enterprise",
priceUSD: 0.1,
}));Access User Payment Info
app.get("/api/user-data",
a402.protect({
resource: "user-data",
priceUSD: 0.005,
}),
(req: any, res) => {
// Access payment information
const { userId, resource, tier, token } = req.payment;
res.json({
data: "User specific content",
userId,
tier,
});
}
);Payment Flow
- Initial Request: Client requests protected resource
- 402 Response: Server returns payment required with payment info
- Payment: User completes payment via provided URL
- Token Exchange: Client exchanges payment ID for access token
- Authenticated Request: Client includes token in Authorization header
Example Client Flow
// 1. Initial request
const response = await fetch("/api/protected");
if (response.status === 402) {
const { payment } = await response.json();
// 2. Redirect to payment
window.location.href = payment.paymentUrl;
// 3. After payment, exchange for token
const tokenResponse = await fetch("/api/protected?paymentId=xxx");
const token = tokenResponse.headers.get("X-Access-Token");
// 4. Use token for future requests
const data = await fetch("/api/protected", {
headers: {
"Authorization": `Bearer ${token}`,
},
});
}Testing
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watchAdvanced Configuration
Custom Payment URL
a402.protect({
resource: "api-access",
priceUSD: 0.01,
customPaymentUrl: "https://pay.myapp.com",
});Custom Contract Address
a402.protect({
resource: "special-feature",
priceUSD: 0.05,
contractAddress: "0x456...", // Different contract
});Error Handling
The SDK throws specific errors:
PaymentRequiredError: No valid payment or tokenInvalidTokenError: Token validation failedPaymentVerificationError: On-chain payment verification failed
app.use((err, req, res, next) => {
if (err.name === "PaymentRequiredError") {
res.status(402).json({
error: err.message,
payment: err.paymentInfo,
});
} else {
res.status(500).json({ error: "Internal server error" });
}
});Security Considerations
- Always use HTTPS in production
- Keep your JWT secret secure
- Implement rate limiting on payment endpoints
- Validate contract addresses
- Use environment variables for sensitive config
License
MIT
