☰
陕西GogoAI自助健身小程序核销功能开发解析
2026/10/16 12:08:00 网站建设 项目流程

陕西GogoAI自助健身小程序核销功能开发解析

24小时自助健身的核销不同于传统门店人工核验,核销链路直接关联次卡扣减、门禁开闸、AI训练权限下发。小程序端支持扫码核销、券码核销、人脸核销多种入场方式,在弱网、用户重复提交、门禁指令下发超时场景下,极易出现多次扣卡、核销成功但门禁不开闸、核销状态不一致问题。本文结合陕西GogoAI自助健身小程序落地实践,拆解核销核心链路、并发控制、幂等防护以及和门禁设备联动的实现方案。

自助健身核销业务痛点

自助场馆核销的核心矛盾在于业务和硬件联动,链路变长之后异常点增多。首先是并发重复核销,用户扫码后网络卡顿反复点击,或者扫码枪连续上报,导致同一张次卡连续扣减多次。其次是分布式事务问题,数据库次卡次数扣减成功,但是门禁下发指令超时,出现“次数扣了、门没开”。还有跨门店权限校验,会员在A门店购买的次卡,不能在未授权的B门店核销,需要结合多租户storeId做门店隔离。核销凭证存在有效期,过期券码需要直接拦截;同时核销记录要和订单、体测、训练记录打通,支撑后续的数据对账和运营报表。

单纯依靠前端按钮置灰无法保障安全,前端容易被绕过,所有核销校验、扣减、设备指令逻辑都收敛在后端服务。

核销整体链路与状态流转设计

核销链路流程:小程序提交核销凭证 → 后端验签、解析核销码 → 校验券状态、有效期、门店权限、剩余次数 → 状态机校验流转 → 原子扣减次卡次数、生成核销流水 → 异步下发门禁开闸指令 → 返回核销结果给小程序。
定义核销凭证状态:UNUSED待核销、REDEEMING核销中、REDEEMED已核销、EXPIRED已过期、CANCELLED已作废。
增加REDEEMING中间态是关键,防止两个并发请求同时读到UNUSED,同时进入扣减逻辑。合法流转路径固定为:UNUSED → REDEEMING → REDEEMED;核销中如果门禁下发失败,可以回滚为UNUSED,支持用户重新核销。

数据库模型与乐观锁并发控制

核心包含券主表和核销流水表,流水表记录每一次核销动作,作为对账的唯一凭证。券表使用version版本号做乐观锁,避免并发扣次超卖。
券记录DO核心字段示例:

@Data @TableName("fitness_voucher") public class FitnessVoucher { @TableId(type = IdType.ASSIGN_ID) private Long id; /** 门店ID,多门店隔离 */ private String storeId; /** 关联订单号 */ private String orderNo; /** 核销券码 */ private String redeemCode; /** 剩余次数 */ private Integer remainCount; /** 券状态 */ private String voucherStatus; /** 有效期开始 */ private LocalDateTime validStartTime; /** 有效期结束 */ private LocalDateTime validEndTime; /** 乐观锁版本号 */ @Version private Integer version; }

核销流水表增加唯一索引(redeemCode + redeemSerialNo),redeemSerialNo由小程序端或者网关生成,作为本次核销的幂等编号,从数据库层面拦截重复核销记录写入。

Java核销核心服务逻辑实现

核销接口入参携带核销码、门店编号、幂等流水号,后端先做幂等校验,再走状态机和乐观锁更新。简化业务代码如下:

@Service public class VoucherRedeemService { @Autowired private FitnessVoucherMapper voucherMapper; @Autowired private RedeemLogMapper redeemLogMapper; @Autowired private AccessGateClient gateClient; @Transactional(rollbackFor = Exception.class) public Result<String> redeem(String redeemCode, String storeId, String redeemSerialNo) { // 幂等判断:流水已存在直接返回成功 RedeemLog existLog = redeemLogMapper.selectBySerialNo(redeemSerialNo); if(existLog != null){ return Result.success("已核销"); } FitnessVoucher voucher = voucherMapper.selectByCodeAndStore(redeemCode, storeId); if(voucher == null){ return Result.fail(4001,"券不存在或不属于当前门店"); } // 状态机校验 if(!"UNUSED".equals(voucher.getVoucherStatus())){ return Result.fail(4002,"券不可核销"); } if(voucher.getRemainCount() <= 0){ return Result.fail(4003,"次数已用完"); } // 乐观锁原子更新:扣减次数,状态改为核销中 int update = voucherMapper.redeemLock(voucher.getId(), voucher.getVersion()); if(update <= 0){ return Result.fail(4004,"核销冲突,请重试"); } // 写入核销流水 RedeemLog log = new RedeemLog(); log.setRedeemCode(redeemCode); log.setRedeemSerialNo(redeemSerialNo); log.setStoreId(storeId); log.setRedeemTime(LocalDateTime.now()); redeemLogMapper.insert(log); // 异步调用门禁开闸 gateClient.asyncOpenGate(storeId, voucher.getMemberId()); return Result.success("核销成功,门禁已下发指令"); } }

门禁开闸采用异步调用,不阻塞主核销事务;门禁回调通知服务之后,再把券状态从REDEEMING更新为REDEEMED。如果门禁超时无回调,后台补偿任务自动回滚券状态,释放次数。

多核销方式适配与安全校验

小程序支持三种核销入口:会员二维码、购买的次卡券码、团购兑换码。二维码属于动态凭证,后端实时生成短时效token,几分钟自动失效,防止截图复用。
所有核销请求强制带上storeId,结合之前项目的租户上下文拦截器,门店操作员只能核销本店的券。接口增加签名校验,小程序请求参数加时间戳和签名,防止被抓包伪造核销请求。人脸核销作为扩展能力,对接人脸比对服务,比对通过之后自动生成虚拟核销流水,逻辑和扫码核销复用同一套核销服务,不用重复开发扣次和状态流转代码。

异常补偿与核销对账方案

自助场景门禁、网络不稳定是常态,单独依靠同步调用风险很高。项目采用MQ异步下发门禁指令,消费端记录指令状态,超时未收到门禁成功回调的任务,进入补偿队列,重试2-3次,多次失败标记异常工单,门店后台可以手动重新触发开闸或者回退本次核销。
每日凌晨自动执行核销对账,比对订单、券表、核销流水、门禁通行记录,找出单边账:流水存在但是门禁没有开门记录、门禁开门但是没有核销记录。对账差异数据形成报表,运营人员核对后做补扣或者次数返还。所有核销日志保留traceId,串联小程序请求、数据库更新、MQ消息、门禁回调日志,方便快速排查。

落地总结

这套核销方案在陕西多家24小时自助健身门店上线,核心思路是状态机规范流转、乐观锁控制并发、幂等流水防重复、异步解耦硬件设备。小程序端只负责展示凭证和收集扫码动作,核心校验全部下沉后端,兼顾安全性和自助场景的弱网适配。
和传统健身房核销对比,自助核销最大的难点就是业务系统和物联网门禁设备的协同。在GogoAI健身小程序迭代中,核销模块可以继续扩展第三方团购券接入、时段预约核销,整套核销底层逻辑可以复用,减少重复开发工作量。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询