Shop Module
The shop module handles all e-commerce functionality: product listings, order management, coupon systems, user balance accounting, and gift card redemption. When you need to add payment integrations, modify pricing logic, or extend the checkout flow, this is where you start.
Overview
- Config (
config.rs) – Runtime configuration for order limits, auto-cancellation timing, and ePay integration URLs. Adjust these when tuning business rules or payment gateway endpoints. - Entities (
entities/) – Database models for orders, productions (products), coupons, user balances, gift cards, and ePay providers. Extend these when adding new persistent data structures. - Services (
services/) – Business logic services implementing order processing, coupon validation, balance management, and production queries. All APIs must be exposed through theProcessortrait pattern, not object-oriented methods. - RPC (
rpc/) – gRPC endpoints exposing shop capabilities to clients and other modules. Organized into user-facing services (order, production, account) and admin management services. - API (
api/) – REST/HTTP API endpoints for payment gateway callbacks and integrations that require non-gRPC interfaces. - Events (
events/) – Event definitions for order lifecycle (created, paid, cancelled, delivered) using RabbitMQ for inter-module communication. - Hooks (
hooks/) – Event consumers that react to order events, handle ePay callbacks, log balance changes, and initialize user balances on registration. - Cron (
cron.rs) – Background jobs for automatic order cancellation when unpaid orders exceed the configured timeout period.
Core Services
User-Facing Services
OrderService (services/order.rs)
Handles the complete order lifecycle from creation to payment. Key operations:
- List user orders with production details and status
- Create orders with optional coupon application
- Generate ePay payment URLs for third-party payment gateways
- Process payments via account balance or external providers
- Cancel unpaid orders
- List available ePay providers and channels
ProductionService (services/production.rs)
Manages product catalog visibility and access control:
- List productions filtered by user group permissions
- Retrieve individual production details with access validation
- Products can be restricted to specific user groups or extra permission groups
CouponService (services/coupon.rs)
Validates promotional codes and discount rules:
- Verify coupon validity considering time windows, usage limits, and user eligibility
- Support for both percentage-based and amount-based discounts
- Per-account and global usage tracking
BalanceService (services/user_balance.rs)
User account balance operations:
- Query available and frozen balance
- List balance change history with pagination
- Redeem gift cards for balance credits
GiftCardService (services/gift_card.rs)
Gift card redemption and validation
Management Services
ManageService (services/manage.rs)
Admin operations for all shop entities with RBAC enforcement:
- Orders: Mark paid, change amounts, list with filters, view details
- Coupons: Create, update, delete, list with full metadata
- Productions: Create, delete, list with package relationships
- Balances: Adjust user balances, view change logs
- Gift Cards: Generate in batches, create special codes, delete, list with filters
All management operations are integrated with the admin audit log system and require appropriate AdminRole permissions.
Payment Integration
The module integrates with ePay (易支付) third-party payment gateway:
-
Payment Flow:
- User creates order → receives order ID
- User requests payment URL with provider and channel (AliPay, WeChat, USDT)
- Module generates signed URL using provider credentials
- User completes payment on gateway
- Gateway sends callback to
api/epay.rswebhook - Hook verifies signature and updates order status
OrderPaidEventemitted for downstream processing
-
Provider Management:
- Multiple ePay providers supported with different channels
- Providers configured with merchant URLs, PIDs, and keys
- Each provider can be enabled/disabled via database switch
Events & Hooks
Published Events (via RabbitMQ):
OrderCreatedEvent(exchange:shop, routing:order_created) – Internal trackingOrderPaidEvent(exchange:shop, routing:order_paid) – Consumed by market module for affiliate rewardsOrderCancelledEvent(exchange:shop, routing:order_cancelled) – Internal trackingOrderDeliveredEvent(exchange:shop, routing:order_delivered) – Currently unused, candidate for removal
Event Consumers:
- ePay Hook (
hooks/epay.rs) – Listens to payment callbacks and updates order status - Log Hook (
hooks/log.rs) – Tracks balance changes in audit logs - Register Hook (
hooks/register.rs) – Initializes zero balance for new user accounts
Typical Extension Workflow
- Add Configuration – Define new config fields in
config.rsand surface through Redis configuration provider - Extend Entities – Add or modify database models in
entities/for new persistent data - Implement Service Logic – Create
Processorimplementations inservices/following the pattern:impl Processor<MyInput, Result<MyOutput, Error>> for MyService { async fn process(&self, input: MyInput) -> Result<MyOutput, Error> { // Business logic here } } - Expose via RPC – Add gRPC methods in
rpc/that delegate to service processors - Define Proto Messages – Update
.protofiles inproto/shop/and rebuild - Emit Events – Publish events through
AmqpPoolwhen state changes need cross-module notification - Add Hooks – Create event consumers in
hooks/if other modules need to react - Schedule Maintenance – Add cron jobs in
cron.rsfor cleanup or periodic tasks
Architecture Notes
- Processor Pattern: All service APIs use the
Processor<Input, Result<Output, Error>>trait from thekanaucrate. Never expose business logic through object methods. - Owned Resources: Services hold owned
RedisConnection,DatabaseProcessor, andAmqpPoolinstead of static lifetimes or references. - Coupon Discount Types: Two variants –
RateDiscount(percentage) andAmountDiscount(fixed amount with minimum threshold) - Order Status Flow: Unpaid → Paid → Delivered (or Cancelled/Refunding/Refunded)
- Balance Types: Available balance (spendable) and frozen balance (temporarily locked during transactions)
- Decimal Handling: All monetary values use
rust_decimal::Decimalinternally and serialize as strings in proto/JSON
Database Schema
Key tables (see migrations/20250815133800_create_shop_entites.sql):
productions– Product catalog with pricing and package referencesorders– Order records with status tracking and payment detailscoupons– Promotional codes with discount rules and usage trackinguser_balance– Account balance per useruser_balance_change_log– Audit trail for all balance modificationsgift_cards– Redeemable codes with amounts and expirationepay_providers– Configured payment gateway providers
Usage Examples
Creating an Order:
let result = order_service.process(CreateOrder {
user_id: user.id,
production_id: prod_uuid,
coupon_id: Some(123),
}).await?;
Payment with Balance:
let result = order_service.process(PayOrderWithBalance {
user_id: user.id,
order_id: order_uuid,
}).await?;
Redeeming Gift Card:
let result = balance_service.process(RedeemGiftCard {
user_id: user.id,
secret: "GIFT-CODE-123",
}).await?;
Configuration
Shop module configuration is stored in Redis under key shop:
{
"max_unpaid_orders": 5,
"auto_cancel_after": "30m",
"epay_notify_url": "https://api.example.com/shop/epay/callback",
"epay_return_url": "https://example.com/order/complete"
}
Keep this document synchronized with structural changes so future developers can quickly navigate the codebase.