README.md
This page is generated directly from the repository README.
KHQR SDK Demo
Interactive demo application showcasing the KHQR SDK for Cambodiaβs Bakong QR payment system.

π― Features
- QR Code Generator: Create static and dynamic KHQR codes with customizable payment details
- Bakong API Tester: Test real Bakong API endpoints with manual input
- QR Verification: Decode and validate KHQR strings with CRC integrity checks
- Type-Safe: Full TypeScript support throughout the application
- Modern SSR: Built with Astro, React islands, and TailwindCSS
π Quick Start
Prerequisites
- Node.js >= 20
- pnpm (recommended) or npm
Installation
# Install dependencies
pnpm install
Development
# Start development server
pnpm dev
Then open http://localhost:4321 in your browser.
Production
# Build for production
pnpm build
# Preview production build locally
pnpm preview
# Deploy to Vercel
pnpm deploy
π Project Structure
example/
βββ src/
β βββ pages/
β β βββ api/
β β β βββ qr/
β β β β βββ generate.json.ts # QR generation endpoint
β β β βββ bakong/
β β β βββ check-account.json.ts # Bakong API proxy
β β β βββ check-tx-md5.json.ts # Transaction check proxy
β β β βββ check-tx-short-hash.json.ts
β β β βββ renew-token.json.ts
β β βββ index.astro # Homepage
β β βββ generator.astro # QR Generator page
β β βββ api-tester.astro # API Tester page
β βββ components/
β β βββ QRGeneratorClient.tsx # QR Generator React island
β β βββ BakongAPITesterClient.tsx # API Tester React island
β β βββ ToasterProvider.tsx # Toast notifications
β βββ layouts/
β β βββ Layout.astro # Base layout
β βββ styles/
β β βββ global.css # Global styles
β βββ utils/
β β βββ api.ts # API client functions
β βββ types/
β βββ index.ts # TypeScript types
βββ public/ # Static assets
βββ astro.config.mjs # Astro configuration
βββ vercel.json # Vercel deployment config
βββ package.json
π API Endpoints
QR Operations
POST /api/qr/generate
Body: { bakongAccountID, merchantName, merchantCity, currency, amount?, ... }
Response: { qr: string, md5: string }
Bakong API (Proxy Endpoints)
POST /api/bakong/renew-token
Body: { email, token? }
Response: APIResponse
POST /api/bakong/check-account
Body: { bakongAccountID, token? }
Response: APIResponse
POST /api/bakong/check-tx-md5
Body: { md5, token? }
Response: APIResponse
POST /api/bakong/check-tx-short-hash
Body: { shortHashRequest: { hash, amount, currency }, token? }
Response: APIResponse
π¦ Tech Stack
Framework
- Astro 5 - SSR framework with React islands architecture
- React 18 - Interactive UI components (islands)
- TypeScript - Type safety
Styling
- TailwindCSS - Utility-first CSS
- Lucide React - Icons
Libraries
- @manethpak/khqr-sdk - KHQR generation, decoding, and validation
- QRCode - QR code image generation
- Sonner - Toast notifications
Deployment
- Vercel - Serverless deployment with edge functions
π Deployment
Deploy to Vercel
The easiest way to deploy this demo:
Or manually:
# Install Vercel CLI (if not already installed)
npm i -g vercel
# Deploy
cd example
vercel
Environment Variables
For real Bakong API integration (optional):
# Copy example env file
cp .env.example .env
# Edit .env and add your token
BAKONG_API_TOKEN=your_jwt_token_here
Architecture
This demo uses Astroβs islands architecture for optimal performance:
- Static pages: Generated at build time (homepage)
- SSR pages: Server-rendered on demand (generator, api-tester)
- React islands: Interactive components hydrated on the client
- API routes: Serverless functions that proxy to Bakong API or handle QR generation
Why Astro?
- Better performance: Ships minimal JavaScript (only islands are interactive)
- Simpler deployment: Single unified codebase with built-in SSR
- Vercel-optimized: First-class Vercel adapter support
- Developer experience: File-based routing, automatic TypeScript support
API Proxy Pattern
The API endpoints follow a simple proxy pattern:
- User provides input through React component
- Component calls
/api/*endpoint - API endpoint uses KHQR SDK server-side
- Response sent back to client
This approach:
- β Keeps SDK logic server-side (Node.js crypto module compatibility)
- β Allows users to test with their own API tokens
- β No database or state management needed
- β Perfect for demo/testing purposes
π§ͺ Development Notes
No Backend State
The demo is designed for manual testing:
- No database or persistence layer
- API endpoints are stateless proxies
- Users provide all input directly through forms
- Perfect for learning and testing the KHQR SDK
Adding Custom Endpoints
Create a new file in src/pages/api/:
// src/pages/api/custom.json.ts
import type { APIRoute } from 'astro'
export const POST: APIRoute = async ({ request }) => {
const body = await request.json()
// Your logic here
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
}
π Learn More
π€ Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
π License
ISC Β© Manethpak
Made with β€οΈ for the Cambodian fintech community