在本地生活服务场景中,碰碰好评卡是商家提升用户好评率、拉动复购的常用运营工具,近期我们团队完成了一套可支持多商家、多端访问的碰碰好评卡系统从需求拆解到全量上线的完整开发,本文将从技术视角分享全流程的实战经验,为同类系统的开发提供可复用的落地思路。
需求拆解与核心功能建模
碰碰好评卡的核心业务逻辑是:用户完成线下消费后,商家发放实体NFC碰卡或电子好评卡,用户扫码/碰卡完成好评提交后,可激活对应权益(优惠券、免单资格、积分等),后续到店消费时可核销使用。我们首先对需求做了角色拆分和流程抽象,避免后续开发出现逻辑遗漏。
角色与功能划分
参考多角色服务系统的设计思路,我们将系统拆分为三类角色的功能集合:
- 用户端:支持扫码/碰卡激活、好评凭证提交、卡包权益查询、核销码展示、权益消费记录查询等功能,需兼容小程序、公众号H5、iOS、Android多端访问,满足不同用户的使用习惯。
- 商家端:支持好评卡批量生成、权益规则配置、核销核验、订单数据统计、门店信息管理等功能,采用H5开发,商家无需下载APP即可通过浏览器操作。
- 平台管理端:支持商家准入审核、卡模板全局配置、运营数据大盘查看、风控规则调整等功能,为平台运营人员提供全链路的管控能力。
核心流程与状态机设计
我们梳理了核心业务的流转链路:用户到店消费→商家发放好评卡→用户扫码绑定对应消费订单→提交好评凭证→系统/商家审核→权益生效→用户到店核销。
为了避免状态错乱,我们为好评卡设计了明确的状态机:未发放→待激活→待审核→已生效→已核销→已过期,每个状态的流转仅能通过指定操作触发,比如只有待审核状态的卡审核通过后才能进入已生效状态,所有状态变更都要记录操作日志,方便后续问题排查。
技术架构选型与分层设计
结合团队的技术栈积累和系统的多端支持需求,我们选择了成熟的Java生态技术方案,兼顾开发效率和系统稳定性:
技术栈选型
- 后端服务:采用Spring Boot + JPA + MySQL的组合,Spring Boot的开箱即用特性可以快速搭建服务框架,JPA简化ORM层开发,适合业务快速迭代的场景,MySQL作为关系型数据库存储核心业务数据,支持事务保证数据一致性。
- 用户端:采用UniApp开发,一套代码可以编译到小程序、H5、iOS、Android等多个端,大幅减少多端重复开发的工作量,同时可以快速适配不同端的特性。
- 管理端:采用Vue + ElementUI的组合,组件库丰富,开发效率高,适合内部管理系统的快速搭建。
- 中间件:使用Redis做缓存,存储活跃用户的卡包数据、验证码、风控规则;使用RabbitMQ做异步解耦,将消息推送、数据统计更新等非核心流程异步处理,减少主流程的响应时间。
分层架构设计
我们将系统分为四层,各层职责明确,模块解耦便于后续扩展:
- 表现层:对接多端用户请求,负责参数校验、权限校验,返回统一格式的响应,配置全局异常处理器,统一处理业务异常和系统异常,避免敏感信息泄露。
- 业务层:处理核心业务逻辑,封装好评卡生成、激活审核、权益核销、风控校验等核心能力,每个模块通过接口抽象实现,方便后续业务迭代时快速替换实现逻辑。
- 数据访问层:基于JPA实现数据的增删改查,复杂查询使用@Query注解自定义SQL,避免JPA自动生成的SQL性能过差的问题。
- 基础服务层:封装通用的工具能力,包括文件上传、位置服务、OCR识别、消息推送等,多个业务模块可以复用这些能力,减少重复开发。
核心模块开发实战
好评卡批量生成模块
商家可以自定义权益类型、有效期、发放数量,批量生成好评卡,每张卡生成的16位卡号和6位核销码,数据库层面给卡号加索引,防止重复卡生成。核心代码示例如下:
@ServicepublicclassCardService{@AutowiredprivateCardRepositorycardRepository;@Transactional(rollbackFor=Exception.class)publicList<Card>batchGenerateCard(CardGenerateDTOdto,LongmerchantId){List<Card>cardList=newArrayList<>();// 批量生成卡,每次多生成10000张,避免单次操作耗时过长intgenerateCount=Math.min(dto.getCount(),10000);for(inti=0;i<generateCount;i++){Cardcard=newCard();// 生成16位卡号card.setCardNo(UUID.randomUUID().toString().replace("-","").substring(0,16));// 生成6位数字核销码card.setVerifyCode(RandomUtil.randomNumbers(6));card.setMerchantId(merchantId);card.setBenefitType(dto.getBenefitType());card.setBenefitContent(dto.getBenefitContent());card.setExpireTime(dto.getExpireTime());card.setStatus(CardStatusEnum.UNISSUED.getCode());cardList.add(card);}returncardRepository.saveAll(cardList);}}权益核销模块
核销是核心的敏感操作,我们设计了多重校验逻辑,避免出现资损:首先校验卡的状态是否为已生效,其次校验当前操作的用户是否为卡的绑定持有人,然后如果是到店核销场景,调用位置服务校验用户当前位置和商家门店位置的距离是否在指定范围内,后校验卡的有效期是否有效。所有校验通过后才可以完成核销,同时扣减对应权益,记录核销日志,整个操作包裹在事务中,保证原子性,避免重复核销的问题。
风控模块
为了防止恶意刷好评卡的情况,我们配置了多层风控规则:每个消费订单只能绑定一张好评卡,数据库层面给订单ID加索引;同一个用户7天内只能领取同一个商家的一张好评卡;提交的好评凭证通过OCR识别关键词,防止用户提交无效截图。所有规则支持在管理端动态配置,无需发版即可调整规则阈值。
上线前测试与性能优化
测试覆盖
我们完成了全链路的功能测试,覆盖卡生成、激活、审核、核销、过期的所有流程,同时做了多端兼容性测试,覆盖主流手机机型、小程序版本、浏览器版本,避免出现适配问题。性能测试阶段使用JMeter对核销接口做压测,初始压测结果为300QPS,响应时间500ms,不满足业务预期,我们针对性做了性能优化。
优化方案
- 缓存优化:将已生效的好评卡数据缓存到Redis,缓存有效期和卡的有效期保持一致,查询卡信息时先查缓存,缓存未命中再查DB,大幅减少DB查询压力,优化后接口响应时间降低到150ms。
- 数据库优化:给高频查询的字段(卡号、商家ID、用户ID、状态)加索引,复杂查询拆分为单表查询,避免多表联查超过3张表,JPA查询时使用fetch join避免N+1问题,慢SQL占比从15%降低到1%以下。
- 异步优化:将非核心流程比如消息推送、数据统计更新改成异步处理,通过RabbitMQ解耦,主流程不再等待非核心操作完成,接口QPS提升到1200,满足业务峰值需求。
上线时采用灰度发布策略,先开放给小范围商家试点,观察系统运行7天无异常后再全量上线,上线后通过Prometheus + Grafana监控接口响应时间、错误率、DB连接数等核心指标,出现异常及时告警处理,目前系统运行稳定,支持多场景的好评卡运营需求。