ZAP Ecosystem & Database Server Architecture
Complete end-to-end topology mapping 4 client applications, API Gateway, 4 Spring microservices, explicit Database Server Cluster connections, and external payment gateways.
https://prod-api.zap.vn
- GCP Project:
zap-ecosystem-production - Cloud SQL DB:
zap-postgres-db-prod(PostgreSQL 15) - SSL Certificate:
zap-prod-api-cert(Managed SSL) - Target Clients: Merchant POS WPF, Kiosk & Branded Ordering Apps (Pendogo, Pho24)
https://uat-api.zap.vn
- GCP Project:
zap-ecosystem-sandbox-504003 - Cloud SQL DB:
zap-postgres-db-final(Sandbox DB) - SSL Certificate:
zap-uat-api-cert-v2(Managed SSL) - Target Clients: Internal TestFlight QA, Staging Build & Developer Sandbox
Microservice Domain Breakdown
Handles E.164 User Registration, BCrypt Auth, Hardware RSA-2048 Public Key Binding, JWT Refresh Token Rotation, and Merchant Tenant RBAC.
Atomic Redis Lua Cart Mutate, Product Catalog, Voucher Reservation, POS Order Checkout, and Real-Time Kitchen Order Display (KDS).
Payoo, VietQR Instant Bank Transfer & Stripe Webhook Callbacks, Redis Lua Idempotency Lock, and Transactional Outbox Event Dispatcher.
FCM Push Notification Dispatcher for Customer Apps and Telegram Ops Bot (@zap_ops_alert_bot) for instant merchant order & alert triggers.
ZAP System Security Architecture Specification
Frontend SSL/TLS Certificate Pinning, Hardware-bound RSA 2048-bit Digital Signatures, and OAuth2 JWT Bearer Security.
Enforces SSL/TLS Certificate Pinning on mobile/desktop client apps to defeat MITM packet sniffing, paired with Hardware KeyStore (iOS Secure Enclave / Android StrongBox) for non-repudiation digital signatures.
1. End-to-End Multi-Layer Security Execution Order
Enforced on all FE Client Apps (Flutter & C# WPF).
β’ Pins SHA-256 Public Key Hashes of API Gateway TLS cert.
β’ Rejects untrusted CA certificates.
β’ Completely blocks Charles Proxy, Fiddler, & Burp Suite MITM inspection.
Validates identity token on Authorization: Bearer <token>.
β’ Checks RSA/HMAC-256 JWT signature using public key.
β’ Verifies token expiration time (exp claim).
β’ Extracts userId, roles, and merchantId into Spring
SecurityContext.
Validates non-repudiation hardware signature.
β’ Fetches user's RSA Public Key from Redis (user:public_key:{userId}).
β’ Verifies body SHA-256 digest (x-auth-checksum).
β’ Checks epoch timestamp drift (< 300s).
β’ Blocks Replay Attacks via x-auth-nonce.
2. Mandatory Security Headers Breakdown
| Header Name | Requirement | Description & Cryptographic Verification Purpose | Example Value |
|---|---|---|---|
Authorization |
Mandatory | OAuth2 Bearer JWT Access Token for session authentication. | Bearer eyJhbGciOiJSUzI1Ni... |
x-auth-signature |
Secured APIs | Base64-encoded RSA-SHA256 signature computed over canonical request payload using Secure Enclave. | Base64SignatureString== |
x-auth-timestamp |
Secured APIs | Unix epoch timestamp in milliseconds. Gateway rejects requests with
|T_server - T_req| > 300000ms.
|
1723205160000 |
x-auth-nonce |
Secured APIs | Cryptographic 128-bit random hex string. Cached in Redis for 5 mins to prevent replay of captured packets. | nonce_8f92a10b4c |
x-auth-checksum |
Secured APIs | SHA-256 hash digest of the raw HTTP request body bytes. Prevents man-in-the-middle body tampering. | e3b0c44298fc1c149afb... |
x-internal-call |
Internal Only | Header injected by API Gateway for microservice-to-microservice traffic. Bypasses L2 signature check. | true |
3. Canonical String Assembly & RSA Verification Formula
Both Client (Flutter / .NET C#) and Gateway construct the exact same canonical UTF-8 string before computing/verifying the signature:
// Step 1: Compute Request Body Hash
String bodyChecksum = SHA256_Hex(requestBodyBytes);
// Step 2: Assemble Canonical Message String
String canonicalPayload = String.format("%s|%s|%s|%s|%s",
httpMethod.toUpperCase(), // e.g. "POST"
requestURI.getPath(), // e.g. "/v1/orders/checkout"
timestampMs, // e.g. "1723205160000"
nonceHex, // e.g. "nonce_8f92a10b4c"
bodyChecksum // SHA-256 string
);
// Step 3: RSA 2048-bit Signature Verification
boolean isValid = Signature.getInstance("SHA256withRSA")
.initVerify(userPublicKeyFromRedis)
.update(canonicalPayload.getBytes(StandardCharsets.UTF_8))
.verify(Base64.getDecoder().decode(xAuthSignature));
4. Threat Model & Attack Mitigation Matrix
| Attack Vector | Impact Risk | ZAP Defense Mechanism |
|---|---|---|
| Packet Replay Attack | High (Duplicate Orders / Fraud Payment) | x-auth-nonce stored in Redis TTL key nonce:{nonce}. Duplicate nonces within
5 mins are immediately rejected with HTTP 403 REQUEST_TIMESTAMP_EXPIRED. |
| Man-In-The-Middle Body Tampering | Critical (Price/Quantity Manipulation) | x-auth-checksum SHA-256 digest is signed by Hardware RSA Key. Any byte alteration in
transit invalidates the digital signature. |
| Device Malware / Jailbreak Key Theft | Critical (Stolen User Identity) | RSA Private Keys generated in iOS Secure Enclave / Android StrongBox KeyStore are non-exportable and hardware-enforced. Malware cannot copy private keys. |
| OTP SMS Brute-force Attack | Medium (Account Takeover) | Redis sliding window rate limiter key otp:rate:{phone} limits SMS requests to max 1 per
60s and 5 per hour. Triggering returns HTTP 429 OTP_RATE_LIMIT_EXCEEDED. |
Redis Lua High-Concurrency Scripting Engine
Single-threaded atomic operations executing directly in Redis memory for zero DB lock contention, instant cart mutations, rate limiting, and idempotency locks.
Executing Lua scripts inside Redis server memory guarantees complete atomicity: no other command can run concurrently while a script executes. This eliminates database row locks, deadlocks during flash-sale concurrency spikes, and saves 3-4 TCP network round-trips (RTT).
1. Primary Production Lua Scripts Architecture
Target Key: cart:user:{userId}
β’ Atomically increments/decrements item quantities.
β’ Automatically deletes items if qty ≤ 0.
β’ Refreshes TTL to 24 hours (86,400s) on every modification.
Target Key: otp:rate:{phone}
β’ Uses Redis Sorted Set (ZSET) with epoch timestamps.
β’ Evicts timestamps older than sliding window.
β’ Returns HTTP 429 if request count exceeds threshold.
Target Key: payment:lock:{txnId}
β’ Verifies lock ownership UUID before deleting.
β’ Prevents thread A from releasing thread B's expired lock.
β’ Guarantees strict single-charge payment processing.
2. Production Script 1: Atomic Cart Quantity Mutation (`cart_mutate.lua`)
Executes directly on key cart:user:{userId} in Redis memory when users tap "+" or "-" in
`flutter_order_app`:
-- Redis Lua Script: cart_mutate.lua
-- KEYS[1]: Cart Redis Hash Key (e.g., "cart:user:usr_99812")
-- ARGV[1]: Product Variant ID (e.g., "prd_milktea_large")
-- ARGV[2]: Delta Quantity (+1 or -1)
-- ARGV[3]: Selected Options JSON String
local cartKey = KEYS[1]
local productId = ARGV[1]
local delta = tonumber(ARGV[2])
local currentQty = redis.call('HGET', cartKey, productId)
local newQty = 0
if currentQty then
newQty = tonumber(currentQty) + delta
else
newQty = delta
end
if newQty <= 0 then
-- Remove product item from cart Hash
redis.call('HDEL', cartKey, productId)
else
-- Update item quantity atomically
redis.call('HSET', cartKey, productId, newQty)
end
-- Refresh 24-hour expiration TTL
redis.call('EXPIRE', cartKey, 86400)
-- Return complete updated cart payload
return redis.call('HGETALL', cartKey)
3. Production Script 2: Sliding Window Rate Limiter (`rate_limiter.lua`)
Protects SMS OTP Gateway from brute-force attacks and abuse on key otp:rate:{phone}:
-- Redis Lua Script: rate_limiter.lua
-- KEYS[1]: Rate limit ZSET key (e.g., "otp:rate:+84901234567")
-- ARGV[1]: Current Unix Timestamp (milliseconds)
-- ARGV[2]: Window Size (milliseconds, e.g., 60000 for 1 minute)
-- ARGV[3]: Max Requests Allowed (e.g., 1 request per min)
local rateKey = KEYS[1]
local now = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local maxLimit = tonumber(ARGV[3])
local clearBefore = now - window
-- 1. Remove expired timestamps outside the current window
redis.call('ZREMRANGEBYSCORE', rateKey, 0, clearBefore)
-- 2. Count remaining requests inside the sliding window
local currentRequests = redis.call('ZCARD', rateKey)
if currentRequests < maxLimit then
-- 3. Add current timestamp to ZSET
redis.call('ZADD', rateKey, now, now)
redis.call('EXPIRE', rateKey, math.ceil(window / 1000))
return 1 -- ALLOWED
else
return 0 -- REJECTED (HTTP 429 Rate Limit Exceeded)
end
4. Production Script 3: Safe Idempotency Lock Release (`release_lock.lua`)
Ensures a worker thread only releases a payment transaction lock if it still owns the lock UUID:
-- Redis Lua Script: release_lock.lua
-- KEYS[1]: Lock key (e.g., "payment:lock:txn_778129")
-- ARGV[1]: Unique Lock UUID generated by acquiring thread
if redis.call('GET', KEYS[1]) == ARGV[1] then
-- Only delete if lock value matches worker thread UUID
return redis.call('DEL', KEYS[1])
else
-- Lock has expired or been acquired by another thread
return 0
end
Event-Driven Pub/Sub Topic Catalog
Asynchronous microservice event streams dispatched via RabbitMQ / Apache Kafka Event Bus.
Publishers (e.g. commerce-service) publish domain events to MQ exchanges without waiting for
consumers. Subscribers consume events asynchronously for zero-latency checkout.
| Event Topic Name | Publisher Microservice | Subscriber Microservices | Payload Event DTO & Triggers |
|---|---|---|---|
order.created.event |
commerce-service | notification-service, kiosk-terminal |
Dispatched when customer places order. Triggers Kitchen Kiosk push notification & customer receipt SMS. |
payment.success.event |
payment-service | commerce-service, notification-service |
Dispatched on Payoo / VietQR IPN callback. Updates Order status to PAID and exports PDF
receipt to GCS. |
user.registered.event |
identity-service | notification-service, wallet-service |
Dispatched on customer OTP signup. Initializes loyalty wallet and sends SMS welcome voucher. |
PostgreSQL ERD & Table Schema Reference
Complete schema reference scanned directly from JPA Entities across 4 Cloud SQL PostgreSQL databases (100+ tables total).
Each microservice exclusively owns its database. Cross-domain data flow is performed via REST endpoints or RabbitMQ transactional outbox events β zero cross-database SQL joins.
π commerce_db (Cloud SQL PostgreSQL 15 β 60+ Tables)
Owned by
commerce-service. Powers POS terminals, Omnichannel store management, Product Catalog, Inventory,
Fees, and Manager Analytics.
1. Manager Daily Aggregation Reports (Analytics & Audit)
| Table Name | Entity Class | Description |
|---|---|---|
manager_daily_sales_reports |
ManagerDailySalesReportEntity |
Daily revenue, net sales, tax total, discount totals per store branch |
manager_daily_item_reports |
ManagerDailyItemReportEntity |
Daily itemized sales count, revenue per SKU / variant |
manager_daily_category_reports |
ManagerDailyCategoryReportEntity |
Daily breakdown by category (Drinks, Food, Combo, Add-ons) |
manager_daily_payment_reports |
ManagerDailyPaymentReportEntity |
Daily breakdown by payment method (Payoo, VietQR, Cash, MoMo, Stripe) |
manager_daily_discount_reports |
ManagerDailyDiscountReportEntity |
Voucher & promotion redemption statistics and burn rate |
manager_daily_customer_reports |
ManagerDailyCustomerReportEntity |
Customer traffic, average order value (AOV), new vs returning buyers |
manager_daily_dining_option_reports |
ManagerDailyDiningOptionReportEntity |
Dine-in vs Takeaway vs Delivery fulfillment breakdown |
manager_daily_section_reports |
ManagerDailySectionReportEntity |
Floor plan section / zone performance aggregation |
manager_daily_location_reports |
ManagerDailyLocationReportEntity |
Geographic region & store location comparison matrix |
manager_daily_report_status |
ManagerDailyReportStatusEntity |
ETL aggregation batch status and locked reporting dates |
2. Product Catalog, SKUs & Variants
| Table Name | Entity Class | Description & Key Columns |
|---|---|---|
products |
ProductEntity |
Core product catalog (id, store_id, category_id, sku, name, base_price, status) |
product_skus |
ProductSkuEntity |
Barcode & SKU stock mapping (id, product_id, sku_code, barcode, cost_price) |
variant_groups |
VariantGroupEntity |
Variant categories e.g., "Size", "Topping", "Ice level", "Sugar level" |
variants |
VariantEntity |
Specific options e.g., "Size L (+10K)", "Less Ice", "Extra Boba" |
variant_option_sets |
VariantOptionSetTemplateEntity |
Reusable variant template presets across categories |
categories |
CategoryEntity |
Tree structure with self-referential parent_id and URL slugs |
menu_collections |
MenuCollectionEntity |
Curated product groupings e.g., "Best Sellers", "Seasonal Drinks" |
3. Orders, Line Items & Delivery
| Table Name | Entity Class | Description & Key Columns |
|---|---|---|
orders |
OrderEntity |
Order header (order_code, customer_id, store_id, total_amount, status, payment_method) |
order_items |
OrderItemEntity |
Line items (order_id, product_id, variant_id, quantity, unit_price, line_total) |
order_payments |
OrderPaymentEntity |
Payment attempt snapshots & split-pay references |
order_delivery_addresses |
OrderDeliveryAddressEntity |
Customer shipping address, contact phone, delivery notes |
order_times |
OrderTimeEntity |
Timestamps for KDS kitchen workflow (created, prepped, ready, dispatched) |
dining_options |
DiningOptionEntity |
Fulfillment modes: DINE_IN, TAKEAWAY, DELIVERY |
sales_channels |
SalesChannelEntity |
Channels e.g. POS_APP, WEB_PORTAL, MOBILE_FLUTTER, GRABFOOD_API |
4. POS Terminals & Store Floorplan
| Table Name | Entity Class | Description |
|---|---|---|
stores |
StoreEntity |
Physical branch store location details, coordinates, status |
devices |
DeviceEntity |
Registered POS Android/Windows hardware terminal binding |
floorplans |
FloorplanEntity |
Restaurant layout grids per store branch |
floorplan_squares |
FloorplanSquareEntity |
Individual dining table coordinates, capacity & live seating status |
location_business_hours |
LocationBusinessHourEntity |
Store opening/closing schedules & holiday overrides |
5. Inventory, Warehouse, Stock Documents & BOM Recipes
| Table Name | Entity Class | Description |
|---|---|---|
inventory_documents |
InventoryDocumentEntity |
Stock entry/exit/transfer documents (id, doc_code, doc_type, warehouse_id) |
inventory_document_items |
InventoryDocumentItemEntity |
Line items per inventory document with unit cost & quantity |
inventory_counts |
InventoryCountEntity |
Physical stock count audits & variance reconciliation |
inventory_movements |
InventoryMovementEntity |
Granular stock ledger audit log for every transaction increment/decrement |
inventory_reservations |
InventoryReservationEntity |
Temporary stock reservation held while customer is in checkout flow |
product_boms |
ProductBomEntity |
Bill of Materials (BOM) recipe composition per product/variant |
units |
UnitEntity |
Units of measurement e.g., kg, gram, ml, cup, piece |
suppliers |
SupplierEntity |
Vendor & raw material supplier master data |
supplier_sku_prices |
SupplierSkuPriceEntity |
Contracted supplier procurement prices per raw ingredient SKU |
geo_regions |
GeoRegionEntity |
Regional warehouse & store distribution zones |
customer_groups |
CustomerGroupEntity |
CRM customer segmentation e.g. VIP, Wholesale, Regular |
6. Price Lists & Multi-Tier Pricing Matrix
| Table Name | Entity Class | Description |
|---|---|---|
price_lists |
PriceListEntity |
Price books e.g. "Dine-in Menu", "GrabFood Menu", "Happy Hour Pricing" |
price_list_skus |
PriceListSkuEntity |
SKU-specific prices override per price list |
price_list_times |
PriceListTimeEntity |
Time-window schedule when price list is active (e.g. 14:00 - 17:00) |
7. Modifiers, Toppings, Combos & BOGO Deals
| Table Name | Entity Class | Description |
|---|---|---|
modifier_groups |
ModifierGroupEntity |
Topping groups e.g. "Choose 2 Toppings", "Crust Choice" |
modifiers |
ModifierEntity |
Individual topping choices e.g. "Boba (+5k)", "Cheese Foam (+10k)" |
order_item_modifiers |
OrderItemModifierEntity |
Selected toppings stored on order line items |
combo_conditions |
ComboConditionEntity |
Combo rules e.g. "1 Main + 1 Side + 1 Drink" |
combo_item_conditions |
ComboItemConditionEntity |
Eligible products qualifying for combo conditions |
discount_bogo_buys |
DiscountBogoBuyEntity |
Buy-X-Get-Y "Buy" triggers |
discount_bogo_gets |
DiscountBogoGetEntity |
Buy-X-Get-Y "Get" rewards (free or discounted item) |
order_bogo_collections |
OrderBogoCollectionEntity |
BOGO deals applied on active order |
order_combo_collections |
OrderComboCollectionEntity |
Combo bundles applied on active order |
8. Loyalty Points Rules & Membership Tiers
| Table Name | Entity Class | Description |
|---|---|---|
membership_tiers |
MembershipTierEntity |
Customer tiers: Bronze, Silver, Gold, Platinum |
membership_benefits |
MembershipBenefitEntity |
Perks per tier e.g., 5% discount, free birthday drink |
earn_point_rules |
EarnPointRuleEntity |
Point accumulation rate e.g. 10,000 VND = 1 Point |
9. Marketing Banners, Favorites & Customer CRM Profiles
| Table Name | Entity Class | Description |
|---|---|---|
banners |
BannerEntity |
App homepage promotional carousel banners |
favorites |
FavoriteEntity |
Customer favorite products & bookmarked stores |
customer_profiles |
CustomerProfileEntity |
Commerce CRM profile, birthday, preferences & total lifetime spend |
10. Media Assets & Transactional Outbox
| Table Name | Entity Class | Description |
|---|---|---|
media_assets |
MediaAssetEntity |
GCS image metadata (file size, mime, CDN URL, resolution) |
media_folders |
MediaFolderEntity |
Folder hierarchy for merchant asset organization |
media_asset_usages |
MediaAssetUsageEntity |
Cross-reference tracking where image is used |
commerce_outbox_events |
CommerceOutboxEventEntity |
Transactional outbox event log for order & product changes |
payment_db (Cloud SQL PostgreSQL 15 β 10 Tables)
Owned by
payment-service. Manages 8 payment gateway integrations, Prepaid Wallets, Loyalty Points,
Refunds, and Webhook Audit logs.
| Table Name | Entity Class | Description |
|---|---|---|
transactions |
TransactionEntity |
Main financial transaction log (txn_code, amount, status, gateway, gateway_ref) |
order_payments |
OrderPaymentEntity |
Bridge table between commerce orders and payment transactions |
payment_methods |
PaymentMethodEntity |
Active payment gateways: PAYOO, VIETQR, MOMO, STRIPE, VNPAY, SMARTPAY, PAYPAL, CASH |
user_payment_methods |
UserPaymentMethodEntity |
Vaulted payment tokens e.g., saved credit card / tokenized e-wallet |
brand_sales_channel_payment_methods |
BrandSalesChannelPaymentMethodEntity |
Per-merchant payment gateway routing configuration |
payment_refunds |
PaymentRefundEntity |
Refund requests, gateway refund response codes, admin requester ID |
payment_webhook_events |
PaymentWebhookEventEntity |
Raw inbound IPN payload audit trail for security forensic investigation |
wallets |
WalletEntity |
Prepaid customer digital wallet balance & deposit history |
loyalty_history |
LoyaltyHistoryEntity |
Reward points earn/burn history per order |
payment_outbox_events |
PaymentOutboxEventEntity |
Transactional outbox event log for payment.success RabbitMQ events |
identity_db (Cloud SQL PostgreSQL 15 β 20 Tables)
Owned by
identity-service. Handles user accounts, RBAC security permissions, RSA hardware keys, OAuth2
SSO, Brands & Multi-tenancy.
| Table Name | Entity Class | Description |
|---|---|---|
customers |
CustomerEntity |
End-user customer profiles, phone numbers, status |
customer_identities |
CustomerIdentityEntity |
Authentication identity records & hashed passwords |
customer_avatar_collections |
CustomerAvatarCollectionEntity |
Avatar gallery history |
customer_logging_whitelists |
CustomerLoggingWhitelistEntity |
Audit logging & debug tracing whitelist per user |
employees |
EmployeeEntity |
Staff & merchant employee master profiles |
employee_identities |
EmployeeIdentityEntity |
Staff login credentials & PIN numbers |
employee_roles |
EmployeeRoleEntity |
Staff store-level role assignments |
merchants |
MerchantEntity |
Merchant business profiles, tax ID (MST), license GCS URLs |
merchant_journeys |
MerchantJourneyEntity |
Merchant onboarding wizard step progress |
brands |
BrandEntity |
Multi-tenant brand enterprise entities |
brand_configs |
BrandConfigEntity |
Brand-level system parameters & feature toggles |
brand_themes |
BrandThemeEntity |
White-label mobile app color palettes & logos |
addresses |
AddressEntity |
Normalized street addresses & GPS coordinates |
address_types |
AddressTypeEntity |
Address categories: HOME, WORK, STORE, WAREHOUSE |
countries |
CountryEntity |
ISO country codes, phone prefixes & currencies |
roles |
RoleEntity |
System roles: ROLE_CUSTOMER, ROLE_MERCHANT, ROLE_STORE_MANAGER, ROLE_ADMIN |
permissions |
PermissionEntity |
Granular API permissions e.g., order:read, report:export |
role_permissions |
RolePermissionEntity |
RBAC mapping bridge between roles and permissions |
systems |
SystemEntity |
Registered client applications e.g. FLUTTER_APP, POS_DESKTOP |
system_configs |
SystemConfigEntity |
Global system-wide configuration key-value pairs |
notification_db (Cloud SQL PostgreSQL 15 β 4 Tables)
Owned by
notification-service. Manages Firebase Push Tokens, Templates, Deliveries, and FCM Configs.
| Table Name | Entity Class | Description |
|---|---|---|
user_notification_tokens |
UserNotificationTokenEntity |
Active Firebase Cloud Messaging device push tokens per user & device |
notification_templates |
NotificationTemplateEntity |
Push notification HTML/text templates with dynamic placeholder variables |
notification_deliveries |
NotificationDeliveryEntity |
Dispatch log & delivery receipt status for FCM, SMS, Telegram |
notification_firebase_configs |
FirebaseConfigEntity |
FCM Service Account JSON keys & channel settings |
Interactive End-to-End Sequence Flows
Step-by-step messaging sequences across Client Apps, API Gateway, Microservices, Redis, RabbitMQ, and PostgreSQL.
Flow 1: π 3-Tier Auth & Hardware RSA Key Pair Binding
| Step | Sender β Receiver | Protocol / Tech | Action & Payload Description |
|---|---|---|---|
| 1 | Flutter App β API Gateway | POST /api/v1/auth/login |
Sends E.164 phone + password hash or OAuth ID token |
| 2 | API Gateway β identity-service | gRPC / REST internal | Validates credentials, increments/resets login fail counter |
| 3 | identity-service β identity_db | Spring Data JPA | Fetches BCrypt hash & active user roles from users table |
| 4 | Flutter App β identity-service | POST /api/v1/auth/rsa/register |
Sends client-generated RSA-2048 public key PEM + device_id |
| 5 | identity-service β Redis | SET user:public_key:{userId} |
Caches RSA public key with 24h TTL for Layer 2 signature verification |
| 6 | identity-service β Flutter App | HTTP 200 OK + JWT | Returns Access Token (15 min) + Refresh Token (30 days) |
Postman Collection & OpenAPI 3.0 Exporter
Export all 350 microservice endpoints to standard Postman Collection v2.1 or OpenAPI 3.0 JSON format for instant import into Postman, Insomnia, or Swagger UI.
Postman Collection v2.1
Contains all 350 ZAP microservice endpoints organized by service folders, pre-configured headers (JWT, X-Signature), request bodies, and cURL samples.
OpenAPI 3.0.0 Specification
Standard OpenAPI 3.0 spec format compatible with Swagger UI, Redoc, Stoplight, and Automated API SDK Code Generators.
Generated Export JSON Preview:
{
"info": {
"name": "ZAP Ecosystem Microservices API Catalog",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{ "name": "commerce-service (215 APIs)" },
{ "name": "identity-service (83 APIs)" },
{ "name": "payment-service (44 APIs)" },
{ "name": "notification-service (7 APIs)" },
{ "name": "api-gateway (1 API)" }
]
}
Microservice Git Commit Velocity & Frequency
Real-time repository commit velocity metrics, contributor frequency analysis, and commit feed across all ZAP poly-repo services.
Microservice Git Commit Velocity & Frequency
Environment Matrix & Live Service Health Monitor
Environment configurations (Production, Staging, Local) and simulated live health uptime monitors across all ZAP microservice nodes.
Microservice Health & Latency Monitor
PROD (prod-api.zap.vn)Microservice Git Commit Velocity & Frequency
Environment Deployment Parameters
| Environment | Base Gateway API Domain | GCP Project ID | Cloud SQL Instance | Managed SSL Certificate |
|---|---|---|---|---|
| PROD (Production) | https://prod-api.zap.vn |
zap-ecosystem-production |
zap-postgres-db-prod (:5432) |
zap-prod-api-cert |
| SANDBOX / UAT | https://uat-api.zap.vn |
zap-ecosystem-sandbox-504003 |
zap-postgres-db-final (:5432) |
zap-uat-api-cert-v2 |
Payment IPN & Webhook Signature Verification
Per-gateway HMAC-SHA256 checksum rules, IP whitelist enforcement, and Redis idempotency lock for Payoo, VietQR (NAPAS), MoMo, and Stripe callbacks.
Every inbound IPN callback must pass 3 sequential checks before mutating order state: (1) Source IP Whitelist validation β (2) HMAC-SHA256 / RSA Signature verification β (3) Redis Idempotency Lock to prevent double-charge processing.
1. Gateway IPN Comparison Table
| Payment Gateway | IPN Endpoint | Signature Algorithm | Signature Location | IP Whitelist Required |
|---|---|---|---|---|
| Payoo (NAPAS) | POST /v1/payments/payoo/ipn |
HMAC-SHA256 with shared secret | X-Payoo-Checksum header |
Yes β Payoo server IPs |
| VietQR (BIDV) | POST /v1/payments/vietqr/ipn |
HMAC-SHA256 with client secret | checksum field in JSON body |
Yes β BIDV/NAPAS IPs |
| MoMo Wallet | POST /v1/payments/momo/ipn |
HMAC-SHA256 with secret key | signature field in JSON body |
Yes β MoMo server IPs |
| Stripe | POST /v1/payments/stripe/webhook |
HMAC-SHA256 with webhook secret + timestamp tolerance | Stripe-Signature header |
No β Uses signed secret |
2. Payoo IPN β HMAC-SHA256 Verification
Canonical string:
amount + "|" + orderId + "|" + responseCode + "|" + payooSecret
@PostMapping("/v1/payments/payoo/ipn")
public ResponseEntity<?> handlePayooIpn(
@RequestBody PayooIpnRequest req,
@RequestHeader("X-Payoo-Checksum") String headerChecksum,
HttpServletRequest http) {
// 1. IP Whitelist Check
String clientIp = http.getHeader("X-Forwarded-For");
if (!PAYOO_ALLOWED_IPS.contains(clientIp))
return ResponseEntity.status(403).build();
// 2. Reconstruct canonical string & compute HMAC-SHA256
String canonical = req.getAmount() + "|" + req.getOrderId()
+ "|" + req.getResponseCode() + "|" + payooSecret;
String computed = HmacUtils.hmacSha256Hex(payooSecret, canonical);
if (!computed.equalsIgnoreCase(headerChecksum))
return ResponseEntity.status(400).body("INVALID_CHECKSUM");
// 3. Redis Idempotency Lock β prevent double-processing
String lockKey = "payment:ipn:lock:" + req.getOrderId();
Boolean acquired = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "processing", Duration.ofMinutes(10));
if (Boolean.FALSE.equals(acquired))
return ResponseEntity.ok("ALREADY_PROCESSED");
// 4. Process β update order status & publish payment.success.event
paymentService.handlePayooSuccess(req);
return ResponseEntity.ok("00"); // Payoo expects "00" = success
}
3. VietQR (BIDV/NAPAS) IPN β HMAC-SHA256 Verification
Canonical string:
clientId + "|" + apiKey + "|" + amount + "|" + orderId
@PostMapping("/v1/payments/vietqr/ipn")
public ResponseEntity<?> handleVietQrIpn(@RequestBody VietQrIpnRequest req) {
// 1. Reconstruct canonical string
String canonical = vietQrClientId + "|" + vietQrApiKey
+ "|" + req.getAmount() + "|" + req.getOrderId();
String computed = HmacUtils.hmacSha256Hex(vietQrApiKey, canonical);
// 2. Compare with checksum in body
if (!computed.equals(req.getChecksum()))
return ResponseEntity.badRequest().body(Map.of("code", "01", "desc", "Checksum invalid"));
// 3. Idempotency lock + event dispatch
String lockKey = "payment:ipn:lock:" + req.getOrderId();
if (Boolean.FALSE.equals(
redisTemplate.opsForValue().setIfAbsent(lockKey, "1", Duration.ofMinutes(10))))
return ResponseEntity.ok(Map.of("code", "00", "desc", "Already processed"));
paymentService.handleVietQrSuccess(req);
return ResponseEntity.ok(Map.of("code", "00", "desc", "Success"));
}
4. MoMo Wallet IPN β HMAC-SHA256 Verification
Canonical string built from sorted query params:
accessKey + amount + extraData + message + orderId + orderInfo + orderType + partnerCode + payType + requestId + responseTime + resultCode + transId
@PostMapping("/v1/payments/momo/ipn")
public ResponseEntity<?> handleMomoIpn(@RequestBody MomoIpnRequest req) {
// 1. Reconstruct raw signature string (MoMo-sorted fields)
String raw = "accessKey=" + momoAccessKey
+ "&amount=" + req.getAmount()
+ "&extraData=" + req.getExtraData()
+ "&message=" + req.getMessage()
+ "&orderId=" + req.getOrderId()
+ "&orderInfo=" + req.getOrderInfo()
+ "&orderType=" + req.getOrderType()
+ "&partnerCode=" + req.getPartnerCode()
+ "&payType=" + req.getPayType()
+ "&requestId=" + req.getRequestId()
+ "&responseTime=" + req.getResponseTime()
+ "&resultCode=" + req.getResultCode()
+ "&transId=" + req.getTransId();
// 2. Compute HMAC-SHA256 with secretKey
String computed = HmacUtils.hmacSha256Hex(momoSecretKey, raw);
if (!computed.equals(req.getSignature()))
return ResponseEntity.badRequest().body("Signature mismatch");
// 3. Only process successful transactions (resultCode == 0)
if (req.getResultCode() != 0)
return ResponseEntity.ok("Noted β non-success callback");
// 4. Idempotency + event
paymentService.handleMomoSuccess(req);
return ResponseEntity.ok("OK");
}
5. Stripe Webhook β Signed Payload + Timestamp Tolerance
Stripe uses Stripe-Signature header
containing t=timestamp,v1=hmac. A 5-minute timestamp tolerance prevents replay attacks.
@PostMapping("/v1/payments/stripe/webhook")
public ResponseEntity<?> handleStripeWebhook(
@RequestBody String payload,
@RequestHeader("Stripe-Signature") String sigHeader) {
// Stripe SDK validates HMAC-SHA256 + timestamp tolerance (300s)
Event event;
try {
event = Webhook.constructEvent(payload, sigHeader, stripeWebhookSecret);
} catch (SignatureVerificationException e) {
return ResponseEntity.status(400).body("Invalid Stripe signature");
}
// Handle specific event types
switch (event.getType()) {
case "payment_intent.succeeded":
PaymentIntent intent = (PaymentIntent) event.getData().getObject();
paymentService.handleStripeSuccess(intent.getId(), intent.getAmount());
break;
case "payment_intent.payment_failed":
paymentService.handleStripeFailure(intent.getId());
break;
}
return ResponseEntity.ok("received");
}
6. Redis Idempotency Guard β Prevent Double-Charge
Applied on every IPN handler before mutating
order
state. Uses SET NX EX atomic semantics via Lua script:
-- Redis Lua Idempotency Guard: ipn_lock.lua
-- KEYS[1]: "payment:ipn:lock:{orderId}"
-- ARGV[1]: Current processor ID
-- ARGV[2]: TTL in seconds (600 = 10 minutes)
if redis.call('SET', KEYS[1], ARGV[1], 'NX', 'EX', ARGV[2]) then
return 1 -- Lock acquired: safe to process IPN
else
return 0 -- Lock already held: IPN already processed, skip
end
Client Distribution & Multi-Tenant App Publishing Architecture
Visual architecture model of ZAP-managed internal single-app operations suite vs multi-tenant white-label customer ordering apps uploaded per merchant brand (Pendogo, Pho24, etc.).
β’ Merchant Operations Suite (POS / Kiosk / CRM): Managed centrally by ZAP as 1 single
application stack across UAT and PROD.
β’ Customer Ordering Apps: Built from a single white-label codebase, compiled per merchant
brand (Pendogo, Pho24, Brand X), and published to Apple App Store & Google Play Store
as independent branded apps.
1. Client App Publishing & Environment Distribution Model (Visual Diagram)
2. Client Application Distribution & Publishing Matrix
| Application Category | Ownership & Management | App Store Publishing Model | Target Environments / Brands | Build Flavor / Scheme |
|---|---|---|---|---|
|
Merchant Operations Suite POS WPF, Kiosk & Staff CRM |
Managed 100% by ZAP Core Team | 1 Single App under ZAP Developer Account |
UAT
PROD
|
--flavor zap_staff |
|
Customer Ordering Suite White-Label Ordering Apps |
White-label Multi-Tenant Architecture | Uploaded as Multiple Separate Branded Apps per Merchant Account |
UAT
App
Pendogo
App
Pho24
App
Brand
X...
|
--flavor pendogo_prod--flavor pho24_prod |
3. Application Product & Platform Build Inventory Matrix
| Application Product | Target Platform | UAT Environment Build | Production Environment Build | Managed Apps Count |
|---|---|---|---|---|
1. ZAP
Manager
Merchant
Staff CRM, Store Manager & Admin Web
flutter_manager
|
Apple iOS | 1 App (Manager UAT β TestFlight) |
1 App (Manager Prod β App Store) |
2 iOS Apps |
| Google Android | 1 App (Manager UAT β Play Internal) |
1 App (Manager Prod β Play Console) |
2 Android Apps | |
| Web & Desktop Browser | 1 App (Manager UAT Web β uat-manager.zap.vn) |
1 App (Manager Prod Web β manager.zap.vn) |
2 Web/Desktop Apps | |
2. ZAP POS
Desktop
Windows
WPF POS & Thermal Printer Driver
pos_wpf (.NET C#)
|
Microsoft Windows | 1 App (POS Cashier UAT Installer) |
1 App (POS Cashier Prod Installer) |
2 Windows Apps |
3. ZAP POS
Mobile
Handheld
Mobile POS & Sunmi Terminal
flutter_pos_mobile
|
Apple iOS (iPad/iPhone) | 1 App (POS Mobile UAT β TestFlight) |
1 App (POS Mobile Prod β App Store) |
2 iOS Apps |
| Google Android (Sunmi POS) | 1 App (POS Mobile UAT β Play Internal) |
1 App (POS Mobile Prod β Sunmi/Play Store) |
2 Android Apps | |
4. ZAP
Kiosk
Self-Service
Touchscreen Kiosk App
flutter_kiosk
|
Google Android | 1 App (Kiosk Android UAT) |
1 App (Kiosk Android Prod) |
2 Android Apps |
| Microsoft Windows | 1 App (Kiosk Windows UAT) |
1 App (Kiosk Windows Prod) |
2 Windows Apps | |
5. ZAP Order
App
Multi-Tenant
White-Label Branded App
flutter_order_app
|
Apple iOS | 1 App (Central ZAP Order UAT App) |
N Separate Branded Apps (Pendogo, Pho24...) | N + 1 iOS Apps |
| Google Android | 1 App (Central ZAP Order UAT App) |
N Separate Branded Apps (Pendogo, Pho24...) | N + 1 Android Apps | |
| TOTAL ECOSYSTEM APPS TO MANAGE: | 10 UAT Sandbox Builds | 2N + 7 Production Builds | 2N + 17 Active Builds | |
4. Target OS & Mobile Store Publishing Pipeline (iOS, Android & Windows)
4. Multi-Platform Build & Publishing Specification Matrix
| Target OS Platform | Build Artifact | Signing & Security Cert | UAT Testing Channel | Production Publishing Store |
|---|---|---|---|---|
| Apple iOS | .ipa Package |
Apple Distribution Cert + Provisioning Profile | Apple TestFlight (Internal Group) | Apple App Store Connect |
| Google Android | .aab / .apk |
Android Keystore (upload-keystore.jks) |
Play Internal App Sharing / Firebase | Google Play Console |
| Windows Desktop | .exe / .msi |
EV Code Signing Certificate | Direct MSI / UAT Update Server | ZAP Auto-Updater Service |
Software Continuous Deployment (CD) Architecture Diagram
End-to-end visual workflow diagram for automated container build, GCP Artifact Registry storage, zero-downtime deployment, health probes, and automatic rollback.
Every pull request merged to uat automatically triggers Cloud Build & deploys to UAT
(zap-ecosystem-sandbox-504003). Merges to main trigger a tagged release
requiring
1-click manual approval before deploying to Production (zap-ecosystem-production).
1. Automated CD Deployment Pipeline Architecture (Visual Workflow Diagram)
Monorepo Workspace Structure & Branching Architecture
Accurate repository topology matching the real zap-system workspace
layout: Java 17 backend monorepo, multi-platform frontend workspace, GCP infrastructure scripts, and
Gitflow
branching rules.
The ZAP ecosystem is structured as a unified monorepo workspace at root zap-system, combining
backend microservices, multi-platform client apps, and GCP infrastructure IaC submodules.
1. Workspace Directory & Monorepo Architecture (Visual Model)
2. Gitflow Branching & Release Timeline Architecture
3. Conventional Commit Classifier Standard (Visual Cards)
New Feature Implementation
Bug Fix & Patch
Configuration & Dependencies
Documentation Updates
Code Refactoring & Clean Up
Automated Unit & Integration Tests
Resilience4j Circuit Breaker & Fallback Policies
API Gateway fault-tolerance configuration to protect upstream microservices from cascading failures.
When a microservice failure rate exceeds threshold, the Circuit Breaker transitions to OPEN state, immediately short-circuiting all downstream requests and returning a pre-configured fallback response β no thread pool exhaustion.
1. Circuit Breaker State Machine
All requests pass through normally to microservices.
β’ Monitors failure rate using sliding window.
β’ Transitions to OPEN if failure rate > 50%.
All requests are immediately rejected (HTTP 503).
β’ Returns fallback JSON response instantly.
β’ Waits waitDurationInOpenState (default 30s).
Allows limited test requests to probe microservice.
β’ Success β transitions back to CLOSED.
β’ Failure β returns to OPEN state.
2. Gateway Circuit Breaker Configuration (application.yml)
resilience4j:
circuitbreaker:
configs:
default:
slidingWindowSize: 10 # Evaluate last 10 requests
failureRateThreshold: 50 # Trip if 50%+ requests fail
waitDurationInOpenState: 30s # Stay OPEN for 30 seconds
permittedNumberOfCallsInHalfOpenState: 3
registerHealthIndicator: true
timelimiter:
configs:
default:
timeoutDuration: 5s # Abort upstream call after 5s
spring:
cloud:
gateway:
routes:
- id: identity-service-route
predicates:
- Path=/api/v1/auth/**
filters:
- name: CircuitBreaker
args:
name: identity-service-cb
fallbackUri: forward:/fallback/identity
3. Fallback Response Contract
// Circuit Breaker Fallback Controller
@RestController
public class FallbackController {
@GetMapping("/fallback/identity")
public Mono<ApiResponse<?>> identityFallback() {
return Mono.just(ApiResponse.error(5000,
"identity-service is temporarily unavailable. Please retry in 30 seconds."));
}
@GetMapping("/fallback/commerce")
public Mono<ApiResponse<?>> commerceFallback() {
return Mono.just(ApiResponse.error(5000,
"commerce-service is temporarily unavailable."));
}
}
Google Cloud Storage (GCS) Media Upload Flow
Signed URL pre-authentication upload pattern for product images, store banners, and PDF invoice receipts.
Clients upload media directly to GCS using a short-lived signed URL issued by
commerce-service
β API Gateway is not involved in the media data transfer, reducing backend bandwidth by 100%.
1. Upload Flow Sequence
Client calls
POST /v1/media/upload-url on commerce-service with filename + MIME type.
Server
returns
signed GCS URL valid for 15 mins: gs://zap-media-assets/products/{uuid}
Client streams file bytes via HTTP PUT directly to signed GCS URL. Backend is not involved.
2. Bucket Folder Organization
| GCS Folder Path | Content Type | Access Control |
|---|---|---|
gs://zap-media-assets/products/ |
Product food images, variants photos (JPEG/WebP) | Public read via CDN endpoint |
gs://zap-media-assets/stores/logos/ |
Brand logo images and banner artwork (PNG) | Public read via CDN endpoint |
gs://zap-media-assets/invoices/ |
Customer order PDF receipt exports | Private β Signed URL access only |
3. Java Signed URL Generation (commerce-service)
// Generate 15-minute GCS Signed URL for direct client upload
public String generateSignedUploadUrl(String fileName, String contentType) {
BlobInfo blobInfo = BlobInfo.newBuilder(
BlobId.of("zap-media-assets", "products/" + UUID.randomUUID() + "_" + fileName)
).setContentType(contentType).build();
return storage.signUrl(
blobInfo,
15, TimeUnit.MINUTES,
Storage.SignUrlOption.withV4Signature(),
Storage.SignUrlOption.httpMethod(HttpMethod.PUT)
).toString();
}
API Endpoint Reference Catalog
Parsed directly from Java Controller source code declarations across all microservices.
Backend Design System & API Envelope Contract
Standardized response formats, global error codes, and Redis cache conventions.
Standardized Response Envelope (ApiResponse<T>)
{
"code": 1000,
"message": "Operation completed successfully",
"data": { ... },
"timestamp": "2026-08-09T18:49:00Z"
}
Global System & Payment Gateway Error Codes (153 Total Codes)
Redis Cache Naming Conventions
ZAP Platform — Development Roadmap
Structured roadmap with detailed task breakdown across UAT, PROD setup, mobile/desktop app configurations, backend microservices, and upcoming releases (May–August 2026).
ZAP CRM Terms of Service
Welcome to ZAP CRM! By downloading, installing, registering, or using the ZAP CRM Application, you agree to be bound by the terms and conditions set forth below.
PART I. TERMS OF SERVICE
1.1. Definitions
- βZAPβ / βWeβ / βUsβ: The entity that owns, develops, and operates the ZAP CRM customer relationship management software system.
- βZAP CRM Applicationβ (hereinafter referred to as "ZAP"): The official mobile application distributed on application stores (Apple App Store, Google Play Store) running on mobile devices (Smartphones, Tablets, iPads).
- βServicesβ: CRM management features, customer management, reporting, and channel integrations provided on the ZAP Application.
- βAccount Ownerβ: An individual or business representative who registers the initial account and holds the highest administrative rights.
- βYouβ / βUserβ: The Account Owner or employees authorized to access and experience the ZAP Application.
- βBusiness Dataβ: All information and data (customers, orders, receipts/vouchers, reports, etc.) created, entered, or stored by You on the ZAP Application.
1.2. Registration and Login Methods
To use ZAP CRM, You may register/log in through the following methods:
- Phone Number: Authentication via an OTP code sent to Your personal/business phone number.
- Facebook Account (Facebook Login): Quick login via Meta's official SDK.
- Google Account (Google Sign-In): Quick login via Google's OAuth 2.0 protocol.
You are responsible for maintaining the confidentiality and security of Your mobile device, password, and login credentials. ZAP shall not be liable for any losses arising from Your negligence or disclosure of login information.
1.3. Acceptable Use
You commit to using ZAP CRM solely for lawful business activities in compliance with the laws of Vietnam and applicable regulations. The following actions are strictly prohibited:
- Using ZAP to commit fraud, send spam messages, disseminate false information, or violate the law.
- Uploading or storing obscene content, copyright-infringing materials, or content that compromises national security.
- Interfering with, reverse-engineering, or damaging system integrity or ZAPβs databases.
1.4. Intellectual Property Rights
All source code, user interface designs, logos, the ZAP trademark, and related intellectual property belong exclusively to ZAP. You are not permitted to copy, redistribute, or sublicense any part of the service to any third party without prior written consent from ZAP.
1.5. Limitation of Liability
ZAP makes every reasonable effort to ensure stable and uninterrupted Services. However, the Services rely on Internet infrastructure, user devices, and third-party platform providers (Apple, Google). ZAP shall not be held liable for temporary disruptions caused by network errors, force majeure cyberattacks, or compromised/damaged user devices.
ZAP is not responsible for the accuracy of Business Data entered into the system by You, nor for Your business performance results.
PART II. CONTACT AND SUPPORT INFORMATION
If You have any questions, complaints, or support requests regarding the Terms of Service, please contact ZAP via:
ZAP CRM Privacy Policy
This policy details how ZAP collects, uses, and protects Your personal information in compliance with Decree No. 13/2023/ND-CP of Vietnam and Apple & Google Store privacy requirements.
PART I. PRIVACY POLICY
1.1. Data We Collect
- Account Identification Information: Registered phone number. Profile information from Google/Facebook accounts (Full Name, Email address, Profile Picture/Avatar) when You choose to log in via Google or Facebook.
- Business & CRM Data: Customer lists, interaction history, order details, and documents proactively created by You on the app.
- Technical Device Information: Device type (iOS/Android), operating system version, IP address, and crash logs for application optimization purposes.
1.2. App Permissions Details
ZAP requests mobile device permissions (Mobile, Tablet, iPad) only when essential for business features, and always seeks Your permission prior to access:
- Contacts: To assist You in selecting and quickly syncing customer contacts from Your phone/tablet into the CRM system.
- Camera: To take product photos, scan QR codes on invoices/vouchers, or capture transaction proof images.
- Photos / Storage: To temporarily store offline data and select photo documents/files to upload to the CRM.
- Location (GPS): To support sales point check-ins, customer locating, or staff work location tracking when You enable this feature.
- Internet Connection & Push Notifications: To synchronize real-time data and send push notifications for customer care schedules and new orders.
1.3. Third-Party Integrations and Services (Facebook, Google)
- Google Account (Google Sign-In): ZAP uses Google Sign-In via standard protocols for identity verification and to support secure, quick logins.
- Facebook Account (Facebook Login): ZAP utilizes Facebook Login SDK solely to authenticate user identity and assist You in creating/logging into Your ZAP CRM account using Your personal Facebook account. ZAP does not request Page management permissions, nor does it read or interfere with messages, comments, or any other administrative data on Your Facebook account.
1.4. Data Storage and Security
- Security: Your data is encrypted during transmission (SSL/TLS) and stored securely on cloud server infrastructure meeting industry security standards.
- Retention Period: Data is stored for as long as You maintain Your ZAP CRM account or until the account is deleted.
1.5. User Rights & Account Deletion Procedure
You possess full rights regarding Your personal data, including:
- Viewing and editing personal information directly within the ZAP Application.
- Requesting the export of Your Business Data from the system.
PART II. CONTACT AND SUPPORT INFORMATION
If You have any questions, complaints, or support requests regarding the Privacy Policy, please contact ZAP via: