文旅系统搭建方案景点套餐分销功能实现景点套餐分销是智慧文旅系统里重要的拓客模块套餐一般包含多景点联票、门票观光车、门票民宿等组合产品支持旅行社、本地达人、私域团长推广裂变。和普通商品分销不同套餐分销需要和分时预约库存、实名入园、退票核销深度联动。很多项目开发后容易出现套餐佣金配置不独立、退票无法冲销佣金、分销关系被覆盖、套餐库存和单票库存冲突、对账困难等问题。本文从业务痛点出发梳理整套套餐分销实现方案附带Java核心代码方便源码开发和二次集成。业务痛点分析第一套餐和单品佣金规则混用。不同套餐利润空间不一样统一佣金比例会出现部分套餐亏损、高利润套餐激励不足。 第二分销关系绑定不稳定。游客多次点击不同推广链接上级推广人被替换推广员收益错乱打击达人推广积极性。 第三退票、过期订单佣金处理缺失。套餐下单后生成佣金游客退票或者套餐过期失效佣金没有逆向冲销造成资金损失。 第四套餐库存管控割裂。分销下单独立扣库存没有接入景区分时承载分销爆单后出现时段超约无法入园。 第五分销权限和数据没有隔离。多个旅行社共用一套数据A旅行社能看到B旅行社的订单和佣金存在数据泄露风险。 第六缺少分销风控。黑产批量注册分销账号囤套餐票、批量退票套取佣金平台损耗严重。模块整体流程设计套餐分销模块拆分为套餐分销配置、推广关系绑定、订单分佣计算、佣金冻结解冻、逆向冲销、分销看板几个子单元和预约订单、时段库存、核销模块共用一套资源。 整体流程后台上架景点套餐单独配置套餐分销比例、分销开关、可推广人群推广员生成带推广ID的分享海报、链接游客点击链接进入小程序首次访问绑定上下级关系游客购买套餐支付成功后触发分佣计算佣金进入冻结池套餐核销完成且超过退票窗口期佣金解冻到可提现余额游客发起退票或者套餐过期执行佣金作废或者冲销推广员在工作台查看订单明细、佣金流水发起提现。 技术栈使用SpringBoot、MyBatisPlus、Redis、MQRedis缓存套餐分销配置、推广关系MQ异步处理分佣、冲销消息避免支付回调超时。核心数据表设计要点核心四张表套餐分销配置表、用户推广关系表、套餐佣金流水表、分销员账户表。 套餐分销配置表绑定套餐ID记录该套餐是否开启分销、各级佣金比例、退票是否扣回佣金用户推广关系表记录用户和上级推广人用户只绑定一次上级佣金流水表以套餐订单号作为唯一索引记录每一笔分佣、冲销记录分销员账户表区分冻结佣金、可提现佣金独立统计。 所有佣金变更都留存流水日志不和订单主表直接修改满足财务对账和追溯需求。套餐下单分佣核心代码实现订单支付回调成功之后触发分佣逻辑先读取套餐独立分销配置获取推广链路使用分布式锁做幂等控制防止同一套餐订单重复分佣。Service public class PackageCommissionService { Autowired private PackageDistributeConfigMapper distributeConfigMapper; Autowired private UserPromoteRelationMapper promoteRelationMapper; Autowired private CommissionRecordMapper commissionRecordMapper; Autowired private RedissonClient redissonClient; private static final String COMMISSION_LOCK_PREFIX tour:package:commission:; Transactional(rollbackFor Exception.class) public void calcPackageCommission(String orderNo, Long packageId, Long buyUserId, BigDecimal payAmount){ RLock lock redissonClient.getLock(COMMISSION_LOCK_PREFIX orderNo); try { boolean lockFlag lock.tryLock(2, 8, TimeUnit.SECONDS); if(!lockFlag){ return; } // 幂等校验避免重复分佣 CommissionRecord existRecord commissionRecordMapper.selectOne(Wrappers.lambdaQuery() .eq(CommissionRecord::getOrderNo, orderNo)); if(existRecord ! null){ return; } // 查询套餐独立分销配置 PackageDistributeConfig config distributeConfigMapper.selectOne(Wrappers.lambdaQuery() .eq(PackageDistributeConfig::getPackageId, packageId) .eq(PackageDistributeConfig::getEnable, 1)); if(config null){ return; } // 获取推广链路 ListUserPromoteRelation relationChain getPromoteChain(buyUserId); for(UserPromoteRelation item : relationChain){ BigDecimal rate getRateByLevel(config, item.getLevel()); BigDecimal commission payAmount.multiply(rate); CommissionRecord record new CommissionRecord(); record.setOrderNo(orderNo); record.setPackageId(packageId); record.setPromoterId(item.getPromoterId()); record.setBuyUserId(buyUserId); record.setCommissionAmount(commission); record.setStatus(0); //0冻结待结算 record.setCreateTime(LocalDateTime.now()); commissionRecordMapper.insert(record); } }catch (Exception e){ log.error(套餐分佣异常订单号{},orderNo,e); throw e; }finally { if(lock.isHeldByCurrentThread()){ lock.unlock(); } } } }佣金解冻、退票逆向冲销逻辑佣金不能在支付完成直接提现需要等待套餐核销、退票窗口期结束定时任务批量解冻冻结佣金。 分两种退票场景 佣金处于冻结状态退票成功后直接标记佣金记录作废不会计入分销员可提现余额风险最低。 佣金已经解冻提现生成负向冲销流水优先从该分销员后续套餐佣金中抵扣无法抵扣的订单进入后台人工复核。 后台支持配置部分特价套餐可以设置退票不扣回佣金适配景区营销活动。分销员工作台与权限隔离分销员分为普通达人、签约旅行社两种类型旅行社账号可以开通子账号给导游分配推广权限。每个分销员只能查看自己推广产生的套餐订单、佣金明细看不到其他分销员数据和景区基础营收。 工作台功能包含推广海报生成、套餐预览、订单列表、佣金明细、提现记录海报链接携带分销员ID参数扫码后自动绑定推广关系。 后台可以单独对套餐关闭分销也可以单独禁用某个分销员推广权限快速管控违规推广账号。套餐分销和库存核销联动设计分销下单和普通购票走同一个预约库存中心不管是分销渠道、官方小程序下单统一扣减分时时段名额。套餐内包含多个景点的核销时按套餐子项单独核验只要套餐订单状态正常分销佣金逻辑不受单景点核销顺序影响。 核销系统回调订单服务后更新订单核销状态作为佣金解冻的前置条件未核销套餐订单不会自动结算佣金。风控、看板和落地优化要点风控重点监控同一分销账号短时间大量出单、下单后快速退票、同一个实名信息多次通过不同分销链接购买套餐命中风控的分销账号暂停结算佣金转入人工审核。 分销数据看板统计每个套餐的推广订单、核销数量、退票率、佣金支出按分销员、渠道分组统计评估套餐分销ROI。 套餐分销配置缓存到Redis修改配置实时刷新不需要发布版本佣金流水表按月分表存储减少大数据量查询压力预留对外接口支持OTA渠道、本地生活平台接入套餐分销。 分销层级严格按照合规要求配置后台可以一键开关分销功能限制推广文案规避违规宣传风险。这套方案把景点套餐分销和景区预约、核销、库存体系打通既可以用来旅行社批量拓客也适合达人私域裂变和之前的预约订单、线上营销模块可以无缝组合适配智慧文旅项目长期迭代。
阅读完成 · 觉得有帮助?