GogoAI自助健身房团购核销模块设计与开发思路
痛点分析
自助健身房对接美团、抖音等团购渠道时,很容易遇到多种业务问题。团购券和自有会员卡体系隔离,券码校验、核销状态分散在第三方后台,运营人员需要跨平台核对;没有和门禁权限打通,核销之后还需要人工给会员开权限,不符合无人场馆的运营模式。
并发场景下容易出现一码多核销,缺少幂等控制;团购产品类型多,单次体验券、周卡、月卡、私教体验课规则各不相同,有效期、使用时段、跨店限制、限购次数配置复杂;核销之后课时、入场权限不能自动生效,退款、过期退款、验券失败的订单缺少统一状态机管理。连锁模式下,团购券要区分单店券和通用券,总部统一上架、门店独立核销,数据对账工作量大。同时团购回调不稳定,存在回调丢失、延迟,导致第三方显示已核销,但本地系统权益没有发放。
GogoAI团购核销模块对接主流团购平台开放接口,设计独立的券状态机,和会员、卡包、门禁权限、订单异常模块打通,实现验券、核销、发权益、门禁自动放行、对账全流程闭环,适配24小时无人自助场馆。
整体模块设计
团购核销模块分为渠道适配层、券核心服务层、权益分发层、对账与回调补偿层。
渠道适配层对不同平台的接口、回调格式做适配封装,新增渠道只需要新增适配器;券核心服务负责券状态流转、幂等校验、核销规则判断;权益分发层根据团购商品配置,自动发放体验资格、卡包、私教课时;对账补偿层处理回调丢失、状态不一致、退款同步。
核心数据表:group_product团购商品配置表、group_coupon团购券表、group_verify_record核销记录表、group_refund_record退款流水表。
券状态定义:未使用、已核销、已过期、已退款、核销失败。
商品维度支持配置:适用门店范围、限购数量、可用时段、是否跨店、核销后发放权益类型、过期自动退款开关。
核销校验核心Java代码实现
核销入口增加幂等控制,先查券状态,再通过事务保证核销和权益发放原子性,防止重复核销。
@Service@Slf4jpublicclassGroupVerifyService{@AutowiredprivateGroupCouponMappercouponMapper;@AutowiredprivateMemberCardServicememberCardService;@AutowiredprivateAccessAuthServiceaccessAuthService;@AutowiredprivateRabbitTemplaterabbitTemplate;@Transactional(rollbackFor=Exception.class)publicResultDTOverifyCoupon(GroupVerifyDTOdto){// 查询团购券GroupCouponcoupon=couponMapper.selectByCode(dto.getCouponCode());if(coupon==null){returnResultDTO.fail("团购券不存在");}// 状态校验if(!"UNUSED".equals(coupon.getStatus())){returnResultDTO.fail("券已核销/已退款,不可重复核销");}// 校验门店、有效期、使用限制if(!checkStoreLimit(coupon,dto.getStoreId())){returnResultDTO.fail("该券不支持在当前门店使用");}if(isExpired(coupon)){returnResultDTO.fail("团购券已过期");}// 更新券状态为已核销coupon.setStatus("VERIFIED");coupon.setVerifyTime(newDate());coupon.setVerifyStoreId(dto.getStoreId());couponMapper.updateById(coupon);// 根据商品配置自动发放对应权益GroupProductproduct=productMapper.selectById(coupon.getProductId());if("CARD".equals(product.getGiftType())){memberCardService.giveCardToMember(coupon.getMemberId(),product.getCardTemplateId());}elseif("LESSON".equals(product.getGiftType())){lessonService.addLesson(coupon.getMemberId(),product.getLessonNum());}// 同步生成临时通行权限,支持门禁扫码入场accessAuthService.createTempAuth(coupon.getMemberId(),dto.getStoreId(),product.getValidDay());// 投递消息,记录核销流水,通知对账服务rabbitTemplate.convertAndSend("group_exchange","group.verify",coupon);returnResultDTO.success("核销成功");}privatebooleancheckStoreLimit(GroupCouponcoupon,LongstoreId){GroupProductproduct=productMapper.selectById(coupon.getProductId());if("ALL".equals(product.getStoreScope())){returntrue;}returnproduct.getStoreIdList().contains(storeId);}}渠道适配器与回调补偿机制
不同团购平台的验券接口、回调参数、退款通知格式差异很大,使用适配器模式隔离差异,统一对外输出标准化券信息。适配器抽象方法包含验券、查询券状态、同步退款、查询商品库存。
平台异步回调是不稳定环节,很容易出现网络抖动导致回调丢失。方案采用双重保障:第一,回调接收后先落本地流水,返回成功给第三方,再异步执行业务逻辑;第二,定时补偿任务,定时拉取第三方平台券状态,对比本地库,状态不一致时自动修正。
例如第三方标记已核销但本地还是未使用,自动执行核销流程;第三方退款成功而本地券状态未更新,自动回收会员权益,锁死门禁通行权限。补偿任务做分片处理,避免全量拉取拖慢数据库。
自助核销的两种使用场景
第一种,会员端自助核销。会员在小程序输入券码或者跳转团购授权页面完成验券,核销成功后自动发放卡包、课时,即时获得门禁通行权限,直接扫码进场,全程不需要店员操作,适配无人场馆。
第二种,店长后台手动核销。店长后台输入券码或者扫码核销,适合线下接待场景;后台支持查看核销记录、导出核销明细。核销操作记入审计日志,总部可以查看全部门店核销数据,门店店长只能查看本店核销记录。
同时支持预约类团购产品,比如私教体验课,核销之后自动生成一条待预约记录,会员可以直接在约课模块预约教练时段,核销记录和排课数据打通。
退款、过期与限购控制
退款分为用户主动退款、平台超时自动退款。退款触发时,同步执行权益回收:刚核销还未入场的团购券,回收门禁权限;已经入场消耗的体验券,不支持退款。
限购控制在两层拦截:平台侧设置限购,本地模块二次校验会员历史购买和核销记录,防止刷券。
过期任务由定时任务扫描,过期券更新状态,配置了过期自动退款的商品,自动调用平台退款接口发起退款。
对账与连锁管控
连锁场景下商品分为总部通用商品和门店专属商品。总部统一创建团购商品模板,下发到门店;门店可以单独上架本店团购。核销流水按门店隔离,总部后台可以汇总所有门店核销、退款、营收数据,生成渠道对账报表,统计渠道佣金、核销率、退款率。
报表区分已核销、已退款、待补偿数据,导出流水用来和平台结算对账。权限复用多门店数据拦截器,门店账号不能查看其他门店核销和财务数据。
和其他模块联动逻辑
和会员卡包模块联动,核销自动发卡、发课时;
和门禁IoT权限模块联动,核销成功生成通行凭证,支持自助入场;
和私教排课模块联动,私教体验券核销后支持预约私教;
和订单异常模块联动,核销失败、状态不一致的券进入异常工单,运营人工处理;
和消息推送模块联动,核销成功、退款成功、券即将过期推送通知给会员。
开发落地踩坑总结
第一,第三方回调一定要先持久化再执行业务,不要业务处理失败后给平台返回成功,造成两边状态不一致;
第二,核销方法必须加事务和幂等判断,不能只依赖第三方平台防重;
第三,自助核销后门禁权限有效期要和商品配置对齐,不能永久放行;
第四,补偿拉取不要高频全量同步,按券的创建时间分片,控制接口调用频率,避免触发平台限流;
第五,区分通用券和单店券,跨门店核销时提前做好规则拦截,避免会员在不支持门店核销。
落地效果总结
团购核销模块已经对接多个自助健身门店的抖音、美团团购渠道,把第三方券码和场馆内部会员体系、门禁权限打通,实现无人场景自助验券核销,不需要人工介入。适配器模式降低新增渠道的开发成本,补偿机制解决回调丢失带来的数据不一致问题。
核销流水、退款流水集中汇总,大幅降低财务对账成本。整套模块和卡包、排课、IoT门禁、多门店管理系统深度结合,形成从引流团购、自助核销、进场体验到数据对账的完整链路,是自助场馆线上获客环节的核心支撑。