Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 the Processor trait 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:

  1. 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.rs webhook
    • Hook verifies signature and updates order status
    • OrderPaidEvent emitted for downstream processing
  2. 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 tracking
  • OrderPaidEvent (exchange: shop, routing: order_paid) – Consumed by market module for affiliate rewards
  • OrderCancelledEvent (exchange: shop, routing: order_cancelled) – Internal tracking
  • OrderDeliveredEvent (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

  1. Add Configuration – Define new config fields in config.rs and surface through Redis configuration provider
  2. Extend Entities – Add or modify database models in entities/ for new persistent data
  3. Implement Service Logic – Create Processor implementations in services/ following the pattern:
    impl Processor<MyInput, Result<MyOutput, Error>> for MyService {
        async fn process(&self, input: MyInput) -> Result<MyOutput, Error> {
            // Business logic here
        }
    }
  4. Expose via RPC – Add gRPC methods in rpc/ that delegate to service processors
  5. Define Proto Messages – Update .proto files in proto/shop/ and rebuild
  6. Emit Events – Publish events through AmqpPool when state changes need cross-module notification
  7. Add Hooks – Create event consumers in hooks/ if other modules need to react
  8. Schedule Maintenance – Add cron jobs in cron.rs for cleanup or periodic tasks

Architecture Notes

  • Processor Pattern: All service APIs use the Processor<Input, Result<Output, Error>> trait from the kanau crate. Never expose business logic through object methods.
  • Owned Resources: Services hold owned RedisConnection, DatabaseProcessor, and AmqpPool instead of static lifetimes or references.
  • Coupon Discount Types: Two variants – RateDiscount (percentage) and AmountDiscount (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::Decimal internally 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 references
  • orders – Order records with status tracking and payment details
  • coupons – Promotional codes with discount rules and usage tracking
  • user_balance – Account balance per user
  • user_balance_change_log – Audit trail for all balance modifications
  • gift_cards – Redeemable codes with amounts and expiration
  • epay_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.