|
@@ -49,6 +49,10 @@ public class InviteService {
|
|
|
@Value("${invite.base-url:https://app.zhijiayun.com}")
|
|
@Value("${invite.base-url:https://app.zhijiayun.com}")
|
|
|
private String inviteBaseUrl;
|
|
private String inviteBaseUrl;
|
|
|
|
|
|
|
|
|
|
+ /** 桌面客户端下载基础URL,为空时自动从 inviteBaseUrl 推断域名 */
|
|
|
|
|
+ @Value("${invite.desktop-download-base-url:}")
|
|
|
|
|
+ private String desktopDownloadBaseUrl;
|
|
|
|
|
+
|
|
|
/** 补填邀请码有效窗口(天),默认30天 */
|
|
/** 补填邀请码有效窗口(天),默认30天 */
|
|
|
@Value("${invite.bind-window-days:30}")
|
|
@Value("${invite.bind-window-days:30}")
|
|
|
private int bindWindowDays;
|
|
private int bindWindowDays;
|
|
@@ -104,10 +108,11 @@ public class InviteService {
|
|
|
* 浏览器打开邀请链接时调用,展示邀请人信息和下载链接
|
|
* 浏览器打开邀请链接时调用,展示邀请人信息和下载链接
|
|
|
* 支持多渠道:app、wechat、miniapp、dingtalk、feishu
|
|
* 支持多渠道:app、wechat、miniapp、dingtalk、feishu
|
|
|
*
|
|
*
|
|
|
- * @param code 邀请码
|
|
|
|
|
- * @param channel 渠道(可选,默认app)
|
|
|
|
|
|
|
+ * @param code 邀请码
|
|
|
|
|
+ * @param channel 渠道(可选,默认app)
|
|
|
|
|
+ * @param userAgent 浏览器 User-Agent,用于判断桌面客户端下载包
|
|
|
*/
|
|
*/
|
|
|
- public InvitePageResponse getInvitePage(String code, String channel) {
|
|
|
|
|
|
|
+ public InvitePageResponse getInvitePage(String code, String channel, String userAgent) {
|
|
|
InviteCode inviteCode = inviteCodeMapper.selectOne(
|
|
InviteCode inviteCode = inviteCodeMapper.selectOne(
|
|
|
new LambdaQueryWrapper<InviteCode>()
|
|
new LambdaQueryWrapper<InviteCode>()
|
|
|
.eq(InviteCode::getCode, code));
|
|
.eq(InviteCode::getCode, code));
|
|
@@ -151,7 +156,15 @@ public class InviteService {
|
|
|
|
|
|
|
|
// 根据渠道生成提示文案
|
|
// 根据渠道生成提示文案
|
|
|
String instructionText = generateInstructionText(code, channel, config);
|
|
String instructionText = generateInstructionText(code, channel, config);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 落地页下载按钮指向 /api/invite/{code},访问时会再次记录点击并自动重定向到对应安装包
|
|
|
|
|
+ String inviteDownloadUrl = inviteBaseUrl + "/invite/" + code;
|
|
|
|
|
+
|
|
|
|
|
+ // Windows/app 渠道使用邀请链接作为下载入口(自动识别设备并重定向),其他渠道保持配置中的下载地址
|
|
|
|
|
+ String appDownloadUrl = ("windows".equals(channel) || "app".equals(channel))
|
|
|
|
|
+ ? inviteDownloadUrl
|
|
|
|
|
+ : config.getAppDownloadUrl();
|
|
|
|
|
+
|
|
|
// 处理落地页标题:支持 {inviter} 和 {pharmacy} 占位符
|
|
// 处理落地页标题:支持 {inviter} 和 {pharmacy} 占位符
|
|
|
String landingTitle = config.getLandingTitle();
|
|
String landingTitle = config.getLandingTitle();
|
|
|
if (landingTitle == null || landingTitle.isBlank()) {
|
|
if (landingTitle == null || landingTitle.isBlank()) {
|
|
@@ -183,7 +196,7 @@ public class InviteService {
|
|
|
.landingTitle(landingTitle)
|
|
.landingTitle(landingTitle)
|
|
|
.landingDesc(config.getLandingDesc())
|
|
.landingDesc(config.getLandingDesc())
|
|
|
// 渠道特定字段
|
|
// 渠道特定字段
|
|
|
- .appDownloadUrl(config.getAppDownloadUrl())
|
|
|
|
|
|
|
+ .appDownloadUrl(appDownloadUrl)
|
|
|
.miniappPath(miniappPath)
|
|
.miniappPath(miniappPath)
|
|
|
.miniappAppId(config.getMiniappAppId())
|
|
.miniappAppId(config.getMiniappAppId())
|
|
|
.wechatRedirectUrl(config.getWechatRedirectUrl())
|
|
.wechatRedirectUrl(config.getWechatRedirectUrl())
|
|
@@ -232,6 +245,60 @@ public class InviteService {
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 解析桌面客户端下载完整URL(公开,无需登录)
|
|
|
|
|
+ * 根据 User-Agent 判断系统架构,返回对应下载包地址
|
|
|
|
|
+ */
|
|
|
|
|
+ public String resolveDownloadUrl(String code, String userAgent) {
|
|
|
|
|
+ // 校验邀请码存在性(可选:不存在也允许下载,这里只做简单校验并记录点击)
|
|
|
|
|
+ InviteCode inviteCode = inviteCodeMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<InviteCode>()
|
|
|
|
|
+ .eq(InviteCode::getCode, code));
|
|
|
|
|
+ if (inviteCode != null) {
|
|
|
|
|
+ inviteCode.setClickCount(inviteCode.getClickCount() + 1);
|
|
|
|
|
+ inviteCodeMapper.updateById(inviteCode);
|
|
|
|
|
+ log.debug("下载链接 {} 被访问,累计点击 {} 次", code, inviteCode.getClickCount());
|
|
|
|
|
+ }
|
|
|
|
|
+ return resolveDesktopDownloadUrl(userAgent);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据 User-Agent 判断系统并返回桌面客户端下载地址
|
|
|
|
|
+ * Windows x64 -> /desktop-updates/智价云-x64.exe
|
|
|
|
|
+ * macOS ARM64 -> /desktop-updates/智价云-arm64.dmg
|
|
|
|
|
+ * 其他默认返回 Windows x64 包
|
|
|
|
|
+ */
|
|
|
|
|
+ private String resolveDesktopDownloadUrl(String userAgent) {
|
|
|
|
|
+ String baseUrl = getDesktopDownloadBaseUrl();
|
|
|
|
|
+ String path = "/desktop-updates/智价云-x64.exe";
|
|
|
|
|
+ if (userAgent != null) {
|
|
|
|
|
+ String ua = userAgent.toLowerCase();
|
|
|
|
|
+ boolean isMac = ua.contains("macintosh") || ua.contains("mac os");
|
|
|
|
|
+ boolean isArm = ua.contains("arm64") || ua.contains("aarch64");
|
|
|
|
|
+ if (isMac && isArm) {
|
|
|
|
|
+ path = "/desktop-updates/智价云-arm64.dmg";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return baseUrl + path;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取桌面客户端下载基础URL
|
|
|
|
|
+ * 优先使用配置 invite.desktop-download-base-url,未配置时从 inviteBaseUrl 推断域名根地址
|
|
|
|
|
+ */
|
|
|
|
|
+ private String getDesktopDownloadBaseUrl() {
|
|
|
|
|
+ if (desktopDownloadBaseUrl != null && !desktopDownloadBaseUrl.isBlank()) {
|
|
|
|
|
+ return desktopDownloadBaseUrl.replaceAll("/$", "");
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ java.net.URL url = new java.net.URL(inviteBaseUrl);
|
|
|
|
|
+ return url.getProtocol() + "://" + url.getAuthority();
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("无法从 inviteBaseUrl 推断下载域名: {}", inviteBaseUrl, e);
|
|
|
|
|
+ return inviteBaseUrl.replaceAll("/$", "");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 追踪邀请链接被打开(公开,浏览器打开时调用)
|
|
* 追踪邀请链接被打开(公开,浏览器打开时调用)
|
|
|
* 记录到 invite_code.click_count
|
|
* 记录到 invite_code.click_count
|
|
@@ -414,24 +481,25 @@ public class InviteService {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 5.1 检查邀请人总邀请人数上限
|
|
|
|
|
|
|
+ // 5.1 检查邀请人总邀请奖励上限(仍可继续邀请,但超过上限后不再发放奖励)
|
|
|
Long totalInvited = inviteRelationMapper.selectCount(
|
|
Long totalInvited = inviteRelationMapper.selectCount(
|
|
|
new LambdaQueryWrapper<InviteRelation>()
|
|
new LambdaQueryWrapper<InviteRelation>()
|
|
|
.eq(InviteRelation::getInviterId, inviterId)
|
|
.eq(InviteRelation::getInviterId, inviterId)
|
|
|
.eq(InviteRelation::getRegistered, 1));
|
|
.eq(InviteRelation::getRegistered, 1));
|
|
|
int maxTotal = config.getMaxTotalInvites() != null ? config.getMaxTotalInvites() : 30;
|
|
int maxTotal = config.getMaxTotalInvites() != null ? config.getMaxTotalInvites() : 30;
|
|
|
- if (totalInvited >= maxTotal) {
|
|
|
|
|
- log.warn("邀请人{}已达邀请上限{}人", inviterId, maxTotal);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ boolean rewardAllowed = totalInvited < maxTotal;
|
|
|
|
|
+ if (!rewardAllowed) {
|
|
|
|
|
+ log.warn("邀请人{}已达会员时长奖励上限{}人,继续邀请不再发放奖励", inviterId, maxTotal);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 6. 创建邀请关系(直接标记为已注册,奖励类型为赠送会员时长)
|
|
// 6. 创建邀请关系(直接标记为已注册,奖励类型为赠送会员时长)
|
|
|
|
|
+ Integer rewardMonths = config.getRewardMonths() != null ? config.getRewardMonths() : 1;
|
|
|
InviteRelation relation = InviteRelation.builder()
|
|
InviteRelation relation = InviteRelation.builder()
|
|
|
.inviterId(inviterId)
|
|
.inviterId(inviterId)
|
|
|
.inviteeId(inviteeId)
|
|
.inviteeId(inviteeId)
|
|
|
.inviteCodeId(inviteCode.getId())
|
|
.inviteCodeId(inviteCode.getId())
|
|
|
.registered(1)
|
|
.registered(1)
|
|
|
- .rewardGranted(config.getRewardMonths() != null ? config.getRewardMonths() : 1)
|
|
|
|
|
|
|
+ .rewardGranted(rewardAllowed ? rewardMonths : 0)
|
|
|
.status(1)
|
|
.status(1)
|
|
|
.build();
|
|
.build();
|
|
|
inviteRelationMapper.insert(relation);
|
|
inviteRelationMapper.insert(relation);
|
|
@@ -440,10 +508,13 @@ public class InviteService {
|
|
|
inviteCode.setUsedCount(inviteCode.getUsedCount() + 1);
|
|
inviteCode.setUsedCount(inviteCode.getUsedCount() + 1);
|
|
|
inviteCodeMapper.updateById(inviteCode);
|
|
inviteCodeMapper.updateById(inviteCode);
|
|
|
|
|
|
|
|
- // 8. 给邀请人发放奖励(赠送30天高级会员)
|
|
|
|
|
- grantInviteReward(inviterId, inviteeId);
|
|
|
|
|
-
|
|
|
|
|
- log.info("邀请成功: 用户 {} 邀请了用户 {},邀请人获赠30天高级会员", inviterId, inviteeId);
|
|
|
|
|
|
|
+ // 8. 给邀请人发放奖励(在奖励上限内赠送30天会员时长)
|
|
|
|
|
+ if (rewardAllowed) {
|
|
|
|
|
+ grantInviteReward(inviterId, inviteeId);
|
|
|
|
|
+ log.info("邀请成功: 用户 {} 邀请了用户 {},邀请人获赠30天会员时长", inviterId, inviteeId);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.info("邀请成功: 用户 {} 邀请了用户 {},已达奖励上限,不发放会员时长", inviterId, inviteeId);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -517,24 +588,22 @@ public class InviteService {
|
|
|
throw new BusinessException(ErrorCode.BUSINESS_ERROR, "邀请功能已停用");
|
|
throw new BusinessException(ErrorCode.BUSINESS_ERROR, "邀请功能已停用");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 7.1 检查邀请人总邀请人数上限
|
|
|
|
|
|
|
+ // 7.1 检查邀请人总邀请奖励上限(仍可继续绑定,但超过上限后不再发放奖励)
|
|
|
Long totalInvited = inviteRelationMapper.selectCount(
|
|
Long totalInvited = inviteRelationMapper.selectCount(
|
|
|
new LambdaQueryWrapper<InviteRelation>()
|
|
new LambdaQueryWrapper<InviteRelation>()
|
|
|
.eq(InviteRelation::getInviterId, inviterId)
|
|
.eq(InviteRelation::getInviterId, inviterId)
|
|
|
.eq(InviteRelation::getRegistered, 1));
|
|
.eq(InviteRelation::getRegistered, 1));
|
|
|
int maxTotal = config.getMaxTotalInvites() != null ? config.getMaxTotalInvites() : 30;
|
|
int maxTotal = config.getMaxTotalInvites() != null ? config.getMaxTotalInvites() : 30;
|
|
|
- if (totalInvited >= maxTotal) {
|
|
|
|
|
- throw new BusinessException(ErrorCode.INVITE_LIMIT_REACHED,
|
|
|
|
|
- String.format("邀请人已达邀请上限%d人", maxTotal));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ boolean rewardAllowed = totalInvited < maxTotal;
|
|
|
|
|
|
|
|
// 8. 创建邀请关系
|
|
// 8. 创建邀请关系
|
|
|
|
|
+ Integer rewardMonths = config.getRewardMonths() != null ? config.getRewardMonths() : 1;
|
|
|
InviteRelation relation = InviteRelation.builder()
|
|
InviteRelation relation = InviteRelation.builder()
|
|
|
.inviterId(inviterId)
|
|
.inviterId(inviterId)
|
|
|
.inviteeId(userId)
|
|
.inviteeId(userId)
|
|
|
.inviteCodeId(inviteCode.getId())
|
|
.inviteCodeId(inviteCode.getId())
|
|
|
.registered(1)
|
|
.registered(1)
|
|
|
- .rewardGranted(config.getRewardMonths() != null ? config.getRewardMonths() : 1)
|
|
|
|
|
|
|
+ .rewardGranted(rewardAllowed ? rewardMonths : 0)
|
|
|
.status(1)
|
|
.status(1)
|
|
|
.build();
|
|
.build();
|
|
|
inviteRelationMapper.insert(relation);
|
|
inviteRelationMapper.insert(relation);
|
|
@@ -543,13 +612,17 @@ public class InviteService {
|
|
|
inviteCode.setUsedCount(inviteCode.getUsedCount() + 1);
|
|
inviteCode.setUsedCount(inviteCode.getUsedCount() + 1);
|
|
|
inviteCodeMapper.updateById(inviteCode);
|
|
inviteCodeMapper.updateById(inviteCode);
|
|
|
|
|
|
|
|
- // 10. 发放奖励:邀请人30天高级会员
|
|
|
|
|
- membershipService.grantInviteRewardMembership(inviterId, userId);
|
|
|
|
|
-
|
|
|
|
|
- log.info("补填邀请码成功: 用户{}绑定邀请码{},邀请人{},邀请人获赠30天高级会员",
|
|
|
|
|
- userId, inviteCodeStr, inviterId);
|
|
|
|
|
-
|
|
|
|
|
- return "补填邀请码成功!邀请人获赠1个月高级会员时长";
|
|
|
|
|
|
|
+ // 10. 发放奖励:邀请人30天会员时长(在奖励上限内)
|
|
|
|
|
+ if (rewardAllowed) {
|
|
|
|
|
+ membershipService.grantInviteRewardMembership(inviterId, userId);
|
|
|
|
|
+ log.info("补填邀请码成功: 用户{}绑定邀请码{},邀请人{},邀请人获赠30天会员时长",
|
|
|
|
|
+ userId, inviteCodeStr, inviterId);
|
|
|
|
|
+ return "补填邀请码成功!邀请人获赠1个月会员时长";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.info("补填邀请码成功: 用户{}绑定邀请码{},邀请人{},已达奖励上限,不发放会员时长",
|
|
|
|
|
+ userId, inviteCodeStr, inviterId);
|
|
|
|
|
+ return "补填邀请码成功!邀请人已达奖励上限,本次不发放会员时长";
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -667,6 +740,41 @@ public class InviteService {
|
|
|
}).collect(Collectors.toList());
|
|
}).collect(Collectors.toList());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 查询是谁邀请了我(被邀请人视角)
|
|
|
|
|
+ * 从 t_invite_relation 中查找 inviteeId = 当前用户的记录
|
|
|
|
|
+ */
|
|
|
|
|
+ public MyInviterResponse getMyInviter(Long userId) {
|
|
|
|
|
+ InviteRelation relation = inviteRelationMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<InviteRelation>()
|
|
|
|
|
+ .eq(InviteRelation::getInviteeId, userId)
|
|
|
|
|
+ .orderByDesc(InviteRelation::getCreateTime)
|
|
|
|
|
+ .last("LIMIT 1"));
|
|
|
|
|
+
|
|
|
|
|
+ if (relation == null) {
|
|
|
|
|
+ return MyInviterResponse.builder()
|
|
|
|
|
+ .invited(false)
|
|
|
|
|
+ .build();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ User inviter = userMapper.selectById(relation.getInviterId());
|
|
|
|
|
+ InviteCode inviteCode = relation.getInviteCodeId() != null
|
|
|
|
|
+ ? inviteCodeMapper.selectById(relation.getInviteCodeId())
|
|
|
|
|
+ : null;
|
|
|
|
|
+
|
|
|
|
|
+ return MyInviterResponse.builder()
|
|
|
|
|
+ .invited(true)
|
|
|
|
|
+ .inviterId(relation.getInviterId())
|
|
|
|
|
+ .inviterNickname(getDisplayName(inviter))
|
|
|
|
|
+ .inviterPhone(inviter != null ? ValidateUtil.maskPhone(inviter.getPhone()) : null)
|
|
|
|
|
+ .inviterAvatar(inviter != null ? inviter.getAvatar() : null)
|
|
|
|
|
+ .pharmacyName(inviter != null ? inviter.getPharmacyName() : null)
|
|
|
|
|
+ .inviteCode(inviteCode != null ? inviteCode.getCode() : null)
|
|
|
|
|
+ .inviteTime(relation.getCreateTime() != null ?
|
|
|
|
|
+ relation.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null)
|
|
|
|
|
+ .build();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 获取用户可用的额外爬虫次数
|
|
* 获取用户可用的额外爬虫次数
|
|
|
*/
|
|
*/
|
|
@@ -711,12 +819,16 @@ public class InviteService {
|
|
|
* 获取用户昵称
|
|
* 获取用户昵称
|
|
|
*/
|
|
*/
|
|
|
/**
|
|
/**
|
|
|
- * 获取用户对外展示名:优先用昵称,其次用手机尾号,都没有则用兜底文案
|
|
|
|
|
|
|
+ * 获取用户对外展示名:
|
|
|
|
|
+ * 优先顺序:微信昵称 > 用户自定义昵称 > 手机尾号 > 兜底文案
|
|
|
*/
|
|
*/
|
|
|
private String getDisplayName(User user) {
|
|
private String getDisplayName(User user) {
|
|
|
if (user == null) {
|
|
if (user == null) {
|
|
|
return "一位药店用户";
|
|
return "一位药店用户";
|
|
|
}
|
|
}
|
|
|
|
|
+ if (user.getWechatNickname() != null && !user.getWechatNickname().isBlank()) {
|
|
|
|
|
+ return user.getWechatNickname();
|
|
|
|
|
+ }
|
|
|
if (user.getNickname() != null && !user.getNickname().isBlank()) {
|
|
if (user.getNickname() != null && !user.getNickname().isBlank()) {
|
|
|
return user.getNickname();
|
|
return user.getNickname();
|
|
|
}
|
|
}
|
|
@@ -745,26 +857,29 @@ public class InviteService {
|
|
|
|
|
|
|
|
// 生成分享文案(邀请人 + 产品价值 + 操作指引)
|
|
// 生成分享文案(邀请人 + 产品价值 + 操作指引)
|
|
|
// 分享标题:让接收方一眼知道是谁邀请的
|
|
// 分享标题:让接收方一眼知道是谁邀请的
|
|
|
- String shareTitle = inviterNickname + "邀请你加入" + config.getAppName();
|
|
|
|
|
|
|
+ String shareTitle = inviterNickname + " 邀请你加入" + config.getAppName();
|
|
|
// 分享描述:说明产品核心价值(绑定B2B平台→聚合查价)
|
|
// 分享描述:说明产品核心价值(绑定B2B平台→聚合查价)
|
|
|
String shareDescription = config.getLandingDesc() != null
|
|
String shareDescription = config.getLandingDesc() != null
|
|
|
&& !config.getLandingDesc().isBlank()
|
|
&& !config.getLandingDesc().isBlank()
|
|
|
- ? config.getLandingDesc() : "登录智价云(药店端)平台,聚合比价查低价";
|
|
|
|
|
|
|
+ ? config.getLandingDesc() : "注册登录" + config.getAppName() + "平台,聚合比价查低价";
|
|
|
String rewardDesc = "邀请人每成功邀请1家药店注册,赠送1个月高级会员时长";
|
|
String rewardDesc = "邀请人每成功邀请1家药店注册,赠送1个月高级会员时长";
|
|
|
|
|
|
|
|
- // 复制文本
|
|
|
|
|
|
|
+ // 邀请链接即下载入口,访问后根据对方设备自动重定向到对应安装包
|
|
|
|
|
+ String downloadLink = inviteLink;
|
|
|
|
|
+
|
|
|
|
|
+ // 复制文本:与示例文案保持一致,便于用户一键转发
|
|
|
String copyText = String.format(
|
|
String copyText = String.format(
|
|
|
- "%s\n%s\n\n邀请码:%s\n%s\n\n点击链接下载:\n%s",
|
|
|
|
|
- shareTitle,
|
|
|
|
|
- shareDescription,
|
|
|
|
|
|
|
+ "%s,我在这里发现了一个药店采购神器——%s,咱们一起用起来吧!它聚合比价功能特别方便,能快速查到低价,帮你节省采购成本。用我的邀请码 %s 注册,你会获取到会员权益,咱们平台上见!下载链接%s",
|
|
|
|
|
+ inviterNickname,
|
|
|
|
|
+ config.getAppName(),
|
|
|
code.getCode(),
|
|
code.getCode(),
|
|
|
- rewardDesc,
|
|
|
|
|
- inviteLink
|
|
|
|
|
|
|
+ downloadLink
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
return InviteCodeResponse.builder()
|
|
return InviteCodeResponse.builder()
|
|
|
.code(code.getCode())
|
|
.code(code.getCode())
|
|
|
.inviteLink(inviteLink)
|
|
.inviteLink(inviteLink)
|
|
|
|
|
+ .downloadUrl(inviteLink)
|
|
|
.inviterNickname(inviterNickname)
|
|
.inviterNickname(inviterNickname)
|
|
|
.clickCount(code.getClickCount() != null ? code.getClickCount() : 0)
|
|
.clickCount(code.getClickCount() != null ? code.getClickCount() : 0)
|
|
|
.usedCount(code.getUsedCount())
|
|
.usedCount(code.getUsedCount())
|