佣金分成系统的核心是准确追踪每一笔订单的来源,并按照预设规则实时或定期计算分佣金额。本方案采用事件驱动架构,确保高并发下的数据一致性。
以下是MySQL数据库的核心表结构定义,直接执行以下SQL语句创建表:
```sql -- 用户关系表,记录推广关系 CREATE TABLE `user_relation` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `inviter_id` bigint(20) NOT NULL COMMENT '推广人ID', `invitee_id` bigint(20) NOT NULL COMMENT '被邀请人ID', `relation_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '关系类型:1-直接邀请', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_invitee` (`invitee_id`), KEY `idx_inviter` (`inviter_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户邀请关系表'; -- 佣金规则表 CREATE TABLE `commission_rule` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `rule_name` varchar(100) NOT NULL COMMENT '规则名称', `product_type` varchar(50) NOT NULL COMMENT '商品类型', `commission_type` tinyint(4) NOT NULL COMMENT '佣金类型:1-百分比,2-固定金额', `commission_value` decimal(10,2) NOT NULL COMMENT '佣金值', `level_limit` tinyint(4) NOT NULL DEFAULT 1 COMMENT '分成层级限制', `is_enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否启用', `effective_time` datetime NOT NULL COMMENT '生效时间', `expire_time` datetime DEFAULT NULL COMMENT '失效时间', PRIMARY KEY (`id`), KEY `idx_product_time` (`product_type`,`effective_time`,`expire_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='佣金规则表'; -- 订单佣金记录表 CREATE TABLE `order_commission` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `order_no` varchar(64) NOT NULL COMMENT '订单号', `order_amount` decimal(10,2) NOT NULL COMMENT '订单金额', `user_id` bigint(20) NOT NULL COMMENT '下单用户ID', `commission_amount` decimal(10,2) NOT NULL COMMENT '总佣金金额', `commission_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '佣金状态:0-待计算,1-已计算,2-已结算', `calc_time` datetime DEFAULT NULL COMMENT '计算时间', `settle_time` datetime DEFAULT NULL COMMENT '结算时间', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_order` (`order_no`), KEY `idx_user_status` (`user_id`,`commission_status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单佣金记录表'; -- 佣金分成明细表 CREATE TABLE `commission_detail` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `order_commission_id` bigint(20) NOT NULL COMMENT '订单佣金ID', `user_id` bigint(20) NOT NULL COMMENT '受益人ID', `level` tinyint(4) NOT NULL COMMENT '层级:1-一级,2-二级', `commission_rule_id` bigint(20) NOT NULL COMMENT '佣金规则ID', `commission_amount` decimal(10,2) NOT NULL COMMENT '分佣金额', `commission_rate` decimal(5,4) NOT NULL COMMENT '分佣比例', `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态:0-待结算,1-已结算', PRIMARY KEY (`id`), KEY `idx_order_commission` (`order_commission_id`), KEY `idx_user` (`user_id`,`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='佣金分成明细表'; ```使用Spring Boot 2.7+创建项目,在pom.xml中添加以下依赖:
```xml在application.yml中配置数据库和消息队列:
```yaml spring: datasource: url: jdbc:mysql://localhost:3306/commission_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true kafka: bootstrap-servers: localhost:9092 consumer: group-id: commission-group auto-offset-reset: earliest key-deserializer: org.apache.kafka.common.serialization.StringDeserializer value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer properties: spring.json.trusted.packages: "" redis: address: redis://localhost:6379 ```
在用户注册时,通过邀请码建立推广关系。创建UserRelationService.java:
```java @Service @Slf4j public class UserRelationService { @Autowired private UserRelationRepository userRelationRepository; @Autowired private RedisTemplate创建佣金规则管理接口,CommissionRuleController.java:
```java @RestController @RequestMapping("/api/commission/rule") public class CommissionRuleController { @Autowired private CommissionRuleRepository ruleRepository; @PostMapping("/create") public ApiResponse createRule(@RequestBody CommissionRuleDTO dto) { CommissionRule rule = new CommissionRule(); rule.setRuleName(dto.getRuleName()); rule.setProductType(dto.getProductType()); rule.setCommissionType(dto.getCommissionType()); rule.setCommissionValue(dto.getCommissionValue()); rule.setLevelLimit(dto.getLevelLimit()); rule.setEffectiveTime(dto.getEffectiveTime()); rule.setExpireTime(dto.getExpireTime()); rule.setIsEnabled(true); ruleRepository.save(rule); // 清除规则缓存 redisTemplate.delete("commission:rule:" + dto.getProductType()); return ApiResponse.success("规则创建成功"); } @GetMapping("/effective") public ApiResponse getEffectiveRules(String productType) { String cacheKey = "commission:rule:" + productType; String cached = redisTemplate.opsForValue().get(cacheKey); if (cached != null) { return ApiResponse.success(JSON.parseArray(cached, CommissionRule.class)); } LocalDateTime now = LocalDateTime.now(); List创建佣金计算服务,OrderCommissionService.java:
```java @Service @Slf4j public class OrderCommissionService { @Autowired private UserRelationService userRelationService; @Autowired private CommissionRuleRepository ruleRepository; @Autowired private OrderCommissionRepository orderCommissionRepository; @Autowired private CommissionDetailRepository detailRepository; @KafkaListener(topics = "order.created") @Transactional public void calculateCommission(String orderMessage) { OrderDTO order = JSON.parseObject(orderMessage, OrderDTO.class); // 1. 创建订单佣金记录 OrderCommission commission = new OrderCommission(); commission.setOrderNo(order.getOrderNo()); commission.setOrderAmount(order.getAmount()); commission.setUserId(order.getUserId()); commission.setCommissionStatus(0); orderCommissionRepository.save(commission); // 2. 获取用户的推广链 List创建定时结算任务,SettlementService.java:
```java @Service @Slf4j public class SettlementService { @Autowired private CommissionDetailRepository detailRepository; @Scheduled(cron = "0 0 1 ?") // 每天凌晨1点执行 @Transactional public void dailySettlement() { LocalDate settleDate = LocalDate.now().minusDays(1); Date startTime = Date.from(settleDate.atStartOfDay() .atZone(ZoneId.systemDefault()).toInstant()); Date endTime = Date.from(settleDate.plusDays(1).atStartOfDay() .atZone(ZoneId.systemDefault()).toInstant()); // 1. 查询待结算的佣金明细 List创建对账服务,ReconciliationService.java:
```java @Service public class ReconciliationService { public ReconciliationReport generateDailyReport(LocalDate date) { ReconciliationReport report = new ReconciliationReport(); report.setReportDate(date); // 1. 查询当日所有佣金明细 Date startTime = Date.from(date.atStartOfDay() .atZone(ZoneId.systemDefault()).toInstant()); Date endTime = Date.from(date.plusDays(1).atStartOfDay() .atZone(ZoneId.systemDefault()).toInstant()); List易频IT社区是综合性互联网IT技术门户网站,专注分享网络技术、服务器运维、网络安全、编程开发、系统架构、云计算、大数据等行业干货,实时更新IT行业资讯、零基础教程、实战案例,为IT从业者、技术爱好者提供专业的学习交流平台。
Copyright © 2021-2026 易频IT社区. All Rights Reserved. 备案号:闽ICP备2023013482号 网站地图