按次付费的档案管理系统,其核心在于将传统的一次性软件授权或年费模式,转变为按实际使用量(如档案查阅次数、存储空间增量、API调用次数)计费。这要求系统具备精确的计量、灵活的计费策略和安全的支付集成能力。
为实现高可用与可扩展性,建议采用微服务架构:
明确哪些操作触发计费是设计关键。以下是常见的计量点:
以 Ubuntu 22.04 LTS 服务器为例,部署基础服务。
安装 Docker 与 Docker Compose:
``` sudo apt update sudo apt install -y apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io sudo systemctl start docker sudo systemctl enable docker sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose ```创建 `docker-compose-infra.yml` 文件:
``` version: '3.8' services: postgres: image: postgres:15-alpine container_name: archive-postgres environment: POSTGRES_DB: archive_main POSTGRES_USER: archive_admin POSTGRES_PASSWORD: YourStrongPassword123! 请务必修改 volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" restart: unless-stopped redis: image: redis:7-alpine container_name: archive-redis command: redis-server --requirepass YourRedisPassword456! 请务必修改 volumes: - redis_data:/data ports: - "6379:6379" restart: unless-stopped volumes: postgres_data: redis_data: ```启动服务:sudo docker-compose -f docker-compose-infra.yml up -d
创建 `docker-compose-minio.yml` 文件:
``` version: '3.8' services: minio: image: minio/minio:latest container_name: archive-minio command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: YourMinioAdminPass789! 请务必修改 volumes: - minio_data:/data ports: - "9000:9000" API端口 - "9001:9001" 管理控制台端口 restart: unless-stopped volumes: minio_data: ```启动服务:sudo docker-compose -f docker-compose-minio.yml up -d。访问 `http://服务器IP:9001` 登录管理控制台,创建名为 `archive-files` 的存储桶。
创建一个独立的 Spring Boot 服务 `metering-service`。核心是拦截所有付费操作,生成不可篡改的计量事件。
MeteringEvent 实体类:
``` @Entity @Table(name = "metering_events") public class MeteringEvent { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String userId; // 触发用户 private String eventType; // 如 "DOCUMENT_VIEW", "STORAGE_GB" private String resourceId; // 档案ID等 private BigDecimal units; // 消耗单位数,如1次,或0.5GB private LocalDateTime eventTime; private String traceId; // 用于链路追踪 // getters and setters } ```事件发布AOP切面:在关键业务方法上添加 `@Metering` 注解,切面自动记录事件。
``` @Aspect @Component public class MeteringAspect { @Autowired private MeteringEventService eventService; @Around("@annotation(metering)") public Object recordMeteringEvent(ProceedingJoinPoint joinPoint, Metering metering) throws Throwable { // 1. 执行原方法 Object result = joinPoint.proceed(); // 2. 构建并保存计量事件 MeteringEvent event = new MeteringEvent(); event.setEventType(metering.eventType()); event.setUserId(SecurityContextHolder.getContext().getAuthentication().getName()); // ... 设置其他属性 eventService.saveEvent(event); // 3. 可选:异步发送到消息队列供计费服务消费 kafkaTemplate.send("metering-events", event); return result; } } ```
创建 `billing-service`,消费计量事件,按配置的价目表生成账单。
价目表配置(数据库表):
``` CREATE TABLE price_plan ( id SERIAL PRIMARY KEY, event_type VARCHAR(50) NOT NULL, unit_price DECIMAL(10,4) NOT NULL, -- 单价,如0.1元/次 currency VARCHAR(10) DEFAULT 'CNY', effective_date DATE NOT NULL, is_active BOOLEAN DEFAULT true ); ```周期性账单生成任务(Spring Scheduler):
``` @Service public class BillingCycleService { @Scheduled(cron = "0 0 0 1 ?") // 每月1号执行 public void generateMonthlyBill() { // 1. 查询上个月所有用户的计量事件,按用户和事件类型聚合 String sql = """ SELECT user_id, event_type, SUM(units) as total_units FROM metering_events WHERE event_time >= ? AND event_time < ? GROUP BY user_id, event_type """; // 2. 联查价目表,计算每个用户的总费用 // 3. 生成账单记录,状态为'待支付' // 4. 调用支付网关预创建订单,获取支付链接 } } ```在支付宝开放平台创建应用,获取 `APP_ID`、`应用私钥`、`支付宝公钥`。
AlipayClient 配置 Bean:
``` @Configuration public class AlipayConfig { @Value("${alipay.app-id}") private String appId; @Value("${alipay.merchant-private-key}") private String privateKey; @Value("${alipay.alipay-public-key}") private String alipayPublicKey; @Bean public AlipayClient alipayClient() { return new DefaultAlipayClient( "https://openapi.alipay.com/gateway.do", appId, privateKey, "json", "UTF-8", alipayPublicKey, "RSA2" ); } } ```发起支付请求:
``` @Service public class AlipayService { @Autowired private AlipayClient alipayClient; public String createOrder(Bill bill) { AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); request.setReturnUrl("https://your-domain.com/payment/return"); request.setNotifyUrl("https://your-domain.com/api/payment/alipay/notify"); // 异步通知地址 AlipayTradePagePayModel model = new AlipayTradePagePayModel(); model.setOutTradeNo(bill.getBillNumber()); // 你的账单号 model.setTotalAmount(bill.getTotalAmount().setScale(2).toString()); model.setSubject("档案服务账单 - " + bill.getPeriod()); model.setProductCode("FAST_INSTANT_TRADE_PAY"); request.setBizModel(model); try { AlipayTradePagePayResponse response = alipayClient.pageExecute(request); return response.getBody(); // 返回的是一个表单HTML,可直接渲染给前端 } catch (AlipayApiException e) { throw new RuntimeException("创建支付宝订单失败", e); } } } ```支付结果异步通知处理:必须验证签名并更新本地账单状态。
``` @PostMapping("/api/payment/alipay/notify") public String handleAlipayNotify(HttpServletRequest request) { Map部署 Prometheus 和 Grafana 监控计量事件流。
查看服务日志:sudo docker logs -f archive-postgres
备份数据库:sudo docker exec archive-postgres pg_dump -U archive_admin archive_main > backup_$(date +%Y%m%d).sql
检查服务状态:sudo docker-compose -f docker-compose-infra.yml ps
至此,一个具备按次付费能力的档案管理系统核心架构与部署流程已完成。重点在于确保计量无遗漏、计费准确、支付安全,并通过监控对账保障业务财务一致性。所有代码与配置均可直接用于生产环境原型开发。