Commit b7e92bae by yxdubhe_bot

merge:feature-sharer-20250514:operator:wb.xiaoke@mesg.corp.netease.com:auto_bran…

merge:feature-sharer-20250514:operator:wb.xiaoke@mesg.corp.netease.com:auto_branch_merge_by_branchService_end
parents f7b14568 06ea1bfd
Pipeline #75782 passed with stages
in 1 minute 18 seconds
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
<yanxuan-log.version>1.0.2</yanxuan-log.version> <yanxuan-log.version>1.0.2</yanxuan-log.version>
<tracer.version>1.0.8-RELEASE</tracer.version> <tracer.version>1.0.8-RELEASE</tracer.version>
<shadow.version>1.0.6-RELEASE</shadow.version> <shadow.version>1.0.6-RELEASE</shadow.version>
<user-info-client.version>1.0.14-RELEASE</user-info-client.version>
<netease.ddb.version>4.6.0.4</netease.ddb.version> <netease.ddb.version>4.6.0.4</netease.ddb.version>
<!-- store-db --> <!-- store-db -->
...@@ -184,6 +185,12 @@ ...@@ -184,6 +185,12 @@
<version>${shadow.version}</version> <version>${shadow.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.netease.yanxuan</groupId>
<artifactId>user-info-client</artifactId>
<version>${user-info-client.version}</version>
</dependency>
<!-- store-db --> <!-- store-db -->
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
......
...@@ -13,14 +13,14 @@ import org.springframework.scheduling.annotation.EnableAsync; ...@@ -13,14 +13,14 @@ import org.springframework.scheduling.annotation.EnableAsync;
* 项目启动类 * 项目启动类
*/ */
@EnableAsync @EnableAsync
@ComponentScan(basePackages = "com.netease.yanxuan.wx.store.sharer")
@EnableApolloConfig @EnableApolloConfig
@EnableMissaClients(basePackages = "com.netease.yanxuan.wx.store.sharer") @EnableMissaClients(basePackages = "com.netease.yanxuan.wx.store.sharer")
@MapperScan(basePackages = "com.netease.yanxuan.wx.store.sharer.dal") @MapperScan(basePackages = "com.netease.yanxuan.wx.store.sharer.dal")
@ComponentScan(basePackages = {"com.netease.mail.yanxuan.dschedule", "com.netease.yanxuan.wx.store.sharer"})
@SpringBootApplication @SpringBootApplication
public class Application extends SpringBootServletInitializer { public class Application extends SpringBootServletInitializer {
public static void main(String[] args) throws Exception { public static void main(String[] args) {
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
} }
} }
package com.netease.yanxuan.wx.store.sharer.biz.config;
import com.ctrip.framework.apollo.spring.annotation.EnableAutoUpdateApolloConfig;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Description 应用配置
* @Author fanjiaxin
* @Date 2025/3/10 17:26
*/
@Data
@Component
@EnableAutoUpdateApolloConfig
public class AppConfig {
/**
* 实名认证开关
*/
@Value("${sys.realname.authenticated.enabled:true}")
private Boolean realNameAuthenticatedEnabled;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.biz.config;
import com.netease.mail.yanxuan.dschedule.core.executor.DscheduleExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description Dschedule配置
* @Author fanjiaxin
* @Date 2025/2/21 14:40
*/
@Configuration
public class DscheduleConfig {
/**
* dschedule执行器
*/
@Bean(value = "dscheduleExecutor", initMethod = "start", destroyMethod = "destroy")
public DscheduleExecutor dscheduleExecutor() {
return new DscheduleExecutor();
}
}
package com.netease.yanxuan.wx.store.sharer.biz.job;
import com.netease.mail.yanxuan.dschedule.core.biz.model.ReturnT;
import com.netease.mail.yanxuan.dschedule.core.handler.IJobHandler;
import com.netease.mail.yanxuan.dschedule.core.handler.annotation.JobHandler;
import com.netease.yanxuan.wx.store.sharer.biz.service.ICommissionOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @Description 微信小店佣金订单数据同步失败重试任务
* @Author fanjiaxin
* @Date 2025/3/27 19:08
*/
@Slf4j
@RequiredArgsConstructor
@Component
@JobHandler("weChatCommissionOrderFailRetryJob")
public class WeChatCommissionOrderFailRetryJob extends IJobHandler {
private final ICommissionOrderService iCommissionOrderService;
@Override
public ReturnT<String> execute(String... strings) {
log.info("[op:weChatCommissionOrderFailRetryJob] start...");
iCommissionOrderService.doCommissionOrderFailRetry();
log.info("[op:weChatCommissionOrderFailRetryJob] end...");
return ReturnT.SUCCESS;
}
}
package com.netease.yanxuan.wx.store.sharer.biz.job;
import com.netease.mail.yanxuan.dschedule.core.biz.model.ReturnT;
import com.netease.mail.yanxuan.dschedule.core.handler.IJobHandler;
import com.netease.mail.yanxuan.dschedule.core.handler.annotation.JobHandler;
import com.netease.yanxuan.wx.store.sharer.biz.service.ICommissionOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @Description 微信小店佣金单数据同步任务
* @Author fanjiaxin
* @Date 2025/3/27 19:08
*/
@Slf4j
@RequiredArgsConstructor
@Component
@JobHandler("weChatCommissionOrderSyncJob")
public class WeChatCommissionOrderSyncJob extends IJobHandler {
private final ICommissionOrderService iCommissionOrderService;
@Override
public ReturnT<String> execute(String... strings) {
log.info("[op:weChatCommissionOrderSyncJob] start...");
Long syncStartTimestamp = iCommissionOrderService.getLatestCommissionSyncTimestamp();
long syncEndTimestamp = System.currentTimeMillis() / 1000;
iCommissionOrderService.doCommissionOrderSync(syncStartTimestamp, syncEndTimestamp);
log.info("[op:weChatCommissionOrderSyncJob] end...");
return ReturnT.SUCCESS;
}
}
package com.netease.yanxuan.wx.store.sharer.biz.meta.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @Description 短信场景枚举
* @Author fanjiaxin
* @Date 2025/5/14 13:12
*/
@Getter
@RequiredArgsConstructor
public enum SmsScenesEnum {
REAL_NAME_AUTHENTICATED("实名认证");
private final String desc;
/**
* 检查场景标识是否存在
*
* @param scenes 场景标识
* @return true:存在,false: 不存在
*/
public static boolean checkScenes(String scenes) {
for (SmsScenesEnum scenesEnum : SmsScenesEnum.values()) {
if (scenesEnum.name().equals(scenes)) {
return true;
}
}
return false;
}
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Description 实名认证-业务对象
* @Author fanjiaxin
* @Date 2025/3/9 13:44
*/
@Data
public class RealNameAuthenticatedBO {
/**
* 姓名
*/
@NotBlank(message = "姓名不能为空")
private String username;
/**
* 身份证号
*/
@NotBlank(message = "身份证号不能为空")
private String idCardNumber;
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
private String mobilePhone;
/**
* 验证码
*/
@NotBlank(message = "验证码不能为空")
private String smsCode;
}
package com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Description 发送短信验证码-业务对象
* @Author fanjiaxin
* @Date 2025/3/9 13:44
*/
@Data
public class SmsCodeBO {
/**
* 场景
*/
@NotBlank(message = "场景不能为空")
private String scenes;
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
private String mobilePhone;
}
...@@ -49,6 +49,11 @@ public class SharerInfoVO { ...@@ -49,6 +49,11 @@ public class SharerInfoVO {
* 绑定时需要的queryString参数 * 绑定时需要的queryString参数
*/ */
private String bindQueryString; private String bindQueryString;
/**
* 是否实名认证
*/
private Boolean isRealNameAuthenticated;
@Getter @Getter
@RequiredArgsConstructor @RequiredArgsConstructor
......
package com.netease.yanxuan.wx.store.sharer.biz.service;
/**
* @Description 订单-业务层
* @Author fanjiaxin
* @Date 2025/3/10 12:28
*/
public interface ICommissionOrderService {
/**
* 获取最新分佣单同步时间戳
*/
Long getLatestCommissionSyncTimestamp();
/**
* 佣金订单列表同步
*/
void doCommissionOrderSync(Long startTime, Long endTime);
/**
* 佣金订单失败重试
*/
void doCommissionOrderFailRetry();
}
package com.netease.yanxuan.wx.store.sharer.biz.service;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.SmsCodeBO;
/**
* @Description 短信-业务层
* @Author fanjiaxin
* @Date 2025/3/10 12:28
*/
public interface ISmsService {
/**
* 发送短信验证码
*/
void sendSmsCode(SmsCodeBO bo);
/**
* 验证短信验证码
*/
void verifySmsCode(String scenes, String phone, String code);
/**
* 失效短信验证码
*/
void invalidSmsCode(String scenes, String phone);
}
package com.netease.yanxuan.wx.store.sharer.biz.service; package com.netease.yanxuan.wx.store.sharer.biz.service;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.LoginBO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.LoginBO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.RealNameAuthenticatedBO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserCommissionRatioVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserCommissionRatioVO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserTokenVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserTokenVO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.SharerInfoVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.SharerInfoVO;
...@@ -30,4 +31,9 @@ public interface IUserService { ...@@ -30,4 +31,9 @@ public interface IUserService {
* 查询平台默认的分佣比例 * 查询平台默认的分佣比例
*/ */
UserCommissionRatioVO getCommissionRatioDefault(); UserCommissionRatioVO getCommissionRatioDefault();
/**
* 实名认证
*/
void realNameAuthenticated(RealNameAuthenticatedBO bo);
} }
...@@ -9,11 +9,11 @@ import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.ProductPromotionLin ...@@ -9,11 +9,11 @@ import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.ProductPromotionLin
import com.netease.yanxuan.wx.store.sharer.biz.meta.page.PageQuery; import com.netease.yanxuan.wx.store.sharer.biz.meta.page.PageQuery;
import com.netease.yanxuan.wx.store.sharer.biz.meta.page.PageVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.page.PageVO;
import com.netease.yanxuan.wx.store.sharer.biz.service.IProductService; import com.netease.yanxuan.wx.store.sharer.biz.service.IProductService;
import com.netease.yanxuan.wx.store.sharer.common.constant.CoreConstant;
import com.netease.yanxuan.wx.store.sharer.common.exception.NoBindSharerException; import com.netease.yanxuan.wx.store.sharer.common.exception.NoBindSharerException;
import com.netease.yanxuan.wx.store.sharer.common.handler.RedisClient; import com.netease.yanxuan.wx.store.sharer.common.handler.RedisClient;
import com.netease.yanxuan.wx.store.sharer.common.util.AsyncUtils; import com.netease.yanxuan.wx.store.sharer.common.util.AsyncUtils;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi; import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatConstant;
import com.netease.yanxuan.wx.store.sharer.integration.handler.impl.*; import com.netease.yanxuan.wx.store.sharer.integration.handler.impl.*;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.*; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.*;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
...@@ -160,12 +160,12 @@ public class ProductServiceImpl implements IProductService { ...@@ -160,12 +160,12 @@ public class ProductServiceImpl implements IProductService {
*/ */
private WeChatPromoteProductDetailVO getProductDetailCache(String shopAppid, String productId) { private WeChatPromoteProductDetailVO getProductDetailCache(String shopAppid, String productId) {
WeChatPromoteProductDetailVO detailVO; WeChatPromoteProductDetailVO detailVO;
String productDetailKey = CoreConstant.REDIS_PRODUCT_DETAIL_KEY + shopAppid + ":" + productId; String productDetailKey = WeChatConstant.REDIS_PRODUCT_DETAIL_KEY + shopAppid + ":" + productId;
String productDetailJson = redisClient.getStr(productDetailKey); String productDetailJson = redisClient.getStr(productDetailKey);
if (StringUtils.isBlank(productDetailJson)) { if (StringUtils.isBlank(productDetailJson)) {
detailVO = weChatShopPromoteProductDetailRequest.handle(shopAppid, Long.valueOf(productId)); detailVO = weChatShopPromoteProductDetailRequest.handle(shopAppid, Long.valueOf(productId));
if (null != detailVO) { if (null != detailVO) {
redisClient.setStr(productDetailKey, JSON.toJSONString(detailVO), CoreConstant.REDIS_PRODUCT_DETAIL_EXPIRE_SECONDS); redisClient.setStr(productDetailKey, JSON.toJSONString(detailVO), WeChatConstant.REDIS_PRODUCT_DETAIL_EXPIRE_SECONDS);
} }
} else { } else {
detailVO = JSON.parseObject(productDetailJson, WeChatPromoteProductDetailVO.class); detailVO = JSON.parseObject(productDetailJson, WeChatPromoteProductDetailVO.class);
......
package com.netease.yanxuan.wx.store.sharer.biz.service.impl;
import com.netease.yanxuan.wx.store.sharer.biz.core.LoginUserContextHolder;
import com.netease.yanxuan.wx.store.sharer.biz.meta.enums.SmsScenesEnum;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.SmsCodeBO;
import com.netease.yanxuan.wx.store.sharer.biz.service.ISmsService;
import com.netease.yanxuan.wx.store.sharer.common.exception.BizException;
import com.netease.yanxuan.wx.store.sharer.common.handler.RedisClient;
import com.netease.yanxuan.wx.store.sharer.common.util.PhoneCheckUtils;
import com.netease.yanxuan.wx.store.sharer.common.util.RandomUtils;
import com.netease.yanxuan.wx.store.sharer.integration.client.IUasClient;
import com.netease.yanxuan.wx.store.sharer.integration.config.SmsConfig;
import com.netease.yanxuan.wx.store.sharer.integration.constant.SmsConstant;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.SmsCodeScenesConfigBO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;
/**
* @Description 短信-业务实现类
* @Author fanjiaxin
* @Date 2025/3/10 12:31
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class SmsServiceImpl implements ISmsService {
private final SmsConfig smsConfig;
private final IUasClient iUasClient;
private final RedisClient redisClient;
@Override
public void sendSmsCode(SmsCodeBO bo) {
log.info("[op:sendSmsCode] begin...");
// 前置校验
validateSendCode(bo.getScenes(), bo.getMobilePhone());
boolean success = sendCode(bo.getScenes(), bo.getMobilePhone());
if (!success) {
log.info("[op:sendSmsCode] is error...");
throw new BizException("短信验证码发送失败");
}
}
@Override
public void verifySmsCode(String scenes, String phone, String code) {
// 对比验证码
String codeKey = String.format(SmsConstant.SMS_CODE_KEY, scenes, phone);
String originCode = redisClient.getStr(codeKey);
if (StringUtils.isBlank(originCode) || !originCode.equals(code)) {
throw new BizException("验证码有误");
}
}
@Override
public void invalidSmsCode(String scenes, String phone) {
// 对比验证码
String codeKey = String.format(SmsConstant.SMS_CODE_KEY, scenes, phone);
redisClient.delete(codeKey);
}
/**
* 发送短信
*/
private Boolean sendCode(String scenes, String mobilePhone) {
log.info("[op:sendSmsCode] sendCode...");
SmsCodeScenesConfigBO scenesConfigBO = smsConfig.getScenesConfig(scenes);
if (null == scenesConfigBO) {
throw new BizException("短信配置错误");
}
// 生成6位随机数字
String code = RandomUtils.randomNumber(6);
// uas发送验证码
boolean success = iUasClient.sendSmsCode(LoginUserContextHolder.get().getOpenId(),
mobilePhone, code, scenes, scenesConfigBO);
if (!success) {
return false;
}
int sendIntervalSeconds = scenesConfigBO.getSendIntervalSeconds();
int codeValidMinutes = scenesConfigBO.getCodeValidMinutes();
// 标记验证码已发送
String sendCodeKey = String.format(SmsConstant.SMS_SEND_INTERVAL_KEY, scenes, mobilePhone);
redisClient.setStr(sendCodeKey, String.valueOf(System.currentTimeMillis()), sendIntervalSeconds);
// 验证码放进缓存
String codeKey = String.format(SmsConstant.SMS_CODE_KEY, scenes, mobilePhone);
redisClient.setStr(codeKey, code, codeValidMinutes * 60);
return true;
}
/**
* 手机格式校验以及验证码相关校验
*
* @param scenes 场景
* @param mobilePhone 手机号
*/
private void validateSendCode(String scenes, String mobilePhone) {
log.info("[op:sendSmsCode] validate...");
// 场景标识检查
if (!SmsScenesEnum.checkScenes(scenes)) {
throw new BizException("场景标识错误");
}
// 手机格式校验
if (!PhoneCheckUtils.checkPhoneFormat(mobilePhone)) {
throw new BizException("手机号码格式错误");
}
// 验证码发送标记缓存
if (!validateVerifyCodeSend(scenes, mobilePhone)) {
throw new BizException("验证码发送过于频繁,请稍后重试");
}
// 验证码每日发送次数上限缓存
if (!validateVerifyCodeSendCount(scenes, mobilePhone)) {
throw new BizException("验证码发送达到次数上限");
}
}
/**
* 验证码发送标记
*
* @param scenes 场景
* @param mobilePhone 手机号
* @return true: 标记不存在,false:标记存在
*/
private Boolean validateVerifyCodeSend(String scenes, String mobilePhone) {
String key = String.format(SmsConstant.SMS_SEND_INTERVAL_KEY, scenes, mobilePhone);
return Boolean.FALSE.equals(redisClient.hasKey(key));
}
/**
* 验证码每日发送次数上限
*
* @param scenes 场景
* @param mobilePhone 手机号
* @return true: 未达上限,false: 到了上限
*/
private Boolean validateVerifyCodeSendCount(String scenes, String mobilePhone) {
String key = String.format(SmsConstant.SMS_SEND_COUNT_KEY, scenes, mobilePhone, getToday());
BoundValueOperations<String, Object> operations = redisClient.boundValueOps(key);
Long sendCount = operations.increment();
operations.expire(1, TimeUnit.DAYS);
return smsConfig.getScenesConfig(scenes).getSendMaxCount() >= (sendCount == null ? 1 : sendCount);
}
private String getToday() {
// 获取当前日期
LocalDate today = LocalDate.now();
// 定义日期格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
// 格式化日期
return today.format(formatter);
}
}
package com.netease.yanxuan.wx.store.sharer.biz.service.impl; package com.netease.yanxuan.wx.store.sharer.biz.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.netease.yanxuan.wx.store.sharer.biz.config.AppConfig;
import com.netease.yanxuan.wx.store.sharer.biz.config.DrmSharerConfig; import com.netease.yanxuan.wx.store.sharer.biz.config.DrmSharerConfig;
import com.netease.yanxuan.wx.store.sharer.biz.core.LoginUserContextHolder; import com.netease.yanxuan.wx.store.sharer.biz.core.LoginUserContextHolder;
import com.netease.yanxuan.wx.store.sharer.biz.core.LoginUserHelper; import com.netease.yanxuan.wx.store.sharer.biz.core.LoginUserHelper;
import com.netease.yanxuan.wx.store.sharer.biz.core.LoginUserInfo; import com.netease.yanxuan.wx.store.sharer.biz.core.LoginUserInfo;
import com.netease.yanxuan.wx.store.sharer.biz.meta.enums.SmsScenesEnum;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.LoginBO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.LoginBO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.RealNameAuthenticatedBO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.SharerInfoVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.SharerInfoVO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserCommissionRatioVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserCommissionRatioVO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserTokenVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserTokenVO;
import com.netease.yanxuan.wx.store.sharer.biz.service.ISmsService;
import com.netease.yanxuan.wx.store.sharer.biz.service.IUserService; import com.netease.yanxuan.wx.store.sharer.biz.service.IUserService;
import com.netease.yanxuan.wx.store.sharer.common.exception.BizException;
import com.netease.yanxuan.wx.store.sharer.common.exception.WeChatException; import com.netease.yanxuan.wx.store.sharer.common.exception.WeChatException;
import com.netease.yanxuan.wx.store.sharer.dal.mapper.SharerInfoMapper; import com.netease.yanxuan.wx.store.sharer.dal.mapper.SharerInfoMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerInfo; import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerInfo;
import com.netease.yanxuan.wx.store.sharer.integration.client.IUserInfoClient;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi; import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.handler.impl.WeChatShopSetSharerCommissionRequest; import com.netease.yanxuan.wx.store.sharer.integration.handler.impl.WeChatShopSetSharerCommissionRequest;
import com.netease.yanxuan.wx.store.sharer.integration.handler.impl.WeChatShopSharerListRequest; import com.netease.yanxuan.wx.store.sharer.integration.handler.impl.WeChatShopSharerListRequest;
...@@ -45,6 +52,7 @@ import java.util.Date; ...@@ -45,6 +52,7 @@ import java.util.Date;
@Service @Service
public class UserServiceImpl implements IUserService { public class UserServiceImpl implements IUserService {
private final AppConfig appConfig;
private final SharerInfoMapper sharerInfoMapper; private final SharerInfoMapper sharerInfoMapper;
private final LoginUserHelper loginUserHelper; private final LoginUserHelper loginUserHelper;
private final WeChatUserInfoRequest weChatUserRequest; private final WeChatUserInfoRequest weChatUserRequest;
...@@ -52,6 +60,8 @@ public class UserServiceImpl implements IUserService { ...@@ -52,6 +60,8 @@ public class UserServiceImpl implements IUserService {
private final WeChatShopSharerListRequest weChatShopSharerListRequest; private final WeChatShopSharerListRequest weChatShopSharerListRequest;
private final WeChatShopSetSharerCommissionRequest weChatShopSetSharerCommissionRequest; private final WeChatShopSetSharerCommissionRequest weChatShopSetSharerCommissionRequest;
private final DrmSharerConfig drmSharerConfig; private final DrmSharerConfig drmSharerConfig;
private final IUserInfoClient iUserInfoClient;
private final ISmsService iSmsService;
@Override @Override
...@@ -92,7 +102,7 @@ public class UserServiceImpl implements IUserService { ...@@ -92,7 +102,7 @@ public class UserServiceImpl implements IUserService {
public SharerInfoVO refreshUserInfo() { public SharerInfoVO refreshUserInfo() {
LoginUserInfo loginUserInfo = LoginUserContextHolder.get(); LoginUserInfo loginUserInfo = LoginUserContextHolder.get();
if (loginUserInfo == null) { if (loginUserInfo == null) {
log.error("[op:refreshUserInfo] refreshUserInfo loginUserInfo = null"); log.info("[op:refreshUserInfo] refreshUserInfo loginUserInfo = null");
return null; return null;
} }
log.info("[op:refreshUserInfo] refresh user commission userOpenId={}, userUnionId={}, shareId={}", log.info("[op:refreshUserInfo] refresh user commission userOpenId={}, userUnionId={}, shareId={}",
...@@ -160,6 +170,8 @@ public class UserServiceImpl implements IUserService { ...@@ -160,6 +170,8 @@ public class UserServiceImpl implements IUserService {
} else { } else {
sharerInfoMapper.updateById(sharerInfo); sharerInfoMapper.updateById(sharerInfo);
} }
// 身份证号码不为空证明已经实名认证过
result.setIsRealNameAuthenticated(StringUtils.isNotBlank(sharerInfo.getIdCardNumber()));
return result; return result;
} }
...@@ -173,9 +185,13 @@ public class UserServiceImpl implements IUserService { ...@@ -173,9 +185,13 @@ public class UserServiceImpl implements IUserService {
sharerInfoLqw.last("LIMIT 1"); sharerInfoLqw.last("LIMIT 1");
SharerInfo sharerInfo = sharerInfoMapper.selectOne(sharerInfoLqw); SharerInfo sharerInfo = sharerInfoMapper.selectOne(sharerInfoLqw);
// 已经绑定 // 已经绑定
if (null != sharerInfo && StringUtils.isNotBlank(sharerInfo.getSharerAppid())) { if (null != sharerInfo) {
if(StringUtils.isNotBlank(sharerInfo.getSharerAppid())){
result.setSharerAppId(sharerInfo.getSharerAppid()); result.setSharerAppId(sharerInfo.getSharerAppid());
} }
// 身份证号码不为空证明已经实名认证过
result.setIsRealNameAuthenticated(StringUtils.isNotBlank(sharerInfo.getIdCardNumber()));
}
return result; return result;
} }
...@@ -185,6 +201,35 @@ public class UserServiceImpl implements IUserService { ...@@ -185,6 +201,35 @@ public class UserServiceImpl implements IUserService {
return UserCommissionRatioVO.builder().commissionRatio(defaultCommissionRatio).build(); return UserCommissionRatioVO.builder().commissionRatio(defaultCommissionRatio).build();
} }
@Override
public void realNameAuthenticated(RealNameAuthenticatedBO bo) {
// 验证码校验
iSmsService.verifySmsCode(SmsScenesEnum.REAL_NAME_AUTHENTICATED.name(),
bo.getMobilePhone(), bo.getSmsCode());
// 验证身份信息
Boolean realNameAuthenticatedEnabled = appConfig.getRealNameAuthenticatedEnabled();
if(null == realNameAuthenticatedEnabled || realNameAuthenticatedEnabled){
log.info("[op:realNameAuthenticated] realNameAuthenticatedEnabled is enabled");
Boolean isVerifySuccess = iUserInfoClient.verifyByIdentityNo(bo.getUsername(), bo.getIdCardNumber());
if(null == isVerifySuccess || !isVerifySuccess){
throw new BizException("实名认证不通过");
}
}else{
log.info("[op:realNameAuthenticated] realNameAuthenticatedEnabled is disabled");
}
// 验证通过后更新实名认证信息
LoginUserInfo loginUserInfo = LoginUserContextHolder.get();
LambdaUpdateWrapper<SharerInfo> sharerInfoLuw = Wrappers.lambdaUpdate();
sharerInfoLuw.set(SharerInfo::getUsername, bo.getUsername());
sharerInfoLuw.set(SharerInfo::getIdCardNumber, bo.getIdCardNumber());
sharerInfoLuw.set(SharerInfo::getMobilePhone, bo.getMobilePhone());
sharerInfoLuw.set(SharerInfo::getUpdateTime, new Date());
sharerInfoLuw.eq(SharerInfo::getOpenId, loginUserInfo.getOpenId());
sharerInfoMapper.update(null, sharerInfoLuw);
// 验证成功后清除验证码
iSmsService.invalidSmsCode(SmsScenesEnum.REAL_NAME_AUTHENTICATED.name(), bo.getMobilePhone());
}
private SharerInfoVO getSharerRegisterBindInfo(String openId) { private SharerInfoVO getSharerRegisterBindInfo(String openId) {
// 获取推客注册与绑定信息 // 获取推客注册与绑定信息
WeChatSharerRegisterBindVO sharerRegisterBindVO = weChatShopSharerRegisterBindRequest.handle(openId); WeChatSharerRegisterBindVO sharerRegisterBindVO = weChatShopSharerRegisterBindRequest.handle(openId);
...@@ -196,6 +241,7 @@ public class UserServiceImpl implements IUserService { ...@@ -196,6 +241,7 @@ public class UserServiceImpl implements IUserService {
result.setRegisterQueryString(sharerRegisterBindVO.getRegister_query_string()); result.setRegisterQueryString(sharerRegisterBindVO.getRegister_query_string());
result.setBindBusinessType(sharerRegisterBindVO.getBind_business_type()); result.setBindBusinessType(sharerRegisterBindVO.getBind_business_type());
result.setBindQueryString(sharerRegisterBindVO.getBind_query_string()); result.setBindQueryString(sharerRegisterBindVO.getBind_query_string());
result.setIsRealNameAuthenticated(false);
return result; return result;
} }
} }
...@@ -19,49 +19,4 @@ public interface CoreConstant { ...@@ -19,49 +19,4 @@ public interface CoreConstant {
* Redis认证Token失效时间,秒 * Redis认证Token失效时间,秒
*/ */
int REDIS_TOKEN_EXPIRE_SECONDS = 30 * 24 * 60 * 60; int REDIS_TOKEN_EXPIRE_SECONDS = 30 * 24 * 60 * 60;
/**
* Redis微信认证Token
*/
String REDIS_TOKEN_WECHAT_KEY = "TOKEN:WECHAT";
/**
* Redis微信认证Token锁
*/
String REDIS_TOKEN_WECHAT_LOCK_KEY = "TOKEN:WECHAT:LOCK";
/**
* Redis微信认证Token锁时间,秒
*/
String REDIS_TOKEN_WECHAT_LOCK_VALUE = "wechat:lock";
/**
* Redis微信认证Token锁时间,秒
*/
int REDIS_TOKEN_WECHAT_LOCK_TIME = 5;
/**
* Redis微信小店认证Token
*/
String REDIS_TOKEN_WECHAT_SHOP_KEY = "TOKEN:WECHAT:SHOP";
/**
* Redis微信小店认证Token锁
*/
String REDIS_TOKEN_WECHAT_SHOP_LOCK_KEY = "TOKEN:WECHAT:SHOP:LOCK";
/**
* Redis微信小店认证Token锁时间,秒
*/
String REDIS_TOKEN_WECHAT_SHOP_LOCK_VALUE = "wechat:shop:lock";
/**
* Redis微信小店认证Token锁时间,秒
*/
int REDIS_TOKEN_WECHAT_SHOP_LOCK_TIME = 5;
/**
* Redis商品详情缓存KEY
*/
String REDIS_PRODUCT_DETAIL_KEY = "PRODUCT:DETAIL:";
/**
* Redis商品详情过期时间,秒
*/
int REDIS_PRODUCT_DETAIL_EXPIRE_SECONDS = 6 * 60 * 60;
} }
package com.netease.yanxuan.wx.store.sharer.common.handler; package com.netease.yanxuan.wx.store.sharer.common.handler;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -49,4 +50,12 @@ public class RedisClient { ...@@ -49,4 +50,12 @@ public class RedisClient {
public Boolean delete(String key) { public Boolean delete(String key) {
return redisTemplate.delete(key); return redisTemplate.delete(key);
} }
public Boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
public BoundValueOperations<String, Object> boundValueOps(String key) {
return redisTemplate.boundValueOps(key);
}
} }
\ No newline at end of file
/**
* @(#)PhoneCheckUtils.java, 2022/7/25.
* <p/>
* Copyright 2022 Netease, Inc. All rights reserved.
* NETEASE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.netease.yanxuan.wx.store.sharer.common.util;
import org.apache.commons.lang3.StringUtils;
import java.util.regex.Pattern;
/**
* @author 张艳(wb.zhangyan12 @ mesg.corp.netease.com)
*/
public class PhoneCheckUtils {
private static final String regex = "^[1][0-9]{10}$";
/**
* 手机号码格式验证
*
* @param phone 手机号
*/
public static boolean checkPhoneFormat(String phone) {
if (StringUtils.isBlank(phone)) {
return false;
}
if (phone.length() != 11) {
return false;
} else {
return Pattern.compile(regex).matcher(phone).matches();
}
}
}
\ No newline at end of file
/**
* @(#)RandomUtils.java, 2022/7/25.
* <p/>
* Copyright 2022 Netease, Inc. All rights reserved.
* NETEASE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.netease.yanxuan.wx.store.sharer.common.util;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author 张艳(wb.zhangyan12 @ mesg.corp.netease.com)
*/
public class RandomUtils {
private static final String CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final String NUMBER = "0123456789";
/**
* 获取随机字符串
*
* @param length 生成的随机字符串长度
* @return 返回随机字符串
*/
public static String randomString(int length) {
return randomString(CHARS, length);
}
/**
* 获取随机数字字符串
*
* @param length
* @return
*/
public static String randomNumber(int length) {
return randomString(NUMBER, length);
}
/**
* 获取随机字符串
*
* @param sampleString 样本字符串
* @param length 生成的随机字符串长度
* @return 返回随机字符串
*/
public static String randomString(String sampleString, int length) {
if (sampleString == null || sampleString.length() == 0) {
return "";
}
if (length < 1) {
length = 1;
}
final StringBuilder sb = new StringBuilder(length);
int baseLength = sampleString.length();
while (sb.length() < length) {
int number = ThreadLocalRandom.current().nextInt(baseLength);
sb.append(sampleString.charAt(number));
}
return sb.toString();
}
public static String genUUID() {
return UUID.randomUUID().toString().replace("-", "");
}
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderBuyer;
/**
* 推客佣金单买家表Mapper
*/
public interface SharerOrderBuyerMapper extends BaseMapper<SharerOrderBuyer> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderCommissionFinder;
/**
* 推客佣金单分佣视频号达人表Mapper
*/
public interface SharerOrderCommissionFinderMapper extends BaseMapper<SharerOrderCommissionFinder> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderCommission;
/**
* 推客佣金单分佣表Mapper
*/
public interface SharerOrderCommissionMapper extends BaseMapper<SharerOrderCommission> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderCommissionPromoterAgency;
/**
* 推客佣金单分佣推客机构表Mapper
*/
public interface SharerOrderCommissionPromoterAgencyMapper extends BaseMapper<SharerOrderCommissionPromoterAgency> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderCommissionSharer;
/**
* 推客佣金单分佣推客表Mapper
*/
public interface SharerOrderCommissionSharerMapper extends BaseMapper<SharerOrderCommissionSharer> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderCommissionSubAgency;
/**
* 推客佣金单分佣帮卖机构表Mapper
*/
public interface SharerOrderCommissionSubAgencyMapper extends BaseMapper<SharerOrderCommissionSubAgency> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderCommissionTalent;
/**
* 推客佣金单分佣达人表Mapper
*/
public interface SharerOrderCommissionTalentMapper extends BaseMapper<SharerOrderCommissionTalent> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrder;
/**
* 推客佣金单表Mapper
*/
public interface SharerOrderMapper extends BaseMapper<SharerOrder> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderProduct;
/**
* 推客佣金单商品表Mapper
*/
public interface SharerOrderProductMapper extends BaseMapper<SharerOrderProduct> {
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.netease.yanxuan.wx.store.sharer.dal.meta.model.po.SharerOrderSyncFail;
/**
* 推客佣金单同步失败表Mapper
*/
public interface SharerOrderSyncFailMapper extends BaseMapper<SharerOrderSyncFail> {
}
\ No newline at end of file
...@@ -49,6 +49,18 @@ public class SharerInfo implements Serializable { ...@@ -49,6 +49,18 @@ public class SharerInfo implements Serializable {
*/ */
private Integer commissionType; private Integer commissionType;
/** /**
* 姓名
*/
private String username;
/**
* 身份证号
*/
private String idCardNumber;
/**
* 手机号
*/
private String mobilePhone;
/**
* 创建时间 * 创建时间
*/ */
private Date createTime; private Date createTime;
......
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单表
*/
@Data
@TableName("SHARER_ORDER")
public class SharerOrder {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 订单号
*/
private String orderId;
/**
* 商品skuid
*/
private String skuId;
/**
* 佣金单状态
*/
private String commissionStatus;
/**
* 订单状态
*/
private String orderStatus;
/**
* 订单创建时间
*/
private Long orderCreateTime;
/**
* 订单更新时间
*/
private Long orderUpdateTime;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单买家表
*/
@Data
@TableName("SHARER_ORDER_BUYER")
public class SharerOrderBuyer {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 佣金单ID
*/
private Long sharerOrderId;
/**
* 购买者的openid
*/
private String openId;
/**
* 购买者的unionid
*/
private String unionId;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单分佣表
*/
@Data
@TableName("SHARER_ORDER_COMMISSION")
public class SharerOrderCommission {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 佣金单ID
*/
private Long sharerOrderId;
/**
* 服务费率[0, 1000000]
*/
private Integer serviceRatio;
/**
* 服务费金额
*/
private Integer serviceAmount;
/**
* 服务费结算时间
*/
private Long profitShardingSucTime;
/**
* 0-橱窗带货,1-推客带货
*/
private Integer promotionChannel;
/**
* 作为推客的时候,推广的一些参数
*/
private String promotionInfo;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单分佣视频号达人表
*/
@Data
@TableName("SHARER_ORDER_COMMISSION_FINDER")
public class SharerOrderCommissionFinder {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 佣金单ID
*/
private Long sharerOrderId;
/**
* 佣金单分佣ID
*/
private Long sharerOrderCommissionId;
/**
* 视频号昵称
*/
private String nickname;
/**
* 佣金率[0, 1000000]
*/
private Integer ratio;
/**
* 佣金
*/
private Integer amount;
/**
* 视频号openfinderid
*/
private String openfinderid;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单分佣推客机构表
*/
@Data
@TableName("SHARER_ORDER_COMMISSION_PROMOTER_AGENCY")
public class SharerOrderCommissionPromoterAgency {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 佣金单ID
*/
private Long sharerOrderId;
/**
* 佣金单分佣ID
*/
private Long sharerOrderCommissionId;
/**
* 推客机构appid
*/
private String appid;
/**
* 推客机构昵称
*/
private String nickname;
/**
* 推客机构服务费率[0, 1000000]
*/
private Integer ratio;
/**
* 推客机构服务费
*/
private Integer amount;
/**
* 推客机构服务费结算时间
*/
private Long profitShardingSucTime;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单分佣推客表
*/
@Data
@TableName("SHARER_ORDER_COMMISSION_SHARER")
public class SharerOrderCommissionSharer {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 佣金单ID
*/
private Long sharerOrderId;
/**
* 佣金单分佣ID
*/
private Long sharerOrderCommissionId;
/**
* 推客appid
*/
private String sharerAppid;
/**
* 推客昵称
*/
private String nickname;
/**
* 推客佣金率[0, 1000000]
*/
private Integer ratio;
/**
* 推客佣金
*/
private Integer amount;
/**
* 推客的opensharerid
*/
private String opensharerid;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单分佣帮卖机构表
*/
@Data
@TableName("SHARER_ORDER_COMMISSION_SUB_AGENCY")
public class SharerOrderCommissionSubAgency {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 佣金单ID
*/
private Long sharerOrderId;
/**
* 佣金单分佣ID
*/
private Long sharerOrderCommissionId;
/**
* 帮卖机构appid
*/
private String appid;
/**
* 帮卖机构昵称
*/
private String nickname;
/**
* 帮卖机构服务费率[0, 1000000]
*/
private Integer ratio;
/**
* 帮卖机构服务费
*/
private Integer amount;
/**
* 帮卖机构服务费结算时间
*/
private Long profitShardingSucTime;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单分佣达人表
*/
@Data
@TableName("SHARER_ORDER_COMMISSION_TALENT")
public class SharerOrderCommissionTalent {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 佣金单ID
*/
private Long sharerOrderId;
/**
* 佣金单分佣ID
*/
private Long sharerOrderCommissionId;
/**
* 新带货达人appid
*/
private String talent_appid;
/**
* 达人昵称
*/
private String nickname;
/**
* 达人佣金率[0, 1000000]
*/
private Integer ratio;
/**
* 达人佣金
*/
private Integer amount;
/**
* 带货助手的opentalentid
*/
private String opentalentid;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单商品表
*/
@Data
@TableName("SHARER_ORDER_PRODUCT")
public class SharerOrderProduct {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 佣金单ID
*/
private Long sharerOrderId;
/**
* 店铺ID
*/
private String shopAppid;
/**
* 商品id
*/
private String productId;
/**
* sku小图
*/
private String thumbImg;
/**
* 可分佣金额
*/
private Integer actualPayment;
/**
* 商品标题
*/
private String title;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.dal.meta.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 推客佣金单同步失败表
*/
@Data
@TableName("SHARER_ORDER_SYNC_FAIL")
public class SharerOrderSyncFail {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 订单号
*/
private String orderId;
/**
* 商品skuid
*/
private String skuId;
/**
* 重试次数
*/
private Integer retryCount;
/**
* 失败信息
*/
private String failMsg;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
\ No newline at end of file
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
<groupId>com.netease.yanxuan</groupId> <groupId>com.netease.yanxuan</groupId>
<artifactId>yanxuan-wx-store-sharer-common</artifactId> <artifactId>yanxuan-wx-store-sharer-common</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.netease.yanxuan</groupId>
<artifactId>user-info-client</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.integration.client;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.SmsCodeScenesConfigBO;
/**
* @Description Uas服务
* @Author fanjiaxin
* @Date 2025/5/14 13:47
*/
public interface IUasClient {
/**
* 发送短信
*/
boolean sendSmsCode(String uid, String phone, String code,
String scenes, SmsCodeScenesConfigBO scenesConfigBO);
}
package com.netease.yanxuan.wx.store.sharer.integration.client;
/**
* @Description UserInfo服务
* @Author fanjiaxin
* @Date 2025/5/14 13:47
*/
public interface IUserInfoClient {
/**
* 实名认证
*/
Boolean verifyByIdentityNo(String realName, String identityNo);
}
/**
* @(#)UasClientImpl.java, 2022/7/27.
* <p/>
* Copyright 2022 Netease, Inc. All rights reserved.
* NETEASE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.netease.yanxuan.wx.store.sharer.integration.client.impl;
import com.alibaba.fastjson.JSON;
import com.netease.yanxuan.missa.specs.interfaces.response.MissaResponse;
import com.netease.yanxuan.wx.store.sharer.integration.client.IUasClient;
import com.netease.yanxuan.wx.store.sharer.integration.facade.UasFacade;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.SmsCodeScenesConfigBO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@Slf4j
@RequiredArgsConstructor
@Service
public class UasClientImpl implements IUasClient {
private final UasFacade uasFacade;
private static final String TOPIC_FORMAT = "verify_%s";
/**
* 发送验证码
*
* @param phone 手机号码
* @param code 验证码
* @param scenes 业务场景标识
*/
@Override
public boolean sendSmsCode(String uid, String phone, String code,
String scenes, SmsCodeScenesConfigBO scenesConfigBO) {
// 构建入参
MultiValueMap<String, Object> params = assembleSmsArg(uid, phone, code, scenes, scenesConfigBO);
log.info("[op:UasClientImpl:sendSmsCode] params:{}", JSON.toJSONString(params));
try {
MissaResponse<Void> missaResponse = uasFacade.pushSmsCode(params);
log.info("[op:UasClientImpl:sendSmsCode] rpcResult:{}", JSON.toJSONString(missaResponse));
return null != missaResponse && missaResponse.isOK() && HttpStatus.OK.value() == missaResponse.getCode();
} catch (Exception e) {
log.error("[op:UasClientImpl:sendSmsCode] is error", e);
}
return false;
}
private MultiValueMap<String, Object> assembleSmsArg(String uid, String phone,
String code, String scenes,
SmsCodeScenesConfigBO scenesConfigBO) {
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(5);
params.add("phone", phone);
params.add("message", String.format(scenesConfigBO.getMessageFormat(), code, scenesConfigBO.getCodeValidMinutes()));
params.add("level", 1);
params.add("uid", uid);
params.add("topic", String.format(TOPIC_FORMAT, scenes));
return params;
}
}
/**
* @(#)UasClientImpl.java, 2022/7/27.
* <p/>
* Copyright 2022 Netease, Inc. All rights reserved.
* NETEASE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.netease.yanxuan.wx.store.sharer.integration.client.impl;
import com.alibaba.fastjson.JSON;
import com.netease.yanxuan.userinfo.client.meta.CommonResult;
import com.netease.yanxuan.wx.store.sharer.integration.client.IUserInfoClient;
import com.netease.yanxuan.wx.store.sharer.integration.facade.UserInfoFacade;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.UserInfoVerifyByIdentityNoBO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
@Slf4j
@RequiredArgsConstructor
@Service
public class UserInfoClientImpl implements IUserInfoClient {
private final UserInfoFacade userInfoFacade;
@Override
public Boolean verifyByIdentityNo(String realName, String identityNo) {
log.info("[op:UserInfoClientImpl:verifyByIdentityNo] realName:{}, identityNo:{}", realName, identityNo);
try {
UserInfoVerifyByIdentityNoBO bo = UserInfoVerifyByIdentityNoBO.builder().realName(realName).identityNo(identityNo).build();
CommonResult<Boolean> missaResponse = userInfoFacade.verifyByIdentityNo(bo);
log.info("[op:UserInfoClientImpl:verifyByIdentityNo] missaResponse:{}", JSON.toJSONString(missaResponse));
if (null != missaResponse && HttpStatus.OK.value() == missaResponse.getCode()) {
return missaResponse.getResult();
}
} catch (Exception e) {
log.error("[op:UserInfoClientImpl:verifyByIdentityNo] is error", e);
}
return false;
}
}
package com.netease.yanxuan.wx.store.sharer.integration.config;
import com.ctrip.framework.apollo.spring.annotation.EnableAutoUpdateApolloConfig;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Getter
@Component
@EnableAutoUpdateApolloConfig("rpc.config")
public class RpcConfig {
}
package com.netease.yanxuan.wx.store.sharer.integration.config;
import com.ctrip.framework.apollo.spring.annotation.EnableAutoUpdateApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ValueMapping;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.SmsCodeScenesConfigBO;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @Description 应用配置
* @Author fanjiaxin
* @Date 2025/3/10 17:26
*/
@Data
@Component
@EnableAutoUpdateApolloConfig("sms.config")
public class SmsConfig {
/**
* 场景验证码配置
* key: 业务场景标识
*/
@ValueMapping("${scenes.config.map:{\"REAL_NAME_AUTHENTICATED\":{\"sendIntervalSeconds\":60,\"codeValidMinutes\":5,\"messageFormat\":\"【网易】验证码:%s,您正在实名认证,%s分钟内输入有效(若非本人操作,请删除本短信)\",\"sendMaxCount\":10}}}")
private Map<String, SmsCodeScenesConfigBO> scenesConfigMap;
public SmsCodeScenesConfigBO getScenesConfig(String scenes) {
return scenesConfigMap.get(scenes);
}
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.integration.constant;
/**
* @Description 短信常量类
* @Author fanjiaxin
* @Date 2025/3/11 11:59
*/
public class SmsConstant {
/**
* 短信验证码缓存key,公共前缀
*/
public static final String SMS_VERIFY_CODE_COMMON_PREFIX = "act_mobile_verify_";
/**
* 验证码发送标记缓存
* 验证码使用业务场景标识+手机号
*/
public static final String SMS_SEND_INTERVAL_KEY = SMS_VERIFY_CODE_COMMON_PREFIX + "send_interval_%s_%s";
/**
* 用户当前验证码缓存
* 验证码使用业务场景标识+手机号
*/
public static final String SMS_CODE_KEY = SMS_VERIFY_CODE_COMMON_PREFIX + "code_%s_%s";
/**
* 验证码每日发送次数上限缓存
* 验证码使用业务场景标识+手机号+今日0点时间戳毫秒
*/
public static final String SMS_SEND_COUNT_KEY = SMS_VERIFY_CODE_COMMON_PREFIX + "send_count_%s_%s_%s";
/**
* 验证码每日校验次数上限缓存
* 验证码使用业务场景标识+手机号+今日0点时间戳毫秒
*/
public static final String SMS_VERIFY_COUNT_KEY = SMS_VERIFY_CODE_COMMON_PREFIX + "verify_count_%s_%s_%s";
}
...@@ -68,4 +68,17 @@ public class WeChatApi { ...@@ -68,4 +68,17 @@ public class WeChatApi {
* 设置推客的单个商品的分佣比例信息 * 设置推客的单个商品的分佣比例信息
*/ */
public static final String SET_SHARER_PRODUCT_COMMISSION_INFO = "/channels/ec/promoter/set_sharer_product_commission_info"; public static final String SET_SHARER_PRODUCT_COMMISSION_INFO = "/channels/ec/promoter/set_sharer_product_commission_info";
// -------------------------------------- 分佣单 --------------------------------------
/**
* 获取分佣单列表
*/
public static final String GET_COMMISSION_ORDER_LIST = "/channels/ec/league/headsupplier/order/list/get";
/**
* 获取分佣单详情
*/
public static final String GET_COMMISSION_ORDER_DETAIL = "/channels/ec/league/headsupplier/order/get";
} }
package com.netease.yanxuan.wx.store.sharer.integration.constant;
/**
* @Description 微信常量信息
* @Author fanjiaxin
* @Date 2025/3/9 13:15
*/
public interface WeChatConstant {
/**
* Redis微信认证Token
*/
String REDIS_TOKEN_WECHAT_KEY = "TOKEN:WECHAT";
/**
* Redis微信认证Token锁
*/
String REDIS_TOKEN_WECHAT_LOCK_KEY = "TOKEN:WECHAT:LOCK";
/**
* Redis微信认证Token锁时间,秒
*/
String REDIS_TOKEN_WECHAT_LOCK_VALUE = "wechat:lock";
/**
* Redis微信认证Token锁时间,秒
*/
int REDIS_TOKEN_WECHAT_LOCK_TIME = 5;
/**
* Redis微信小店认证Token
*/
String REDIS_TOKEN_WECHAT_SHOP_KEY = "TOKEN:WECHAT:SHOP";
/**
* Redis微信小店认证Token锁
*/
String REDIS_TOKEN_WECHAT_SHOP_LOCK_KEY = "TOKEN:WECHAT:SHOP:LOCK";
/**
* Redis微信小店认证Token锁时间,秒
*/
String REDIS_TOKEN_WECHAT_SHOP_LOCK_VALUE = "wechat:shop:lock";
/**
* Redis微信小店认证Token锁时间,秒
*/
int REDIS_TOKEN_WECHAT_SHOP_LOCK_TIME = 5;
/**
* Redis商品详情缓存KEY
*/
String REDIS_PRODUCT_DETAIL_KEY = "PRODUCT:DETAIL:";
/**
* Redis商品详情过期时间,秒
*/
int REDIS_PRODUCT_DETAIL_EXPIRE_SECONDS = 6 * 60 * 60;
}
package com.netease.yanxuan.wx.store.sharer.integration.core; package com.netease.yanxuan.wx.store.sharer.integration.core;
import com.netease.yanxuan.wx.store.sharer.common.constant.CoreConstant;
import com.netease.yanxuan.wx.store.sharer.common.exception.WeChatException; import com.netease.yanxuan.wx.store.sharer.common.exception.WeChatException;
import com.netease.yanxuan.wx.store.sharer.common.handler.RedisClient; import com.netease.yanxuan.wx.store.sharer.common.handler.RedisClient;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatConstant;
import com.netease.yanxuan.wx.store.sharer.integration.handler.impl.WeChatShopAccessTokenRequest; import com.netease.yanxuan.wx.store.sharer.integration.handler.impl.WeChatShopAccessTokenRequest;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatAccessTokenVO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatAccessTokenVO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
...@@ -33,7 +33,7 @@ public class WeChatContextHolder { ...@@ -33,7 +33,7 @@ public class WeChatContextHolder {
*/ */
public String getShopAccessToken() { public String getShopAccessToken() {
// 检查锁定 // 检查锁定
String accessToken = redisClient.getStr(CoreConstant.REDIS_TOKEN_WECHAT_SHOP_KEY); String accessToken = redisClient.getStr(WeChatConstant.REDIS_TOKEN_WECHAT_SHOP_KEY);
if (StringUtils.isNotBlank(accessToken)) { if (StringUtils.isNotBlank(accessToken)) {
return accessToken; return accessToken;
} }
...@@ -46,15 +46,15 @@ public class WeChatContextHolder { ...@@ -46,15 +46,15 @@ public class WeChatContextHolder {
public String createShopAccessToken() { public String createShopAccessToken() {
try { try {
// 设置10秒的锁 // 设置10秒的锁
boolean locked = redisClient.setIfAbsent(CoreConstant.REDIS_TOKEN_WECHAT_SHOP_LOCK_KEY, boolean locked = redisClient.setIfAbsent(WeChatConstant.REDIS_TOKEN_WECHAT_SHOP_LOCK_KEY,
CoreConstant.REDIS_TOKEN_WECHAT_SHOP_LOCK_VALUE, CoreConstant.REDIS_TOKEN_WECHAT_SHOP_LOCK_TIME); WeChatConstant.REDIS_TOKEN_WECHAT_SHOP_LOCK_VALUE, WeChatConstant.REDIS_TOKEN_WECHAT_SHOP_LOCK_TIME);
if (!locked) { if (!locked) {
// 未获取到锁,等待一段时间后重试 // 未获取到锁,等待一段时间后重试
TimeUnit.MILLISECONDS.sleep(RETRY_DELAY_MS); TimeUnit.MILLISECONDS.sleep(RETRY_DELAY_MS);
return getShopAccessToken(); return getShopAccessToken();
} }
WeChatAccessTokenVO handle = weChatShopAccessTokenRequest.handle(); WeChatAccessTokenVO handle = weChatShopAccessTokenRequest.handle();
redisClient.setStr(CoreConstant.REDIS_TOKEN_WECHAT_SHOP_KEY, handle.getAccess_token(), redisClient.setStr(WeChatConstant.REDIS_TOKEN_WECHAT_SHOP_KEY, handle.getAccess_token(),
handle.getExpires_in() - EXPIRE_SECONDS); handle.getExpires_in() - EXPIRE_SECONDS);
return handle.getAccess_token(); return handle.getAccess_token();
} catch (InterruptedException e) { } catch (InterruptedException e) {
......
package com.netease.yanxuan.wx.store.sharer.integration.facade;
import com.netease.yanxuan.missa.client.annotation.MissaClient;
import com.netease.yanxuan.missa.specs.interfaces.response.MissaResponse;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@MissaClient(serviceCode = "logistics-uas")
public interface UasFacade {
@RequestMapping(value = "/push/sms/yanxuan-wx-store-sharer",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
MissaResponse<Void> pushSmsCode(@RequestParam MultiValueMap<String, Object> formData);
}
package com.netease.yanxuan.wx.store.sharer.integration.facade;
import com.netease.yanxuan.missa.client.annotation.MissaClient;
import com.netease.yanxuan.userinfo.client.meta.CommonResult;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.UserInfoVerifyByIdentityNoBO;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@MissaClient(serviceCode = "user-info")
public interface UserInfoFacade {
@RequestMapping(value = "/user/realName/verifyByIdentityNo", method = RequestMethod.POST)
CommonResult<Boolean> verifyByIdentityNo(@RequestBody UserInfoVerifyByIdentityNoBO bo);
}
package com.netease.yanxuan.wx.store.sharer.integration.handler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.netease.yanxuan.wx.store.sharer.common.exception.BizException;
import com.netease.yanxuan.wx.store.sharer.common.handler.RestTemplateClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
/**
* @Description RestTemplateClient
* @Author fanjiaxin
* @Date 2025/3/11 17:27
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class RestTemplateHandler {
private final RestTemplateClient restTemplateClient;
/**
* 执行操作
*/
public <T, R> R execute(String url, HttpMethod method, T params, Class<R> resType) {
try {
log.info("[op:RestTemplateHandler.execute] url:{} params:{}", url, JSONObject.toJSONString(params));
String resultJson = restTemplateClient.execute(url, method, params);
log.info("[op:RestTemplateHandler.execute] result:{}", resultJson);
return JSON.parseObject(resultJson, resType);
} catch (Exception e) {
log.info("[op:RestTemplateHandler.execute] is error", e);
throw new BizException(e);
}
}
}
package com.netease.yanxuan.wx.store.sharer.integration.handler; package com.netease.yanxuan.wx.store.sharer.integration.handler;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.netease.yanxuan.wx.store.sharer.common.constant.CoreConstant; import com.alibaba.fastjson.JSONObject;
import com.netease.yanxuan.wx.store.sharer.common.exception.WeChatException; import com.netease.yanxuan.wx.store.sharer.common.exception.WeChatException;
import com.netease.yanxuan.wx.store.sharer.common.handler.RedisClient; import com.netease.yanxuan.wx.store.sharer.common.handler.RedisClient;
import com.netease.yanxuan.wx.store.sharer.common.handler.RestTemplateClient; import com.netease.yanxuan.wx.store.sharer.common.handler.RestTemplateClient;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi; import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatConstant;
import com.netease.yanxuan.wx.store.sharer.integration.meta.enums.WeChatErrorCodeEnum; import com.netease.yanxuan.wx.store.sharer.integration.meta.enums.WeChatErrorCodeEnum;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatCoreVO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatCoreVO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
...@@ -30,16 +31,19 @@ public class WeChatRestTemplateHandler { ...@@ -30,16 +31,19 @@ public class WeChatRestTemplateHandler {
public <T, R extends WeChatCoreVO> R execute(String url, HttpMethod method, T params, Class<R> resType) { public <T, R extends WeChatCoreVO> R execute(String url, HttpMethod method, T params, Class<R> resType) {
R result; R result;
try { try {
log.info("[op:WeChatRestTemplateHandler.execute] url:{} params:{}", url, JSONObject.toJSONString(params));
String resultJson = restTemplateClient.execute(url, method, params); String resultJson = restTemplateClient.execute(url, method, params);
log.info("[op:WeChatRestTemplateHandler.execute] result:{}", resultJson);
result = JSON.parseObject(resultJson, resType); result = JSON.parseObject(resultJson, resType);
} catch (Exception e) { } catch (Exception e) {
log.info("[op:WeChatRestTemplateHandler.execute] is error", e);
throw new WeChatException(e); throw new WeChatException(e);
} }
if (StringUtils.isNotBlank(result.getErrcode()) if (StringUtils.isNotBlank(result.getErrcode())
&& !WeChatApi.WECHAT_REQUEST_SUCCESS_CODE.equals(result.getErrcode())) { && !WeChatApi.WECHAT_REQUEST_SUCCESS_CODE.equals(result.getErrcode())) {
if(WeChatErrorCodeEnum.INVALID_CREDENTIAL.getCode().equals(result.getErrcode())){ if(WeChatErrorCodeEnum.INVALID_CREDENTIAL.getCode().equals(result.getErrcode())){
// token过期,清除微信小店认证信息 // token过期,清除微信小店认证信息
redisClient.delete(CoreConstant.REDIS_TOKEN_WECHAT_SHOP_KEY); redisClient.delete(WeChatConstant.REDIS_TOKEN_WECHAT_SHOP_KEY);
} }
throw new WeChatException(String.join(",","调用微信接口失败" + result.getErrmsg())); throw new WeChatException(String.join(",","调用微信接口失败" + result.getErrmsg()));
} }
......
package com.netease.yanxuan.wx.store.sharer.integration.handler.impl;
import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder;
import com.netease.yanxuan.wx.store.sharer.integration.handler.IWeChatRequest;
import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplateHandler;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatCommissionOrderDetailBO;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatCommissionOrderDetailVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
/**
* @Description 微信小店-分佣单详情请求
* @Author fanjiaxin
* @Date 2025/3/11 17:33
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class WeChatCommissionOrderDetailRequest implements IWeChatRequest {
private final WeChatContextHolder weChatContextHolder;
private final WeChatRestTemplateHandler weChatRestTemplateHandler;
private final WeChatConfig weChatConfig;
@Override
public HttpMethod getRequestMethod() {
return HttpMethod.POST;
}
@Override
public String getRequestUrl() {
return weChatConfig.getUrl() + WeChatApi.GET_COMMISSION_ORDER_DETAIL
+ "?" + WeChatApi.WECHAT_REQUEST_TOKEN_FIELD_NAME + "="
+ weChatContextHolder.getShopAccessToken();
}
/**
* 处理
*/
public WeChatCommissionOrderDetailVO handle(String orderId, String skuId) {
WeChatCommissionOrderDetailBO params = WeChatCommissionOrderDetailBO.builder()
.order_id(orderId)
.sku_id(skuId)
.build();
return weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(),
params, WeChatCommissionOrderDetailVO.class);
}
}
package com.netease.yanxuan.wx.store.sharer.integration.handler.impl;
import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder;
import com.netease.yanxuan.wx.store.sharer.integration.handler.IWeChatRequest;
import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplateHandler;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatCommissionOrderListBO;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatTimeRangeBO;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatCommissionOrderListVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
/**
* @Description 微信小店-分佣单列表请求
* @Author fanjiaxin
* @Date 2025/3/11 17:33
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class WeChatCommissionOrderListRequest implements IWeChatRequest {
private final WeChatContextHolder weChatContextHolder;
private final WeChatRestTemplateHandler weChatRestTemplateHandler;
private final WeChatConfig weChatConfig;
@Override
public HttpMethod getRequestMethod() {
return HttpMethod.POST;
}
@Override
public String getRequestUrl() {
return weChatConfig.getUrl() + WeChatApi.GET_COMMISSION_ORDER_LIST
+ "?" + WeChatApi.WECHAT_REQUEST_TOKEN_FIELD_NAME + "="
+ weChatContextHolder.getShopAccessToken();
}
/**
* 处理
*/
public WeChatCommissionOrderListVO handle(Long startTime, Long endTime, String nextKey, Integer pageSize) {
WeChatCommissionOrderListBO params = WeChatCommissionOrderListBO.builder()
.update_time_range(WeChatTimeRangeBO.builder().start_time(startTime).end_time(endTime).build())
.next_key(nextKey)
.page_size(pageSize)
.build();
return weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(),
params, WeChatCommissionOrderListVO.class);
}
}
package com.netease.yanxuan.wx.store.sharer.integration.handler.impl; package com.netease.yanxuan.wx.store.sharer.integration.handler.impl;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig; import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi; import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder; import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder;
...@@ -12,9 +8,10 @@ import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplat ...@@ -12,9 +8,10 @@ import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplat
import com.netease.yanxuan.wx.store.sharer.integration.meta.enums.CommissionTypeEnum; import com.netease.yanxuan.wx.store.sharer.integration.meta.enums.CommissionTypeEnum;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatSetSharerCommissionBO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatSetSharerCommissionBO;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatCoreVO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatCoreVO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
/** /**
* @Description 设置推客的分佣比例信息 * @Description 设置推客的分佣比例信息
...@@ -51,9 +48,6 @@ public class WeChatShopSetSharerCommissionRequest implements IWeChatRequest { ...@@ -51,9 +48,6 @@ public class WeChatShopSetSharerCommissionRequest implements IWeChatRequest {
.commission_type(CommissionTypeEnum.PLATFORM.getCode()) .commission_type(CommissionTypeEnum.PLATFORM.getCode())
.commission_ratio(commissionRatio) .commission_ratio(commissionRatio)
.build(); .build();
log.info("[op:WeChatShopSetSharerCommissionRequest.handle] requestParam={}", JSONObject.toJSONString(params)); return weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(), params, WeChatCoreVO.class);
WeChatCoreVO res = weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(), params, WeChatCoreVO.class);
log.info("[op:WeChatShopSetSharerCommissionRequest.handle] res={}", JSONObject.toJSONString(res));
return res;
} }
} }
package com.netease.yanxuan.wx.store.sharer.integration.handler.impl; package com.netease.yanxuan.wx.store.sharer.integration.handler.impl;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig; import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi; import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder; import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder;
...@@ -11,9 +7,10 @@ import com.netease.yanxuan.wx.store.sharer.integration.handler.IWeChatRequest; ...@@ -11,9 +7,10 @@ import com.netease.yanxuan.wx.store.sharer.integration.handler.IWeChatRequest;
import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplateHandler; import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplateHandler;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatSetSharerProductCommissionBO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatSetSharerProductCommissionBO;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatCoreVO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatCoreVO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
/** /**
* @Description 设置推客的单个商品的分佣比例信息 * @Description 设置推客的单个商品的分佣比例信息
...@@ -50,9 +47,6 @@ public class WeChatShopSetSharerProductCommissionRequest implements IWeChatReque ...@@ -50,9 +47,6 @@ public class WeChatShopSetSharerProductCommissionRequest implements IWeChatReque
.product_id(productId) .product_id(productId)
.commission_ratio(commissionRatio) .commission_ratio(commissionRatio)
.build(); .build();
log.info("[op:WeChatShopSetSharerProductCommissionRequest.handle] requestParam={}", JSONObject.toJSONString(params)); return weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(), params, WeChatCoreVO.class);
WeChatCoreVO res = weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(), params, WeChatCoreVO.class);
log.info("[op:WeChatShopSetSharerProductCommissionRequest.handle] res={}", JSONObject.toJSONString(res));
return res;
} }
} }
package com.netease.yanxuan.wx.store.sharer.integration.handler.impl; package com.netease.yanxuan.wx.store.sharer.integration.handler.impl;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig; import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi; import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder; import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder;
...@@ -11,9 +7,10 @@ import com.netease.yanxuan.wx.store.sharer.integration.handler.IWeChatRequest; ...@@ -11,9 +7,10 @@ import com.netease.yanxuan.wx.store.sharer.integration.handler.IWeChatRequest;
import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplateHandler; import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplateHandler;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatSharerListBO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatSharerListBO;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatSharerListVO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatSharerListVO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
/** /**
* @Description 获取机构绑定的推客信息 * @Description 获取机构绑定的推客信息
...@@ -50,9 +47,6 @@ public class WeChatShopSharerListRequest implements IWeChatRequest { ...@@ -50,9 +47,6 @@ public class WeChatShopSharerListRequest implements IWeChatRequest {
.next_key(nextKey) .next_key(nextKey)
.page_size(pageSize) .page_size(pageSize)
.build(); .build();
log.info("[op:WeChatShopSharerListRequest.handle] requestParam={}", JSONObject.toJSONString(params)); return weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(), params, WeChatSharerListVO.class);
WeChatSharerListVO res = weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(), params, WeChatSharerListVO.class);
log.info("[op:WeChatShopSharerListRequest.res] res={}", JSONObject.toJSONString(res));
return res;
} }
} }
package com.netease.yanxuan.wx.store.sharer.integration.handler.impl; package com.netease.yanxuan.wx.store.sharer.integration.handler.impl;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig; import com.netease.yanxuan.wx.store.sharer.integration.config.WeChatConfig;
import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi; import com.netease.yanxuan.wx.store.sharer.integration.constant.WeChatApi;
import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder; import com.netease.yanxuan.wx.store.sharer.integration.core.WeChatContextHolder;
...@@ -11,9 +7,10 @@ import com.netease.yanxuan.wx.store.sharer.integration.handler.IWeChatRequest; ...@@ -11,9 +7,10 @@ import com.netease.yanxuan.wx.store.sharer.integration.handler.IWeChatRequest;
import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplateHandler; import com.netease.yanxuan.wx.store.sharer.integration.handler.WeChatRestTemplateHandler;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatSharerRegisterBindBO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo.WeChatSharerRegisterBindBO;
import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatSharerRegisterBindVO; import com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo.WeChatSharerRegisterBindVO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
/** /**
* @Description 微信凭证请求 * @Description 微信凭证请求
...@@ -49,9 +46,6 @@ public class WeChatShopSharerRegisterBindRequest implements IWeChatRequest { ...@@ -49,9 +46,6 @@ public class WeChatShopSharerRegisterBindRequest implements IWeChatRequest {
.is_simple_register(true) .is_simple_register(true)
.sharer_openid(sharerOpenid) .sharer_openid(sharerOpenid)
.build(); .build();
log.info("[op:WeChatShopSharerRegisterBindRequest.handle] requestParam={}", JSONObject.toJSONString(params)); return weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(), params, WeChatSharerRegisterBindVO.class);
WeChatSharerRegisterBindVO res = weChatRestTemplateHandler.execute(getRequestUrl(), getRequestMethod(), params, WeChatSharerRegisterBindVO.class);
log.info("[op:WeChatShopSharerRegisterBindRequest.handle] res={}", JSONObject.toJSONString(res));
return res;
} }
} }
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 短信验证码-配置-业务对象
* @Author fanjiaxin
* @Date 2025/3/11 18:43
*/
@Data
@Builder
public class SmsCodeScenesConfigBO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 验证码发送间隔时间,秒
*/
private Integer sendIntervalSeconds;
/**
* 验证码有效时间,分钟
*/
private Integer codeValidMinutes;
/**
* 验证码短信格式
*/
private String messageFormat;
/**
* 验证码发送最大次数
*/
private Integer sendMaxCount;
}
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 用户实名认证-业务对象
* @Author fanjiaxin
* @Date 2025/3/11 18:43
*/
@Data
@Builder
public class UserInfoVerifyByIdentityNoBO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 姓名
*/
private String realName;
/**
* 身份证号
*/
private String identityNo;
}
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 分佣单详情-业务对象
* @Author fanjiaxin
* @Date 2025/3/11 18:43
*/
@Data
@Builder
public class WeChatCommissionOrderDetailBO implements Serializable {
private static final long serialVersionUID = 1996751915518651231L;
/**
* 订单ID
*/
private String order_id;
/**
* 商品SKU ID
*/
private String sku_id;
}
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 分佣单列表-业务对象
* @Author fanjiaxin
* @Date 2025/3/11 18:43
*/
@Data
@Builder
public class WeChatCommissionOrderListBO implements Serializable {
private static final long serialVersionUID = 1996751915518651231L;
/**
* 佣金单更新时间范围
*/
private WeChatTimeRangeBO update_time_range;
/**
* 是否还有剩余商品
*/
private Boolean has_more;
/**
* 分页参数,第一页为空,后面返回前面一页返回的数据
*/
private String next_key;
/**
* 一页获取多少个推客,最大 30
*/
private Integer page_size;
}
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.bo;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 时间范围-业务对象
* @Author fanjiaxin
* @Date 2025/3/11 18:43
*/
@Data
@Builder
public class WeChatTimeRangeBO implements Serializable {
private static final long serialVersionUID = 1996751915518651231L;
/**
* 开始时间,秒级时间戳
*/
private Long start_time;
/**
* 结束时间,秒级时间戳
*/
private Long end_time;
}
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @Description 分佣单列表项-视图对象
* @Author fanjiaxin
* @Date 2025/5/11 19:05
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WeChatCommissionOrderDetailVO extends WeChatCoreVO {
private static final long serialVersionUID = 8529644543147459802L;
/**
* 佣金单详情
*/
private CommssionOrderDetailVO commssion_order;
@Data
public static class CommssionOrderDetailVO {
/**
* 订单号
*/
private String order_id;
/**
* 商品skuid
*/
private Long sku_id;
/**
* 秒级时间戳
*/
private Long create_time;
/**
* 秒级时间戳
*/
private Long update_time;
/**
* 佣金单状态,枚举值详情请参考 CommissionOrderStatus
*/
private Integer status;
/**
* 订单详情,结构体详情请参考OrderDetail
*/
private OrderDetailVO order_detail;
}
@Data
public static class OrderDetailVO {
/**
* 小店商家信息,结构体详情请参考BizInfo
*/
private BizInfoVO shop_info;
/**
* 佣金单商品信息,结构体详情请参考 ProductInfo
*/
private ProductInfoVO product_info;
/**
* 订单信息,结构体详情请参考 OrderInfo
*/
private OrderInfoVO order_info;
/**
* 分佣信息,结构体详情请参考 CommissionInfo
*/
private CommissionInfoVO commission_info;
/**
* 买家信息,结构体详情请参考 BuyerInfo
*/
private BuyerInfoVO buyer_info;
}
@Data
public static class BizInfoVO {
/**
* 所属小店appid
*/
private String appid;
}
@Data
public static class ProductInfoVO {
/**
* 商品id
*/
private String product_id;
/**
* sku小图
*/
private String thumb_img;
/**
* 可分佣金额
*/
private Integer actual_payment;
/**
* 商品标题
*/
private String title;
}
@Data
public static class OrderInfoVO {
/**
* 订单状态,枚举值详情请参考OrderStatus
*/
private Integer order_status;
}
@Data
public static class CommissionInfoVO {
/**
* 视频号达人信息,结构体详情请参考 FinderInfo
*/
private FinderInfoVO finder_info;
/**
* 服务费率[0, 1000000]
*/
private Integer service_ratio;
/**
* 服务费金额
*/
private Integer service_amount;
/**
* 服务费结算时间
*/
private Long profit_sharding_suc_time;
/**
* 0-橱窗带货,1-推客带货
*/
private Integer promotion_channel;
/**
* 推客分佣信息,结构体详情请参考 SharerInfo
*/
private SharerInfoVO sharer_info;
/**
* 新带货达人信息,结构体详情请参考 TalentInfo
*/
private TalentInfoVO talent_info;
/**
* 作为推客的时候,推广的一些参数,结构体详情请参考 PromotionInfo
*/
private PromotionInfoVO promotion_info;
/**
* 帮卖机构分佣,结构体详情请参考 AgencyInfo
*/
private AgencyInfoVO sub_agency_info;
/**
* 推客机构分佣,结构体详情请参考 AgencyInfo
*/
private AgencyInfoVO promoter_agency_info;
}
@Data
public static class BuyerInfoVO {
/**
* 购买者的openid
*/
private String open_id;
/**
* 购买者的unionid
*/
private String union_id;
}
@Data
public static class FinderInfoVO {
/**
* 视频号昵称
*/
private String nickname;
/**
* 佣金率[0, 1000000]
*/
private Integer ratio;
/**
* 佣金
*/
private Integer amount;
/**
* 视频号openfinderid
*/
private String openfinderid;
}
@Data
public static class SharerInfoVO {
/**
* 推客appid
*/
private String sharer_appid;
/**
* 推客昵称
*/
private String nickname;
/**
* 佣金率[0, 1000000]
*/
private Integer ratio;
/**
* 佣金
*/
private Integer amount;
/**
* 推客的opensharerid
*/
private String opensharerid;
}
@Data
public static class TalentInfoVO {
/**
* 新带货达人appid
*/
private String talent_appid;
/**
* 达人昵称
*/
private String nickname;
/**
* 佣金率[0, 1000000]
*/
private Integer ratio;
/**
* 佣金
*/
private Integer amount;
/**
* 带货助手的opentalentid
*/
private String opentalentid;
}
@Data
public static class AgencyInfoVO {
/**
* 机构appid
*/
private String appid;
/**
* 帮卖机构昵称
*/
private String nickname;
/**
* 服务费率[0, 1000000]
*/
private Integer ratio;
/**
* 服务费
*/
private Integer amount;
/**
* 服务费结算时间
*/
private Long profit_sharding_suc_time;
}
@Data
public static class PromotionInfoVO {
/**
* 推客推广的类型 【0:无 3:私域商品推广 4:带货内容推广 6:自营内容推广】
*/
private Integer channel_type;
/**
* 推广渠道来自视频号时的视频号信息
*/
private PromotionFinderInfoVO finder_info;
/**
* 推广渠道来自公众号的公众号信息
*/
private PromotionMpInfoVO mp_info;
/**
* 推广渠道来自带货内容推广时的带货助手信息
*/
private PromotionTalentInfoVO talent_info;
}
@Data
public static class PromotionTalentInfoVO {
/**
* 带货助手的appid
*/
private String talent_appid;
/**
* 达人昵称
*/
private String nickname;
/**
* 带货助手的opentalentid
*/
private String opentalentid;
}
@Data
public static class PromotionFinderInfoVO {
/**
* 视频号 id
*/
private String finder_id;
/**
* 昵称
*/
private String nickname;
/**
* 视频号的openfinderid
*/
private String openfinderid;
}
@Data
public static class PromotionMpInfoVO {
/**
* 公众号的 appid
*/
private String appid;
/**
* 昵称
*/
private String nickname;
}
/**
* 佣金单状态枚举类
*/
@Getter
@RequiredArgsConstructor
public enum CommissionOrderStatus {
WAITING_SETTLEMENT(20, "待结算"),
SETTLED(100, "已结算"),
CANCELED(200, "取消结算");
private final Integer code;
private final String description;
}
/**
* 订单状态枚举类
*/
@Getter
@RequiredArgsConstructor
public enum OrderStatus {
PENDING_PAYMENT(10, "待付款"),
AWAITING_GIFT_RECEIPT(12, "待收礼"),
PENDING_SHIPMENT(20, "待发货"),
PARTIALLY_SHIPPED(21, "部分发货"),
PENDING_DELIVERY(30, "待收货"),
COMPLETED(100, "完成"),
CANCELLED_AFTER_FULL_AFTERSALES(200, "全部商品售后之后,订单取消"),
CANCELLED_DUE_TO_NON_PAYMENT(250, "未付款用户主动取消或超时未付款订单自动取消");
private final Integer code;
private final String description;
}
}
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 分佣单列表项-视图对象
* @Author fanjiaxin
* @Date 2025/5/11 19:05
*/
@Data
public class WeChatCommissionOrderItemVO implements Serializable {
private static final long serialVersionUID = 8529644543147459802L;
/**
* 订单ID
*/
private String order_id;
/**
* 商品SKU ID
*/
private String sku_id;
}
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* @Description 分佣单列表-视图对象
* @Author fanjiaxin
* @Date 2025/5/11 19:05
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WeChatCommissionOrderListVO extends WeChatListVO {
private static final long serialVersionUID = 8529644543147459802L;
/**
* 集合
*/
private List<WeChatCommissionOrderItemVO> list;
}
package com.netease.yanxuan.wx.store.sharer.integration.meta.model.vo;
import lombok.Data;
/**
* @Description 微信凭证-核心对象
* @Author fanjiaxin
* @Date 2025/3/11 19:05
*/
@Data
public class WeChatListVO extends WeChatCoreVO {
private static final long serialVersionUID = 1L;
/**
* 是否还有数据
*/
private Boolean has_more;
/**
* 分页参数,第一页为空,后面返回前面一页返回的数据
*/
private String next_key;
}
...@@ -12,14 +12,10 @@ import java.util.List; ...@@ -12,14 +12,10 @@ import java.util.List;
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class WeChatPromoteProductListVO extends WeChatCoreVO { public class WeChatPromoteProductListVO extends WeChatListVO {
private static final long serialVersionUID = 8529644543147459802L; private static final long serialVersionUID = 8529644543147459802L;
/** /**
* 分页参数,第一页为空,后面返回前面一页返回的数据
*/
private String next_key;
/**
* 商品列表 * 商品列表
*/ */
private List<WeChatPromoteProductListItemVO> product_list; private List<WeChatPromoteProductListItemVO> product_list;
......
...@@ -10,14 +10,10 @@ import java.util.List; ...@@ -10,14 +10,10 @@ import java.util.List;
* @Date 2025/3/11 19:05 * @Date 2025/3/11 19:05
*/ */
@Data @Data
public class WeChatSharerListVO extends WeChatCoreVO { public class WeChatSharerListVO extends WeChatListVO {
private static final long serialVersionUID = 8529644543147459802L; private static final long serialVersionUID = 8529644543147459802L;
/** /**
* 分页参数,第一页为空,后面返回前面一页返回的数据
*/
private String next_key;
/**
* 推客集合 * 推客集合
*/ */
private List<WeChatSharerInfoVO> sharer_info_list; private List<WeChatSharerInfoVO> sharer_info_list;
......
package com.netease.yanxuan.wx.store.sharer.web.controller;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.SmsCodeBO;
import com.netease.yanxuan.wx.store.sharer.biz.service.ISmsService;
import com.netease.yanxuan.wx.store.sharer.common.core.Result;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description 短信-控制器
* @Author fanjiaxin
* @Date 2025/3/9 13:10
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/sharer/sms")
@Slf4j
public class SmsController extends BaseController {
private final ISmsService iSmsService;
/**
* 发送短信验证码
*/
@PostMapping("/sendSmsCode")
public Result<Boolean> sendSmsCode(@Validated @RequestBody SmsCodeBO bo) {
iSmsService.sendSmsCode(bo);
return Result.ok(true);
}
}
...@@ -6,10 +6,16 @@ ...@@ -6,10 +6,16 @@
*/ */
package com.netease.yanxuan.wx.store.sharer.web.controller; package com.netease.yanxuan.wx.store.sharer.web.controller;
import com.netease.yanxuan.wx.store.sharer.biz.core.LoginUserHelper; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.RealNameAuthenticatedBO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.SmsCodeBO;
import com.netease.yanxuan.wx.store.sharer.biz.service.ICommissionOrderService;
import com.netease.yanxuan.wx.store.sharer.biz.service.ISmsService;
import com.netease.yanxuan.wx.store.sharer.common.core.Result;
import com.netease.yanxuan.wx.store.sharer.common.exception.BizException;
import com.netease.yanxuan.wx.store.sharer.integration.client.IUserInfoClient;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.*;
/** /**
* @author 刘运星 (liuyunxing01@corp.netease.com) * @author 刘运星 (liuyunxing01@corp.netease.com)
...@@ -18,6 +24,48 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -18,6 +24,48 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/sharer/test") @RequestMapping("/sharer/test")
@RequiredArgsConstructor @RequiredArgsConstructor
public class TestController { public class TestController {
private final LoginUserHelper loginUserHelper; private final ICommissionOrderService iCommissionOrderService;
private final IUserInfoClient iUserInfoClient;
private final ISmsService iSmsService;
/**
* 同步订单
*/
@GetMapping("/syncCommissionOrder")
public Result<Void> syncCommissionOrder() {
Long syncStartTimestamp = iCommissionOrderService.getLatestCommissionSyncTimestamp();
long syncEndTimestamp = System.currentTimeMillis() / 1000;
iCommissionOrderService.doCommissionOrderSync(syncStartTimestamp, syncEndTimestamp);
return Result.ok();
}
/**
* 同步订单重试
*/
@GetMapping("/doCommissionOrderFailRetry")
public Result<Void> doCommissionOrderFailRetry() {
iCommissionOrderService.doCommissionOrderFailRetry();
return Result.ok();
}
/**
* 发送短信验证码
*/
@PostMapping("/sendSmsCode")
public Result<Boolean> sendSmsCode(@Validated @RequestBody SmsCodeBO bo) {
iSmsService.sendSmsCode(bo);
return Result.ok(true);
}
/**
* 实名认证
*/
@PostMapping("/verifyByIdentityNo")
public Result<Boolean> verifyByIdentityNo(@RequestBody RealNameAuthenticatedBO bo) {
Boolean isVerifySuccess = iUserInfoClient.verifyByIdentityNo(bo.getUsername(), bo.getIdCardNumber());
if (null == isVerifySuccess || !isVerifySuccess) {
throw new BizException("实名认证不通过");
}
return Result.ok(true);
}
} }
\ No newline at end of file
package com.netease.yanxuan.wx.store.sharer.web.controller; package com.netease.yanxuan.wx.store.sharer.web.controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.LoginBO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.LoginBO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.bo.RealNameAuthenticatedBO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.SharerInfoVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.SharerInfoVO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserCommissionRatioVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserCommissionRatioVO;
import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserTokenVO; import com.netease.yanxuan.wx.store.sharer.biz.meta.model.vo.UserTokenVO;
import com.netease.yanxuan.wx.store.sharer.biz.service.IUserService; import com.netease.yanxuan.wx.store.sharer.biz.service.IUserService;
import com.netease.yanxuan.wx.store.sharer.common.core.Result; import com.netease.yanxuan.wx.store.sharer.common.core.Result;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** /**
* @Description 用户-控制器 * @Description 用户-控制器
...@@ -63,4 +62,13 @@ public class UserController extends BaseController { ...@@ -63,4 +62,13 @@ public class UserController extends BaseController {
UserCommissionRatioVO result = iUserService.getCommissionRatioDefault(); UserCommissionRatioVO result = iUserService.getCommissionRatioDefault();
return Result.ok(result); return Result.ok(result);
} }
/**
* 实名认证
*/
@PostMapping("/realNameAuthenticated")
public Result<Boolean> realNameAuthenticated(@Validated @RequestBody RealNameAuthenticatedBO bo) {
iUserService.realNameAuthenticated(bo);
return Result.ok(true);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment