多商户折扣卡系统开发,跨门店权益核销方案

发布时间:2026/10/14 23:49:46
多商户折扣卡系统开发,跨门店权益核销方案
多商户折扣卡系统开发跨门店权益核销方案多商户折扣卡常见于同城联盟、商圈聚合、本地生活平台一张折扣卡可以在多家合作门店使用。和单店卡券不同跨门店核销需要管控卡的适用门店范围、防止重复核销、自动分账结算、商户数据隔离。很多项目上线后容易出现跨店权限失控、一码多刷、核销后分账错乱、商户看不到自己门店核销流水、卡范围配置混乱等问题。本文从业务痛点出发梳理跨门店核销完整实现方案附带Java核心核销代码适合多商户本地生活系统开发参考。业务痛点分析第一卡券适用门店管控混乱。通用卡、指定门店卡、商圈卡混在一起核销时没有精准校验出现卡不能在该门店使用却核销成功。 第二并发重复核销。多台核销设备同时扫同一张卡缺少原子控制造成一张卡多次扣减权益带来资金亏损。 第三发卡门店和核销门店分离结算逻辑复杂。A商户售卖的折扣卡用户到B商户门店核销需要自动计算B商户收益、平台服务费、发卡方分成人工对账效率低。 第四商户权限没有隔离。商户后台能看到其他门店的核销数据、用户信息存在数据泄露风险。 第五核销异常缺少补偿机制。网络抖动、PDA断网导致核销状态不一致前端提示失败但后台权益已经扣减引发客诉。 第六权益类型不统一。次卡、折扣卡、满减卡混用一套核销逻辑新增权益类型需要大量改动原有核销代码。模块整体流程设计跨门店核销模块拆分为卡模板门店配置、用户卡资产、核销校验中心、分账结算、核销流水、离线补偿六个子单元。 完整业务流程平台或者商户后台创建折扣卡模板配置卡的核销范围可选全部门店、指定门店分组、单门店用户购买领卡生成用户卡资产用户到合作门店出示核销码门店核销端提交核销请求核销中心依次校验卡状态、有效期、当前门店是否在可核销范围通过分布式锁防止重复核销校验通过后扣减权益生成核销流水MQ异步触发分账任务按预设分佣比例拆分资金商户后台查看属于本店的核销记录和结算明细网络异常场景记录核销单据后台提供人工撤销、补核销能力。 技术栈使用SpringBoot、MyBatisPlus、Redisson、Redis、RabbitMQRedis缓存卡的可用门店集合、用户卡状态分布式锁控制单张卡同一时间只能核销一次MQ异步处理分账通知避免核销主链路阻塞超时。核心数据表设计要点核心四张表折扣卡模板表、卡门店关联表、用户卡资产表、跨店核销流水表。 折扣卡模板表记录卡类型、权益规则、有效期、是否支持跨店卡门店关联表绑定模板ID与门店ID用来存储该卡允许核销的门店列表用户卡资产表记录用户持有卡、剩余次数、状态核销流水表保存核销码、用户卡ID、发卡商户ID、核销门店ID、核销金额、分账结果每一次扫码都新增一条流水流水不可删除。 所有核销、撤销操作都保留记录作为平台、商户财务对账的凭证。跨门店核销核心代码实现核销接口核心逻辑校验门店白名单、加分布式锁、原子更新卡状态防止重复核销。Service public class CrossStoreCardService { Autowired private UserCardMapper userCardMapper; Autowired private CardStoreRelMapper cardStoreRelMapper; Autowired private CardVerifyRecordMapper verifyRecordMapper; Autowired private RedissonClient redissonClient; Autowired private RabbitTemplate rabbitTemplate; Transactional(rollbackFor Exception.class) public ResultDTO verifyCard(String verifyCode, Long storeId, Long merchantId){ // 根据核销码查询用户卡资产 UserCard userCard userCardMapper.selectOne(Wrappers.lambdaQuery() .eq(UserCard::getVerifyCode, verifyCode)); if(userCard null || !userCard.getCardStatus().equals(0)){ return ResultDTO.fail(卡券不存在或已使用/已过期); } // 分布式锁防止同一张卡重复核销 RLock lock redissonClient.getLock(card:verify: userCard.getId()); boolean lockOk lock.tryLock(2, 10, TimeUnit.SECONDS); if(!lockOk){ return ResultDTO.fail(正在核销中请稍后重试); } try { // 校验当前门店是否在该卡允许核销门店范围内 Long relCount cardStoreRelMapper.selectCount(Wrappers.lambdaQuery() .eq(CardStoreRel::getTemplateId, userCard.getTemplateId()) .eq(CardStoreRel::getStoreId, storeId)); if(relCount 0){ return ResultDTO.fail(该卡不可在当前门店核销); } // 更新卡状态为已核销 userCard.setCardStatus(1); userCard.setUseStoreId(storeId); userCard.setVerifyTime(LocalDateTime.now()); userCardMapper.updateById(userCard); // 写入核销流水 CardVerifyRecord record new CardVerifyRecord(); record.setVerifyCode(verifyCode); record.setUserCardId(userCard.getId()); record.setSellMerchantId(userCard.getSellMerchantId()); record.setVerifyStoreId(storeId); record.setVerifyAmount(userCard.getFaceAmount()); record.setCreateTime(LocalDateTime.now()); verifyRecordMapper.insert(record); // 投递消息异步执行分账结算 rabbitTemplate.convertAndSend(card_settlement_exchange, card.settle, record.getId()); return ResultDTO.success(核销成功); } finally { if(lock.isHeldByCurrentThread()){ lock.unlock(); } } } }门店范围配置与权限隔离方案卡模板支持三种核销范围策略专属门店仅发卡门店可用、分组门店商圈A组、商圈B组、全联盟门店。门店配置可以后台可视化勾选修改后刷新Redis缓存不需要发版。 商户账号做数据行级隔离门店店员登录核销端只能核销分配给自己门店的卡商户后台查询核销报表时自动过滤其他门店的核销记录平台管理员拥有全部数据查看权限。商户无法查看其他商户的订单、用户手机号等隐私信息满足多商户入驻的数据安全要求。跨店分账与对账逻辑分账规则在卡模板提前配置支持设置核销门店分成、发卡商户分成、平台服务费。核销成功后异步结算任务读取规则生成分账明细。 区分两种典型场景门店自己售卖的卡在本店核销A门店售卖的卡在B门店核销。两种场景自动匹配不同分账比例。 同时支持撤销核销用户退款、门店误核销时管理员走撤销流程回滚卡状态并且生成反向冲销流水分账同步扣回资金。后台输出商户日结账单包含核销笔数、核销金额、服务费、实际结算金额方便商户核对。离线核销与异常补偿设计门店网络不稳定是线下核销高频问题方案支持离线预核销PDA本地暂存核销单据标记待同步网络恢复后自动上报到平台做二次校验。 离线单据有超时窗口超时未同步自动失效避免离线伪造核销记录。后台增加核销异常看板集中展示状态不一致的单据运营可以人工复核手动确认核销或者撤销降低客诉压力。风控、落地优化要点风控重点校验短时间高频核销同一张卡、跨商圈远距离核销LBS校验、批量伪造核销码、店员账号异地异常核销命中风控的单据标记预警暂停结算。 热点卡模板的门店范围缓存到Redis减少每次核销都查询数据库核销流水按月分表提升历史记录查询速度核销接口轻量化主链路只做状态变更和流水写入分账、通知、统计全部异步化保证扫码响应速度。 系统预留扩展除折扣卡之外可以复用这套核销中心对接次卡、团购券、会员权益一套核销能力给全部权益类型使用同时和分销模块打通核销完成后再结算推广佣金避免提前结算带来资金损失。这套跨门店核销方案适配同城商圈、多商户联盟类折扣卡项目解决跨店使用、重复核销、分账对账三大核心难题可以和渠道归因、卡券模板、分销结算模块集成快速搭建本地生活多商户平台。