核心内容摘要
开源人脸检测工具对比评测:MogFace vs MTCNN vs RetinaFace在复杂场景表现
电商返利系统中佣金计算的幂等性保障与对账补偿机制实现大家好我是 微赚淘客系统
0 的研发者省赚客在微赚淘客系统
0中用户通过专属推广链接下单后平台需从电商平台如淘宝联盟、京东联盟获取订单佣金并按规则分发给推广者。
由于涉及异步回调、网络重试、第三方数据延迟等复杂场景佣金计算极易出现重复入账或漏算问题。
为此我们设计了一套基于唯一业务ID、状态机与定时对账的幂等性保障与补偿机制。
幂等性设计基于唯一业务标识与状态机每笔有效订单在系统内对应一个commission_record表记录其主键为平台生成的全局唯一ID如comm_20260128_abc123但核心幂等依据是第三方订单号third_order_id 佣金类型如“预估”、“结算”的联合唯一索引。
packagejuwatech.cn.commission.entity;importjavax.persistence.*;EntityTable(namecommission_record,uniqueConstraintsUniqueConstraint(columnNames{third_order_id,commission_type}))publicclassCommissionRecord{IdprivateStringid;// comm_xxxColumn(nullablefalse)privateStringthirdOrderId;// 淘宝/京东订单号Column(nullablefalse)privateStringcommissionType;// ESTIMATED, SETTLEDEnumerated(EnumType.STRING)privateStatusstatus;// PENDING, SUCCESS, FAILEDprivateLongamount;// 分为单位privateStringuserId;}在处理回调时先尝试插入记录若因唯一约束冲突抛出异常则视为重复请求直接返回成功packagejuwatech.cn.commission.service;importjuwatech.cn.commission.entity.CommissionRecord;importjuwatech.cn.commission.repo.CommissionRepo;importorg.springframework.dao.DataIntegrityViolationException;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;ServicepublicclassCommissionService{privatefinalCommissionReporepo;privatefinalAccountServiceaccountService;publicCommissionService(CommissionReporepo,AccountServiceaccountService){this.reporepo;this.accountServiceaccountService;}TransactionalpublicvoidhandleCommissionCallback(StringthirdOrderId,Stringtype,Longamount,StringuserId){CommissionRecordrecordnewCommissionRecord();record.setId(comm_System.currentTimeMillis()_userId.substring(0,
);record.setThirdOrderId(thirdOrderId);record.setCommissionType(type);record.setAmount(amount);record.setUserId(userId);record.setStatus(CommissionRecord.Status.PENDING);try{repo.save(record);// 触发唯一索引检查}catch(DataIntegrityViolationExceptione){// 幂等已存在相同 thirdOrderId type直接返回return;}// 执行入账accountService.credit(userId,amount);record.setStatus(CommissionRecord.Status.SUCCESS);repo.save(record);}}
对账补偿定时任务比对三方数据即使有幂等控制仍可能因网络超时导致“本地未记录但三方已成功”的漏单。
因此我们引入每日对账任务从电商平台拉取前一日所有有效订单与本地记录比对补录缺失数据。
packagejuwatech.cn.commission.task;importjuwatech.cn.commission.client.AffiliateClient;importjuwatech.cn.commission.entity.ThirdOrderDTO;importjuwatech.cn.commission.repo.CommissionRepo;importjuwatech.cn.commission.service.CommissionService;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Component;importjava.time.LocalDate;importjava.util.List;importjava.util.Set;importjava.util.stream.Collectors;ComponentpublicclassCommissionReconciliationTask{privatefinalAffiliateClientaffiliateClient;privatefinalCommissionRepocommissionRepo;privatefinalCommissionServicecommissionService;publicCommissionReconciliationTask(AffiliateClientaffiliateClient,CommissionRepocommissionRepo,CommissionServicecommissionService){this.affiliateClientaffiliateClient;this.commissionRepocommissionRepo;this.commissionServicecommissionService;}Scheduled(cron0 0 2 * * ?)// 每天凌晨2点执行publicvoidreconcileYesterday(){LocalDatedateLocalDate.now().minusDays(
;ListThirdOrderDTOremoteOrdersaffiliateClient.queryOrders(date);SetStringremoteOrderIdsremoteOrders.stream().map(ThirdOrderDTO::getOrderId).collect(Collectors.toSet());ListStringlocalOrderIdscommissionRepo.findThirdOrderIdsByDate(date);// 找出远程有但本地无的订单remoteOrderIds.removeAll(localOrderIds);for(StringmissingOrderId:remoteOrderIds){ThirdOrderDTOorderremoteOrders.stream().filter(o-o.getOrderId().equals(missingOrderId)).findFirst().orElse(null);if(order!nullorder.getAmount()
{commissionService.handleCommissionCallback(order.getOrderId(),SETTLED,order.getAmount(),order.getUserId());}}}}其中findThirdOrderIdsByDate对应的 JPQL 如下// 在 CommissionRepo 中Query(SELECT c.thirdOrderId FROM CommissionRecord c WHERE DATE(c.createTime) :date)ListStringfindThirdOrderIdsByDate(Param(date)LocalDatedate);
补偿操作的幂等与事务安全对账补录调用的是同一handleCommissionCallback方法天然具备幂等性。
同时为防止补偿过程中再次失败我们在AccountService.credit中也加入幂等校验packagejuwatech.cn.commission.service;importjuwatech.cn.commission.repo.AccountLogRepo;importorg.springframework.transaction.annotation.Transactional;ServicepublicclassAccountService{privatefinalAccountLogRepologRepo;Transactionalpublicvoidcredit(StringuserId,Longamount){StringbizIdcredit_userId_amount;if(logRepo.existsByBizId(bizId)){return;// 已入账}// 执行DB余额更新updateBalanceInDB(userId,amount);// 记录流水logRepo.save(newAccountLog(bizId,userId,amount));}}
监控与告警我们通过 Prometheus 监控以下指标commission_duplicate_count重复回调次数reconciliation_missing_count对账发现的漏单数compensation_success_rate补偿成功率当漏单率超过阈值如
5%自动触发企业微信告警通知运维介入排查。
通过上述机制系统在近半年运行中佣金计算准确率达到
9
998%有效保障了平台与推广者的资金安全。
本文著作权归 微赚淘客系统