// ReferralCodeServiceImpl.createCode()
@Transactional
public ReferralCodeRes createCode(ReferralCodeCreateReq req) {
// 生成唯一 6 位推薦碼
String code = generateUniqueCode();
ReferralCode referralCode = new ReferralCode();
referralCode.setId(UUID.randomUUID().toString());
referralCode.setCode(code);
referralCode.setStoreId(req.getStoreId());
referralCode.setBonusPerUse(req.getBonusPerUse() != null ? req.getBonusPerUse() : DEFAULT_BONUS_PER_USE);
referralCode.setMaxUsage(req.getMaxUsage() != null ? req.getMaxUsage() : DEFAULT_MAX_USAGE);
referralCode.setUsageCount(0);
referralCode.setIsActive(1);
referralCode.setCreatedAt(LocalDateTime.now());
referralCodeMapper.insert(referralCode);
return toRes(referralCode);
}
private String generateUniqueCode() {
String chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; // 去掉易混淆字符 O, 0, I, 1
for (int attempt = 0; attempt < 10; attempt++) {
StringBuilder code = new StringBuilder();
for (int i = 0; i < 6; i++) {
code.append(chars.charAt(ThreadLocalRandom.current().nextInt(chars.length())));
}
// 檢查唯一性
ReferralCodeExample example = new ReferralCodeExample();
example.createCriteria().andCodeEqualTo(code.toString());
if (referralCodeMapper.selectByExample(example).isEmpty()) {
return code.toString();
}
}
throw new BusinessException("推薦碼生成失敗,請重試");
}
// ReferralCodeServiceImpl.bindReferralCode()
@Transactional
public void bindReferralCode(String newUserId, String code) {
// 1. 查詢推薦碼
ReferralCodeExample example = new ReferralCodeExample();
example.createCriteria().andCodeEqualTo(code.toUpperCase()).andIsActiveEqualTo(1);
List<ReferralCode> codes = referralCodeMapper.selectByExample(example);
if (codes.isEmpty()) {
log.warn("⚠️ 推薦碼不存在或已停用: {}", code);
return; // 靜默失敗,不影響主流程
}
ReferralCode referralCode = codes.get(0);
// 2. 驗證有效性
if (referralCode.getMaxUsage() > 0 && referralCode.getUsageCount() >= referralCode.getMaxUsage()) {
log.warn("⚠️ 推薦碼已達上限: {}", code);
return;
}
if (referralCode.getExpiresAt() != null && referralCode.getExpiresAt().isBefore(LocalDateTime.now())) {
log.warn("⚠️ 推薦碼已過期: {}", code);
return;
}
// 3. 防止重複綁定(一個用戶只能使用一次推薦碼)
ReferralRecordExample recordExample = new ReferralRecordExample();
recordExample.createCriteria()
.andNewUserIdEqualTo(newUserId)
.andReferralCodeIdEqualTo(referralCode.getId());
if (!referralRecordMapper.selectByExample(recordExample).isEmpty()) {
return; // 已綁定過,靜默跳過
}
// 4. 建立綁定記錄
ReferralRecord record = new ReferralRecord();
record.setId(UUID.randomUUID().toString());
record.setReferralCodeId(referralCode.getId());
record.setNewUserId(newUserId);
record.setBonusAwarded(referralCode.getBonusPerUse());
record.setCreatedAt(LocalDateTime.now());
referralRecordMapper.insert(record);
// 5. 發放紅利給新用戶
walletService.addBonus(newUserId, referralCode.getBonusPerUse(), "REFERRAL", referralCode.getId(), "推薦碼獎勵");
// 6. 更新使用次數
referralCode.setUsageCount(referralCode.getUsageCount() + 1);
referralCode.setUpdatedAt(LocalDateTime.now());
referralCodeMapper.updateByPrimaryKey(referralCode);
log.info("✅ 推薦碼綁定成功: newUserId={}, code={}, bonus={}", newUserId, code, referralCode.getBonusPerUse());
}