This commit is contained in:
韩鹏辉
2024-05-23 15:23:08 +08:00
parent 49fe8fe877
commit d969550aa3
2477 changed files with 340990 additions and 0 deletions

185
jeepay-merchant/pom.xml Normal file
View File

@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- POM模型版本 -->
<groupId>com.jeequan</groupId> <!-- 组织名, 类似于包名 -->
<artifactId>jeepay-9218-merchant</artifactId> <!-- 项目名称 -->
<packaging>jar</packaging> <!-- 项目的最终打包类型/发布形式, 可选[jar, war, pom, maven-plugin]等 -->
<version>${isys.version}</version> <!-- 项目当前版本号 -->
<description>Jeepay计全支付系统 [商户后台管理端]</description> <!-- 项目描述 -->
<url>https://www.jeequan.com</url>
<parent>
<groupId>com.jeequan</groupId>
<artifactId>jeepay</artifactId>
<version>Final</version>
</parent>
<!-- 项目属性 -->
<properties>
<projectRootDir>${basedir}/../</projectRootDir>
</properties>
<!-- 项目依赖声明 -->
<dependencies>
<!-- 依赖[ service ]包, 会自动传递依赖[ core ]包。 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-components-db</artifactId>
</dependency>
<!-- 依赖[ bizcommons ]包 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-components-bizcommons</artifactId>
</dependency>
<!-- 依赖[ rpc-thirdparty ]包, 会自动传递依赖[ core , service ]包。 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-components-3rd</artifactId>
</dependency>
<!-- 依赖[ oss ]包 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-components-oss</artifactId>
</dependency>
<!-- 依赖[ mq ]包 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-components-mq</artifactId>
</dependency>
<!-- 依赖 sping-boot-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion> <!-- 删除spring boot默认json映射器 Jackson 引入fastJSON -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</exclusion>
<exclusion> <!-- hibernate.validator插件一般不使用 -->
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- spring-security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- spring-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- 添加redis支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 引入 jeepay-sdk-java -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-sdk-java</artifactId>
</dependency>
<!-- webSocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
<!--阿里云短信依赖-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<!-- 阿里大于 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
</dependency>
<!-- 生成二维码工具包 zxing -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
</dependency>
</dependencies>
<!-- 作为可执行jar -->
<build>
<finalName>${project.artifactId}</finalName>
<!-- resources资源配置项 -->
<resources>
<!-- 通用资源文件 -->
<resource><directory>src/main/resources</directory><includes><include>**/*.*</include></includes></resource>
<!-- 放置通用配置yml文件 开发时仅配置一套参数即可。 实际生产环境下应在每个项目下 与jar同级目录下新建application.yml覆写对应参数。 -->
<resource>
<directory>../conf/devCommons</directory>
<includes><include>**/*.yml</include></includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
<outputDirectory>${session.executionRootDirectory}/target/</outputDirectory>
</configuration> <!-- 包含本地jar文件 -->
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,151 @@
package com.jeequan.jeepay.mch.aop;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.beans.RequestKitBean;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.db.entity.SysLog;
import com.jeequan.jeepay.service.impl.SysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* 方法级日志切面组件
*
* @author terrfly
* @modify pangxiaoyu
* @date 2021-04-27 15:50
*/
@Component
@Aspect
public class MethodLogAop{
private static final Logger logger = LoggerFactory.getLogger(MethodLogAop.class);
@Autowired private SysLogService sysLogService;
@Autowired private RequestKitBean requestKitBean;
/**
* 异步处理线程池
*/
private final static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
/**
* 切点
*/
@Pointcut("@annotation(com.jeequan.jeepay.core.aop.MethodLog)")
public void methodCachePointcut() { }
/**
* 切面
* @param point
* @return
* @throws Throwable
*/
@Around("methodCachePointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
final SysLog sysLog = new SysLog();
//处理切面任务 发生异常将向外抛出 不记录日志
Object result = point.proceed();
try {
// 基础日志信息
setBaseLogInfo(point, sysLog, JeeUserDetails.getCurrentUserDetails());
sysLog.setOptResInfo(JSONObject.toJSON(result).toString());
scheduledThreadPool.execute(() -> sysLogService.save(sysLog));
} catch (Exception e) {
logger.error("methodLogError", e);
}
return result;
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 14:04
* @describe: 记录异常操作请求信息
*/
@AfterThrowing(pointcut = "methodCachePointcut()", throwing="e")
public void doException(JoinPoint joinPoint, Throwable e) throws Exception{
final SysLog sysLog = new SysLog();
// 基础日志信息
setBaseLogInfo(joinPoint, sysLog, JeeUserDetails.getCurrentUserDetails());
sysLog.setOptResInfo(e instanceof BizException ? e.getMessage() : "请求异常");
scheduledThreadPool.execute(() -> sysLogService.save(sysLog));
}
/**
* 获取方法中的中文备注
* @param joinPoint
* @return
* @throws Exception
*/
public static String getAnnotationRemark(JoinPoint joinPoint) throws Exception {
Signature sig = joinPoint.getSignature();
Method m = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), ((MethodSignature) sig).getParameterTypes());
MethodLog methodCache = m.getAnnotation(MethodLog.class);
if (methodCache != null) {
return methodCache.remark();
}
return "";
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 14:12
* @describe: 日志基本信息 公共方法
*/
private void setBaseLogInfo(JoinPoint joinPoint, SysLog sysLog, JeeUserDetails userDetails) throws Exception {
// 使用point.getArgs()可获取request仅限于spring MVC参数包含request改为通过contextHolder获取。
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//请求参数
sysLog.setOptReqParam( requestKitBean.getReqParamJSON().toJSONString() );
//注解备注
sysLog.setMethodRemark(getAnnotationRemark(joinPoint));
//包名 方法名
String methodName = joinPoint.getSignature().getName();
String packageName = joinPoint.getThis().getClass().getName();
if (packageName.indexOf("$$EnhancerByCGLIB$$") > -1 || packageName.indexOf("$$EnhancerBySpringCGLIB$$") > -1) { // 如果是CGLIB动态生成的类
packageName = packageName.substring(0, packageName.indexOf("$$"));
}
sysLog.setMethodName(packageName + "." + methodName);
sysLog.setReqUrl(request.getRequestURL().toString());
sysLog.setUserIp(requestKitBean.getClientIp());
sysLog.setCreatedAt(new Date());
sysLog.setSysType(CS.SYS_ROLE_TYPE.MCH);
if (userDetails != null) {
sysLog.setUserId(JeeUserDetails.getCurrentUserDetails().getSysUser().getSysUserId());
sysLog.setUserName(JeeUserDetails.getCurrentUserDetails().getSysUser().getRealname());
sysLog.setSysType(JeeUserDetails.getCurrentUserDetails().getSysUser().getSysType());
}
}
}

View File

@@ -0,0 +1,66 @@
package com.jeequan.jeepay.mch.bootstrap;
import cn.hutool.core.date.DatePattern;
import cn.hutool.crypto.SmUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.jeequan.jeepay.mch.config.SystemYmlConfig;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* 项目初始化操作
* 比如初始化配置文件, 读取基础数据, 资源初始化等。 避免在Main函数中写业务代码。
* CommandLineRunner / ApplicationRunner都可以达到要求 只是调用参数有所不同。
*
* @author terrfly
*
* @date 2021-04-27 15:50
*/
@Component
public class InitRunner implements CommandLineRunner {
@Autowired private SystemYmlConfig systemYmlConfig;
@Autowired private SysConfigService sysConfigService;
@Override
public void run(String... args) throws Exception {
// 配置是否使用缓存模式
SysConfigService.IS_USE_CACHE = systemYmlConfig.getCacheConfig();
// 初始化系统秘钥
SysConfigService.DB_ENCRYPT_SECRET = systemYmlConfig.getDbEncryptSecret();
SysConfigService.DB_ENCRYPT_SM4 = SmUtil.sm4(SysConfigService.DB_ENCRYPT_SECRET.getBytes());
SysConfigService.HTTP_MESSAGE_ENCRYPT_SECRET = systemYmlConfig.getHttpMessageEncryptSecret();
SysConfigService.HTTP_MESSAGE_ENCRYPT_SM4 = SmUtil.sm4(SysConfigService.HTTP_MESSAGE_ENCRYPT_SECRET.getBytes());
// 检查是否支持服务商
SysConfigService.IS_HAS_AGENT_ENT = sysConfigService.getById(SysConfigService.AGENT_ENT_CONFIG) != null;
// 检查是否支持会员
SysConfigService.IS_HAS_MEMBER_ENT = sysConfigService.getById(SysConfigService.MEMBER_ENT_CONFIG) != null;
// 配置是否通信加密 和 密码修改
SysConfigService.HTTP_MSG_IS_ENCRYPT = sysConfigService.getDBSecurityConfig().httpMsgIsEncrypt();
SysConfigService.PWD_EXPIRED_MUST_RESET = sysConfigService.getDBSecurityConfig().passwordExpiredIsMustModify();
// 配置 平台通信秘钥
SysConfigService.PLATFORM_API_SECRET = sysConfigService.getDBSecurityConfig().getPlatformApiSecret();
//初始化处理fastjson格式
SerializeConfig serializeConfig = SerializeConfig.getGlobalInstance();
serializeConfig.put(Date.class, new SimpleDateFormatSerializer(DatePattern.NORM_DATETIME_PATTERN));
//解决json 序列化时候的 $ref问题
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
}
}

View File

@@ -0,0 +1,86 @@
package com.jeequan.jeepay.mch.bootstrap;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.Arrays;
/**
* spring-boot 主启动程序
*
* @author terrfly
*
* @date 2021-04-27 15:50
*/
@SpringBootApplication
@EnableScheduling
@MapperScan("com.jeequan.jeepay.service.mapper") //Mybatis mapper接口路径
@ComponentScan(basePackages = "com.jeequan.jeepay.*") //由于MainApplication没有在项目根目录 需要配置basePackages属性使得成功扫描所有Spring组件
@Configuration
public class JeepayMchApplication {
/** main启动函数 **/
public static void main(String[] args) {
//启动项目
SpringApplication.run(JeepayMchApplication.class, args);
}
/** 支持搜索 {} [] 否则 springboot 提示 HTTP Status 400 Bad Request **/
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory (){
// 修改内置的 tomcat 容器配置
TomcatServletWebServerFactory tomcatServlet = new TomcatServletWebServerFactory();
tomcatServlet.addConnectorCustomizers( connector -> connector.setProperty("relaxedQueryChars", "[]{}") );
return tomcatServlet ;
}
/** fastJson 配置信息 **/
@Bean
public HttpMessageConverters fastJsonConfig(){
// 开启 FastJSON 安全模式!
ParserConfig.getGlobalInstance().setSafeMode(true);
//新建fast-json转换器
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
//fast-json 配置信息
FastJsonConfig config = new FastJsonConfig();
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
converter.setFastJsonConfig(config);
//设置响应的 Content-Type
converter.setSupportedMediaTypes(Arrays.asList(new MediaType[]{MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8}));
return new HttpMessageConverters(converter);
}
/** Mybatis plus 分页插件 **/
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}

View File

@@ -0,0 +1,70 @@
package com.jeequan.jeepay.mch.config;
import com.jeequan.jeepay.core.cache.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* redis管理类
*
* @author terrfly
*
* @date 2021-04-27 15:50
*/
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.timeout}")
private Integer timeout;
@Value("${spring.redis.database}")
private Integer defaultDatabase;
@Value("${spring.redis.password}")
private String password;
/** 作用:不同系统的前缀。 a.当连接不同的database时可以为空(物理隔离) b.当redis集群时因为必须同一个database所以需通过前缀区分不同系统的业务。 **/
@Value("${spring.redis.sys-prefix-key}")
private String sysPrefixKey;
/** 当前系统的redis缓存操作对象 (主对象) **/
@Primary
@Bean(name = "defaultStringRedisTemplate")
public StringRedisTemplate sysStringRedisTemplate() {
// 赋值前缀key
RedisUtil.SYS_PREFIX_KEY = sysPrefixKey;
StringRedisTemplate template = new StringRedisTemplate();
LettuceConnectionFactory jedisConnectionFactory = new LettuceConnectionFactory();
jedisConnectionFactory.setHostName(host);
jedisConnectionFactory.setPort(port);
jedisConnectionFactory.setTimeout(timeout);
if (!StringUtils.isEmpty(password)) {
jedisConnectionFactory.setPassword(password);
}
if (defaultDatabase != 0) {
jedisConnectionFactory.setDatabase(defaultDatabase);
}
jedisConnectionFactory.afterPropertiesSet();
template.setConnectionFactory(jedisConnectionFactory);
return template;
}
}

View File

@@ -0,0 +1,40 @@
package com.jeequan.jeepay.mch.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 系统Yml配置参数定义Bean
*
* @author terrfly
*
* @date 2021-04-27 15:50
*/
@Component
@ConfigurationProperties(prefix="isys")
@Data
public class SystemYmlConfig {
/** 是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时应开启此配置或在nginx统一配置允许跨域] **/
private Boolean allowCors;
/** 生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。 **/
private String jwtSecret;
/** DB SM4 加解密秘钥 (必须16位) [每个系统配置必须相同,否则加解密不一致导致业务异常!] **/
private String dbEncryptSecret;
/** web传输加解密 秘钥 (必须16位) [每个系统配置必须相同,否则加解密不一致导致业务异常!] **/
private String httpMessageEncryptSecret;
/** 支付网关的公钥和私钥(系统级别!), 请妥善保存,用于回调商户的商户侧的验证, 首次设置好之后不可随意变更! **/
private String sysRSA2PrivateKey;
/**支付网关的公钥和私钥(系统级别!), 请妥善保存,用于回调商户的商户侧的验证, 首次设置好之后不可随意变更! **/
private String sysRSA2PublicKey;
/** 是否内存缓存配置信息: true表示开启如支付网关地址/商户应用配置/服务商配置等, 开启后需检查MQ的广播模式是否正常 false表示直接查询DB. **/
private Boolean cacheConfig;
}

View File

@@ -0,0 +1,108 @@
package com.jeequan.jeepay.mch.ctrl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.ctrls.AbstractCtrl;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.BaseModel;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.db.entity.MemberInfo;
import com.jeequan.jeepay.service.impl.MemberInfoService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 通用ctrl类
*
* @author terrfly
* @modify zhuxiao
* @date 2021-04-27 15:50
*/
public abstract class CommonCtrl extends AbstractCtrl {
@Autowired protected SysConfigService sysConfigService;
@Autowired protected MemberInfoService memberInfoService;
/** 获取当前用户ID */
protected JeeUserDetails getCurrentUser(){
return (JeeUserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
/** 获取当前商户ID **/
protected String getCurrentMchNo() {
return getCurrentUser().getSysUser().getBelongInfoId();
}
/**
* 获取当前用户登录IP
* @return
*/
protected String getIp() {
return getClientIp();
}
/**
* 校验当前用户是否为超管
* @return
*/
protected ApiRes checkIsAdmin() {
SysUser sysUser = getCurrentUser().getSysUser();
if (sysUser.getUserType() != SysUser.UEST_TYPE_ADMIN) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}else {
return null;
}
}
/** 当前是否为普通商户 **/
protected boolean getIsNormalMch() {
return getCurrentUser().getMchType() == CS.MCH_TYPE_NORMAL;
}
/** model 存入会员头像 **/
public void setAvatarUrl(List<? extends BaseModel> modeList) {
if(modeList == null || modeList.isEmpty()){
return ;
}
ArrayList<String> mbrIdList = new ArrayList<>();
for (BaseModel model:modeList) {
JSONObject json = (JSONObject) JSON.toJSON(model);
String mbrId = json.getString("mbrId");
mbrIdList.add(mbrId);
}
List<MemberInfo> defineList = memberInfoService.list(MemberInfo.gw().select(MemberInfo::getAvatarUrl, MemberInfo::getMbrId).in(MemberInfo::getMbrId, mbrIdList));
for (BaseModel model : modeList) {
JSONObject json = (JSONObject) JSON.toJSON(model);
String mbrId = json.getString("mbrId");
if(StringUtils.isBlank(mbrId)) {
continue;
}
for (MemberInfo define : defineList) {
if (mbrId.equals(define.getMbrId())) {
model.addExt("avatarUrl", define.getAvatarUrl());
}
}
}
}
/** 会员头像地址默认值获取 **/
public String getMemberAvatarDefault() {
Collections.shuffle(CS.MEMBER_AVATAR_ICON);
return CS.MEMBER_AVATAR_ICON.get(0);
}
}

View File

@@ -0,0 +1,304 @@
package com.jeequan.jeepay.mch.ctrl;
import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.bizcommons.manage.auth.AuthByQrcodeManage;
import com.jeequan.jeepay.converter.BaseConverter;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.ITokenService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.core.utils.TreeDataBuilder;
import com.jeequan.jeepay.core.utils.google.GoogleAuth;
import com.jeequan.jeepay.db.entity.MchConfig;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.SysEntitlement;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.mch.service.AuthService;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 当前登录者的信息相关接口
*
* @author terrfly
* @modify zhuxiao
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("/api/current")
public class CurrentUserController extends CommonCtrl {
@Autowired
private SysEntitlementService sysEntitlementService;
@Autowired
private SysUserService sysUserService;
@Autowired
private SysUserAuthService sysUserAuthService;
@Autowired
private MchConfigService mchConfigService;
@Autowired
private MchInfoService mchInfoService;
@Autowired
private StoreUserWorkRecordService storeUserWorkRecordService;
@Autowired
private BaseConverter baseConverter;
@RequestMapping(value = "/user", method = RequestMethod.GET)
public ApiRes currentUserInfo() {
///当前用户信息
JeeUserDetails jeeUserDetails = getCurrentUser();
SysUserEntity user = sysUserService.getById(jeeUserDetails.getSysUser().getSysUserId());
//1. 当前用户所有权限ID集合
List<String> entIdList = new ArrayList<>();
jeeUserDetails.getAuthorities().forEach(r -> entIdList.add(r.getAuthority()));
List<SysEntitlement> allMenuList = new ArrayList<>(); //所有菜单集合
//2. 查询出用户所有菜单集合 (包含左侧显示菜单 和 其他类型菜单 )
if (!entIdList.isEmpty()) {
allMenuList = sysEntitlementService.list(SysEntitlement.gw()
.in(SysEntitlement::getEntId, entIdList)
.in(SysEntitlement::getEntType, Arrays.asList(CS.ENT_TYPE.MENU_LEFT, CS.ENT_TYPE.MENU_OTHER))
.eq(SysEntitlement::getSysType, CS.SYS_ROLE_TYPE.MCH)
.eq(SysEntitlement::getState, CS.PUB_USABLE));
}
//4. 转换为json树状结构
JSONArray jsonArray = (JSONArray) JSON.toJSON(allMenuList);
List<JSONObject> allMenuRouteTree = new TreeDataBuilder(jsonArray,
"entId", "pid", "children", "entSort", true)
.buildTreeObject();
//1. 所有权限ID集合
user.addExt("entIdList", entIdList);
user.addExt("allMenuRouteTree", allMenuRouteTree);
user.addExt("mchType", jeeUserDetails.getMchType());
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
user.addExt("mchLevel", mchInfo.getMchLevel());
// 程序是否支持服务商
user.addExt("isHasAgentEnt", SysConfigService.IS_HAS_AGENT_ENT);
// 程序是否支持会员
user.addExt("isHasMemberEnt", SysConfigService.IS_HAS_MEMBER_ENT);
// 商户是否开启会员功能
Byte memberModelState = mchConfigService.getConfigValByMchNoAndKey(mchInfo.getMchNo(), MchConfig.SELF_MEMBER_MODEL_STATE, Byte.class);
// 商户会员功能显示开关
if (memberModelState == null || memberModelState == CS.NO) {
user.addExt("isHasMemberEnt", false);
}
// 查询用户app推送设备是否注册
// mchAppPushInfoService.saveMchCid(getValString("cid1"), getValString("cid2"), getCurrentMchNo(), getCurrentUser().getSysUserId());
// 查询当前登录帐号是否为微信小程序审核帐号
boolean isWxAuditUser = false;
String wxAuditMchNo = sysConfigService.getById("wxAuditUser").getConfigVal();
if (StringUtils.isNotBlank(wxAuditMchNo) && (wxAuditMchNo.equals("*") || wxAuditMchNo.contains(getCurrentMchNo()))) {
isWxAuditUser = true;
}
user.addExt("isWxAuditUser", isWxAuditUser);
//获取商户简称
user.addExt("shortName", mchInfo.getMchShortName());
//获取支付密码
user.addExt("sipw", mchInfo.getSipw() == null ? "2" : "1");
// 刷脸设备上下班状态
if (JWTPayload.LOGIN_PAGE_TYPE.FACE_APP.equals(getCurrentUser().getLoginType())) {
user.addExt("workState", storeUserWorkRecordService.getWorkState(getCurrentUser().getStoreIdList().get(0), user.getSysUserId()));
}
return ApiRes.ok(user);
}
/**
* 修改个人信息
*/
@MethodLog(remark = "修改个人信息")
@RequestMapping(value = "/user", method = RequestMethod.PUT)
public ApiRes modifyCurrentUserInfo() {
//修改头像
String avatarUrl = getValString("avatarUrl");
String realname = getValString("realname");
Byte sex = getValByte("sex");
//编辑预留信息
String safeWord = getValString("safeWord");
SysUserEntity updateRecord = new SysUserEntity();
updateRecord.setSysUserId(getCurrentUser().getSysUser().getSysUserId());
if (StringUtils.isNotEmpty(avatarUrl)) {
updateRecord.setAvatarUrl(avatarUrl);
}
if (StringUtils.isNotEmpty(realname)) {
updateRecord.setRealname(realname);
}
if (sex != null) {
updateRecord.setSex(sex);
}
if (StringUtils.isNotEmpty(safeWord)) {
updateRecord.setSafeWord(safeWord);
}
sysUserService.updateById(updateRecord);
SysUserEntity sysUserEntity = sysUserService.getById(getCurrentUser().getSysUser().getSysUserId());
//保存redis最新数据
JeeUserDetails currentUser = getCurrentUser();
currentUser.setSysUser(baseConverter.toModel(sysUserEntity));
ITokenService.refData(currentUser);
return ApiRes.ok();
}
/**
* modifyPwd
*/
@MethodLog(remark = "修改密码")
@RequestMapping(value = "modifyPwd", method = RequestMethod.PUT)
public ApiRes modifyPwd() throws BizException {
Long opSysUserId = getCurrentUser().getSysUser().getSysUserId();
//更改密码,验证当前用户信息
String currentUserPwd = Base64.decodeStr(getValStringRequired("originalPwd")); //当前用户登录密码
//验证当前密码是否正确
if (!sysUserAuthService.validateCurrentUserPwd(currentUserPwd)) {
throw new BizException("原密码验证失败!");
}
String opUserPwd = Base64.decodeStr(getValStringRequired("confirmPwd"));
// 验证原密码与新密码是否相同
if (opUserPwd.equals(currentUserPwd)) {
throw new BizException("新密码与原密码不能相同!");
}
sysUserAuthService.resetAuthInfo(opSysUserId, null, null, true, opUserPwd, CS.SYS_ROLE_TYPE.MCH);
//调用登出接口
return logout();
}
/**
* 登出
*/
@MethodLog(remark = "退出")
@RequestMapping(value = "logout", method = RequestMethod.POST)
public ApiRes logout() throws BizException {
ITokenService.removeIToken(getCurrentUser().getCacheKey(), getCurrentUser().getSysUser().getSysUserId());
return ApiRes.ok();
}
/**
* MFA验证信息
*/
@GetMapping("/mfaInfo")
@MethodLog(remark = "MFA验证信息")
public ApiRes mfaInfo() throws BizException {
SysUserEntity currentUser = sysUserService.getById(getCurrentUser().getSysUserId());
JSONObject resJson = new JSONObject();
resJson.put("mfaBindState", currentUser.getMfaBindState());
resJson.put("telPhone", currentUser.getTelphone());
// 是否展示MFA绑定信息 [未绑定时显示]
if (currentUser.getMfaBindState() == CS.NO) {
String secretKey = sysUserService.getById(currentUser.getSysUserId()).getMfaSecretKey();
// 更新用户验证秘钥
if (StringUtils.isEmpty(secretKey)) {
secretKey = GoogleAuth.generateSecretKey();
sysUserService.updateMFASecret(currentUser.getSysUserId(), secretKey, null);
}
String qrcodeUrl = GoogleAuth.getQRBarcode(
sysConfigService.getOemConfig().getSysName() + "_商户" + "(" + currentUser.getTelphone() + ")"
, secretKey);
resJson.put("mfaBindUrl", qrcodeUrl);
resJson.put("mfaSecretKey", secretKey);
}
return ApiRes.ok(resJson);
}
/**
* MFA验证 绑定
*/
@RequestMapping(value = "mfaBind", method = RequestMethod.PUT)
@MethodLog(remark = "MFA验证绑定")
public ApiRes mfaBind() throws BizException {
String verCode = getValStringRequired("verCode");
Long userId = getCurrentUser().getSysUserId();
// 验证验证码
sysUserService.checkMFACode(userId, verCode);
// 绑定MFA验证
sysUserService.bindMFA(userId);
return ApiRes.ok();
}
/**
* MFA验证 解绑
*/
@RequestMapping(value = "mfaRelieve", method = RequestMethod.PUT)
@MethodLog(remark = "MFA验证解除")
public ApiRes mfaRelieve() throws BizException {
String verCode = getValStringRequired("verCode");
Long userId = getCurrentUser().getSysUserId();
// 验证验证码
sysUserService.checkMFACode(userId, verCode);
// 解除MFA验证
sysUserService.relieveMFA(userId, CS.SYS_ROLE_TYPE.MCH);
return ApiRes.ok();
}
/**
* app扫码登录接口
*/
@PostMapping("qrcode/login")
public ApiRes loginQrcodeConfirm() {
String qrcodeNo = getValStringRequired("qrcodeNo");
String qrCodeStatus = getValStringRequired("qrcodeStatus");
if (!StringUtils.equalsAny(qrCodeStatus, AuthByQrcodeManage.QRCODE_STATUS_SCANED, AuthByQrcodeManage.QRCODE_STATUS_CANCELED,
AuthByQrcodeManage.QRCODE_STATUS_CONFIRMED)) {
return ApiRes.customFail("qrcodeStatus错误");
}
// 更新状态:等待扫码 --> 已扫
if (qrCodeStatus.equals(AuthByQrcodeManage.QRCODE_STATUS_SCANED)) {
AuthByQrcodeManage.updateQrcodeStatusWaiting2Scaned(qrcodeNo);
return ApiRes.ok();
// 更新状态:已扫 --> 取消
} else if (qrCodeStatus.equals(AuthByQrcodeManage.QRCODE_STATUS_CANCELED)) {
AuthByQrcodeManage.updateQrcodeStatusScaned2Canceled(CS.SYS_ROLE_TYPE.MCH, qrcodeNo);
return ApiRes.ok();
}
// 更新状态:已扫 --> 确认登录
JSONObject tokenJSON = SpringBeansUtil.getBean(AuthService.class).authByAppQrcode(getCurrentUser().getSysUserId(), JWTPayload.LOGIN_PAGE_TYPE.WEB);
// 更新状态:已扫 --> 确认登录
AuthByQrcodeManage.updateQrcodeStatusScaned2Confirmed(qrcodeNo, tokenJSON.toJSONString());
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,38 @@
package com.jeequan.jeepay.mch.ctrl.account;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.AccountChangeInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.AccountChangeInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* TODO
*
* @author crystal
* @date 2023/12/6 15:11
*/
@RestController
@RequestMapping("/api/accountChange")
public class AccountChangeInfoController extends CommonCtrl {
@Autowired private AccountChangeInfoService accountChangeInfoService;
@PreAuthorize("hasAuthority('ENT_ACCOUNT_CHANGE_LIST')")
@GetMapping
public ApiRes list() {
AccountChangeInfo info = getObject(AccountChangeInfo.class);
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<AccountChangeInfo> wrapper = AccountChangeInfo.gw(info);
wrapper.eq(AccountChangeInfo::getMchNo, getCurrentMchNo());
Page<AccountChangeInfo> pages = accountChangeInfoService.pageList(getIPage(),wrapper,info,paramJSON);
return ApiRes.page(pages);
}
}

View File

@@ -0,0 +1,39 @@
package com.jeequan.jeepay.mch.ctrl.account;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.AccountFundInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.AccountFundInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* TODO
* 账户资金明细
* @author crystal
* @date 2024/3/28 16:18
*/
@RestController
@RequestMapping("/api/accountFund")
public class AccountFundInfoController extends CommonCtrl {
@Autowired
private AccountFundInfoService accountFundInfoService;
// @PreAuthorize("hasAuthority('ENT_ACCOUNT_FUND_LIST')")
@GetMapping
public ApiRes list() {
AccountFundInfo info = getObject(AccountFundInfo.class);
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<AccountFundInfo> wrapper = AccountFundInfo.gw(info);
wrapper.eq(AccountFundInfo::getMchNo, getCurrentMchNo());
Page<AccountFundInfo> pages = accountFundInfoService.pageList(getIPage(),wrapper,info,paramJSON);
return ApiRes.page(pages);
}
}

View File

@@ -0,0 +1,225 @@
package com.jeequan.jeepay.mch.ctrl.account;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.ApiField;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.components.mq.model.AccountBalanceMQ;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.AccountOperate;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.model.DBDefaultConfig;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.CommonApiService;
import com.jeequan.jeepay.model.DeviceInfo;
import com.jeequan.jeepay.model.JeepayObject;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.service.impl.*;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.List;
/**
* TODO
*
* @author crystal
* @date 2023/12/6 15:11
*/
@RestController
@RequestMapping("/api/account")
public class AccountInfoController extends CommonCtrl {
@Autowired private AccountInfoService accountInfoService;
@Autowired private MchAppService mchAppService;
@Autowired private MchStoreService mchStoreService;
@Autowired private MchApplymentService mchApplymentService;
@Autowired private IMQSender mqSender;
@PreAuthorize("hasAuthority('ENT_ACCOUNT_LIST')")
@GetMapping
public ApiRes getAccount() {
AccountInfo info = getObject(AccountInfo.class);
SysUser sysUser = getCurrentUser().getSysUser();
List<AccountInfo> list = accountInfoService.getAccountInfo(info,getCurrentMchNo());
for (AccountInfo item:list) {
item.setRealName(sysUser.getRealname());
item.setPhone(sysUser.getTelphone());
}
return ApiRes.ok(list);
}
/**
* 充值
* @return
*/
@PreAuthorize("hasAuthority('ENT_ACCOUNT_RECHARGE')")
@PostMapping(value = "/recharge")
public ApiRes recharge() {
JSONObject result = new JSONObject();
AccountFundInfo.ChangeMethod val = AccountFundInfo.ChangeMethod.getVal(getValRequired("changeMethod",Byte.class));
AccountOperate operate = new AccountOperate(getValStringRequired("accountNo"),getValLongRequired("rechargeAmt"),AccountFundInfo.ChangeType.RECHARGE.getValue(),val.getValue(),SeqKit.genFlowNo("H"),"账户充值");
operate.preRechargeCheck();
MchAppEntity defaultApp = mchAppService.getDefaultApp(getCurrentMchNo());
switch (val){
case SCAN:
DBDefaultConfig dbDefaultConfig = sysConfigService.getDBDefaultConfig();
if(StringUtils.isEmpty(dbDefaultConfig.getSysPaymentMchNo())){
throw new BizException("系统未配置收款商户号,暂时无法使用");
}
MchApplyment applyment = mchApplymentService.getById(dbDefaultConfig.getSysPaymentMchNo());
if(applyment == null){
throw new BizException("系统配置的商户号数据异常");
}
MchStore mchStore = mchStoreService.getByMchApplyId(applyment.getApplyId());
PayOrderCreateRequest request = new PayOrderCreateRequest();
PayOrderCreateReqModelAddStoreId model = new PayOrderCreateReqModelAddStoreId();
model.setPas(SysConfigService.PLATFORM_API_SECRET);
model.setMchNo(getCurrentMchNo());
model.setAppId(defaultApp.getAppId());
model.setStoreId(mchStore.getStoreId());
model.setMchOrderNo(SeqKit.genMhoOrderId());
model.setWayCode(CS.PAY_WAY_CODE.QR_CASHIER);
model.setAmount(operate.getAmount());
model.setSubject(mchStore.getStoreName());
model.setCurrency("CNY");
model.setBody("退款账户充值");
model.setMchExtNo(applyment.getApplyId());
JSONObject extParams = new JSONObject();
extParams.put("payDataType",CS.PAY_DATA_TYPE.CODE_IMG_URL);
model.setClientIp(getClientIp());
model.setChannelExtra(extParams.toString());
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
model.setNotifyUrl(dbApplicationConfig.getMchSiteUrl() + "/api/anon/paytestNotify/payOrder"); //回调地址
String paySiteUrl = sysConfigService.getDBApplicationConfig().getPaySiteUrl();
JeepayClient jeepayClient = new JeepayClient(paySiteUrl, defaultApp.getAppSecret());
try {
request.setBizModel(model);
PayOrderCreateResponse response = jeepayClient.execute(request);
if(response.getCode() != 0){
throw new BizException(response.getMsg());
}
result.put("qrCodeUrl",response.get().getPayData());
operate.setOrderId(response.get().getPayOrderId());
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
break;
case PUBIC:
operate.setFinalAmt(operate.getAmount());
operate.setState(AccountFundInfo.AUDIT);
break;
}
AccountFundInfo fundInfo = accountInfoService.upAccount(operate);
result.put("flowNo",fundInfo.getOrderId());
result.put("amount",operate.getAmount());
result.put("finalAmt",fundInfo.getFinalAmount());
String rechargeText = BigDecimal.valueOf(operate.getAmount()).divide(BigDecimal.valueOf(100)).toPlainString() +"(充值金额) * ";
String rateText = "(1 - 0.6%(费率)) = " + BigDecimal.valueOf(operate.getAmount()).divide(BigDecimal.valueOf(100)).toPlainString() +"(实际到账)";
result.put("text",rechargeText + rateText);
return ApiRes.ok(result);
}
/**
* 设置预警规则
* @return
*/
@PreAuthorize("hasAuthority('ENT_ACCOUNT_RULE')")
@PostMapping(value = "/warnRule")
public ApiRes warnRule() {
AccountInfo info = getObject(AccountInfo.class);
accountInfoService.setWarnRule(info);
if(AccountInfo.REMIND_OPNE.equals(info.getRemindState())){
Boolean val = RedisUtil.getObject(info.getAccountNo(),Boolean.class);
if(val == null || !val){
RedisUtil.set(info.getAccountNo(),true);
mqSender.send(AccountBalanceMQ.build(info.getAccountNo()),info.getRuleExt().getInterval() * 60 * 60);
}
}else{
RedisUtil.set(info.getAccountNo(),false);
}
return ApiRes.ok();
}
/**
* 发起提现
* @return
*/
@PreAuthorize("hasAuthority('ENT_ACCOUNT_CASH')")
@PostMapping(value = "/cash")
public ApiRes cash() {
AccountInfo info = getObject(AccountInfo.class);
accountInfoService.cash(info);
return ApiRes.ok("发起提现审核,等待后台审核");
}
/** 与阿里云sdk一样 直接extends PayOrderCreateReqModel无法传入到接口中对应的参数。 需要把所有的参数放进来。。。 = = 。 **/
@Data
public static class PayOrderCreateReqModelAddStoreId extends JeepayObject {
private static final long serialVersionUID = -3998573128290306948L;
@ApiField("pas")
private String pas;
@ApiField("storeId")
private String storeId;
@ApiField("qrcId")
private String qrcId;
@ApiField("mchNo")
private String mchNo; // 商户号
@ApiField("appId")
private String appId; // 应用ID
@ApiField("mchOrderNo")
String mchOrderNo; // 商户订单号
@ApiField("wayCode")
String wayCode; // 支付方式
@ApiField("amount")
Long amount; // 支付金额
@ApiField("currency")
String currency; // 货币代码当前只支持cny
@ApiField("clientIp")
String clientIp; // 客户端IP
@ApiField("subject")
String subject; // 商品标题
@ApiField("body")
String body; // 商品描述
@ApiField("channelBizData")
String channelBizData; // 渠道业务参数
@ApiField("notifyUrl")
String notifyUrl; // 异步通知地址
@ApiField("returnUrl")
String returnUrl; // 跳转通知地址
@ApiField("expiredTime")
String expiredTime; // 订单失效时间
@ApiField("channelExtra")
String channelExtra; // 特定渠道额外支付参数
@ApiField("extParam")
String extParam; // 商户扩展参数
@ApiField("divisionMode")
private Byte divisionMode; // 分账模式: 0-该笔订单不允许分账[默认], 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额)
@ApiField("sellerRemark")
String sellerRemark; // 卖家备注
@ApiField("buyerRemark")
String buyerRemark; // 买家备注
@ApiField("deviceInfo")
private DeviceInfo deviceInfo; // 设备信息
@ApiField("mchExtNo")
private String mchExtNo; // 新版商户号
}
}

View File

@@ -0,0 +1,33 @@
package com.jeequan.jeepay.mch.ctrl.alipay;
import com.jeequan.jeepay.bizcommons.manage.alipay.AlipayIotDeviceBindManage;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/***
* 支付宝Iot设备-店铺绑定ctrl
*
* @author zx
*
* @date 2023/03/13 15:26
*/
@RestController
@RequestMapping("/api/alipayIot")
public class AlipayIotDeviceBindController extends CommonCtrl {
@Autowired private AlipayIotDeviceBindManage alipayIotDeviceBindManage;
/** 绑定、解绑蚂蚁店铺 **/
@PreAuthorize("hasAuthority('ENT_DEVICE_RUYI_BIND')")
@PostMapping( "/bind/{deviceId}")
public ApiRes bind(@PathVariable("deviceId") Long deviceId) {
return alipayIotDeviceBindManage.bind(getCurrentMchNo(), deviceId, getValByteRequired("alipayBindState"), getValString("storeId"));
}
}

View File

@@ -0,0 +1,54 @@
package com.jeequan.jeepay.mch.ctrl.alipay;
import com.jeequan.jeepay.bizcommons.manage.alipay.AlipayOpenSpOperationManage;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/***
* 支付宝设备绑定
*
* @author zx
*
* @date 2023/03/13 15:26
*/
@RestController
@RequestMapping("/api/alipaySpOperation")
public class AlipayOpenSpOperationController extends CommonCtrl {
@Autowired private AlipayOpenSpOperationManage alipayOpenSpOperationManage;
/** 获取授权码 **/
@PreAuthorize("hasAnyAuthority('ENT_MCH_ALIPAY_SP_OPERATION')")
@GetMapping( "/queryQrcode")
public ApiRes queryQrcode() {
return alipayOpenSpOperationManage.queryQrcode(getCurrentMchNo(), getValStringRequired("alipayAccount"));
}
/** 发起授权 **/
@PreAuthorize("hasAnyAuthority('ENT_MCH_ALIPAY_SP_OPERATION')")
@PostMapping("/apply")
public ApiRes apply() {
return alipayOpenSpOperationManage.apply(getCurrentMchNo(), getValStringRequired("alipayAccount"));
}
/** 查询支付宝授权结果 **/
@PreAuthorize("hasAnyAuthority('ENT_MCH_ALIPAY_SP_OPERATION')")
@GetMapping("/queryResult")
public ApiRes queryResult() {
return alipayOpenSpOperationManage.queryResult(getCurrentMchNo());
}
/** 查询当前商户支付宝授权信息 **/
@PreAuthorize("hasAnyAuthority('ENT_MCH_ALIPAY_SP_OPERATION')")
@GetMapping("/authInfo")
public ApiRes authInfo() {
return alipayOpenSpOperationManage.authInfo(getCurrentMchNo());
}
}

View File

@@ -0,0 +1,61 @@
package com.jeequan.jeepay.mch.ctrl.alipay;
import com.jeequan.jeepay.bizcommons.manage.alipay.AlipayShopManage;
import com.jeequan.jeepay.core.entity.MchStore;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/***
* 蚂蚁门店ctrl
*
* @author zx
*
* @date 2023/03/13 15:26
*/
@RestController
@RequestMapping("/api/alipayShop")
public class AlipayShopController extends CommonCtrl {
@Autowired private AlipayShopManage alipayShopManage;
/** 查询店铺详情 **/
@PreAuthorize("hasAnyAuthority('ENT_MCH_ALIPAY_SHOP_VIEW', 'ENT_MCH_ALIPAY_SHOP_EDIT')")
@GetMapping( "/{storeId}")
public ApiRes query(@PathVariable("storeId") String storeId) {
return alipayShopManage.query(getCurrentMchNo(), storeId);
}
/** 创建店铺 **/
@PreAuthorize("hasAuthority('ENT_MCH_ALIPAY_SHOP_ADD')")
@PostMapping("/{storeId}")
public ApiRes create(@PathVariable("storeId") String storeId) {
MchStore mchStore = getObject(MchStore.class);
return alipayShopManage.create(getCurrentMchNo(), storeId, mchStore);
}
/** 修改店铺 **/
@PreAuthorize("hasAuthority('ENT_MCH_ALIPAY_SHOP_EDIT')")
@PutMapping("/{storeId}")
public ApiRes update(@PathVariable("storeId") String storeId) {
MchStore mchStore = getObject(MchStore.class);
return alipayShopManage.update(getCurrentMchNo(), storeId, mchStore);
}
/** 关闭店铺 **/
@PreAuthorize("hasAuthority('ENT_MCH_ALIPAY_SHOP_DELETE')")
@DeleteMapping( "/{storeId}")
public ApiRes close(@PathVariable("storeId") String storeId) {
return alipayShopManage.close(getCurrentMchNo(), storeId);
}
/** 根据申请单查询店铺创建结果 **/
@PreAuthorize("hasAuthority('ENT_MCH_ALIPAY_SHOP_STATUS')")
@GetMapping("/createResult/{storeId}")
public ApiRes createResultQuery(@PathVariable("storeId") String storeId) {
return alipayShopManage.createResultQuery(getCurrentMchNo(), storeId);
}
}

View File

@@ -0,0 +1,205 @@
package com.jeequan.jeepay.mch.ctrl.anon;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.bizcommons.manage.auth.AuthByQrcodeManage;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.JsonKit;
import com.jeequan.jeepay.db.entity.SysUserAuth;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.AuthService;
import com.jeequan.jeepay.service.impl.SysUserAuthService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;
/**
* 登录鉴权
*
* @author terrfly
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("/api/anon/auth")
public class AuthController extends CommonCtrl {
@Autowired
private AuthService authService;
@Autowired
private SmsManager smsManager;
@Autowired
private SysUserAuthService sysUserAuthService;
@Autowired
private UserDetailsService jeeUserDetailsServiceImpl;
/**
* 这里用于内部接口调用, 不要开放外部登录
* @return
*/
@PostMapping("/privateValidate")
@MethodLog(remark = "三方接口获取accessToken")
public ApiRes privateValidate() {
String userId = getValStringRequired("loginName");
String pwd = getValStringRequired("pwd");
SysUserAuth userAuth = sysUserAuthService.lambdaQuery()
.eq(SysUserAuth::getIdentifier, userId)
.eq(SysUserAuth::getCredential, pwd)
.eq(SysUserAuth::getSysType, CS.SYS_ROLE_TYPE.MCH)
.one();
Assert.notNull("用户ID或密码错误");
String loginPageType = JWTPayload.LOGIN_PAGE_TYPE.LITE;
UserDetails userDetails = jeeUserDetailsServiceImpl.loadUserByUsername(userAuth.getIdentifier());
String accessToken = authService.userDetailsProcess(userDetails, loginPageType, null, JWTPayload.CREDENTIAL_AUTH_TYPE.PASSWD, null);
return ApiRes.ok(accessToken);
}
/**
* 用户信息认证 获取iToken
* <p>
* 认证流程:
* <p>
* WEB端
* 1. 要求输入(用户名 、 密码、 图形验证码)必填, 此时若登录失败会有防穷举校验。
* 2. 若绑定了MFA并且第一步验证通过返回 {isMFA: true}
* 3. 进入到二次验证逻辑, 要求输入(用户名 、 密码、 MFACode , 正常逻辑: 用户名密码已经验证过了, 此时不会有防穷举的验证。 会直接进入到MFA验证过程。
* <p>
* APP: 不验证图形, 其他不变。
*/
@RequestMapping(value = "/validate", method = RequestMethod.POST)
@MethodLog(remark = "登录认证")
public ApiRes validate() throws BizException {
String loginPageType = Base64.decodeStr(getValStringRequired("lt")); //登录页面(终端)类型, 已做base64处理
// 是否app登录
boolean isApp = loginPageType.equals(JWTPayload.LOGIN_PAGE_TYPE.APP) || loginPageType.equals(JWTPayload.LOGIN_PAGE_TYPE.LITE)
|| loginPageType.equals(JWTPayload.LOGIN_PAGE_TYPE.FACE_APP);
String account = Base64.decodeStr(getValStringRequired("ia")); //用户名 i account, 已做base64处理
String ipassport = Base64.decodeStr(getValStringRequired("ip")); //密码 i passport, 已做base64处理
String vercode = isApp ? "" : Base64.decodeStr(getValStringRequired("vc")); // 验证码 vercode, 已做base64处理
String vercodeToken = isApp ? "" : Base64.decodeStr(getValStringRequired("vt")); //验证码token, vercode token , 已做base64处理
String mfaCode = StringUtils.isEmpty(getValString("mc")) ? null : Base64.decodeStr(getValString("mc")); // MFACode, 已做base64处理
// 验证码校验: WEB登录 & 第一次认证MFACode为空的情况
if (!isApp && StringUtils.isEmpty(mfaCode)) {
String cacheCode = RedisUtil.getString(CS.getCacheKeyImgCode(vercodeToken));
if (StringUtils.isEmpty(cacheCode) || !cacheCode.equalsIgnoreCase(vercode)) {
throw new BizException("验证码有误!");
}
}
// 返回前端 accessToken
return authService.authByAuthentication(account, ipassport, loginPageType, vercodeToken, mfaCode, request.getHeader(CS.FACE_DEVICE_NAME));
}
/**
* 用户信息认证[手机验证码登录] 获取iToken
**/
@RequestMapping(value = "/phoneCode", method = RequestMethod.POST)
@MethodLog(remark = "手机验证码登录")
public ApiRes phoneCode() throws BizException {
String loginPageType = Base64.decodeStr(getValStringRequired("lt")); //登录页面(终端)类型, 已做base64处理
String phone = Base64.decodeStr(getValStringRequired("phone")); // 手机号, 已做base64处理
String code = Base64.decodeStr(getValStringRequired("code")); // 验证码 code, 已做base64处理
// 校验验证码 && 如果有异常 抛异常
smsManager.checkSmsVercodeThrowBizEx(phone, code, CS.SMS_TYPE_API_ENUM.TYPE_AUTH);
// 返回前端 accessToken
return authService.authByPhoneCode(phone, loginPageType);
}
/**
* 图片验证码
**/
@RequestMapping(value = "/vercode", method = RequestMethod.GET)
public ApiRes vercode() throws BizException {
//定义图形验证码的长和宽 // 4位验证码
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(137, 40, 4, 80);
lineCaptcha.createCode(); //生成code
//redis
String vercodeToken = UUID.fastUUID().toString();
RedisUtil.setString(CS.getCacheKeyImgCode(vercodeToken), lineCaptcha.getCode(), CS.VERCODE_CACHE_TIME); //图片验证码缓存时间: 1分钟
JSONObject result = new JSONObject();
result.put("imageBase64Data", lineCaptcha.getImageBase64Data());
result.put("vercodeToken", vercodeToken);
result.put("expireTime", CS.VERCODE_CACHE_TIME);
return ApiRes.ok(result);
}
/**
* 轮询 登录二维码状态
**/
@GetMapping("/qrcodeStatus")
public ApiRes qrcodeStatus() {
String qrcodeNo = getValString("qrcodeNo");
// 未传入qrcodeNo直接返回一个并存入rediskeyLOGIN_QRCODE_qrcodeNo
if (StringUtils.isBlank(qrcodeNo)) {
qrcodeNo = CS.getCacheKeyLoginQrcode(IdUtil.simpleUUID());
AuthByQrcodeManage.setQrcodeStatusWaiting(qrcodeNo);
return ApiRes.ok(JsonKit.newJson("qrcodeNo", qrcodeNo));
}
// 根据传入的qrcodeNo判断二维码被扫状态
String qrCodeStatus = RedisUtil.getString(qrcodeNo);
// redis未查询到qrcodeNo信息
if (StringUtils.isBlank(qrCodeStatus)) {
return ApiRes.ok(JsonKit.newJson("qrcodeStatus", AuthByQrcodeManage.QRCODE_STATUS_EXPRIED));
}
JSONObject resJSON = new JSONObject();
if (qrCodeStatus.startsWith(AuthByQrcodeManage.QRCODE_STATUS_CONFIRMED + "_")) {
String tokenStr = qrCodeStatus.replaceFirst(AuthByQrcodeManage.QRCODE_STATUS_CONFIRMED + "_", "");
resJSON = JSONObject.parseObject(tokenStr);
resJSON.put("qrcodeStatus", AuthByQrcodeManage.QRCODE_STATUS_CONFIRMED);
// 清空二维码缓存
AuthByQrcodeManage.delQrcodeStatus(qrcodeNo);
} else if (qrCodeStatus.equals(AuthByQrcodeManage.QRCODE_STATUS_CANCELED)) {
resJSON.put("qrcodeStatus", AuthByQrcodeManage.QRCODE_STATUS_CANCELED);
// 清空二维码缓存
AuthByQrcodeManage.delQrcodeStatus(qrcodeNo);
} else {
resJSON.put("qrcodeStatus", qrCodeStatus);
}
return ApiRes.ok(resJSON);
}
}

View File

@@ -0,0 +1,110 @@
package com.jeequan.jeepay.mch.ctrl.anon;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.SysClientVersion;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysClientVersionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 版本管理
*
* @author xiaoyu
*
* @date 2021/12/31 11:11
*/
@Slf4j
@RestController
@RequestMapping("api/anon/clientVersion")
public class ClientVersionController extends CommonCtrl {
@Autowired private SysClientVersionService sysClientVersionService;
/**
* @author: xiaoyu
* @date: 2021/12/31 11:28
* @describe: 版本信息
*/
@RequestMapping(value = "/versionInfo", method = RequestMethod.GET)
public ApiRes versionInfo() {
// 版本号
String versionNumber = getValStringRequired("versionNumber");
SysClientVersion dbClientVersion = sysClientVersionService.getOne(
SysClientVersion.gw()
.eq(SysClientVersion::getClientType, SysClientVersion.CLIENT_TYPE_MCH)
.eq(SysClientVersion::getVersionSerialNumber, versionNumber)
);
//未查询到当前版本信息, 查询最新版本作为 需[强制更新] 的版本
if(dbClientVersion == null){
List<SysClientVersion> newVersionList = sysClientVersionService.page(
new Page<>(1, 1),
new QueryWrapper<SysClientVersion>().lambda().eq(SysClientVersion:: getClientType, SysClientVersion.CLIENT_TYPE_MCH).orderByDesc(SysClientVersion:: getVersionId)
).getRecords();
if(newVersionList != null && !newVersionList.isEmpty()){
SysClientVersion newVersion = newVersionList.get(0);
newVersion.setForceUpdate(CS.YES);
return ApiRes.ok(newVersion);
}else{
//未查询到 任何版本信息
return ApiRes.ok(new JSONObject());
}
}
// 查询到当前版本信息, 需查询当前版本之后的最新版本信息
List<SysClientVersion> newVersionList = sysClientVersionService.page(
new Page<>(1, 1),
new QueryWrapper<SysClientVersion>().lambda()
.eq(SysClientVersion:: getClientType, SysClientVersion.CLIENT_TYPE_MCH)
.gt(SysClientVersion:: getVersionId, dbClientVersion.getVersionId())
.orderByDesc(SysClientVersion:: getVersionId)
).getRecords();
if(newVersionList == null || newVersionList.isEmpty()){
//未查询到 任何版本信息
return ApiRes.ok(new JSONObject());
}
//最新版本信息
SysClientVersion newVersion = newVersionList.get(0);
//如果当前版本前,包含强制更新, 则更改当前版本为强制更新版本
long count = sysClientVersionService.count(
new QueryWrapper<SysClientVersion>().lambda()
.eq(SysClientVersion:: getClientType, SysClientVersion.CLIENT_TYPE_MCH)
.eq(SysClientVersion:: getForceUpdate, CS.YES)
.gt(SysClientVersion:: getVersionId, dbClientVersion.getVersionId())
);
if(count > 0){
newVersion.setForceUpdate(CS.YES);
}
return ApiRes.ok(newVersion);
}
/**
* @author: yr
* @date: 2023/02/10 16:20
* @describe: 商户通App获取最新版下载url
*/
@RequestMapping(value = "/downloadUrl", method = RequestMethod.GET)
public ApiRes downloadUrl() {
LambdaQueryWrapper<SysClientVersion> wrapper = SysClientVersion.gw();
wrapper.eq(SysClientVersion::getClientType, SysClientVersion.CLIENT_TYPE_MCH);
if (sysClientVersionService.count(wrapper) == 0){
return ApiRes.ok();
}
wrapper.orderByDesc(SysClientVersion::getVersionId);
wrapper.last("limit 1");
return ApiRes.ok(sysClientVersionService.getOne(wrapper).getDownloadUrl());
}
}

View File

@@ -0,0 +1,82 @@
package com.jeequan.jeepay.mch.ctrl.anon;
import cn.hutool.core.codec.Base64;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.InviteCodeUtil;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedList;
import java.util.List;
/**
* 商户注册
*
* @author xiaoyu
*
* @date 2021/12/30 14:59
*/
@RestController
@RequestMapping("/api/anon/register")
public class RegisterController extends CommonCtrl {
@Autowired private SysUserService sysUserService;
@Autowired private MchInfoService mchInfoService;
@Autowired private SmsManager smsManager;
/** 商户注册接口 **/
@PostMapping(value = "/mchRegister")
@MethodLog(remark = "商户注册")
public ApiRes retrieve() throws BizException {
// 商户名称, 已做base64处理
String mchName = getValStringRequired("mchName");
// 手机号, 已做base64处理
String phone = Base64.decodeStr(getValStringRequired("phone"));
// 验证码, 已做base64处理
String code = Base64.decodeStr(getValStringRequired("code"));
// 确认密码 confirmPassword, 已做base64处理
String confirmPwd = Base64.decodeStr(getValStringRequired("confirmPwd"));
// 商户类型 特约商户、普通商户
// Byte mchType = getValByteRequired("mchType");
// 邀请码
String inviteCode = getValString("inviteCode");
// 验证短信验证码
smsManager.checkSmsVercodeThrowBizEx(phone, code, CS.SMS_TYPE_API_ENUM.TYPE_REGISTER);
// 注册商户信息 *默认注册为特约商户
mchInfoService.mchRegister(mchName, phone, confirmPwd, CS.MCH_TYPE_ISVSUB, inviteCode);
return ApiRes.ok();
}
/** 处理邀请码 **/
@PostMapping(value = "/inviteCode")
public ApiRes inviteCode() throws BizException {
List<SysUserEntity> sysUserEntityList = sysUserService.list();
List<SysUserEntity> updateList = new LinkedList<>();
for (SysUserEntity sysUserEntity : sysUserEntityList) {
SysUserEntity update = new SysUserEntity();
update.setSysUserId(sysUserEntity.getSysUserId());
update.setInviteCode(InviteCodeUtil.idToCode(sysUserEntity.getSysUserId()));
updateList.add(update);
}
sysUserService.updateBatchById(updateList);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,71 @@
package com.jeequan.jeepay.mch.ctrl.anon;
import cn.hutool.core.codec.Base64;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysConfigService;
import com.jeequan.jeepay.service.impl.SysUserAuthService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/*
* 登录密码接口
*
* @author xiaoyu
*
* @date 2021/6/8 17:09
*/
@RestController
@RequestMapping("/api/anon/cipher")
public class RetrieveController extends CommonCtrl {
@Autowired private SysUserService sysUserService;
@Autowired private SysUserAuthService sysUserAuthService;
@Autowired private SysConfigService sysConfigService;
@Autowired private SmsManager smsManager;
/** 密码找回接口 **/
@RequestMapping(value = "/retrieve", method = RequestMethod.POST)
@MethodLog(remark = "密码找回")
public ApiRes retrieve() throws BizException {
// 手机号, 已做base64处理
String phone = Base64.decodeStr(getValStringRequired("phone"));
// 验证码, 已做base64处理
String code = Base64.decodeStr(getValStringRequired("code"));
// 新密码 password, 已做base64处理
String newPwd = Base64.decodeStr(getValString("newPwd"));
// 验证手机号
smsManager.checkSmsVercodeThrowBizEx(phone, code, CS.SMS_TYPE_API_ENUM.TYPE_RETRIEVE);
SysUserEntity dbUser = sysUserService.getOne(SysUserEntity.gw().eq(SysUserEntity::getTelphone, phone).eq(SysUserEntity::getSysType, CS.SYS_ROLE_TYPE.MCH));
if (dbUser == null) {
throw new BizException("用户不存在");
}
if (StringUtils.isNotEmpty(newPwd)) {
// 更新用户登录密码
sysUserAuthService.resetAuthInfo(dbUser.getSysUserId(), null, null, true, newPwd, CS.SYS_ROLE_TYPE.MCH);
// TODO mq更新用户密码
}
return ApiRes.ok();
}
/** 获取密码校验规则正则 **/
@RequestMapping(value = "/pwdRulesRegexp", method = RequestMethod.GET)
public ApiRes getPwdRulesRegexp() throws BizException {
return ApiRes.ok(sysConfigService.getDBSecurityConfig().getPasswordRegexp());
}
}

View File

@@ -0,0 +1,85 @@
package com.jeequan.jeepay.mch.ctrl.anon;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBOEMConfig;
import com.jeequan.jeepay.core.service.ISysConfigService;
import com.jeequan.jeepay.core.utils.JsonKit;
import com.jeequan.jeepay.db.entity.AgentConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.AgentConfigService;
import com.jeequan.jeepay.service.impl.SysAdvertConfigService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 网站信息ctrl
*
* @author terrfly
*
* @date 2022/2/14 20:56
*/
@RestController
@RequestMapping("/api/anon/siteInfos")
public class SiteInfoController extends CommonCtrl {
@Autowired private ISysConfigService sysConfigService;
@Autowired private SysAdvertConfigService advertConfigService;
@Autowired private AgentConfigService agentConfigService;
@GetMapping(value = "")
public ApiRes getSiteInfos() throws BizException {
JSONObject result = new JSONObject();
result.put("sysConfig", JsonKit.newJson("httpMsgIsEncrypt", SysConfigService.HTTP_MSG_IS_ENCRYPT));
DBOEMConfig dboemConfig = sysConfigService.getOemConfig();
//获取域名
String headerDomainName = getdomainName();
if (headerDomainName != null && headerDomainName.contains("//")) {
int startIndex = headerDomainName.indexOf("//") + 2; // 获取第一个 "//" 后的位置
int endIndex = headerDomainName.indexOf("/", startIndex); // 获取从 startIndex 开始的第一个 "/"
if (endIndex != -1) {
String domainName = headerDomainName.substring(startIndex, endIndex);
AgentConfig agentConfig = agentConfigService.getOne(AgentConfig.gw().eq(AgentConfig::getGroupKey, "agentSiteConfig")
.eq(AgentConfig::getConfigVal,domainName)
.last("limit 1"));
if (agentConfig == null){
//该域名没配置,取总后台数据
result.put("siteInfo", dboemConfig);
return ApiRes.ok(result);
}
//获取商户域名
AgentConfig mchDomainName = agentConfigService.getOne(AgentConfig.gw().eq(AgentConfig::getGroupKey, "agentSiteConfig")
.eq(AgentConfig::getConfigKey, "mchSiteUrl")
.eq(AgentConfig::getAgentNo,agentConfig.getAgentNo()));
if (mchDomainName !=null){
result.put("mchDomainName", mchDomainName.getConfigVal());
}
//获取服务商域名
AgentConfig agentDomainName = agentConfigService.getOne(AgentConfig.gw().eq(AgentConfig::getGroupKey, "agentSiteConfig")
.eq(AgentConfig::getConfigKey, "agentSiteUrl")
.eq(AgentConfig::getAgentNo,agentConfig.getAgentNo()));
if (mchDomainName !=null){
result.put("agentDomainName", agentDomainName.getConfigVal());
}
AgentConfig oemConfig = agentConfigService.getOne(AgentConfig.gw().eq(AgentConfig::getConfigKey, "oemConfig")
.eq(AgentConfig::getAgentNo,agentConfig.getAgentNo()));
if(oemConfig == null){
//贴牌数据为空,取总后台数据
result.put("siteInfo", dboemConfig);
return ApiRes.ok(result);
}
result.put("siteInfo", JSONObject.parseObject(oemConfig.getConfigVal()));
}
}
return ApiRes.ok(result);
}
}

View File

@@ -0,0 +1,71 @@
package com.jeequan.jeepay.mch.ctrl.anon;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysConfigService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/*
* 短信验证
*
* @author xiaoyu
*
* @date 2021/6/8 17:09
*/
@RestController
@RequestMapping("/api/anon/sms")
public class SmsCodeController extends CommonCtrl {
@Autowired private SysUserService sysUserService;
@Autowired private SysConfigService sysConfigService;
@Autowired private SmsManager smsManager;
/** 发送短信验证码 **/
@RequestMapping(value = "/code", method = RequestMethod.POST)
public ApiRes code() throws BizException {
// 验证参数 手机号, 已做base64处理
String phone = getValStringRequired("phone");
String smsType = getValStringRequired("smsType");
String vercodeToken = getValStringRequired("vercodeToken");
String vercode = getValStringRequired("vercode");
String redisVercode = RedisUtil.getString(CS.getCacheKeyImgCode(vercodeToken));
if (!vercode.equalsIgnoreCase(redisVercode)) {
throw new BizException("验证码错误");
}
// 校验用户
checkUser(phone, smsType);
smsManager.sendSmsVercode(phone, smsType);
return ApiRes.ok();
}
/**
* @author: xiaoyu
* @date: 2022/1/14 9:01
* @describe: 校验用户是否存在
*/
private void checkUser(String phone, String smsType) {
SysUserEntity dbUser = sysUserService.getOne(SysUserEntity.gw().eq(SysUserEntity::getTelphone, phone).eq(SysUserEntity::getSysType, CS.SYS_ROLE_TYPE.MCH));
if (CS.SMS_TYPE_API_ENUM.TYPE_REGISTER.equals(smsType)) {
if (dbUser != null) {
throw new BizException("当前用户已存在");
}
} else {
if (dbUser == null) {
throw new BizException("用户不存在");
}
}
}
}

View File

@@ -0,0 +1,66 @@
package com.jeequan.jeepay.mch.ctrl.anon;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.AgentConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.AgentConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 服务政策 隐私协议ctrl
*
* @author xiaoyu
*
* @date 2022/2/16 14:51
*/
@RestController
@RequestMapping("/api/anon/treaty")
public class TreatyController extends CommonCtrl {
@Autowired
private AgentConfigService agentConfigService;
@GetMapping(value = "")
public ApiRes getTreaty() throws BizException {
Map<String,Object> result = new HashMap<>();
//获取域名
String headerDomainName = getdomainName();
if (headerDomainName != null && headerDomainName.contains("//")) {
int startIndex = headerDomainName.indexOf("//") + 2; // 获取第一个 "//" 后的位置
int endIndex = headerDomainName.indexOf("/", startIndex); // 获取从 startIndex 开始的第一个 "/"
if (endIndex != -1) {
String domainName = headerDomainName.substring(startIndex, endIndex);
AgentConfig agentConfig = agentConfigService.getOne(AgentConfig.gw().eq(AgentConfig::getGroupKey, "agentSiteConfig")
.eq(AgentConfig::getConfigVal,domainName)
.last("limit 1"));
if (agentConfig == null){
//该域名没配置,取总后台数据
return ApiRes.ok(sysConfigService.getTreatyConfig());
}
List<AgentConfig> treatyConfigList = agentConfigService.list(AgentConfig.gw().eq(AgentConfig::getGroupKey, "treatyConfig")
.eq(AgentConfig::getAgentNo,agentConfig.getAgentNo()));
if(treatyConfigList.isEmpty()){
//贴牌数据为空,取总后台数据
return ApiRes.ok(sysConfigService.getTreatyConfig());
}else {
for (AgentConfig config : treatyConfigList) {
result.put(config.getConfigKey(), config.getConfigVal());
}
return ApiRes.ok(result);
}
}
}
return ApiRes.ok(sysConfigService.getTreatyConfig());
}
}

View File

@@ -0,0 +1,34 @@
package com.jeequan.jeepay.mch.ctrl.applyment;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBDefaultConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 系统默认配置
*
* @author xiaoyu
*
* @date 2023/4/11 9:38
*/
@RestController
@RequestMapping("/api/defaultConfig")
public class DefaultConfigController extends CommonCtrl {
/** 平台默认配置查询 **/
@GetMapping("")
public ApiRes getDefaultConfig() {
JSONObject result = new JSONObject();
// 进件图片大小默认配置
DBDefaultConfig defaultConfig = sysConfigService.getDBDefaultConfig();
result.put("applymentImgUploadSize", defaultConfig.getApplymentImgUploadSize());
return ApiRes.ok(result);
}
}

View File

@@ -0,0 +1,54 @@
package com.jeequan.jeepay.mch.ctrl.applyment;
import com.jeequan.jeepay.converter.MchInfoConverter;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchApplyment;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchApplymentService;
import com.jeequan.jeepay.thirdparty.channel.kqpay.KqpayMchApplymentService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@RestController
@RequestMapping("/api/mchApplyments")
public class KqpayMchApplymentController extends CommonCtrl {
@Autowired
private MchApplymentService mchApplymentService;
@Autowired
private KqpayMchApplymentService kqpayMchApplymentService;
@Autowired
private MchInfoConverter mchInfoConverter;
@PostMapping("/kqSignApply/{recordId}")
public ApiRes signApply(@PathVariable("recordId") String recordId) {
MchApplyment dbRecord = mchApplymentService.getById(recordId);
if (dbRecord == null || dbRecord.getState() != MchApplyment.STATE_WAIT_SIGN) {
throw new BizException("请刷新当前申请单状态,该申请单当前状态无法执行该操作。");
}
com.jeequan.jeepay.core.entity.MchApplyment mchApplyment = kqpayMchApplymentService.signApply(mchInfoConverter.toModel(dbRecord));
MchApplyment applymentResult = new MchApplyment();
BeanUtils.copyProperties(mchApplyment, applymentResult);
// 当状态发生了变化时
if (!dbRecord.getState().equals(applymentResult.getState())) {
// 更新数据
applymentResult.setApplyId(recordId);
applymentResult.setLastApplyAt(new Date());
mchApplymentService.updateById(applymentResult);
}
return ApiRes.ok(applymentResult);
}
}

View File

@@ -0,0 +1,38 @@
package com.jeequan.jeepay.mch.ctrl.applyment;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/api/mchApplyments")
public class LklspayMchApplymentController {
/** 拉卡拉获取银行信息列表 **/
@GetMapping("/getLklBankList/{areaCode}/{branchName}")
public ApiRes getLklBankList(@PathVariable("areaCode") String areaCode, @PathVariable("branchName") String branchName) {
HttpResponse httpResponse = null;
try {
String result = null;
if (StringUtils.isNotEmpty(areaCode)) {
httpResponse = HttpRequest.get("https://tkapi.lakala.com/registration/bank?areaCode=" + areaCode + "&bankName=" + branchName).execute();
result = httpResponse.body();
}
return ApiRes.ok(result);
} catch (Exception e) {
throw new BizException(e.getMessage());
} finally {
if (httpResponse != null) {
httpResponse.close();
}
}
}
}

View File

@@ -0,0 +1,276 @@
package com.jeequan.jeepay.mch.ctrl.applyment;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.components.mq.model.MchAuditThirdNotifyMQ;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.converter.MchInfoConverter;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchModifyApplyment;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.paychannel.IYsApplymentApiService;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchApplyment;
import com.jeequan.jeepay.db.entity.MchModifyApplymentEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchAppService;
import com.jeequan.jeepay.service.impl.MchApplymentService;
import com.jeequan.jeepay.service.impl.MchModifyApplymentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/api/mchApplyments")
public class YspayMchApplymentController extends CommonCtrl {
@Autowired private MchApplymentService mchApplymentService;
@Autowired private MchModifyApplymentService mchModifyApplymentService;
@Autowired private MchAppService mchAppService;
@Autowired
private MchInfoConverter mchInfoConverter;
@Autowired private IMQSender mqSender;
/** 银盛 上传图片 **/
@PostMapping("/yspayUpload/{recordId}")
public ApiRes yspayUpload(@PathVariable("recordId") String recordId) {
JSONObject paramJSON = getReqParamJSON();
MchApplyment dbRecord = mchApplymentService.getById(recordId);
// 只有申请单状态为待上传图片的才可以进行这一步操作
if (dbRecord == null || dbRecord.getState() != MchApplyment.STATE_WAIT_VERIFY || dbRecord.getRemainStep() != 2) {
throw new BizException("当前申请单状态错误,无法继续。");
}
IYsApplymentApiService ysApplymentApiService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(dbRecord.getIfCode()) + "ApplymentApiService", IYsApplymentApiService.class);
String respJSONStr;
// 更新参数
dbRecord.setApplyDetailInfo(paramJSON.toJSONString());
// 调起接口
com.jeequan.jeepay.core.entity.MchApplyment mchApplymentImg = ysApplymentApiService.uploadImg(mchInfoConverter.toModel(dbRecord));
respJSONStr = mchApplymentImg.getChannelVar1();
MchApplyment updateRecord = new MchApplyment();
updateRecord.setApplyDetailInfo(dbRecord.getApplyDetailInfo());
BeanUtils.copyProperties(mchApplymentImg, updateRecord);
// 更新数据
updateRecord.setApplyId(recordId);
mchApplymentService.updateById(updateRecord);
return ApiRes.ok(respJSONStr);
}
/** 银盛 资料确认 **/
@PostMapping("/yspayConfirm/{recordId}")
public ApiRes yspayConfirm(@PathVariable("recordId") String recordId) {
MchApplyment dbRecord = mchApplymentService.getById(recordId);
// 只有申请单状态为待确认的才可以进行这一步操作
if (dbRecord == null || dbRecord.getState() != MchApplyment.STATE_WAIT_VERIFY || dbRecord.getRemainStep() != 1) {
throw new BizException("当前申请单状态错误,无法继续。");
}
IYsApplymentApiService ysApplymentApiService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(dbRecord.getIfCode()) + "ApplymentApiService", IYsApplymentApiService.class);
String respJSONStr = "";
// 提交审核
com.jeequan.jeepay.core.entity.MchApplyment applymentResult = ysApplymentApiService.attachConfirm(mchInfoConverter.toModel(dbRecord));
respJSONStr = applymentResult.getApplyErrorInfo();
MchApplyment updateRecordAudit = new MchApplyment();
BeanUtils.copyProperties(applymentResult, updateRecordAudit);
// 更新数据
updateRecordAudit.setApplyId(recordId);
mchApplymentService.updateById(updateRecordAudit);
return ApiRes.ok(respJSONStr);
}
/** 银盛 发起合同签约 **/
@PostMapping("/ysSignApply/{recordId}")
public ApiRes ysSignApply(@PathVariable("recordId") String recordId) {
MchApplyment dbRecord = mchApplymentService.getById(recordId);
if (dbRecord == null || dbRecord.getState() != MchApplyment.STATE_WAIT_SIGN) {
throw new BizException("请刷新当前申请单状态,该申请单当前状态无法执行该操作。");
}
IYsApplymentApiService ysApplymentApiService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(dbRecord.getIfCode()) + "ApplymentApiService", IYsApplymentApiService.class);
// 调起接口
com.jeequan.jeepay.core.entity.MchApplyment applymentResult = ysApplymentApiService.signApply(getReqParamJSON(), mchInfoConverter.toModel(dbRecord));
// 更新商户费率配置
MchApplyment updateRecordAudit = new MchApplyment();
BeanUtils.copyProperties(applymentResult, updateRecordAudit);
// 更新数据
updateRecordAudit.setApplyId(recordId);
mchApplymentService.updateById(updateRecordAudit);
return ApiRes.ok(applymentResult.getChannelVar2());
}
/** 银盛 查询合同签约状态 **/
@PostMapping("/ysSignQuery/{recordId}")
public ApiRes ysSignQuery(@PathVariable("recordId") String recordId) {
MchApplyment dbRecord = mchApplymentService.getById(recordId);
if (dbRecord == null || dbRecord.getState() != MchApplyment.STATE_WAIT_SIGN) {
throw new BizException("请刷新当前申请单状态,该申请单当前状态无法执行该操作。");
}
// 获取当前进件签约信息,未发起签约时为空
if (StringUtils.isBlank(dbRecord.getChannelVar2())) {
return ApiRes.ok();
}
IYsApplymentApiService ysApplymentApiService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(dbRecord.getIfCode()) + "ApplymentApiService", IYsApplymentApiService.class);
// 调起接口
com.jeequan.jeepay.core.entity.MchApplyment applymentResult = ysApplymentApiService.signQuery(mchInfoConverter.toModel(dbRecord));
// 更新商户费率配置
MchApplyment updateRecordAudit = new MchApplyment();
BeanUtils.copyProperties(applymentResult, updateRecordAudit);
// 更新数据
updateRecordAudit.setApplyId(recordId);
mchApplymentService.updateById(updateRecordAudit);
if (updateRecordAudit.getState() == MchApplyment.STATE_SUCCESS) {
mchApplymentService.onApplymentSuccess(updateRecordAudit.getApplyId());
mqSender.send(MchAuditThirdNotifyMQ.build(recordId, MchAuditThirdNotifyMQ.TYPE_AUDIT));
}
return ApiRes.ok(applymentResult.getChannelVar2());
}
/** 银盛 签约重发 **/
@PostMapping("/ysSignSendAgain/{recordId}")
public ApiRes ysSignSendAgain(@PathVariable("recordId") String recordId) {
MchApplyment dbRecord = mchApplymentService.getById(recordId);
if (dbRecord == null) {
MchModifyApplymentEntity modifyApplyment = mchModifyApplymentService.getById(recordId);
if (modifyApplyment == null || modifyApplyment.getState() != MchApplyment.STATE_WAIT_SIGN) {
throw new BizException("请刷新当前申请单状态,该申请单当前状态无法执行该操作。");
}
IYsApplymentApiService ysApplymentApiService = SpringBeansUtil.getBean(CS.IF_CODE.YSPAY + "ApplymentApiService", IYsApplymentApiService.class);
// 调起接口
MchModifyApplyment applymentResult = ysApplymentApiService.signSendAgain(getReqParamJSON(), mchInfoConverter.toModel(modifyApplyment));
// 更新数据
if (!StrUtil.isEmpty(applymentResult.getChannelVar1())) {
MchModifyApplymentEntity updateRecordAudit = new MchModifyApplymentEntity();
updateRecordAudit.setApplyId(recordId);
updateRecordAudit.setChannelVar1(applymentResult.getChannelVar1());
mchModifyApplymentService.updateById(updateRecordAudit);
}
return ApiRes.ok(applymentResult.getChannelVar1());
} else {
if (dbRecord.getState() != MchApplyment.STATE_WAIT_SIGN) {
throw new BizException("请刷新当前申请单状态,该申请单当前状态无法执行该操作。");
}
IYsApplymentApiService ysApplymentApiService = SpringBeansUtil.getBean(CS.IF_CODE.YSPAY + "ApplymentApiService", IYsApplymentApiService.class);
// 调起接口
com.jeequan.jeepay.core.entity.MchApplyment applymentResult = ysApplymentApiService.signSendAgain(getReqParamJSON(), mchInfoConverter.toModel(dbRecord));
// 更新数据
if (!StrUtil.isEmpty(applymentResult.getChannelVar2())) {
MchApplyment updateRecordAudit = new MchApplyment();
updateRecordAudit.setApplyId(recordId);
updateRecordAudit.setChannelVar2(applymentResult.getChannelVar2());
mchApplymentService.updateById(updateRecordAudit);
}
return ApiRes.ok(applymentResult.getChannelVar2());
}
}
/** 银盛费率配置 **/
@PostMapping("/ysPayRateConfig/{recordId}")
public ApiRes ysPayRateConfig(@PathVariable("recordId") String recordId) {
JSONObject reqParamJSON = getReqParamJSON();
MchApplyment dbRecord = mchApplymentService.getById(recordId);
if (dbRecord == null || (dbRecord.getState() != MchApplyment.STATE_AUDITING && dbRecord.getState() != MchApplyment.STATE_REJECT_WAIT_MODIFY
&& dbRecord.getState() != MchApplyment.STATE_WAIT_SIGN)) {
throw new BizException("请刷新当前申请单状态,该申请单当前状态无法执行该操作。");
}
IYsApplymentApiService ysApplymentApiService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(dbRecord.getIfCode()) + "ApplymentApiService", IYsApplymentApiService.class);
// 调起接口
com.jeequan.jeepay.core.entity.MchApplyment applymentResult = ysApplymentApiService.payRateConfig(reqParamJSON, mchInfoConverter.toModel(dbRecord));
// 更新商户费率配置
MchApplyment updateRecordAudit = new MchApplyment();
// 配置成功更新费率
if (applymentResult.getState() != null && applymentResult.getState() == MchApplyment.STATE_SUCCESS) {
BeanUtils.copyProperties(applymentResult, updateRecordAudit);
} else {
applymentResult.setApplyDetailInfo(null);
applymentResult.setState(MchApplyment.STATE_AUDITING);
BeanUtils.copyProperties(applymentResult, updateRecordAudit);
}
// 更新数据
updateRecordAudit.setApplyId(recordId);
mchApplymentService.updateById(updateRecordAudit);
return ApiRes.ok(applymentResult.getChannelVar1());
}
/** 银盛 配置相关信息 **/
@PostMapping("/yspayInterfaceConfig/{applyId}/{mchAppId}")
public ApiRes yspayInterfaceConfig(@PathVariable("applyId") String applyId, @PathVariable("mchAppId") String mchAppId) {
String configType = getValStringRequired("configType"); // PAY_BASE_URL, BIND_APP_ID, SUBSCRIBE_APP_ID, QUERY
String configVal = getValStringRequired("configVal");
MchApplyment tbMchApplyment = mchApplymentService.getById(applyId);
MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
IYsApplymentApiService applymentApiService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(tbMchApplyment.getIfCode()) + "ApplymentApiService", IYsApplymentApiService.class);
if (applymentApiService != null && "PAY_BASE_URL".equals(configType)) {
return ApiRes.ok(applymentApiService.configPayBaseUrl(configVal, mchAppEntity.getAppId(), mchInfoConverter.toModel(tbMchApplyment)));
} else if (applymentApiService != null && "BIND_APP_ID".equals(configType)) {
return ApiRes.ok(applymentApiService.configBindAppId(configVal, mchAppEntity.getAppId(), mchInfoConverter.toModel(tbMchApplyment)));
} else if (applymentApiService != null && "SUBSCRIBE_APP_ID".equals(configType)) {
return ApiRes.ok(applymentApiService.configSubscribeAppId(configVal, mchAppEntity.getAppId(), mchInfoConverter.toModel(tbMchApplyment)));
}
return ApiRes.customFail("没有[" + configType + "]配置");
}
}

View File

@@ -0,0 +1,50 @@
package com.jeequan.jeepay.mch.ctrl.appmanage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchAppApplyment;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchAppApplymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 应用管理类
*/
@RestController
@RequestMapping("/api/mchappapplyment")
public class MchAppApplymentController extends CommonCtrl {
@Autowired
private MchAppApplymentService mchAppApplymentService;
/**
* 查询应用与商户进件数据表
*
* @return
*/
@PreAuthorize("true ")
@GetMapping
public ApiRes inquire() {
MchAppApplyment queryObject = getObject(MchAppApplyment.class);
//获取分页参数G
Page<MchAppApplyment> page = getIPage();
return ApiRes.ok(mchAppApplymentService.appApplymentsInquire(page, queryObject));
}
@PreAuthorize("true ")
@PutMapping
@MethodLog(remark = "修改调整商户池关联关系")
public ApiRes update() {
MchAppApplyment queryObject = getObject(MchAppApplyment.class);
boolean delAuthenticationFlag = mchAppApplymentService.appApplymentRevamp(queryObject);
return ApiRes.ok(delAuthenticationFlag);
}
}

View File

@@ -0,0 +1,426 @@
package com.jeequan.jeepay.mch.ctrl.aqf;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipayFundAccountbookQueryResponse;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.components.oss.service.AliyunOssOssService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.TransferOrder;
import com.jeequan.jeepay.core.entity.TransferSubject;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.tranfer.TransferBasicInfo;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import com.jeequan.jeepay.thirdparty.channel.alipay.AliAqfV2Service;
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@RestController
@RequestMapping("/api/aqfApi")
public class AqfApiController extends CommonCtrl {
@Autowired
private AliAqfV2Service aliAqfV2Service;
@Autowired
private SysConfigService sysConfigService;
@Autowired
private TransferSubjectService transferSubjectService;
@Autowired
private TaskListService taskListService;
@Autowired
private ChannelCertConfigKitBean channelCertConfigKitBean;
@Autowired
private TransferWalletService transferWalletService;
@Autowired
private AliyunOssOssService aliyunOssOssService;
@Autowired
private MchInfoService mchInfoService;
@Autowired
private SmsManager smsManager;
/**
* 签约
*
* @return
*/
@RequestMapping(value = "/signUrl", method = RequestMethod.GET)
public ApiRes signUrl() {
String subId = getValStringRequired("subId");
String resutUrl = aliAqfV2Service.userAgreementPageSign(subId);
return ApiRes.ok(resutUrl);
}
/**
* 支付宝个人代扣协议查询接口
*
* @return
*/
@RequestMapping(value = "/agreementQuery" , method = RequestMethod.GET)
public ApiRes agreementQuery(){
String subId = getValStringRequired("subId");
JSONObject alipayUserAgreementQueryResponse = aliAqfV2Service.userAgreementQuery(subId);
return ApiRes.ok(alipayUserAgreementQueryResponse);
}
/**
* 解约
*
* @return
*/
@RequestMapping(value = "/userAgreementUnsign" , method = RequestMethod.GET)
public ApiRes userAgreementUnsign(){
String subId = getValStringRequired("subId");
JSONObject alipayUserAgreementUnsignResponse = aliAqfV2Service.userAgreementUnsign(subId);
return ApiRes.ok(alipayUserAgreementUnsignResponse);
}
/**
* 记账本开通
*
* @return
*/
/*@RequestMapping(value = "/alipayFundAccountbookCreate" , method = RequestMethod.GET)
public ApiRes alipayFundAccountbookCreate(){
String subId = getValStringRequired("subId");
JSONObject createResponse = aliAqfV2Service.fundAccountbookCreate(subId, getDefaultIsvConfig());
return ApiRes.ok(createResponse);
}*/
/**
* 记账本查询
*
* @return
*/
@RequestMapping(value = "/alipayFundAccountbookQuery", method = RequestMethod.GET)
public ApiRes alipayFundAccountbookQuery() {
String subId = getValStringRequired("subId");
// 设计上,一个签约主体可以创建多个记账本,实际使用的时候,尽量保持一个签约主体只有一个账本
String walletApplyId = getValString("walletApplyId");
AlipayFundAccountbookQueryResponse alipayFundAccountbookQueryResponse = aliAqfV2Service.fundAccountbookQuery(walletApplyId);
return ApiRes.ok(JSON.parseObject(alipayFundAccountbookQueryResponse.getBody()).getJSONObject("alipay_fund_accountbook_query_response"));
}
/**
* 资金专款拨入(商户自身给记账本充值)
*
* @return
*/
@RequestMapping(value = "/transPage" , method = RequestMethod.GET)
public ApiRes transPage(){
String subId = getValStringRequired("subId");
String transAmount = getValStringRequired("transAmount");
String transferDesc = getValString("transferDesc");
String transedUrl = aliAqfV2Service.transPage(subId, transAmount ,transferDesc);
return ApiRes.ok(transedUrl);
}
/**
* 单笔生成待发待结算信息
*
* @return
*/
@RequestMapping(value = "/settlementData", method = RequestMethod.POST)
public ApiRes settlementData() {
String mchNo = getCurrentMchNo();
String transferSubjectIdFq = getValStringRequired("transferSubjectIdFq");
// String vc = Base64.decodeStr(getValStringRequired("vc"));
// String vt = Base64.decodeStr(getValStringRequired("vt"));
String sipw = Base64.decodeStr(getValStringRequired("sipw"));
// 验证码校验
// String cacheCode = RedisUtil.getString(CS.getCacheKeyImgCode(vt));
// if(StringUtils.isEmpty(cacheCode) || !cacheCode.equalsIgnoreCase(vc)){
// throw new BizException("验证码有误!");
// }
TransferSubjectEntity transferSubject = transferSubjectService.getById(transferSubjectIdFq);
if (!transferSubject.getInfoType().equals(CS.SYS_ROLE_TYPE.MCH)
|| !mchNo.equals(transferSubject.getMchNo())) {
throw new BizException("非法操作");
}
MchInfo mchInfo = mchInfoService.getById(transferSubject.getMchNo());
if (!new BCryptPasswordEncoder().matches(sipw, mchInfo.getSipw())) {
throw new BizException("支付密码验证失败!");
}
String code = Base64.decodeStr(getValStringRequired("code")); // 验证码 code, 已做base64处理
// 校验验证码
smsManager.checkSmsVercodeThrowBizEx(mchInfo.getContactTel(), code, CS.SMS_TYPE_API_ENUM.TYPE_AUTH);
SettlementDataModel object = getObject(SettlementDataModel.class);
String date = aliAqfV2Service.settlementData(object.getTransferSubjectIdFq(), object.getTransferOrders());
return ApiRes.ok(date);
}
@PostMapping("/batchSettlementData")
public ApiRes uploadExcel() {
String mchNo = getCurrentMchNo();
String transferSubjectIdFq = getValStringRequired("transferSubjectIdFq");
// String vc = Base64.decodeStr(getValStringRequired("vc"));
// String vt = Base64.decodeStr(getValStringRequired("vt"));
String sipw = Base64.decodeStr(getValStringRequired("sipw"));
// 验证码校验
// String cacheCode = RedisUtil.getString(CS.getCacheKeyImgCode(vt));
// if(StringUtils.isEmpty(cacheCode) || !cacheCode.equalsIgnoreCase(vc)){
// throw new BizException("验证码有误!");
// }
TransferSubjectEntity transferSubject = transferSubjectService.getById(transferSubjectIdFq);
if (!transferSubject.getInfoType().equals(CS.SYS_ROLE_TYPE.MCH)
|| !mchNo.equals(transferSubject.getMchNo())) {
throw new BizException("非法操作");
}
MchInfo mchInfo = mchInfoService.getById(transferSubject.getMchNo());
if (!new BCryptPasswordEncoder().matches(sipw, mchInfo.getSipw())) {
throw new BizException("支付密码验证失败!");
}
String code = Base64.decodeStr(getValStringRequired("code")); // 验证码 code, 已做base64处理
// 校验验证码
smsManager.checkSmsVercodeThrowBizEx(mchInfo.getContactTel(), code, CS.SMS_TYPE_API_ENUM.TYPE_AUTH);
String excelFileName = getValStringRequired("excelFileName");
String tempDir = System.getProperty("java.io.tmpdir");
String fileName = excelFileName.substring(excelFileName.lastIndexOf("/") + 1);
File excelFile = new File(new File(tempDir), fileName);
HttpUtil.downloadFile(excelFileName, excelFile);
SettlementDataModel params = getObject(SettlementDataModel.class);
List<SettleBatchExcel> dataList = new ArrayList<>();
List<TransferOrder> transferOrderList = new ArrayList<>();
String batch = "BATCH" + DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6);
try {
InputStream inputStream = Files.newInputStream(excelFile.toPath());
EasyExcel.read(inputStream, SettleBatchExcel.class, new AnalysisEventListener<SettleBatchExcel>() {
@Override
public void invoke(SettleBatchExcel settleBatchExcel, AnalysisContext analysisContext) {
dataList.add(settleBatchExcel);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 解析完成后的操作,可以在这里进行一些清理工作
}
}).sheet().doRead();
//把数据新增到收款信息中
TransferSubjectEntity sponsor = transferSubjectService.getById(params.getTransferSubjectIdFq());
if (!CS.SYS_ROLE_TYPE.MCH.equalsIgnoreCase(sponsor.getInfoType())
|| !getCurrentMchNo().equalsIgnoreCase(sponsor.getMchNo())) {
throw new BizException("非法访问");
}
if (!Objects.equals(sponsor.getState(), TransferSubject.STATE_ENABLE)) {
throw new BizException("付款账户当前状态不可用");
}
if (!Objects.equals(sponsor.getSignState(), (int) TransferSubject.SIGN_STATE_SUCCESS)) {
throw new BizException("付款账户暂未完成签约");
}
TransferWalletEntity transferWallet = transferWalletService.getByApplyId(sponsor.getTransApplyId(), null);
String extCardInfo = transferWallet.getExtCardInfo();
JSONObject extCardJSON = JSONObject.parseObject(extCardInfo);
Assert.notNull(sponsor, "未获取到对应的转账发起方信息");
for (SettleBatchExcel settleBatchExcel : dataList) {
TransferSubjectEntity receiver = transferSubjectService.getReceiver(sponsor.getIsvNo(),
CS.IF_CODE.ALIAQF, CS.SYS_ROLE_TYPE.MCH, getCurrentMchNo(), settleBatchExcel.getAccountNo(),
settleBatchExcel.getEntryType(), settleBatchExcel.getAccountType());
if (receiver == null) {
// 先存储转账接受账户信息
receiver = new TransferSubjectEntity();
receiver.setId("SUB" + DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6));
receiver.setAccount(settleBatchExcel.getAccountNo());
receiver.setState(TransferSubject.STATE_ENABLE);
receiver.setSubjectType(TransferSubject.SUBJECT_TYPE_RECEIVER);
receiver.setIsvNo(sponsor.getIsvNo());
receiver.setInfoType(sponsor.getInfoType());
receiver.setMchNo(sponsor.getMchNo());
receiver.setAgentNo(sponsor.getAgentNo());
receiver.setAgentName(sponsor.getAgentName());
receiver.setTopAgentNo(sponsor.getTopAgentNo());
receiver.setTransIfCode(sponsor.getTransIfCode());
receiver.setSignState(sponsor.getSignState());
receiver.setAccountName(settleBatchExcel.getAccountName());
receiver.setAccountType(settleBatchExcel.getAccountType());
receiver.setEntryType(settleBatchExcel.getEntryType());
transferSubjectService.save(receiver);
if (TransferBasicInfo.ENTRY_TYPE_BANK.equalsIgnoreCase(settleBatchExcel.getEntryType())) {
// 保存银联支行信息
JSONObject bankCardBranchInfo = new JSONObject();
if (settleBatchExcel.getInstCity() != null) {
bankCardBranchInfo.put("instName", settleBatchExcel.getInstName());
bankCardBranchInfo.put("instProvince", settleBatchExcel.getInstProvince());
bankCardBranchInfo.put("instCity", settleBatchExcel.getInstCity());
bankCardBranchInfo.put("instBranchName", settleBatchExcel.getInstBranchName());
}
receiver.setAccountMessage(bankCardBranchInfo.toJSONString());
}
}
// 保存一些订单信息
TransferOrder transferOrder = new TransferOrder();
transferOrder.setMchNo(sponsor.getMchNo());
transferOrder.setIsvNo(sponsor.getIsvNo());
transferOrder.setAgentNo(sponsor.getAgentNo());
transferOrder.setTransferSubjectIdFq(params.getTransferSubjectIdFq());
transferOrder.setTransferSubjectIdJs(receiver.getId());
transferOrder.setIfCode(receiver.getTransIfCode());
transferOrder.setWalletId(transferWallet.getId());
transferOrder.setEntryType(settleBatchExcel.getEntryType());
transferOrder.setAccountType(settleBatchExcel.getAccountType());
transferOrder.setAccountName(settleBatchExcel.getAccountName());
transferOrder.setAccountNo(settleBatchExcel.getAccountNo());
transferOrder.setOriginAccountNo(sponsor.getAccount());
transferOrder.setOriginAccountName(sponsor.getAccountName());
transferOrder.setTransAmount(new BigDecimal(settleBatchExcel.getTransAmount()));
transferOrder.setBatchId(batch);
transferOrderList.add(transferOrder);
}
//新增或更新完毕后发起结算
aliAqfV2Service.settlementData(params.getTransferSubjectIdFq(), transferOrderList);
} catch (IOException e) {
logger.info("批量导入安全发代发数据解析失败!");
// 处理异常
}
// 对 dataList 进行后续操作,如存储到数据库等
return ApiRes.ok();
}
// /**
// * 代发到户 --不直接调用
// * @return
// */
// @RequestMapping(value = "/transUniTransfer" , method = RequestMethod.GET)
// public ApiRes transUniTransfer(){
// String ersubId = getValStringRequired("ersubId");
// String eesubId = getValStringRequired("eesubId");
// String transAmount = getValStringRequired("transAmount");
// String taskId = getValStringRequired("taskId");
// String transferDesc = getValString("transferDesc");
// AlipayFundTransUniTransferResponse alipayFundTransUniTransferResponse = aliAqfV2Service.transUniTransfer(ersubId, eesubId, getDefaultIsvConfig(), transAmount,taskId,null,transferDesc);
// return ApiRes.ok(alipayFundTransUniTransferResponse);
// }
// /**
// * 代发到卡 --不直接调用
// * @return
// */
// @RequestMapping(value = "/transUniTransferCard" , method = RequestMethod.GET)
// public ApiRes transUniTransferCard(){
// String ersubId = getValStringRequired("ersubId");
// String eesubId = getValStringRequired("eesubId");
// String transAmount = getValStringRequired("transAmount");
// String taskId = getValStringRequired("taskId");
// String transferDesc = getValString("transferDesc");
// AlipayFundTransUniTransferResponse alipayFundTransUniTransferResponse = aliAqfV2Service.transUniTransferCard(ersubId, eesubId, getDefaultIsvConfig(), transAmount, taskId,null,transferDesc);
// return ApiRes.ok(alipayFundTransUniTransferResponse);
// }
/**
* 账单查询
*
* @return
*/
@RequestMapping(value = "/bizfundagentQuery", method = RequestMethod.GET)
public ApiRes bizfundagentQuery() {
String ersubId = getValStringRequired("ersubId");
String startTime = getValStringRequired("startTime");
String endTime = getValStringRequired("endTime");
String pageNo = getValStringRequired("pageNo");
String pageSize = getValStringRequired("pageSize");
JSONObject alipayDataBillBizfundagentQueryResponse = aliAqfV2Service.bizfundagentQuery(ersubId, startTime, endTime, pageNo, pageSize);
return ApiRes.ok(alipayDataBillBizfundagentQueryResponse);
}
/**
* 电子回单申请
*
* @return
*/
@RequestMapping(value = "/applicationForm", method = RequestMethod.GET)
public ApiRes applicationForm() {
String ersubId = getValStringRequired("ersubId");
String transferId = getValStringRequired("transferId");
JSONObject alipayDataBillEreceiptagentApplyResponse = aliAqfV2Service.applicationForm(ersubId, transferId);
return ApiRes.ok(alipayDataBillEreceiptagentApplyResponse);
}
/**
* 电子回单下载地址获取
*
* @return
*/
@RequestMapping(value = "/applicationFormDownload", method = RequestMethod.GET)
public ApiRes applicationFormDownload() {
String ersubId = getValStringRequired("ersubId");
String transferId = getValStringRequired("transferId");
JSONObject alipayDataBillAccountbookereceiptQueryResponse = aliAqfV2Service.applicationFormDownload(ersubId, transferId);
return ApiRes.ok(alipayDataBillAccountbookereceiptQueryResponse);
}
public String getDefaultIsvConfig() {
SysConfig serviceOne = sysConfigService.getOne(SysConfig.gw().eq(SysConfig::getGroupKey, "defaultConfig")
.eq(SysConfig::getConfigKey, "defaultIsvNo"));
if (serviceOne != null) {
return serviceOne.getConfigVal();
}
return null;
}
/**
* 根据付款人信息id获取详情
*/
public TransferSubjectEntity getSubjectOne(String subId){
TransferSubjectEntity transferSubjectEntity = transferSubjectService.getById(subId);
if (transferSubjectEntity != null){
return transferSubjectEntity;
}else {
throw new BizException("未查询到当前付款人信息!");
}
}
}

View File

@@ -0,0 +1,212 @@
package com.jeequan.jeepay.mch.ctrl.aqf;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.entity.TransferSubject;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.AgentInfo;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.SysConfig;
import com.jeequan.jeepay.db.entity.TransferSubjectEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.*;
/**
* 转账对象信息
*/
@RestController
@RequestMapping("/api/aqf")
public class AqfController extends CommonCtrl {
@Autowired
private TransferSubjectService transferSubjectService;
@Autowired
private TransferInterfaceConfigService transferInterfaceConfigService;
@Autowired
private IsvInfoService isvInfoService;
@Autowired
private AgentInfoService agentInfoService;
@Autowired
private MchInfoService mchInfoService;
/**
* 新增付款方账户信息
*
* @return
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
public ApiRes addTransferSubject() {
TransferSubjectEntity transferSubject = getObject(TransferSubjectEntity.class);
// 当前登录用户信息
transferSubject.setId("SUB" + DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6));
SysUser sysUser = getCurrentUser().getSysUser();
transferSubject.setSubjectType("FQ");
transferSubject.setTransApplyId(UUID.randomUUID().toString().replace("-", "").substring(0, 32));
//当前用户
transferSubject.setMchNo(getCurrentMchNo());
//获取服务商信息
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
transferSubject.setAgentNo(mchInfo.getAgentNo());
//获取渠道信息
AgentInfo agentInfo = agentInfoService.getById(transferSubject.getAgentNo());
transferSubject.setIsvNo(agentInfo.getIsvNo());
transferSubject.setCreatedUid(sysUser.getSysUserId());
boolean save = transferSubjectService.save(transferSubject);
if (save) {
return ApiRes.ok();
} else {
return ApiRes.customFail("新增失败!");
}
}
/**
* 查询
*/
@GetMapping("/getPageList")
public ApiRes pageTransferSubject() {
TransferSubjectEntity transferSubject = getObject(TransferSubjectEntity.class);
// 时间搜索
Date[] searchDateRange = transferSubject.buildQueryDateRange();
transferSubject.setFirstDate(searchDateRange[0]);
transferSubject.setLastDate(searchDateRange[1]);
transferSubject.setMchNo(getCurrentMchNo());
IPage<TransferSubjectEntity> pageList = transferSubjectService.getPageList(getIPage(), transferSubject);
return ApiRes.page(pageList);
}
/**
* 查询详情
*/
@GetMapping(value = "/{id}")
public ApiRes getByIdTransferSubject(@PathVariable("id") Integer id) {
TransferSubjectEntity byId = transferSubjectService.getById(id);
return ApiRes.ok(byId);
}
/**
* 修改
*/
@PutMapping(value = "/{id}")
public ApiRes updateTransferSubject(@PathVariable("id") String id) {
TransferSubjectEntity transferSubject = getObject(TransferSubjectEntity.class);
transferSubject.setId(id);
//当前用户
transferSubject.setMchNo(getCurrentMchNo());
//获取服务商信息
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
transferSubject.setAgentNo(mchInfo.getAgentNo());
//获取渠道信息
AgentInfo agentInfo = agentInfoService.getById(transferSubject.getAgentNo());
transferSubject.setIsvNo(agentInfo.getIsvNo());
boolean resut = transferSubjectService.updateById(transferSubject);
if (resut) {
return ApiRes.ok();
} else {
return ApiRes.customFail("修改失败!");
}
}
/**
* 删除
*/
@DeleteMapping("/{id}")
public ApiRes deleteTransferSubject(@PathVariable("id") Integer id) {
boolean resut = transferSubjectService.removeById(id);
if (resut) {
return ApiRes.ok();
} else {
return ApiRes.customFail("删除失败!");
}
}
/**
* 新增收款方账户信息
*/
@PostMapping("/addJs")
public ApiRes addJsTransferSubject() {
TransferSubjectEntity transferSubject = getObject(TransferSubjectEntity.class);
// 当前登录用户信息
transferSubject.setId("SUB" + DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6));
SysUser sysUser = getCurrentUser().getSysUser();
transferSubject.setSubjectType("JS");
transferSubject.setCreatedUid(sysUser.getSysUserId());
//当前用户
transferSubject.setMchNo(getCurrentMchNo());
//获取服务商信息
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
transferSubject.setAgentNo(mchInfo.getAgentNo());
//获取渠道信息
AgentInfo agentInfo = agentInfoService.getById(transferSubject.getAgentNo());
transferSubject.setIsvNo(agentInfo.getIsvNo());
boolean save = transferSubjectService.save(transferSubject);
if (save) {
return ApiRes.ok();
} else {
return ApiRes.customFail("新增失败!");
}
}
@GetMapping("/getBatchData")
public ApiRes getBatchData() {
String transferSubjects = getValStringRequired("transferSubjects");
List<TransferSubjectEntity> transferSubjectEntityList = new ArrayList<>();
String[] transferSubjectSpli = transferSubjects.split(",");
for (String transferSubjectId : transferSubjectSpli) {
TransferSubjectEntity transferSubjectEntity = transferSubjectService.getById(transferSubjectId);
if (transferSubjectEntity != null) {
transferSubjectEntityList.add(transferSubjectEntity);
}
}
return ApiRes.ok(transferSubjectEntityList);
}
@PostMapping("/state")
public ApiRes exam() {
JSONObject reqParamJSON = getReqParamJSON();
Integer state = reqParamJSON.getInteger("state");
String id = reqParamJSON.getString("id");
String remark = reqParamJSON.getString("remark");
TransferSubjectEntity transferSubjectEntity = transferSubjectService.getById(id);
Assert.notNull(transferSubjectEntity, "付款账户信息不存在");
if (state == TransferSubject.STATE_DISABLE) {
transferSubjectEntity.setState(TransferSubject.STATE_DISABLE);
transferSubjectEntity.setRemark(remark);
transferSubjectService.updateById(transferSubjectEntity);
} else if (state == TransferSubject.STATE_ENABLE) {
transferSubjectEntity.setState(TransferSubject.STATE_ENABLE);
transferSubjectService.updateById(transferSubjectEntity);
} else if (state == TransferSubject.STATE_ENABLE_REVIEW) {
transferSubjectEntity.setState(TransferSubject.STATE_ENABLE_REVIEW);
transferSubjectService.updateById(transferSubjectEntity);
}
return ApiRes.ok();
}
/**
* 统计收款账户总成交金额和总成交笔数
*/
@GetMapping("/getSubStatistics")
public Map<String, Object> getSubStatistics(){
TransferSubjectEntity subject = getObject(TransferSubjectEntity.class);
subject.setMchNo(getCurrentMchNo());
return transferSubjectService.getSubStatistics(subject);
}
}

View File

@@ -0,0 +1,119 @@
package com.jeequan.jeepay.mch.ctrl.aqf;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.AgentInfo;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.TaskList;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.TaskListService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* 任务
*/
@RestController
@RequestMapping("/api/taskList")
public class TaskListController extends CommonCtrl {
@Autowired
private TaskListService taskListService;
@Autowired
private MchInfoService mchInfoService;
/**
* 新增任务
* @return
*/
@RequestMapping(value = "/add" ,method = RequestMethod.POST)
public ApiRes addTaskList(){
TaskList taskList = getObject(TaskList.class);
//当前用户
taskList.setMchNo(getCurrentMchNo());
//获取服务商信息
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
taskList.setAgentNo(mchInfo.getAgentNo());
// 当前登录用户信息
SysUser sysUser = getCurrentUser().getSysUser();
taskList.setId(DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6));
taskList.setCreatedBy(String.valueOf(sysUser.getSysUserId()));
boolean save = taskListService.save(taskList);
if (save){
return ApiRes.ok();
}else {
return ApiRes.customFail("新增失败!");
}
}
/**
* 查询
* @return
*/
@RequestMapping(value = "/getPageList" ,method = RequestMethod.GET)
public ApiRes getlistTaskList(){
TaskList taskList = getObject(TaskList.class);
// 时间搜索
Date[] searchDateRange = taskList.buildQueryDateRange();
taskList.setFirstDate(searchDateRange[0]);
taskList.setLastDate(searchDateRange[1]);
taskList.setMchNo(getCurrentMchNo());
IPage<TaskList> pageList = taskListService.getPageList(getIPage(), taskList);
//Page<TaskList> page = taskListService.page(getIPage(), TaskList.gw(taskList).orderByDesc(TaskList::getCreatedAt));
return ApiRes.page(pageList);
}
/**
* 查询详情
* @return
*/
@RequestMapping(value = "/{id}" ,method = RequestMethod.GET)
public ApiRes getByIdTaskList(@PathVariable("id") Integer id){
TaskList byId = taskListService.getById(id);
return ApiRes.ok(byId);
}
/**
* 修改
* @return
*/
@RequestMapping(value = "/{id}" ,method = RequestMethod.PUT)
public ApiRes updateTaskList(@PathVariable("id") String id){
TaskList taskList = getObject(TaskList.class);
//当前用户
taskList.setMchNo(getCurrentMchNo());
//获取服务商信息
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
taskList.setAgentNo(mchInfo.getAgentNo());
taskList.setId(id);
boolean resut = taskListService.updateById(taskList);
if (resut){
return ApiRes.ok();
}else {
return ApiRes.customFail("修改失败!");
}
}
/**
* 删除
* @return
*/
@RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)
public ApiRes deleteTaskList(@PathVariable("id") Integer id){
boolean resut = taskListService.removeById(id);
if (resut){
return ApiRes.ok();
}else {
return ApiRes.customFail("删除失败!");
}
}
}

View File

@@ -0,0 +1,119 @@
package com.jeequan.jeepay.mch.ctrl.aqf;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.converter.TransferConverter;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.interfaces.paychannel.ITransferService;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.service.ValidatorService;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.core.validate.Add;
import com.jeequan.jeepay.db.entity.SysConfig;
import com.jeequan.jeepay.db.entity.TransferInterfaceConfigEntity;
import com.jeequan.jeepay.db.entity.TransferSubjectEntity;
import com.jeequan.jeepay.db.entity.TransferWalletEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.TransferInterfaceConfigService;
import com.jeequan.jeepay.service.impl.TransferSubjectService;
import com.jeequan.jeepay.service.impl.TransferWalletService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.UUID;
/**
* 代付对象
*
* @author deng
* @since 2024/5/9
*/
@Slf4j
@RestController
@RequestMapping("/api/transferSubject")
public class TransferSubjectController extends CommonCtrl {
@Autowired
private TransferInterfaceConfigService transferInterfaceConfigService;
@Autowired
private ValidatorService validate;
@Autowired
private TransferSubjectService transferSubjectService;
@Autowired
private TransferWalletService transferWalletService;
@Autowired
private TransferConverter transferConverter;
/**
* 新增转账发起方
*/
@PostMapping("/sponsor")
public ApiRes sponsor() {
TransferSubjectEntity transferSubject = getObject(TransferSubjectEntity.class);
validate.validate(transferSubject, Add.class);
// 当前登录用户信息
transferSubject.setId("SUB" + DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6));
SysUser sysUser = getCurrentUser().getSysUser();
transferSubject.setSubjectType("FQ");
transferSubject.setTransApplyId(UUID.randomUUID().toString().replace("-", "").substring(0, 32));
//如果不传递取默认值
if (StringUtils.isEmpty(transferSubject.getIsvNo())) {
SysConfig serviceOne = sysConfigService.getOne(SysConfig.gw().eq(SysConfig::getGroupKey, "defaultConfig")
.eq(SysConfig::getConfigKey, "defaultIsvNo"));
if (serviceOne != null) {
transferSubject.setIsvNo(serviceOne.getConfigVal());
}
}
if (StringUtils.isNotEmpty(transferSubject.getIsvNo())) {
//取对应参数信息
//获取下发金额
TransferInterfaceConfigEntity configEntity = transferInterfaceConfigService.getTransferConfig(transferSubject.getTransIfCode(), transferSubject.getIsvNo(), CS.SYS_ROLE_TYPE.ISV);
if (configEntity != null && StringUtils.isNotEmpty(configEntity.getTransIfParams())) {
String zfbDayMax = JSONObject.parseObject(configEntity.getTransIfParams()).getString("zfbDayMax");
String bankCardDayMax = JSONObject.parseObject(configEntity.getTransIfParams()).getString("bankCardDayMax");
transferSubject.setZfbDayMax(Long.valueOf(zfbDayMax));
transferSubject.setBankCardDayMax(Long.valueOf(bankCardDayMax));
}
}
transferSubject.setCreatedUid(sysUser.getSysUserId());
boolean save = transferSubjectService.save(transferSubject);
if (save) {
return ApiRes.ok();
} else {
return ApiRes.customFail("新增失败!");
}
}
@PostMapping("/refreshBalance")
public ApiRes refreshBalance() {
String transferSubjectId = getValStringRequired("transferSubjectId");
TransferWalletEntity transferWallet = transferWalletService.getByApplyId(transferSubjectId, null);
// 刷新记账本余额
ITransferService transferService = SpringBeansUtil.getBean(transferWallet.getTransIfCode() + "TransferService", ITransferService.class);
MutablePair<String, Long> balanceResult = transferService.queryBalanceAmount(transferConverter.toModel(transferWallet));
// 查询更新余额
transferWallet.setAccountBookBalance(balanceResult.right);
transferWalletService.updateById(transferWallet);
return ApiRes.ok(transferWallet);
}
}

View File

@@ -0,0 +1,67 @@
package com.jeequan.jeepay.mch.ctrl.article;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.SysArticle;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 文章管理类
*
* @author yurong
*
* @date 2022-07-08 14:15
*/
@RestController
@RequestMapping("api/sysArticles")
public class SysArticleController extends CommonCtrl {
@Autowired private SysArticleService sysArticleService;
/**
* @author: yurong
* @date: 2022-07-08 14:15
* @describe: 文章列表 articleType 1公告
*/
@PreAuthorize("hasAuthority('ENT_ARTICLE_NOTICEINFO')")
@RequestMapping(value = "",method = RequestMethod.GET)
public ApiRes articleList(){
SysArticle sysArticle = getObject(SysArticle.class);
if (sysArticle.getArticleType() == null){
return ApiRes.customFail("文章类型不明确");
}
LambdaQueryWrapper<SysArticle> wrapper = SysArticle.gw();
wrapper.select(SysArticle::getArticleId,SysArticle::getTitle,SysArticle::getSubtitle,SysArticle::getPublisher,SysArticle::getCreatedAt)
.eq(SysArticle::getArticleType,sysArticle.getArticleType())
.apply("FIND_IN_SET('"+ CS.SYS_ROLE_TYPE.MCH+"',"+SysArticle.ARTICLE_RANGE+")")
.orderByDesc(SysArticle::getPublishTime);
IPage<SysArticle> iPage = sysArticleService.page(getIPage(), wrapper);
return ApiRes.page(iPage);
}
/**
* @author: yurong
* @date: 2022-07-08 14:15
* @describe: 文章详情 articleType 1公告
*/
@PreAuthorize("hasAuthority('ENT_ARTICLE_NOTICEINFO')")
@RequestMapping(value = "/{articleId}",method = RequestMethod.GET)
public ApiRes detail(@PathVariable("articleId") Long articleId){
SysArticle sysArticle = sysArticleService.getById(articleId);
if (sysArticle == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(sysArticle);
}
}

View File

@@ -0,0 +1,15 @@
package com.jeequan.jeepay.mch.ctrl.division;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 商户分账模板配置控制器
*/
@RestController
@RequestMapping("/api/divisionSubject")
public class DivisionSubjectController extends CommonCtrl {
}

View File

@@ -0,0 +1,89 @@
package com.jeequan.jeepay.mch.ctrl.division;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.DivisionTask;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
/**
* 分账任务控制器
*/
@RestController
@RequestMapping("/api/divisionTask")
public class DivisionTaskController extends CommonCtrl {
@Autowired private DivisionTaskService divisionTaskService;
/** list */
@GetMapping
public ApiRes list() {
DivisionTask queryObject = getObject(DivisionTask.class);
queryObject.setMchNo(getCurrentMchNo());
IPage<DivisionTask> pages = divisionTaskService.pageList(getIPage(true), queryObject);
return ApiRes.page(pages);
}
/** add */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_TASK_ADD' )")
@RequestMapping(value="", method = RequestMethod.POST)
@MethodLog(remark = "新增分账任务")
public ApiRes add() {
DivisionTask template = getObject(DivisionTask.class);
divisionTaskService.addSave(template,getCurrentMchNo());
return ApiRes.ok();
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_TASK_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
@MethodLog(remark = "更新分账任务")
public ApiRes update(@PathVariable("recordId") Long recordId) {
DivisionTask update = getObject(DivisionTask.class);
DivisionTask ext = divisionTaskService.getById(recordId);
Assert.notNull(ext,"非法参数");
divisionTaskService.updateById(update);
return ApiRes.ok();
}
/** delete */
@PreAuthorize("hasAuthority('ENT_DIVISION_TASK_DELETE')")
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
@MethodLog(remark = "删除分账任务")
public ApiRes del(@PathVariable("recordId") Long recordId) {
divisionTaskService.removeById(recordId);
return ApiRes.ok();
}
/**
* 获取分账配置
* @param taskId
* @return
*/
@PreAuthorize("hasAuthority('ENT_DIVISION_TASK_DETAIL')")
@RequestMapping(value="/config/{taskId}", method = RequestMethod.GET)
@MethodLog(remark = "获取分账任务")
public ApiRes configDetail(@PathVariable("taskId") String taskId) {
DivisionTask result = divisionTaskService.getDivisionSubject(taskId);
return ApiRes.ok(result);
}
/**
* 新增配置
* @return
*/
@PreAuthorize("hasAuthority('ENT_DIVISION_SUBJECT_ADD')")
@RequestMapping(value="/saveSubject", method = RequestMethod.POST)
@MethodLog(remark = "新增分账任务配置")
public ApiRes saveSubject() {
DivisionTask template = getObject(DivisionTask.class);
divisionTaskService.saveConfig(template);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,229 @@
package com.jeequan.jeepay.mch.ctrl.division;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchDivisionReceiver;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.model.DivisionReceiverBindReqModel;
import com.jeequan.jeepay.model.DivisionReceiverChannelBalanceCashoutReqModel;
import com.jeequan.jeepay.model.DivisionReceiverChannelBalanceQueryReqModel;
import com.jeequan.jeepay.request.DivisionReceiverBindRequest;
import com.jeequan.jeepay.request.DivisionReceiverChannelBalanceCashoutRequest;
import com.jeequan.jeepay.request.DivisionReceiverChannelBalanceQueryRequest;
import com.jeequan.jeepay.response.DivisionReceiverBindResponse;
import com.jeequan.jeepay.response.DivisionReceiverChannelBalanceCashoutResponse;
import com.jeequan.jeepay.response.DivisionReceiverChannelBalanceQueryResponse;
import com.jeequan.jeepay.service.impl.MchAppService;
import com.jeequan.jeepay.service.impl.MchDivisionReceiverService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
/**
* 商户分账接收者账号关系维护
*
* @author terrfly
*
* @date 2021-08-23 11:50
*/
@RestController
@RequestMapping("api/divisionReceivers")
public class MchDivisionReceiverController extends CommonCtrl {
@Autowired private MchDivisionReceiverService mchDivisionReceiverService;
@Autowired private MchAppService mchAppService;
@Autowired private SysConfigService sysConfigService;
/** list */
@PreAuthorize("hasAnyAuthority( 'ENT_DIVISION_RECEIVER_LIST' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
MchDivisionReceiver queryObject = getObject(MchDivisionReceiver.class);
queryObject.setMchNo(getCurrentMchNo());
IPage<MchDivisionReceiver> pages = mchDivisionReceiverService.listByPage(getIPage(true), queryObject);
pages.getRecords().forEach(item->{
//返回应用名称
if (StringUtils.isNotEmpty(item.getAppId())){
MchAppEntity mchAppEntity = mchAppService.getById(item.getAppId());
if (mchAppEntity != null){
item.setAppName(mchAppEntity.getAppName());
}
}
});
return ApiRes.page(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_VIEW' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") Long recordId) {
MchDivisionReceiver record = mchDivisionReceiverService
.getOne(MchDivisionReceiver.gw()
.eq(MchDivisionReceiver::getMchNo, getCurrentMchNo())
.eq(MchDivisionReceiver::getReceiverId, recordId));
if (record == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(record);
}
/** add */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_ADD' )")
@RequestMapping(value="", method = RequestMethod.POST)
@MethodLog(remark = "新增分账接收账号")
public ApiRes add() {
DivisionReceiverBindReqModel model = getObject(DivisionReceiverBindReqModel.class);
MchAppEntity mchAppEntity = mchAppService.getById(model.getAppId());
if(mchAppEntity == null || mchAppEntity.getState() != CS.PUB_USABLE || !mchAppEntity.getMchNo().equals(getCurrentMchNo()) ){
throw new BizException("商户应用不存在或不可用");
}
DivisionReceiverBindRequest request = new DivisionReceiverBindRequest();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
request.setBizModel(model);
model.setMchNo(this.getCurrentMchNo());
model.setAppId(mchAppEntity.getAppId());
model.setDivisionProfit(new BigDecimal(model.getDivisionProfit()).divide(new BigDecimal(100)).toPlainString());
JeepayClient jeepayClient = new JeepayClient(sysConfigService.getDBApplicationConfig().getPaySiteUrl(), mchAppEntity.getAppSecret());
try {
DivisionReceiverBindResponse response = jeepayClient.execute(request);
if(response.getCode() != 0){
throw new BizException(response.getMsg());
}
return ApiRes.ok(response.get());
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
@MethodLog(remark = "更新分账接收账号")
public ApiRes update(@PathVariable("recordId") Long recordId) {
// 请求参数
MchDivisionReceiver reqReceiver = getObject(MchDivisionReceiver.class);
reqReceiver.setReceiverId(recordId);
reqReceiver.setMchNo(getCurrentMchNo());
mchDivisionReceiverService.updateReceiver(reqReceiver);
return ApiRes.ok();
}
/** delete */
@PreAuthorize("hasAuthority('ENT_DIVISION_RECEIVER_DELETE')")
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
@MethodLog(remark = "删除分账接收账号")
public ApiRes del(@PathVariable("recordId") Long recordId) {
MchDivisionReceiver record = mchDivisionReceiverService.getOne(MchDivisionReceiver.gw()
.eq(MchDivisionReceiver::getReceiverGroupId, recordId).eq(MchDivisionReceiver::getMchNo, getCurrentMchNo()));
if (record == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
mchDivisionReceiverService.removeById(recordId);
return ApiRes.ok();
}
/**
* 查询账户余额
*/
@PreAuthorize("hasAuthority('ENT_DIVISION_RECEIVER_EDIT')")
@RequestMapping(value = "/channelBalances/{recordId}", method = RequestMethod.GET)
public ApiRes channelBalances(@PathVariable("recordId") Long recordId) {
MchDivisionReceiver record = mchDivisionReceiverService.getById(recordId);
if (record == null || !record.getMchNo().equals(getCurrentMchNo())) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
MchAppEntity mchAppEntity = mchAppService.getById(record.getAppId());
if (mchAppEntity == null || mchAppEntity.getState() != CS.PUB_USABLE || !mchAppEntity.getMchNo().equals(record.getMchNo())) {
throw new BizException("商户应用不存在或不可用");
}
DivisionReceiverChannelBalanceQueryRequest request = new DivisionReceiverChannelBalanceQueryRequest();
DivisionReceiverChannelBalanceQueryReqModel model = new DivisionReceiverChannelBalanceQueryReqModel();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
model.setReceiverId(recordId);
model.setMchNo(record.getMchNo());
model.setAppId(mchAppEntity.getAppId());
request.setBizModel(model);
JeepayClient jeepayClient = new JeepayClient(sysConfigService.getDBApplicationConfig().getPaySiteUrl(), mchAppEntity.getAppSecret());
try {
DivisionReceiverChannelBalanceQueryResponse response = jeepayClient.execute(request);
if (response.getCode() != 0) {
throw new BizException(response.getMsg());
}
return ApiRes.ok(response.get());
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
/**
* 发起提现
*/
@PreAuthorize("hasAuthority('ENT_DIVISION_RECEIVER_EDIT')")
@RequestMapping(value = "/channelCashout/{recordId}", method = RequestMethod.POST)
@MethodLog(remark = "分账账户发起提现")
public ApiRes channelCashout(@PathVariable("recordId") Long recordId) {
MchDivisionReceiver record = mchDivisionReceiverService.getById(recordId);
if (record == null || !record.getMchNo().equals(getCurrentMchNo())) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
MchAppEntity mchAppEntity = mchAppService.getById(record.getAppId());
if (mchAppEntity == null || mchAppEntity.getState() != CS.PUB_USABLE || !mchAppEntity.getMchNo().equals(record.getMchNo())) {
throw new BizException("商户应用不存在或不可用");
}
DivisionReceiverChannelBalanceCashoutRequest request = new DivisionReceiverChannelBalanceCashoutRequest();
DivisionReceiverChannelBalanceCashoutReqModel model = new DivisionReceiverChannelBalanceCashoutReqModel();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
model.setReceiverId(recordId);
model.setCashoutAmount(getRequiredAmountL("cashoutAmount"));
model.setMchNo(record.getMchNo());
model.setAppId(mchAppEntity.getAppId());
request.setBizModel(model);
JeepayClient jeepayClient = new JeepayClient(sysConfigService.getDBApplicationConfig().getPaySiteUrl(), mchAppEntity.getAppSecret());
try {
DivisionReceiverChannelBalanceCashoutResponse response = jeepayClient.execute(request);
if (response.getCode() != 0) {
throw new BizException(response.getMsg());
}
return ApiRes.ok(response.get());
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
}

View File

@@ -0,0 +1,96 @@
package com.jeequan.jeepay.mch.ctrl.division;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchDivisionReceiverGroup;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchDivisionReceiverGroupService;
import com.jeequan.jeepay.service.impl.MchDivisionReceiverService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 商户分账接收者账号组
*
* @author terrfly
*
* @date 2021-08-23 11:50
*/
@RestController
@RequestMapping("api/divisionReceiverGroups")
public class MchDivisionReceiverGroupController extends CommonCtrl {
@Autowired private MchDivisionReceiverGroupService mchDivisionReceiverGroupService;
@Autowired private MchDivisionReceiverService mchDivisionReceiverService;
/** list */
@PreAuthorize("hasAnyAuthority( 'ENT_DIVISION_RECEIVER_GROUP_LIST' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
MchDivisionReceiverGroup queryObject = getObject(MchDivisionReceiverGroup.class);
queryObject.setMchNo(getCurrentMchNo());
IPage<MchDivisionReceiverGroup> pages = mchDivisionReceiverGroupService.listByPage(getIPage(true), queryObject);
return ApiRes.page(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_GROUP_VIEW' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") Long recordId) {
MchDivisionReceiverGroup record = mchDivisionReceiverGroupService
.getOne(MchDivisionReceiverGroup.gw()
.eq(MchDivisionReceiverGroup::getMchNo, getCurrentMchNo())
.eq(MchDivisionReceiverGroup::getReceiverGroupId, recordId));
if (record == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(record);
}
/** add */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_GROUP_ADD' )")
@RequestMapping(value="", method = RequestMethod.POST)
@MethodLog(remark = "新增分账账号组")
public ApiRes add() {
MchDivisionReceiverGroup record = getObject(MchDivisionReceiverGroup.class);
record.setMchNo(getCurrentMchNo());
record.setCreatedUid(getCurrentUser().getSysUser().getSysUserId());
record.setCreatedBy(getCurrentUser().getSysUser().getRealname());
mchDivisionReceiverGroupService.add(record);
return ApiRes.ok();
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_GROUP_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
@MethodLog(remark = "更新分账账号组")
public ApiRes update(@PathVariable("recordId") Long recordId) {
MchDivisionReceiverGroup reqRecord = getObject(MchDivisionReceiverGroup.class);
reqRecord.setMchNo(getCurrentMchNo());
reqRecord.setReceiverGroupId(recordId);
mchDivisionReceiverGroupService.updateGroup(reqRecord);
return ApiRes.ok();
}
/** delete */
@PreAuthorize("hasAuthority('ENT_DIVISION_RECEIVER_GROUP_DELETE')")
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
@MethodLog(remark = "删除分账账号组")
public ApiRes del(@PathVariable("recordId") Long recordId) {
mchDivisionReceiverGroupService.removeGroup(recordId, getCurrentMchNo());
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,90 @@
package com.jeequan.jeepay.mch.ctrl.division;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.components.mq.model.PayOrderDivisionMQ;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PayOrderDivisionRecord;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.PayOrderDivisionRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
/**
* 分账记录
*
* @author terrfly
*
* @date 2021-08-25 11:50
*/
@RestController
@RequestMapping("api/division/records")
public class PayOrderDivisionRecordController extends CommonCtrl {
@Autowired private PayOrderDivisionRecordService payOrderDivisionRecordService;
@Autowired private IMQSender mqSender;
/** list */
@PreAuthorize("hasAnyAuthority( 'ENT_DIVISION_RECORD_LIST' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
PayOrderDivisionRecord queryObject = getObject(PayOrderDivisionRecord.class);
queryObject.setMchNo(getCurrentMchNo());
IPage<PayOrderDivisionRecord> pages = payOrderDivisionRecordService.listByPage(getIPage(true), queryObject);
return ApiRes.page(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECORD_VIEW' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") Long recordId) {
PayOrderDivisionRecord record = payOrderDivisionRecordService
.getOne(PayOrderDivisionRecord.gw()
.eq(PayOrderDivisionRecord::getMchNo, getCurrentMchNo())
.eq(PayOrderDivisionRecord::getRecordId, recordId));
if (record == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(record);
}
/** 分账接口重试 */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECORD_RESEND' )")
@RequestMapping(value="/resend", method = RequestMethod.POST)
public ApiRes resend() {
List<String> recordIds = Arrays.asList(getValStringRequired("recordIds").split(","));
// 筛选分账失败的账单
List<PayOrderDivisionRecord> recordList = payOrderDivisionRecordService.list(
PayOrderDivisionRecord.gw()
.in(PayOrderDivisionRecord::getRecordId, recordIds)
.eq(PayOrderDivisionRecord::getState, PayOrderDivisionRecord.STATE_FAIL)
);
if (CollUtil.isEmpty(recordList)) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
// 是否重新计算订单金额
boolean isResendAndRecalAmount = (CS.YES == getValByteDefault("isResendAndRecalAmount", CS.NO));
// 重发到MQ
for (PayOrderDivisionRecord record: recordList) {
mqSender.send(PayOrderDivisionMQ.build(record.getPayOrderId(), null, null, true, isResendAndRecalAmount));
}
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,55 @@
package com.jeequan.jeepay.mch.ctrl.division;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PayOrderDivisionRefundRecord;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.PayOrderDivisionRefundRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 分账回退记录
*
* @author terrfly
*
* @date 2022-06-10 17:50
*/
@RestController
@RequestMapping("api/division/refunds/records")
public class PayOrderDivisionRefundRecordController extends CommonCtrl {
@Autowired private PayOrderDivisionRefundRecordService payOrderDivisionRefundRecordService;
/** list */
@PreAuthorize("hasAnyAuthority( 'ENT_DIVISION_REFUND_RECORD_LIST' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
PayOrderDivisionRefundRecord queryObject = getObject(PayOrderDivisionRefundRecord.class);
queryObject.setMchNo(getCurrentMchNo());
IPage<PayOrderDivisionRefundRecord> pages = payOrderDivisionRefundRecordService.listByPage(getIPage(), queryObject);
return ApiRes.page(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_DIVISION_REFUND_RECORD_VIEW' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") String recordId) {
PayOrderDivisionRefundRecord record = payOrderDivisionRefundRecordService
.getOne(PayOrderDivisionRefundRecord.gw()
.eq(PayOrderDivisionRefundRecord::getMchNo, getCurrentMchNo())
.eq(PayOrderDivisionRefundRecord::getDivisionRefundId, recordId));
if (record == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(record);
}
}

View File

@@ -0,0 +1,71 @@
package com.jeequan.jeepay.mch.ctrl.isv;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.IsvInfo;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.IsvInfoService;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/isvInfo")
public class IsvInfoController extends CommonCtrl {
@Autowired
private IsvInfoService isvInfoService;
@Autowired
private MchInfoService mchInfoService;
@Autowired
private PayInterfaceConfigService payInterfaceConfigService;
@GetMapping("/isvInfoList")
public ApiRes getIsvInfoList() {
String ifCode = getValStringRequired("ifCode");
String currentMchNo = getCurrentMchNo();
String range = getValStringRequired("range");
Integer state = getValInteger("state");
String isvName = getValString("isvName");
List<IsvInfo> isvAndPayConfig = isvInfoService.getIsvAndPayConfig(CS.SYS_ROLE_TYPE.MCH, isvName,currentMchNo, ifCode, range, state);
Page<IsvInfo> page = new Page<>();
page.setRecords(isvAndPayConfig);
page.setSize(-1);
page.setPages(1);
// 如果是查看商户数据,则查询他的默认渠道
List<Map<String, String>> defIsv = mchInfoService.getDefIsv(currentMchNo, ifCode);
if (!ObjectUtils.isEmpty(defIsv)) {
Map<String, String> defIsvItem = defIsv.get(0);
String defIsvNo = defIsvItem.get(MchConfig.getDefIsvKey(ifCode));
page.getRecords().forEach(r -> r.addExt("defFlag", r.getIsvNo().equals(defIsvNo) ? CS.YES : CS.NO));
} else {
page.getRecords().forEach(r -> r.addExt("defFlag", CS.NO));
}
return ApiRes.ok(page);
}
@GetMapping("/getSettType")
public ApiRes getSettType(){
String ifCode = getValStringRequired("ifCode");
String infoId = getValStringRequired("infoId");
JSONArray settType = isvInfoService.getSettType(ifCode, infoId);
return ApiRes.ok(settType);
}
}

View File

@@ -0,0 +1,114 @@
package com.jeequan.jeepay.mch.ctrl.member;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MemberAccountHistory;
import com.jeequan.jeepay.db.entity.MemberInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MemberAccountHistoryService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 会员账户流水
*
* @author xiaoyu
*
* @date 2023/4/13 17:22
*/
@RestController
@RequestMapping("/api/member/accountHistory")
public class MemberAccountHistoryController extends CommonCtrl {
@Autowired private MemberAccountHistoryService accountHistoryService;
/**
* @author: xiaoyu
* @date: 2023/4/13 17:24
* @describe: 会员账户流水列表
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_ACCOUNT_HISTORY_LIST')")
@GetMapping
public ApiRes list() {
MemberAccountHistory accountHistory = getObject(MemberAccountHistory.class);
LambdaQueryWrapper<MemberAccountHistory> wrapper = MemberAccountHistory.gw();
wrapper.eq(MemberAccountHistory::getMchNo, getCurrentMchNo());
// 查询条件
accountHistoryService.selectParams(accountHistory, wrapper);
// 额外条件参数
JSONObject paramJSON = getReqParamJSON();
// 二合一 会员名称/订单号/手机号
if (paramJSON != null && StringUtils.isNotEmpty(paramJSON.getString("unionQueryParam"))) {
wrapper.and(wr -> {
wr.like(MemberAccountHistory::getMbrTel, paramJSON.getString("unionQueryParam"))
.or().like(MemberAccountHistory::getMbrName, paramJSON.getString("unionQueryParam"))
.or().like(MemberAccountHistory::getRelaBizOrderId, paramJSON.getString("unionQueryParam"));
});
}
wrapper.orderByDesc(MemberAccountHistory::getCreatedAt);
IPage<MemberAccountHistory> page = accountHistoryService.page(getIPage(), wrapper);
// 手机号脱敏
page.getRecords().stream().forEach(i -> i.setMbrTel(DesensitizedUtil.mobilePhone(i.getMbrTel())));
// 会员头像
setAvatarUrl(page.getRecords());
return ApiRes.page(page);
}
/**
* @author: xiaoyu
* @date: 2023/4/13 17:49
* @describe: 会员账户流水信息
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_ACCOUNT_HISTORY_VIEW')")
@GetMapping("/{hid}")
public ApiRes detail(@PathVariable("hid") String hid) {
MemberAccountHistory history = accountHistoryService.getById(hid);
if (history == null || !history.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
// 查询会员信息
MemberInfo memberInfo = memberInfoService.getById(history.getMbrId());
// 会员头像
history.addExt("avatarUrl", memberInfo.getAvatarUrl());
return ApiRes.ok(history);
}
/**
* @author: xiaoyu
* @date: 2023/4/18 9:32
* @describe: 账户流水统计
*/
@RequestMapping(value="/count", method = RequestMethod.GET)
public ApiRes count() {
MemberAccountHistory accountHistory = getObject(MemberAccountHistory.class);
LambdaQueryWrapper<MemberAccountHistory> wrapper = MemberAccountHistory.gw();
wrapper.eq(MemberAccountHistory::getMchNo, getCurrentMchNo());
// 查询参数
accountHistoryService.selectParams(accountHistory, wrapper);
Map count = accountHistoryService.count(wrapper);
return ApiRes.ok(count);
}
}

View File

@@ -0,0 +1,263 @@
package com.jeequan.jeepay.mch.ctrl.member;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.export.MemberInfoExportExcel;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.ExcelUtil;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.MemberAccountHistory;
import com.jeequan.jeepay.db.entity.MemberInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.MemberAccountHistoryService;
import com.jeequan.jeepay.service.impl.MemberInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 会员管理
*
* @author xiaoyu
*
* @date 2023/4/13 17:22
*/
@RestController
@RequestMapping("/api/member")
public class MemberController extends CommonCtrl {
@Autowired private MemberInfoService memberInfoService;
@Autowired private MchInfoService mchInfoService;
@Autowired private MemberAccountHistoryService accountHistoryService;
/**
* @author: xiaoyu
* @date: 2023/4/13 17:24
* @describe: 会员列表
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_LIST')")
@GetMapping
public ApiRes list() {
MemberInfo memberInfo = getObject(MemberInfo.class);
LambdaQueryWrapper<MemberInfo> wrapper = MemberInfo.gw();
wrapper.eq(MemberInfo::getMchNo, getCurrentMchNo());
// 额外条件参数
JSONObject paramJSON = getReqParamJSON();
// 会员查询条件
memberInfoService.memberParams(memberInfo, wrapper);
wrapper.orderByDesc(MemberInfo::getCreatedAt);
// 二合一 会员名称/手机号
if (paramJSON != null && StringUtils.isNotEmpty(paramJSON.getString("unionQueryParam"))) {
wrapper.and(wr -> {
wr.like(MemberInfo::getMbrTel, paramJSON.getString("unionQueryParam"))
.or().like(MemberInfo::getMbrName, paramJSON.getString("unionQueryParam"));
});
}
IPage<MemberInfo> page = memberInfoService.page(getIPage(), wrapper);
// 手机号脱敏
page.getRecords().stream().forEach(i -> i.setMbrTel(DesensitizedUtil.mobilePhone(i.getMbrTel())));
return ApiRes.page(page);
}
/**
* @author: xiaoyu
* @date: 2023/4/13 17:36
* @describe: 新增会员
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_ADD')")
@MethodLog(remark = "新增会员")
@PostMapping
public ApiRes add() {
MemberInfo memberInfo = getObject(MemberInfo.class);
memberInfo.setMbrId("B" + DateUtil.currentSeconds());
memberInfo.setMchNo(getCurrentMchNo());
memberInfo.setBalance(0L);
memberInfo.setSafeKey(JeepayKit.genAccountSafeKey(memberInfo.getMbrId(), 0L));
memberInfo.setAvatarUrl(getMemberAvatarDefault());
if (StringUtils.isEmpty(memberInfo.getMbrTel())) {
throw new BizException("会员手机号不可为空");
}
// 查询当前会员是否已存在
MemberInfo dbMemberInfo = memberInfoService.selectOne(getCurrentMchNo(), null, memberInfo.getMbrTel(), null, null);
if (dbMemberInfo != null) {
throw new BizException(memberInfo.getMbrTel() + "当前会员已存在");
}
boolean result = memberInfoService.save(memberInfo);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
}
return ApiRes.ok();
}
/**
* @author: xiaoyu
* @date: 2023/4/13 17:49
* @describe: 会员信息
*/
@PreAuthorize("hasAnyAuthority('ENT_MEMBER_VIEW', 'ENT_MEMBER_EDIT')")
@GetMapping("/{mbrId}")
public ApiRes detail(@PathVariable("mbrId") String mbrId) {
MemberInfo memberInfo = memberInfoService.selectOne(getCurrentMchNo(), mbrId, null, null, null);
if (memberInfo == null || !memberInfo.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(memberInfo);
}
/**
* @author: xiaoyu
* @date: 2023/4/13 17:51
* @describe: 更新会员信息
*/
@PreAuthorize("hasAuthority('ENT_MCH_APP_EDIT')")
@MethodLog(remark = "更新会员信息")
@PutMapping("/{mbrId}")
public ApiRes update(@PathVariable("mbrId") String mbrId) {
MemberInfo memberInfo = getObject(MemberInfo.class);
memberInfo.setMbrId(mbrId);
memberInfo.setMchNo(null);
memberInfo.setBalance(null);
memberInfo.setSafeKey(null);
memberInfo.setMbrTel(null);
// 校验当前会员信息
MemberInfo dbMemberInfo = memberInfoService.getById(mbrId);
if (dbMemberInfo == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if (!dbMemberInfo.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
// 更新信息
boolean result = memberInfoService.updateById(memberInfo);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
/**
* @author: xiaoyu
* @date: 2023/4/14 14:30
* @describe: 会员调账
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_MANUAL')")
@MethodLog(remark = "会员调账")
@PostMapping("/manual/{mbrId}")
public ApiRes manual(@PathVariable("mbrId") String mbrId) {
// 变动金额
Long changeAmount = getRequiredAmountL("changeAmount");
// 登录密码
String currentPassword = Base64.decodeStr(getValStringRequired("currentPassword"));
// 校验当前会员信息
MemberInfo dbMemberInfo = memberInfoService.getById(mbrId);
if (dbMemberInfo == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
// 权限校验
if (!dbMemberInfo.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
// 验证商户支付密码
MchInfo mchInfo = mchInfoService.getById(dbMemberInfo.getMchNo());
if(!new BCryptPasswordEncoder().matches(currentPassword, mchInfo.getSipw())){
throw new BizException("支付密码验证失败!");
}
// 会员调账
accountHistoryService.updateMbrAccountAndInsertHistory(dbMemberInfo.getMchNo(), null, null, dbMemberInfo.getMbrId(), changeAmount,
MemberAccountHistory.BIZ_MANUAL, null, null);
return ApiRes.ok();
}
/**
* @author: xiaoyu
* @date: 2023/4/17 17:25
* @describe: 会员列表数据导出
*/
@RequestMapping(value="/exportExcel", method = RequestMethod.GET)
public void exportExcel() {
try {
MemberInfo memberInfo = getObject(MemberInfo.class);
LambdaQueryWrapper<MemberInfo> wrapper = MemberInfo.gw();
wrapper.eq(MemberInfo::getMchNo, getCurrentMchNo());
// 会员查询条件
memberInfoService.memberParams(memberInfo, wrapper);
wrapper.orderByDesc(MemberInfo::getCreatedAt);
IPage<MemberInfo> memberList = memberInfoService.page(getIPage(true), wrapper);
List<JSONObject> newList = new LinkedList<>();
for (MemberInfo info: memberList.getRecords()) {
JSONObject object = (JSONObject) JSONObject.toJSON(info);
object.put("balance", AmountUtil.convertCent2Dollar(info.getBalance()));
newList.add(object);
}
List<MemberInfoExportExcel> linkedList = JSONArray.parseArray(JSONArray.toJSONString(newList), MemberInfoExportExcel.class);
// excel输出
ExcelUtil.exportExcel(linkedList, "会员信息", "会员信息", MemberInfoExportExcel.class, "会员信息", response);
}catch (Exception e) {
logger.error("导出excel失败", e);
throw new BizException("导出订单失败!");
}
}
/**
* @author: xiaoyu
* @date: 2023/4/18 9:32
* @describe: 会员统计
*/
@RequestMapping(value="/count", method = RequestMethod.GET)
public ApiRes count() {
MemberInfo memberInfo = getObject(MemberInfo.class);
// 状态不作为参数传入
memberInfo.setState(null);
LambdaQueryWrapper<MemberInfo> wrapper = MemberInfo.gw();
wrapper.eq(MemberInfo::getMchNo, getCurrentMchNo());
// 查询参数
memberInfoService.memberParams(memberInfo, wrapper);
Map count = memberInfoService.count(wrapper);
return ApiRes.ok(count);
}
}

View File

@@ -0,0 +1,135 @@
package com.jeequan.jeepay.mch.ctrl.member;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MemberInfo;
import com.jeequan.jeepay.db.entity.MemberRechargeRecord;
import com.jeequan.jeepay.db.entity.PayWay;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MemberRechargeRecordService;
import com.jeequan.jeepay.service.impl.PayWayService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 会员充值记录
*
* @author xiaoyu
*
* @date 2023/4/13 17:22
*/
@RestController
@RequestMapping("/api/member/rechargeRecord")
public class MemberRechargeRecordController extends CommonCtrl {
@Autowired private MemberRechargeRecordService rechargeRecordService;
@Autowired private PayWayService payWayService;
/**
* @author: xiaoyu
* @date: 2023/4/13 17:24
* @describe: 会员充值记录列表
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_RECHARGE_RECORD_LIST')")
@GetMapping
public ApiRes list() {
MemberRechargeRecord rechargeRecord = getObject(MemberRechargeRecord.class);
LambdaQueryWrapper<MemberRechargeRecord> wrapper = MemberRechargeRecord.gw();
wrapper.eq(MemberRechargeRecord::getMchNo, getCurrentMchNo());
// 查询参数
rechargeRecordService.selectParams(rechargeRecord, wrapper);
// 额外条件参数
JSONObject paramJSON = getReqParamJSON();
// 二合一 会员名称/订单号/手机号
if (paramJSON != null && StringUtils.isNotEmpty(paramJSON.getString("unionQueryParam"))) {
wrapper.and(wr -> {
wr.like(MemberRechargeRecord::getMbrTel, paramJSON.getString("unionQueryParam"))
.or().like(MemberRechargeRecord::getMbrName, paramJSON.getString("unionQueryParam"))
.or().like(MemberRechargeRecord::getPayOrderId, paramJSON.getString("unionQueryParam"));
});
}
wrapper.orderByDesc(MemberRechargeRecord::getCreatedAt);
IPage<MemberRechargeRecord> page = rechargeRecordService.page(getIPage(), wrapper);
// 得到所有支付方式
Map<String, String> payWayNameMap = new HashMap<>();
List<PayWay> payWayList = payWayService.list();
// 手机号脱敏、支付方式名称赋值
page.getRecords().stream().forEach(i -> {
i.setMbrTel(DesensitizedUtil.mobilePhone(i.getMbrTel()));
if (!CollectionUtils.isEmpty(payWayList)) {
for (PayWay payWay:payWayList) {
payWayNameMap.put(payWay.getWayCode(), payWay.getWayName());
}
// 存入支付方式名称
if (StringUtils.isNotEmpty(payWayNameMap.get(i.getWayCode()))) {
i.addExt("wayName", payWayNameMap.get(i.getWayCode()));
}else {
i.addExt("wayName", i.getWayCode());
}
}
});
// 会员头像
setAvatarUrl(page.getRecords());
return ApiRes.page(page);
}
/**
* @author: xiaoyu
* @date: 2023/4/13 17:49
* @describe: 会员充值记录详情
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_RECHARGE_RECORD_VIEW')")
@GetMapping("/{recordId}")
public ApiRes detail(@PathVariable("recordId") String recordId) {
MemberRechargeRecord record = rechargeRecordService.getById(recordId);
if (record == null || !record.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
// 查询会员信息
MemberInfo memberInfo = memberInfoService.getById(record.getMbrId());
// 会员头像
record.addExt("avatarUrl", memberInfo.getAvatarUrl());
return ApiRes.ok(record);
}
/**
* @author: xiaoyu
* @date: 2023/4/18 9:32
* @describe: 充值记录统计
*/
@RequestMapping(value="/count", method = RequestMethod.GET)
public ApiRes count() {
MemberRechargeRecord rechargeRecord = getObject(MemberRechargeRecord.class);
LambdaQueryWrapper<MemberRechargeRecord> wrapper = MemberRechargeRecord.gw();
wrapper.eq(MemberRechargeRecord::getMchNo, getCurrentMchNo());
// 查询参数
rechargeRecordService.selectParams(rechargeRecord, wrapper);
Map count = rechargeRecordService.count(wrapper);
return ApiRes.ok(count);
}
}

View File

@@ -0,0 +1,190 @@
package com.jeequan.jeepay.mch.ctrl.member;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchStore;
import com.jeequan.jeepay.db.entity.MemberRechargeRule;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchConfigService;
import com.jeequan.jeepay.service.impl.MchStoreService;
import com.jeequan.jeepay.service.impl.MemberRechargeRuleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
/**
* 会员充值规则管理
*
* @author xiaoyu
*
* @date 2023/4/13 17:22
*/
@RestController
@RequestMapping("/api/member/rechargeRule")
public class MemberRechargeRuleController extends CommonCtrl {
@Autowired private MemberRechargeRuleService memberRechargeRuleService;
@Autowired private MchConfigService mchConfigService;
@Autowired private MchStoreService mchStoreService;
/**
* @author: xiaoyu
* @date: 2023/4/13 17:24
* @describe: 会员充值规则列表
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_RECHARGE_LIST')")
@GetMapping
public ApiRes list() {
MemberRechargeRule rechargeRule = getObject(MemberRechargeRule.class);
LambdaQueryWrapper<MemberRechargeRule> wrapper = MemberRechargeRule.gw();
// 商户号
wrapper.eq(MemberRechargeRule::getMchNo, getCurrentMchNo());
// 充值ID
wrapper.eq(rechargeRule.getRuleId() != null, MemberRechargeRule::getRuleId, rechargeRule.getRuleId());
// 充值金额
wrapper.eq(rechargeRule.getRechargeAmount() != null, MemberRechargeRule::getRechargeAmount, rechargeRule.getRechargeAmount());
// 会员状态
wrapper.eq(rechargeRule.getState() != null, MemberRechargeRule::getState, rechargeRule.getState());
//门店id和名称
if (StringUtils.isNotEmpty(rechargeRule.getStoreId())){
wrapper.and(i->i.eq(MemberRechargeRule::getStoreId,rechargeRule.getStoreId())
.or().eq(MemberRechargeRule::getStoreName,rechargeRule.getStoreId()));
}
// 时间范围条件
Date[] dateRange = rechargeRule.buildQueryDateRange();
if (dateRange[0] != null) {
wrapper.ge(MemberRechargeRule::getCreatedAt, dateRange[0]);
}
if (dateRange[1] != null) {
wrapper.le(MemberRechargeRule::getCreatedAt, dateRange[1]);
}
wrapper.orderByAsc(MemberRechargeRule::getSort);
wrapper.orderByDesc(MemberRechargeRule::getCreatedAt);
IPage page = memberRechargeRuleService.page(getIPage(true), wrapper);
return ApiRes.page(page);
}
/**
* @author: xiaoyu
* @date: 2023/4/13 19:09
* @describe: 新增会员充值规则
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_RECHARGE_ADD')")
@MethodLog(remark = "新增会员充值规则")
@PostMapping
public ApiRes add() {
// 充值金额
Long rechargeAmount = getRequiredAmountL("rechargeAmount");
// 赠送金额
Long giveAmount = getAmountL("giveAmount");
MemberRechargeRule rechargeRule = getObject(MemberRechargeRule.class);
// 商户号
rechargeRule.setMchNo(getCurrentMchNo());
// 充值金额
rechargeRule.setRechargeAmount(rechargeAmount);
// 赠送金额
rechargeRule.setGiveAmount(giveAmount);
//将规则同步到门店
if (rechargeRule.getIsAllStore() != null){
memberRechargeRuleService.saveDB(rechargeRule);
}
return ApiRes.ok();
}
/**
* @author: xiaoyu
* @date: 2023/4/13 17:49
* @describe: 会员充值规则信息
*/
@PreAuthorize("hasAnyAuthority('ENT_MEMBER_RECHARGE_VIEW', 'ENT_MEMBER_RECHARGE_EDIT')")
@GetMapping("/{ruleId}")
public ApiRes detail(@PathVariable("ruleId") String ruleId) {
MemberRechargeRule rechargeRule = memberRechargeRuleService.getById(ruleId);
if (rechargeRule == null || !rechargeRule.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(rechargeRule);
}
/**
* @author: xiaoyu
* @date: 2023/4/13 17:51
* @describe: 更新会员充值规则
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_RECHARGE_EDIT')")
@MethodLog(remark = "更新会员充值规则")
@PutMapping("/{ruleId}")
public ApiRes update(@PathVariable("ruleId") String ruleId) {
// 校验当前会员信息
MemberRechargeRule dbRechargeRule = memberRechargeRuleService.getById(ruleId);
if (dbRechargeRule == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
// 充值金额
Long rechargeAmount = getRequiredAmountL("rechargeAmount");
// 赠送金额
Long giveAmount = getAmountL("giveAmount");
MemberRechargeRule rechargeRule = getObject(MemberRechargeRule.class);
rechargeRule.setMchNo(null);
// 充值金额
rechargeRule.setRechargeAmount(rechargeAmount);
// 赠送金额
rechargeRule.setGiveAmount(giveAmount);
if (!dbRechargeRule.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
// 更新信息
boolean result = memberRechargeRuleService.updateById(rechargeRule);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
/**
* @author: xiaoyu
* @date: 2023/4/13 17:58
* @describe: 删除会员充值规则
*/
@PreAuthorize("hasAuthority('ENT_MEMBER_RECHARGE_DELETE')")
@MethodLog(remark = "删除会员充值规则")
@DeleteMapping("/{ruleId}")
public ApiRes delete(@PathVariable("ruleId") String ruleId) {
MemberRechargeRule rechargeRule = memberRechargeRuleService.getById(ruleId);
if (rechargeRule == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if (!rechargeRule.getMchNo().equals(getCurrentMchNo())) {
throw new BizException("无权操作!");
}
memberRechargeRuleService.removeById(ruleId);
//清除绑定的门店信息
MchStore getMchStore = mchStoreService.getById(rechargeRule.getStoreId());
if (getMchStore != null){
mchStoreService.update(new LambdaUpdateWrapper<MchStore>()
.set(MchStore::getRuleId,null)
.eq(MchStore::getStoreId,rechargeRule.getStoreId()));
}
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,215 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.SysAdvertConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.MarketAdvertService;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.SysAdvertConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 广告
*
* @author xiaoyu
*
* @date 2023/2/21 16:13
*/
@RestController
@RequestMapping("/api/advert")
public class AdvertController extends CommonCtrl {
@Autowired SysAdvertConfigService advertConfigService;
@Autowired MchInfoService mchInfoService;
@Autowired MarketAdvertService marketAdvertService;
/** 刷脸设备广告 **/
@GetMapping("/faceDevice")
public ApiRes faceDevice() {
// 商户是否开启并配置刷脸设备广告
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
if (mchInfo != null && mchInfo.getAdvertFlag() != null) {
if (mchInfo.getAdvertFlag() == CS.YES) {
// 查询配置商户的广告
LambdaQueryWrapper<SysAdvertConfig> wrapper = SysAdvertConfig.gw();
wrapper.eq(SysAdvertConfig::getMchNo, getCurrentMchNo());
wrapper.eq(SysAdvertConfig::getAdvertType, SysAdvertConfig.ADVERT_TYPE_FACE);
wrapper.eq(SysAdvertConfig::getReleaseState, CS.YES);
wrapper.orderByDesc(SysAdvertConfig::getCreatedAt);
List<SysAdvertConfig> list = advertConfigService.list(wrapper);
// 广告配置不为空
if (!list.isEmpty()) {
return ApiRes.ok(list.get(0));
}
return ApiRes.ok();
}
}
// 查询平台全局广告
LambdaQueryWrapper<SysAdvertConfig> wrapper = SysAdvertConfig.gw();
wrapper.eq(SysAdvertConfig::getAdvertType, SysAdvertConfig.ADVERT_TYPE_FACE);
wrapper.eq(SysAdvertConfig::getReleaseState, CS.YES);
wrapper.isNull(SysAdvertConfig::getMchNo);
wrapper.orderByDesc(SysAdvertConfig::getCreatedAt);
List<SysAdvertConfig> listPlat = advertConfigService.list(wrapper);
if (!listPlat.isEmpty()) {
return ApiRes.ok(listPlat.get(0));
}
return ApiRes.ok();
}
/** APP 商户通广告 **/
@GetMapping("/appAdvert")
public ApiRes appAdvert() {
// 广告位置 1-启动页 2-首页 3-我的页
Byte appPlace = getValByteRequired("appPlace");
// 查询平台全局广告
LambdaQueryWrapper<SysAdvertConfig> wrapper = SysAdvertConfig.gw();
wrapper.eq(SysAdvertConfig::getAdvertType, SysAdvertConfig.ADVERT_TYPE_APP_MCH);
wrapper.eq(SysAdvertConfig::getAppPlace, appPlace);
wrapper.eq(SysAdvertConfig::getReleaseState, CS.YES);
wrapper.orderByAsc(SysAdvertConfig::getAdvertSort);
wrapper.orderByDesc(SysAdvertConfig::getCreatedAt);
List<SysAdvertConfig> list = advertConfigService.list(wrapper);
return ApiRes.ok(list);
}
/**
* @author: xiaoyu
* @date: 2023/2/20 11:06
* @describe: 广告配置列表
*/
@PreAuthorize("hasAnyAuthority('ENT_ADVERT_LIST', 'ENT_ADVERT_VIEW')")
@GetMapping
public ApiRes pages() {
SysAdvertConfig record = getObject(SysAdvertConfig.class);
LambdaQueryWrapper<SysAdvertConfig> condition = SysAdvertConfig.gw();
condition.eq(record.getAdvertId() != null, SysAdvertConfig::getAdvertId, record.getAdvertId());
condition.eq(record.getAppPlaceType() != null, SysAdvertConfig::getAppPlaceType, record.getAppPlaceType());
condition.eq(record.getReleaseState() != null, SysAdvertConfig::getReleaseState, record.getReleaseState());
condition.eq(record.getAdvertType() != null, SysAdvertConfig::getAdvertType, record.getAdvertType());
condition.eq(record.getAppPlace() != null, SysAdvertConfig::getAppPlace, record.getAppPlace());
condition.like(StringUtils.isNotEmpty(record.getTitle()), SysAdvertConfig::getTitle, record.getTitle());
condition.eq(SysAdvertConfig::getMchNo, getCurrentMchNo());
condition.orderByDesc(SysAdvertConfig::getCreatedAt);
IPage<SysAdvertConfig> pages = advertConfigService.page(getIPage(), condition);
for (SysAdvertConfig config: pages.getRecords()) {
if (StringUtils.isNotEmpty(config.getMchNo())) {
MchInfo mchInfo = mchInfoService.getById(config.getMchNo());
if (mchInfo != null) {
config.addExt("infoName", mchInfo.getMchName());
}else {
config.addExt("infoName", "");
}
}
}
//返回数据
return ApiRes.ok(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_ADVERT_VIEW' )")
@RequestMapping(value="/{advertId}", method = RequestMethod.GET)
public ApiRes getConfigs(@PathVariable("advertId") Long advertId) {
checkAdvertFlag();
SysAdvertConfig config = advertConfigService.getOne(
SysAdvertConfig.gw()
.eq(SysAdvertConfig::getAdvertId, advertId)
.eq(SysAdvertConfig::getMchNo, getCurrentMchNo())
);
return ApiRes.ok(config);
}
/**
* @author: xiaoyu
* @date: 2023/2/20 11:06
* @describe: 广告配置修改
*/
@PreAuthorize("hasAnyAuthority('ENT_ADVERT_EDIT')")
@MethodLog(remark = "广告配置修改")
@RequestMapping(value="/{advertId}", method = RequestMethod.PUT)
public ApiRes update(@PathVariable("advertId") Long advertId) {
// 校验权限
SysAdvertConfig config = advertConfigService.getById(advertId);
if (config != null && !getCurrentMchNo().equals(config.getMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
checkAdvertFlag();
SysAdvertConfig record = getObject(SysAdvertConfig.class);
record.setAdvertId(advertId);
if (getReqParamJSON().getByte("state") != null) {
record.setReleaseState(getReqParamJSON().getByte("state"));
}
advertConfigService.updateAdvert(record);
return ApiRes.ok();
}
/**
* @author: xiaoyu
* @date: 2023/2/20 11:10
* @describe: 广告配置新增
*/
@PreAuthorize("hasAuthority( 'ENT_ADVERT_ADD' )")
@MethodLog(remark = "广告配置新增")
@RequestMapping(value="", method = RequestMethod.POST)
public ApiRes add() {
checkAdvertFlag();
SysAdvertConfig record = getObject(SysAdvertConfig.class);
record.setCreatedUid(getCurrentUser().getSysUserId());
record.setCreatedBy(getCurrentUser().getSysUser().getRealname());
advertConfigService.addConfig(getCurrentMchNo(), record);
return ApiRes.ok();
}
/** delete */
@PreAuthorize("hasAuthority('ENT_ADVERT_DEL')")
@MethodLog(remark = "广告配置删除")
@DeleteMapping
public ApiRes del() {
checkAdvertFlag();
String delAdvertIds = getValStringRequired("delAdvertIds");
List<String> advertIdList = Arrays.stream(delAdvertIds.split(",")).collect(Collectors.toList());
advertConfigService.removeConfig(advertIdList, getCurrentMchNo(), CS.SYS_ROLE_TYPE.MCH);
return ApiRes.ok();
}
public void checkAdvertFlag() {
// 商户广告权限校验
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
if (mchInfo.getAdvertFlag() == null || mchInfo.getAdvertFlag() != CS.YES) {
throw new BizException("权限错误,当前用户不支持此操作");
}
}
}

View File

@@ -0,0 +1,38 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.OCRImgParams;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.ImgInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 图片信息OCR
*
* @author xiaoyu
*
* @date 2022/1/12 15:15
*/
@RestController
@RequestMapping("/api/imgInfo")
public class ImgInfoOCRController extends CommonCtrl {
@Autowired private ImgInfoService imgInfoService;
/** 图片信息 **/
@PreAuthorize("hasAuthority('ENT_MCH_IMG_OCR_DETAIL')")
@PostMapping("/detail")
public ApiRes detail() {
String imgUrl = getValStringRequired("imgUrl");
String type = getValStringRequired("type");
// 调用ocr接口
OCRImgParams imgParams = imgInfoService.getImgInfo(imgUrl, type);
return ApiRes.ok(imgParams);
}
}

View File

@@ -0,0 +1,143 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.db.entity.ToDoListModel;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 主页数据类
*
* @author pangxiaoyu
*
* @date 2021-04-27 15:50
*/
@Slf4j
@RestController
@RequestMapping("api/mainChart")
public class MainChartController extends CommonCtrl {
@Autowired private PayOrderService payOrderService;
@Autowired private SysUserService sysUserService;
@Autowired private MchInfoService mchInfoService;
@Autowired private StatsTradeService statsTradeService;
@Autowired private MainChartService mainChartService;
/**
* @author: xiaoyu
* @date: 2021/12/28 14:54
* @describe: 今日/昨日交易统计
*/
@PreAuthorize("hasAuthority('ENT_MCH_MAIN_PAY_DAY_COUNT')")
@RequestMapping(value="/payDayCount", method = RequestMethod.GET)
public ApiRes payDayCount() {
JSONObject reqParamJSON = getReqParamJSON();
// 门店ID条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
reqParamJSON.put("storeIdList", storeIdList);
// JSONObject resJson = payOrderService.payDayCount(getCurrentMchNo(), null, null, paramJSON);
JSONObject resJson = statsTradeService.payDayCount(getCurrentMchNo(), null, reqParamJSON);
return ApiRes.ok(resJson);
}
/**
* @author: xiaoyu
* @date: 2021/12/28 14:53
* @describe: 趋势图数据
*/
@PreAuthorize("hasAuthority('ENT_MCH_MAIN_PAY_TREND_COUNT')")
@RequestMapping(value="/payTrendCount", method = RequestMethod.GET)
public ApiRes payTrendCount() {
JSONObject paramJSON = getReqParamJSON();
int recentDay = paramJSON.getIntValue("recentDay");
if (recentDay == 0){
recentDay = 30; // 默认30天
}
paramJSON.put("recentDay", recentDay);
// 门店ID条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
paramJSON.put("storeIdList", storeIdList);
JSONObject resJson = payOrderService.payTrendCount(paramJSON, getCurrentMchNo(), null);
return ApiRes.ok(resJson);
}
/**
* @author: xiaoyu
* @date: 2021/12/28 14:54
* @describe: 交易统计
*/
@PreAuthorize("hasAuthority('ENT_MCH_MAIN_PAY_COUNT')")
@RequestMapping(value="/payCount", method = RequestMethod.GET)
public ApiRes payCount() {
JSONObject paramJSON = getReqParamJSON();
// 门店ID条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
paramJSON.put("storeIdList", storeIdList);
// 获取传入参数
JSONObject resJson = payOrderService.mainPagePayCount(getCurrentMchNo(), null, paramJSON);
return ApiRes.ok(resJson);
}
/**
* @author: xiaoyu
* @date: 2021/12/28 14:54
* @describe: 支付方式统计
*/
@PreAuthorize("hasAuthority('ENT_MCH_MAIN_PAY_TYPE_COUNT')")
@RequestMapping(value="/payTypeCount", method = RequestMethod.GET)
public ApiRes payWayCount() {
JSONObject paramJSON = getReqParamJSON();
// 门店ID条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
paramJSON.put("storeIdList", storeIdList);
ArrayList arrayResult = payOrderService.mainPagePayTypeCount(getCurrentMchNo(), null, paramJSON);
return ApiRes.ok(arrayResult);
}
/**
* @author: xiaoyu
* @date: 2021/12/28 14:54
* @describe: 商户基本信息、用户基本信息
*/
@PreAuthorize("hasAuthority('ENT_MCH_INFO')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes userDetail() {
SysUserEntity sysUserEntity = sysUserService.getById(getCurrentUser().getSysUser().getSysUserId());
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
JSONObject json = (JSONObject) JSON.toJSON(mchInfo);
json.put("loginUsername", sysUserEntity.getLoginUsername());
json.put("realname", sysUserEntity.getRealname());
return ApiRes.ok(json);
}
/**
*
* @describe (待办事项)汇总待审核或者待操作的事件数量
*
* @return
*/
@RequestMapping(value = "/getWaitOperationNumber",method = RequestMethod.GET)
public ApiRes getWaitOperationNumber(){
List<ToDoListModel> waitOperationNumber = new ArrayList<>();
return ApiRes.ok(waitOperationNumber);
}
}

View File

@@ -0,0 +1,347 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import cn.hutool.core.codec.Base64;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.converter.MchInfoConverter;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchApp;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.config.SystemYmlConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 商户应用管理类
*
* @date 2021-06-16 09:15
*/
@RestController
@RequestMapping("/api/mchApps")
public class MchAppController extends CommonCtrl {
@Autowired
private MchAppService mchAppService;
@Autowired
private MchInfoService mchInfoService;
@Autowired
private SystemYmlConfig systemYmlConfig;
@Autowired
private IMQSender mqSender;
@Autowired
private ProductAppConnService productAppConnService;
@Autowired
private ProductInfoService productInfoService;
@Autowired
private ProductAppService productAppService;
@Autowired
private MachAppUpdateEXTVService machAppUpdateEXTVService;
@Autowired
private MchInfoConverter mchInfoConverter;
@PreAuthorize("hasAuthority('ENT_MCH_APP_LIST')")
@MethodLog(remark = "一键关联")
@PostMapping("/relevance")
public ApiRes oneKeyXRelevance() {
MchAppEntity mchAppEntity = getObject(MchAppEntity.class);
return ApiRes.ok(mchAppService.correlation(mchAppEntity.getAppId()));
}
/**
* @Description: 应用列表
* @since 2021/6/16
*/
@PreAuthorize("hasAuthority('ENT_MCH_APP_LIST')")
@GetMapping
public ApiRes list() {
MchAppEntity mchAppEntity = getObject(MchAppEntity.class);
mchAppEntity.setMchNo(getCurrentMchNo());
String unionSearchId= getValString("unionSearchId");
if(ObjectUtils.isNotEmpty(unionSearchId)){
mchAppEntity.setAppName(unionSearchId);
}
IPage<MchAppEntity> pages = mchAppService.selectPage(getIPage(true), mchAppEntity);
return ApiRes.page(pages);
}
/**
* @Description: 新建应用
* @since 10:05 2021/6/16
*/
@PreAuthorize("hasAuthority('ENT_MCH_APP_ADD')")
@MethodLog(remark = "新建应用")
@PostMapping
public ApiRes add() {
MchApp mchApp = getObject(MchApp.class);
mchApp.setAppId(SeqKit.getMchAppId());
mchApp.setMchNo(getCurrentMchNo());
MchInfo mchInfo = mchInfoService.getById(mchApp.getMchNo());
if (mchInfo == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
mchApp.setAgentNo(mchInfo.getAgentNo());
mchApp.setTopAgentNo(mchInfo.getTopAgentNo());
//默认设置为审核中
mchApp.setState(MchAppEntity.AUDIT);
// 如果当前为默认
if (mchApp.getDefaultFlag() == CS.YES) {
mchAppService.update(new LambdaUpdateWrapper<MchAppEntity>()
.set(MchAppEntity::getDefaultFlag, CS.NO)
.eq(MchAppEntity::getMchNo, mchApp.getMchNo())
);
}
// 根据功能code获取功能的信息
// List<Capability> openFuncList = new ArrayList<>();
// for (String code : mchApp.getCapabilityCodeList()) {
// Capability capability = Capability.MAP.get(code);
// Assert.notNull(capability, "非法的功能代码");
//
// openFuncList.add(capability);
// }
// mchApp.setPreCapabilities(openFuncList);
boolean result = mchAppService.save(mchInfoConverter.toDbEntity(mchApp));
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
}
return ApiRes.ok();
}
/**
* @Description: 应用详情
* @since 10:13 2021/6/16
*/
@PreAuthorize("hasAnyAuthority('ENT_MCH_APP_VIEW', 'ENT_MCH_APP_EDIT')")
@GetMapping("/{appId}")
public ApiRes detail(@PathVariable("appId") String appId) {
MchAppEntity mchAppEntity = mchAppService.selectById(appId);
if (mchAppEntity == null || !mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(mchAppEntity);
}
/**
* @since 2022/8/30 14:54
* @describe: 查看应用私钥
*/
@PreAuthorize("hasAuthority('ENT_MCH_APP_SIGN')")
@PostMapping("/secret")
public ApiRes viewSecret() {
// 应用ID
String appId = getValStringRequired("appId");
// 验证支付密码
String payPassword = Base64.decodeStr(getValStringRequired("payPassword"));
//验证当前密码是否正确
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
if (StringUtils.isEmpty(mchInfo.getSipw())) {
throw new BizException("当前未设置支付密码,请进入[账号中心-系统配置-安全管理]设置支付密码");
}
if (!new BCryptPasswordEncoder().matches(payPassword, mchInfo.getSipw())) {
throw new BizException("支付密码验证失败!");
}
MchAppEntity mchAppEntity = mchAppService.getOneByMch(getCurrentMchNo(), appId);
if (mchAppEntity == null || !mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(mchAppEntity.getAppSecret());
}
/**
* @Description: 更新应用信息
* @since 10:11 2021/6/16
*/
@PreAuthorize("hasAuthority('ENT_MCH_APP_EDIT')")
@MethodLog(remark = "更新应用信息")
@PutMapping("/{appId}")
public ApiRes update(@PathVariable("appId") String appId) {
MchApp mchApp = getObject(MchApp.class);
mchApp.setAppId(appId);
MchAppEntity dbMchAppEntity = mchAppService.getById(appId);
if (!dbMchAppEntity.getDefaultFlag().equals(mchApp.getDefaultFlag())) {
// 如果修改当前为默认
if (mchApp.getDefaultFlag() == CS.YES) {
mchAppService.update(new LambdaUpdateWrapper<MchAppEntity>()
.set(MchAppEntity::getDefaultFlag, CS.NO)
.eq(MchAppEntity::getMchNo, dbMchAppEntity.getMchNo())
);
} else {
throw new BizException("应用不可修改为非默认!");
}
}
//如果是审核驳回的修改则重新发起审核
if (Objects.equals(dbMchAppEntity.getState(), MchAppEntity.REJECT)){
mchApp.setState(MchAppEntity.AUDIT);
}
// 根据功能code获取功能的信息
/*List<Capability> openFuncList = new ArrayList<>();
Optional.ofNullable(mchApp.getCapabilityCodeList()).ifPresent(it ->
it.forEach(code -> {
Capability capability = Capability.MAP.get(code);
Assert.notNull(capability, "非法的功能代码");
openFuncList.add(capability);
})
);
mchApp.setPreCapabilities(openFuncList);*/
boolean result = mchAppService.updateById(mchInfoConverter.toDbEntity(mchApp));
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
/**
* @Author: ZhuXiao
* @Description: 删除应用
* @since 10:14 2021/6/16
*/
@PreAuthorize("hasAuthority('ENT_MCH_APP_DEL')")
@MethodLog(remark = "删除应用")
@DeleteMapping("/{appId}")
public ApiRes delete(@PathVariable("appId") String appId) {
MchAppEntity mchAppEntity = mchAppService.getById(appId);
if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
throw new BizException("无权操作!");
}
mchAppService.removeByAppId(appId);
return ApiRes.ok();
}
/**
* 功能描述: 查询系统公钥
*/
@PreAuthorize("hasAnyAuthority('ENT_MCH_APP_ADD', 'ENT_MCH_APP_EDIT')")
@GetMapping("/sysRSA2PublicKey")
public ApiRes sysRSA2PublicKey() {
return ApiRes.ok(systemYmlConfig.getSysRSA2PublicKey());
}
@GetMapping("/getNewProductList")
@MethodLog(remark = "新获取产品列表")
public ApiRes getNewProductList() {
String appId = getValString("appId");
if (StringUtils.isBlank(appId)) {
return ApiRes.customFail("appId不能为空!");
}
//获取已审核通过和正在审核的产品列表包括产品和商户的绑定关系
//1.获取t_product_app表中已经通过审核和待审核的数据并拿到product_id
LambdaQueryWrapper<PackageOrder> appWrapper = new LambdaQueryWrapper<>();
appWrapper.in(PackageOrder::getState, 1, 3);
List<PackageOrder> appList = productAppService.list(appWrapper);
List<String> productIdCollect = appList.stream()
.map(PackageOrder::getProductId)
.collect(Collectors.toList());
//2通过product_id获取到具体的产品信息
LambdaQueryWrapper<ProductInfo> infoWrapper = new LambdaQueryWrapper<>();
infoWrapper.in(ProductInfo::getProductId, productIdCollect);
List<ProductInfo> infoList = productInfoService.list(infoWrapper);
//3.获取关联关系
// 获取当前商户信息
String mchNo = getCurrentUser().getSysUser().getBelongInfoId();
//合并信息通过审核和待审核的产品和当前appid绑定的数据有则返回1没有则为0
for (ProductInfo itemProductInfo : infoList) {
String productId = itemProductInfo.getProductId();
LambdaQueryWrapper<ProductAppConn> appConnWrapper = new LambdaQueryWrapper<>();
appConnWrapper.eq(ProductAppConn::getProductId, productId)
.eq(ProductAppConn::getAppId, appId)
.eq(ProductAppConn::getState, 1)
.eq(ProductAppConn::getMchNo, mchNo);
//传入审核状态
List<PackageOrder> appStateList = appList.stream().filter(u -> productId.equals(u.getProductId())).collect(Collectors.toList());
if (!appStateList.isEmpty()) {
int checkState = appStateList.get(0).getState();
itemProductInfo.setCheckState(checkState);
}
//添加绑定状态
List<ProductAppConn> appConnList = productAppConnService.list(appConnWrapper);
if (!appConnList.isEmpty()) {
itemProductInfo.setState(1);
} else {
itemProductInfo.setState(0);
}
}
Page<ProductInfo> page = new Page<>();
page.setRecords(infoList);
page.setTotal(infoList.size());
page.setCurrent(1);
return ApiRes.ok(page);
}
@PostMapping("/relevancyProduct")
@MethodLog(remark = "关联/解除关联产品")
public ApiRes relevancyProduct() {
ProductAppConn productAppConn = getReqParamJSON().toJavaObject(ProductAppConn.class);
if (!Optional.ofNullable(productAppConn.getAppId()).isPresent()) {
return ApiRes.customFail("传入数据不能为空!");
}
// 获取当前商户信息
String mchNo = getCurrentUser().getSysUser().getBelongInfoId();
//根据传入信息查看库中是否有数据
LambdaQueryWrapper<ProductAppConn> appConnWrapper = new LambdaQueryWrapper<>();
appConnWrapper.eq(ProductAppConn::getProductId, productAppConn.getProductId())
.eq(ProductAppConn::getAppId, productAppConn.getAppId())
.eq(ProductAppConn::getMchNo, mchNo);
List<ProductAppConn> appConnList = productAppConnService.list(appConnWrapper);
//如果没有则进行新增关联关系
if (appConnList.isEmpty()) {
ProductAppConn appConnOne = new ProductAppConn();
appConnOne.setProductId(productAppConn.getProductId());
appConnOne.setAppId(productAppConn.getAppId());
appConnOne.setState(productAppConn.getState());
appConnOne.setMchNo(mchNo);
productAppConnService.save(appConnOne);
//关联时将产品关联的固定功能信息`funcCode`存储到应用信息`extx`中
machAppUpdateEXTVService.machAppUpdateEXTV(productAppConn, 1);
return ApiRes.ok("关联成功!");
} else {
//如果库中有数据则进行修改 关联状态修改
ProductAppConn appConnOne = productAppConnService.getOne(appConnWrapper);
appConnOne.setState(productAppConn.getState());
productAppConnService.updateById(appConnOne);
if (Objects.equals(productAppConn.getState(), 1)) {
//关联时将产品关联的固定功能信息`funcCode`存储到应用信息`extx`中
machAppUpdateEXTVService.machAppUpdateEXTV(productAppConn, 1);
return ApiRes.ok("关联成功!");
} else {
machAppUpdateEXTVService.machAppUpdateEXTV(productAppConn, 0);
return ApiRes.ok("解除关联成功!");
}
}
}
}

View File

@@ -0,0 +1,48 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import com.jeequan.jeepay.core.interfaces.push.IBaiduBceService;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBBaiduBceConfig;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchAppPushInfoService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 商户App推送 + 语音播报
*
* @author zhuxiao
*
* @date 2021-06-16 09:15
*/
@RestController
@RequestMapping("/api/pushinfo")
public class MchAppPushInfoController extends CommonCtrl {
@Autowired private MchAppPushInfoService mchAppPushInfoService;
@Autowired private SysConfigService sysConfigService;
/** 商户app推送设备注册 **/
@RequestMapping(value = "/register", method = RequestMethod.POST)
public ApiRes register() {
// 查询用户app推送设备是否注册
mchAppPushInfoService.saveMchCid(getReqParamJSON(), getCurrentMchNo(), getCurrentUser().getSysUserId());
return ApiRes.ok();
}
/** 获取百度语音播报token **/
@RequestMapping(value = "/getBaiduToken", method = RequestMethod.GET)
public ApiRes getBaiduToken() {
DBBaiduBceConfig baiduBceConfig = sysConfigService.getDBBaiduBceConfig();
IBaiduBceService baiduBceService = SpringBeansUtil.getBean("baiduBceService", IBaiduBceService.class);
return ApiRes.ok(baiduBceService.getBaiduBceToken(baiduBceConfig));
}
}

View File

@@ -0,0 +1,214 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBDefaultConfig;
import com.jeequan.jeepay.db.entity.MchConfig;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchConfigService;
import com.jeequan.jeepay.service.impl.MchInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 商户配置管理类
*
* @author zx
*
* @date 2021-06-16 09:15
*/
@RestController
@RequestMapping("/api/mchConfig")
public class MchConfigController extends CommonCtrl {
@Autowired private MchConfigService mchConfigService;
@Autowired private MchInfoService mchInfoService;
/**
* @Author: zx
* @Description: 查询商户配置
* @Date: 9:59 2021/6/16
*/
@GetMapping
public ApiRes list() {
String groupKey = getValString("groupKey");
String mchNo = getCurrentMchNo();
String mchAppId = getValString("mchAppId");
String mchApplyId = getValString("mchApplyId");
LambdaQueryWrapper<MchConfig> queryWrapper = MchConfig.gw()
.eq(MchConfig::getMchNo, mchNo)
.eq(!ObjUtil.isEmpty(mchAppId), MchConfig::getMchAppId, mchAppId)
.eq(!ObjUtil.isEmpty(mchApplyId), MchConfig::getMchApplyId, mchApplyId);
List<MchConfig> list = mchConfigService.list(queryWrapper);
return ApiRes.ok(list);
}
/**
* @Author: zx
* @Description: 根据configKey查询商户配置
* @Date: 9:59 2021/6/16
*/
@GetMapping("/{configKey}")
public ApiRes get(@PathVariable("configKey") String configKey) {
MchConfig mchConfig = mchConfigService.getOne(MchConfig.gw().eq(MchConfig::getMchNo, getCurrentMchNo()).eq(MchConfig::getConfigKey, configKey));
return ApiRes.ok(mchConfig);
}
/**
* @Author: zx
* @Description: 根据configKey更新商户配置信息
* @Date: 10:11 2021/6/16
*/
@PreAuthorize("hasAuthority('ENT_MCH_CONFIG_EDIT')")
@MethodLog(remark = "更新商户配置")
@PutMapping("/updateById/{configKey}")
public ApiRes updateByConfigKey(@PathVariable("configKey") String configKey) {
MchConfig mchConfig = getObject(MchConfig.class);
mchConfig.setConfigKey(configKey);
mchConfig.setMchNo(getCurrentMchNo());
if (MchConfig.NOT_ALLOW_MCH_EDIT.contains(configKey)) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
int count = mchConfigService.saveOrUpdateConfig(mchConfig);
if(count <= 0) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
/**
* @author: zx
* @Description: 批量更新商户配置信息
* @Date: 10:11 2021/6/16
*/
@PreAuthorize("hasAuthority('ENT_MCH_CONFIG_EDIT')")
@MethodLog(remark = "批量更新商户配置信息")
@PutMapping("/{groupKey}")
public ApiRes updateBatch(@PathVariable("groupKey") String groupKey) {
String params = getValStringRequired("configData");
List<MchConfig> mchConfigList = JSONArray.parseArray(params, MchConfig.class);
mchConfigList.removeIf(mchConfig -> MchConfig.NOT_ALLOW_MCH_EDIT.contains(mchConfig.getConfigKey()));
String mchNo = getValStringRequired("mchNo");
String mchAppId = getValString("mchAppId");
String mchApplyId = getValString("mchApplyId");
int update = mchConfigService.updateBatch(mchConfigList, mchNo, mchAppId, mchApplyId, groupKey);
if(update <= 0) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
@MethodLog(remark = "更改商户级别")
@PutMapping("/mchLevel")
public ApiRes updateMchLevel() {
String mchLevel = getValStringRequired("mchLevel");
MchInfo mchInfo = new MchInfo();
mchInfo.setMchNo(getCurrentMchNo());
mchInfo.setMchLevel(mchLevel);
mchInfoService.updateById(mchInfo);
return ApiRes.ok();
}
@MethodLog(remark = "更改支付密码")
@PutMapping("/mchSipw")
public ApiRes updateMchSipw() {
String confirmPwd = Base64.decodeStr(getValStringRequired("confirmPwd"));
// 验证原密码
MchInfo dbMchInfo = mchInfoService.getById(getCurrentMchNo());
if(StringUtils.isNotEmpty(dbMchInfo.getSipw())){
//当前旧密码
String originalPwd = Base64.decodeStr(getValStringRequired("originalPwd"));
if(!new BCryptPasswordEncoder().matches(originalPwd, dbMchInfo.getSipw())){
throw new BizException("原支付验证失败!");
}
}
MchInfo mchInfo = new MchInfo();
mchInfo.setMchNo(getCurrentMchNo());
mchInfo.setSipw(new BCryptPasswordEncoder().encode(confirmPwd));
mchInfoService.updateById(mchInfo);
return ApiRes.ok();
}
/** 是否设置了支付密码 **/
@GetMapping("/hasSipwValidate")
public ApiRes hasSipwValidate() {
MchInfo dbMchInfo = mchInfoService.getById(getCurrentMchNo());
if(StringUtils.isNotEmpty(dbMchInfo.getSipw())){
return ApiRes.ok(true);
}
return ApiRes.ok(false);
}
/** 验证支付密码是否正确 **/
@PostMapping("/mchSipwValidate")
public ApiRes mchSipwValidate() {
//当前旧密码
String originalPwd = Base64.decodeStr(getValStringRequired("originalPwd"));
// 验证原密码
MchInfo dbMchInfo = mchInfoService.getById(getCurrentMchNo());
if(StringUtils.isNotEmpty(dbMchInfo.getSipw())){
if(!new BCryptPasswordEncoder().matches(originalPwd, dbMchInfo.getSipw())){
return ApiRes.ok(false);
}
}
return ApiRes.ok(true);
}
/** 会员最大储值余额 **/
@GetMapping("/mbrMaxBalance")
public ApiRes getMbrMaxBalance() {
MchConfig mbrMaxBalanceConfig = mchConfigService.getByMchNoAndConfigKey(getCurrentMchNo(), MchConfig.SELF_MEMBER_MAX_BALANCE);
if (mbrMaxBalanceConfig != null && StringUtils.isNotBlank(mbrMaxBalanceConfig.getConfigVal()) && !MchConfig.NO.equals(mbrMaxBalanceConfig.getConfigVal())) {
return ApiRes.ok(mbrMaxBalanceConfig.getConfigVal());
}
DBDefaultConfig defaultConfig = sysConfigService.getDBDefaultConfig();
if (defaultConfig != null && defaultConfig.getMchMbrMaxBalance() != null && defaultConfig.getMchMbrMaxBalance() != 0L) {
return ApiRes.ok(defaultConfig.getMchMbrMaxBalance());
}
return ApiRes.ok(CS.NO);
}
}

View File

@@ -0,0 +1,212 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.DesensitizedUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.components.mq.model.CleanMchLoginAuthCacheMQ;
import com.jeequan.jeepay.components.mq.model.ResetIsvMchAppInfoConfigMQ;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.smsconfig.SmsBizDiyContentModel;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 商户管理类
*
* @date 2021-06-07 07:15
*/
@RestController
@RequestMapping("/api/mchInfo")
public class MchInfoController extends CommonCtrl {
@Autowired private MchInfoService mchInfoService;
@Autowired private SysUserService sysUserService;
@Autowired private IMQSender mqSender;
@Autowired private SmsManager smsManager;
/**
* @date: 2021/6/7 16:14
* @describe: 商户信息列表
*/
// @PreAuthorize("hasAuthority('ENT_MCH_LIST')")
@GetMapping
public ApiRes list() {
MchInfo mchInfo = getObject(MchInfo.class);
LambdaQueryWrapper<MchInfo> wrapper = MchInfo.gw();
wrapper.eq(StringUtils.isNotEmpty(mchInfo.getMchNo()), MchInfo::getMchNo, mchInfo.getMchNo());
wrapper.eq(StringUtils.isNotEmpty(mchInfo.getAgentNo()), MchInfo::getAgentNo, mchInfo.getAgentNo());
wrapper.like(StringUtils.isNotEmpty(mchInfo.getMchName()), MchInfo::getMchName, mchInfo.getMchName());
wrapper.eq(mchInfo.getType() != null, MchInfo::getType, mchInfo.getType());
wrapper.eq(mchInfo.getState() != null && mchInfo.getState() == CS.YES, MchInfo::getState, CS.YES);
wrapper.ne(mchInfo.getState() != null && mchInfo.getState() != CS.YES, MchInfo::getState, CS.YES);
wrapper.eq(mchInfo.getAdvertFlag() != null, MchInfo::getAdvertFlag, mchInfo.getAdvertFlag());
wrapper.like(StringUtils.isNotEmpty(mchInfo.getContactTel()), MchInfo::getContactTel, mchInfo.getContactTel());
wrapper.like(StringUtils.isNotEmpty(mchInfo.getLoginUsername()), MchInfo::getLoginUsername, mchInfo.getLoginUsername());
wrapper.orderByDesc(MchInfo::getCreatedAt);
// 扩展员仅查询自己的数据
wrapper.eq(getCurrentUser().isEpUser(), MchInfo::getCreatedUid, getCurrentUser().getSysUser().getSysUserId());
IPage<MchInfo> pages = mchInfoService.page(getIPage(), wrapper);
// 数据脱敏
pages.getRecords().stream().forEach(r -> r.setContactTel(DesensitizedUtil.mobilePhone(r.getContactTel())));
return ApiRes.page(pages);
}
/**
* @date: 2021/6/7 16:14
* @describe: 新增商户信息
*/
//@PreAuthorize("hasAuthority('ENT_MCH_INFO_ADD')")
@MethodLog(remark = "新增商户")
@RequestMapping(value="", method = RequestMethod.POST)
public ApiRes add() {
MchInfo mchInfo = getObject(MchInfo.class);
// 获取传入的商户登录名、登录密码
String loginPassword = getValString("loginPassword");
Byte isNotify = getValByteRequired("isNotify");
if (StringUtils.isBlank(loginPassword)) {
loginPassword = null;
}
mchInfo.setMchNo(SeqKit.genMchNo());
// 当前登录用户信息
SysUser sysUser = getCurrentUser().getSysUser();
mchInfo.setCreatedUid(sysUser.getSysUserId());
mchInfo.setCreatedBy(sysUser.getRealname());
mchInfoService.addMch(mchInfo, loginPassword);
// 发送短信通知
if (isNotify == CS.YES) {
smsManager.sendDiyContentSms(SmsBizDiyContentModel.genUserOpenAccount(mchInfo.getContactTel(), mchInfo.getLoginUsername(), loginPassword));
}
return ApiRes.ok();
}
/**
* @date: 2021/6/7 16:14
* @describe: 删除商户信息
*/
//@PreAuthorize("hasAuthority('ENT_MCH_INFO_DEL')")
@MethodLog(remark = "删除商户")
@RequestMapping(value="/{mchNo}", method = RequestMethod.DELETE)
public ApiRes delete(@PathVariable("mchNo") String mchNo) {
List<Long> userIdList = mchInfoService.removeByMchNo(mchNo);
// 推送mq删除redis用户缓存
mqSender.send(CleanMchLoginAuthCacheMQ.build(userIdList));
// 推送mq到目前节点进行更新数据
mqSender.send(ResetIsvMchAppInfoConfigMQ.build(ResetIsvMchAppInfoConfigMQ.RESET_TYPE_MCH_INFO, null, mchNo, null));
return ApiRes.ok();
}
/**
* @date: 2021/6/7 16:14
* @describe: 更新商户信息
*/
//@PreAuthorize("hasAuthority('ENT_MCH_INFO_EDIT')")
@MethodLog(remark = "更新商户信息")
@RequestMapping(value="/{mchNo}", method = RequestMethod.PUT)
public ApiRes update(@PathVariable("mchNo") String mchNo) {
//获取查询条件
MchInfo mchInfo = getObject(MchInfo.class);
mchInfo.setMchNo(mchNo); //设置商户号主键
mchInfo.setType(null); //防止变更商户类型
mchInfo.setLoginUsername(null); // 防止修改用户登录名
// 是否重置密码 & 确认新密码
boolean resetPass = getReqParamJSON().getBooleanValue("resetPass");
String confirmPwd = null;
if(resetPass){
confirmPwd = getReqParamJSON().getBoolean("defaultPass") ? null : Base64.decodeStr(getValStringRequired("confirmPwd"));
}
// 是否修改状态为停用,设置为由运营平台停用
if (mchInfo.getState() != null && mchInfo.getState() != MchInfo.STATE_YES) {
mchInfo.setState(MchInfo.STATE_NO_MGR);
}
// 更新商户 & 得到需要删除的商户用户ID的记录
Set<Long> removeCacheUserIdList = mchInfoService.updateMch(mchInfo, resetPass, confirmPwd);
// 推送mq删除redis用户认证信息
if (!removeCacheUserIdList.isEmpty()) {
mqSender.send(CleanMchLoginAuthCacheMQ.build(new ArrayList<>(removeCacheUserIdList)));
}
// 推送mq到目前节点进行更新数据
mqSender.send(ResetIsvMchAppInfoConfigMQ.build(ResetIsvMchAppInfoConfigMQ.RESET_TYPE_MCH_INFO, null, mchNo, null));
return ApiRes.ok();
}
/**
* @date: 2021/6/7 16:14
* @describe: 查询商户信息
*/
//@PreAuthorize("hasAnyAuthority('ENT_MCH_INFO_VIEW', 'ENT_MCH_INFO_EDIT')")
@RequestMapping(value="/{mchNo}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("mchNo") String mchNo) {
MchInfo mchInfo = mchInfoService.getById(mchNo);
if (mchInfo == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if (mchInfo.getState() == MchInfo.STATE_NO_MGR) {
mchInfo.setState(CS.NO);
}
return ApiRes.ok(mchInfo);
}
/**
* 获取默认渠道
*
* @return
*/
@GetMapping("/defIsv")
public ApiRes getDefaultIsv() {
String ifCode = getValString("ifCode");
String currentMchNo = getCurrentMchNo();
List<Map<String, String>> defIsv = mchInfoService.getDefIsv(currentMchNo, ifCode);
return ApiRes.ok(defIsv);
}
/**
* 设置默认渠道
*/
@PostMapping("/defIsv")
public ApiRes setDefaultIsv() {
String ifCode = getValStringRequired("ifCode");
String isvNo = getValStringRequired("isvNo");
String currentMchNo = getCurrentMchNo();
mchInfoService.setDefIsv(currentMchNo, ifCode, isvNo);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,67 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchModifyApplymentEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchModifyApplymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* TODO
*
* @author crystal
* @date 2023/12/27 15:36
*/
@RestController
@RequestMapping("/api/mchModifyApplyment")
public class MchModifyApplymentController extends CommonCtrl {
@Autowired
private MchModifyApplymentService modifyApplymentService;
@PreAuthorize("hasAuthority('ENT_MCH_MODIFY_LIST')")
@GetMapping
public ApiRes list() {
MchModifyApplymentEntity modifyApplyment = getObject(MchModifyApplymentEntity.class);
modifyApplyment.setMchNo(getCurrentMchNo());
Page<MchModifyApplymentEntity> pages = modifyApplymentService.pageList(getIPage(), modifyApplyment,null);
return ApiRes.page(pages);
}
@PostMapping(value = "/audit")
public ApiRes audit() {
String modifyApplymentId = getValStringRequired("modifyApplymentId");
Boolean auditFlag = getValRequired("state", Boolean.class);
String remark = getValString("remark");
modifyApplymentService.audit(modifyApplymentId, auditFlag, remark, true);
return ApiRes.ok();
}
@GetMapping("/result/{modifyApplyId}")
public ApiRes getResult(@PathVariable("modifyApplyId") String modifyApplyId) {
modifyApplymentService.getResult(modifyApplyId);
return ApiRes.ok();
}
@PreAuthorize("hasAuthority('ENT_MCH_APPLYMENT_VIEW')")
@GetMapping("/{recordId}")
public ApiRes detail(@PathVariable("recordId") String recordId) {
Byte originData = getValByteDefault("originData", CS.NO);
MchModifyApplymentEntity record;
if (CS.NO == originData) {
record = modifyApplymentService.getInfoById(recordId);
} else {
record = modifyApplymentService.getById(recordId);
}
return ApiRes.ok(record);
}
}

View File

@@ -0,0 +1,309 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.IConfigContextQueryService;
import com.jeequan.jeepay.core.interfaces.paychannel.aliaqfbiz.IAliaqfApiService;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvParams;
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvsubMchParams;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.PayInterfaceConfig;
import com.jeequan.jeepay.db.entity.PayInterfaceDefine;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 商户支付接口配置类
*
* @author zhuxiao
*
* @date 2021-04-27 15:50
*/
@Slf4j
@RestController
@RequestMapping("/api/mch/payConfigs")
public class MchPayInterfaceConfigController extends CommonCtrl {
@Autowired
private PayInterfaceDefineService payInterfaceDefineService;
@Autowired
private PayInterfaceConfigService payInterfaceConfigService;
@Autowired
private MchInfoService mchInfoService;
@Autowired
private MchAppService mchAppService;
@Autowired
private SysConfigService sysConfigService;
@Autowired
private IMQSender mqSender;
@Autowired
private IConfigContextQueryService configContextQueryService;
/**
* @Author: ZhuXiao
* @Description: 查询商户支付接口配置列表
* @Date: 10:51 2021/5/13
*/
@GetMapping
public ApiRes list() {
MchInfo mchInfo = mchInfoService.getById(getCurrentUser().getSysUser().getBelongInfoId());
List<PayInterfaceDefine> list = payInterfaceConfigService.selectAllPayIfConfigListByAppId(getValStringRequired("appId"));
for (PayInterfaceDefine define : list) {
define.addExt("mchParams", mchInfo.getType() == CS.MCH_TYPE_NORMAL ? define.getNormalMchParams() : define.getIsvsubMchParams());
define.setNormalMchParams(null);
define.setIsvsubMchParams(null);
}
return ApiRes.ok(list);
}
/**
* 查询支付宝商户授权URL
**/
@GetMapping("/alipayIsvsubMchAuthUrls/{mchAppId}/{isvNo}")
public ApiRes queryAlipayIsvsubMchAuthUrl(@PathVariable("mchAppId") String mchAppId,
@PathVariable("isvNo") String isvNo) {
MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
if (mchAppEntity == null || !mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
MchInfo mchInfo = mchInfoService.getById(mchAppEntity.getMchNo());
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
String authUrl = dbApplicationConfig.genAlipayIsvsubMchAuthUrl(isvNo, mchAppId);
String authQrImgUrl = dbApplicationConfig.genScanImgUrl(authUrl);
JSONObject result = new JSONObject();
result.put("authUrl", authUrl);
result.put("authQrImgUrl", authQrImgUrl);
return ApiRes.ok(result);
}
/**
* 查询当前应用支持的支付接口
*/
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_ADD' )")
@RequestMapping(value = "ifCodes/{appId}", method = RequestMethod.GET)
public ApiRes getIfCodeByAppId(@PathVariable("appId") String appId) {
if (mchAppService.lambdaQuery().eq(MchAppEntity::getAppId, appId).eq(MchAppEntity::getMchNo, getCurrentMchNo()).count() <= 0) {
throw new BizException("商户应用不存在");
}
Set<String> result = new HashSet<>();
payInterfaceConfigService.list(PayInterfaceConfig.gw().select(PayInterfaceConfig::getIfCode).eq(PayInterfaceConfig::getState, CS.PUB_USABLE).eq(PayInterfaceConfig::getInfoId, appId).eq(PayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.MCH_APP)).forEach(r -> result.add(r.getIfCode()));
if (result.isEmpty()) {
return ApiRes.ok(new ArrayList<>());
}
return ApiRes.ok(payInterfaceDefineService.list(PayInterfaceDefine.gw().select(PayInterfaceDefine::getIfCode, PayInterfaceDefine::getIfName, PayInterfaceDefine::getIcon, PayInterfaceDefine::getBgColor).in(PayInterfaceDefine::getIfCode, result)));
}
/**
* 支付宝安全发签约页面
**/
@PreAuthorize("hasAuthority( 'AGREEMENT_PAGE_SIGN' )")
@GetMapping("/alipayAgreementPageSign/{mchAppId}/{isvNo}")
public ApiRes alipayAgreementPageSign(@PathVariable("mchAppId") String mchAppId, @PathVariable("isvNo") String isvNo) {
MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
// 权限判断
if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
AliaqfIsvParams aliaqfIsvParams = getIsvParams(mchAppEntity.getMchNo(), isvNo);
IAliaqfApiService aliaqfApiService = SpringBeansUtil.getBean(CS.IF_CODE.ALIAQF + "ApiService", IAliaqfApiService.class);
// 获取签约页面
String jumpUrl = aliaqfApiService.userAgreementPageSign(aliaqfIsvParams, mchAppId);
return ApiRes.ok(jumpUrl);
}
/**
* 查询支付宝安全发签约结果
*/
@PreAuthorize("hasAnyAuthority( 'USER_AGREEMENT_PAGE_SIGN', 'AGREEMENT_PAGE_SIGN' )")
@GetMapping("/queryUserAgreementPageSign/{mchAppId}/{isvNo}")
public ApiRes queryUserAgreementPageSign(@PathVariable("mchAppId") String mchAppId,
@PathVariable("isvNo") String isvNo) {
MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
// 权限判断
if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
if (MchInfo.TYPE_ISVSUB != mchInfo.getType()) {
throw new BizException("仅支持特约商户");
}
AliaqfIsvParams ALIAQFIsvParams = (AliaqfIsvParams) configContextQueryService.queryIsvParams(isvNo, CS.IF_CODE.ALIAQF);
if (ALIAQFIsvParams == null) {
JSONObject isvReturnJson = new JSONObject();
isvReturnJson.put("isvConfigIsOpen", "hide");
log.info("{}当前服务商未配置安全发参数", isvNo);
return ApiRes.ok(isvReturnJson);
}
// 商户应用配置是否开启;如果当前应用配置
PayInterfaceConfig infoIdAndIfCode = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.MCH_APP, mchAppEntity.getAppId(), CS.IF_CODE.ALIAQF);
if (infoIdAndIfCode == null || infoIdAndIfCode.getState() != CS.YES) {
JSONObject buttonJson = new JSONObject();
buttonJson.put("isShowButton", "hide");
log.info("{}当前商户应用未开启安全发配置", mchAppEntity.getAppId());
return ApiRes.ok(buttonJson);
}
IAliaqfApiService aliaqfApiService = SpringBeansUtil.getBean(CS.IF_CODE.ALIAQF + "ApiService", IAliaqfApiService.class);
// 1.查询签约结果
String agreementNo = aliaqfApiService.queryUserAgreementPageSign(ALIAQFIsvParams, mchAppId);
String accountBookId = "";
if (StringUtils.isNotEmpty(agreementNo)) {
// 2.资金记账本开通
accountBookId = aliaqfApiService.fundAccountbookCreate(ALIAQFIsvParams, mchAppId, mchAppEntity.getMchNo(), agreementNo);
}
// 更新保存该应用配置
AliaqfIsvsubMchParams mchParams = new AliaqfIsvsubMchParams();
mchParams.setAgreementNo(agreementNo);
mchParams.setAccountBookId(accountBookId);
// 配置信息为空时,不操作保存更新
if (StringUtils.isNotEmpty(agreementNo) || StringUtils.isNotEmpty(accountBookId)) {
PayInterfaceConfig config = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.MCH_APP, mchAppId, CS.IF_CODE.ALIAQF);
if (config != null) {
// 配置参数不为空不做更新处理
AliaqfIsvsubMchParams dbMchParams = JSONObject.parseObject(config.getIfParams(), AliaqfIsvsubMchParams.class);
// 签约码、记账本ID不为空时直接返回数据
if (dbMchParams != null && StringUtils.isNotEmpty(dbMchParams.getAgreementNo()) && StringUtils.isNotEmpty(dbMchParams.getAccountBookId())) {
return ApiRes.ok(dbMchParams);
}
config.setIfParams(JSONObject.toJSONString(mchParams));
} else {
config = new PayInterfaceConfig();
// 账号类型 商户应用类型
config.setInfoType(CS.SYS_ROLE_TYPE.MCH_APP);
// 商户appId
config.setInfoId(mchAppId);
// 支付接口代码
config.setIfCode(CS.IF_CODE.ALIAQF);
// 接口配置参数
config.setIfParams(JSONObject.toJSONString(mchParams));
}
boolean result = payInterfaceConfigService.saveOrUpdate(config);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "请联系开发人员");
}
}
return ApiRes.ok(mchParams);
}
/**
* 记账本信息查询
**/
@PreAuthorize("hasAnyAuthority( 'FUND_ACCOUNTBOOK_QUERY', 'AGREEMENT_PAGE_SIGN' )")
@GetMapping("/fundAccountbookQuery/{mchAppId}")
public ApiRes fundAccountbookQuery(@PathVariable String mchAppId) {
MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
// 权限判断
if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
IAliaqfApiService aliaqfApiService = SpringBeansUtil.getBean(CS.IF_CODE.ALIAQF + "ApiService", IAliaqfApiService.class);
if (aliaqfApiService == null) {
throw new BizException("无支付宝安全发接口");
}
MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfoV2(mchAppEntity.getMchNo(), mchAppEntity.getAppId(),null);
// 查询记账本详情
JSONObject accountBookInfo = aliaqfApiService.fundAccountbookQuery(mchAppConfigContext);
return ApiRes.ok(accountBookInfo);
}
/**
* 资金转账页面
**/
@PreAuthorize("hasAnyAuthority( 'FUND_TRANS_PAGE', 'AGREEMENT_PAGE_SIGN' )")
@PostMapping("/fundTransPage/{mchAppId}/isvNo")
public ApiRes fundTransPage(@PathVariable("mchAppId") String mchAppId,
@PathVariable("isvNo") String isvNo) {
MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
// 充值金额
Long transAmount = getAmountL("transAmount");
// 权限判断
if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
AliaqfIsvParams aliaqfIsvParams = getIsvParams(mchAppEntity.getMchNo(), isvNo);
IAliaqfApiService aliaqfApiService = SpringBeansUtil.getBean(CS.IF_CODE.ALIAQF + "ApiService", IAliaqfApiService.class);
if (aliaqfApiService == null) {
throw new BizException("无支付宝安全发接口");
}
// 资金转账页面
String transPage = aliaqfApiService.fundTransPage(aliaqfIsvParams, mchAppId, getCurrentMchNo(), transAmount);
return ApiRes.ok(transPage);
}
/**
* @author: xiaoyu
* @date: 2023/4/5 11:34
* @describe: 获取支付宝安全发服务商参数
*/
private AliaqfIsvParams getIsvParams(String mchNo, String isvNo) {
MchInfo mchInfo = mchInfoService.getById(mchNo);
if (MchInfo.TYPE_ISVSUB != mchInfo.getType()) {
throw new BizException("仅支持特约商户");
}
AliaqfIsvParams isvParams = (AliaqfIsvParams) configContextQueryService.queryIsvParams(isvNo, CS.IF_CODE.ALIAQF);
if (isvParams == null) {
throw new BizException("服务商未配置参数,请联系平台处理!");
}
return isvParams;
}
}

View File

@@ -0,0 +1,71 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import com.jeequan.jeepay.bizcommons.manage.MchPayPassageConfigManage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchPayPassageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/****
* 新版商户支付通道配置ctrl
*
* @author terrfly
*
* @date 2022/3/30 16:37
*/
@RestController
@RequestMapping("/api/mch/payPassages")
public class MchPayPassageConfigController extends CommonCtrl {
@Autowired private MchPayPassageService mchPayPassageService;
@Autowired private MchPayPassageConfigManage mchPayPassageConfigManage;
/**
* 支付方式 <--> 通道配置
* 左侧列表(支付方式)
*
* **/
@GetMapping
public ApiRes list() {
String appId = getValStringRequired("appId");
String wayCode = getValString("wayCode");
String wayName = getValString("wayName");
String wayType = getValString("wayType");
return mchPayPassageConfigManage.queryPaywayList(appId, wayCode, wayName, wayType,null, getIPage());
}
/**
* 支付方式 <--> 通道配置
* 右侧列表(可用的支付接口)
*
* **/
@GetMapping("/availablePayInterface/{appId}/{wayCode}")
public ApiRes availablePayInterface(@PathVariable("appId") String appId, @PathVariable("wayCode") String wayCode) {
return mchPayPassageConfigManage.availablePayInterface(appId, wayCode);
}
/**
* 更新商户使用的通道信息
*/
@PostMapping("/mchPassage")
@MethodLog(remark = "更新商户支付通道")
public ApiRes updatePassage() {
String appId = getValStringRequired("appId");
String ifCode = getValStringRequired("ifCode");
String wayCode = getValStringRequired("wayCode");
Byte state = getValByteRequired("state");
mchPayPassageService.updateMchPassageState(appId, wayCode, ifCode, state);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,79 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.ctrls.AbstractCtrl;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchVideoCacheEntity;
import com.jeequan.jeepay.service.impl.MchVideoCacheService;
import com.jeequan.jeepay.thirdparty.service.wxchannel.WechatChannelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/mchVideo")
public class MchVideoController extends AbstractCtrl {
@Autowired
private WechatChannelService wechatChannelService;
@Autowired
private MchVideoCacheService mchVideoCacheService;
@PostMapping("/authTask")
public ApiRes auth() {
String mchNo = getValStringRequired("mchNo");
JSONObject task = wechatChannelService.createTask(mchNo);
return ApiRes.ok(task);
}
@GetMapping("/authTask")
public ApiRes taskResult() {
String taskId = getValStringRequired("taskId");
JSONObject taskResult = wechatChannelService.queryTask(taskId);
return ApiRes.ok(taskResult);
}
@GetMapping("/dataList")
public ApiRes cacheList() {
Page<MchVideoCacheEntity> iPage = getIPage();
MchVideoCacheEntity mchInfo = getObject(MchVideoCacheEntity.class);
LambdaQueryWrapper<MchVideoCacheEntity> wrapper = Wrappers.lambdaQuery(mchInfo);
Page<MchVideoCacheEntity> page = mchVideoCacheService.page(iPage, wrapper);
return ApiRes.ok(page);
}
@GetMapping("/randomOne")
public ApiRes randomOne() {
String mchNo = getValStringRequired("mchNo");
MchVideoCacheEntity result = mchVideoCacheService.getRandomOne(mchNo);
return ApiRes.ok(result);
}
@DeleteMapping("/{id}")
public ApiRes remove(@PathVariable("id") Long id) {
mchVideoCacheService.removeById(id);
return ApiRes.ok();
}
@PostMapping("/choiceFlag/{id}")
public ApiRes choiceFlag(@PathVariable("id") Long id) {
String choiceFlag = getValStringRequired("choiceFlag");
mchVideoCacheService.lambdaUpdate()
.eq(MchVideoCacheEntity::getId, id)
.set(MchVideoCacheEntity::getChoiceFlag, choiceFlag)
.update();
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,125 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PackageInfo;
import com.jeequan.jeepay.db.entity.PackageOrder;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/packageInfo")
public class PackageInfoController extends CommonCtrl {
@Autowired private PackageInfoService packageInfoService;
@Autowired private PackageProductService packageProductService;
@Autowired private ProductInfoService productInfoService;
@Autowired private PackageOrderService packageOrderService;
@Autowired private PackageTypeService packageTypeService;
@RequestMapping(value = "/getPackageList", method = RequestMethod.GET)
@MethodLog(remark = "方案中心列表")
public ApiRes getPackageList() throws BizException {
PackageInfo packageInfo = getObject(PackageInfo.class);
Page<PackageInfo> page = new Page<>();
List<PackageInfo> packageInfoList = packageInfoService.getPackageList(packageInfo.getName(),packageInfo.getState(),packageInfo.getPackageType());
page.setRecords(packageInfoList);
page.setTotal(packageInfoList.size());
page.setCurrent(1);
return ApiRes.ok(page);
}
@RequestMapping(value = "/getPackageById", method = RequestMethod.GET)
@MethodLog(remark = "商户端方案详情")
public ApiRes getPackageById() throws BizException {
//获取查询条件
PackageInfo packageInfo = getObject(PackageInfo.class);
PackageInfo info = packageInfoService.getPackageById(packageInfo.getPackageId());
//查询已关联已开通的应用数量,
List<PackageOrder> packageOrderList = packageOrderService.getList(packageInfo.getPackageId(),getCurrentMchNo());
List<String> bindingApp = packageOrderList.stream().map(PackageOrder::getAppId).filter(str-> !str.isEmpty()).distinct().collect(Collectors.toList());
info.setApplyCount(packageOrderList.size());
info.setBindingAppList(bindingApp);
//返回收费信息和剩余天数
List<PackageOrder> packageOrderListSave =new ArrayList<>();
long allRemainingDays = 0L;
for (PackageOrder packageOrder : packageOrderList) {
if (packageOrder.getCostRule() != null){
JSONArray costRule = packageOrder.getCostRule();
//目前规则只能选取一条
int validTime = costRule.getJSONObject(0).getIntValue("validTime");
if (costRule.getJSONObject(0).getDate("autoTime") != null){
LocalDate currentDate = costRule.getJSONObject(0).getDate("autoTime").toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
// 计算到期后的日期
LocalDate futureDate = currentDate.plusDays(validTime);
// 计算剩余天数
LocalDate today = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
long remainingDays = ChronoUnit.DAYS.between(today, futureDate);
packageOrder.setRemainingDays(remainingDays);
//暂时不需要
//productAppListSave.add(productApp);
allRemainingDays += remainingDays;
}
}
}
//暂时不需要
//info.setProductAppList(productAppListSave);
info.setAllRemainingDays(allRemainingDays);
return ApiRes.ok(info);
}
@GetMapping("/getPackageOder")
@MethodLog(remark = "开通记录")
public ApiRes getPackageOder(){
Page<PackageOrder> page=getIPage(true);
PackageOrder packageOrder = getObject(PackageOrder.class);
// 时间搜索
Date[] searchDateRange = packageOrder.buildQueryDateRange();
packageOrder.setFirstDate(searchDateRange[0]);
packageOrder.setLastDate(searchDateRange[1]);
packageOrder.setMchNo(getCurrentMchNo());
Page<PackageOrder> result = packageOrderService.getList(page, packageOrder);
return ApiRes.ok(result);
}
@RequestMapping(value = "/getPackageOderById", method = RequestMethod.GET)
@MethodLog(remark = "开通记录详情")
public ApiRes getPackageOderById() throws BizException {
//获取查询条件
PackageOrder packageOrder = getObject(PackageOrder.class);
PackageOrder serviceById = packageOrderService.getDetail(packageOrder.getId());
return ApiRes.ok(serviceById);
}
@MethodLog(remark = "更新开通记录")
@RequestMapping(value="/{id}", method = RequestMethod.PUT)
public ApiRes reSubmit(@PathVariable("id") String id) {
PackageOrder packageOrder = getObject(PackageOrder.class);
packageOrder.setId(id);//设置主键
packageOrder.setUpdatedAt(new Date());
packageOrder.setState(PackageOrder.STATE_AUDITING);
packageOrderService.updateById(packageOrder);
return ApiRes.ok();
}
@RequestMapping(value = "/getPackageTypeList", method = RequestMethod.GET)
@MethodLog(remark = "获取所有方案分类列表")
public ApiRes getPackageTypeList() throws BizException {
return ApiRes.ok(packageTypeService.list());
}
}

View File

@@ -0,0 +1,178 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.bizcommons.manage.MchStoreTerminalManage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchStoreTerminal;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchAppService;
import com.jeequan.jeepay.service.impl.MchStoreTerminalService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/***
* 终端设备管理
*
* @author terrfly
*
* @date 2022/4/26 17:34
*/
@Slf4j
@RestController
@RequestMapping("/api/mchTerminals")
public class TerminalController extends CommonCtrl {
@Autowired private MchStoreTerminalService mchStoreTerminalService;
@Autowired private MchStoreTerminalManage mchStoreTerminalManage;
@Autowired private MchAppService mchAppService;
@PreAuthorize("hasAuthority('ENT_TERMINAL_LIST')")
@GetMapping
public ApiRes pages() {
// 请求参数
MchStoreTerminal queryObject = getObject(MchStoreTerminal.class);
queryObject.setMchNo(getCurrentMchNo()); //查询当前商户的信息
LambdaQueryWrapper<MchStoreTerminal> gw = MchStoreTerminal.gw();
gw.eq(StringUtils.isNotEmpty(queryObject.getAgentNo()), MchStoreTerminal::getAgentNo, queryObject.getAgentNo());
gw.eq(StringUtils.isNotEmpty(queryObject.getMchNo()), MchStoreTerminal::getMchNo, queryObject.getMchNo());
gw.eq(queryObject.getStoreId() != null, MchStoreTerminal::getStoreId, queryObject.getStoreId());
gw.like(StringUtils.isNotEmpty(queryObject.getTrmNo()), MchStoreTerminal::getTrmNo, queryObject.getTrmNo());
gw.like(StringUtils.isNotEmpty(queryObject.getTrmName()), MchStoreTerminal::getTrmName, queryObject.getTrmName());
gw.eq(queryObject.getTrmType() != null, MchStoreTerminal::getTrmType, queryObject.getTrmType());
gw.eq(queryObject.getState() != null, MchStoreTerminal::getState, queryObject.getState());
// 商户号 / 设备名称 / 设备编号
if(StringUtils.isNotEmpty(getValString("unionSearchId"))){
gw.and(wr ->
wr.like(MchStoreTerminal::getMchNo, getValString("unionSearchId"))
.or().like(MchStoreTerminal::getTrmName, getValString("unionSearchId"))
.or().like(MchStoreTerminal::getTrmNo, getValString("unionSearchId"))
);
}
// 门店条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
if (CollectionUtil.isNotEmpty(storeIdList)) {
gw.in(MchStoreTerminal::getStoreId, storeIdList);
}
gw.orderByDesc(MchStoreTerminal::getCreatedAt);
//返回数据
IPage<MchStoreTerminal> page = mchStoreTerminalService.page(getIPage(), gw);
return ApiRes.page(page);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_TERMINAL_VIEW' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") String recordId) {
MchStoreTerminal terminal = mchStoreTerminalService.getById(recordId);
MchAppEntity mchAppEntity = mchAppService.getById(terminal.getAppId());
terminal.addExt("appName", mchAppEntity.getAppName());
return ApiRes.ok(terminal);
}
/** add */
@PreAuthorize("hasAuthority( 'ENT_TERMINAL_ADD' )")
@MethodLog(remark = "添加商户终端信息")
@RequestMapping(value="", method = RequestMethod.POST)
public ApiRes add() {
MchStoreTerminal mchStoreTerminal = getObject(MchStoreTerminal.class);
mchStoreTerminal.setMchNo(getCurrentMchNo());
// 商户的默认门店
if(StringUtils.isEmpty(mchStoreTerminal.getAppId())){
mchStoreTerminal.setAppId(mchAppService.getDefaultApp(getCurrentMchNo()).getAppId());
}
return mchStoreTerminalManage.add(mchStoreTerminal);
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_TERMINAL_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
@MethodLog(remark = "更新商户终端信息")
public ApiRes update(@PathVariable("recordId") Long recordId) {
MchStoreTerminal record = getObject(MchStoreTerminal.class);
record.setTrmId(recordId);
return mchStoreTerminalManage.update(record);
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_TERMINAL_EDIT' )")
@RequestMapping(value="/trmDefaults", method = RequestMethod.PUT)
@MethodLog(remark = "更新商户终端默认状态")
public ApiRes updateDefault() {
return mchStoreTerminalManage.updateDefault(getValLongRequired("trmId"), getValByteRequired("defaultFlag"));
}
/** delete */
@PreAuthorize("hasAuthority('ENT_TERMINAL_DEL')")
@MethodLog(remark = "删除终端")
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
public ApiRes del(@PathVariable("recordId") String recordId) {
mchStoreTerminalService.removeById(recordId);
return ApiRes.ok();
}
/** 报备列表 */
@PreAuthorize("hasAuthority('ENT_TERMINAL_SENDUP')")
@RequestMapping(value="channelBindInfos/{recordId}", method = RequestMethod.GET)
public ApiRes channelBindInfos(@PathVariable("recordId") Long recordId) {
return mchStoreTerminalManage.getChannelBindInfos(recordId);
}
/** 终端报备 */
@PreAuthorize("hasAuthority('ENT_TERMINAL_SENDUP')")
@MethodLog(remark = "终端报备")
@RequestMapping(value="channelSendup/{recordId}", method = RequestMethod.POST)
public ApiRes channelSendup(@PathVariable("recordId") Long recordId) {
String ifCode = getValStringRequired("ifCode");
Byte state = getValByteRequired("state"); // 0 - 取消报备, 1- 申请报备
return mchStoreTerminalManage.channelSendup(recordId, ifCode, state);
}
/** 修改终端报备信息 */
@PreAuthorize("hasAuthority('ENT_TERMINAL_SENDUP')")
@MethodLog(remark = "自定义终端报备信息")
@RequestMapping(value="channelBindInfos/{recordId}", method = RequestMethod.POST)
public ApiRes updChannelBindInfos(@PathVariable("recordId") Long recordId) {
String ifCode = getValStringRequired("ifCode");
String channelTrmNo = getValStringDefault("channelTrmNo", ""); // 报备信息
Byte state = getValByteRequired("state");
return mchStoreTerminalManage.updChannelBindInfos(recordId, ifCode, channelTrmNo, state);
}
}

View File

@@ -0,0 +1,208 @@
package com.jeequan.jeepay.mch.ctrl.merchant;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.model.DBWxMpConfig;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.MchWxmpUser;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
/**
* 微信公众号提醒配置类
*
* @author zx
*
* @date 2021-10-15 09:15
*/
@RestController
@RequestMapping("/api/wxmp")
public class WxMpUserController extends CommonCtrl {
@Autowired private MchInfoService mchInfoService;
@Autowired private SysConfigService sysConfigService;
@Autowired private MchWxmpUserService mchWxmpUserService;
@Autowired private SysUserService sysUserService;
@Autowired private SysUserMchStoreRelaService sysUserMchStoreRelaService;
/**
* @Author: zx
* @Description: 商户创建微信公众号接收者的显示信息
* @Date: 2021-10-15 09:15
*/
@GetMapping("/getWxmpInfo")
public ApiRes getWxmpInfo() {
MchInfo mchInfo = mchInfoService.getById(getCurrentUser().getSysUser().getBelongInfoId());
DBApplicationConfig applicationConfig = sysConfigService.getDBApplicationConfig();
DBWxMpConfig wxMpConfig = sysConfigService.getDBWxMpConfig();
if(wxMpConfig == null){
throw new BizException("未正确配置微信公众号消息配置项");
}
String mchAuthRedirectUrl = StringUtils.isBlank(wxMpConfig.getMchAuthRedirectUrl()) ? DBWxMpConfig.DEFAULT_WX_AUTH_DOMAIN : wxMpConfig.getMchAuthRedirectUrl();
JSONObject result = new JSONObject();
String authUrl = DBWxMpConfig.mchAuthUrl
.replace("{{mchAuthRedirectUrl}}", mchAuthRedirectUrl)
.replace("{{mchNo}}", mchInfo.getMchNo())
.replace("{{sysUserId}}", String.valueOf(getCurrentUser().getSysUserId()))
.replace("{{appId}}", wxMpConfig.getWxAppId())
.replace("{{paySiteUrl}}", applicationConfig.getPaySiteUrl());
result.put("authQr", applicationConfig.genScanImgUrl(authUrl));
result.put("authUrl", authUrl);
result.put("wxmpQr", wxMpConfig.getWxmpUrl());
return ApiRes.ok(result);
}
/**
* @Author: zx
* @Description: 微信公众号取消关注
* @Date: 2021-10-15 09:15
*/
@GetMapping("/unAuth")
public ApiRes unAuth() {
LambdaUpdateWrapper<MchWxmpUser> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(MchWxmpUser::getMchNo, getCurrentMchNo());
updateWrapper.set(MchWxmpUser::getSendStatus, MchWxmpUser.SEND_STATE_CLOSE);
boolean updateResult = mchWxmpUserService.update(updateWrapper);
if (!updateResult) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 微信公众号消息接收者列表
*/
@PreAuthorize("hasAuthority('ENT_MCH_WXMP_USER_LIST')")
@GetMapping
public ApiRes pages() {
String mchNo = getCurrentMchNo();
SysUserEntity sysUserEntity = sysUserService.getById(getCurrentUser().getSysUserId());
LambdaQueryWrapper<MchWxmpUser> gw = MchWxmpUser.gw();
gw.eq(MchWxmpUser::getMchNo, mchNo);
// 店员只能看自己的授权信息
if (sysUserEntity.getUserType() == SysUser.UEST_TYPE_CASHIER) {
gw.eq(MchWxmpUser::getSysUserId, sysUserEntity.getSysUserId());
}
// 店长只能看自己门店下的授权信息
if (sysUserEntity.getUserType() == SysUser.UEST_TYPE_DIRECTOR) {
List<String> storeIdList = getCurrentUser().getStoreIdList();
Set<Long> sysUserIdSet = sysUserMchStoreRelaService.selectSysUserIdsByStoreIdList(storeIdList);
gw.in(CollUtil.isNotEmpty(sysUserIdSet), MchWxmpUser::getSysUserId, sysUserIdSet);
}
if (StringUtils.isNotBlank(getValString("nickname"))) {
gw.like(MchWxmpUser::getNickname, getValString("nickname"));
}
IPage<MchWxmpUser> page = mchWxmpUserService.page(getIPage(), gw);
//返回数据
return ApiRes.page(page);
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 微信公众号消息接收者修改
*/
@PreAuthorize("hasAuthority('ENT_MCH_WXMP_USER_EDIT')")
@MethodLog(remark = "微信公众号消息接收者修改")
@PutMapping("/{userId}")
public ApiRes update(@PathVariable("userId") Long userId) {
MchWxmpUser mchWxmpUser = getObject(MchWxmpUser.class);
mchWxmpUser.setUserId(userId);
MchWxmpUser dbRecord = mchWxmpUserService.getById(userId);
if (!getCurrentMchNo().equals(dbRecord.getMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
SysUserEntity sysUserEntity = sysUserService.getById(getCurrentUser().getSysUserId());
// 店员只能看自己的授权信息
if (sysUserEntity.getUserType() == SysUser.UEST_TYPE_CASHIER && !dbRecord.getSysUserId().equals(sysUserEntity.getSysUserId())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
// 店长只能看自己门店下的授权信息
if (sysUserEntity.getUserType() == SysUser.UEST_TYPE_DIRECTOR) {
List<String> storeIdList = getCurrentUser().getStoreIdList();
Set<Long> sysUserIdSet = sysUserMchStoreRelaService.selectSysUserIdsByStoreIdList(storeIdList);
if (!sysUserIdSet.contains(dbRecord.getSysUserId())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
}
if(!mchWxmpUserService.updateById(mchWxmpUser)) {
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "更新失败");
}
return ApiRes.ok();
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 微信公众号消息接收者删除
*/
@PreAuthorize("hasAuthority('ENT_MCH_WXMP_USER_DELETE')")
@MethodLog(remark = "微信公众号消息接收者删除")
@DeleteMapping("/{userId}")
public ApiRes delete(@PathVariable("userId") Long userId) {
MchWxmpUser dbRecord = mchWxmpUserService.getById(userId);
if (!getCurrentMchNo().equals(dbRecord.getMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
SysUserEntity sysUserEntity = sysUserService.getById(getCurrentUser().getSysUserId());
// 店员只能看自己的授权信息
if (sysUserEntity.getUserType() == SysUser.UEST_TYPE_CASHIER && !dbRecord.getSysUserId().equals(sysUserEntity.getSysUserId())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
// 店长只能看自己门店下的授权信息
if (sysUserEntity.getUserType() == SysUser.UEST_TYPE_DIRECTOR) {
List<String> storeIdList = getCurrentUser().getStoreIdList();
Set<Long> sysUserIdSet = sysUserMchStoreRelaService.selectSysUserIdsByStoreIdList(storeIdList);
if (!sysUserIdSet.contains(dbRecord.getSysUserId())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
}
if(mchWxmpUserService.removeById(userId)) {
return ApiRes.ok();
}
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_DELETE);
}
}

View File

@@ -0,0 +1,365 @@
package com.jeequan.jeepay.mch.ctrl.order;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.MchModifyApplyment;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.device.IPrinterService;
import com.jeequan.jeepay.core.interfaces.paychannel.IRefundService;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBOSSConfig;
import com.jeequan.jeepay.core.model.device.PayOrderInfo4Device;
import com.jeequan.jeepay.core.model.export.MchPayOrderExportExcel;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRefundLimit;
import com.jeequan.jeepay.core.utils.*;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.model.PayOrderQueryReqModel;
import com.jeequan.jeepay.model.PayOrderQueryResModel;
import com.jeequan.jeepay.model.RefundOrderCreateReqModel;
import com.jeequan.jeepay.request.PayOrderQueryRequest;
import com.jeequan.jeepay.request.RefundOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderQueryResponse;
import com.jeequan.jeepay.response.RefundOrderCreateResponse;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.util.*;
/**
* 支付订单管理类
*
* @author zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("/api/payOrder")
public class PayOrderController extends CommonCtrl {
@Autowired private PayOrderService payOrderService;
@Autowired private PayWayService payWayService;
@Autowired private MchAppService mchAppService;
@Autowired private SysConfigService sysConfigService;
@Autowired private MchStoreDeviceService mchStoreDeviceService;
@Autowired private MchInfoService mchInfoService;
@Autowired private StatsTradeService statsTradeService;
@Autowired private SysUserService sysUserService;
@Autowired private MchModifyApplymentService mchModifyApplymentService;
/**
* @Author: ZhuXiao
* @Description: 订单信息列表
* @Date: 10:43 2021/5/13
*/
@PreAuthorize("hasAuthority('ENT_ORDER_LIST')")
@GetMapping
public ApiRes list() {
PayOrder payOrder = getObject(PayOrder.class);
JSONObject paramJSON = getReqParamJSON();
payOrder.setMchNo(getCurrentMchNo());
// 门店条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
if (CollectionUtil.isNotEmpty(storeIdList)) {
payOrder.setStoreIdList(storeIdList);
}
IPage<PayOrder> pages = payOrderService.listByPage(getIPage(), payOrder, paramJSON);
return ApiRes.page(pages);
}
/**
* @Author: ZhuXiao
* @Description: 支付订单信息
* @Date: 10:43 2021/5/13
*/
@PreAuthorize("hasAuthority('ENT_PAY_ORDER_VIEW')")
@GetMapping("/{payOrderId}")
public ApiRes detail(@PathVariable("payOrderId") String payOrderId) {
PayOrder payOrder = payOrderService.getDetails(payOrderId);
if (payOrder == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if (!payOrder.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
if (StringUtils.isNotBlank(payOrder.getChannelOrderNo())) {
DBOSSConfig ossConfig = sysConfigService.getOssConfig();
payOrder.addExt("channelOrderNoBar", ossConfig.getOssPublicSiteUrl() + "/bar/" + payOrder.getChannelOrderNo());
}
if (payOrder.getStoreUserId() != null) {
SysUserEntity sysUserEntity = sysUserService.getById(payOrder.getStoreUserId());
payOrder.addExt("storeUserName", sysUserEntity.getRealname());
}
return ApiRes.ok(payOrder);
}
/**
* 是否支持平台户退款
* @param payOrderId
* @return
*/
@GetMapping("/refunds/limit/{payOrderId}")
public ApiRes isPlatCheck(@PathVariable("payOrderId") String payOrderId) {
PayOrder payOrder = payOrderService.getById(payOrderId);
if (payOrder == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
//获取退款接口
IRefundService refundService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(payOrder.getIfCode()) + "RefundService", IRefundService.class);
if(refundService == null){
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR,"未获取到退款接口");
}
ChannelRefundLimit refundLimit = refundService.isRefundLimit(payOrder.getSettleType(), payOrder.getMchExtNo());
return ApiRes.ok(refundLimit);
}
/**
* 平台账户申请接口
* @param payOrderId
* @return
*/
@PostMapping("/refunds/apply/{payOrderId}")
public ApiRes applyRefund(@PathVariable("payOrderId") String payOrderId) {
PayOrder payOrder = payOrderService.getById(payOrderId);
if (payOrder == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
//获取退款接口
IRefundService refundService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(payOrder.getIfCode()) + "RefundService", IRefundService.class);
if(refundService == null){
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR,"未获取到退款接口");
}
ChannelRefundLimit refundLimit = refundService.isRefundLimit(payOrder.getSettleType(), payOrder.getMchExtNo());
if(refundLimit.getIsPlatAccount() && ChannelRefundLimit.SUCCESS == refundLimit.getBindStatus()){
throw new BizException("当前通道支持平台退款,无需重复申请");
}
mchModifyApplymentService.commonApply(getCurrentMchNo(),payOrder.getMchExtNo(),MchModifyApplyment.MODIFY_TYPE_REFUND_ACCOUNT_TYPE);
return ApiRes.ok();
}
/**
* 发起订单退款
* @author terrfly
*
* @date 2021/6/17 16:38
*/
@MethodLog(remark = "发起订单退款")
@PreAuthorize("hasAuthority('ENT_PAY_ORDER_REFUND')")
@PostMapping("/refunds/{payOrderId}")
public ApiRes refund(@PathVariable("payOrderId") String payOrderId) {
Long refundAmount = getRequiredAmountL("refundAmount");
String refundReason = getValStringRequired("refundReason");
String refundPassword = Base64.decodeStr(getValStringRequired("refundPassword"));
//退款模式 “1”收款商户号退款,"2"平台一般户退款
String refundModel = getValStringRequired("refundModel");
//验证当前密码是否正确
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
if(StringUtils.isEmpty(mchInfo.getSipw())){
throw new BizException("当前未设置支付密码,请进入[账号中心-系统配置-安全管理]设置支付密码");
}
if(!new BCryptPasswordEncoder().matches(refundPassword, mchInfo.getSipw())){
throw new BizException("支付密码验证失败!");
}
PayOrder payOrder = payOrderService.getById(payOrderId);
if (payOrder == null || !payOrder.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if(payOrder.getState() != PayOrder.STATE_SUCCESS && PayOrder.REFUND_STATE_ALL == payOrder.getRefundState()){
throw new BizException("订单状态不正确");
}
if(payOrder.getRefundAmount() + refundAmount > payOrder.getAmount()){
throw new BizException("退款金额超过订单可退款金额!");
}
if (!mchInfo.getRefundMode().contains(MchInfo.REFUND_MODEL_PLAT)) {
throw new BizException("无退款权限!");
}
RefundOrderCreateRequest request = new RefundOrderCreateRequest();
RefundOrderCreateReqModel model = new RefundOrderCreateReqModel();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
model.setExtParam(refundModel);
request.setBizModel(model);
model.setMchNo(payOrder.getMchNo()); // 商户号
model.setAppId(payOrder.getAppId());
model.setPayOrderId(payOrderId);
model.setMchRefundNo(SeqKit.genMhoOrderId());
model.setRefundAmount(refundAmount);
model.setRefundReason(refundReason);
model.setCurrency("CNY");
String paySiteUrl = sysConfigService.getDBApplicationConfig().getPaySiteUrl();
// String paySiteUrl = "http://192.168.1.24:9216";
MchAppEntity mchAppEntity = mchAppService.getById(payOrder.getAppId());
JeepayClient jeepayClient = new JeepayClient(paySiteUrl, mchAppEntity.getAppSecret());
try {
RefundOrderCreateResponse response = jeepayClient.execute(request);
if(response.getCode() != 0){
throw new BizException(response.getMsg());
}
return ApiRes.ok(response.get());
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
@MethodLog(remark = "订单状态刷新")
@PreAuthorize("hasAuthority('ENT_PAY_ORDER_REFRESH')")
@PostMapping("/refresh/{payOrderId}")
public ApiRes refresh(@PathVariable("payOrderId") String payOrderId) {
PayOrder payOrder = payOrderService.getById(payOrderId);
if(payOrder == null){
throw new BizException("订单数据异常");
}
if(PayOrder.STATE_ING != payOrder.getState()){
throw new BizException("订单状态不支持该操作");
}
MchAppEntity mchAppEntity = mchAppService.getById(payOrder.getAppId());
PayOrderQueryRequest request = new PayOrderQueryRequest();
PayOrderQueryReqModel model = new PayOrderQueryReqModel();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
model.setMchNo(payOrder.getMchNo()); // 商户号
model.setAppId(payOrder.getAppId());
model.setPayOrderId(payOrderId);
request.setBizModel(model);
JeepayClient jeepayClient = new JeepayClient(sysConfigService.getDBApplicationConfig().getPaySiteUrl(), mchAppEntity.getAppSecret());
try {
PayOrderQueryResponse response = jeepayClient.execute(request);
if(response.getCode() != 0){
throw new BizException(response.getMsg());
}
PayOrderQueryResModel respData = response.get();
if(respData.getState() == PayOrder.STATE_SUCCESS){
return ApiRes.ok("订单刷新成功");
}
return ApiRes.customFail("订单状态一致,无需当前操作");
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
/**
* @author: xiaoyu
* @date: 2022/2/10 17:00
* @describe: 订单列表统计
*/
@PreAuthorize("hasAuthority('ENT_ORDER_COUNT')")
@RequestMapping(value="/count", method = RequestMethod.GET)
public ApiRes count() {
PayOrder payOrder = getObject(PayOrder.class);
payOrder.setMchNo(getCurrentMchNo());
JSONObject paramJSON = getReqParamJSON();
paramJSON.put("mchNo", getCurrentMchNo());
// 门店ID条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
paramJSON.put("storeIdList", storeIdList);
// 查询支付、退款金额 笔数
PayOrderCount orderCount = statsTradeService.selectTotalByTransaction(paramJSON, null);
return ApiRes.ok(orderCount);
}
/**
* @author: xiaoyu
* @date: 2022/1/14 9:45
* @describe: 订单列表数据导出
*/
@RequestMapping(value="/exportExcel", method = RequestMethod.GET)
public void exportExcel() {
try {
PayOrder payOrder = getObject(PayOrder.class);
payOrder.setMchNo(getCurrentMchNo());
JSONObject paramJSON = getReqParamJSON();
IPage<PayOrder> pages = payOrderService.listByPage(getIPage(true), payOrder, paramJSON);
List<JSONObject> newList = new LinkedList<>();
for (PayOrder order:pages.getRecords()) {
JSONObject object = (JSONObject) JSONObject.toJSON(order);
object.put("amount", AmountUtil.convertCent2Dollar(order.getAmount()));
object.put("refundAmount", AmountUtil.convertCent2Dollar(order.getRefundAmount()));
object.put("mchFeeAmount", AmountUtil.convertCent2Dollar(order.getMchFeeAmount()));
object.put("mchOrderFeeAmount", AmountUtil.convertCent2Dollar(order.getMchOrderFeeAmount()));
newList.add(object);
}
List<MchPayOrderExportExcel> linkedList = JSONArray.parseArray(JSONArray.toJSONString(newList), MchPayOrderExportExcel.class);
// excel输出
ExcelUtil.exportExcel(linkedList, "支付订单", "支付订单", MchPayOrderExportExcel.class, "支付订单", response);
}catch (Exception e) {
logger.error("导出excel失败", e);
throw new BizException("导出订单失败!");
}
}
/**
* @Author: ZhuXiao
* @Description: 订单打印
* @Date: 10:43 2022/01/13
*/
@PreAuthorize("hasAuthority('ENT_PAY_ORDER_VIEW')")
@GetMapping("/print/{payOrderId}")
public ApiRes print(@PathVariable("payOrderId") String payOrderId) {
PayOrder payOrder = payOrderService.getById(payOrderId);
if (payOrder == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if (!payOrder.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
PayOrderInfo4Device printPayOrderInfo = new PayOrderInfo4Device();
BeanUtil.copyProperties(payOrder, printPayOrderInfo);
try {
// 查询打印设备
List<JSONObject> deviceList = mchStoreDeviceService.selectAvailableDeviceList(payOrder.getMchNo(), payOrder.getStoreId(), Arrays.asList(DeviceProvideConfig.DEVICE_TYPE_PRINTER));
if (CollectionUtils.isEmpty(deviceList)) {
return ApiRes.customFail("打印机未配置");
}
// 循环调用单个设备播报
for (JSONObject deviceParams : deviceList) {
// 设备类型
String provider = deviceParams.getString("provider");
IPrinterService printerService = SpringBeansUtil.getBean(provider + "PrinterService", IPrinterService.class);
printerService.send(deviceParams, printPayOrderInfo);
}
return ApiRes.ok();
} catch (BizException e) {
throw e;
}
}
}

View File

@@ -0,0 +1,177 @@
package com.jeequan.jeepay.mch.ctrl.order;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.export.MchRefundOrderExportExcel;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.ExcelUtil;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 退款订单管理类
*
* @author zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("/api/refundOrder")
public class RefundOrderController extends CommonCtrl {
@Autowired private RefundOrderService refundOrderService;
@Autowired private PayInterfaceDefineService payInterfaceDefineService;
@Autowired private MchAppService mchAppService;
@Autowired private PayOrderService payOrderService;
@Autowired private IsvInfoService isvInfoService;
@Autowired private StatsTradeService statsTradeService;
/**
* @Author: ZhuXiao
* @Description: 退款订单信息列表
* @Date: 10:44 2021/5/13
*/
@PreAuthorize("hasAuthority('ENT_REFUND_LIST')")
@GetMapping
public ApiRes list() {
RefundOrder refundOrder = getObject(RefundOrder.class);
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<RefundOrder> wrapper = RefundOrder.gw();
wrapper.eq(RefundOrder::getMchNo, getCurrentMchNo());
// 门店条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
if (CollectionUtil.isNotEmpty(storeIdList)) {
wrapper.in(RefundOrder::getStoreId, storeIdList);
}
IPage<RefundOrder> pages = refundOrderService.pageList(getIPage(), wrapper, refundOrder, paramJSON);
Map<String, String> ifCodeMap = new HashMap<>();
List<PayInterfaceDefine> list = payInterfaceDefineService.list();
if(!list.isEmpty()){
for (PayInterfaceDefine define:list) {
ifCodeMap.put(define.getIfCode(), define.getIfName());
}
}
for (RefundOrder order:pages.getRecords()) {
if(StringUtils.isNotBlank(order.getIfCode())){
order.setIfName(ifCodeMap.get(order.getIfCode()));
}
}
return ApiRes.page(pages);
}
/**
* @Author: ZhuXiao
* @Description: 退款订单信息
* @Date: 10:44 2021/5/13
*/
@PreAuthorize("hasAuthority('ENT_REFUND_ORDER_VIEW')")
@GetMapping("/{refundOrderId}")
public ApiRes detail(@PathVariable("refundOrderId") String refundOrderId) {
RefundOrder refundOrder = refundOrderService.getById(refundOrderId);
if (refundOrder == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if (!refundOrder.getMchNo().equals(getCurrentUser().getSysUser().getBelongInfoId())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
return ApiRes.ok(refundOrder);
}
/**
* @author: xiaoyu
* @date: 2022/1/14 9:45
* @describe: 退款列表数据导出
*/
@RequestMapping(value="/exportExcel", method = RequestMethod.GET)
public void exportExcel() {
try {
RefundOrder refundOrder = getObject(RefundOrder.class);
refundOrder.setMchNo(getCurrentMchNo());
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<RefundOrder> wrapper = RefundOrder.gw();
IPage<RefundOrder> pages = refundOrderService.pageList(getIPage(true), wrapper, refundOrder, paramJSON);
List<JSONObject> newList = new LinkedList<>();
for (RefundOrder order:pages.getRecords()) {
JSONObject object = (JSONObject) JSONObject.toJSON(order);
object.put("payAmount", AmountUtil.convertCent2Dollar(order.getPayAmount()));
object.put("refundAmount", AmountUtil.convertCent2Dollar(order.getRefundAmount()));
object.put("refundFeeAmount", AmountUtil.convertCent2Dollar(order.getRefundFeeAmount()));
//增加订单表数据
PayOrder payOrder = payOrderService.getById(order.getPayOrderId());
if (payOrder != null){
object.put("platformOrderNo", payOrder.getPlatformOrderNo());
object.put("mchOrderNo", payOrder.getMchOrderNo());
object.put("platformMchOrderNo", payOrder.getPlatformMchOrderNo());
}
//增加应用数据
if (StringUtils.isNotEmpty(order.getAppId())){
MchAppEntity mchAppEntity = mchAppService.getById(order.getAppId());
if (mchAppEntity != null){
object.put("appName", mchAppEntity.getAppName());
}
}
//增加支付接口数据
if (StringUtils.isNotEmpty(order.getIfCode())){
PayInterfaceDefine payInterfaceDefine = payInterfaceDefineService.getById(order.getIfCode());
if (payInterfaceDefine != null){
object.put("ifName", payInterfaceDefine.getIfName());
}
}
//增加渠道数据
if (StringUtils.isNotEmpty(order.getIsvNo())){
IsvInfoEntity isvInfoEntity = isvInfoService.getById(order.getIsvNo());
if (isvInfoEntity != null){
object.put("isvName", isvInfoEntity.getIsvName());
}
}
newList.add(object);
}
List<MchRefundOrderExportExcel> linkedList = JSONArray.parseArray(JSONArray.toJSONString(newList), MchRefundOrderExportExcel.class);
// excel输出
ExcelUtil.exportExcel(linkedList, "退款订单", "退款订单", MchRefundOrderExportExcel.class, "退款订单", response);
}catch (Exception e) {
logger.error("导出excel失败", e);
throw new BizException("导出订单失败!");
}
}
/**
* 获取退款统计数据
* @return
*/
@GetMapping("/count")
public ApiRes count(){
JSONObject paramJSON = getReqParamJSON();
paramJSON.put("mchNo",getCurrentMchNo());
// 查询支付、退款金额 笔数
PayOrderCount resMap = statsTradeService.selectTotalByTransaction(paramJSON, null);
return ApiRes.ok(resMap);
}
}

View File

@@ -0,0 +1,116 @@
package com.jeequan.jeepay.mch.ctrl.order;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.export.MchTransferOrderExportExcel;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.ExcelUtil;
import com.jeequan.jeepay.db.entity.TransferOrderEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.TransferOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 转账订单api
*
* @author terrfly
*
* @date 2021/8/13 10:52
*/
@RestController
@RequestMapping("/api/transferOrders")
public class TransferOrderController extends CommonCtrl {
@Autowired private TransferOrderService transferOrderService;
/** list **/
@PreAuthorize("hasAuthority('ENT_TRANSFER_ORDER_LIST')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
TransferOrderEntity transferOrder = getObject(TransferOrderEntity.class);
transferOrder.setMchNo(getCurrentMchNo());
IPage<TransferOrderEntity> pages = transferOrderService.pageList(getIPage(), transferOrder);
return ApiRes.page(pages);
}
/** detail **/
@PreAuthorize("hasAuthority('ENT_TRANSFER_ORDER_VIEW')")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") String transferId) {
TransferOrderEntity refundOrder = transferOrderService.queryMchOrder(getCurrentMchNo(), null, transferId);
if (refundOrder == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(refundOrder);
}
/**
* @author: xiaoyu
* @date: 2022/1/14 9:45
* @describe: 转账数据导出
*/
@RequestMapping(value="/exportExcel", method = RequestMethod.GET)
public void exportExcel() {
try {
TransferOrderEntity transferOrder = getObject(TransferOrderEntity.class);
transferOrder.setMchNo(getCurrentMchNo());
IPage<TransferOrderEntity> pages = transferOrderService.pageList(getIPage(true), transferOrder);
List<JSONObject> newList = new LinkedList<>();
for (TransferOrderEntity order:pages.getRecords()) {
JSONObject object = (JSONObject) JSONObject.toJSON(order);
object.put("entryType", order.getEntryType().replaceAll("_",""));
object.put("amount", AmountUtil.convertCent2Dollar(order.getAmount()));
newList.add(object);
}
List<MchTransferOrderExportExcel> linkedList = JSONArray.parseArray(JSONArray.toJSONString(newList), MchTransferOrderExportExcel.class);
// excel输出
ExcelUtil.exportExcel(linkedList, "转账订单", "转账订单", MchTransferOrderExportExcel.class, "转账订单", response);
}catch (Exception e) {
logger.error("导出excel失败", e);
throw new BizException("导出订单失败!");
}
}
/**
* @author: xiaoyu
* @date: 2023/4/26 14:55
* @describe: 数据统计
*/
@PreAuthorize("hasAuthority('ENT_TRANSFER_ORDER_COUNT')")
@RequestMapping(value="/count", method = RequestMethod.GET)
public ApiRes count() {
TransferOrderEntity transferOrder = getObject(TransferOrderEntity.class);
LambdaQueryWrapper<TransferOrderEntity> wrapper = TransferOrderEntity.gw();
// 商户号
transferOrder.setMchNo(getCurrentMchNo());
transferOrder.setState(null);
// 条件参数
transferOrderService.selectParams(wrapper, transferOrder);
Map result = transferOrderService.queryCount(wrapper);
return ApiRes.ok(result);
}
}

View File

@@ -0,0 +1,298 @@
package com.jeequan.jeepay.mch.ctrl.payconfig;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.params.NormalMchParams;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
/***
* 支付配置
*
* @author terrfly
*
* @date 2022/3/21 0:13
*/
@RestController
@RequestMapping("/api/payConfig")
public class PayConfigController extends CommonCtrl {
@Autowired
private MchInfoService mchInfoService;
@Autowired
private MchAppService mchAppService;
@Autowired
private PayInterfaceDefineService payInterfaceDefineService;
@Autowired
private PayInterfaceConfigService payInterfaceConfigService;
@Autowired
private RateConfigService rateConfigService;
@Autowired
private IMQSender mqSender;
@Autowired
private IsvUserConnService isvUserConnService;
/**
* 查询可用的支付接口
* <p>
* 使用功能项目: 参数及费率的填写
* 服务商查询全部支付接口
* 服务商查询服务商开启的支付接口
**/
@PreAuthorize("hasAnyAuthority( 'ENT_MCH_APP_PAY_CONFIG', 'ENT_MCH_APPLYMENT' )")
@GetMapping("/ifCodes")
public ApiRes ifCodes() {
// 搜索条件
String ifName = getValString("ifName");
String infoId = getValStringRequired("infoId"); // infoId
String configMode = getValStringRequired("configMode"); // 设置类型
Integer range = getValInteger("range");
String mccCode = getValString("mccCode");
// 支付接口列表
LambdaQueryWrapper<PayInterfaceDefine> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.eq(PayInterfaceDefine::getState, CS.YES); // 查询可用的支付接口列表
lambdaQueryWrapper.like(StringUtils.isNotEmpty(ifName), PayInterfaceDefine::getIfName, ifName);
String infoType = CS.SYS_ROLE_TYPE.MCH_APP;
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
if (mchInfo.getType() == CS.MCH_TYPE_ISVSUB) {
// 商户进件模式
if (RateConfig.CONFIG_MODE_MCHAPPLYMENT.equals(configMode)) {
// 查询 服务商 or 服务商开通的支付接口
lambdaQueryWrapper.eq(PayInterfaceDefine::getIsSupportApplyment, CS.YES); // 查询可用的支付接口列表
lambdaQueryWrapper.eq(PayInterfaceDefine::getIsOpenApplyment, CS.YES); // 查询 开启的
Set<String> ifCodes = new HashSet<>();
// 获取关联的渠道信息
// 获取关联的渠道信息
List<String> isvList = isvUserConnService.lambdaQuery()
.eq(IsvUserConnEntity::getInfoType, CS.SYS_ROLE_TYPE.MCH)
.eq(IsvUserConnEntity::getStatus, CS.YES)
.eq(IsvUserConnEntity::getInfoId, mchInfo.getMchNo())
.list()
.stream().map(IsvUserConnEntity::getIsvNo).collect(Collectors.toList());
if (isvList.isEmpty()) {
return ApiRes.ok(new ArrayList<>());
}
// 根据渠道号获取ifCode
QueryWrapper<PayInterfaceConfig> query = Wrappers.query();
// 去重
query.select("DISTINCT")
.lambda()
.select(PayInterfaceConfig::getIfCode)
.eq(PayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.ISV)
.in(PayInterfaceConfig::getInfoId, isvList)
.eq(PayInterfaceConfig::getState, CS.YES)
.eq(PayInterfaceConfig::getIsOpenApplyment, CS.YES);
payInterfaceConfigService.list(query).forEach(r -> ifCodes.add(r.getIfCode()));
if (ifCodes.isEmpty()) {
return ApiRes.ok(new ArrayList<>());
}
lambdaQueryWrapper.in(PayInterfaceDefine::getIfCode, ifCodes); // 查询可用的支付接口列表
} else { // 特约商户无需配置
return ApiRes.ok(new ArrayList<>());
}
} else {
// 普通商户
lambdaQueryWrapper.eq(PayInterfaceDefine::getIsMchMode, CS.YES); //支持普通商户模式
}
lambdaQueryWrapper.orderByAsc(PayInterfaceDefine::getCreatedAt);
List<PayInterfaceDefine> list = payInterfaceDefineService.list(lambdaQueryWrapper);
if (list.isEmpty()) {
return ApiRes.ok(list);
}
Map<String, Byte> stateMap = new HashMap<>();
payInterfaceConfigService.lambdaQuery().select(PayInterfaceConfig::getIfCode, PayInterfaceConfig::getState)
.eq(PayInterfaceConfig::getInfoId, infoId)
.eq(PayInterfaceConfig::getInfoType, infoType)
.list().forEach(r -> stateMap.put(r.getIfCode(), r.getState()));
list.forEach(r -> {
// 是否已配置
if (RateConfig.CONFIG_MODE_MGRAGENT.equals(configMode)) { // 服务商查询的就是已经配置的接口,无需填入
r.addExt("configState", stateMap.get(r.getIfCode()));
} else {
r.addExt("configState", ObjectUtil.defaultIfNull(stateMap.get(r.getIfCode()), 1));
}
//返回json数据
if (StringUtils.isNotEmpty(r.getChannelTypes())){
try {
JSONArray jsonObject = JSON.parseArray("[" + r.getChannelTypes() + "]");
r.setJsonChannelTypes(jsonObject);
}catch (Exception e){
r.setJsonChannelTypes(new JSONArray());
}
}
});
return ApiRes.ok(list);
}
/**
* 查询已经配置的参数信息
**/
@GetMapping(value = "/interfaceSavedConfigs")
public ApiRes interfaceSavedConfigs() {
MchInfo mchInfoSelf = mchInfoService.getById(getCurrentMchNo());
if (mchInfoSelf.getType() == CS.MCH_TYPE_ISVSUB) {
throw new BizException("特约商户,无需配置");
}
String ifCode = getValStringRequired("ifCode"); // ifCode
String infoId = getValStringRequired("infoId"); // infoId
String configMode = getValStringRequired("configMode"); // 设置类型
PayInterfaceDefine payInterfaceDefine = payInterfaceDefineService.getById(ifCode);
String infoType = null;
JSONArray ifDefineArray = null;
Byte mchType = CS.MCH_TYPE_NORMAL; // 商户类型
// 配置商户应用信息
if (RateConfig.CONFIG_MODE_MCHSELFAPP1.equals(configMode)) {
infoType = CS.SYS_ROLE_TYPE.MCH_APP;
ifDefineArray = JSONArray.parseArray(payInterfaceDefine.getNormalMchParams());
}
// 查询已经配置的信息
PayInterfaceConfig payInterfaceConfig = payInterfaceConfigService.getByInfoIdAndIfCode(infoType, infoId, ifCode);
if (payInterfaceConfig == null) {
payInterfaceConfig = new PayInterfaceConfig();
}
// 处理脱敏数据
if (StringUtils.isNotEmpty(payInterfaceConfig.getIfParams())) {
NormalMchParams isvParams = NormalMchParams.factory(ifCode, payInterfaceConfig.getIfParams());
if (isvParams != null) {
payInterfaceConfig.setIfParams(isvParams.deSenData());
}
}
payInterfaceConfig.addExt("ifDefineArray", ifDefineArray);
payInterfaceConfig.addExt("mchType", mchType);
payInterfaceConfig.addExt("configPageType", payInterfaceDefine.getConfigPageType());
return ApiRes.ok(payInterfaceConfig);
}
/**
* 更新支付参数
**/
@PostMapping("/interfaceParams")
@MethodLog(remark = "更新支付参数")
public ApiRes saveOrUpdate() {
MchInfo mchInfoSelf = mchInfoService.getById(getCurrentMchNo());
if (mchInfoSelf.getType() == CS.MCH_TYPE_ISVSUB) {
throw new BizException("特约商户,无需配置");
}
PayInterfaceConfig payInterfaceConfig = getObject(PayInterfaceConfig.class);
String configMode = payInterfaceConfig.extv().getString("configMode"); // 设置类型
String infoType = CS.SYS_ROLE_TYPE.MCH_APP;
payInterfaceConfig.setInfoType(infoType);
//添加更新者信息
Long userId = getCurrentUser().getSysUser().getSysUserId();
String realName = getCurrentUser().getSysUser().getRealname();
payInterfaceConfig.setUpdatedUid(userId);
payInterfaceConfig.setUpdatedBy(realName);
//根据 服务商号、接口类型 获取商户参数配置
PayInterfaceConfig dbRecoed = payInterfaceConfigService.getByInfoIdAndIfCode(payInterfaceConfig.getInfoType(), payInterfaceConfig.getInfoId(), payInterfaceConfig.getIfCode());
//若配置存在为saveOrUpdate添加ID第一次配置添加创建者
if (dbRecoed != null) {
payInterfaceConfig.setId(dbRecoed.getId());
// 合并支付参数
payInterfaceConfig.setIfParams(StringKit.marge(dbRecoed.getIfParams(), payInterfaceConfig.getIfParams(), dbRecoed.getIfCode()));
} else {
payInterfaceConfig.setCreatedUid(userId);
payInterfaceConfig.setCreatedBy(realName);
}
boolean result = payInterfaceConfigService.saveOrUpdate(payInterfaceConfig);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "配置失败");
}
return ApiRes.ok();
}
@GetMapping("/existPayParams/{appId}/{ifCode}")
public ApiRes existPayParams(@PathVariable("appId") String appId, @PathVariable("ifCode") String ifCode) {
// RateConfig param = getObject(RateConfig.class);
//
// // 应用参数配置
// PayInterfaceConfig interfaceConfig = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.MCH_APP, appId, ifCode);
// if (interfaceConfig == null) {
// return ApiRes.ok();
// }
//
// if (StringUtils.isNotBlank(interfaceConfig.getIfParams()) && !interfaceConfig.getIfParams().equals("{}")) {
// return ApiRes.ok(JsonKit.newJson("existMchParams", CS.YES));
// }
//
// // 费率配置
// Map<String, PaywayFee> paywayFeeMap = rateConfigService.queryPaywayFeeMap(appId + "_" + RateConfig.MCHRATE, CS.SYS_ROLE_TYPE.MCH_APP, param.getIfCode(), param.getRange(), param.getMccCode(), param.getIsvNo());
// if (paywayFeeMap != null && StringUtils.isNotBlank(interfaceConfig.getIfParams()) && !interfaceConfig.getIfParams().equals("{}")) {
// return ApiRes.ok(JsonKit.newJson("existMchParams", CS.YES));
// }
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,70 @@
package com.jeequan.jeepay.mch.ctrl.payconfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.IsvUserConn;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.PayInterfaceDefine;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.IsvInfoService;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import com.jeequan.jeepay.service.impl.PayInterfaceDefineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* 支付接口定义管理类
*
* @author zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("api/payIfDefines")
public class PayInterfaceDefineController extends CommonCtrl {
@Autowired private PayInterfaceDefineService payInterfaceDefineService;
@Autowired private PayInterfaceConfigService payInterfaceConfigService;
@Autowired private MchInfoService mchInfoService;
@Autowired
private IsvInfoService isvInfoService;
/**
* @Author: ZhuXiao
* @Description: list
* @Date: 15:51 2021/4/27
*/
@GetMapping
public ApiRes list() {
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
PayInterfaceDefine queryRecord = getObject(PayInterfaceDefine.class);
LambdaQueryWrapper<PayInterfaceDefine> lambdaQueryWrapper = PayInterfaceDefine.gw();
lambdaQueryWrapper.eq(queryRecord.getState() != null , PayInterfaceDefine::getState, queryRecord.getState());
lambdaQueryWrapper.eq(queryRecord.getIsSupportApplyment() != null , PayInterfaceDefine::getIsSupportApplyment, queryRecord.getIsSupportApplyment());
lambdaQueryWrapper.orderByAsc(PayInterfaceDefine::getCreatedAt);
Map<String, IsvUserConn> isvConnMap = isvInfoService.getIsvUserConn(CS.SYS_ROLE_TYPE.MCH, mchInfo.getMchNo(), CS.YES);
if (isvConnMap.isEmpty()) {
return ApiRes.ok(Collections.emptyList());
}
// 过滤掉当前商户的所属服务商的配置没有填写或开通的接口。
List<PayInterfaceDefine> list = payInterfaceDefineService.lambdaQuery()
.in(PayInterfaceDefine::getIfCode, isvConnMap.keySet()).list();
return ApiRes.ok(list);
}
}

View File

@@ -0,0 +1,111 @@
package com.jeequan.jeepay.mch.ctrl.payconfig;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.oauth2.Oauth2Params;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.db.entity.PayInterfaceConfig;
import com.jeequan.jeepay.db.entity.RateConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchAppService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/***
* oauth2配置
*
* @author terrfly
*
* @date 2022/11/9 17:01
*/
@RestController
@RequestMapping("/api/payOauth2Config")
public class PayOauth2ConfigController extends CommonCtrl {
@Autowired private MchAppService mchAppService;
@Autowired private PayInterfaceConfigService payInterfaceConfigService;
@Autowired private IMQSender mqSender;
/** 查询已经配置的参数信息
*
* **/
@GetMapping(value="/savedConfigs")
public ApiRes interfaceSavedConfigs() {
String ifCode = getValStringRequired("ifCode"); // ifCode
String infoId = getValStringRequired("infoId"); // infoId
String configMode = getValStringRequired("configMode"); // 设置类型
String infoType = null;
// 普通商户的配置
if(RateConfig.CONFIG_MODE_MCHSELFAPP1.equals(configMode)){
infoType = CS.SYS_ROLE_TYPE.MCH_APP_OAUTH2;
}
// 查询已经配置的信息
PayInterfaceConfig payInterfaceConfig = payInterfaceConfigService.getByInfoIdAndIfCode(infoType, infoId, ifCode);
if(payInterfaceConfig == null){
payInterfaceConfig = new PayInterfaceConfig();
}
// 处理脱敏数据
if(StringUtils.isNotEmpty(payInterfaceConfig.getIfParams())){
Oauth2Params isvParams = Oauth2Params.factory(ifCode, payInterfaceConfig.getIfParams());
if (isvParams != null) {
payInterfaceConfig.setIfParams(isvParams.deSenData());
}
}
return ApiRes.ok(payInterfaceConfig);
}
/** 更新支付参数 **/
@PostMapping("/configParams")
@MethodLog(remark = "更新oauth2参数")
public ApiRes saveOrUpdate() {
PayInterfaceConfig payInterfaceConfig = getObject(PayInterfaceConfig.class);
String infoType = CS.SYS_ROLE_TYPE.MCH_APP_OAUTH2;
payInterfaceConfig.setInfoType(infoType);
//添加更新者信息
Long userId = getCurrentUser().getSysUser().getSysUserId();
String realName = getCurrentUser().getSysUser().getRealname();
payInterfaceConfig.setUpdatedUid(userId);
payInterfaceConfig.setUpdatedBy(realName);
//根据 服务商号、接口类型 获取商户参数配置
PayInterfaceConfig dbRecord = payInterfaceConfigService.getByInfoIdAndIfCode(payInterfaceConfig.getInfoType(), payInterfaceConfig.getInfoId(), payInterfaceConfig.getIfCode());
//若配置存在为saveOrUpdate添加ID第一次配置添加创建者
if (dbRecord != null) {
payInterfaceConfig.setId(dbRecord.getId());
// 合并支付参数
payInterfaceConfig.setIfParams(StringKit.marge(dbRecord.getIfParams(), payInterfaceConfig.getIfParams(), dbRecord.getIfCode()));
}else {
payInterfaceConfig.setCreatedUid(userId);
payInterfaceConfig.setCreatedBy(realName);
}
boolean result = payInterfaceConfigService.saveOrUpdate(payInterfaceConfig);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "配置失败");
}
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,58 @@
package com.jeequan.jeepay.mch.ctrl.payconfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PayWay;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 支付方式配置类
*
* @author zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("api/payWays")
public class PayWayController extends CommonCtrl {
@Autowired PayWayService payWayService;
@Autowired MchPayPassageService mchPayPassageService;
@Autowired PayOrderService payOrderService;
@Autowired MchInfoService mchInfoService;
@Autowired PayInterfaceConfigService payInterfaceConfigService;
/**
* @Author: ZhuXiao
* @Description: list
* @Date: 15:52 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PAY_ORDER_SEARCH_PAY_WAY')")
@GetMapping
public ApiRes list() {
PayWay queryObject = getObject(PayWay.class);
LambdaQueryWrapper<PayWay> condition = PayWay.gw();
if(StringUtils.isNotEmpty(queryObject.getWayCode())){
condition.like(PayWay::getWayCode, queryObject.getWayCode());
}
if(StringUtils.isNotEmpty(queryObject.getWayName())){
condition.like(PayWay::getWayName, queryObject.getWayName());
}
condition.orderByAsc(PayWay::getWayCode);
IPage<PayWay> pages = payWayService.page(getIPage(true), condition);
return ApiRes.page(pages);
}
}

View File

@@ -0,0 +1,35 @@
package com.jeequan.jeepay.mch.ctrl.payconfig;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.QualificationDefineEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.QualificationDefineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/qualificationDefine")
@RestController
public class QualificationDefineController extends CommonCtrl {
@Autowired
private QualificationDefineService qualificationDefineService;
@GetMapping("/page")
public ApiRes page() {
Page<QualificationDefineEntity> iPage = getIPage(false);
QualificationDefineEntity condition = getObject(QualificationDefineEntity.class);
qualificationDefineService.lambdaQuery().setEntity(condition).page(iPage);
return ApiRes.ok(iPage);
}
@GetMapping("/{code}")
public ApiRes one(@PathVariable String code) {
QualificationDefineEntity one = qualificationDefineService.lambdaQuery().eq(QualificationDefineEntity::getCode, code).one();
return ApiRes.ok(one);
}
}

View File

@@ -0,0 +1,375 @@
package com.jeequan.jeepay.mch.ctrl.payconfig;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.PayWay;
import com.jeequan.jeepay.db.entity.RateConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.model.RateConfigSimple;
import com.jeequan.jeepay.service.impl.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
/***
* 费率配置信息
*
* @author terrfly
*
* @since 2022/3/21 0:13
*/
@RestController
@RequestMapping("/api/rateConfig")
public class RateConfigController extends CommonCtrl {
@Autowired
private MchInfoService mchInfoService;
@Autowired
private RateConfigService rateConfigService;
@Autowired
private PayWayService payWayService;
@Autowired
private MchAppService mchAppService;
@Autowired
private RateConfigV2Service rateConfigV2Service;
/**
* 查询所有可配置的支付方式 payways
**/
@GetMapping("/payways")
public ApiRes payways() {
String ifCode = getValStringRequired("ifCode"); // ifCode
String infoId = getValStringRequired("infoId"); // infoId
String isvNo = getValStringRequired("isvNo"); // infoId
String configMode = getValStringRequired("configMode"); // 设置类型
Integer range = getValInteger("range");
String mccCode = getValString("mccCode");
/**
* 获取商户费率时, 通过关联的应用获取费率类型
*/
String mchAppId = getValString("appId");
if (!ObjUtil.isEmpty(mchAppId)) {
MchAppEntity mchApp = mchAppService.getById(mchAppId);
range = mchApp.getRange();
mccCode = mchApp.getMccCode();
}
// 商户服务商或者服务商的父ID (用于过滤掉关闭的支付方式)
String belongAgentNo = null;
// 是否仅显示 支持进件的支付方式(用作进件使用)
boolean isOnlyApplymentSupport = false;
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
belongAgentNo = mchInfo.getAgentNo();
// 商户进件模式
if (RateConfig.CONFIG_MODE_MCHAPPLYMENT.equals(configMode)) {
isOnlyApplymentSupport = true;
}
IPage<PayWay> pages = payWayService.queryWayListByRate(ifCode, isvNo, belongAgentNo, isOnlyApplymentSupport, range, mccCode, isvNo);
if (pages.getRecords().isEmpty()) {
return ApiRes.page(pages);
}
// 进件模式 : 只能获取到默认进件费率。
if (isOnlyApplymentSupport && mchInfo.getType() == CS.MCH_TYPE_ISVSUB) {
Set<String> defWayCodes;
if (!ObjUtil.isEmpty(mchInfo.getAgentNo())) { // 包含上级服务商
// 上级服务商支持的 支付方式 [默认支付方式]
defWayCodes = rateConfigService.getAllWayCodesByInfoId(ifCode, RateConfig.appendInfoByMchDef(mchInfo.getAgentNo()), CS.SYS_ROLE_TYPE.AGENT, isvNo);
} else { // 顶级商户
// 服务商支持的 支付方式 [默认支付方式]
defWayCodes = rateConfigService.getAllWayCodesByInfoId(ifCode, RateConfig.appendInfoByMchDef(isvNo), CS.SYS_ROLE_TYPE.ISV, isvNo);
}
List<PayWay> result = new ArrayList<>();
for (PayWay item : pages.getRecords()) {
if (defWayCodes.contains(item.getWayCode())) {
result.add(item);
}
}
return ApiRes.page(new Page<PayWay>().setRecords(result).setTotal(result.size()));
}
return ApiRes.page(pages);
}
/**
* 查询当前已经配置的列表
**/
@GetMapping(value = "/savedMapData")
public ApiRes savedMapData() {
String ifCode = getValStringRequired("ifCode"); // ifCode
String infoId = getValStringRequired("infoId"); // infoId
String configMode = getValStringRequired("configMode"); // 设置类型
Integer range = getValInteger("range");
String mccCode = getValString("mccCode");
String isvNo = getValString("isvNo");
/* 获取商户费率时, 通过关联的应用获取费率类型 */
String mchAppId = getValString("appId");
if (!ObjUtil.isEmpty(mchAppId)) {
MchAppEntity mchApp = mchAppService.getById(mchAppId);
range = mchApp.getRange();
mccCode = mchApp.getMccCode();
}
// 商户自主进件
if (RateConfig.CONFIG_MODE_MCHAPPLYMENT.equals(configMode)) {
Map<String, Object> result = new HashMap<>();
String mchNo = getCurrentMchNo();
Map<String, PaywayFee> paywayFeeMap = new HashMap<>();
Map<String, PaywayFee> mchSetFeeMap = new HashMap<>();
// 查询默认费率
MchInfo mchInfo = mchInfoService.getById(mchNo);
// 特约商户
if (mchInfo.getType() == CS.MCH_TYPE_ISVSUB) {
// 先获取代理给商户配置的特定费率
mchSetFeeMap = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByMchApp(mchInfo.getMchNo()), CS.SYS_ROLE_TYPE.MCH_APP, ifCode, range, mccCode, isvNo);
if (ObjUtil.isEmpty(mchSetFeeMap) && !ObjUtil.isEmpty(mchInfo.getAgentNo())) {
// 查询上级服务商的费率
mchSetFeeMap = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByMchDef(mchInfo.getAgentNo()), CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo);
}
}
if (mchSetFeeMap == null) {
mchSetFeeMap = new HashMap<>();
}
// 查询已经配置的费率
String applyId = infoId.split("_")[0];
if (!ObjUtil.isEmpty(applyId)) {
// 已经配置的费率
// Map<String, PaywayFee> paywayFeeMapByApplyment = rateConfigService.queryPaywayFeeMapByApplyment(applyId);
// 此处费率不从商户信息里面取了
Map<String, PaywayFee> applymentPaywayFee = rateConfigService.queryPaywayFeeMap(mchNo, CS.SYS_ROLE_TYPE.MCH_APPLYMENT, ifCode, range, mccCode, isvNo);
// 同时收集两个数据的keySet作为并集
Set<String> keySet = mchSetFeeMap.keySet();
keySet.addAll(applymentPaywayFee.keySet());
// 当进件关闭该支付产品时, 那么需要读取默认费率(避免全部关闭后保存, 再次进入无法保存的问题。)
for (String key : keySet) {
if (applymentPaywayFee.get(key) != null) {
paywayFeeMap.put(key, applymentPaywayFee.get(key));
} else {
paywayFeeMap.put(key, mchSetFeeMap.get(key));
}
}
} else {
paywayFeeMap.putAll(mchSetFeeMap);
}
if (!CollUtil.isEmpty(paywayFeeMap)) {
result.put(RateConfig.MCHRATE, paywayFeeMap);
}
return ApiRes.ok(result);
}
// 普通商户的费率配置
if (RateConfig.CONFIG_MODE_MCHSELFAPP1.equals(configMode)) {
Map<String, Object> result = new HashMap<>();
result.put(RateConfig.MCHRATE, rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByMchApp(infoId), commonGetInfoType(configMode), ifCode, range, mccCode, isvNo));
return ApiRes.ok(result);
}
return ApiRes.ok();
}
/**
* 保存费率信息
**/
@MethodLog(remark = "配置费率")
@PostMapping(value = "")
public ApiRes reset() {
String configMode = getValStringRequired("configMode");
// 主对象
RateConfig mainRateConfig = getObject(RateConfig.class);
mainRateConfig.setInfoType(commonGetInfoType(configMode)); // 必须设置infoType, 检查费率会使用
List<RateConfig> list = new ArrayList<>();
// 商户费率 (只能是普通商户)
if (!ObjUtil.isEmpty(mainRateConfig.extv().getString(RateConfig.MCHRATE))) {
JSON.parseArray(mainRateConfig.extv().getString(RateConfig.MCHRATE), PaywayFee.class)
.forEach(r -> list.add(getFillInfoIdAndType(mainRateConfig, r, RateConfig.MCHRATE, configMode)));
}
LambdaQueryWrapper<RateConfig> delWrapper = RateConfig.gw();
delWrapper.eq(RateConfig::getIfCode, mainRateConfig.getIfCode());
delWrapper.eq(RateConfig::getInfoType, commonGetInfoType(configMode));
delWrapper.eq(mainRateConfig.getRange() != null, RateConfig::getRange, mainRateConfig.getRange());
delWrapper.eq(!ObjUtil.isEmpty(mainRateConfig.getMccCode()), RateConfig::getMccCode, mainRateConfig.getMccCode());
delWrapper.in(RateConfig::getInfoId, commonGetInfoId(configMode, mainRateConfig.getInfoId()));
rateConfigService.resetRate(list, delWrapper, mainRateConfig, false, null);
return ApiRes.ok();
}
private RateConfig getFillInfoIdAndType(RateConfig mainRateConfig, PaywayFee paywayFee, String infoSuffix, String configMode) {
RateConfig result = new RateConfig();
result.setInfoId(mainRateConfig.getInfoId() + "_" + infoSuffix);
result.setIfCode(mainRateConfig.getIfCode());
result.setMccCode(mainRateConfig.getMccCode());
result.setRange(mainRateConfig.getRange());
result.setIsvNo(mainRateConfig.getIsvNo());
result.setWayCode(paywayFee.getWayCode());
result.setFeeType(paywayFee.getFeeType());
result.setFeeRate(paywayFee.getFeeRate());
result.setApplymentSupport(paywayFee.getApplymentSupport());
result.setPaywayFeeDetail((JSONObject) JSON.toJSON(paywayFee));
result.setInfoType(commonGetInfoType(configMode));
return result;
}
private String commonGetInfoType(String configMode) {
//设置服务商信息
if (RateConfig.CONFIG_MODE_MGRISV.equals(configMode)) {
return CS.SYS_ROLE_TYPE.ISV;
} else if (RateConfig.CONFIG_MODE_MGRAGENT.equals(configMode)) {
return CS.SYS_ROLE_TYPE.AGENT;
} else if (RateConfig.CONFIG_MODE_MGRMCH.equals(configMode)) {
return CS.SYS_ROLE_TYPE.MCH_APP;
} else if (RateConfig.CONFIG_MODE_AGENTSELF.equals(configMode)) {
return CS.SYS_ROLE_TYPE.AGENT;
} else if (RateConfig.CONFIG_MODE_AGENTSUBAGENT.equals(configMode)) {
return CS.SYS_ROLE_TYPE.AGENT;
} else if (RateConfig.CONFIG_MODE_AGENTEMCH.equals(configMode)) {
return CS.SYS_ROLE_TYPE.MCH_APP;
} else if (RateConfig.CONFIG_MODE_MCHSELFAPP1.equals(configMode)) {
return CS.SYS_ROLE_TYPE.MCH_APP;
}
return "";
}
private List<String> commonGetInfoId(String configMode, String infoId) {
//设置服务商信息
if (RateConfig.CONFIG_MODE_MGRISV.equals(configMode)) {
return Arrays.asList(
(infoId + "_" + RateConfig.ISVCOST),
(infoId + "_" + RateConfig.AGENTDEF),
(infoId + "_" + RateConfig.MCHAPPLYDEF),
(infoId + "_" + RateConfig.MCHAPPLYMAX)
);
} else if (RateConfig.CONFIG_MODE_MGRAGENT.equals(configMode)) {
return Arrays.asList(
(infoId + "_" + RateConfig.AGENTRATE),
(infoId + "_" + RateConfig.AGENTDEF),
(infoId + "_" + RateConfig.MCHAPPLYDEF),
(infoId + "_" + RateConfig.MCHAPPLYMAX)
);
} else if (RateConfig.CONFIG_MODE_MGRMCH.equals(configMode)) {
return Collections.singletonList(
(infoId + "_" + RateConfig.MCHRATE)
);
} else if (RateConfig.CONFIG_MODE_AGENTSELF.equals(configMode)) {
return Arrays.asList(
(infoId + "_" + RateConfig.AGENTDEF),
(infoId + "_" + RateConfig.MCHAPPLYDEF)
);
} else if (RateConfig.CONFIG_MODE_AGENTSUBAGENT.equals(configMode)) {
return Collections.singletonList(
(infoId + "_" + RateConfig.AGENTRATE)
);
} else if (RateConfig.CONFIG_MODE_AGENTEMCH.equals(configMode)) {
return Collections.singletonList(
(infoId + "_" + RateConfig.MCHRATE)
);
} else if (RateConfig.CONFIG_MODE_MCHSELFAPP1.equals(configMode)) {
return Collections.singletonList(
(infoId + "_" + RateConfig.MCHRATE)
);
}
return new ArrayList<>();
}
@GetMapping("/rateInfoDetail")
public ApiRes rateInfoDetail() {
String isvNo = getValStringRequired("isvNo");
String ifCode = getValStringRequired("ifCode");
Integer range = getValInteger("range");
String mccCode = getValString("mccCode");
String infoType = getValStringRequired("infoType");
String infoId = getValStringRequired("infoId");
List<RateConfigSimple> result = rateConfigV2Service.getRankFeeList(isvNo, infoType, infoId, ifCode, range, mccCode, isvNo);
return ApiRes.ok(result);
}
}

View File

@@ -0,0 +1,138 @@
package com.jeequan.jeepay.mch.ctrl.payment;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchApplyment;
import com.jeequan.jeepay.db.entity.MchStoreDevice;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.ctrl.paytest.PaytestController;
import com.jeequan.jeepay.model.DeviceInfo;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/*
* 支付测试类
*
* @author zx
*
* @date 2021/6/22 9:43
*/
@RestController
@RequestMapping("/api/pay/app")
public class AppPaymentController extends CommonCtrl {
@Autowired private MchAppService mchAppService;
@Autowired private SysConfigService sysConfigService;
@Autowired private MchStoreService mchStoreService;
@Autowired private SysUserService sysUserService;
@Autowired private MchApplymentService mchApplymentService;
/** 商户APP、刷脸设备下单接口 **/
@PostMapping
public ApiRes doPay() {
//获取请求参数
Long amount = getRequiredAmountL("amount");
String wayCode = getValStringRequired("wayCode");
// 前端明确了支付参数的类型 payDataType
String payDataType = getValString("payDataType");
String authCode = getValString("authCode");
// 收银员ID
Long storeUserId = getCurrentUser().getSysUserId();
PayOrderCreateRequest orderCreateRequest = new PayOrderCreateRequest();
PaytestController.PayOrderCreateReqModelAddStoreId model = new PaytestController.PayOrderCreateReqModelAddStoreId();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
orderCreateRequest.setBizModel(model);
String storeId = getValString("storeId");
String appId = getValString("appId");
// 刷脸设备,设置其门店、应用、设备信息
if (JWTPayload.LOGIN_PAGE_TYPE.FACE_APP.equals(getCurrentUser().getLoginType())) {
MchStoreDevice mchStoreDevice = sysUserService.checkFaceApp(getCurrentUser().getSysUser(), request.getHeader(CS.FACE_DEVICE_NAME));
DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.setDeviceNo(mchStoreDevice.getDeviceNo());
deviceInfo.setProvider(mchStoreDevice.getProvider());
deviceInfo.setDeviceType(PayOrder.DEVICE_TYPE_FACE_APP);
model.setDeviceInfo(deviceInfo); // 设备信息
storeId = mchStoreDevice.getStoreId(); // 门店
}
MchStore store = mchStoreService.getById(storeId);
Assert.notNull(store,"门店信息异常");
MchApplyment mchApplyment = mchApplymentService.getById(store.getMchApplyId());
Assert.notNull(mchApplyment,"商户信息异常");
Assert.isTrue(mchApplyment.isPay(),"商户还未进件通过或状态不正确");
MchAppEntity mchAppEntity = mchAppService.getById(mchApplyment.getAutoConfigMchAppId());
if(mchAppEntity == null || mchAppEntity.getState() != CS.PUB_USABLE){
throw new BizException("应用不存在或不可用");
}
if(CS.PAY_WAY_CODE.AUTO_BAR.equals(wayCode)){
if(mchApplyment.getScanPayPerm() != CS.YES){
throw new BizException("当前商户未开通反扫功能");
}
}
model.setStoreId(storeId); // 门店ID
model.setStoreUserId(storeUserId); // 收银员ID
model.setMchNo(getCurrentMchNo()); // 商户号
model.setAppId(mchAppEntity.getAppId());
model.setMchOrderNo(SeqKit.genMhoOrderId());
model.setWayCode(wayCode);
model.setAmount(amount);
model.setCurrency("CNY");
model.setClientIp(getClientIp());
model.setSubject( mchApplyment.getMchShortName()+ "商户APP收银");
model.setBody( mchApplyment.getMchShortName()+ "商户APP收银");
model.setSellerRemark(getValString("sellerRemark")); // 卖家备注
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
model.setNotifyUrl(dbApplicationConfig.getMchSiteUrl() + "/api/anon/paytestNotify/payOrder"); //回调地址
//设置扩展参数
JSONObject extParams = new JSONObject();
if(StringUtils.isNotEmpty(payDataType)) {
extParams.put("payDataType", payDataType.trim());
}
if(StringUtils.isNotEmpty(authCode)) {
extParams.put("authCode", authCode.trim());
}
model.setChannelExtra(extParams.toString());
String paySiteUrl = dbApplicationConfig.getPaySiteUrl();
// String paySiteUrl = "http://192.168.1.24:9216";
JeepayClient jeepayClient = new JeepayClient(paySiteUrl, mchAppEntity.getAppSecret());
try {
PayOrderCreateResponse response = jeepayClient.execute(orderCreateRequest);
if(response.getCode() != 0){
throw new BizException(response.getMsg());
}
return ApiRes.ok(response.get());
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
}

View File

@@ -0,0 +1,255 @@
package com.jeequan.jeepay.mch.ctrl.paytest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.ApiField;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchConfig;
import com.jeequan.jeepay.db.entity.MchPayPassage;
import com.jeequan.jeepay.db.entity.MchStore;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.model.DeviceInfo;
import com.jeequan.jeepay.model.JeepayObject;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.service.impl.*;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.HashSet;
import java.util.Set;
/*
* 支付测试类
*
* @author terrfly
*
* @date 2021/6/22 9:43
*/
@RestController
@RequestMapping("/api/paytest")
public class PaytestController extends CommonCtrl {
@Autowired private MchAppService mchAppService;
@Autowired private MchPayPassageService mchPayPassageService;
@Autowired private SysConfigService sysConfigService;
@Autowired private MchConfigService mchConfigService;
@Autowired private MchStoreService mchStoreService;
/** 查询商户对应应用下支持的支付方式 **/
@PreAuthorize("hasAuthority('ENT_MCH_PAY_TEST_PAYWAY_LIST')")
@GetMapping("/payways/{appId}")
public ApiRes payWayList(@PathVariable("appId") String appId) {
JSONObject respJson = new JSONObject();
Set<String> payWaySet = new HashSet<>();
mchPayPassageService.list(
MchPayPassage.gw().select(MchPayPassage::getWayCode)
.eq(MchPayPassage::getMchNo, getCurrentMchNo())
.eq(MchPayPassage::getAppId, appId)
.eq(MchPayPassage::getState, CS.PUB_USABLE)
).forEach(r -> payWaySet.add(r.getWayCode()));
// 收银台权限默认开启
respJson.put("webCashierIsShow", true);
// 商户是否拥有便捷收银台权限
Byte mchWebCashierConfig = mchConfigService.getConfigValByMchNoAndKey(getCurrentMchNo(), MchConfig.WEB_CASHIER_STATE, Byte.class);
// 配置不为空 && 配置为关闭状态 显示状态修改为false
if (mchWebCashierConfig != null && mchWebCashierConfig == CS.NO) {
respJson.put("webCashierIsShow", false);
}
respJson.put("payWaySet", payWaySet);
return ApiRes.ok(respJson);
}
/** 调起下单接口 **/
@PreAuthorize("hasAnyAuthority('ENT_MCH_PAY_TEST_DO', 'ENT_C_QUICKCASHIER')")
@PostMapping("/payOrders")
public ApiRes doPay() {
//获取请求参数
// String appId = getValString("appId");
String storeId = getValStringRequired("storeId");
Long amount = getRequiredAmountL("amount");
String mchOrderNo = getValStringRequired("mchOrderNo");
String wayCode = getValStringRequired("wayCode");
Byte divisionMode = getValByteRequired("divisionMode");
String orderTitle = getValString("orderTitle");
if(StringUtils.isEmpty(orderTitle)){
throw new BizException("订单标题不能为空");
}
// 前端明确了支付参数的类型 payDataType
String payDataType = getValString("payDataType");
String authCode = getValString("authCode");
String autoPosExtra = getValString("autoPosExtra");
// 当前没有传入应用,那么使用默认应用
MchStore store = mchStoreService.getById(storeId);
MchAppEntity mchAppEntity = mchAppService.getById(store.getBindAppId());
if(mchAppEntity == null || mchAppEntity.getState() != CS.PUB_USABLE || !mchAppEntity.getAppId().equals(store.getBindAppId())){
throw new BizException("商户应用不存在或不可用");
}
PayOrderCreateRequest request = new PayOrderCreateRequest();
PayOrderCreateReqModelAddStoreId model = new PayOrderCreateReqModelAddStoreId();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
request.setBizModel(model);
model.setMchNo(getCurrentMchNo()); // 商户号
model.setAppId(store.getBindAppId());
model.setStoreId(storeId);
model.setMchOrderNo(mchOrderNo);
model.setWayCode(wayCode);
model.setAmount(amount);
// PayPal通道使用USD类型货币
if(wayCode.equalsIgnoreCase(CS.PAY_WAY_CODE.PP_PC)) {
model.setCurrency("USD");
}else {
model.setCurrency("CNY");
}
model.setClientIp(getClientIp());
model.setSubject(orderTitle + "[" + getCurrentMchNo() + "商户联调]");
model.setBody(orderTitle + "[" + getCurrentMchNo() + "商户联调]");
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
model.setNotifyUrl(dbApplicationConfig.getMchSiteUrl() + "/api/anon/paytestNotify/payOrder"); //回调地址
model.setDivisionMode(divisionMode); //分账模式
// model.setReturnUrl("https://www.jeequan.com");
//设置扩展参数
JSONObject extParams = new JSONObject();
if(StringUtils.isNotEmpty(payDataType)) {
extParams.put("payDataType", payDataType.trim());
}
if(StringUtils.isNotEmpty(authCode)) {
extParams.put("authCode", authCode.trim());
}
model.setChannelExtra(extParams.toString());
if (StringUtils.isNotBlank(autoPosExtra)) {
model.setChannelBizData(autoPosExtra); // 业务参数
// 设备参数
JSONObject deviceJSON = JSON.parseObject(autoPosExtra);
if (deviceJSON != null && !deviceJSON.isEmpty()) {
DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.setDeviceType(PayOrder.DEVICE_TYPE_AUTO_POS);
deviceInfo.setDeviceNo(deviceJSON.getString("deviceNo"));
model.setDeviceInfo(deviceInfo);
}
}
JeepayClient jeepayClient = new JeepayClient(dbApplicationConfig.getPaySiteUrl(), mchAppEntity.getAppSecret());
try {
PayOrderCreateResponse response = jeepayClient.execute(request);
if(response.getCode() != 0){
throw new BizException(response.getMsg());
}
return ApiRes.ok(response.get());
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
/** 收银台地址 **/
@PreAuthorize("hasAnyAuthority('ENT_MCH_CASHIER_URL')")
@PostMapping("/createCashier")
public ApiRes createCashier() {
//获取请求参数
String appId = getValString("appId");
String storeId = getValStringRequired("storeId");
// 当前没有传入应用,那么使用默认应用
if(StringUtils.isBlank(appId)){
appId = mchAppService.getDefaultApp(getCurrentMchNo()).getAppId();
}
MchAppEntity mchAppEntity = mchAppService.getById(appId);
if(mchAppEntity == null || mchAppEntity.getState() != CS.PUB_USABLE || !mchAppEntity.getAppId().equals(appId)){
throw new BizException("商户应用不存在或不可用");
}
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
try {
String payUrl = dbApplicationConfig.genCashierPayUrl(appId, storeId+"");
return ApiRes.ok(payUrl);
} catch (Exception e) {
throw new BizException(e.getMessage());
}
}
/** 与阿里云sdk一样 直接extends PayOrderCreateReqModel无法传入到接口中对应的参数。 需要把所有的参数放进来。。。 = = 。 **/
@Data
public static class PayOrderCreateReqModelAddStoreId extends JeepayObject {
@ApiField("pas")
private String pas;
@ApiField("storeId")
private String storeId;
@ApiField("storeUserId")
private Long storeUserId;
private static final long serialVersionUID = -3998573128290306948L;
@ApiField("mchNo")
private String mchNo; // 商户号
@ApiField("appId")
private String appId; // 应用ID
@ApiField("mchOrderNo")
String mchOrderNo; // 商户订单号
@ApiField("wayCode")
String wayCode; // 支付方式
@ApiField("amount")
Long amount; // 支付金额
@ApiField("currency")
String currency; // 货币代码当前只支持cny
@ApiField("clientIp")
String clientIp; // 客户端IP
@ApiField("subject")
String subject; // 商品标题
@ApiField("body")
String body; // 商品描述
@ApiField("channelBizData")
String channelBizData; // 渠道业务参数
@ApiField("notifyUrl")
String notifyUrl; // 异步通知地址
@ApiField("returnUrl")
String returnUrl; // 跳转通知地址
@ApiField("expiredTime")
String expiredTime; // 订单失效时间
@ApiField("channelExtra")
String channelExtra; // 特定渠道额外支付参数
@ApiField("channelUser")
String channelUser; // 渠道用户标识,如微信openId,支付宝账号
@ApiField("extParam")
String extParam; // 商户扩展参数
@ApiField("divisionMode")
private Byte divisionMode; // 分账模式: 0-该笔订单不允许分账[默认], 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额)
@ApiField("sellerRemark")
String sellerRemark; // 卖家备注
@ApiField("deviceInfo")
private DeviceInfo deviceInfo; // 设备信息
}
}

View File

@@ -0,0 +1,91 @@
package com.jeequan.jeepay.mch.ctrl.paytest;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.websocket.server.WsPayOrderServer;
import com.jeequan.jeepay.service.impl.MchAppService;
import com.jeequan.jeepay.util.JeepayKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.Enumeration;
/*
* 支付测试 - 回调函数
*
* @author terrfly
*
* @date 2021/6/22 14:22
*/
@RestController
@RequestMapping("/api/anon/paytestNotify")
public class PaytestNotifyController extends CommonCtrl {
@Autowired private MchAppService mchAppService;
@RequestMapping("/payOrder")
public void payOrderNotify() throws IOException {
// // 本地调试!!!!!!
// this.headerAndBodyPrint();
//请求参数
JSONObject params = getReqParamJSON();
String mchNo = params.getString("mchNo");
String appId = params.getString("appId");
String sign = params.getString("sign");
MchAppEntity mchAppEntity = mchAppService.getById(appId);
if(mchAppEntity == null || !mchAppEntity.getMchNo().equals(mchNo)){
response.getWriter().print("app is not exists");
return;
}
params.remove("sign");
if(!JeepayKit.getSign(params, mchAppEntity.getAppSecret()).equalsIgnoreCase(sign)){
response.getWriter().print("sign fail");
return;
}
JSONObject msg = new JSONObject();
msg.put("state", params.getIntValue("state"));
msg.put("errCode", params.getString("errCode"));
msg.put("errMsg", params.getString("errMsg"));
//推送到前端
WsPayOrderServer.sendMsgByOrderId(params.getString("payOrderId"), msg.toJSONString());
response.getWriter().print("SUCCESS");
}
// header和body打印 (用于测试)
private void headerAndBodyPrint(){
try {
System.out.println("METHOD:" + request.getMethod());
System.out.println("QUERYSTRING:" + request.getQueryString());
// 查询到所有的header
Enumeration<String> list = request.getHeaderNames();
while (list.hasMoreElements()){
String key = list.nextElement();
System.out.println(key + ":" + request.getHeader(key));
}
String body = "";
String str;
while((str = request.getReader().readLine()) != null){
body += str;
}
System.out.println("BODY: " + body);
} catch (IOException e) {
logger.error("error", e);
}
}
}

View File

@@ -0,0 +1,29 @@
package com.jeequan.jeepay.mch.ctrl.payuser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PayUser;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.PayUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.Map;
/**
* TODO
* 付款用户
* @author crystal
* @date 2023/12/6 15:11
*/
@RestController
@RequestMapping("/api/payUser")
public class PayUserController extends CommonCtrl {
}

View File

@@ -0,0 +1,265 @@
package com.jeequan.jeepay.mch.ctrl.plugin;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.device.PluginCdKeyParams;
import com.jeequan.jeepay.core.model.device.PluginProviderParams;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 收银插件 接口管理类
*
* @author zx
*
* @date 2022/3/4 9:43
*/
@Slf4j
@RestController
@RequestMapping("/api/anon/cashier")
public class PluginController extends CommonCtrl {
@Autowired private DeviceProvideConfigService deviceProvideConfigService;
@Autowired private MchStoreDeviceService mchStoreDeviceService;
@Autowired private MchInfoService mchInfoService;
@Autowired private MchStoreService mchStoreService;
@Autowired private MchAppService mchAppService;
@Autowired private PayOrderService payOrderService;
@Autowired private RefundOrderService refundOrderService;
@Autowired private PayWayService payWayService;
/** 激活码 激活 **/
@PostMapping("/pluginActive/{cdKey}")
public ApiRes init(@PathVariable("cdKey") String cdKey) {
// 验证appSecret
DeviceProvideConfig provideConfig = checkAppSecret();
// 激活码对象
MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, true);
// 激活码详细参数
PluginCdKeyParams cdKeyParams = JSONObject.parseObject(mchStoreDevice.getDeviceParams(), PluginCdKeyParams.class);
// 更新对象
MchStoreDevice updateRecord = new MchStoreDevice();
updateRecord.setState(CS.YES); // 已激活
cdKeyParams.setActiveTime(DateUtil.now()); // 激活时间
cdKeyParams.setDeActiveTime(""); // 解除激活时间置空
updateRecord.setDeviceParams(JSONObject.toJSONString(cdKeyParams));
// 更新操作
boolean result = mchStoreDeviceService.update(updateRecord, new LambdaUpdateWrapper<MchStoreDevice>()
.eq(MchStoreDevice::getDeviceId, mchStoreDevice.getDeviceId())
.eq(MchStoreDevice::getState, CS.NO)
);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok(genCdkeyParams(mchStoreDevice, cdKeyParams, provideConfig));
}
/** 激活码查询 **/
@GetMapping("/plugin/{cdKey}")
public ApiRes detail(@PathVariable("cdKey") String cdKey) {
// 验证appSecret
DeviceProvideConfig provideConfig = checkAppSecret();
// 激活码对象
MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, false);
// 激活码详细参数
PluginCdKeyParams cdKeyParams = JSONObject.parseObject(mchStoreDevice.getDeviceParams(), PluginCdKeyParams.class);
return ApiRes.ok(genCdkeyParams(mchStoreDevice, cdKeyParams, provideConfig));
}
/** 校验appSecret **/
private DeviceProvideConfig checkAppSecret() {
String appSecret = request.getHeader("appSecret");
if (StringUtils.isBlank(appSecret)) {
throw new BizException("非法请求");
}
DeviceProvideConfig provideConfig = deviceProvideConfigService.getOneByAppId(appSecret);
if (provideConfig == null || provideConfig.getState() == CS.NO || StringUtils.isBlank(provideConfig.getProviderParams())) {
throw new BizException("非法请求");
}
return provideConfig;
}
/** 汇总查询 **/
@GetMapping("/statictics/{cdKey}")
public ApiRes statictics(@PathVariable("cdKey") String cdKey) {
// 验证appSecret
DeviceProvideConfig provideConfig = checkAppSecret();
// 激活码对象
MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, false);
JSONObject paramJSON = getReqParamJSON();
PayOrder payOrder = getObject(PayOrder.class);
payOrder.setMchNo(mchStoreDevice.getMchNo());
payOrder.setStoreId(mchStoreDevice.getStoreId());
payOrder.setAppId(mchStoreDevice.getAppId());
PayOrderCount orderCount = payOrderService.orderCount(payOrder, paramJSON, null);
// 支付类型
Page<PayOrderCount> mapPage = payOrderService.countListByWayCodeType(payOrder, paramJSON);
if (CollUtil.isNotEmpty(mapPage.getRecords())) {
mapPage.getRecords().forEach(map -> {
String wayType = map.getWayType();
//TODO 需要修改
// orderCount.put((String) map.get("wayType"), map);
});
}
return ApiRes.ok(orderCount);
}
/** 支付订单查询 **/
@GetMapping("/payList/{cdKey}")
public ApiRes payList(@PathVariable("cdKey") String cdKey) {
// 验证appSecret
DeviceProvideConfig provideConfig = checkAppSecret();
// 激活码对象
MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, false);
JSONObject paramJSON = getReqParamJSON();
PayOrder payOrder = getObject(PayOrder.class);
payOrder.setMchNo(mchStoreDevice.getMchNo());
payOrder.setStoreId(mchStoreDevice.getStoreId());
payOrder.setAppId(mchStoreDevice.getAppId());
IPage<PayOrder> pages = payOrderService.listByPage(getIPage(), payOrder, paramJSON);
return ApiRes.page(pages);
}
/** 退款订单查询 **/
@GetMapping("/refundList/{cdKey}")
public ApiRes refundList(@PathVariable("cdKey") String cdKey) {
// 验证appSecret
DeviceProvideConfig provideConfig = checkAppSecret();
// 激活码对象
MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, false);
JSONObject paramJSON = getReqParamJSON();
RefundOrder refundOrder = getObject(RefundOrder.class);
refundOrder.setMchNo(mchStoreDevice.getMchNo());
refundOrder.setStoreId(mchStoreDevice.getStoreId());
refundOrder.setAppId(mchStoreDevice.getAppId());
LambdaQueryWrapper<RefundOrder> gw = RefundOrder.gw();
gw.select(RefundOrder::getRefundOrderId, RefundOrder::getPayOrderId, RefundOrder::getMchRefundNo, RefundOrder::getState, RefundOrder::getRefundAmount, RefundOrder::getMchNo, RefundOrder::getMchName,
RefundOrder::getStoreId, RefundOrder::getStoreName, RefundOrder::getAppId, RefundOrder::getMchRefundNo, RefundOrder::getWayCode, RefundOrder::getPayAmount,
RefundOrder::getRefundReason, RefundOrder::getSuccessTime, RefundOrder::getExpiredTime, RefundOrder::getCreatedAt);
IPage<RefundOrder> pages = refundOrderService.pageList(getIPage(), gw, refundOrder, paramJSON);
// 得到所有支付方式
Map<String, PayWay> payWayMap = new HashMap<>();
List<PayWay> payWayList = payWayService.list();
if (!CollectionUtils.isEmpty(payWayList)) {
for (PayWay payWay:payWayList) {
payWayMap.put(payWay.getWayCode(), payWay);
}
for (RefundOrder order:pages.getRecords()) {
// 存入支付方式名称
if (payWayMap.get(order.getWayCode()) != null) {
order.addExt("wayName", payWayMap.get(order.getWayCode()).getWayName());
order.addExt("wayCodeType", payWayMap.get(order.getWayCode()).getWayType());
}else {
order.addExt("wayName", order.getWayCode());
}
}
}
return ApiRes.page(pages);
}
/** 校验cdKey **/
private MchStoreDevice checkCdKey(String provider, String cdKey, boolean isInit) {
MchStoreDevice mchStoreDevice = mchStoreDeviceService.getOne(MchStoreDevice.gw()
.eq(MchStoreDevice::getDeviceType, MchStoreDevice.DEVICE_TYPE_PLUGIN)
.eq(MchStoreDevice::getProvider, provider)
.eq(MchStoreDevice::getDeviceNo, cdKey)
);
// 激活码不存在 || 已激活 || 未绑定 || 无参数
if (mchStoreDevice == null || mchStoreDevice.getBindState() == CS.NO || StringUtils.isBlank(mchStoreDevice.getDeviceParams())) {
throw new BizException("激活码无效");
}
if (isInit && mchStoreDevice.getState() == CS.YES) {
throw new BizException("激活码无效");
}else if (!isInit && mchStoreDevice.getState() == CS.NO) {
throw new BizException("激活码无效");
}
PluginCdKeyParams cdKeyParams = JSONObject.parseObject(mchStoreDevice.getDeviceParams(), PluginCdKeyParams.class);
// 激活码已失效
if (cdKeyParams == null || StringUtils.isAnyBlank(cdKeyParams.getCdKey(), cdKeyParams.getExpiredTime())
|| (!StringUtils.equals("0", cdKeyParams.getExpiredTime()) && DateUtil.compare(new Date(), DateUtil.parseDate(cdKeyParams.getExpiredTime())) > 0)) {
throw new BizException("激活码无效");
}
return mchStoreDevice;
}
/** 返回的 激活码对象 **/
private JSONObject genCdkeyParams(MchStoreDevice mchStoreDevice, PluginCdKeyParams cdKeyParams, DeviceProvideConfig provideConfig) {
MchInfo mchInfo = mchInfoService.getById(mchStoreDevice.getMchNo());
MchStore mchStore = mchStoreService.getById(mchStoreDevice.getStoreId());
MchAppEntity mchAppEntity = mchAppService.getById(mchStoreDevice.getAppId());
if (mchInfo == null || mchStore == null || mchAppEntity == null) {
throw new BizException("系统异常");
}
PluginProviderParams providerParams = JSONObject.parseObject(provideConfig.getProviderParams(), PluginProviderParams.class);
if (providerParams == null) {
throw new BizException("厂商");
}
// 返回数据
JSONObject resJSON = new JSONObject();
resJSON.put("provider", mchStoreDevice.getProvider()); // 厂商
resJSON.put("subject", StringUtils.isBlank(providerParams.getSubject()) ? "收银插件收款" : providerParams.getSubject()); // 默认商品标题
resJSON.put("body", StringUtils.isBlank(providerParams.getBody()) ? "收银插件收款" : providerParams.getBody()); // 默认商品描述
resJSON.put("cdKey", mchStoreDevice.getDeviceNo()); // 激活码
resJSON.put("activeTime", cdKeyParams.getActiveTime()); // 激活时间
resJSON.put("expiredTime", cdKeyParams.getExpiredTime()); // 有效期
resJSON.put("mchNo", mchStoreDevice.getMchNo()); // 商户号
resJSON.put("mchName", mchInfo.getMchName()); // 商户名称
resJSON.put("storeId", mchStoreDevice.getStoreId()); // 门店ID
resJSON.put("storeName", mchStore.getStoreName()); // 门店名称
resJSON.put("appId", mchStoreDevice.getAppId()); // 应用appId
resJSON.put("appName", mchAppEntity.getAppName()); // 应用名称
resJSON.put("appSignType", mchAppEntity.getAppSignType()); // 签名方式
resJSON.put("appSecret", mchAppEntity.getAppSecret()); // 应用私钥
resJSON.put("state", CS.YES); // 激活状态
resJSON.put("payUrl", sysConfigService.getDBApplicationConfig().getPaySiteUrl()); // 支付网关地址
return resJSON;
}
}

View File

@@ -0,0 +1,813 @@
package com.jeequan.jeepay.mch.ctrl.pos;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.model.OriginalRes;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.ctrl.paytest.PaytestController;
import com.jeequan.jeepay.model.DeviceInfo;
import com.jeequan.jeepay.model.PayOrderCreateResModel;
import com.jeequan.jeepay.model.RefundOrderCreateReqModel;
import com.jeequan.jeepay.model.RefundOrderCreateResModel;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.request.RefundOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.response.RefundOrderCreateResponse;
import com.jeequan.jeepay.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static com.jeequan.jeepay.mch.ctrl.pos.PosSignUtil.sign;
/**
* 扫码POS 接口管理类
*
* @author zx
* @date 2022/3/4 9:43
*/
@Slf4j
@RestController
@RequestMapping("/api/pos")
public class PosController extends CommonCtrl {
@Autowired private DeviceProvideConfigService deviceProvideConfigService;
@Autowired private MchStoreDeviceService mchStoreDeviceService;
@Autowired private MchInfoService mchInfoService;
@Autowired private MchStoreService mchStoreService;
@Autowired private MchAppService mchAppService;
@Autowired private PayOrderService payOrderService;
@Autowired private RefundOrderService refundOrderService;
@Autowired private PayWayService payWayService;
/** 设备初始化 **/
@PostMapping("/deviceInit/{version}")
public OriginalRes init(@PathVariable("version") String version) {
JSONObject reqParams = getReqParamJSON();
log.info("扫码POS初始化请求{}", reqParams.toJSONString());
// 验证通用请求字段、签名
Object object = checkParamsWithSign(reqParams, false);
if (object instanceof String) {
return OriginalRes.ok(buildResFail((String) object));
}
JSONObject deviceJSON = (JSONObject) object;
MchInfo mchInfo = deviceJSON.getObject("mchInfo", MchInfo.class);
MchStore mchStore = deviceJSON.getObject("mchStore", MchStore.class);
if (mchInfo == null) {
log.error("系统异常,请联系管理员。设备绑定的商户不存在");
return OriginalRes.ok(buildResFail("系统异常,请联系管理员"));
}
JSONObject result = new JSONObject();
result.put("merchantName", mchStore.getStoreName());
result.put("merchantId", mchInfo.getMchNo());
return OriginalRes.ok(buildResSuccess(result,reqParams.getString("key")));
}
/** 设备支付 **/
@PostMapping("/pay/{version}")
public OriginalRes pay(@PathVariable("version") String version) {
JSONObject reqParams = getReqParamJSON();
log.info("扫码POS支付请求{}", reqParams.toJSONString());
// 验证通用请求字段、签名
Object object = checkParamsWithSign(reqParams, true, "pay");
if (object instanceof String) {
return OriginalRes.ok(buildResFail((String) object));
}
JSONObject deviceJSON = (JSONObject) object;
try {
PayOrderCreateResModel resModel = doPay(reqParams.getJSONObject("data"), deviceJSON);
JSONObject result = new JSONObject();
result.put("cxOrderNum", resModel.getPayOrderId());
result.put("payAmount", reqParams.getJSONObject("data").getString("payAmount"));
result.put("receiveAmount", reqParams.getJSONObject("data").getString("payAmount"));
result.put("payableAmount", reqParams.getJSONObject("data").getString("payAmount"));
if (resModel.getOrderState() == 2) { // 支付成功
result.put("payStatus", 10);
} else if (resModel.getOrderState() == 0) {
result.put("payStatus", 0);
} else if (resModel.getOrderState() == 1) {
result.put("payStatus", 5);
}
return OriginalRes.ok(buildResSuccess(result,reqParams.getString("key")));
}catch (BizException e) {
log.error("扫码POS下单异常", e);
return OriginalRes.ok(buildResFail(e.getMessage()));
}
}
/** 支付查单 **/
@PostMapping("/orderDetail/{version}")
public OriginalRes query(@PathVariable("version") String version) {
JSONObject reqParams = getReqParamJSON();
log.info("扫码POS查单请求{}", reqParams.toJSONString());
if (StringUtils.isBlank(reqParams.getString("data"))) {
return OriginalRes.ok(buildResFail("订单号不能为空"));
}
// 验证通用请求字段、签名
Object object = checkParamsWithSign(reqParams, true, "orderDetail");
if (object instanceof String) {
return OriginalRes.ok(buildResFail((String) object));
}
JSONObject deviceJSON = (JSONObject) object;
MchInfo mchInfo = deviceJSON.getObject("mchInfo", MchInfo.class);
String provider = deviceJSON.getString("provider");
// 查询订单号退款前查单为交易凭证商户单号platformMchOrderNo其他为payOrderId
String cxOrderNum;
if (provider.equals(CS.DEVICE_PROVIDER.PS)) {
String dataStr = reqParams.getString("data").replace("\\", "");
cxOrderNum = JSONObject.parseObject(dataStr).getString("deviceOrderNum");;
}else {
cxOrderNum = reqParams.getJSONObject("data").getString("cxOrderNum");
}
if (StringUtils.isBlank(cxOrderNum)) {
return OriginalRes.ok(buildResFail("订单号不能为空"));
}
PayOrder payOrder;
// queryEntryType 可为空,订单查询类型:
// 默认 payOrder使用支付订单查询一般指设备支付接口返回的cxOrderNum字段
// mchOrder使用商户订单号查询一般指设备支付接口的deviceOrderNum字段
// beforeRefund扫码退款或输入订单号退款一般指交易凭证上的商户单号
String queryEntryType = reqParams.getJSONObject("data").getString("queryEntryType");
if (StringUtils.isNotBlank(queryEntryType) && queryEntryType.equals("beforeRefund")) {
// 订单信息
List<PayOrder> payOrderList = payOrderService.list(PayOrder.gw().eq(PayOrder::getPlatformMchOrderNo, cxOrderNum));
if (CollUtil.isEmpty(payOrderList)) {
return OriginalRes.ok(buildResFail("订单不存在"));
}
if (payOrderList.size() > 1) {
return OriginalRes.ok(buildResFail("当前订单不支持扫码退款,可前往订单列表查询并完成退款"));
}
payOrder = payOrderList.get(0);
}else if (StringUtils.isNotBlank(queryEntryType) && queryEntryType.equals("mchOrder")) {
// 订单信息
payOrder = payOrderService.queryMchOrder(mchInfo.getMchNo(), null, cxOrderNum);
if (payOrder == null) {
return OriginalRes.ok(buildResFail("订单不存在"));
}
}else {
payOrder = payOrderService.queryMchOrder(mchInfo.getMchNo(), cxOrderNum, null);
if (payOrder == null) {
return OriginalRes.ok(buildResFail("订单不存在"));
}
}
JSONObject result = new JSONObject();
result.put("cxOrderNum", payOrder.getPayOrderId());
result.put("payAmount", AmountUtil.convertCent2Dollar(payOrder.getAmount()));
result.put("merchantReceiveAmount", AmountUtil.convertCent2Dollar(payOrder.getAmount()));
result.put("payableAmount", AmountUtil.convertCent2Dollar(payOrder.getAmount()));
result.put("createdAt", payOrder.getCreatedAt());
if (payOrder.getState() == 2) { // 支付成功
result.put("payStatus", 10);
} else if (payOrder.getState() == 0) {
result.put("payStatus", 0);
} else if (payOrder.getState() == 1) {
result.put("payStatus", 5);
} else if (payOrder.getState() == 3) {
result.put("payStatus", 15);
}
PayWay payWay = payWayService.getById(payOrder.getWayCode());
if (payWay.getWayType().equals(CS.PAY_WAY_CODE_TYPE.ALIPAY)) { // 支付成功
result.put("payType", 1);
} else if (payWay.getWayType().equals(CS.PAY_WAY_CODE_TYPE.WECHAT)) {
result.put("payType", 2);
} else if (payWay.getWayType().equals(CS.PAY_WAY_CODE_TYPE.YSFPAY)) {
result.put("payType", 3);
} else {
result.put("payType", 4);
}
return OriginalRes.ok(buildResSuccess(result,reqParams.getString("key")));
}
/** 退款 **/
@PostMapping("/refund/{version}")
public OriginalRes refund(@PathVariable("version") String version) {
JSONObject reqParams = getReqParamJSON();
log.info("扫码POS退款请求{}", reqParams.toJSONString());
// 验证通用请求字段、签名
Object object = checkParamsWithSign(reqParams, true);
if (object instanceof String) {
return OriginalRes.ok(buildResFail((String) object));
}
JSONObject deviceJSON = (JSONObject) object;
try {
// 调起退款
RefundOrderCreateResModel resModel = doRefund(reqParams.getJSONObject("data"), deviceJSON);
JSONObject result = new JSONObject();
result.put("cxOrderNum", reqParams.getJSONObject("data").getString("cxOrderNum"));
result.put("refundOrderNum", resModel.getRefundOrderId());
result.put("refundAmount", AmountUtil.convertCent2Dollar(resModel.getRefundAmount()));
result.put("refundStatus", resModel.getState());
result.put("payAmount", resModel.getPayAmount());
return OriginalRes.ok(buildResSuccess(result,reqParams.getString("key")));
}catch (BizException e) {
log.error("扫码POS退款异常", e);
return OriginalRes.ok(buildResFail(e.getMessage()));
}
}
/** 退款订单查单 **/
@PostMapping("/queryRefund/{version}")
public OriginalRes queryRefund(@PathVariable("version") String version) {
JSONObject reqParams = getReqParamJSON();
log.info("扫码POS退款查单请求{}", reqParams.toJSONString());
// 验证通用请求字段、签名
Object object = checkParamsWithSign(reqParams, true);
if (object instanceof String) {
return OriginalRes.ok(buildResFail((String) object));
}
String refundOrderNum = reqParams.getJSONObject("data").getString("refundOrderNum");
if (StringUtils.isBlank(refundOrderNum)) {
return OriginalRes.ok(buildResFail("退款单号不能为空"));
}
RefundOrder refundOrder = refundOrderService.getById(refundOrderNum);
JSONObject result = new JSONObject();
result.put("refundOrderNum", refundOrderNum);
result.put("refundAmount", AmountUtil.convertCent2Dollar(refundOrder.getRefundAmount()));
result.put("refundStatus", refundOrder.getState());
result.put("createdAt", refundOrder.getCreatedAt());
return OriginalRes.ok(buildResSuccess(result,reqParams.getString("key")));
}
/** 汇总查询 **/
@PostMapping("/statictics/{version}")
public OriginalRes statictics(@PathVariable("version") String version) {
JSONObject reqParams = getReqParamJSON();
log.info("扫码POS汇总查询请求{}", reqParams.toJSONString());
// 验证通用请求字段、签名
Object object = checkParamsWithSign(reqParams, true);
if (object instanceof String) {
return OriginalRes.ok(buildResFail((String) object));
}
JSONObject deviceJSON = (JSONObject) object;
MchInfo mchInfo = deviceJSON.getObject("mchInfo", MchInfo.class);
JSONObject dataJSON = reqParams.getJSONObject("data");
if (StringUtils.isBlank(dataJSON.getString("queryDate"))) {
return OriginalRes.ok(buildResFail("queryDate不能为空"));
}
try {
// 时间范围
Date[] dateRange = getQueryDate(dataJSON.getString("queryDate"));
String createStart = null;
String createEnd = null;
if (dateRange != null) {
createStart = DateUtil.formatDateTime(dateRange[0]);
createEnd = DateUtil.formatDateTime(dateRange[1]);
}
// 成功交易统计
PayOrderCount payCountMap = payOrderService.payCount(mchInfo.getMchNo(), null, null, null, PayOrder.STATE_SUCCESS,
null, createStart, createEnd, null, null);
// 退款交易统计
PayOrderCount refundCountMap = payOrderService.payCount(mchInfo.getMchNo(), null, null, null, null,
PayOrder.REFUND_STATE_NONE, createStart, createEnd, null, null);
JSONObject result = new JSONObject();
result.put("totalPayCount", payCountMap.getTotalNum());
result.put("totalPayAmount", payCountMap.getTotalAmt());
result.put("totalRefundCount", refundCountMap.getTotalNum());
result.put("totalRefundAmount", refundCountMap.getTotalRefundAmt());
return OriginalRes.ok(buildResSuccess(result,reqParams.getString("key")));
} catch (BizException e) {
log.error("pos机汇总查询异常", e);
return OriginalRes.ok(buildResFail(e.getMessage()));
}
}
/** 交易查询 **/
@PostMapping("/payList/{version}")
public OriginalRes payList(@PathVariable("version") String version) {
JSONObject reqParams = getReqParamJSON();
log.info("扫码POS交易查询请求{}", reqParams.toJSONString());
// 验证通用请求字段、签名
Object object = checkParamsWithSign(reqParams, true);
if (object instanceof String) {
return OriginalRes.ok(buildResFail((String) object));
}
JSONObject deviceJSON = (JSONObject) object;
MchAppEntity mchAppEntity = deviceJSON.getObject("mchApp", MchAppEntity.class);
JSONObject dataJSON = reqParams.getJSONObject("data");
if (dataJSON.getInteger("pageNumber") == null) {
return OriginalRes.ok(buildResFail("pageNumber不能为空"));
}
if (dataJSON.getInteger("pageSize") == null) {
return OriginalRes.ok(buildResFail("pageSize不能为空"));
}
try {
Date[] dateRange = getQueryDate(dataJSON.getString("queryDate"));
LambdaQueryWrapper<PayOrder> gw = PayOrder.gw();
gw.orderByDesc(PayOrder::getCreatedAt);
gw.eq(PayOrder::getMchNo, mchAppEntity.getMchNo());
gw.in(PayOrder::getState, Arrays.asList(PayOrder.STATE_SUCCESS, PayOrder.STATE_REFUND));
gw.select(PayOrder::getPayOrderId, PayOrder::getState, PayOrder::getWayCodeType, PayOrder::getAmount, PayOrder::getRefundAmount, PayOrder::getCreatedAt);
// 时间范围条件
if (dateRange != null && dateRange[0] != null) {
gw.ge(PayOrder::getCreatedAt, dateRange[0]);
}
if (dateRange != null && dateRange[1] != null) {
gw.le(PayOrder::getCreatedAt, dateRange[1]);
}
// 分页
IPage page = new Page(dataJSON.getInteger("pageNumber"), dataJSON.getInteger("pageSize"));
IPage iPage = payOrderService.page(page, gw);
JSONObject result = new JSONObject();
result.put("records", iPage.getRecords()); //记录明细
result.put("total", iPage.getTotal()); //总条数
result.put("current", iPage.getCurrent()); //当前页码
result.put("hasNext", iPage.getPages() > iPage.getCurrent() ); //是否有下一页
return OriginalRes.ok(buildResSuccess(result,reqParams.getString("key")));
} catch (BizException e) {
log.error("pos机异常", e);
return OriginalRes.ok(buildResFail(e.getMessage()));
}
}
// 校验数据 + 验签
private Object checkParamsWithSign(JSONObject reqParams, boolean isCheckMchNo, String apiType) {
String appId = reqParams.getString("appId");
if (StringUtils.isBlank(appId)) {
return "appId不能为空";
}
String deviceId = reqParams.getString("deviceId");
if (StringUtils.isBlank(deviceId)) {
return "deviceId不能为空";
}
// String merchantId = reqParams.getString("merchantId");
// 只有初始化接口不校验此参数
// if (isCheckMchNo && StringUtils.isBlank(merchantId)) {
// return "merchantId不能为空";
// }
String requestTime = reqParams.getString("requestTime");
if (StringUtils.isBlank(requestTime)) {
return "requestTime不能为空";
}
String sign = reqParams.getString("sign");
if (StringUtils.isBlank(sign)) {
return "签名错误";
}
DeviceProvideConfig deviceProvideConfig = deviceProvideConfigService.getOne(DeviceProvideConfig.gw().eq(DeviceProvideConfig::getAppId, appId));
if (deviceProvideConfig == null) {
return "appId不正确";
}
// 验签
JSONObject configJSON = JSONObject.parseObject(deviceProvideConfig.getProviderParams());
String provider = deviceProvideConfig.getProvider();
// 为了兼容品生的扫码pos针对品生科技的支付和查单接口验签时需要特殊处理
if(CS.DEVICE_PROVIDER.PS.equalsIgnoreCase(provider)) {
if("pay".equals(apiType)) {
// 支付接口,如果有productNum字段则去掉
reqParams.remove("productNum");
}else if("orderDetail".equals(apiType)) {
// 查询支付接口, data数据需要加 \" {\"deviceOrderNum\":\"P1514055777637289986\"}
JSONObject dataObj = reqParams.getJSONObject("data");
String deviceOrderNum = dataObj.getString("deviceOrderNum");
if(StringUtils.isNotBlank(deviceOrderNum)) {
reqParams.put("data", "{\\\"deviceOrderNum\\\":\\\""+deviceOrderNum+"\\\"}");
}
}
}
if (!PosSignUtil.verify(reqParams, configJSON.getString("appSecret"))) {
return "签名错误";
}
// 扫码POS设备信息
MchStoreDevice mchStoreDevice = mchStoreDeviceService.getOne(MchStoreDevice.gw()
.eq(MchStoreDevice::getProvider, deviceProvideConfig.getProvider())
.eq(MchStoreDevice::getDeviceType, MchStoreDevice.DEVICE_TYPE_POS)
.eq(MchStoreDevice::getDeviceNo, deviceId)
);
if (mchStoreDevice == null) {
return "该设备没有入库";
}else if(mchStoreDevice.getState() != CS.YES) {
return "该设备已停用";
}else if (mchStoreDevice.getBindState() != CS.YES) {
return "该设备没有绑定商户";
}
String mchNo = mchStoreDevice.getMchNo();
MchInfo mchInfo = mchInfoService.getById(mchNo);
if (mchInfo == null) {
return "设备绑定商户不存在";
}else if(mchInfo.getState() != CS.YES) {
return "当前商户已停用";
}
String mchAppId = mchStoreDevice.getAppId();
MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
if (mchAppEntity == null) {
return "设备绑定应用不存在";
}else if(mchAppEntity.getState() != CS.YES) {
return "设备绑定应用已停用";
}
String storeId = mchStoreDevice.getStoreId();
MchStore mchStore = mchStoreService.getById(storeId);
if (mchStore == null) {
return "设备绑定门店不存在";
}
JSONObject deviceParamsJSON = new JSONObject();
deviceParamsJSON.put("mchInfo", mchInfo);
deviceParamsJSON.put("mchStore", mchStore);
deviceParamsJSON.put("mchApp", mchAppEntity);
deviceParamsJSON.put("provider", provider);
deviceParamsJSON.put("deviceNo", mchStoreDevice.getDeviceNo());
reqParams.put("key",configJSON.getString("appSecret"));
return deviceParamsJSON;
}
// 校验数据 + 验签
private Object checkParamsWithSign(JSONObject reqParams, boolean isCheckMchNo) {
return checkParamsWithSign(reqParams, isCheckMchNo, "");
}
// 获取日期搜索条件
private Date[] getQueryDate(String queryDateStr) {
if (StringUtils.isBlank(queryDateStr)) {
return null;
}
String[] dateArray = queryDateStr.split("-");
if(dateArray.length == 2){ // 月份
queryDateStr += "-01";
Date queryDate = DateUtil.parseDate(queryDateStr);
return new Date[]{ DateUtil.beginOfMonth(queryDate), DateUtil.endOfMonth(queryDate) };
} else if(dateArray.length == 3){ // 日期
Date queryDate = DateUtil.parseDate(queryDateStr);
return new Date[]{ DateUtil.beginOfDay(queryDate), DateUtil.endOfDay(queryDate) };
} else { // 格式错误
throw new BizException("查询时间参数有误");
}
}
private JSONObject buildResSuccess(JSONObject result,String key) {
JSONObject resJSON = new JSONObject();
resJSON.put("code", "00000");
resJSON.put("message", "success");
resJSON.put("result", result.toString());
log.info("扫码POS响应结果" + resJSON.toJSONString());
String sign = sign(resJSON, key);
resJSON.put("sign",sign);
return resJSON;
}
private JSONObject buildResFail(String message) {
JSONObject resJSON = new JSONObject();
resJSON.put("code", "99999");
resJSON.put("message", message);
log.info("扫码POS响应结果" + resJSON.toJSONString());
return resJSON;
}
// 支付
private PayOrderCreateResModel doPay(JSONObject reqParams, JSONObject deviceJSON) {
// 条码不能为空
if (StringUtils.isBlank(reqParams.getString("qrCode"))) {
throw new BizException("qrCode不能为空");
}
// 支付金额不能为空
if (StringUtils.isBlank(reqParams.getString("payAmount"))) {
throw new BizException("payAmount不能为空");
}
// 下单参数
String amount = AmountUtil.convertDollar2Cent(reqParams.getString("payAmount"));
String wayCode = JeepayKit.getPayWayCodeByBarCode(reqParams.getString("qrCode"));
String authCode = reqParams.getString("qrCode"); // 付款码
MchAppEntity mchAppEntity = deviceJSON.getObject("mchApp", MchAppEntity.class);
MchStore mchStore = deviceJSON.getObject("mchStore", MchStore.class);
PayOrderCreateRequest request = new PayOrderCreateRequest();
PaytestController.PayOrderCreateReqModelAddStoreId model = new PaytestController.PayOrderCreateReqModelAddStoreId();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
request.setBizModel(model);
model.setMchNo(mchAppEntity.getMchNo()); // 商户号
model.setAppId(mchAppEntity.getAppId());
model.setStoreId(mchStore.getStoreId());
model.setMchOrderNo(StringUtils.defaultString(reqParams.getString("deviceOrderNum"), SeqKit.genMhoOrderId()));
model.setWayCode(wayCode);
model.setAmount(Long.valueOf(amount));
model.setCurrency("CNY");
model.setClientIp(getClientIp());
model.setSubject( "扫码终端收银");
model.setBody( "扫码终端收银");
// model.setDeviceNo(deviceJSON.getString("deviceNo"));
// model.setDeviceType(PayOrder.DEVICE_TYPE_SCAN_POS);
DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.setDeviceType(PayOrder.DEVICE_TYPE_SCAN_POS);
deviceInfo.setDeviceNo(deviceJSON.getString("deviceNo"));
deviceInfo.setProvider(deviceJSON.getString("provider"));
model.setDeviceInfo(deviceInfo);
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
model.setNotifyUrl(dbApplicationConfig.getMchSiteUrl() + "/api/anon/paytestNotify/payOrder"); //回调地址
//设置扩展参数
JSONObject extParams = new JSONObject();
extParams.put("authCode", authCode.trim());
model.setChannelExtra(extParams.toString());
JeepayClient jeepayClient = new JeepayClient(dbApplicationConfig.getPaySiteUrl(), mchAppEntity.getAppSecret());
try {
PayOrderCreateResponse response = jeepayClient.execute(request);
// 请求失败
if(response.getCode() != 0){
throw new BizException(StringUtils.isNotBlank(response.getMsg()) ? response.getMsg(): "请求失败");
}
// 支付失败
PayOrderCreateResModel resModel = response.get();
if (!response.isSuccess(mchAppEntity.getAppSecret())) {
throw new BizException(resModel.getErrMsg());
}
return response.get();
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
// 退款
private RefundOrderCreateResModel doRefund(JSONObject data, JSONObject deviceJSON) {
if (data == null) {
throw new BizException("data不能为空");
}
// 订单号不能为空
// if (StringUtils.isBlank(data.getString("cxOrderNum"))) {
// throw new BizException("cxOrderNum不能为空");
// }
// // 退款密码
// if (StringUtils.isBlank(data.getString("refundPwd"))) {
// throw new BizException("refundPwd不能为空");
// }
// 退款权限
MchInfo mchInfo = deviceJSON.getObject("mchInfo", MchInfo.class);
if (!mchInfo.getRefundMode().contains(MchInfo.REFUND_MODEL_PLAT)) {
throw new BizException("无退款权限");
}
// //验证当前密码是否正确
// if(StringUtils.isEmpty(mchInfo.getSipw())){
// throw new BizException("当前未设置支付密码,请进入平台[系统管理-系统配置-安全管理]设置支付密码");
// }
//
// if(!new BCryptPasswordEncoder().matches(data.getString("refundPwd"), mchInfo.getSipw())){
// throw new BizException("支付密码验证失败!");
// }
// 订单信息
String cxOrderNum = data.getString("cxOrderNum");
//支付宝账单上的商户订单号
String cxMchOrderNo = data.getString("cxMchOrderNo");
BigDecimal refundAmt = data.getBigDecimal("refundAmt");
PayOrder payOrder = null;
if(StringUtils.isNotEmpty(cxOrderNum)){
payOrder = payOrderService.getById(cxOrderNum);
}else if(StringUtils.isNotEmpty(cxMchOrderNo)){
payOrder = payOrderService.getPlatformMchOrderNo(cxMchOrderNo);
}else{
throw new BizException("cxOrderNum或cxMchOrderNo不能为空");
}
if (payOrder == null || payOrder.getState() != PayOrder.STATE_SUCCESS || !payOrder.getMchNo().equals(mchInfo.getMchNo())) {
throw new BizException("订单信息错误");
}
long useRefundAmt = refundAmt == null ? BigDecimal.ZERO.longValue() + payOrder.getRefundAmount() : refundAmt.multiply(BigDecimal.valueOf(100)).longValue() + payOrder.getRefundAmount() ;
if(useRefundAmt > payOrder.getAmount()){
throw new BizException("退款金额超出订单剩余可退金额");
}
MchAppEntity mchAppEntity = deviceJSON.getObject("mchApp", MchAppEntity.class);
RefundOrderCreateRequest request = new RefundOrderCreateRequest();
RefundOrderCreateReqModel model = new RefundOrderCreateReqModel();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
request.setBizModel(model);
model.setMchNo(mchAppEntity.getMchNo()); // 商户号
model.setAppId(mchAppEntity.getAppId()); // 商户应用
model.setPayOrderId(payOrder.getPayOrderId());
model.setMchRefundNo(SeqKit.genMhoOrderId());
model.setRefundAmount(refundAmt != null ? refundAmt.multiply(BigDecimal.valueOf(100)).longValue() : payOrder.getAmount() - useRefundAmt); // 退款金额
model.setRefundReason("扫码终端退款");
model.setCurrency("CNY");
JeepayClient jeepayClient = new JeepayClient(sysConfigService.getDBApplicationConfig().getPaySiteUrl(), mchAppEntity.getAppSecret());
try {
RefundOrderCreateResponse response = jeepayClient.execute(request);
// 请求失败
if(response.getCode() != 0){
throw new BizException(StringUtils.isNotBlank(response.getMsg()) ? response.getMsg(): "请求失败");
}
// 退款失败
RefundOrderCreateResModel resModel = response.get();
if (!response.isSuccess(mchAppEntity.getAppSecret())) {
throw new BizException(resModel.getErrMsg());
}
return response.get();
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
public static void main(String[] args) {
String appId = "5c93bb17952842e1afde1ad5ff461b18";
String key = "2fbgmc9otniikpc0mgmuav7s25lfpr5m9d0z8aqy0ylu86sex7w7cj11nqn6p3buxvkoh5eyxygbrbny158spnunx0d1ub75ii5lr72ipx7jhew67fh8gmq08tylwj54";
// initTest(appId, key); // 设备初始化
// payTest(appId, key); // 设备支付
// payQueryTest(appId, key); // 订单查询
// refundTest(appId, key); // 退款
// refundQueryTest(appId, key); // 退款查单
statisticsTest(appId, key); // 汇总查询
// orderQueryTest(appId, key); // 交易查询(查询成功或退款)
}
private static void initTest(String appId, String key) {
JSONObject reqJSON = getCommonJSON(appId);
reqJSON.put("sign", sign(reqJSON, key));
log.info("请求参数:{}", reqJSON.toJSONString());
PosSignUtil.verify(reqJSON, key);
}
private static void payTest(String appId, String key) {
JSONObject reqJSON = getCommonJSON(appId);
JSONObject data = new JSONObject();
data.put("qrCode", "286120303995188105");
data.put("payType", 1);
data.put("payAmount", "0.01");
data.put("deviceOrderNum", "A999999");
reqJSON.put("data", data.toJSONString());
reqJSON.put("sign", sign(reqJSON, key));
log.info("请求参数:{}", reqJSON.toJSONString());
PosSignUtil.verify(reqJSON, key);
}
private static void payQueryTest(String appId, String key) {
JSONObject reqJSON = getCommonJSON(appId);
JSONObject data = new JSONObject();
data.put("cxOrderNum", "P1514893239079043074");
reqJSON.put("data", data.toJSONString());
reqJSON.put("sign", sign(reqJSON, key));
log.info("请求参数:{}", reqJSON.toJSONString());
PosSignUtil.verify(reqJSON, key);
}
private static void refundTest(String appId, String key) {
JSONObject reqJSON = getCommonJSON(appId);
JSONObject data = new JSONObject();
data.put("cxOrderNum", "P1514894810143686657");
data.put("refundPwd", "123456");
reqJSON.put("data", data.toJSONString());
reqJSON.put("sign", sign(reqJSON, key));
log.info("请求参数:{}", reqJSON.toJSONString());
PosSignUtil.verify(reqJSON, key);
}
private static void refundQueryTest(String appId, String key) {
JSONObject reqJSON = getCommonJSON(appId);
JSONObject data = new JSONObject();
data.put("refundOrderNum", "R1514905832518746113");
reqJSON.put("data", data.toJSONString());
reqJSON.put("sign", sign(reqJSON, key));
log.info("请求参数:{}", reqJSON.toJSONString());
PosSignUtil.verify(reqJSON, key);
}
private static void statisticsTest(String appId, String key) {
JSONObject reqJSON = getCommonJSON(appId);
JSONObject data = new JSONObject();
data.put("queryDate", "2022-04-11");
reqJSON.put("data", data.toJSONString());
reqJSON.put("sign", sign(reqJSON, key));
log.info("请求参数:{}", reqJSON.toJSONString());
PosSignUtil.verify(reqJSON, key);
}
private static void orderQueryTest(String appId, String key) {
JSONObject reqJSON = getCommonJSON(appId);
JSONObject data = new JSONObject();
data.put("pageNumber", "1");
data.put("pageSize", "10");
data.put("queryDate", "2022-04");
reqJSON.put("data", data.toJSONString());
reqJSON.put("sign", sign(reqJSON, key));
log.info("请求参数:{}", reqJSON.toJSONString());
PosSignUtil.verify(reqJSON, key);
}
public static JSONObject getCommonJSON(String appId) {
JSONObject reqJSON = new JSONObject();
reqJSON.put("appId", appId);
reqJSON.put("deviceId", "JEEPAY666");
// reqJSON.put("requestTime", "1649816066");
reqJSON.put("requestTime", DateUtil.currentSeconds());
reqJSON.put("merchantId", "M1648869277");
reqJSON.put("productNum", "123456");
return reqJSON;
}
}

View File

@@ -0,0 +1,140 @@
package com.jeequan.jeepay.mch.ctrl.pos;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.TreeMap;
/**
* pos机接口管理类
*
* @author zx
*
* @date 2022/3/4 9:43
*/
@Slf4j
public class PosSignUtil extends CommonCtrl {
/** 校验签名字符串 */
public static boolean verify(JSONObject reqParams, String secretKey) {
String sign = sign(reqParams, secretKey);
return sign.equals(reqParams.getString("sign"));
}
public static String sign(JSONObject reqParams, String secretKey) throws BizException {
TreeMap<String, Object> tree = new TreeMap<>();
// 1. 所有参数进行排序
reqParams.keySet().forEach(key -> tree.put(key, reqParams.get(key)));
//2. 拼接value
StringBuffer stringBuffer = new StringBuffer();
tree.keySet().forEach(key -> {
if (tree.get(key) == null) {
return ;
}
if(StringUtils.isAnyEmpty(key, tree.get(key).toString())){ //空值, 不参与签名
return ;
}
if("sign".equals(key)){ //签名串, 不参与签名
return ;
}
stringBuffer.append(key + "=" + tree.get(key) + "&");
});
String signStr = stringBuffer.append("key=" + secretKey).toString();
log.info("POS机【待加签字符串】{}", signStr);
String md5 = JeepayKit.md5(signStr, "UTF-8");
log.info("POS机【签名结果】{}", md5);
if (StringUtils.isBlank(md5)) {
throw new BizException("POS机数据加密失败");
}
return md5.toLowerCase();
}
public static void main(String[] args) {
//queryOrderTest();
payOrderTest();
String pp = "{\"result\":{\"total\":2,\"current\":1,\"records\":[{\"amount\":14,\"createdAt\":\"2024-02-28 09:55:10\",\"payOrderId\":\"O1762657665502453761\",\"refundAmount\":0,\"state\":2,\"wayCodeType\":\"WECHAT\"},{\"amount\":20,\"createdAt\":\"2024-02-28 09:53:18\",\"payOrderId\":\"O1762657192787615745\",\"refundAmount\":0,\"state\":2,\"wayCodeType\":\"WECHAT\"}],\"hasNext\":false},\"code\":\"00000\",\"sign\":\"17d32156e6ffd0374b6884c74b813df3\",\"message\":\"success\"}";
JSONObject jsonObject = JSONObject.parseObject(pp);
String sign = sign(jsonObject,"0zjyefg6q1r485llp0x9sdbifss4da24hi42qt0bikfg0sv3nf4asz2buykgxokv5mg32k02ctcijzfiak5yuhtxqv8jrzwf4vvyc78iswlzmdr2anqjhbknbsyqcylq");
System.out.println(sign);
}
public static void queryOrderTest() {
JSONObject param = new JSONObject();
/*
发送地址https://mch.s.jeepay.vip/api/pos/orderDetail/1
发送内容:{"appId": "79f23e319567442f8c26e86dee787162","data": "{\"deviceOrderNum\":\"P1517371225137188866\"}","deviceId": "D123456","merchantId": "M1648869277","requestTime": "1650609500","sign": "b958270775ea2c06785cd80b532c7fad","productNum":"123456"}
返回内容:{"code":"99999","message":"签名错误"}
*/
param.put("appId", "79f23e319567442f8c26e86dee787162");
param.put("data", "{\"deviceOrderNum\":\"P1517371225137188866\"}");
param.put("deviceId", "D123456");
param.put("merchantId", "M1648869277");
param.put("requestTime", "1650609500");
param.put("productNum", "123456");
param.put("appId", "79f23e319567442f8c26e86dee787162");
// "sign": "974954509d21dcd4b280f297ea01f12f"
JSONObject dataObj = param.getJSONObject("data");
String deviceOrderNum = dataObj.getString("deviceOrderNum");
if(StringUtils.isNotBlank(deviceOrderNum)) {
param.put("data", "{\\\"deviceOrderNum\\\":\\\""+deviceOrderNum+"\\\"}");
}
String secret = "fdgd3geo62vmfe2pl5m4neckyjeivbuz599giiicjmnwza6yy5grtgxvbm0kxw10t3xihkffec7kjq3tgqyv1515lbsr34h8hn41p6m81yx1zizceg3v4oxk1o9y5epk";
System.out.println(PosSignUtil.sign(param, secret));
// 品生问题
// 查单接口 签名串 fdgd3geo62vmfe2pl5m4neckyjeivbuz599giiicjmnwza6yy5grtgxvbm0kxw10t3xihkffec7kjq3tgqyv1515lbsr34h8hn41p6m81yx1zizceg3v4oxk1o9y5epk79f23e319567442f8c26e86dee787162{\"deviceOrderNum\":\"P1517371225137188866\"}D123456M16488692771234561650609500
// 查单接口有传productNumdata里的数据必须 带\
}
public static void payOrderTest() {
/*
发送地址https://mch.s.jeepay.vip/api/pos/pay/1
发送内容:{"appId": "79f23e319567442f8c26e86dee787162","data":"{\"deviceOrderNum\":\"20220422142430913355\",\"payAmount\":0.01,\"payType\":2,\"qrCode\":\"132554727973706005\"}",
"deviceId": "D123456","merchantId": "M1648869277","requestTime": "1650609381","sign": "fc7498947b73a3f86b326e6557a15fb0"}
返回内容:{"code":"99999","message":"签名错误"}
*/
JSONObject param = new JSONObject();
param.put("appId", "79f23e319567442f8c26e86dee787162");
param.put("data", "{\"deviceOrderNum\":\"20220422180818629757\",\"payAmount\":0.01,\"payType\":2,\"qrCode\":\"134155583541292265\"}");
param.put("deviceId", "D123456");
param.put("merchantId", "M1648869277");
param.put("requestTime", "1650622175");
param.put("productNum", "123456");
// "sign": "974954509d21dcd4b280f297ea01f12f"
String secret = "fdgd3geo62vmfe2pl5m4neckyjeivbuz599giiicjmnwza6yy5grtgxvbm0kxw10t3xihkffec7kjq3tgqyv1515lbsr34h8hn41p6m81yx1zizceg3v4oxk1o9y5epk";
param.remove("productNum");
System.out.println(PosSignUtil.sign(param, secret));
// 品生问题
// 查单接口 签名串 fdgd3geo62vmfe2pl5m4neckyjeivbuz599giiicjmnwza6yy5grtgxvbm0kxw10t3xihkffec7kjq3tgqyv1515lbsr34h8hn41p6m81yx1zizceg3v4oxk1o9y5epk79f23e319567442f8c26e86dee787162{\"deviceOrderNum\":\"P1514055777637289986\"}D123456M16488692771650604549
}
}

View File

@@ -0,0 +1,131 @@
package com.jeequan.jeepay.mch.ctrl.product;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PackageOrder;
import com.jeequan.jeepay.db.entity.ProductInfo;
import com.jeequan.jeepay.db.entity.ProductType;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.ProductAppService;
import com.jeequan.jeepay.service.impl.ProductInfoService;
import com.jeequan.jeepay.service.impl.ProductTypeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 产品中心
*
* @author huay
* @date 2023-11-08 14:50
*/
@RestController
@RequestMapping("/api/product")
public class ProductController extends CommonCtrl {
@Autowired private ProductInfoService productInfoService;
@Autowired private ProductTypeService productTypeService;
@Autowired private ProductAppService productAppService;
/**
* 产品中心列表
* **/
@RequestMapping(value = "/getProductList", method = RequestMethod.GET)
@MethodLog(remark = "产品中心列表")
public ApiRes getProductList() throws BizException {
ProductInfo productInfo = getObject(ProductInfo.class);
/*LambdaQueryWrapper<ProductInfo> wrapper = ProductInfo.gw();
selectParams(productInfo, wrapper);
wrapper.orderByDesc(ProductInfo::getCreatedAt);*/
Page<ProductInfo> page = new Page<>();
List<ProductInfo> productInfoList = productInfoService.getProductList(productInfo.getProductName(),productInfo.getState(),productInfo.getProductType());
page.setRecords(productInfoList);
page.setTotal(productInfoList.size());
page.setCurrent(1);
return ApiRes.ok(page);
}
@RequestMapping(value = "/getProductById", method = RequestMethod.GET)
@MethodLog(remark = "产品详情")
public ApiRes getProductById() throws BizException {
//获取查询条件
ProductInfo productInfo = getObject(ProductInfo.class);
ProductInfo info = productInfoService.getProductById(productInfo.getProductId());
//查询已关联已开通的应用数量,
List<PackageOrder> packageOrderList = productAppService.getList(productInfo.getProductId(),getCurrentMchNo());
List<String> bindingApp = packageOrderList.stream().map(PackageOrder::getAppId).filter(str-> !str.isEmpty()).distinct().collect(Collectors.toList());
info.setApplyCount(packageOrderList.size());
info.setBindingAppList(bindingApp);
//返回收费信息和剩余天数以及总剩余天数
List<PackageOrder> packageOrderListSave =new ArrayList<>();
long allRemainingDays = 0L;
for (PackageOrder packageOrder : packageOrderList) {
if (packageOrder.getCostRule() != null){
JSONArray costRule = packageOrder.getCostRule();
//目前规则只能选取一条
int validTime = costRule.getJSONObject(0).getIntValue("validTime");
if (costRule.getJSONObject(0).getDate("autoTime") != null){
LocalDate currentDate = costRule.getJSONObject(0).getDate("autoTime").toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
// 计算到期后的日期
LocalDate futureDate = currentDate.plusDays(validTime);
// 计算剩余天数
LocalDate today = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
long remainingDays = ChronoUnit.DAYS.between(today, futureDate);
packageOrder.setRemainingDays(remainingDays);
//暂时不需要
//productAppListSave.add(productApp);
allRemainingDays += remainingDays;
}
}
}
//暂时不需要
//info.setProductAppList(productAppListSave);
info.setAllRemainingDays(allRemainingDays);
return ApiRes.ok(info);
}
@RequestMapping(value = "/startProduct", method = RequestMethod.POST)
@MethodLog(remark = "产品开通")
public ApiRes startProduct() throws BizException {
//获取查询条件
PackageOrder app = getObject(PackageOrder.class);
app.setMchNo(getCurrentMchNo());
app.setCreatedAt(new Date());
app.setUpdatedAt(new Date());
app.setPracPrice(BigDecimal.valueOf(0));
productInfoService.startProduct(app);
return ApiRes.ok("已提交!");
}
@RequestMapping(value = "/getProductTypeList", method = RequestMethod.GET)
@MethodLog(remark = "获取所有分类列表")
public ApiRes getProductTypeList() throws BizException {
return ApiRes.ok(productTypeService.list(ProductType.gw()));
}
/**
* @author: huay
* @describe: 查询公共条件
*/
public void selectParams(ProductInfo productInfo, LambdaQueryWrapper<ProductInfo> wrapper) {
wrapper.like(StringUtils.isNotEmpty(productInfo.getProductName()), ProductInfo::getProductName, productInfo.getProductName());
wrapper.eq(ProductInfo::getState, productInfo.getState());
}
}

View File

@@ -0,0 +1,340 @@
package com.jeequan.jeepay.mch.ctrl.qrcode;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.icbc.api.internal.apache.http.impl.cookie.S;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchInfo;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.QRCodeParams;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 商户应用管理类
*
* @author zhuxiao
*
* @date 2021-06-16 09:15
*/
@RestController
@RequestMapping("/api/mchQrCodes")
public class MchQrCodeController extends CommonCtrl {
@Autowired private MchQrcodeCardService mchQrcodeCardService;
@Autowired private MchStoreService mchStoreService;
@Autowired private MchAppService mchAppService;
@Autowired private MchInfoService mchInfoService;
@Autowired private MchApplymentService mchApplymentService;
@Autowired private MchQrcShellService mchQrcShellService;
@PreAuthorize("hasAuthority('ENT_MCH_QR_CODE_LIST')")
@GetMapping
public ApiRes list() {
String appSearchData=getValString("appSearchData");
// 构造查询条件
MchQrcodeCard mchQrCode = getObject(MchQrcodeCard.class);
if(ObjectUtils.isNotEmpty(appSearchData)){
mchQrCode.setQrcAlias(appSearchData);
}
// mchQrCode.setBindState(CS.YES);
mchQrCode.setMchNo(getCurrentMchNo());
// 门店条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
if (CollectionUtil.isNotEmpty(storeIdList)) {
mchQrCode.setStoreIdList(storeIdList);
}
IPage<MchQrcodeCard> resut = mchQrcodeCardService.selectPageRecords(getIPage(), mchQrCode);
return ApiRes.page(resut);
}
@PreAuthorize("hasAuthority('ENT_MCH_QR_CODE_ADD')")
@MethodLog(remark = "新建商户自制码牌")
@PostMapping
public ApiRes add() {
// 处理金额类型
handleParamAmount("fixedPayAmount");
MchQrcodeCard mchQrCode = getObject(MchQrcodeCard.class);
mchQrCode.setMchNo(getCurrentMchNo());
mchQrCode.setQrcBelongType(MchQrcodeCard.QRC_BELONG_TYPE_MCH); // 商户自制码牌
// ID
mchQrCode.setQrcId(SeqKit.genQrcodeCardId());
// 未传入商户appId 则使用默认应用
if(StringUtils.isEmpty(mchQrCode.getAppId())){
mchQrCode.setAppId(mchAppService.getDefaultApp(getCurrentMchNo()).getAppId());
}
MchStore mchStore = mchStoreService.getById(mchQrCode.getStoreId());
if(mchStore == null){
throw new BizException("门店不存在!");
}
if(StringUtils.isEmpty(mchStore.getBindAppId())){
MchApplyment applyment = mchApplymentService.getById(mchStore.getMchApplyId());
mchQrCode.setAppId(applyment.getAutoConfigMchAppId());
}else{
mchQrCode.setAppId(mchStore.getBindAppId());
}
if(StringUtils.isEmpty(mchQrCode.getAlipayWayCode())){
mchQrCode.setAlipayWayCode(CS.PAY_WAY_CODE.ALI_JSAPI);
}
// 默认已绑定
mchQrCode.setBindState(CS.YES);
//获取默认的二维码模板
MchQrcShell qrcShell = mchQrcShellService.getDefaultTemplate(CS.SYS_ROLE_TYPE.PLATFORM);
if(qrcShell != null){
mchQrCode.setQrcShellId(qrcShell.getSid());
}
//获取商户信息
if (StringUtils.isNotEmpty(mchStore.getMchApplyId())){
MchApplyment applyment = mchApplymentService.getById(mchStore.getMchApplyId());
if (applyment != null){
mchQrCode.setMchApplyName(applyment.getMchShortName());
mchQrCode.setMchApplyId(mchStore.getMchApplyId());
}
}
boolean result = mchQrcodeCardService.save(mchQrCode);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
}
return ApiRes.ok();
}
@PreAuthorize("hasAnyAuthority('ENT_MCH_QR_CODE_VIEW', 'ENT_MCH_QR_CODE_EDIT')")
@GetMapping("/{recordId}")
public ApiRes detail(@PathVariable("recordId") Long recordId) {
MchQrcodeCard dbRecord = mchQrcodeCardService.getById(recordId);
if (dbRecord == null || !dbRecord.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
// 添加商户、门店、应用名称
if (dbRecord.getBindState() == CS.YES) {
if (dbRecord.getStoreId() != null) {
MchStore mchStore = mchStoreService.getById(dbRecord.getStoreId());
if (mchStore != null) {
dbRecord.addExt("storeName", mchStore.getStoreName());
}
}
if (StringUtils.isNotBlank(dbRecord.getAppId())) {
MchAppEntity mchAppEntity = mchAppService.getById(dbRecord.getAppId());
if (mchAppEntity != null) {
dbRecord.addExt("appName", mchAppEntity.getAppName());
}
}
}
MchApplyment mchApplyment = mchApplymentService.getById(dbRecord.getMchApplyId());
// 封装URL
dbRecord.addExt("qrUrl", sysConfigService.getDBApplicationConfig().genUniJsapiPayUrl(QRCodeParams.TYPE_QRC, dbRecord.getEntryPage(), recordId + "", mchApplyment.getIsvNo()));
return ApiRes.ok(dbRecord);
}
@PreAuthorize("hasAuthority('ENT_MCH_QR_CODE_EDIT')")
@MethodLog(remark = "更新二维码信息")
@PutMapping("/{recordId}")
public ApiRes update(@PathVariable("recordId") Long recordId) {
// 处理金额类型
handleParamAmount("fixedPayAmount");
MchQrcodeCard mchQrCode = getObject(MchQrcodeCard.class);
mchQrCode.setQrcId(recordId);
mchQrCode.setCreatedAt(null);
mchQrCode.setUpdatedAt(null);
MchQrcodeCard dbRecord = mchQrcodeCardService.getById(recordId);
if (dbRecord == null || !dbRecord.getMchNo().equals(getCurrentMchNo())) {
throw new BizException("无权操作!");
}
mchQrcodeCardService.updateOrReBindQR(mchQrCode, dbRecord);
return ApiRes.ok();
}
@PreAuthorize("hasAuthority('ENT_MCH_QR_CODE_DEL')")
@MethodLog(remark = "删除二维码")
@DeleteMapping("/{recordId}")
public ApiRes delete(@PathVariable("recordId") Long recordId) {
MchQrcodeCard mchQrCode = mchQrcodeCardService.getById(recordId);
if (!mchQrCode.getMchNo().equals(getCurrentMchNo())) {
throw new BizException("无权操作!");
}
mchQrcodeCardService.removeById(recordId);
return ApiRes.ok();
}
/** 解析二维码 && 验证二维码是否可绑定 **/
@GetMapping("/parseQrCodeUrl")
public ApiRes parseQrCodeUrl() {
String url = getValStringRequired("qrUrl");
// 不是支付平台开头的, 说明不是可用二维码
if(!url.startsWith(sysConfigService.getDBApplicationConfig().getPaySiteUrl())){
throw new BizException("二维码解析失败");
}
int tokenIndex = url.indexOf(JeepayKit.TOKEN_KEY + "=");
if(tokenIndex <= 0){
throw new BizException("二维码解析失败");
}
String token = url.substring(tokenIndex + 12);
QRCodeParams qrCodeParams = JSON.parseObject(JeepayKit.aesDecode(token), QRCodeParams.class); //解析token
MchQrcodeCard mchQrcodeCard = mchQrcodeCardService.getById(qrCodeParams.getId());
// 不存在 不可用 已绑定
if(mchQrcodeCard == null || mchQrcodeCard.getQrcState() != CS.YES || mchQrcodeCard.getBindState() != CS.NO){
throw new BizException("当前码牌被解绑或已被停用");
}
return ApiRes.ok(mchQrcodeCard.getQrcId());
}
/** 绑定空码 **/
@PostMapping("/bindEmptyQR")
@PreAuthorize("hasAuthority('ENT_MCH_QR_CODE_ADD')")
public ApiRes bindEmptyQR() {
// 处理金额类型
handleParamAmount("fixedPayAmount");
MchQrcodeCard record = getObject(MchQrcodeCard.class);
record.setMchNo(getCurrentMchNo());
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
record.setAgentNo(mchInfo.getAgentNo());
MchQrcodeCard mchQrcodeCard = mchQrcodeCardService.getById( record.getQrcId());
// 不存在 不可用 已绑定
if(mchQrcodeCard == null){
throw new BizException("当前码牌已被删除,不支持绑定,请更换其他码牌");
}
if(CS.YES == mchQrcodeCard.getBindState() || CS.NO == mchQrcodeCard.getQrcState()){
throw new BizException("当前码牌已被停用或已被其他门店绑定");
}
if(MchQrcodeCard.QRC_TYPE_DZ == mchQrcodeCard.getQrcType()){
throw new BizException("当前码牌为电子码牌,不支持绑定");
}
// 未传入商户appId 则使用默认应用
if(StringUtils.isEmpty(record.getAppId())){
record.setAppId(mchAppService.getDefaultApp(getCurrentMchNo()).getAppId());
}
if(record.getStoreId() == null ){
throw new BizException("请选择门店");
}
//获取商户信息
MchStore mchStore = mchStoreService.getById(record.getStoreId());
if (StringUtils.isNotEmpty(mchStore.getMchApplyId())){
MchApplyment applyment = mchApplymentService.getById(mchStore.getMchApplyId());
if (applyment != null){
record.setMchApplyName(applyment.getMchShortName());
record.setMchApplyId(mchStore.getMchApplyId());
}
}
record.setBindState(CS.YES); //已绑定
mchQrcodeCardService.bindEmptyQR(record);
return ApiRes.ok();
}
/**
* @Author: zx
* @Description: 解绑码牌
* @Date: 15:59 2022/5/30
*/
@PreAuthorize("hasAuthority('ENT_MCH_QR_CODE_EDIT')")
@PostMapping("/unbind/{qrcId}")
public ApiRes unbind(@PathVariable("qrcId") Long qrcId) {
MchQrcodeCard dbRecord = mchQrcodeCardService.getById(qrcId);
if (dbRecord == null || !dbRecord.getMchNo().equals(getCurrentMchNo()) || dbRecord.getQrcBelongType() != MchQrcodeCard.QRC_BELONG_TYPE_ISV_PRE) {
return ApiRes.customFail("解绑失败");
}
mchQrcodeCardService.unbind(dbRecord);
return ApiRes.ok();
}
/**
* @Author: zx
* @Description: 查看码牌绑定的设备列表
* @Date: 15:59 2022/5/30
*/
@PreAuthorize("hasAuthority('ENT_MCH_QR_CODE_EDIT')")
@GetMapping("/bindDevice/{qrcId}")
public ApiRes bindDevice(@PathVariable("qrcId") Long qrcId) {
MchQrcodeCard dbRecord = mchQrcodeCardService.getById(qrcId);
if (dbRecord == null || !dbRecord.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
IPage<MchStoreDevice> page = mchQrcodeCardService.getBindDevice(getIPage(), dbRecord, null);
//返回门店名称
for (MchStoreDevice record : page.getRecords()) {
if (StringUtils.isNotEmpty(record.getStoreId())){
MchStore mchStore = mchStoreService.getById(record.getStoreId());
record.setStoreName(mchStore.getStoreName());
}
}
return ApiRes.page(page);
}
/**
* 根据设备号判断马牌设备是否绑定
* @return
*/
@GetMapping("/checkQrCodeBind/{qrcId}")
public ApiRes checkQrCodeBind(@PathVariable("qrcId") String qrcId) {
JSONObject res = new JSONObject();
res.put("checkCode", "1");
res.put("checkMsg", "当前设备允许绑定");
try {
mchQrcodeCardService.checkQrCodeBind(qrcId);
}catch (BizException e){
res.put("checkCode", "0");
res.put("checkMsg", e.getMessage());
}
return ApiRes.ok(res);
}
}

View File

@@ -0,0 +1,83 @@
package com.jeequan.jeepay.mch.ctrl.qrcode;
import com.jeequan.jeepay.bizcommons.manage.qrshell.AbstractGenerator;
import com.jeequan.jeepay.bizcommons.manage.qrshell.ShellQRGenerator;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.QRCodeParams;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.MchApplyment;
import com.jeequan.jeepay.db.entity.MchQrcShell;
import com.jeequan.jeepay.db.entity.MchQrcodeCard;
import com.jeequan.jeepay.db.entity.MchStore;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.awt.image.BufferedImage;
/**
* 二维码模板管理
*
* @author terrfly
*
* @date 2022/1/17 14:22
*/
@RestController
@RequestMapping("/api/mchQrcShells")
public class MchQrcShellController extends CommonCtrl {
@Autowired private MchQrcodeCardService mchQrcodeCardService;
@Autowired private MchQrcShellService mchQrcShellService;
@Autowired private SysConfigService sysConfigService;
@Autowired private MchStoreService mchStoreService;
@Autowired private MchApplymentService mchApplymentService;
/** 根据qrcId获取图片base64 **/
@GetMapping("/viewByQrc/{qrcId}")
public ApiRes viewByQrc(@PathVariable("qrcId") Long qrcId) throws Exception {
MchQrcodeCard dbRecord = mchQrcodeCardService.getById(qrcId);
String mchStoreName = "";
if(dbRecord.getBindState() == CS.YES && dbRecord.getStoreId() != null && !"-1".equals(dbRecord.getStoreId())){
MchStore mchStore = mchStoreService.getById(dbRecord.getStoreId());
mchStoreName = mchStore != null ? mchStore.getStoreName() : "";
}
AbstractGenerator shellGenerator = SpringBeansUtil.getBean(ShellQRGenerator.class);
MchApplyment applyment = mchApplymentService.getById(dbRecord.getMchApplyId());
// 封装URL
String qrUrlContent = sysConfigService.getDBApplicationConfig().genUniJsapiPayUrl(QRCodeParams.TYPE_QRC, dbRecord.getEntryPage(), qrcId + "", applyment.getIsvNo());
if(dbRecord.getQrcShellId() == null || dbRecord.getQrcShellId() <= 0){
//给前端拼接上 【 data:image/jpg;base64 】
return ApiRes.ok("data:image/jpg;base64,"+ AbstractGenerator.convertImgBase64(shellGenerator.genQrImgBuffer(null, qrUrlContent, qrcId, mchStoreName, false)));
}
MchQrcShell mchQrcShell = mchQrcShellService.getById(dbRecord.getQrcShellId());
BufferedImage bufferedImage = getAbstractGenerator(mchQrcShell.getStyleCode()).genQrImgBuffer(mchQrcShell.getConfigInfo(), qrUrlContent, qrcId, mchStoreName, false);
//给前端拼接上 【 data:image/jpg;base64 】
return ApiRes.ok("data:image/jpg;base64,"+ AbstractGenerator.convertImgBase64(bufferedImage));
}
private AbstractGenerator getAbstractGenerator(String code){
AbstractGenerator generator = SpringBeansUtil.getBean(code + "Generator", AbstractGenerator.class);
if(generator == null){
throw new BizException("选择模板[" + code + "]不存在!");
}
return generator;
}
}

View File

@@ -0,0 +1,65 @@
package com.jeequan.jeepay.mch.ctrl.red;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PayInterfaceDefine;
import com.jeequan.jeepay.db.entity.PayUser;
import com.jeequan.jeepay.db.entity.RedPacketAccount;
import com.jeequan.jeepay.db.entity.SettleInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.PayInterfaceDefineService;
import com.jeequan.jeepay.service.impl.RedPacketAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.Map;
/**
* TODO
*
* @author crystal
* @date 2023/12/6 15:11
*/
@RestController
@RequestMapping("/api/redPacketUser")
public class RedPacketAccountController extends CommonCtrl {
@Autowired private RedPacketAccountService redPacketAccountService;
@PreAuthorize("hasAuthority('ENT_REDPACKET_USER_LIST')")
@GetMapping
public ApiRes list() {
LambdaQueryWrapper<RedPacketAccount> wrapper = initQuery();
wrapper.orderByDesc(RedPacketAccount::getUpdatedAt);
Page<RedPacketAccount> pages = redPacketAccountService.page(getIPage(), wrapper);
return ApiRes.page(pages);
}
@RequestMapping(value = "/count", method = RequestMethod.GET)
public ApiRes count() {
LambdaQueryWrapper<RedPacketAccount> wrapper = initQuery();
Map<String,Object> resultMap = redPacketAccountService.stsCount(wrapper);
return ApiRes.ok(resultMap);
}
private LambdaQueryWrapper<RedPacketAccount> initQuery() {
RedPacketAccount info = getObject(RedPacketAccount.class);
LambdaQueryWrapper<RedPacketAccount> wrapper = RedPacketAccount.gw(info);
wrapper.eq(RedPacketAccount::getMchNo, getCurrentMchNo());
Date[] dateRange = info.buildQueryDateRange();
if (dateRange[0] != null) {
wrapper.ge(RedPacketAccount::getUpdatedAt, dateRange[0]);
}
if (dateRange[1] != null) {
wrapper.le(RedPacketAccount::getUpdatedAt, dateRange[1]);
}
return wrapper;
}
}

View File

@@ -0,0 +1,50 @@
package com.jeequan.jeepay.mch.ctrl.red;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.RedPacketAccountDetail;
import com.jeequan.jeepay.db.entity.RedPacketInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.RedPacketAccountDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* TODO
* @author crystal
* @date 2023/12/6 15:11
*/
@RestController
@RequestMapping("/api/redPacketChange")
public class RedPacketAccountDetailController extends CommonCtrl {
@Autowired private RedPacketAccountDetailService redPacketAccountDetailService;
/**
*
* @return
*/
@PreAuthorize("hasAuthority('ENT_REDPACKET_CHANGE_LIST')")
@GetMapping
public ApiRes list() {
RedPacketAccountDetail info = getObject(RedPacketAccountDetail.class);
LambdaQueryWrapper<RedPacketAccountDetail> wrapper = RedPacketAccountDetail.gw(info);
wrapper.eq(RedPacketAccountDetail::getMchNo, getCurrentMchNo());
Date[] dateRange = info.buildQueryDateRange();
if (dateRange[0] != null) {
wrapper.ge(RedPacketAccountDetail::getUpdatedAt, dateRange[0]);
}
if (dateRange[1] != null) {
wrapper.le(RedPacketAccountDetail::getUpdatedAt, dateRange[1]);
}
wrapper.orderByDesc(RedPacketAccountDetail::getUpdatedAt);
Page<RedPacketAccountDetail> pages = redPacketAccountDetailService.page(getIPage(), wrapper);
return ApiRes.page(pages);
}
}

View File

@@ -0,0 +1,41 @@
package com.jeequan.jeepay.mch.ctrl.red;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.RedPacketInfo;
import com.jeequan.jeepay.db.entity.RedPacketRule;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.RedPacketInfoService;
import com.jeequan.jeepay.service.impl.RedPacketRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* TODO
* @author crystal
* @date 2023/12/6 15:11
*/
@RestController
@RequestMapping("/api/redPacketInfo")
public class RedPacketInfoController extends CommonCtrl {
@Autowired private RedPacketInfoService redPacketInfoService;
@PreAuthorize("hasAuthority('ENT_REDPACKET_INFO_LIST')")
@GetMapping
public ApiRes list() {
RedPacketInfo info = getObject(RedPacketInfo.class);
LambdaQueryWrapper<RedPacketInfo> wrapper = RedPacketInfo.gw();
wrapper.eq(RedPacketInfo::getMchNo, getCurrentMchNo());
Page<RedPacketInfo> pages = redPacketInfoService.pageList(getIPage(), wrapper,info);
return ApiRes.page(pages);
}
}

View File

@@ -0,0 +1,83 @@
package com.jeequan.jeepay.mch.ctrl.red;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.RedPacketAccount;
import com.jeequan.jeepay.db.entity.RedPacketRule;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.RedPacketAccountService;
import com.jeequan.jeepay.service.impl.RedPacketRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.Map;
/**
* TODO
* @author crystal
* @date 2023/12/6 15:11
*/
@RestController
@RequestMapping("/api/redPacketRule")
public class RedPacketRuleController extends CommonCtrl {
@Autowired private RedPacketRuleService redPacketRuleService;
@PreAuthorize("hasAuthority('ENT_REDPACKET_RULE_LIST')")
@GetMapping
public ApiRes list() {
RedPacketRule info = getObject(RedPacketRule.class);
LambdaQueryWrapper<RedPacketRule> wrapper = RedPacketRule.gw(info);
wrapper.eq(RedPacketRule::getMchNo, getCurrentMchNo());
Date[] dateRange = info.buildQueryDateRange();
if (dateRange[0] != null) {
wrapper.ge(RedPacketRule::getUpdatedAt, dateRange[0]);
}
if (dateRange[1] != null) {
wrapper.le(RedPacketRule::getUpdatedAt, dateRange[1]);
}
wrapper.orderByDesc(RedPacketRule::getUpdatedAt);
Page<RedPacketRule> pages = redPacketRuleService.page(getIPage(), wrapper);
return ApiRes.page(pages);
}
/**
* 新增规则
* @return
*/
@PreAuthorize("hasAuthority('ENT_REDPACKET_RULE_ADD')")
@RequestMapping(method = RequestMethod.POST)
public ApiRes add() {
RedPacketRule info = getObject(RedPacketRule.class);
info.setMchNo(getCurrentMchNo());
redPacketRuleService.addSave(info);
return ApiRes.ok();
}
/**
* 查询信息
* @param id
* @return
*/
@RequestMapping(value = "/{id}",method = RequestMethod.GET)
public ApiRes get(@PathVariable("id") Integer id) {
return ApiRes.ok(redPacketRuleService.getById(id));
}
/**
* 修改
* @param
* @return
*/
@PreAuthorize("hasAuthority('ENT_REDPACKET_RULE_EDIT')")
@RequestMapping(value = "/edit",method = RequestMethod.POST)
public ApiRes edit() {
RedPacketRule info = getObject(RedPacketRule.class);
info.check();
redPacketRuleService.updateById(info);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,93 @@
package com.jeequan.jeepay.mch.ctrl.route;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.QRCodeParams;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 商户路由管理类
*
* @date 2021-06-16 09:15
*/
@RestController
@RequestMapping("/api/route")
public class RouteController extends CommonCtrl {
@Autowired
private RouteService routeService;
/**
* @Description: 商户路由列表
* @since 2024/04/19
*/
// @PreAuthorize("hasAuthority('ENT_ROUTE_LIST')")
@GetMapping
public ApiRes list() {
Route entity = getObject(Route.class).setMchNo(getCurrentMchNo());
IPage<Route> pages = routeService.pageList(getIPage(true), entity);
return ApiRes.page(pages);
}
@PreAuthorize("hasAuthority('ENT_ROUTE_ADD')")
@MethodLog(remark = "新增路由策略")
@PostMapping
public ApiRes add() {
Route entity = getObject(Route.class).setMchNo(getCurrentMchNo());
SysUser sysUser = getCurrentUser().getSysUser();
entity.setCreatedUid(sysUser.getSysUserId());
entity.setCreatedBy(sysUser.getRealname());
entity.setRouteId(SeqKit.genFlowNo("RU"));
routeService.addSave(entity);
return ApiRes.ok();
}
@PreAuthorize("hasAuthority('ENT_ROUTE_EDIT')")
@MethodLog(remark = "修改路由信息")
@PutMapping("/{id}")
public ApiRes update(@PathVariable("id") String id) {
Route entity = getObject(Route.class).setRouteId(id);
entity.preCheck();
routeService.updateById(entity);
return ApiRes.ok();
}
@PreAuthorize("hasAuthority('ENT_ROUTE_DEL')")
@MethodLog(remark = "删除路由")
@DeleteMapping("/{id}")
public ApiRes delete(@PathVariable("id") String id) {
routeService.del(id);
return ApiRes.ok();
}
/**
* 数据统计
* @return
*/
@GetMapping("/count")
public ApiRes count() {
Route entity = getObject(Route.class).setMchNo(getCurrentMchNo());
PayOrderCount count = routeService.totalCount(entity);
return ApiRes.ok(count);
}
/**
* 获取二维码
* @return
*/
@GetMapping("/qrcode/{id}")
public ApiRes qrcode(@PathVariable("id") String id) {
String url = routeService.getQrCode(id);
return ApiRes.ok(url);
}
}

View File

@@ -0,0 +1,51 @@
package com.jeequan.jeepay.mch.ctrl.route;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.db.entity.Route;
import com.jeequan.jeepay.db.entity.RouteRecord;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.PayOrderService;
import com.jeequan.jeepay.service.impl.RouteRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* 路由运行策略
* @date 2021-06-16 09:15
*/
@RestController
@RequestMapping("/api/routeData")
public class RouteDataController extends CommonCtrl {
@Autowired
private PayOrderService payOrderService;
/**
* @Description: 分页查询
* @since 2024/04/19
*/
@GetMapping
public ApiRes list() {
PayOrderCount entity = getObject(PayOrderCount.class).setMchNo(getCurrentMchNo());
IPage<PayOrderCount> pages = payOrderService.routePageList(getIPage(true), entity);
return ApiRes.page(pages);
}
/**
* 统计
* @return
*/
@GetMapping("/count")
public ApiRes count() {
PayOrderCount entity = getObject(PayOrderCount.class).setMchNo(getCurrentMchNo());
PayOrderCount orderCount = payOrderService.routeCount(entity);
return ApiRes.ok(orderCount);
}
}

View File

@@ -0,0 +1,77 @@
package com.jeequan.jeepay.mch.ctrl.route;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.Route;
import com.jeequan.jeepay.db.entity.RouteManage;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.RouteManageService;
import com.jeequan.jeepay.service.impl.RouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
/**
*
*
* @date 2021-06-16 09:15
*/
@RestController
@RequestMapping("/api/routeManage")
public class RouteManageController extends CommonCtrl {
@Autowired
private RouteManageService routeManageService;
/**
* @Description: 商户路由列表
* @since 2024/04/19
*/
@GetMapping
public ApiRes list() {
RouteManage entity = getObject(RouteManage.class).setMchNo(getCurrentMchNo());
IPage<RouteManage> pages = routeManageService.pageList(getIPage(true), entity);
return ApiRes.page(pages);
}
@PreAuthorize("hasAuthority('ENT_ROUTE_MANAGE_ADD')")
@MethodLog(remark = "绑定门店路由")
@PostMapping
public ApiRes add() {
RouteManage entity = getObject(RouteManage.class).setMchNo(getCurrentMchNo());
routeManageService.addSave(entity);
return ApiRes.ok();
}
@PreAuthorize("hasAuthority('ENT_ROUTE_MANAGE_EDIT')")
@MethodLog(remark = "修改路由绑定信息")
@PutMapping("/{id}")
public ApiRes update(@PathVariable("id") String id) {
RouteManage entity = getObject(RouteManage.class).setStoreId(id);
List<String> amtRange = entity.getAmtRange();
if(amtRange != null){
amtRange.stream().map(amt -> {
amtRange.replaceAll(value -> new BigDecimal(value).multiply(BigDecimal.valueOf(100)).toString());
return amtRange;
});
}
routeManageService.updateById(entity);
return ApiRes.ok();
}
@PreAuthorize("hasAuthority('ENT_ROUTE_MANAGE_DEL')")
@MethodLog(remark = "删除路由绑定")
@DeleteMapping("/{id}")
public ApiRes delete(@PathVariable("id") String id) {
routeManageService.removeById(id);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,39 @@
package com.jeequan.jeepay.mch.ctrl.route;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.Route;
import com.jeequan.jeepay.db.entity.RouteRecord;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.RouteRecordService;
import com.jeequan.jeepay.service.impl.RouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 路由运行策略
* @date 2021-06-16 09:15
*/
@RestController
@RequestMapping("/api/routeRecord")
public class RouteRecordController extends CommonCtrl {
@Autowired
private RouteRecordService routeRecordService;
/**
* @Description: 分页查询
* @since 2024/04/19
*/
@GetMapping
public ApiRes list() {
RouteRecord entity = getObject(RouteRecord.class).setMchNo(getCurrentMchNo());
IPage<RouteRecord> pages = routeRecordService.pageList(getIPage(true), entity);
return ApiRes.page(pages);
}
}

View File

@@ -0,0 +1,139 @@
package com.jeequan.jeepay.mch.ctrl.settle;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.export.SettleInfoExportExcel;
import com.jeequan.jeepay.core.utils.ExcelUtil;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.CommonApiService;
import com.jeequan.jeepay.service.impl.PayInterfaceDefineService;
import com.jeequan.jeepay.service.impl.SettleInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* TODO
*
* @author crystal
* @date 2023/12/6 15:11
*/
@RestController
@RequestMapping("/api/settle")
public class SettleInfoController extends CommonCtrl {
@Autowired private SettleInfoService settleInfoService;
@Autowired private PayInterfaceDefineService payInterfaceDefineService;
@Autowired private CommonApiService commonApiService;
@PreAuthorize("hasAuthority('ENT_SETTLE_LIST')")
@GetMapping
public ApiRes list() {
SettleInfo info = getObject(SettleInfo.class);
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<SettleInfo> wrapper = SettleInfo.gw();
wrapper.eq(SettleInfo::getMchNo, getCurrentMchNo());
Page<SettleInfo> pages = settleInfoService.pageList(getIPage(), wrapper,info,paramJSON);
Map<String, String> ifCodeMap = new HashMap<>();
List<PayInterfaceDefine> list = payInterfaceDefineService.list();
if(!list.isEmpty()){
for (PayInterfaceDefine define:list) {
ifCodeMap.put(define.getIfCode(), define.getIfName());
}
}
for (SettleInfo data:pages.getRecords()) {
if(StringUtils.isNotBlank(data.getIfCode())){
data.setIfName(ifCodeMap.get(data.getIfCode()));
}
}
return ApiRes.page(pages);
}
/**
* 结算信息导出
*/
@RequestMapping(value="/exportExcel", method = RequestMethod.GET)
public void exportExcel() {
try {
SettleInfo info = getObject(SettleInfo.class);
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<SettleInfo> wrapper = SettleInfo.gw(info);
wrapper.eq(SettleInfo::getMchNo, getCurrentMchNo());
Page<SettleInfo> pages = settleInfoService.pageList(getIPage(), wrapper,info,paramJSON);
Map<String, String> ifCodeMap = new HashMap<>();
List<PayInterfaceDefine> list = payInterfaceDefineService.list();
if(!list.isEmpty()){
for (PayInterfaceDefine define:list) {
ifCodeMap.put(define.getIfCode(), define.getIfName());
}
}
List<JSONObject> newList = new LinkedList<>();
if (!pages.getRecords().isEmpty()){
//成功交易总笔数
List<SettleInfo> infoList = pages.getRecords().stream().filter(p -> p.getState() == 2).collect(Collectors.toList());
//成功交易总金额
BigDecimal allSuccessAmount = BigDecimal.ZERO;
for (SettleInfo settleInfo : infoList) {
allSuccessAmount=allSuccessAmount.add(BigDecimal.valueOf(settleInfo.getSettleAmt()));
}
for (SettleInfo data:pages.getRecords()) {
if(StringUtils.isNotBlank(data.getIfCode())){
data.setIfName(ifCodeMap.get(data.getIfCode()));
}
JSONObject object = (JSONObject) JSONObject.toJSON(data);
newList.add(object);
}
}
List<SettleInfoExportExcel> linkedList = JSONArray.parseArray(JSONArray.toJSONString(newList), SettleInfoExportExcel.class);
// excel输出
ExcelUtil.exportExcel(linkedList, "结算信息", "结算信息", SettleInfoExportExcel.class, "结算信息", response);
}catch (Exception e){
logger.error("导出excel失败", e);
throw new BizException("导出结算信息失败!");
}
}
@GetMapping("/count")
public ApiRes getCount(){
SettleInfo info = getObject(SettleInfo.class);
LambdaQueryWrapper<SettleInfo> wrapper = SettleInfo.gw();
// 时间范围条件
Date[] dateRange = info.buildQueryDateRange();
if (dateRange[0] != null) {
wrapper.ge(SettleInfo::getUpdatedAt, dateRange[0]);
}
if (dateRange[1] != null) {
wrapper.le(SettleInfo::getUpdatedAt, dateRange[1]);
}
wrapper.eq(SettleInfo::getMchNo, getCurrentMchNo());
List<SettleInfo> infoList = settleInfoService.list(wrapper);
return settleInfoService.getCount(infoList);
}
/**
* 同步结算结果
* @return
*/
@PreAuthorize("hasAuthority('ENT_SETTLE_SYNC')")
@GetMapping("/sync/{recordId}")
public ApiRes syncResult(@PathVariable("recordId") String recordId){
commonApiService.syncSettleResult(recordId);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,143 @@
package com.jeequan.jeepay.mch.ctrl.statistics;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.export.statistic.*;
import com.jeequan.jeepay.core.utils.ExcelUtil;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.StatsDeviceService;
import com.jeequan.jeepay.service.impl.StatsPayWayService;
import com.jeequan.jeepay.service.impl.StatsTradeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
/**
* 统计列表接口
*
* @author xiaoyu
*
* @date 2022/5/23 16:52
*/
@Slf4j
@RestController
@RequestMapping("/api/statistic/export")
public class ExportExcelStatisticController extends CommonCtrl {
@Autowired private StatsTradeService statsTradeService;
@Autowired private StatsPayWayService statsPayWayService;
@Autowired private StatsDeviceService statsDeviceService;
/**
* @author: xiaoyu
* @date: 2022/5/23 17:15
* @describe: 统计列表
*/
@PreAuthorize("hasAnyAuthority('ENT_STATISTIC_TRANSACTION', 'ENT_STATISTIC_MCH_STORE', 'ENT_STATISTIC_MCH_WAY', 'ENT_STATISTIC_MCH_TYPE')")
@RequestMapping(value="", method = RequestMethod.GET)
public void list() {
JSONObject paramJSON = getReqParamJSON();
PayOrder payOrder = getObject(PayOrder.class);
String method = getValStringRequired("method");
String mchNo = getCurrentMchNo();
payOrder.setMchNo(mchNo);
paramJSON.put("mchNo", mchNo);
// 门店ID条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
paramJSON.put("storeIdList", storeIdList);
Page<PayOrderCount> countPage = null;
switch (method) {
case CS.STATISTIC_TYPE.TRANSACTION:
countPage = statsTradeService.selectTransactionStatsList(payOrder, paramJSON, null);
exportExcel(countPage, StatisticTransactionExportExcel.class, "交易报表");
break;
case CS.STATISTIC_TYPE.STORE:
// 门店
countPage = statsTradeService.selectStoreStatsList(paramJSON);
exportExcel(countPage, StatisticStoreExportExcel.class, "门店统计");
break;
case CS.STATISTIC_TYPE.WAY_CODE:
// 支付方式
countPage = statsPayWayService.selectPayWayStatsList(paramJSON);
exportExcel(countPage, StatisticWayCodeExportExcel.class, "支付方式统计");
break;
case CS.STATISTIC_TYPE.WAY_CODE_TYPE:
// 支付类型
countPage = statsPayWayService.selectWayCodeTypeStatsList(paramJSON);
exportExcel(countPage, StatisticWayCodeTypeExportExcel.class, "支付类型统计");
break;
case CS.STATISTIC_TYPE.DEVICE:
// 通道统计
countPage = statsDeviceService.selectStatsList(paramJSON, null);
exportExcel(countPage, StatisticDeviceExportExcel.class, "设备统计");
break;
case CS.STATISTIC_TYPE.MCH:
//商户统计
countPage = statsTradeService.selectByMch(paramJSON,null);
exportExcel(countPage, StatisticMcMchExportExcel.class, "商户统计");
break;
default:
break;
}
}
/** 通用导出类 **/
public void exportExcel(Page<PayOrderCount> mapPage, Class clazz, String title) {
try {
List<JSONObject> newList = new LinkedList<>();
mapPage.getRecords().stream().forEach(record -> {
JSONObject resItem = (JSONObject) JSONObject.toJSON(record);
BigDecimal totalSuccAmt = BigDecimal.valueOf(record.getTotalSuccAmt()).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
resItem.put("allAmount", totalSuccAmt);
// 实收金额转换
BigDecimal totalFinalAmt = BigDecimal.valueOf(record.getTotalFinalAmt()).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
resItem.put("payAmount", totalFinalAmt);
// 退款金额转换
BigDecimal totalRefundAmt = BigDecimal.valueOf(record.getTotalRefundAmt()).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
resItem.put("refundAmount", totalRefundAmt);
// 成功率
resItem.put("round", record.getSuccRate() + "%");
//手续费
if (record.getTotalFeeAmt() != null){
BigDecimal totalfeeamt = BigDecimal.valueOf(record.getTotalFeeAmt()).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
resItem.put("totalFeeAmt", totalfeeamt);
}
//手续费回退
if (record.getTotalRefundFeeAmt() != null){
BigDecimal totalReFeeAmt= BigDecimal.valueOf(record.getTotalRefundFeeAmt()).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
resItem.put("totalRefundFeeAmt", totalReFeeAmt);
}
if (StringUtils.isNotBlank(record.getDeviceType())) {
resItem.put("deviceType", PayOrder.DEVICE_TYPE_MAP.get(record.getDeviceType()));
}
newList.add(resItem);
});
List<T> linkedList = JSONArray.parseArray(JSONArray.toJSONString(newList), clazz);
// excel输出
ExcelUtil.exportExcel(linkedList, title, title, clazz, title, response);
}catch (Exception e) {
logger.error("导出excel失败", e);
throw new BizException("导出订单失败!");
}
}
}

View File

@@ -0,0 +1,108 @@
package com.jeequan.jeepay.mch.ctrl.statistics;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.StatsDeviceService;
import com.jeequan.jeepay.service.impl.StatsPayWayService;
import com.jeequan.jeepay.service.impl.StatsTradeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 统计列表接口
*
* @author xiaoyu
*
* @date 2022/5/23 16:52
*/
@Slf4j
@RestController
@RequestMapping("/api/statistic")
public class StatisticController extends CommonCtrl {
@Autowired private StatsTradeService statsTradeService;
@Autowired private StatsPayWayService statsPayWayService;
@Autowired private StatsDeviceService statsDeviceService;
/**
* @author: xiaoyu
* @date: 2022/5/23 17:15
* @describe: 统计列表
*/
@PreAuthorize("hasAnyAuthority('ENT_STATISTIC_TRANSACTION', 'ENT_STATISTIC_MCH_STORE', 'ENT_STATISTIC_MCH_WAY', 'ENT_STATISTIC_MCH_TYPE')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
JSONObject paramJSON = getReqParamJSON();
PayOrder payOrder = getObject(PayOrder.class);
String method = getValStringRequired("method");
String mchNo = getCurrentMchNo();
payOrder.setMchNo(mchNo);
// 门店ID条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
paramJSON.put("storeIdList", storeIdList);
paramJSON.put("mchNo", mchNo);
Page<PayOrderCount> countPage = new Page<>();
switch (method) {
case CS.STATISTIC_TYPE.TRANSACTION:
// 交易报表
countPage = statsTradeService.selectTransactionStatsList(payOrder, paramJSON, null);
break;
case CS.STATISTIC_TYPE.STORE:
// 门店
countPage = statsTradeService.selectStoreStatsList(paramJSON);
break;
case CS.STATISTIC_TYPE.WAY_CODE:
// 支付方式
countPage = statsPayWayService.selectPayWayStatsList(paramJSON);
break;
case CS.STATISTIC_TYPE.WAY_CODE_TYPE:
// 支付类型
countPage = statsPayWayService.selectWayCodeTypeStatsList(paramJSON);
//对返回数据进行指定排序
List<PayOrderCount> records = countPage.getRecords();
Collections.sort(records, new Comparator<PayOrderCount>() {
@Override
public int compare(PayOrderCount o1, PayOrderCount o2) {
String wayTypeName1 = o1.getName();
String wayTypeName2 = o2.getName();
List<String> orderList = Arrays.asList("微信", "支付宝", "云闪付","银联","数字人民币","其他");
int indexOf1 = orderList.indexOf(wayTypeName1);
int indexOf2 = orderList.indexOf(wayTypeName2);
return indexOf1 - indexOf2;
}
});
break;
case CS.STATISTIC_TYPE.DEVICE:
// 设备
countPage = statsDeviceService.selectStatsList(paramJSON, null);
break;
case CS.STATISTIC_TYPE.MCH:
//商户统计
countPage = statsTradeService.selectByMch(paramJSON,null);
break;
default:
break;
}
// 解决hasnext不显示的问题
countPage.setCurrent(paramJSON.getIntValue("pageNumber"));
countPage.setSize(paramJSON.getIntValue("pageSize"));
return ApiRes.page(countPage);
}
}

View File

@@ -0,0 +1,86 @@
package com.jeequan.jeepay.mch.ctrl.statistics;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.StatsDeviceService;
import com.jeequan.jeepay.service.impl.StatsPayWayService;
import com.jeequan.jeepay.service.impl.StatsTradeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 总计接口
*
* @author xiaoyu
*
* @date 2022/5/23 16:52
*/
@Slf4j
@RestController
@RequestMapping("/api/statistic/total")
public class TotalStatisticController extends CommonCtrl {
@Autowired private StatsTradeService statsTradeService;
@Autowired private StatsPayWayService statsPayWayService;
@Autowired private StatsDeviceService statsDeviceService;
/**
* @author: xiaoyu
* @date: 2022/5/23 17:15
* @describe: 总计
*/
@PreAuthorize("hasAnyAuthority('ENT_STATISTIC_TRANSACTION', 'ENT_STATISTIC_MCH_STORE', 'ENT_STATISTIC_MCH_WAY', 'ENT_STATISTIC_MCH_TYPE')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes total() {
JSONObject paramJSON = getReqParamJSON();
PayOrder payOrder = getObject(PayOrder.class);
String method = getValStringRequired("method");
String mchNo = getCurrentMchNo();
payOrder.setMchNo(mchNo);
paramJSON.put("mchNo", mchNo);
// 门店ID条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
paramJSON.put("storeIdList", storeIdList);
PayOrderCount orderCount = null;
switch (method) {
case CS.STATISTIC_TYPE.TRANSACTION:
// 交易报表统计
orderCount = statsTradeService.selectTotalByTransaction(paramJSON, null);
break;
case CS.STATISTIC_TYPE.STORE:
// 门店统计
orderCount = statsTradeService.selectTotalByStore(paramJSON, null);
break;
case CS.STATISTIC_TYPE.WAY_CODE:
// 支付方式统计
orderCount = statsPayWayService.selectTotalByPayWay(paramJSON);
break;
case CS.STATISTIC_TYPE.WAY_CODE_TYPE:
// 支付类型统计
orderCount = statsPayWayService.selectTotalByWayCodeType(paramJSON);
break;
case CS.STATISTIC_TYPE.DEVICE:
// 设备统计
orderCount = statsDeviceService.selectTotalByDeviceNo(paramJSON, null);
break;
case CS.STATISTIC_TYPE.MCH:
// 商户统计
orderCount = statsTradeService.selectTotalByTransaction(paramJSON, null);
break;
default:
break;
}
return ApiRes.ok(orderCount);
}
}

View File

@@ -0,0 +1,57 @@
package com.jeequan.jeepay.mch.ctrl.store;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.DeviceProvideConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.DeviceProvideConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 设备厂商配置管理类
*
* @author zx
*
* @date 2021-12-28 09:15
*/
@Slf4j
@RestController
@RequestMapping("api/device/provider")
public class DeviceProvideConfigController extends CommonCtrl {
@Autowired private DeviceProvideConfigService deviceProvideConfigService;
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 厂商配置列表
*/
@PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_LIST', 'ENT_DEVICE_PRINTER_LIST', 'ENT_DEVICE_SPEAKER_ADD'," +
"'ENT_DEVICE_PRINTER_ADD', 'ENT_DEVICE_SPEAKER_EDIT', 'ENT_DEVICE_PRINTER_EDIT')")
@GetMapping
public ApiRes pages() {
LambdaQueryWrapper<DeviceProvideConfig> gw = DeviceProvideConfig.gw();
gw.select(DeviceProvideConfig::getConfigId, DeviceProvideConfig::getConfigDesc, DeviceProvideConfig::getProvider);
gw.orderByDesc(DeviceProvideConfig::getCreatedAt);
gw.eq(DeviceProvideConfig::getDeviceType, getValByteRequired("deviceType"));
if (null != getValByte("state")) {
gw.eq(DeviceProvideConfig::getState, getValByte("state"));
}
gw.select(DeviceProvideConfig::getConfigId, DeviceProvideConfig::getConfigDesc, DeviceProvideConfig::getDeviceType, DeviceProvideConfig::getProvider,
DeviceProvideConfig::getCreatedAt, DeviceProvideConfig::getAppId, DeviceProvideConfig::getState);
IPage<DeviceProvideConfig> page = deviceProvideConfigService.page(getIPage(true), gw);
//返回数据
return ApiRes.page(page);
}
}

View File

@@ -0,0 +1,275 @@
package com.jeequan.jeepay.mch.ctrl.store;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApiMapConfig;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* 商户门店管理
*
* @date 2021/12/29 9:52
*/
@RestController
@RequestMapping("/api/mchStore")
public class MchStoreController extends CommonCtrl {
@Autowired
private MchStoreService mchStoreService;
@Autowired
private MchInfoService mchInfoService;
@Autowired
private SysUserMchStoreRelaService sysUserMchStoreRelaService;
@Autowired
private MchApplymentService mchApplymentService;
@Autowired
private MchAppService mchAppService;
@Autowired
private MchStoreDeviceService mchStoreDeviceService;
@Autowired
private MchQrcodeCardService qrcodeCardService;
/**
* @date: 2021/12/29 9:53
* @describe: 门店列表查询
*/
@GetMapping
@PreAuthorize("hasAuthority('ENT_MCH_STORE_LIST')")
public ApiRes list() {
MchStore mchStore = getObject(MchStore.class);
mchStore.setMchNo(getCurrentMchNo());
// 门店条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
if (CollectionUtil.isNotEmpty(storeIdList)) {
mchStore.setStoreIdList(storeIdList);
}
IPage<MchStore> mchStoreList = mchStoreService.listByPage(getIPage(true), mchStore, getReqParamJSON());
return ApiRes.page(mchStoreList);
}
/**
* @date: 2021/12/29 9:59
* @describe: 新建门店
*/
@MethodLog(remark = "新建门店")
@PostMapping
@PreAuthorize("hasAuthority('ENT_MCH_STORE_ADD')")
public ApiRes add() {
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
MchStore mchStore = getObject(MchStore.class);
mchStore.setStoreId(SeqKit.genStoreNo());
Assert.notNull(mchStore.getAreaCode(), "请选择省市区");
mchStore.setMchNo(getCurrentMchNo());
//关联商户信息原进件信息t_mch_applyment需要校验商户状态必须是进件成功的
Assert.hasLength(mchStore.getMchApplyId(), "进件id不能为空! ");
MchApplyment tbMchApplyment = mchApplymentService.getById(mchStore.getMchApplyId());
if (MchApplyment.STATE_SUCCESS != tbMchApplyment.getState()) {
return ApiRes.customFail("该商户状态未进件成功!");
}
//校验指定商户号下的进件信息
String applyMchNo = tbMchApplyment.getMchNo();
String storeMchNo = mchStore.getMchNo();
if (!Objects.equals(applyMchNo, storeMchNo)) {
return ApiRes.customFail("商户信息与进件信息不匹配!");
}
// 初始为非默认门店
mchStore.setDefaultFlag(CS.NO);
mchStore.setAgentNo(mchInfo.getAgentNo());
mchStore.setTopAgentNo(mchInfo.getTopAgentNo());
// mchStore.setIsvNo(mchInfo.getIsvNo());
//门店默认应用为商户绑定的应用
MchApplyment mchApplymentById = mchApplymentService.getById(mchStore.getMchApplyId());
mchStore.setBindAppId(mchApplymentById.getAutoConfigMchAppId());
boolean result = mchStoreService.save(mchStore);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
}
return ApiRes.ok();
}
/**
* @date: 2021/12/29 9:59
* @describe: 门店详情
*/
@GetMapping("/{recordId}")
@PreAuthorize("hasAuthority('ENT_MCH_STORE_VIEW')")
public ApiRes detail(@PathVariable("recordId") String recordId) {
MchStore mchStore = mchStoreService.getById(recordId);
if (mchStore == null || !mchStore.getMchNo().equals(getCurrentMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(mchStore);
}
/**
* @author: xiaoyu
* @date: 2021/12/29 10:00
* @describe: 更新门店
*/
@MethodLog(remark = "更新门店")
@PutMapping("/{recordId}")
@PreAuthorize("hasAnyAuthority('ENT_MCH_STORE_EDIT', 'ENT_MCH_STORE_APP_DIS')")
public ApiRes update(@PathVariable("recordId") String recordId) {
MchStore mchStore = getObject(MchStore.class);
mchStore.setStoreId(recordId);
mchStore.setMchNo(null);
mchStore.setAgentNo(null);
mchStore.setTopAgentNo(null);
mchStore.setCreatedAt(null);
mchStore.setUpdatedAt(null);
MchStore dbRecord = mchStoreService.getById(recordId);
if (!dbRecord.getMchNo().equals(getCurrentMchNo())) {
throw new BizException("无权操作!");
}
// 如果修改当前为默认
if (mchStore.getDefaultFlag() != null && mchStore.getDefaultFlag() == CS.YES) {
mchStoreService.updateAllDefaultFlag(getCurrentMchNo());
} else {
mchStore.setDefaultFlag(null);
}
//门店应用为商户绑定的应用
MchApplyment mchApplymentById = mchApplymentService.getById(mchStore.getMchApplyId());
mchStore.setBindAppId(mchApplymentById.getAutoConfigMchAppId());
boolean result = mchStoreService.updateById(mchStore);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
/**
* @date: 2021/12/29 10:05
* @describe: 删除门店
*/
@MethodLog(remark = "删除门店")
@DeleteMapping("/{recordId}")
@PreAuthorize("hasAuthority('ENT_MCH_STORE_DELETE')")
public ApiRes delete(@PathVariable("recordId") String recordId) {
MchStore mchStore = mchStoreService.getById(recordId);
if (!mchStore.getMchNo().equals(getCurrentMchNo())) {
throw new BizException("无权操作!");
}
if (mchStore.getDefaultFlag() == CS.YES) {
throw new BizException("默认门店无法删除!");
}
mchStoreService.deleteStore(recordId, false);
return ApiRes.ok();
}
/**
* @date: 2022/11/30 10:41
* @describe: 经纬度转换为areacode
*/
@GetMapping("/location2areacode")
@PreAuthorize("hasAuthority('ENT_MCH_STORE_MAP')")
public ApiRes location2areacode() {
try {
// 经纬度 逗号分隔
String location = getValStringRequired("location");
DBApiMapConfig apiMapConfig = sysConfigService.getDBApiMapConfig();
String result = HttpUtil.get("https://restapi.amap.com/v3/geocode/regeo?key=" + apiMapConfig.getApiMapWebServiceKey() + "&location=" + location);
JSONObject resObject = JSONObject.parseObject(result);
String areacode = resObject.getJSONObject("regeocode").getJSONObject("addressComponent").getString("adcode");
JSONObject resJSON = new JSONObject();
resJSON.put("areacode", areacode);
return ApiRes.ok(resJSON);
} catch (Exception e) {
logger.error("经纬度转换为areacode异常", e);
return ApiRes.ok(new JSONObject());
}
}
/**
* @date: 2022/2/19 10:41
* @describe: 获取地图配置参数
*/
@GetMapping("/mapConfig")
@PreAuthorize("hasAuthority('ENT_MCH_STORE_MAP')")
public ApiRes getMapConfig() {
DBApiMapConfig apiMapConfig = sysConfigService.getDBApiMapConfig();
return ApiRes.ok(apiMapConfig);
}
/**
* @date: 2021/12/29 9:53
* @describe: 门店列表查询
*/
@GetMapping("/bindStoreList")
@PreAuthorize("hasAuthority('ENT_MCH_STORE_LIST')")
public ApiRes bindStoreList() {
JSONObject paramJSON = getReqParamJSON();
MchStore mchStore = getObject(MchStore.class);
mchStore.setMchNo(getCurrentMchNo());
// 门店条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
if (CollectionUtil.isNotEmpty(storeIdList)) {
mchStore.setStoreIdList(storeIdList);
}
IPage<MchStore> mchStoreList = mchStoreService.getBindStoreList(getIPage(true), mchStore, paramJSON);
return ApiRes.page(mchStoreList);
}
/**
* 查询已绑定集合
*/
@GetMapping("/userStoreRelas")
@PreAuthorize("hasAuthority('ENT_MCH_STORE_LIST')")
public ApiRes userStoreRelas() {
LambdaQueryWrapper<SysUserMchStoreRela> queryWrapper = SysUserMchStoreRela.gw();
queryWrapper.eq(SysUserMchStoreRela::getSysUserId, getValLongRequired("sysUserId"));
IPage<SysUserMchStoreRela> pages = sysUserMchStoreRelaService.page(getIPage(true), queryWrapper);
return ApiRes.page(pages);
}
}

View File

@@ -0,0 +1,674 @@
package com.jeequan.jeepay.mch.ctrl.store;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchInfo;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.device.IPrinterService;
import com.jeequan.jeepay.core.interfaces.device.ISpeakerService;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.device.PayOrderInfo4Device;
import com.jeequan.jeepay.core.utils.DateKit;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.MarketAdvertService;
import com.jeequan.jeepay.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 设备厂商配置管理类
*
* @author zx
*
* @date 2021-12-28 09:15
*/
@Slf4j
@RestController
@RequestMapping("/api/store/device")
public class MchStoreDeviceController extends CommonCtrl {
@Autowired private DeviceProvideConfigService deviceProvideConfigService;
@Autowired private MchStoreDeviceService mchStoreDeviceService;
@Autowired private MchInfoService mchInfoService;
@Autowired private MchAppService mchAppService;
@Autowired private MchStoreService mchStoreService;
@Autowired private MchQrcDeviceRelaService mchQrcDeviceRelaService;
@Autowired private MchQrcodeCardService mchQrcodeCardService;
@Autowired private MarketAdvertService marketAdvertService;
@Autowired private MchApplymentService mchApplymentService;
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 门店设备列表
*/
@PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_LIST', 'ENT_DEVICE_PRINTER_LIST', 'ENT_DEVICE_POS_LIST', 'ENT_DEVICE_PLUGIN_CDKEY_LIST'," +
"'ENT_DEVICE_AUTO_POS_LIST', 'ENT_DEVICE_FACE_APP_LIST', 'ENT_DEVICE_RUYI_LIST')")
@GetMapping
public ApiRes pages() {
MchStoreDevice mchStoreDevice = getObject(MchStoreDevice.class);
mchStoreDevice.setMchNo(getCurrentMchNo());
// mchStoreDevice.setBindState(CS.YES);
mchStoreDevice.addExt("appSearchData", getValString("appSearchData"));
// 门店条件
List<String> storeIdList = getCurrentUser().getStoreIdList();
if (CollectionUtil.isNotEmpty(storeIdList)) {
mchStoreDevice.setStoreIdList(storeIdList);
}
IPage<MchStoreDevice> page = mchStoreDeviceService.selectPage(getIPage(), mchStoreDevice);
//返回数据
return ApiRes.page(page);
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 检查设备是否允许绑定
*/
@PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_ADD', 'ENT_DEVICE_PRINTER_ADD', 'ENT_DEVICE_POS_ADD', 'ENT_DEVICE_AUTO_POS_ADD'," +
"'ENT_DEVICE_FACE_APP_ADD', 'ENT_DEVICE_RUYI_ADD')")
@MethodLog(remark = "检查设备是否允许绑定")
@PostMapping("/check/{deviceNo}")
public ApiRes getProvider(@PathVariable("deviceNo") String deviceNo) {
Byte deviceType = getValByteRequired("deviceType"); // 1-喇叭 2-打印机
// 校验是否可绑定并返回可绑定设备ID
JSONObject checkJSON = checkDeviceBindInfo(deviceNo, null, deviceType);
return ApiRes.ok(checkJSON);
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 新增门店设备
*/
@PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_ADD', 'ENT_DEVICE_PRINTER_ADD', 'ENT_DEVICE_POS_ADD', 'ENT_DEVICE_AUTO_POS_ADD'," +
"'ENT_DEVICE_FACE_APP_ADD', 'ENT_DEVICE_RUYI_ADD')")
@MethodLog(remark = "新增门店设备")
@PostMapping
public ApiRes add() {
MchStoreDevice mchStoreDevice = getObject(MchStoreDevice.class);
Byte deviceType = getValByteRequired("deviceType");
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
// 校验是否可绑定并返回可绑定设备ID
JSONObject checkJSON = checkDeviceBindInfo(mchStoreDevice.getDeviceNo(), mchStoreDevice.getProvider(), deviceType);
if (checkJSON.getInteger("checkCode") != 1) {
return ApiRes.customFail(checkJSON.getString("checkMsg"));
}
Long deviceId = checkJSON.getLong("deviceId");
// 扫码POS需绑定商户应用未传入商户appId 则使用默认应用
String appId = mchStoreDevice.getAppId();
if (deviceType == MchStoreDevice.DEVICE_TYPE_POS && StringUtils.isEmpty(appId)) {
appId = mchAppService.getDefaultApp(mchInfo.getMchNo()).getAppId();
}
MchStoreDevice updateRecord = new MchStoreDevice();
updateRecord.setDeviceId(deviceId);
updateRecord.setDeviceName(mchStoreDevice.getDeviceName());
updateRecord.setBindState(CS.YES);
updateRecord.setMchNo(mchInfo.getMchNo());
updateRecord.setAppId(appId);
updateRecord.setStoreId(mchStoreDevice.getStoreId());
updateRecord.setBindType(mchStoreDevice.getBindType());
updateRecord.setAgentNo(mchInfo.getAgentNo());
//获取商户信息
MchStore mchStore = mchStoreService.getById(mchStoreDevice.getStoreId());
if(mchStore == null){
throw new BizException("门店不存在!");
}
if (StringUtils.isNotEmpty(mchStore.getMchApplyId())){
MchApplyment applyment = mchApplymentService.getById(mchStore.getMchApplyId());
if (applyment != null){
updateRecord.setMchApplyName(applyment.getMchShortName());
updateRecord.setMchApplyId(mchStore.getMchApplyId());
}
}
// 云喇叭 同步绑定码牌
if (deviceType == MchStoreDevice.DEVICE_TYPE_SPEAKER) {
String qrcIdListStr = getValString("qrcIdList");
// 绑定类型 为码牌时需传入绑定的码牌id
List<Long> qrcList = new LinkedList<>();
if (null != mchStoreDevice.getBindType() && mchStoreDevice.getBindType() == MchStoreDevice.DEVICE_BIND_TYPE_QRC && StringUtils.isNotBlank(qrcIdListStr)) {
qrcList = JSONArray.parseArray(qrcIdListStr, Long.class);
}
Long bindQrcId = checkJSON.getLong("bindQrcId"); // 初始绑定的码牌ID
boolean result = mchStoreDeviceService.bindSpeakerDevice(updateRecord, bindQrcId, qrcList);
if (!result) {
return ApiRes.customFail("绑定失败");
}
return ApiRes.ok();
}
// 云打印、扫码pos执行更新
if (mchStoreDeviceService.updateById(updateRecord)) {
return ApiRes.ok();
}
return ApiRes.customFail("绑定失败");
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 门店设备修改
*/
@PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_EDIT', 'ENT_DEVICE_PRINTER_EDIT', 'ENT_DEVICE_POS_EDIT', 'ENT_DEVICE_PLUGIN_CDKEY_EDIT'," +
"'ENT_DEVICE_AUTO_POS_EDIT', 'ENT_DEVICE_FACE_APP_EDIT', 'ENT_DEVICE_RUYI_EDIT')")
@MethodLog(remark = "门店设备修改")
@PutMapping("/{deviceId}")
public ApiRes update(@PathVariable("deviceId") Long deviceId) {
MchStoreDevice mchStoreDevice = getObject(MchStoreDevice.class);
mchStoreDevice.setDeviceId(deviceId);
// 不能修改项
mchStoreDevice.setDeviceNo(null);
mchStoreDevice.setDeviceParams(null);
mchStoreDevice.setBatchId(null);
mchStoreDevice.setDeviceType(null);
mchStoreDevice.setCreatedAt(null);
mchStoreDevice.setUpdatedAt(null);
MchStoreDevice dbRecord = mchStoreDeviceService.getById(deviceId);
if (!getCurrentMchNo().equals(dbRecord.getMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
mchStoreDevice.setMchNo(dbRecord.getMchNo());
mchStoreDevice.setBindType(dbRecord.getBindType());
//获取商户信息
MchStore mchStore = mchStoreService.getById(dbRecord.getStoreId());
if(mchStore == null){
throw new BizException("门店不存在!");
}
if (StringUtils.isNotEmpty(mchStore.getMchApplyId())){
MchApplyment applyment = mchApplymentService.getById(mchStore.getMchApplyId());
if (applyment != null){
mchStoreDevice.setMchApplyName(applyment.getMchShortName());
mchStoreDevice.setMchApplyId(mchStore.getMchApplyId());
}
}
// 云喇叭 同步绑定码牌
if (dbRecord.getDeviceType() == MchStoreDevice.DEVICE_TYPE_SPEAKER) {
// 绑定类型 为码牌时需传入绑定的码牌id
List<Long> qrcList = new LinkedList<>();
if (null != mchStoreDevice.getBindType() && mchStoreDevice.getBindType() == MchStoreDevice.DEVICE_BIND_TYPE_QRC) {
qrcList = JSONArray.parseArray(getValStringRequired("qrcIdList"), Long.class);
}
boolean result = mchStoreDeviceService.bindSpeakerDevice(mchStoreDevice, dbRecord.getBindQrcId(), qrcList);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
//如果更新金额则需要关联到码牌表进行同步更新
//判断是否绑定了码牌
if (mchStoreDevice.getBindQrcId() != null){
MchQrcodeCard mchQrcodeCard = mchQrcodeCardService.getById(mchStoreDevice.getBindQrcId());
if (mchQrcodeCard != null){
mchQrcodeCard.setFixedFlag(mchStoreDevice.getFixedFlag());
mchQrcodeCard.setFixedPayAmount(mchStoreDevice.getFixedPayAmount());
mchQrcodeCardService.updateById(mchQrcodeCard);
}
}
return ApiRes.ok();
}
// 云打印、扫码pos执行更新
if (mchStoreDeviceService.updateById(mchStoreDevice)) {
return ApiRes.ok();
}
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 解绑设备
*/
@PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_EDIT', 'ENT_DEVICE_PRINTER_EDIT', 'ENT_DEVICE_POS_EDIT', 'ENT_DEVICE_AUTO_POS_EDIT'," +
"'ENT_DEVICE_FACE_APP_EDIT', 'ENT_DEVICE_RUYI_EDIT')")
@PostMapping("/unbind/{deviceId}")
public ApiRes unbind(@PathVariable("deviceId") Long deviceId) {
MchStoreDevice dbRecord = mchStoreDeviceService.getById(deviceId);
if (dbRecord == null || !dbRecord.getMchNo().equals(getCurrentMchNo()) || dbRecord.getBindState() != CS.YES) {
return ApiRes.customFail("解绑失败");
}
mchStoreDeviceService.unbind(dbRecord);
return ApiRes.ok();
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 根据ID获取门店设备
*/
@PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_VIEW', 'ENT_DEVICE_PRINTER_VIEW', 'ENT_DEVICE_POS_VIEW', 'ENT_DEVICE_PLUGIN_CDKEY_VIEW'," +
"'ENT_DEVICE_FACE_APP_VIEW', 'ENT_DEVICE_RUYI_VIEW')")
@GetMapping("/{deviceId}")
public ApiRes get(@PathVariable("deviceId") Long deviceId) {
MchStoreDevice dbRecord = mchStoreDeviceService.getById(deviceId);
if (!getCurrentMchNo().equals(dbRecord.getMchNo())) {
return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
// 门店名称
if (dbRecord.getStoreId() != null) {
MchStore mchStore = mchStoreService.getById(dbRecord.getStoreId());
dbRecord.addExt("storeName", mchStore.getStoreName());
}
// 应用名称
if (StringUtils.isNotBlank(dbRecord.getAppId())) {
MchAppEntity mchAppEntity = mchAppService.getById(dbRecord.getAppId());
dbRecord.addExt("appName", mchAppEntity.getAppName());
}
List<MchQrcDeviceRela> relaList = mchQrcDeviceRelaService.list(MchQrcDeviceRela.gw().eq(MchQrcDeviceRela::getDeviceId, deviceId));
if (!CollectionUtils.isEmpty(relaList)) {
// 已绑定的码牌集合
List<Long> qrcIdList = relaList.stream().map(MchQrcDeviceRela::getQrcId).collect(Collectors.toList());
List<MchQrcodeCard> qrcList = mchQrcodeCardService.list(MchQrcodeCard.gw()
.select(MchQrcodeCard::getQrcId, MchQrcodeCard::getQrcAlias)
.in(MchQrcodeCard::getQrcId, qrcIdList));
dbRecord.addExt("qrcIdList", qrcIdList);
dbRecord.addExt("qrcList", qrcList);
}
return ApiRes.ok(dbRecord);
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 播报测试
*/
@PreAuthorize("hasAuthority('ENT_DEVICE_SPEAKER_TEST')")
@PostMapping("/speak/{deviceId}")
public ApiRes speak(@PathVariable("deviceId") Long deviceId) {
Long amountL = getRequiredAmountL("amount");
MchStoreDevice mchStoreDevice = mchStoreDeviceService.getOne(MchStoreDevice.gw().eq(MchStoreDevice::getMchNo, getCurrentMchNo()).eq(MchStoreDevice::getDeviceId, deviceId));
if (mchStoreDevice == null) {
return ApiRes.customFail("设备不存在");
}
if(mchStoreDevice.getState() != CS.YES || mchStoreDevice.getBindState() != CS.YES){
return ApiRes.customFail("设备已停用或还未绑定");
}
DeviceProvideConfig provideConfig = deviceProvideConfigService.getById(mchStoreDevice.getConfigId());
if (provideConfig == null || provideConfig.getState() != CS.YES) {
return ApiRes.customFail("设备厂商未配置");
}
// 设备类型
String provider = mchStoreDevice.getProvider();
ISpeakerService speakerService = SpringBeansUtil.getBean(provider + "SpeakerService", ISpeakerService.class);
// 设备参数
JSONObject deviceParams = new JSONObject();
deviceParams.put("deviceParams", mchStoreDevice.getDeviceParams());
deviceParams.put("bizConfigParams", mchStoreDevice.getBizConfigParams());
deviceParams.put("providerParams", provideConfig.getProviderParams());
// 消息内容
PayOrderInfo4Device speakPayOrderInfo = new PayOrderInfo4Device();
speakPayOrderInfo.setAmount(amountL);
speakPayOrderInfo.setWayCodeType(CS.PAY_WAY_CODE_TYPE.WECHAT);
speakPayOrderInfo.setPayOrderId(String.valueOf(DateKit.currentTimeMillis()));
try {
speakerService.send(deviceParams, speakPayOrderInfo);
return ApiRes.ok();
}catch (BizException e) {
throw e;
}
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 打印测试
*/
@PreAuthorize("hasAuthority('ENT_DEVICE_PRINTER_TEST')")
@PostMapping("/print/{deviceId}")
public ApiRes print(@PathVariable("deviceId") Long deviceId) {
Long amountL = getRequiredAmountL("amount");
MchStoreDevice mchStoreDevice = mchStoreDeviceService.getOne(MchStoreDevice.gw().eq(MchStoreDevice::getMchNo, getCurrentMchNo()).eq(MchStoreDevice::getDeviceId, deviceId));
if (mchStoreDevice == null || mchStoreDevice.getState() != CS.YES) {
return ApiRes.customFail("设备不存在");
}
DeviceProvideConfig provideConfig = deviceProvideConfigService.getById(mchStoreDevice.getConfigId());
if (provideConfig == null || provideConfig.getState() != CS.YES) {
return ApiRes.customFail("设备厂商未配置");
}
// 设备类型
String provider = mchStoreDevice.getProvider();
IPrinterService printerService = SpringBeansUtil.getBean(provider + "PrinterService", IPrinterService.class);
// 设备参数
JSONObject deviceParams = new JSONObject();
deviceParams.put("deviceParams", mchStoreDevice.getDeviceParams());
deviceParams.put("bizConfigParams", mchStoreDevice.getBizConfigParams());
deviceParams.put("providerParams", provideConfig.getProviderParams());
// 消息内容
PayOrderInfo4Device printPayOrderInfo = new PayOrderInfo4Device();
printPayOrderInfo.setAmount(amountL);
printPayOrderInfo.setWayCodeType(CS.PAY_WAY_CODE_TYPE.WECHAT);
printPayOrderInfo.setPayOrderId(String.valueOf(DateKit.currentTimeMillis()));
printPayOrderInfo.setCreatedAt(DateUtil.date());
try {
printerService.send(deviceParams, printPayOrderInfo);
return ApiRes.ok();
}catch (BizException e) {
throw e;
}
}
/**
* @author: zx
* @date: 2021-12-28 09:15
* @describe: 清空打印队列
*/
@PreAuthorize("hasAuthority('ENT_DEVICE_PRINTER_CLEAR')")
@PostMapping("/clear/{deviceId}")
public ApiRes clear(@PathVariable("deviceId") Long deviceId) {
MchStoreDevice mchStoreDevice = mchStoreDeviceService.getOne(MchStoreDevice.gw().eq(MchStoreDevice::getMchNo, getCurrentMchNo()).eq(MchStoreDevice::getDeviceId, deviceId));
if (mchStoreDevice == null || mchStoreDevice.getState() != CS.YES) {
return ApiRes.customFail("设备不存在");
}
DeviceProvideConfig provideConfig = deviceProvideConfigService.getById(mchStoreDevice.getConfigId());
if (provideConfig == null || provideConfig.getState() != CS.YES) {
return ApiRes.customFail("设备厂商未配置");
}
// 设备类型
String provider = mchStoreDevice.getProvider();
IPrinterService printerService = SpringBeansUtil.getBean(provider + "PrinterService", IPrinterService.class);
// 设备参数
JSONObject deviceParams = new JSONObject();
deviceParams.put("deviceParams", mchStoreDevice.getDeviceParams());
deviceParams.put("bizConfigParams", mchStoreDevice.getBizConfigParams());
deviceParams.put("providerParams", provideConfig.getProviderParams());
try {
printerService.clearPrinter(deviceParams);
return ApiRes.ok();
}catch (Exception e) {
return ApiRes.customFail(e.getMessage());
}
}
/** 校验设备能否绑定 */
private JSONObject checkDeviceBindInfo(String deviceNo, String provider, Byte deviceType) {
if (StringUtils.isBlank(deviceNo)) {
throw new BizException("deviceNo必填");
}
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
String agentNo = mchInfo.getAgentNo();
LambdaQueryWrapper<MchStoreDevice> wrapper = MchStoreDevice.gw()
.eq(MchStoreDevice::getDeviceNo, deviceNo)
.eq(MchStoreDevice::getDeviceType, deviceType)
.eq(MchStoreDevice::getBindState, CS.NO);
// 当前商户存在上级代理,查询上级服务商或平台未划拨的设备
if (StringUtils.isNotBlank(agentNo)) {
wrapper.and(wr -> {
wr.eq(StringUtils.isNotBlank(agentNo), MchStoreDevice::getAgentNo, agentNo)
.or().eq(MchStoreDevice::getAgentNo, "")
.or().isNull(MchStoreDevice::getAgentNo);
});
// 查询未划拨的设备
}else {
wrapper.and(wr -> {
wr.eq(MchStoreDevice::getAgentNo, "")
.or().isNull(MchStoreDevice::getAgentNo);
});
}
if (StringUtils.isNotBlank(provider)) {
wrapper.eq(MchStoreDevice::getProvider, provider);
}
List<MchStoreDevice> deviceList = mchStoreDeviceService.list(wrapper);
// 方法返回内容 { checkCode: "", checkMsg: "" }
// checkCode0-不存在,无法绑定 1-仅存在一个,可直接绑定 2-存在多个,需选择厂商
// checkMsg 错误原因
JSONObject res = new JSONObject();
// 未查询到设备
if (CollectionUtils.isEmpty(deviceList)) {
res.put("checkCode", "0");
res.put("checkMsg", "当前设备无法绑定");
}
// 查询到多个厂商
else if (deviceList.size() > 1) {
res.put("checkCode", "2");
res.put("deviceList", deviceList);
res.put("checkMsg", "请选择厂商");
}
else {
res.put("checkCode", "1");
res.put("checkMsg", "当前设备允许绑定");
res.put("deviceId", deviceList.get(0).getDeviceId()); // 可绑定的设备号
res.put("bindQrcId", deviceList.get(0).getBindQrcId()); // 初始绑定码牌ID
}
return res;
}
@MethodLog(remark = "获取营销设备广告详情")
@RequestMapping(value="/getMarketAdvertInfo/{deviceNo}", method = RequestMethod.GET)
public ApiRes getMarketAdvertInfo(@PathVariable("deviceNo") String deviceNo) {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setDeviceNo(deviceNo);
record.setMchNo(getCurrentMchNo());
JSONObject result = marketAdvertService.getMarketAdvertInfo(record);
return ApiRes.ok(result);
}
/**
* 获取跑马灯广告
* @return
*/
@MethodLog(remark = "获取设备跑马灯广告配置")
@RequestMapping(value="/getMarqueeInfo/{deviceNo}", method = RequestMethod.GET)
public ApiRes getMarqueeInfo(@PathVariable("deviceNo") String deviceNo) {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setDeviceNo(deviceNo);
record.setMchNo(getCurrentMchNo());
JSONObject result = marketAdvertService.getMarqueeInfo(record);
return ApiRes.ok(result);
}
/**
* 设置跑马灯广告
* @return
*/
@MethodLog(remark = "设备跑马灯广告配置")
@RequestMapping(value="/setMarqueeInfo", method = RequestMethod.POST)
public ApiRes setMarqueeInfo() {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setMchNo(getCurrentMchNo());
marketAdvertService.saveMarqueeInfo(record);
return ApiRes.ok();
}
/**
* 获取设备坐标信息
* @return
*/
@MethodLog(remark = "获取设备营销区坐标信息")
@RequestMapping(value="/getMarketPoint/{deviceNo}", method = RequestMethod.GET)
public ApiRes getMarketLocation(@PathVariable("deviceNo") String deviceNo) {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setDeviceNo(deviceNo);
record.setMchNo(getCurrentMchNo());
JSONObject result = marketAdvertService.getMarketLocation(record);
return ApiRes.ok(result);
}
/**
* 获取设备图片信息
* @return
*/
@MethodLog(remark = "获取设备营销区图片信息")
@RequestMapping(value="/getMarketPic/{deviceNo}", method = RequestMethod.GET)
public ApiRes getMarketPic(@PathVariable("deviceNo") String deviceNo) {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setDeviceNo(deviceNo);
record.setMchNo(getCurrentMchNo());
JSONArray result = marketAdvertService.getMarketPic(record);
return ApiRes.ok(result);
}
/**
* 设置营销区域的图片信息
* @return
*/
@MethodLog(remark = "设置营销区域的图片信息")
@RequestMapping(value="/setMarketPic", method = RequestMethod.POST)
public ApiRes setMarketPic() {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setMchNo(getCurrentMchNo());
marketAdvertService.saveMarketPic(record);
return ApiRes.ok();
}
/**
* 设置营销区域的图片信息
* @return
*/
@MethodLog(remark = "查询设备活动码信息")
@RequestMapping(value="/getActivityQrCode/{deviceNo}", method = RequestMethod.GET)
public ApiRes getActivityQrCode(@PathVariable("deviceNo") String deviceNo) {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setDeviceNo(deviceNo);
record.setMchNo(getCurrentMchNo());
JSONObject result = marketAdvertService.getActivityQrCode(record);
return ApiRes.ok(result);
}
/**
* 获取设备付款码坐标
* @return
*/
@MethodLog(remark = "获取设备付款区域坐标")
@RequestMapping(value="/getMarketPayCodeInfo/{deviceNo}", method = RequestMethod.GET)
public ApiRes getMarketPayCodeInfo(@PathVariable("deviceNo") String deviceNo) {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setDeviceNo(deviceNo);
record.setMchNo(getCurrentMchNo());
JSONObject result = marketAdvertService.getMarketPayCodeInfo(record);
return ApiRes.ok(result);
}
/**
* 获取设备付款区域图片信息
* @return
*/
@MethodLog(remark = "获取设备付款区域图片信息")
@RequestMapping(value="/getMarketPayCodePic/{deviceNo}", method = RequestMethod.GET)
public ApiRes getMarketPayCodePic(@PathVariable("deviceNo") String deviceNo) {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setDeviceNo(deviceNo);
record.setMchNo(getCurrentMchNo());
JSONObject result = marketAdvertService.getMarketPayCodePic(record);
return ApiRes.ok(result);
}
/**
* 设置设备付款区域的图片信息
* @return
*/
@MethodLog(remark = "设置设备付款区域的图片信息")
@RequestMapping(value="/setMarketPayCodePic", method = RequestMethod.POST)
public ApiRes setMarketPayCodePic() {
MchStoreDevice record = getObject(MchStoreDevice.class);
record.setMchNo(getCurrentMchNo());
marketAdvertService.setMarketPayCodePic(record);
return ApiRes.ok();
}
/*
* // 飞鹅云打印 同步修改上游
String provider = mchStoreDevice.getProvider();
if ("fe".equals(provider)) {
IPrinterService printerService = SpringBeansUtil.getBean(provider + "PrinterService", IPrinterService.class);
// 设备参数
JSONObject deviceParams = new JSONObject();
// 添加上游所需设备名称字段
JSONObject deviceJSON = JSONObject.parseObject(mchStoreDevice.getDeviceParams());
deviceJSON.put("deviceName", mchStoreDevice.getDeviceName());
deviceParams.put("deviceParams", deviceJSON.toJSONString());
deviceParams.put("bizConfigParams", mchStoreDevice.getBizConfigParams());
deviceParams.put("providerParams", deviceProvideConfig.getProviderParams());
try {
String editResult = printerService.editPrinter(deviceParams);
if (StringUtils.isBlank(editResult)) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
}catch (Exception e) {
return ApiRes.customFail(e.getMessage());
}
}
* */
}

View File

@@ -0,0 +1,160 @@
package com.jeequan.jeepay.mch.ctrl.store;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.StoreUserWorkRecord;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.StoreUserWorkRecordService;
import com.jeequan.jeepay.service.impl.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
/**
* 商户员工交接班记录管理
*
* @author yr
*
* @date 2023/01/31 10:21
*/
@Slf4j
@RestController
@RequestMapping("/api/user/workRecords")
public class StoreUserWorkRecordController extends CommonCtrl {
@Autowired private SysUserService sysUserService;
@Autowired private StoreUserWorkRecordService storeUserWorkRecordService;
/**
* 交接班列表查询
*/
@GetMapping
public ApiRes list() {
StoreUserWorkRecord queryRecord = getObject(StoreUserWorkRecord.class);
LambdaQueryWrapper<StoreUserWorkRecord> gw = StoreUserWorkRecord.gw();
gw.eq(StoreUserWorkRecord::getMchNo, getCurrentMchNo());
String storeId = queryRecord.getStoreId();
// 刷脸设备,只能查看其绑定门店
if (JWTPayload.LOGIN_PAGE_TYPE.FACE_APP.equals(getCurrentUser().getLoginType())) {
storeId = getCurrentUser().getStoreIdList().get(0);
}
gw.eq(storeId!= null, StoreUserWorkRecord::getStoreId, storeId);
Byte userType = getCurrentUser().getSysUser().getUserType();
// 店员 只能看自己
if (SysUser.UEST_TYPE_CASHIER == userType){
gw.eq(StoreUserWorkRecord::getSysUserId, getCurrentUser().getSysUserId());
}
if (StringUtils.isNotEmpty(queryRecord.getUserNo())){
gw.eq(StoreUserWorkRecord::getUserNo, queryRecord.getUserNo());
}
if (StringUtils.isNotEmpty(queryRecord.getRealname())){
gw.like(StoreUserWorkRecord::getRealname, queryRecord.getRealname());
}
// 时间搜索
Date[] searchDateRange = queryRecord.buildQueryDateRange();
gw.ge(searchDateRange[0] != null, StoreUserWorkRecord::getCreatedAt, searchDateRange[0]);
gw.le(searchDateRange[1] != null, StoreUserWorkRecord::getCreatedAt, searchDateRange[1]);
gw.orderByDesc(StoreUserWorkRecord::getCreatedAt);
IPage<StoreUserWorkRecord> page = storeUserWorkRecordService.page(getIPage(true), gw);
//返回数据
return ApiRes.page(page);
}
/**
* 交接班详情
*/
@GetMapping("/{id}")
public ApiRes detail(@PathVariable("id") Long id) {
StoreUserWorkRecord workRecord = storeUserWorkRecordService.getById(id);
workRecord.addExt("payAmount", workRecord.getSuccessAmount());
workRecord.addExt("payCount", workRecord.getSuccessCount());
return ApiRes.ok(workRecord);
}
/**
* 员工交接班打卡
*/
@MethodLog(remark = "员工交接班打卡")
@PostMapping
public ApiRes addOrUpdate() {
Byte workState = getValByte("workState");
if (workState != StoreUserWorkRecord.WORK_STATE_START && workState != StoreUserWorkRecord.WORK_STATE_END){
throw new BizException("请选择是上班还是下班打卡!");
}
// 目前仅支持刷脸设备上下班打卡
if (!JWTPayload.LOGIN_PAGE_TYPE.FACE_APP.equals(getCurrentUser().getLoginType())) {
throw new BizException("仅支持刷脸设备打卡");
}
// 设备绑定门店ID
String storeId = getCurrentUser().getStoreIdList().get(0);
SysUserEntity sysUserEntity = sysUserService.getById(getCurrentUser().getSysUserId());
// 获取当前用户的上班状态
Byte currentWorkState = storeUserWorkRecordService.getWorkState(storeId, sysUserEntity.getSysUserId());
if (currentWorkState.equals(workState)){
throw new BizException("请勿重复打卡!");
}
try {
storeUserWorkRecordService.addOrUpdateWorkAndUser(workState, sysUserEntity, getCurrentUser().getLoginType(), storeId);
} catch (Exception e){
log.error("【员工交接班打卡】异常", e);
throw new BizException("打卡失败,请稍后重试!");
}
return ApiRes.ok();
}
/**
* 员工交班统计
*/
@MethodLog(remark = "员工交班统计")
@GetMapping("/stats")
public ApiRes stats() {
StoreUserWorkRecord latestWorkRecord = storeUserWorkRecordService.getOne(StoreUserWorkRecord.gw()
.eq(StoreUserWorkRecord::getSysUserId, getCurrentUser().getSysUserId())
.orderByDesc(StoreUserWorkRecord::getCreatedAt)
.last("limit 1"));
if (latestWorkRecord == null) {
return ApiRes.ok();
}
String workStartTime = DateUtil.formatDateTime(latestWorkRecord.getWorkStartTime()); // 上班时间
String workEndTime = DateUtil.now(); // 下班时间
if (latestWorkRecord.getWorkEndTime() != null) {
workEndTime = DateUtil.formatDateTime(latestWorkRecord.getWorkEndTime());
}
JSONObject reqParamJSON = new JSONObject();
reqParamJSON.put("storeUserId", getCurrentUser().getSysUserId());
reqParamJSON.put("workStartTime", workStartTime);
reqParamJSON.put("workEndTime", workEndTime);
// 目前仅支持刷脸设备上下班打卡
if (!JWTPayload.LOGIN_PAGE_TYPE.FACE_APP.equals(getCurrentUser().getLoginType())) {
throw new BizException("仅支持刷脸设备");
}
JSONObject resJSON = storeUserWorkRecordService.workCount(getCurrentUser().getSysUserId(), workStartTime, workEndTime, getCurrentUser().getStoreIdList());
resJSON.put("workStartTime", workStartTime);
resJSON.put("workEndTime", workEndTime);
return ApiRes.ok(resJSON);
}
}

View File

@@ -0,0 +1,53 @@
package com.jeequan.jeepay.mch.ctrl.sysuser;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.TreeDataBuilder;
import com.jeequan.jeepay.db.entity.SysEntitlement;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysEntitlementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 权限菜单管理类
*
* @author terrfly
* @modify zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("api/sysEnts")
public class SysEntController extends CommonCtrl {
@Autowired SysEntitlementService sysEntitlementService;
/** 查询权限集合 */
@PreAuthorize("hasAnyAuthority( 'ENT_UR_ROLE_ENT_LIST', 'ENT_UR_ROLE_DIST' )")
@RequestMapping(value="/showTree", method = RequestMethod.GET)
public ApiRes showTree() {
//查询全部数据
List<SysEntitlement> list = sysEntitlementService.lambdaQuery()
.eq(SysEntitlement::getSysType, CS.SYS_ROLE_TYPE.MCH)
.eq(SysEntitlement::getState, CS.YES).list();
//4. 转换为json树状结构
JSONArray jsonArray = (JSONArray) JSONArray.toJSON(list);
List<JSONObject> leftMenuTree = new TreeDataBuilder(jsonArray,
"entId", "pid", "children", "entSort", true)
.buildTreeObject();
return ApiRes.ok(leftMenuTree);
}
}

View File

@@ -0,0 +1,159 @@
package com.jeequan.jeepay.mch.ctrl.sysuser;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.db.entity.SysRole;
import com.jeequan.jeepay.db.entity.SysUserRoleRela;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.AuthService;
import com.jeequan.jeepay.service.impl.SysRoleEntRelaService;
import com.jeequan.jeepay.service.impl.SysRoleService;
import com.jeequan.jeepay.service.impl.SysUserRoleRelaService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 角色管理类
*
* @author terrfly
* @modify zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("api/sysRoles")
public class SysRoleController extends CommonCtrl {
@Autowired SysRoleService sysRoleService;
@Autowired SysUserRoleRelaService sysUserRoleRelaService;
@Autowired private AuthService authService;
@Autowired private SysRoleEntRelaService sysRoleEntRelaService;
/** list */
@PreAuthorize("hasAnyAuthority( 'ENT_UR_ROLE_LIST', 'ENT_UR_USER_UPD_ROLE' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysRole queryObject = getObject(SysRole.class);
LambdaQueryWrapper<SysRole> condition = SysRole.gw();
condition.eq(SysRole::getSysType, CS.SYS_ROLE_TYPE.MCH);
condition.eq(SysRole::getBelongInfoId, getCurrentMchNo());
if(StringUtils.isNotEmpty(queryObject.getRoleName())){
condition.like(SysRole::getRoleName, queryObject.getRoleName());
}
if(StringUtils.isNotEmpty(queryObject.getRoleId())){
condition.like(SysRole::getRoleId, queryObject.getRoleId());
}
condition.orderByDesc(SysRole::getUpdatedAt); //时间倒序
IPage<SysRole> pages = sysRoleService.page(getIPage(true), condition);
return ApiRes.page(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") String recordId) {
SysRole sysRole = sysRoleService.getOne(SysRole.gw().eq(SysRole::getRoleId, recordId).eq(SysRole::getBelongInfoId, getCurrentMchNo()));
if (sysRole == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
return ApiRes.ok(sysRole);
}
/** add */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_ADD' )")
@RequestMapping(value="", method = RequestMethod.POST)
public ApiRes add() {
SysRole SysRole = getObject(SysRole.class);
String roleId = "ROLE_" + StringKit.getUUID(6);
SysRole.setRoleId(roleId);
SysRole.setSysType(CS.SYS_ROLE_TYPE.MCH); //后台系统
SysRole.setBelongInfoId(getCurrentUser().getSysUser().getBelongInfoId());
sysRoleService.save(SysRole);
//权限信息集合
String entIdListStr = getValString("entIdListStr");
//如果包含: 可分配权限的权限 && entIdListStr 不为空
if(getCurrentUser().getAuthorities().contains(new SimpleGrantedAuthority("ENT_UR_ROLE_DIST"))
&& StringUtils.isNotEmpty(entIdListStr)){
List<String> entIdList = JSONArray.parseArray(entIdListStr, String.class);
sysRoleEntRelaService.resetRela(roleId, entIdList);
}
return ApiRes.ok();
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
public ApiRes update(@PathVariable("recordId") String recordId) {
SysRole sysRole = getObject(SysRole.class);
LambdaUpdateWrapper<SysRole> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(SysRole::getRoleId, recordId);
updateWrapper.eq(SysRole::getBelongInfoId, getCurrentMchNo());
sysRoleService.update(sysRole, updateWrapper);
//权限信息集合
String entIdListStr = getValString("entIdListStr");
//如果包含: 可分配权限的权限 && entIdListStr 不为空
if(getCurrentUser().getAuthorities().contains(new SimpleGrantedAuthority("ENT_UR_ROLE_DIST"))
&& StringUtils.isNotEmpty(entIdListStr)){
List<String> entIdList = JSONArray.parseArray(entIdListStr, String.class);
sysRoleEntRelaService.resetRela(recordId, entIdList);
List<Long> sysUserIdList = new ArrayList<>();
sysUserRoleRelaService.list(SysUserRoleRela.gw().eq(SysUserRoleRela::getRoleId, recordId)).stream().forEach(item -> sysUserIdList.add(item.getUserId()));
//查询到该角色的人员, 将redis更新
authService.refAuthentication(sysUserIdList);
}
return ApiRes.ok();
}
/** delete */
@PreAuthorize("hasAuthority('ENT_UR_ROLE_DEL')")
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
public ApiRes del(@PathVariable("recordId") String recordId) {
SysRole sysRole = sysRoleService.getOne(SysRole.gw().eq(SysRole::getRoleId, recordId).eq(SysRole::getBelongInfoId, getCurrentMchNo()));
if (sysRole == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if(sysUserRoleRelaService.count(SysUserRoleRela.gw().eq(SysUserRoleRela::getRoleId, recordId)) > 0){
throw new BizException("当前角色已分配到用户, 不可删除!");
}
sysRoleService.removeRole(recordId);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,85 @@
package com.jeequan.jeepay.mch.ctrl.sysuser;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.SysRole;
import com.jeequan.jeepay.db.entity.SysRoleEntRela;
import com.jeequan.jeepay.db.entity.SysUserRoleRela;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.AuthService;
import com.jeequan.jeepay.service.impl.SysRoleEntRelaService;
import com.jeequan.jeepay.service.impl.SysRoleService;
import com.jeequan.jeepay.service.impl.SysUserRoleRelaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 角色权限管理类
*
* @author terrfly
* @modify zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("api/sysRoleEntRelas")
public class SysRoleEntRelaController extends CommonCtrl {
@Autowired private SysRoleEntRelaService sysRoleEntRelaService;
@Autowired private SysUserRoleRelaService sysUserRoleRelaService;
@Autowired private SysRoleService sysRoleService;
@Autowired private AuthService authService;
/** list */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_DIST' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysRoleEntRela queryObject = getObject(SysRoleEntRela.class);
LambdaQueryWrapper<SysRoleEntRela> condition = SysRoleEntRela.gw();
if(queryObject.getRoleId() != null){
condition.eq(SysRoleEntRela::getRoleId, queryObject.getRoleId());
}
IPage<SysRoleEntRela> pages = sysRoleEntRelaService.page(getIPage(true), condition);
return ApiRes.page(pages);
}
/** 重置角色权限关联信息 */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_DIST' )")
@RequestMapping(value="relas/{roleId}", method = RequestMethod.POST)
public ApiRes relas(@PathVariable("roleId") String roleId) {
SysRole sysRole = sysRoleService.getOne(SysRole.gw().eq(SysRole::getRoleId, roleId).eq(SysRole::getBelongInfoId, getCurrentMchNo()));
if (sysRole == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
List<String> entIdList = JSONArray.parseArray(getValStringRequired("entIdListStr"), String.class);
sysRoleEntRelaService.resetRela(roleId, entIdList);
List<Long> sysUserIdList = new ArrayList<>();
sysUserRoleRelaService.list(SysUserRoleRela.gw().eq(SysUserRoleRela::getRoleId, roleId)).stream().forEach(item -> sysUserIdList.add(item.getUserId()));
//查询到该角色的人员, 将redis更新
authService.refAuthentication(sysUserIdList);
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,363 @@
package com.jeequan.jeepay.mch.ctrl.sysuser;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.smsconfig.SmsBizDiyContentModel;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.AuthService;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 用户管理类
*
* @author terrfly
* @modify zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("/api/sysUsers")
public class SysUserController extends CommonCtrl {
@Autowired SysUserService sysUserService;
@Autowired SysUserAuthService sysUserAuthService;
@Autowired SysConfigService sysConfigService;
@Autowired private AuthService authService;
@Autowired private SysUserMchStoreRelaService mchStoreRelaService;
@Autowired private MchInfoService mchInfoService;
@Autowired private SysUserEntruleRelaService entruleRelaService;
@Autowired private SmsManager smsManager;
/** list */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_LIST' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysUserEntity queryObject = getObject(SysUserEntity.class);
LambdaQueryWrapper<SysUserEntity> condition = SysUserEntity.gw();
// 不包含普通操作员 ( APP不允许该操作 )
if(queryObject.extv().getIntValue("isNotHasType2") == 1){
condition.ne(SysUserEntity::getUserType, SysUser.UEST_TYPE_NORMAL);
}
condition.eq(SysUserEntity::getSysType, CS.SYS_ROLE_TYPE.MCH);
condition.eq(SysUserEntity::getBelongInfoId, getCurrentUser().getSysUser().getBelongInfoId());
if(StringUtils.isNotEmpty(queryObject.getRealname())){
condition.like(SysUserEntity::getRealname, queryObject.getRealname());
}
if(queryObject.getSysUserId() != null){
condition.eq(SysUserEntity::getSysUserId, queryObject.getSysUserId());
}
condition.like(StringUtils.isNotEmpty(queryObject.getTelphone()), SysUserEntity::getTelphone, queryObject.getTelphone());
// 店长增加条件
if (SysUser.UEST_TYPE_DIRECTOR == getCurrentUser().getSysUser().getUserType()) {
// 用户为店长或店员类型
condition.in(SysUserEntity::getUserType, SysUser.UEST_TYPE_DIRECTOR, SysUser.UEST_TYPE_CASHIER);
// 当前绑定门店的所属用户
List<String> storeIdList = getCurrentUser().getStoreIdList();
List<SysUserMchStoreRela> relaList = mchStoreRelaService.list(
SysUserMchStoreRela.gw().select(SysUserMchStoreRela::getSysUserId)
.in(CollectionUtil.isNotEmpty(storeIdList), SysUserMchStoreRela::getStoreId, storeIdList)
);
ArrayList<Long> userIdList = new ArrayList<>();
relaList.stream().forEach(item ->{
userIdList.add(item.getSysUserId());
});
condition.in(CollectionUtil.isNotEmpty(userIdList), SysUserEntity::getSysUserId, userIdList);
}
condition.orderByDesc(SysUserEntity::getCreatedAt); // 时间 倒序
IPage<SysUserEntity> pages = sysUserService.page(getIPage(), condition);
// 数据脱敏
pages.getRecords().stream().forEach(i-> {
i.setTelphone(DesensitizedUtil.mobilePhone(i.getTelphone()));
// 是否初始用户
boolean ifInitUser = mchInfoService.count(MchInfo.gw().eq(MchInfo::getInitUserId, i.getSysUserId()).eq(MchInfo::getMchNo, i.getBelongInfoId())) >0;
i.addExt("initUser", ifInitUser);
});
return ApiRes.page(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") Integer recordId) {
SysUserEntity sysUserEntity = sysUserService.getById(recordId);
if (sysUserEntity == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
if (!sysUserEntity.getBelongInfoId().equals(getCurrentUser().getSysUser().getBelongInfoId())) {
throw new BizException(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
List<SysUserMchStoreRela> storeRelaList = mchStoreRelaService.list(SysUserMchStoreRela.gw().eq(SysUserMchStoreRela::getSysUserId, recordId));
if (CollectionUtil.isNotEmpty(storeRelaList)) {
ArrayList<String> storeIdList = new ArrayList<>();
storeRelaList.forEach(item -> {
storeIdList.add(item.getStoreId());
});
sysUserEntity.addExt("storeIdList", storeIdList);
}
SysUserEntruleRela entruleRela = entruleRelaService.getById(recordId);
if (entruleRela != null) {
sysUserEntity.addExt("rulesList", JSONArray.parse(entruleRela.getRules()));
}
return ApiRes.ok(sysUserEntity);
}
/** add */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_ADD' )")
@RequestMapping(value="", method = RequestMethod.POST)
@MethodLog(remark = "添加管理员")
public ApiRes add() {
String loginPassword = getValString("loginPassword");
Byte isNotify = getValByteRequired("isNotify");
if (StringUtils.isBlank(loginPassword)) {
loginPassword = null;
}
SysUserEntity sysUserEntity = getObject(SysUserEntity.class);
// 新增店长、店员 需为M1类型商户
if (SysUser.UEST_TYPE_DIRECTOR == sysUserEntity.getUserType() || SysUser.UEST_TYPE_CASHIER == sysUserEntity.getUserType()) {
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
if (mchInfo == null) {
throw new BizException("商户不存在");
}
// 判断当前商户类型是否为M1商户
if (!MchInfo.MCH_LEVEL_M1.equals(mchInfo.getMchLevel())) {
throw new BizException("请先修改为M1商户");
}
}
sysUserEntity.setBelongInfoId(getCurrentUser().getSysUser().getBelongInfoId());
// sysUser.setUserType(com.jeequan.jeepay.core.entity.SysUser.UEST_TYPE_NORMAL);
// sysUserService.addSysUser(sysUser, CS.SYS_ROLE_TYPE.MCH, loginPassword);
sysUserService.addSysUser2(sysUserEntity, CS.SYS_ROLE_TYPE.MCH, loginPassword, getValString("storeIdList"), getValString("rulesList"));
// 发送短信通知
if (isNotify == CS.YES) {
smsManager.sendDiyContentSms(
SmsBizDiyContentModel.genUserOpenAccount(sysUserEntity.getTelphone(), sysUserEntity.getLoginUsername(), loginPassword)
);
}
return ApiRes.ok();
}
/** 修改操作员 登录认证信息 */
// @RequestMapping(value="/modifyPwd", method = RequestMethod.PUT)
public ApiRes authInfo() {
Long opSysUserId = getValLongRequired("recordId"); //操作员ID
//更改密码, 验证当前用户信息
String currentUserPwd = getValStringRequired("originalPwd"); //当前用户登录密码
//验证当前密码是否正确
if(!sysUserAuthService.validateCurrentUserPwd(currentUserPwd)){
throw new BizException("原密码验证失败!");
}
String opUserPwd = getValStringRequired("confirmPwd");
// 验证原密码与新密码是否相同
if (opUserPwd.equals(currentUserPwd)) {
throw new BizException("新密码与原密码相同!");
}
sysUserAuthService.resetAuthInfo(opSysUserId, null, null, true, opUserPwd, CS.SYS_ROLE_TYPE.MCH);
return ApiRes.ok();
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
@MethodLog(remark = "修改操作员信息")
public ApiRes update(@PathVariable("recordId") Long recordId) {
SysUserEntity sysUserEntity = getObject(SysUserEntity.class);
sysUserEntity.setSysUserId(recordId);
// 避免越权操作
SysUserEntity dbRecord = sysUserService.getOne(SysUserEntity.gw().eq(SysUserEntity::getSysUserId, recordId)
.eq(SysUserEntity::getSysType, CS.SYS_ROLE_TYPE.MCH).eq(SysUserEntity::getBelongInfoId, getCurrentMchNo()));
if (dbRecord == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
// boolean delAuthenticationFlag = sysUserService.updateUserOnTx(sysUser, recordId, getCurrentUser().getSysUserId());
boolean delAuthenticationFlag = sysUserService.updateUserOnTx2(sysUserEntity, recordId,
getCurrentUser().getSysUserId(), getValString("storeIdList"), getValString("rulesList"),
getCurrentUser().getSysUser().getUserType());
//查询到该角色的人员, 将redis更新
authService.refAuthentication(Arrays.asList(recordId));
// 删除用户redis缓存信息
if(delAuthenticationFlag){
authService.delAuthentication(Arrays.asList(recordId));
}
return ApiRes.ok();
}
/** delete */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_DELETE' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
@MethodLog(remark = "删除操作员信息")
public ApiRes delete(@PathVariable("recordId") Long recordId) {
//查询该操作员信息
SysUserEntity sysUserEntity = sysUserService.getById(recordId);
if (sysUserEntity == null) {
throw new BizException("该操作员不存在!");
}
//判断是否自己删除自己
if(recordId.equals(getCurrentUser().getSysUser().getSysUserId())){
throw new BizException("系统不允许删除当前登陆用户!");
}
//判断是否删除商户默认超管
if(mchInfoService.count(MchInfo.gw().eq(MchInfo::getInitUserId, recordId).eq(MchInfo::getMchNo, sysUserEntity.getBelongInfoId())) > 0 ){
throw new BizException("系统不允许删除商户默认用户!");
}
// 删除用户
sysUserService.removeUser(sysUserEntity, CS.SYS_ROLE_TYPE.MCH);
//如果用户被删除需要更新redis数据
authService.refAuthentication(Arrays.asList(recordId));
return ApiRes.ok();
}
/** MFA验证 解绑 */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_MFA_DELETE' )")
@RequestMapping(value="/mfaRelieve", method = RequestMethod.PUT)
@MethodLog(remark = "MFA验证解除")
public ApiRes mfaRelieve() throws BizException{
Long recordId = getValLongRequired("recordId");
// 当前登录账户是否为超管
Long currentUserId = getCurrentUser().getSysUser().getSysUserId();
// 解除操作员MFA验证
sysUserService.relieveOperatorMFA(currentUserId, recordId);
return ApiRes.ok();
}
/** 解除登录失败次数限制 */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_LOGIN_LIMIT_DELETE' )")
@RequestMapping(value="/loginLimit/{recordId}", method = RequestMethod.DELETE)
@MethodLog(remark = "解除登录限制")
public ApiRes deleteLoginLimit(@PathVariable("recordId") Long recordId) throws BizException{
List<SysUserAuth> authList = sysUserAuthService.list(SysUserAuth.gw().eq(SysUserAuth::getUserId, recordId));
if (authList.isEmpty()) {
return ApiRes.ok();
}
for (SysUserAuth sysUserAuth : authList) {
RedisUtil.del(CS.getCacheKeyLoginErr(CS.SYS_ROLE_TYPE.MCH, sysUserAuth.getIdentifier()));
}
return ApiRes.ok();
}
/** 操作员绑定门店 */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
@RequestMapping(value="/bindStore/{recordId}", method = RequestMethod.POST)
@MethodLog(remark = "绑定门店")
public ApiRes bindStore(@PathVariable("recordId") Long recordId) throws BizException{
String storeIdList = getValString("storeIdList");
//查询该操作员信息
SysUserEntity sysUserEntity = sysUserService.getById(recordId);
if (sysUserEntity == null) {
throw new BizException("该操作员不存在!");
}
// 店员不支持该操作
if (getCurrentUser().getSysUser().getUserType() == SysUser.UEST_TYPE_CASHIER) {
throw new BizException(ApiCodeEnum.SYS_PERMISSION_ERROR);
}
// 绑定门店
mchStoreRelaService.bindStore(sysUserEntity, storeIdList);
return ApiRes.ok();
}
/** 查询用户的 动态权限 */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
@RequestMapping(value="/userEntRoles/{recordId}", method = RequestMethod.GET)
public ApiRes userEntRoles(@PathVariable("recordId") Integer recordId) {
SysUserEntruleRela entruleRela = entruleRelaService.getById(recordId);
return ApiRes.ok(entruleRela);
}
/** 更新用户的动态权限 */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
@RequestMapping(value="/userEntRoles/{recordId}", method = RequestMethod.PUT)
public ApiRes updateUserEntRoles(@PathVariable("recordId") Long recordId) {
// 更新单条记录
String ruleName = getValStringRequired("ruleName");
Byte state = getValByteRequired("state");
entruleRelaService.updateUserEntRoles(recordId, state, ruleName);
//查询到该角色的人员, 将redis更新
authService.refAuthentication(Arrays.asList(recordId));
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,78 @@
package com.jeequan.jeepay.mch.ctrl.sysuser;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.db.entity.SysUserRoleRela;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.AuthService;
import com.jeequan.jeepay.service.impl.SysUserRoleRelaService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
/**
* 用户角色管理类
*
* @author terrfly
* @modify zhuxiao
*
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("api/sysUserRoleRelas")
public class SysUserRoleRelaController extends CommonCtrl {
@Autowired private SysUserRoleRelaService sysUserRoleRelaService;
@Autowired private SysUserService sysUserService;
@Autowired private AuthService authService;
/** list */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_UPD_ROLE' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysUserRoleRela queryObject = getObject(SysUserRoleRela.class);
LambdaQueryWrapper<SysUserRoleRela> condition = SysUserRoleRela.gw();
if(queryObject.getUserId() != null){
condition.eq(SysUserRoleRela::getUserId, queryObject.getUserId());
}
IPage<SysUserRoleRela> pages = sysUserRoleRelaService.page(getIPage(true), condition);
return ApiRes.page(pages);
}
/** 重置用户角色关联信息 */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_UPD_ROLE' )")
@RequestMapping(value="relas/{sysUserId}", method = RequestMethod.POST)
public ApiRes relas(@PathVariable("sysUserId") Long sysUserId) {
SysUserEntity dbRecord = sysUserService.getOne(SysUserEntity.gw().eq(SysUserEntity::getSysUserId, sysUserId).eq(SysUserEntity::getBelongInfoId, getCurrentMchNo()));
if (dbRecord == null) {
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
}
List<String> roleIdList = JSONArray.parseArray(getValStringRequired("roleIdListStr"), String.class);
sysUserService.saveUserRole(sysUserId, roleIdList);
authService.refAuthentication(Arrays.asList(sysUserId));
return ApiRes.ok();
}
}

View File

@@ -0,0 +1,45 @@
package com.jeequan.jeepay.mch.ctrl.transfer;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.websocket.server.WsChannelUserIdServer;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 获取用户ID - 回调函数
*
* @author terrfly
*
* @date 2021/8/13 17:54
*/
@Controller
@RequestMapping("/api/anon/channelUserIdCallback")
public class ChannelUserIdNotifyController extends CommonCtrl {
@RequestMapping("")
public String channelUserIdCallback() {
try {
// 静态CDN地址
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
request.setAttribute("staticCdnHost", dbApplicationConfig.getStaticCdnHost());
//请求参数
JSONObject params = getReqParamJSON();
String extParam = params.getString("extParam");
String channelUserId = params.getString("channelUserId");
String appId = params.getString("appId");
//推送到前端
WsChannelUserIdServer.sendMsgByAppAndCid(appId, extParam, channelUserId);
} catch (Exception e) {
request.setAttribute("errMsg", e.getMessage());
}
return "channelUser/getChannelUserIdPage";
}
}

View File

@@ -0,0 +1,135 @@
package com.jeequan.jeepay.mch.ctrl.transfer;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.utils.DateKit;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.PayInterfaceConfig;
import com.jeequan.jeepay.db.entity.PayInterfaceDefine;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.model.TransferOrderCreateReqModel;
import com.jeequan.jeepay.request.TransferOrderCreateRequest;
import com.jeequan.jeepay.response.TransferOrderCreateResponse;
import com.jeequan.jeepay.service.impl.MchAppService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import com.jeequan.jeepay.service.impl.PayInterfaceDefineService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* 转账api
*
* @author terrfly
*
* @date 2021/8/13 14:43
*/
@RestController
@RequestMapping("/api/mchTransfers")
public class MchTransferController extends CommonCtrl {
@Autowired private MchAppService mchAppService;
@Autowired private PayInterfaceConfigService payInterfaceConfigService;
@Autowired private PayInterfaceDefineService payInterfaceDefineService;
@Autowired private SysConfigService sysConfigService;
/** 查询商户对应应用下支持的支付通道 **/
@PreAuthorize("hasAuthority('ENT_MCH_TRANSFER_IF_CODE_LIST')")
@GetMapping("/ifCodes/{appId}")
public ApiRes ifCodeList(@PathVariable("appId") String appId) {
List<String> ifCodeList = new ArrayList<>();
payInterfaceConfigService.list(
PayInterfaceConfig.gw().select(PayInterfaceConfig::getIfCode)
.eq(PayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.MCH_APP)
.eq(PayInterfaceConfig::getInfoId, appId)
.eq(PayInterfaceConfig::getState, CS.PUB_USABLE)
).stream().forEach(r -> ifCodeList.add(r.getIfCode()));
if(ifCodeList.isEmpty()){
return ApiRes.ok(ifCodeList);
}
List<PayInterfaceDefine> result = payInterfaceDefineService.list(PayInterfaceDefine.gw().in(PayInterfaceDefine::getIfCode, ifCodeList));
return ApiRes.ok(result);
}
/** 获取渠道侧用户ID **/
@PreAuthorize("hasAuthority('ENT_MCH_TRANSFER_CHANNEL_USER')")
@GetMapping("/channelUserId")
public ApiRes channelUserId() {
String appId = getValStringRequired("appId");
MchAppEntity mchAppEntity = mchAppService.getById(appId);
if(mchAppEntity == null || mchAppEntity.getState() != CS.PUB_USABLE || !mchAppEntity.getMchNo().equals(getCurrentMchNo())){
throw new BizException("商户应用不存在或不可用");
}
JSONObject param = getReqParamJSON();
param.put("mchNo", getCurrentMchNo());
param.put("appId", appId);
param.put("ifCode", getValStringRequired("ifCode"));
param.put("extParam", getValStringRequired("extParam"));
param.put("reqTime", DateKit.currentTimeMillis() + "");
param.put("version", "1.0");
param.put("signType", "MD5");
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
param.put("redirectUrl", dbApplicationConfig.getMchSiteUrl() + "/api/anon/channelUserIdCallback");
param.put("sign", JeepayKit.getSign(param, mchAppEntity.getAppSecret()));
String url = StringKit.appendUrlQuery(dbApplicationConfig.getPaySiteUrl() + "/api/channelUserId/jump", param);
return ApiRes.ok(url);
}
/** 调起下单接口 **/
@PreAuthorize("hasAuthority('ENT_MCH_PAY_TEST_DO')")
@PostMapping("/doTransfer")
public ApiRes doTransfer() {
handleParamAmount("amount");
TransferOrderCreateReqModel model = getObject(TransferOrderCreateReqModel.class);
MchAppEntity mchAppEntity = mchAppService.getById(model.getAppId());
if(mchAppEntity == null || mchAppEntity.getState() != CS.PUB_USABLE || !mchAppEntity.getMchNo().equals(getCurrentMchNo()) ){
throw new BizException("商户应用不存在或不可用");
}
TransferOrderCreateRequest request = new TransferOrderCreateRequest();
model.setPas(SysConfigService.PLATFORM_API_SECRET); // 通信秘钥
model.setMchNo(this.getCurrentMchNo());
model.setAppId(mchAppEntity.getAppId());
model.setCurrency("CNY");
request.setBizModel(model);
JeepayClient jeepayClient = new JeepayClient(sysConfigService.getDBApplicationConfig().getPaySiteUrl(), mchAppEntity.getAppSecret());
try {
TransferOrderCreateResponse response = jeepayClient.execute(request);
if(response.getCode() != 0){
throw new BizException(response.getMsg());
}
return ApiRes.ok(response.get());
} catch (JeepayException e) {
throw new BizException(e.getMessage());
}
}
}

View File

@@ -0,0 +1,142 @@
package com.jeequan.jeepay.mch.ctrl.transfer;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.IsvUserConnService;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import com.jeequan.jeepay.service.impl.TransferInterfaceDefineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
import java.util.stream.Collectors;
/**
* TODO
*
* @author deng
* @since 2024/4/25
*/
@RestController
@RequestMapping("api/transferConfig")
public class TransferConfigController extends CommonCtrl {
@Autowired
private TransferInterfaceDefineService transferInterfaceDefineService;
@Autowired
private MchInfoService mchInfoService;
@Autowired
private PayInterfaceConfigService payInterfaceConfigService;
@Autowired
private IMQSender mqSender;
@Autowired
private IsvUserConnService isvUserConnService;
/**
* 查询可用的支付接口
* <p>
* 使用功能项目: 参数及费率的填写
* 服务商查询全部支付接口
* 服务商查询服务商开启的支付接口
**/
@GetMapping("/ifCodes")
public ApiRes ifCodes() {
// 搜索条件
String ifName = getValString("ifName");
String infoId = getValStringRequired("infoId"); // infoId
String configMode = getValStringRequired("configMode"); // 设置类型
Integer range = getValInteger("range");
String mccCode = getValString("mccCode");
// 支付接口列表
LambdaQueryWrapper<TransferInterfaceDefineEntity> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.eq(TransferInterfaceDefineEntity::getState, CS.YES); // 查询可用的支付接口列表
lambdaQueryWrapper.like(ObjUtil.isNotEmpty(ifName), TransferInterfaceDefineEntity::getTransIfName, ifName);
String infoType = CS.SYS_ROLE_TYPE.MCH_APP;
MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
if (mchInfo.getType() == CS.MCH_TYPE_ISVSUB) {
// 商户进件模式
if (RateConfig.CONFIG_MODE_MCHAPPLYMENT.equals(configMode)) {
Set<String> ifCodes = new HashSet<>();
// 获取关联的渠道信息
List<String> isvList = isvUserConnService.lambdaQuery()
.eq(IsvUserConnEntity::getInfoType, CS.SYS_ROLE_TYPE.MCH)
.eq(IsvUserConnEntity::getStatus, CS.YES)
.eq(IsvUserConnEntity::getInfoId, mchInfo.getMchNo())
.list()
.stream().map(IsvUserConnEntity::getIsvNo).collect(Collectors.toList());
if (isvList.isEmpty()) {
return ApiRes.ok(new ArrayList<>());
}
// 根据渠道号获取ifCode
QueryWrapper<PayInterfaceConfig> query = Wrappers.query();
// 去重
query.select("DISTINCT")
.lambda()
.select(PayInterfaceConfig::getIfCode)
.eq(PayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.ISV)
.in(PayInterfaceConfig::getInfoId, isvList)
.eq(PayInterfaceConfig::getState, CS.YES)
.eq(PayInterfaceConfig::getIsOpenApplyment, CS.YES);
payInterfaceConfigService.list(query).forEach(r -> ifCodes.add(r.getIfCode()));
if (ifCodes.isEmpty()) {
return ApiRes.ok(new ArrayList<>());
}
lambdaQueryWrapper.in(TransferInterfaceDefineEntity::getTransIfCode, ifCodes); // 查询可用的支付接口列表
} else { // 特约商户无需配置
return ApiRes.ok(new ArrayList<>());
}
}
lambdaQueryWrapper.orderByAsc(TransferInterfaceDefineEntity::getId);
List<TransferInterfaceDefineEntity> list = transferInterfaceDefineService.list(lambdaQueryWrapper);
if (list.isEmpty()) {
return ApiRes.ok(list);
}
Map<String, Byte> stateMap = new HashMap<>();
payInterfaceConfigService.lambdaQuery().select(PayInterfaceConfig::getIfCode, PayInterfaceConfig::getState)
.eq(PayInterfaceConfig::getInfoId, infoId)
.eq(PayInterfaceConfig::getInfoType, infoType)
.list().forEach(r -> stateMap.put(r.getIfCode(), r.getState()));
list.forEach(r -> {
// 是否已配置
if (RateConfig.CONFIG_MODE_MGRAGENT.equals(configMode)) { // 服务商查询的就是已经配置的接口,无需填入
r.addExt("configState", stateMap.get(r.getTransIfCode()));
} else {
r.addExt("configState", ObjectUtil.defaultIfNull(stateMap.get(r.getTransIfCode()), 1));
}
});
return ApiRes.ok(list);
}
}

Some files were not shown because too many files have changed in this diff Show More