✨ 添加新特性。 支付收单模块

This commit is contained in:
pigxcloud committed 2019-06-03 07:41:34 +08:00
1 parent 2ee8021b5e
commit 075c31a508
139 files changed
+4703 -4864

No files matched your search

+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-auth</artifactId>
+7 -2
View File
@@ -6,7 +6,7 @@
<parent>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>2.1.3.RELEASE</version>
<version>2.1.5.RELEASE</version>
<relativePath/>
</parent>
@@ -16,7 +16,7 @@
<description>pigx 公共版本控制</description>
<properties>
<pigx.version>3.0.0</pigx.version>
<pigx.version>3.2</pigx.version>
<mybatis-plus.version>3.1.0</mybatis-plus.version>
<druid.version>1.1.16</druid.version>
<mysql.connector.version>8.0.16</mysql.connector.version>
@@ -66,6 +66,11 @@
<artifactId>pigx-common-security</artifactId>
<version>${pigx.version}</version>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-sequence</artifactId>
<version>${pigx.version}</version>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-swagger</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-core</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-data</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>pigx-common</artifactId>
<groupId>com.pig4cloud</groupId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-gateway</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-job</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-log</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-minio</artifactId>
@@ -137,7 +137,7 @@ public class MinioTemplate implements InitializingBean {
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
client.putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");
client.putObject(bucketName, objectName, stream, (long) stream.available(), null, null, "application/octet-stream");
}
/**
@@ -151,7 +151,7 @@ public class MinioTemplate implements InitializingBean {
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
client.putObject(bucketName, objectName, stream, size, contextType);
client.putObject(bucketName, objectName, stream, size, null, null, contextType);
}
/**
+1 -1
View File
@@ -23,7 +23,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-security</artifactId>
+27
View File
@@ -0,0 +1,27 @@
<?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>
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.2</version>
</parent>
<artifactId>pigx-common-sequence</artifactId>
<packaging>jar</packaging>
<description>pigx 分布式发号器</description>
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-core</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,89 @@
package com.pig4cloud.common.sequence;
import com.pig4cloud.common.sequence.builder.DbSeqBuilder;
import com.pig4cloud.common.sequence.builder.RedisSeqBuilder;
import com.pig4cloud.common.sequence.builder.SnowflakeSeqBuilder;
import com.pig4cloud.common.sequence.properties.SequenceDbProperties;
import com.pig4cloud.common.sequence.properties.SequenceRedisProperties;
import com.pig4cloud.common.sequence.properties.SequenceSnowflakeProperties;
import com.pig4cloud.common.sequence.range.impl.name.DateBizName;
import com.pig4cloud.common.sequence.range.impl.name.DefaultBizName;
import com.pig4cloud.common.sequence.sequence.Sequence;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* @author lengleng
* @date 2019-05-26
*/
@Configuration
@ComponentScan("com.pig4cloud.common.sequence")
@ConditionalOnMissingBean(Sequence.class)
public class SequenceAutoConfiguration {
/**
* 数据库作为发号器的存储介质
*
* @param dataSource
* @param properties
* @return
*/
@Bean
@ConditionalOnBean(DataSource.class)
@ConditionalOnProperty("xsequence.db")
public Sequence dbSequence(DataSource dataSource,
SequenceDbProperties properties) {
return DbSeqBuilder
.create()
.bizName(new DefaultBizName(properties.getBizName()))
.dataSource(dataSource)
.step(properties.getStep())
.retryTimes(properties.getRetryTimes())
.tableName(properties.getTableName())
.build();
}
/**
* Redis 作为发号器的存储介质
*
* @param redisProperties
* @param properties
* @return
*/
@Bean
@ConditionalOnProperty("xsequence.redis")
public Sequence redisSequence(RedisProperties redisProperties,
SequenceRedisProperties properties) {
return RedisSeqBuilder
.create()
.bizName(new DateBizName(properties.getBizName()))
.ip(redisProperties.getHost())
.port(redisProperties.getPort())
.auth(redisProperties.getPassword())
.step(properties.getStep())
.build();
}
/**
* snowflak 算法作为发号器实现
*
* @param properties
* @return
*/
@Bean
@ConditionalOnProperty("xsequence.snowflak")
public Sequence snowflakeSequence(SequenceSnowflakeProperties properties) {
return SnowflakeSeqBuilder
.create()
.datacenterId(properties.getDatacenterId())
.workerId(properties.getWorkerId())
.build();
}
}
@@ -0,0 +1,97 @@
package com.pig4cloud.common.sequence.builder;
import com.pig4cloud.common.sequence.range.BizName;
import com.pig4cloud.common.sequence.range.impl.db.DbSeqRangeMgr;
import com.pig4cloud.common.sequence.sequence.Sequence;
import com.pig4cloud.common.sequence.sequence.impl.DefaultRangeSequence;
import javax.sql.DataSource;
/**
* 基于DB取步长,序列号生成器构建者
* Created by xuan on 2018/5/30.
*/
public class DbSeqBuilder implements SeqBuilder {
/**
* 数据库数据源[必选]
*/
private DataSource dataSource;
/**
* 业务名称[必选]
*/
private BizName bizName;
/**
* 存放序列号步长的表[可选:默认:sequence]
*/
private String tableName = "sequence";
/**
* 并发是数据使用了乐观策略,这个是失败重试的次数[可选:默认:100]
*/
private int retryTimes = 100;
/**
* 获取range步长[可选:默认:1000]
*/
private int step = 1000;
/**
* 序列号分配起始值[可选:默认:0]
*/
private long stepStart = 0;
public static DbSeqBuilder create() {
DbSeqBuilder builder = new DbSeqBuilder();
return builder;
}
@Override
public Sequence build() {
//利用DB获取区间管理器
DbSeqRangeMgr dbSeqRangeMgr = new DbSeqRangeMgr();
dbSeqRangeMgr.setDataSource(this.dataSource);
dbSeqRangeMgr.setTableName(this.tableName);
dbSeqRangeMgr.setRetryTimes(this.retryTimes);
dbSeqRangeMgr.setStep(this.step);
dbSeqRangeMgr.setStepStart(stepStart);
dbSeqRangeMgr.init();
//构建序列号生成器
DefaultRangeSequence sequence = new DefaultRangeSequence();
sequence.setName(this.bizName);
sequence.setSeqRangeMgr(dbSeqRangeMgr);
return sequence;
}
public DbSeqBuilder dataSource(DataSource dataSource) {
this.dataSource = dataSource;
return this;
}
public DbSeqBuilder tableName(String tableName) {
this.tableName = tableName;
return this;
}
public DbSeqBuilder retryTimes(int retryTimes) {
this.retryTimes = retryTimes;
return this;
}
public DbSeqBuilder step(int step) {
this.step = step;
return this;
}
public DbSeqBuilder bizName(BizName bizName) {
this.bizName = bizName;
return this;
}
public DbSeqBuilder stepStart(long stepStart) {
this.stepStart = stepStart;
return this;
}
}
@@ -0,0 +1,94 @@
package com.pig4cloud.common.sequence.builder;
import com.pig4cloud.common.sequence.range.BizName;
import com.pig4cloud.common.sequence.range.impl.redis.RedisSeqRangeMgr;
import com.pig4cloud.common.sequence.sequence.Sequence;
import com.pig4cloud.common.sequence.sequence.impl.DefaultRangeSequence;
/**
* 基于redis取步长,序列号生成器构建者
*
* @author xuan on 2018/5/30.
*/
public class RedisSeqBuilder implements SeqBuilder {
/**
* 连接redis的IP[必选]
*/
private String ip;
/**
* 连接redis的port[必选]
*/
private int port;
/**
* 业务名称[必选]
*/
private BizName bizName;
/**
* 认证权限,看redis是否配置了需要密码auth[可选]
*/
private String auth;
/**
* 获取range步长[可选,默认:1000]
*/
private int step = 1000;
/**
* 序列号分配起始值[可选:默认:0]
*/
private long stepStart = 0;
public static RedisSeqBuilder create() {
RedisSeqBuilder builder = new RedisSeqBuilder();
return builder;
}
@Override
public Sequence build() {
//利用Redis获取区间管理器
RedisSeqRangeMgr redisSeqRangeMgr = new RedisSeqRangeMgr();
redisSeqRangeMgr.setIp(this.ip);
redisSeqRangeMgr.setPort(this.port);
redisSeqRangeMgr.setAuth(this.auth);
redisSeqRangeMgr.setStep(this.step);
redisSeqRangeMgr.setStepStart(stepStart);
redisSeqRangeMgr.init();
//构建序列号生成器
DefaultRangeSequence sequence = new DefaultRangeSequence();
sequence.setName(this.bizName);
sequence.setSeqRangeMgr(redisSeqRangeMgr);
return sequence;
}
public RedisSeqBuilder ip(String ip) {
this.ip = ip;
return this;
}
public RedisSeqBuilder port(int port) {
this.port = port;
return this;
}
public RedisSeqBuilder auth(String auth) {
this.auth = auth;
return this;
}
public RedisSeqBuilder step(int step) {
this.step = step;
return this;
}
public RedisSeqBuilder bizName(BizName bizName) {
this.bizName = bizName;
return this;
}
public RedisSeqBuilder stepStart(long stepStart) {
this.stepStart = stepStart;
return this;
}
}
@@ -0,0 +1,19 @@
package com.pig4cloud.common.sequence.builder;
import com.pig4cloud.common.sequence.sequence.Sequence;
/**
* 序列号生成器构建者
* @author xuan on 2018/5/30.
*/
public interface SeqBuilder {
/**
* 构建一个序列号生成器
*
* @return 序列号生成器
*/
Sequence build();
}
@@ -0,0 +1,45 @@
package com.pig4cloud.common.sequence.builder;
import com.pig4cloud.common.sequence.sequence.Sequence;
import com.pig4cloud.common.sequence.sequence.impl.SnowflakeSequence;
/**
* 基于雪花算法,序列号生成器构建者
* @author xuan on 2018/5/30.
*/
public class SnowflakeSeqBuilder implements SeqBuilder {
/**
* 数据中心ID,值的范围在[0,31]之间,一般可以设置机房的IDC[必选]
*/
private long datacenterId;
/**
* 工作机器ID,值的范围在[0,31]之间,一般可以设置机器编号[必选]
*/
private long workerId;
public static SnowflakeSeqBuilder create() {
SnowflakeSeqBuilder builder = new SnowflakeSeqBuilder();
return builder;
}
@Override
public Sequence build() {
SnowflakeSequence sequence = new SnowflakeSequence();
sequence.setDatacenterId(this.datacenterId);
sequence.setWorkerId(this.workerId);
return sequence;
}
public SnowflakeSeqBuilder datacenterId(long datacenterId) {
this.datacenterId = datacenterId;
return this;
}
public SnowflakeSeqBuilder workerId(long workerId) {
this.workerId = workerId;
return this;
}
}
@@ -0,0 +1,19 @@
package com.pig4cloud.common.sequence.exception;
/**
* 序列号生成异常
* @author xuan on 2018/1/10.
*/
public class SeqException extends RuntimeException {
private static final long serialVersionUID = 1L;
public SeqException(String message) {
super(message);
}
public SeqException(Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,27 @@
package com.pig4cloud.common.sequence.properties;
import lombok.Data;
/**
* @author lengleng
* @date 2019-05-26
* <p>
* 发号器通用属性
*/
@Data
class BaseSequenceProperties {
/**
* 获取range步长[可选,默认:1000]
*/
private int step = 1000;
/**
* 序列号分配起始值[可选:默认:0]
*/
private long stepStart = 0;
/**
* 业务名称
*/
private String bizName = "pigx";
}
@@ -0,0 +1,31 @@
package com.pig4cloud.common.sequence.properties;
/**
* @author lengleng
* @date 2019-05-26
*/
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2019/5/26
* <p>
* 发号器DB配置属性
*/
@Data
@Component
@ConfigurationProperties(prefix = "xsequence.db")
public class SequenceDbProperties extends BaseSequenceProperties {
/**
* 表名称
*/
private String tableName;
/**
* 重试次数
*/
private int retryTimes;
}
@@ -0,0 +1,23 @@
package com.pig4cloud.common.sequence.properties;
/**
* @author lengleng
* @date 2019-05-26
*/
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2019/5/26
* <p>
* 发号器Redis配置属性
*/
@Data
@Component
@ConfigurationProperties(prefix = "xsequence.redis")
public class SequenceRedisProperties extends BaseSequenceProperties {
}
@@ -0,0 +1,26 @@
package com.pig4cloud.common.sequence.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2019-05-26
* <p>
* Snowflake 发号器属性
*/
@Data
@Component
@ConfigurationProperties(prefix = "xsequence.snowflake")
public class SequenceSnowflakeProperties extends BaseSequenceProperties {
/**
* 数据中心ID,值的范围在[0,31]之间,一般可以设置机房的IDC[必选]
*/
private long datacenterId;
/**
* 工作机器ID,值的范围在[0,31]之间,一般可以设置机器编号[必选]
*/
private long workerId;
}
@@ -0,0 +1,15 @@
package com.pig4cloud.common.sequence.range;
/**
* @author lengleng
* @date 2019-05-26
* <p>
* 名称生成器
*/
public interface BizName {
/**
* 生成名称
*/
String create();
}
@@ -0,0 +1,70 @@
package com.pig4cloud.common.sequence.range;
import java.util.concurrent.atomic.AtomicLong;
/**
* 序列号区间对象模型
* @author xuan on 2018/1/10.
*/
public class SeqRange {
/**
* 区间的序列号开始值
*/
private final long min;
/**
* 区间的序列号结束值
*/
private final long max;
/**
* 区间的序列号当前值
*/
private final AtomicLong value;
/**
* 区间的序列号是否分配完毕,每次分配完毕就会去重新获取一个新的区间
*/
private volatile boolean over = false;
public SeqRange(long min, long max) {
this.min = min;
this.max = max;
this.value = new AtomicLong(min);
}
/**
* 返回并递增下一个序列号
*
* @return 下一个序列号,如果返回-1表示序列号分配完毕
*/
public long getAndIncrement() {
long currentValue = value.getAndIncrement();
if (currentValue > max) {
over = true;
return -1;
}
return currentValue;
}
public long getMin() {
return min;
}
public long getMax() {
return max;
}
public boolean isOver() {
return over;
}
public void setOver(boolean over) {
this.over = over;
}
@Override
public String toString() {
return "max: " + max + ", min: " + min + ", value: " + value;
}
}
@@ -0,0 +1,25 @@
package com.pig4cloud.common.sequence.range;
import com.pig4cloud.common.sequence.exception.SeqException;
/**
* 区间管理器
* @author xuan on 2018/1/10.
*/
public interface SeqRangeMgr {
/**
* 获取指定区间名的下一个区间
*
* @param name 区间名
* @return 返回区间
* @throws SeqException 异常
*/
SeqRange nextRange(String name) throws SeqException;
/**
* 初始化
*/
void init();
}
@@ -0,0 +1,172 @@
package com.pig4cloud.common.sequence.range.impl.db;
import com.pig4cloud.common.sequence.exception.SeqException;
import javax.sql.DataSource;
import java.sql.*;
/**
* 操作DB帮助类
* @author xuan on 2018/4/29.
*/
abstract class BaseDbHelper {
private static final long DELTA = 100000000L;
private final static String SQL_CREATE_TABLE =
"CREATE TABLE IF NOT EXISTS #tableName(" + "id bigint(20) NOT NULL AUTO_INCREMENT,"
+ "value bigint(20) NOT NULL," + "name varchar(32) NOT NULL," + "gmt_create DATETIME NOT NULL,"
+ "gmt_modified DATETIME NOT NULL," + "PRIMARY KEY (`id`),UNIQUE uk_name (`name`)" + ")";
private final static String SQL_INSERT_RANGE =
"INSERT IGNORE INTO #tableName(name,value,gmt_create,gmt_modified)" + " VALUE(?,?,?,?)";
private final static String SQL_UPDATE_RANGE =
"UPDATE #tableName SET value=?,gmt_modified=? WHERE name=? AND " + "value=?";
private final static String SQL_SELECT_RANGE = "SELECT value FROM #tableName WHERE name=?";
/**
* 创建表
*
* @param dataSource DB来源
* @param tableName 表名
*/
static void createTable(DataSource dataSource, String tableName) {
Connection conn = null;
Statement stmt = null;
try {
conn = dataSource.getConnection();
stmt = conn.createStatement();
stmt.executeUpdate(SQL_CREATE_TABLE.replace("#tableName", tableName));
} catch (SQLException e) {
throw new SeqException(e);
} finally {
closeQuietly(stmt);
closeQuietly(conn);
}
}
/**
* 插入数据区间
*
* @param dataSource DB来源
* @param tableName 表名
* @param name 区间名称
* @param stepStart 初始位置
*/
private static void insertRange(DataSource dataSource, String tableName, String name, long stepStart) {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = dataSource.getConnection();
stmt = conn.prepareStatement(SQL_INSERT_RANGE.replace("#tableName", tableName));
stmt.setString(1, name);
stmt.setLong(2, stepStart);
stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
stmt.setTimestamp(4, new Timestamp(System.currentTimeMillis()));
stmt.executeUpdate();
} catch (SQLException e) {
throw new SeqException(e);
} finally {
closeQuietly(stmt);
closeQuietly(conn);
}
}
/**
* 更新区间,乐观策略
*
* @param dataSource DB来源
* @param tableName 表名
* @param newValue 更新新数据
* @param oldValue 更新旧数据
* @param name 区间名称
* @return 成功/失败
*/
static boolean updateRange(DataSource dataSource, String tableName, Long newValue, Long oldValue, String name) {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = dataSource.getConnection();
stmt = conn.prepareStatement(SQL_UPDATE_RANGE.replace("#tableName", tableName));
stmt.setLong(1, newValue);
stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
stmt.setString(3, name);
stmt.setLong(4, oldValue);
int affectedRows = stmt.executeUpdate();
return affectedRows > 0;
} catch (SQLException e) {
throw new SeqException(e);
} finally {
closeQuietly(stmt);
closeQuietly(conn);
}
}
/**
* 查询区间,如果区间不存在,会新增一个区间,并返回null,由上层重新执行
*
* @param dataSource DB来源
* @param tableName 来源
* @param name 区间名称
* @param stepStart 初始位置
* @return 区间值
*/
static Long selectRange(DataSource dataSource, String tableName, String name, long stepStart) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
long oldValue;
try {
conn = dataSource.getConnection();
stmt = conn.prepareStatement(SQL_SELECT_RANGE.replace("#tableName", tableName));
stmt.setString(1, name);
rs = stmt.executeQuery();
if (!rs.next()) {
//没有此类型数据,需要初始化
insertRange(dataSource, tableName, name, stepStart);
return null;
}
oldValue = rs.getLong(1);
if (oldValue < 0) {
String msg =
"Sequence value cannot be less than zero, value = " + oldValue + ", please check table sequence"
+ tableName;
throw new SeqException(msg);
}
if (oldValue > Long.MAX_VALUE - DELTA) {
String msg =
"Sequence value overflow, value = " + oldValue + ", please check table sequence" + tableName;
throw new SeqException(msg);
}
return oldValue;
} catch (SQLException e) {
throw new SeqException(e);
} finally {
closeQuietly(rs);
closeQuietly(stmt);
closeQuietly(conn);
}
}
private static void closeQuietly(AutoCloseable closeable) {
if (null != closeable) {
try {
closeable.close();
} catch (Throwable e) {
//Ignore
}
}
}
}
@@ -0,0 +1,139 @@
package com.pig4cloud.common.sequence.range.impl.db;
import com.pig4cloud.common.sequence.exception.SeqException;
import com.pig4cloud.common.sequence.range.SeqRange;
import com.pig4cloud.common.sequence.range.SeqRangeMgr;
import javax.sql.DataSource;
/**
* DB区间管理器
* @author xuan on 2018/4/29.
*/
public class DbSeqRangeMgr implements SeqRangeMgr {
/**
* 区间步长
*/
private int step = 1000;
/**
* 区间起始位置,真实从stepStart+1开始
*/
private long stepStart = 0;
/**
* 获取区间失败重试次数
*/
private int retryTimes = 100;
/**
* DB来源
*/
private DataSource dataSource;
/**
* 表名,默认range
*/
private String tableName = "range";
@Override
public SeqRange nextRange(String name) throws SeqException {
if (isEmpty(name)) {
throw new SecurityException("[DbSeqRangeMgr-nextRange] name is empty.");
}
Long oldValue;
Long newValue;
for (int i = 0; i < getRetryTimes(); i++) {
oldValue = BaseDbHelper.selectRange(getDataSource(), getRealTableName(), name, getStepStart());
if (null == oldValue) {
//区间不存在,重试
continue;
}
newValue = oldValue + getStep();
if (BaseDbHelper.updateRange(getDataSource(), getRealTableName(), newValue, oldValue, name)) {
return new SeqRange(oldValue + 1, newValue);
}
//else 失败重试
}
throw new SeqException("Retried too many times, retryTimes = " + getRetryTimes());
}
@Override
public void init() {
checkParam();
BaseDbHelper.createTable(getDataSource(), getRealTableName());
}
private boolean isEmpty(String str) {
return null == str || str.trim().length() == 0;
}
private String getRealTableName() {
return getTableName();
}
private void checkParam() {
if (step <= 0) {
throw new SecurityException("[DbSeqRangeMgr-checkParam] step must greater than 0.");
}
if (stepStart < 0) {
throw new SecurityException("[DbSeqRangeMgr-setStepStart] stepStart < 0.");
}
if (retryTimes <= 0) {
throw new SecurityException("[DbSeqRangeMgr-setRetryTimes] retryTimes must greater than 0.");
}
if (null == dataSource) {
throw new SecurityException("[DbSeqRangeMgr-setDataSource] dataSource is null.");
}
if (isEmpty(tableName)) {
throw new SecurityException("[DbSeqRangeMgr-setTableName] tableName is empty.");
}
}
////////getter and setter
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
public long getStepStart() {
return stepStart;
}
public void setStepStart(long stepStart) {
this.stepStart = stepStart;
}
public int getRetryTimes() {
return retryTimes;
}
public void setRetryTimes(int retryTimes) {
this.retryTimes = retryTimes;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
}
@@ -0,0 +1,26 @@
package com.pig4cloud.common.sequence.range.impl.name;
import cn.hutool.core.date.DateUtil;
import com.pig4cloud.common.sequence.range.BizName;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
/**
* @author lengleng
* @date 2019-05-26
* <p>
* 根据时间重置bizname
*/
@NoArgsConstructor
@AllArgsConstructor
public class DateBizName implements BizName {
private String bizName;
/**
* 生成空间名称
*/
@Override
public String create() {
return bizName + DateUtil.today();
}
}
@@ -0,0 +1,24 @@
package com.pig4cloud.common.sequence.range.impl.name;
import com.pig4cloud.common.sequence.range.BizName;
import lombok.AllArgsConstructor;
/**
* @author lengleng
* @date 2019-05-26
* 根据传入返回bizname
*/
@AllArgsConstructor
public class DefaultBizName implements BizName {
private String bizName;
/**
* 生成空间名称
*/
@Override
public String create() {
return bizName;
}
}
@@ -0,0 +1,137 @@
package com.pig4cloud.common.sequence.range.impl.redis;
import cn.hutool.core.util.StrUtil;
import com.pig4cloud.common.sequence.exception.SeqException;
import com.pig4cloud.common.sequence.range.SeqRange;
import com.pig4cloud.common.sequence.range.SeqRangeMgr;
import redis.clients.jedis.Jedis;
/**
* Redis区间管理器
*
* @author xuan on 2018/5/8.
*/
public class RedisSeqRangeMgr implements SeqRangeMgr {
/**
* 前缀防止key重复
*/
private final static String KEY_PREFIX = "x_sequence_";
/**
* redis客户端
*/
private Jedis jedis;
/**
* IP
*/
private String ip;
/**
* PORT
*/
private Integer port;
/**
* 验证权限
*/
private String auth;
/**
* 区间步长
*/
private int step = 1000;
/**
* 区间起始位置,真实从stepStart+1开始
*/
private long stepStart = 0;
/**
* 标记业务key是否存在,如果false,在取nextRange时,会取check一把
* 这个boolean只为提高性能,不用每次都取redis check
*/
private volatile boolean keyAlreadyExist;
@Override
public SeqRange nextRange(String name) throws SeqException {
if (!keyAlreadyExist) {
Boolean isExists = jedis.exists(getRealKey(name));
if (!isExists) {
//第一次不存在,进行初始化,setnx不存在就set,存在就忽略
jedis.setnx(getRealKey(name), String.valueOf(stepStart));
}
keyAlreadyExist = true;
}
Long max = jedis.incrBy(getRealKey(name), step);
Long min = max - step + 1;
return new SeqRange(min, max);
}
@Override
public void init() {
checkParam();
jedis = new Jedis(ip, port);
if (StrUtil.isNotBlank(auth)) {
jedis.auth(auth);
}
}
private void checkParam() {
if (isEmpty(ip)) {
throw new SecurityException("[RedisSeqRangeMgr-checkParam] ip is empty.");
}
if (null == port) {
throw new SecurityException("[RedisSeqRangeMgr-checkParam] port is null.");
}
}
private String getRealKey(String name) {
return KEY_PREFIX + name;
}
private boolean isEmpty(String str) {
return null == str || str.trim().length() == 0;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
public String getAuth() {
return auth;
}
public void setAuth(String auth) {
this.auth = auth;
}
public long getStepStart() {
return stepStart;
}
public void setStepStart(long stepStart) {
this.stepStart = stepStart;
}
}
@@ -0,0 +1,26 @@
package com.pig4cloud.common.sequence.sequence;
import com.pig4cloud.common.sequence.range.BizName;
import com.pig4cloud.common.sequence.range.SeqRangeMgr;
/**
* 序列号区间生成器接口
* @author xuan on 2018/5/6.
*/
public interface RangeSequence extends Sequence {
/**
* 设置区间管理器
*
* @param seqRangeMgr 区间管理器
*/
void setSeqRangeMgr(SeqRangeMgr seqRangeMgr);
/**
* 设置获取序列号名称
*
* @param name 名称
*/
void setName(BizName name);
}
@@ -0,0 +1,28 @@
package com.pig4cloud.common.sequence.sequence;
import com.pig4cloud.common.sequence.exception.SeqException;
/**
* 序列号生成器接口
*
* @author xuan on 2018/1/10.
*/
public interface Sequence {
/**
* 生成下一个序列号
*
* @return 序列号
* @throws SeqException 序列号异常
*/
long nextValue() throws SeqException;
/**
* 下一个生成序号(带格式)
*
* @return
* @throws SeqException
*/
String nextNo() throws SeqException;
}
@@ -0,0 +1,111 @@
package com.pig4cloud.common.sequence.sequence.impl;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.pig4cloud.common.sequence.exception.SeqException;
import com.pig4cloud.common.sequence.range.BizName;
import com.pig4cloud.common.sequence.range.SeqRange;
import com.pig4cloud.common.sequence.range.SeqRangeMgr;
import com.pig4cloud.common.sequence.sequence.RangeSequence;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 序列号区间生成器接口默认实现
*
* @author xuan on 2018/1/10.
* <p>
* 根据biz name 自增
*/
public class DefaultRangeSequence implements RangeSequence {
/**
* 获取区间是加一把独占锁防止资源冲突
*/
private final Lock lock = new ReentrantLock();
/**
* 序列号区间管理器
*/
private SeqRangeMgr seqRangeMgr;
/**
* 当前序列号区间
*/
private volatile SeqRange currentRange;
/**
* 需要获取区间的业务名称
*/
private BizName bizName;
@Override
public long nextValue() throws SeqException {
String name = bizName.create();
//当前区间不存在,重新获取一个区间
if (null == currentRange) {
lock.lock();
try {
if (null == currentRange) {
currentRange = seqRangeMgr.nextRange(name);
}
} finally {
lock.unlock();
}
}
//当value值为-1时,表明区间的序列号已经分配完,需要重新获取区间
long value = currentRange.getAndIncrement();
if (value == -1) {
lock.lock();
try {
for (; ; ) {
if (currentRange.isOver()) {
currentRange = seqRangeMgr.nextRange(name);
}
value = currentRange.getAndIncrement();
if (value == -1) {
continue;
}
break;
}
} finally {
lock.unlock();
}
}
if (value < 0) {
throw new SeqException("Sequence value overflow, value = " + value);
}
return value;
}
/**
* 下一个生成序号(带格式)
*
* @return
* @throws SeqException
*/
@Override
public String nextNo() throws SeqException {
return String.format("%s%05d", DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT), nextValue());
}
@Override
public void setSeqRangeMgr(SeqRangeMgr seqRangeMgr) {
this.seqRangeMgr = seqRangeMgr;
}
@Override
public void setName(BizName name) {
this.bizName = name;
}
}
@@ -0,0 +1,177 @@
package com.pig4cloud.common.sequence.sequence.impl;
import com.pig4cloud.common.sequence.exception.SeqException;
import com.pig4cloud.common.sequence.sequence.Sequence;
/**
* 使用雪花算法
* 一个long类型的数据,64位。以下是每位的具体含义。
* <br>
* snowflake的结构如下(每部分用-分开):
* <br>
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
* <br>
* (1)第一位为未使用
* (2)接下来的41位为毫秒级时间(41位的长度可以使用69年)
* (3)然后是5位datacenterId
* (4)5位workerId
* (5)最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)
* <br>
* 一共加起来刚好64位,为一个Long型。(转换成字符串长度为18)
* @author xuan on 2018/5/9.
*/
public class SnowflakeSequence implements Sequence {
/**
* 开始时间截 (2018-01-01)
*/
private final long twepoch = 1514736000000L;
/**
* 机器id所占的位数
*/
private final long workerIdBits = 5L;
/**
* 数据标识id所占的位数
*/
private final long datacenterIdBits = 5L;
/**
* 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
*/
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
/**
* 支持的最大数据标识id,结果是31
*/
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
/**
* 序列在id中占的位数
*/
private final long sequenceBits = 12L;
/**
* 机器ID向左移12位
*/
private final long workerIdShift = sequenceBits;
/**
* 数据标识id向左移17位(12+5)
*/
private final long datacenterIdShift = sequenceBits + workerIdBits;
/**
* 时间截向左移22位(5+5+12)
*/
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
/**
* 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
*/
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
/**
* 工作机器ID(0~31)
*/
private long workerId;
/**
* 数据中心ID(0~31)
*/
private long datacenterId;
/**
* 毫秒内序列(0~4095)
*/
private long sequence = 0L;
/**
* 上次生成ID的时间截
*/
private long lastTimestamp = -1L;
@Override
public synchronized long nextValue() throws SeqException {
long timestamp = timeGen();
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if (timestamp < lastTimestamp) {
throw new SeqException("[SnowflakeSequence-nextValue] 当前时间小于上次生成序列号的时间,时间被回退了,请确认服务器时间的设置.");
}
//如果是同一时间生成的,则进行毫秒内序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
//毫秒内序列溢出
if (sequence == 0) {
//阻塞到下一个毫秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp);
}
} else {
//时间戳改变,毫秒内序列重置
sequence = 0L;
}
//上次生成ID的时间截
lastTimestamp = timestamp;
//移位并通过或运算拼到一起组成64位的ID
return ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
/**
* 阻塞到下一个毫秒,直到获得新的时间戳
*
* @param lastTimestamp 上次生成ID的时间截
* @return 当前时间戳
*/
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
/**
* 返回以毫秒为单位的当前时间
*
* @return 当前时间(毫秒)
*/
private long timeGen() {
return System.currentTimeMillis();
}
public void setWorkerId(long workerId) {
if (workerId > maxWorkerId) {
throw new SeqException("[SnowflakeSequence-setWorkerId] workerId 不能大于31.");
}
this.workerId = workerId;
}
public void setDatacenterId(long datacenterId) {
if (datacenterId > maxDatacenterId) {
throw new SeqException("[SnowflakeSequence-setDatacenterId] datacenterId 不能大于31.");
}
this.datacenterId = datacenterId;
}
/**
* 下一个生成序号(带格式)
*
* @return
* @throws SeqException
*/
@Override
public String nextNo() throws SeqException {
return String.valueOf(nextValue());
}
}
@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pig4cloud.common.sequence.SequenceAutoConfiguration
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-swagger</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common-transaction</artifactId>
+2 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-common</artifactId>
@@ -42,6 +42,7 @@
<module>pigx-common-minio</module>
<module>pigx-common-security</module>
<module>pigx-common-swagger</module>
<module>pigx-common-sequence</module>
<module>pigx-common-transaction</module>
<module>pigx-common-datasource</module>
</modules>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-gateway</artifactId>
+1 -1
View File
@@ -18,7 +18,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-register</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-upms</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-upms-api</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-upms</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-upms-biz</artifactId>
@@ -35,6 +35,8 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
;
/**
* @author lengleng
* @date 2018-12-30
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-upms</artifactId>
+1 -1
View File
@@ -23,7 +23,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-visual</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-activiti</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-visual</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-codegen</artifactId>
+1 -1
View File
@@ -23,7 +23,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-visual</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-daemon-elastic-job</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-visual</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+2 -2
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-visual</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-monitor</artifactId>
@@ -36,7 +36,7 @@
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-core</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-visual</artifactId>
<version>3.0.0</version>
<version>3.2</version>
</parent>
<artifactId>pigx-mp-manager</artifactId>
+15
View File
@@ -0,0 +1,15 @@
FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER wangiegie@gmail.com
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN mkdir -p /pigx-pay
WORKDIR /pigx-pay
EXPOSE 5003
ADD ./pigx-visual/pigx-pay/target/pigx-pay.jar ./
CMD sleep 30;java -Djava.security.egd=file:/dev/./urandom -jar pigx-pay.jar
+100
View File
@@ -0,0 +1,100 @@
<?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>
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-visual</artifactId>
<version>3.2</version>
</parent>
<artifactId>pigx-pay</artifactId>
<packaging>jar</packaging>
<description>支付系统</description>
<dependencies>
<!--注册中心客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--配置中心客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--common-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-data</artifactId>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-sequence</artifactId>
</dependency>
<!--swagger-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-swagger</artifactId>
</dependency>
<!--安全模块-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-security</artifactId>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-log</artifactId>
</dependency>
<!-- 支付依赖-->
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.0.52.ALL</version>
</dependency>
<!--web 模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--undertow容器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay;
import com.pig4cloud.pigx.common.security.annotation.EnablePigxFeignClients;
import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer;
import com.pig4cloud.pigx.common.swagger.annotation.EnablePigxSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
/**
* @author lengleng
* @date 2019年05月27日17:25:38
* <p>
* 支付模块
*/
@EnablePigxSwagger2
@SpringCloudApplication
@EnablePigxFeignClients
@EnablePigxResourceServer
public class PigxPayApplication {
public static void main(String[] args) {
SpringApplication.run(PigxPayApplication.class, args);
}
}
@@ -0,0 +1,41 @@
package com.pig4cloud.pigx.pay.config;
import com.jpay.alipay.AliPayApiConfig;
import com.jpay.alipay.AliPayApiConfigKit;
import com.pig4cloud.pigx.pay.service.PayChannelService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
/**
* @author lengleng
* @date 2019-05-31
* <p>
* 支付参数初始化
*/
@Slf4j
@Configuration
@AllArgsConstructor
public class PayConfigParmaInitRunner {
private final PayChannelService channelService;
@Async
@Order
@EventListener({WebServerInitializedEvent.class})
public void initPayConfig() {
AliPayApiConfig rsa2 = AliPayApiConfig.New()
.setAppId("2016102000727659")
.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCkejVpiLJlece9KLb8gG/+WODkpe5SRfr65n3aUAvRPoouDUp/URBAtt24mzHFdGkaU/Il7ZxG7KUjLaFNTfq8t/bHEF7HBt7MZidpEjVaDxeG/hkA+xc+X2ePAJXVhy7v1tH+XRrxuggTj+d4q7vVGD7r1mtgX4d5hK9TTKnyhO6IUcthPOUSn07wx+5wlbv4/51ggj4Ku4AWCGaCWiebDFy4VZ/FmOMP5u3O7TocCGSy5UtaFZaVMM1nH603DG6NJ8fG+zKum9IvrdQMMmBWPT8rpy0U9ztchcd+0gTNrTfE/NOCgl/RF6z7Qic7NiTKjLxkGRq73XPzfJx0hyfpAgMBAAECggEAa2/sndAN/90JjNUgmlVnUnRKCvEceJ9/rw6KXOV2oqrAZg6GgB26iRsqP6EYZMuCsBDvlrjcITQJNq5is/Vg+I8OYr+duVISjN+ZlLexI+/BxYsLWCmr6DE3myCdvwn7rezb5NR6ejWzetvALoG3Qx4AU9sO7rfX7ZevUrE8Pc5pa/rTCHOIec9P7Hfm4xrXd0DPmbAwFvUQ4spcC9xjcBhLJ3tfmkoEU11jC6Y/J7N0/TZZxqNC+HcYftSNEmbO3vxYfz/9mbabx7Uzp8xs4qHPJACmaP5tcWOCf1qJVOwP53Cd3H9J9Be9cAvlxKfT48s1ghoxLn7QB27p0UwntQKBgQDzTpCCFDoUH328B3iGTkwZq24DOUh5ZwhMG6VIFPLHwJYK6HVM473SX0nJWkbiBYFG4WiQWUZnOhz/qjTH1vvE/nzJwQ79zZahren2b8XulXKM6S/mafiBAHKl/FArcr14iAWkh+scZKWFKrNf6Hp8rQ6zu0fWdwzUOlaQFaSnTwKBgQCtDtpIagRPyNj0J39uMRJqsaY0TdJ53TD4bflf5UiFhNFH2Dikgw/uX8Pom2qtIvf3xnO2bzmJW2+OSkF7U0fL+UXkAaBHW+7YVcs8pWARSd5LWBXGWysV2wUALwynZSdwtgpgrzMQnuzklQ3hNR9LBSEGN7yJwkU83ZRWPzbvRwKBgQDU3E8g/oExSbu+3Opc1fNOIeTFfUAitjlUHHulbG5aw+qA8I5vDm/rtOHg/tI0u4w2bs4EO5aUiQsFwesbSsJJvjt+ZyCue0blfDnMGE2aRbVKAlidxOhcNAAZp3ycBm4tHROStjbDSGpm7syvg7xlhyHtrFNVFiJrKf7BX64FkQKBgCA8lAzJMuRp1YAlm2c7XOLjFMLJfFuXCHg+hCWI4Gl+xD1N2b9LarxMuoGp8cUurmJJZWSmc2FS1wT6cBg4+zbTyGEgrGqehW9nC+TQKYUO7Ym7btL0SKJZmiTenszP2vjz8Bryh+CguiAaY+t/qcSfv/cYitZeiec8n1UxkVohAoGAa8YwnzkEGBgz0TpdrGFxVBCqMIriMH4PQs2tWZ1nEBk6A7GrODRcRL0FQnRpHyf3mY5N/iEiNQ5GhQ5p1lifTvolTkVkdHpTGFhVfnYegaEAOznigi7dWJPoYlloN36AROxirGJKRIm+Od2bsybM/dNPJfoTDBDPFWGBH/klEBs=")
.setCharset("UTF-8")
.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuPkP2VJMR6vWCX8RwSFqNIa3klCdvRFJbuS1PN1anzQeeL9eOwtU7kGdI85yxb0dcdPzOYlG+jf9go8W9hBlgjxSRoXxLx03Yfl7cLmzJO9l9vIM1+HmNF0Ctm+el4Yi9dGs/P6q7lcHPUqs/RXGfeLrg33GMVwJbLmRcDZYeIcqPAA1OVF/4SHYr+f+O7glDOd60z+veOOexyoHmvUzYWlEz5+R4kOCNM/Z0w7KGgEYvHbZopexuTuFgUWy/9tYlNrnX+cZUWXVTskLUgD1UGWM1dS5+qfriqY9MPEwJjetcPJkoCK7A4IReE4q1DffUY9KS50/1ML+7na3R/p/UQIDAQAB")
.setServiceUrl("https://openapi.alipaydev.com/gateway.do")
.setSignType("RSA2")
.build();
AliPayApiConfigKit.putApiConfig(rsa2);
}
}
@@ -0,0 +1,61 @@
package com.pig4cloud.pigx.pay.config;
import cn.hutool.core.date.DateUtil;
import com.pig4cloud.common.sequence.builder.DbSeqBuilder;
import com.pig4cloud.common.sequence.properties.SequenceDbProperties;
import com.pig4cloud.common.sequence.sequence.Sequence;
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* @author lengleng
* @date 2019-05-26
* <p>
* 设置发号器生成规则
*/
@Configuration
public class SequenceConfig {
/**
* 订单流水号发号器
*
* @param dataSource
* @param properties
* @return
*/
@Bean
public Sequence paySequence(DataSource dataSource,
SequenceDbProperties properties) {
return DbSeqBuilder
.create()
.bizName(() -> String.format("pay_%s_%s", TenantContextHolder.getTenantId(), DateUtil.today()))
.dataSource(dataSource)
.step(properties.getStep())
.retryTimes(properties.getRetryTimes())
.tableName(properties.getTableName())
.build();
}
/**
* 通道编号发号器
*
* @param dataSource
* @param properties
* @return
*/
@Bean
public Sequence channelSequence(DataSource dataSource,
SequenceDbProperties properties) {
return DbSeqBuilder
.create()
.bizName(() -> String.format("channel_%s", TenantContextHolder.getTenantId()))
.dataSource(dataSource)
.step(properties.getStep())
.retryTimes(properties.getRetryTimes())
.tableName(properties.getTableName())
.build();
}
}
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.pay.entity.PayChannel;
import com.pig4cloud.pigx.pay.service.PayChannelService;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 渠道
*
* @author lengleng
* @date 2019-05-28 23:57:58
*/
@RestController
@AllArgsConstructor
@RequestMapping("/paychannel")
@Api(value = "paychannel", tags = "paychannel管理")
public class PayChannelController {
private final PayChannelService payChannelService;
/**
* 分页查询
*
* @param page 分页对象
* @param payChannel 渠道
* @return
*/
@GetMapping("/page")
public R getPayChannelPage(Page page, PayChannel payChannel) {
return R.ok(payChannelService.page(page, Wrappers.query(payChannel)));
}
/**
* 通过id查询渠道
*
* @param id id
* @return R
*/
@GetMapping("/{id}")
public R getById(@PathVariable("id") Integer id) {
return R.ok(payChannelService.getById(id));
}
/**
* 新增渠道
*
* @param payChannel 渠道
* @return R
*/
@SysLog("新增渠道")
@PostMapping
@PreAuthorize("@pms.hasPermission('pay_paychannel_add')")
public R save(@RequestBody PayChannel payChannel) {
return R.ok(payChannelService.saveChannel(payChannel));
}
/**
* 修改渠道
*
* @param payChannel 渠道
* @return R
*/
@SysLog("修改渠道")
@PutMapping
@PreAuthorize("@pms.hasPermission('pay_paychannel_edit')")
public R updateById(@RequestBody PayChannel payChannel) {
return R.ok(payChannelService.updateById(payChannel));
}
/**
* 通过id删除渠道
*
* @param id id
* @return R
*/
@SysLog("删除渠道")
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('pay_paychannel_del')")
public R removeById(@PathVariable Integer id) {
return R.ok(payChannelService.removeById(id));
}
}
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.pay.entity.PayCheckBatch;
import com.pig4cloud.pigx.pay.service.PayCheckBatchService;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* 批量对账
*
* @author lengleng
* @date 2019-05-28 23:57:38
*/
@RestController
@AllArgsConstructor
@RequestMapping("/paycheckbatch" )
@Api(value = "paycheckbatch", tags = "paycheckbatch管理")
public class PayCheckBatchController {
private final PayCheckBatchService payCheckBatchService;
/**
* 分页查询
* @param page 分页对象
* @param payCheckBatch 批量对账
* @return
*/
@GetMapping("/page" )
public R getPayCheckBatchPage(Page page, PayCheckBatch payCheckBatch) {
return R.ok(payCheckBatchService.page(page, Wrappers.query(payCheckBatch)));
}
/**
* 通过id查询批量对账
* @param id id
* @return R
*/
@GetMapping("/{id}" )
public R getById(@PathVariable("id" ) Long id) {
return R.ok(payCheckBatchService.getById(id));
}
/**
* 新增批量对账
* @param payCheckBatch 批量对账
* @return R
*/
@SysLog("新增批量对账" )
@PostMapping
@PreAuthorize("@pms.hasPermission('pay_paycheckbatch_add')" )
public R save(@RequestBody PayCheckBatch payCheckBatch) {
return R.ok(payCheckBatchService.save(payCheckBatch));
}
/**
* 修改批量对账
* @param payCheckBatch 批量对账
* @return R
*/
@SysLog("修改批量对账" )
@PutMapping
@PreAuthorize("@pms.hasPermission('pay_paycheckbatch_edit')" )
public R updateById(@RequestBody PayCheckBatch payCheckBatch) {
return R.ok(payCheckBatchService.updateById(payCheckBatch));
}
/**
* 通过id删除批量对账
* @param id id
* @return R
*/
@SysLog("删除批量对账" )
@DeleteMapping("/{id}" )
@PreAuthorize("@pms.hasPermission('pay_paycheckbatch_del')" )
public R removeById(@PathVariable Long id) {
return R.ok(payCheckBatchService.removeById(id));
}
}
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.pay.entity.PayCheckMistake;
import com.pig4cloud.pigx.pay.service.PayCheckMistakeService;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* 差错
*
* @author lengleng
* @date 2019-05-28 23:57:50
*/
@RestController
@AllArgsConstructor
@RequestMapping("/paycheckmistake" )
@Api(value = "paycheckmistake", tags = "paycheckmistake管理")
public class PayCheckMistakeController {
private final PayCheckMistakeService payCheckMistakeService;
/**
* 分页查询
* @param page 分页对象
* @param payCheckMistake 差错
* @return
*/
@GetMapping("/page" )
public R getPayCheckMistakePage(Page page, PayCheckMistake payCheckMistake) {
return R.ok(payCheckMistakeService.page(page, Wrappers.query(payCheckMistake)));
}
/**
* 通过id查询差错
* @param id id
* @return R
*/
@GetMapping("/{id}" )
public R getById(@PathVariable("id" ) Long id) {
return R.ok(payCheckMistakeService.getById(id));
}
/**
* 新增差错
* @param payCheckMistake 差错
* @return R
*/
@SysLog("新增差错" )
@PostMapping
@PreAuthorize("@pms.hasPermission('pay_paycheckmistake_add')" )
public R save(@RequestBody PayCheckMistake payCheckMistake) {
return R.ok(payCheckMistakeService.save(payCheckMistake));
}
/**
* 修改差错
* @param payCheckMistake 差错
* @return R
*/
@SysLog("修改差错" )
@PutMapping
@PreAuthorize("@pms.hasPermission('pay_paycheckmistake_edit')" )
public R updateById(@RequestBody PayCheckMistake payCheckMistake) {
return R.ok(payCheckMistakeService.updateById(payCheckMistake));
}
/**
* 通过id删除差错
* @param id id
* @return R
*/
@SysLog("删除差错" )
@DeleteMapping("/{id}" )
@PreAuthorize("@pms.hasPermission('pay_paycheckmistake_del')" )
public R removeById(@PathVariable Long id) {
return R.ok(payCheckMistakeService.removeById(id));
}
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.controller;
import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* 商品
*
* @author lengleng
* @date 2019-05-28 23:58:27
*/
@RestController
@AllArgsConstructor
@RequestMapping("/goods")
@Api(value = "goods", tags = "商品订单管理")
public class PayGoodsOrderController {
private final PayGoodsOrderService payGoodsOrderService;
/**
* 商品订单
*
* @param amount 金额
* @return R
*/
@Inner(false)
@GetMapping("/buy")
@SysLog("新增商品订单")
public R save(Long amount, HttpServletRequest request) {
String ua = request.getHeader(HttpHeaders.USER_AGENT);
if (StrUtil.isBlank(ua)) {
return R.failed("终端不合法");
}
return payGoodsOrderService.buy(amount);
}
}
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* 异步通知记录
*
* @author lengleng
* @date 2019-05-28 23:57:23
*/
@RestController
@AllArgsConstructor
@RequestMapping("/paynotifyrecord" )
@Api(value = "paynotifyrecord", tags = "paynotifyrecord管理")
public class PayNotifyRecordController {
private final PayNotifyRecordService payNotifyRecordService;
/**
* 分页查询
* @param page 分页对象
* @param payNotifyRecord 异步通知记录
* @return
*/
@GetMapping("/page" )
public R getPayNotifyRecordPage(Page page, PayNotifyRecord payNotifyRecord) {
return R.ok(payNotifyRecordService.page(page, Wrappers.query(payNotifyRecord)));
}
/**
* 通过id查询异步通知记录
* @param id id
* @return R
*/
@GetMapping("/{id}" )
public R getById(@PathVariable("id" ) Long id) {
return R.ok(payNotifyRecordService.getById(id));
}
/**
* 新增异步通知记录
* @param payNotifyRecord 异步通知记录
* @return R
*/
@SysLog("新增异步通知记录" )
@PostMapping
@PreAuthorize("@pms.hasPermission('pay_paynotifyrecord_add')" )
public R save(@RequestBody PayNotifyRecord payNotifyRecord) {
return R.ok(payNotifyRecordService.save(payNotifyRecord));
}
/**
* 修改异步通知记录
* @param payNotifyRecord 异步通知记录
* @return R
*/
@SysLog("修改异步通知记录" )
@PutMapping
@PreAuthorize("@pms.hasPermission('pay_paynotifyrecord_edit')" )
public R updateById(@RequestBody PayNotifyRecord payNotifyRecord) {
return R.ok(payNotifyRecordService.updateById(payNotifyRecord));
}
/**
* 通过id删除异步通知记录
* @param id id
* @return R
*/
@SysLog("删除异步通知记录" )
@DeleteMapping("/{id}" )
@PreAuthorize("@pms.hasPermission('pay_paynotifyrecord_del')" )
public R removeById(@PathVariable Long id) {
return R.ok(payNotifyRecordService.removeById(id));
}
}
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.pay.entity.PayRefundOrder;
import com.pig4cloud.pigx.pay.service.PayRefundOrderService;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 退款
*
* @author lengleng
* @date 2019-05-28 23:58:11
*/
@RestController
@AllArgsConstructor
@RequestMapping("/payrefundorder")
@Api(value = "payrefundorder", tags = "payrefundorder管理")
public class PayRefundOrderController {
private final PayRefundOrderService payRefundOrderService;
/**
* 分页查询
*
* @param page 分页对象
* @param payRefundOrder 退款
* @return
*/
@GetMapping("/page")
public R getPayRefundOrderPage(Page page, PayRefundOrder payRefundOrder) {
return R.ok(payRefundOrderService.page(page, Wrappers.query(payRefundOrder)));
}
/**
* 通过id查询退款
*
* @param refundOrderId id
* @return R
*/
@GetMapping("/{refund]orderId}")
public R getById(@PathVariable("refund]orderId") String refundOrderId) {
return R.ok(payRefundOrderService.getById(refundOrderId));
}
/**
* 新增退款
*
* @param payRefundOrder 退款
* @return R
*/
@SysLog("新增退款")
@PostMapping
@PreAuthorize("@pms.hasPermission('pay_payrefundorder_add')")
public R save(@RequestBody PayRefundOrder payRefundOrder) {
return R.ok(payRefundOrderService.save(payRefundOrder));
}
/**
* 修改退款
*
* @param payRefundOrder 退款
* @return R
*/
@SysLog("修改退款")
@PutMapping
@PreAuthorize("@pms.hasPermission('pay_payrefundorder_edit')")
public R updateById(@RequestBody PayRefundOrder payRefundOrder) {
return R.ok(payRefundOrderService.updateById(payRefundOrder));
}
/**
* 通过id删除退款
*
* @param refundOrderId refundOrderId
* @return R
*/
@SysLog("删除退款")
@DeleteMapping("/{refundOrderId}")
@PreAuthorize("@pms.hasPermission('pay_payrefundorder_del')")
public R removeById(@PathVariable String refundOrderId) {
return R.ok(payRefundOrderService.removeById(refundOrderId));
}
}
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* 支付
*
* @author lengleng
* @date 2019-05-28 23:58:18
*/
@RestController
@AllArgsConstructor
@RequestMapping("/paytradeorder" )
@Api(value = "paytradeorder", tags = "paytradeorder管理")
public class PayTradeOrderController {
private final PayTradeOrderService payTradeOrderService;
/**
* 分页查询
* @param page 分页对象
* @param payTradeOrder 支付
* @return
*/
@GetMapping("/page" )
public R getPayTradeOrderPage(Page page, PayTradeOrder payTradeOrder) {
return R.ok(payTradeOrderService.page(page, Wrappers.query(payTradeOrder)));
}
/**
* 通过id查询支付
* @param orderId id
* @return R
*/
@GetMapping("/{orderId}" )
public R getById(@PathVariable("orderId" ) String orderId) {
return R.ok(payTradeOrderService.getById(orderId));
}
/**
* 新增支付
* @param payTradeOrder 支付
* @return R
*/
@SysLog("新增支付" )
@PostMapping
@PreAuthorize("@pms.hasPermission('pay_paytradeorder_add')" )
public R save(@RequestBody PayTradeOrder payTradeOrder) {
return R.ok(payTradeOrderService.save(payTradeOrder));
}
/**
* 修改支付
* @param payTradeOrder 支付
* @return R
*/
@SysLog("修改支付" )
@PutMapping
@PreAuthorize("@pms.hasPermission('pay_paytradeorder_edit')" )
public R updateById(@RequestBody PayTradeOrder payTradeOrder) {
return R.ok(payTradeOrderService.updateById(payTradeOrder));
}
/**
* 通过id删除支付
* @param orderId id
* @return R
*/
@SysLog("删除支付" )
@DeleteMapping("/{orderId}" )
@PreAuthorize("@pms.hasPermission('pay_paytradeorder_del')" )
public R removeById(@PathVariable String orderId) {
return R.ok(payTradeOrderService.removeById(orderId));
}
}
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 渠道
*
* @author lengleng
* @date 2019-05-28 23:57:58
*/
@Data
@TableName("pay_channel")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "渠道")
public class PayChannel extends Model<PayChannel> {
private static final long serialVersionUID = 1L;
/**
* 渠道主键ID
*/
@TableId
private Integer id;
/**
* 渠道ID
*/
private String channelId;
/**
* 渠道名称,如:alipay,wechat
*/
private String channelName;
/**
* 渠道商户ID
*/
private String channelMchId;
/**
* 内部商户ID
*/
private String mchId;
/**
* 渠道状态
*/
private String state;
/**
* 配置参数,json字符串
*/
private String param;
/**
* 备注
*/
private String remark;
/**
* 删除标记
*/
@TableLogic
private String delFlag;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 租户ID
*/
private Integer tenantId;
}
@@ -0,0 +1,151 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 批量对账
*
* @author lengleng
* @date 2019-05-28 23:57:38
*/
@Data
@TableName("pay_check_batch")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "批量对账")
public class PayCheckBatch extends Model<PayCheckBatch> {
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String status;
/**
*
*/
private String remark;
/**
*
*/
private String batchNo;
/**
*
*/
private LocalDateTime billDate;
/**
*
*/
private String billType;
/**
*
*/
private String handleStatus;
/**
*
*/
private String bankType;
/**
*
*/
private Integer mistakeCount;
/**
*
*/
private Integer unhandleMistakeCount;
/**
*
*/
private Integer tradeCount;
/**
*
*/
private Integer bankTradeCount;
/**
*
*/
private BigDecimal tradeAmount;
/**
*
*/
private BigDecimal bankTradeAmount;
/**
*
*/
private BigDecimal refundAmount;
/**
*
*/
private BigDecimal bankRefundAmount;
/**
*
*/
private BigDecimal bankFee;
/**
*
*/
private String orgCheckFilePath;
/**
*
*/
private String releaseCheckFilePath;
/**
*
*/
private String releaseStatus;
/**
*
*/
private String checkFailMsg;
/**
*
*/
private String bankErrMsg;
/**
*
*/
@TableLogic
private String delFlag;
/**
*
*/
private LocalDateTime createTime;
/**
*
*/
private LocalDateTime updateTime;
/**
* 租户ID
*/
private Integer tenantId;
}
@@ -0,0 +1,151 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 差错
*
* @author lengleng
* @date 2019-05-28 23:57:50
*/
@Data
@TableName("pay_check_mistake")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "差错")
public class PayCheckMistake extends Model<PayCheckMistake> {
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId
private Long id;
/**
* 商品名称
*/
private String productName;
/**
* 订单号
*/
private String orderNo;
/**
* 支付流水号
*/
private String trxNo;
/**
* 银行订单号
*/
private String bankOrderNo;
/**
* 银行流水号
*/
private String bankTrxNo;
/**
* 订单金额
*/
private BigDecimal orderAmount;
/**
* 平台收入
*/
private BigDecimal platIncome;
/**
* 费率
*/
private BigDecimal feeRate;
/**
* 平台成本
*/
private BigDecimal platCost;
/**
* 平台利润
*/
private BigDecimal platProfit;
/**
* 状态(参考枚举:paymentrecordstatusenum)
*/
private String status;
/**
* 支付通道编号
*/
private String payWayCode;
/**
* 支付通道名称
*/
private String payWayName;
/**
* 支付成功时间
*/
private LocalDateTime paySuccessTime;
/**
* 完成时间
*/
private LocalDateTime completeTime;
/**
* 是否退款(100:是,101:否,默认值为:101)
*/
private String isRefund;
/**
* 退款次数(默认值为:0)
*/
private Integer refundTimes;
/**
* 成功退款总金额
*/
private BigDecimal successRefundAmount;
/**
* 备注
*/
private String remark;
/**
*
*/
private String batchNo;
/**
*
*/
private LocalDateTime billDate;
/**
*
*/
private LocalDateTime createTime;
/**
*
*/
private LocalDateTime updateTime;
/**
*
*/
@TableLogic
private String delFlag;
/**
* 租户ID
*/
private Integer tenantId;
}
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 商品
*
* @author lengleng
* @date 2019-05-28 23:58:27
*/
@Data
@TableName("pay_goods_order")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "商品")
public class PayGoodsOrder extends Model<PayGoodsOrder> {
private static final long serialVersionUID = 1L;
/**
* 商品订单ID
*/
@TableId
private String goodsOrderId;
/**
* 商品ID
*/
private String goodsId;
/**
* 商品名称
*/
private String goodsName;
/**
* 金额,单位分
*/
private Long amount;
/**
* 用户ID
*/
private String userId;
/**
* 订单状态,订单生成(0),支付成功(1),处理完成(2),处理失败(-1)
*/
private Integer status;
/**
* 支付订单号
*/
private String payOrderId;
/**
* 0-正常,1-删除
*/
@TableLogic
private String delFlag;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 租户ID
*/
private Integer tenantId;
}
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 异步通知记录
*
* @author lengleng
* @date 2019-05-28 23:57:23
*/
@Data
@TableName("pay_notify_record")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "异步通知记录")
public class PayNotifyRecord extends Model<PayNotifyRecord> {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId
private Long id;
/**
* 响应ID
*/
private String notifyId;
/**
* 请求报文
*/
private String request;
/**
* 响应报文
*/
private String response;
/**
* 系统订单号
*/
private String orderNo;
/**
* http状态
*/
private String httpStatus;
/**
* 删除标记
*/
@TableLogic
private String delFlag;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 租户ID
*/
private Integer tenantId;
}
@@ -0,0 +1,166 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 退款
*
* @author lengleng
* @date 2019-05-28 23:58:11
*/
@Data
@TableName("pay_refund_order")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "退款")
public class PayRefundOrder extends Model<PayRefundOrder> {
private static final long serialVersionUID = 1L;
/**
* 退款订单号
*/
@TableId
private String refundOrderId;
/**
* 支付订单号
*/
private String payOrderId;
/**
* 渠道支付单号
*/
private String channelPayOrderNo;
/**
* 商户ID
*/
private String mchId;
/**
* 商户退款单号
*/
private String mchRefundNo;
/**
* 渠道ID
*/
private String channelId;
/**
* 支付金额,单位分
*/
private Long payAmount;
/**
* 退款金额,单位分
*/
private Long refundAmount;
/**
* 三位货币代码,人民币:cny
*/
private String currency;
/**
* 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败,4-业务处理完成
*/
private Integer status;
/**
* 退款结果:0-不确认结果,1-等待手动处理,2-确认成功,3-确认失败
*/
private Integer result;
/**
* 客户端IP
*/
private String clientIp;
/**
* 设备
*/
private String device;
/**
* 备注
*/
private String remark;
/**
* 渠道用户标识,如微信openId,支付宝账号
*/
private String channelUser;
/**
* 用户姓名
*/
private String username;
/**
* 渠道商户ID
*/
private String channelMchId;
/**
* 渠道订单号
*/
private String channelOrderNo;
/**
* 渠道错误码
*/
private String channelErrCode;
/**
* 渠道错误描述
*/
private String channelErrMsg;
/**
* 特定渠道发起时额外参数
*/
private String extra;
/**
* 通知地址
*/
private String notifyurl;
/**
* 扩展参数1
*/
private String param1;
/**
* 扩展参数2
*/
private String param2;
/**
* 订单失效时间
*/
private LocalDateTime expireTime;
/**
* 订单退款成功时间
*/
private LocalDateTime refundSuccTime;
/**
* 删除标记
*/
@TableLogic
private String delFlag;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 租户ID
*/
private Integer tenantId;
}
@@ -0,0 +1,147 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 支付
*
* @author lengleng
* @date 2019-05-28 23:58:18
*/
@Data
@TableName("pay_trade_order")
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "支付")
public class PayTradeOrder extends Model<PayTradeOrder> {
private static final long serialVersionUID = 1L;
/**
* 支付订单号
*/
@TableId(type = IdType.INPUT)
private String orderId;
/**
* 渠道ID
*/
private String channelId;
/**
* 支付金额,单位分
*/
private Long amount;
/**
* 三位货币代码,人民币:cny
*/
private String currency;
/**
* 支付状态,0-订单生成,1-支付中(目前未使用),2-支付成功,3-业务处理完成
*/
private Integer status;
/**
* 客户端IP
*/
private String clientIp;
/**
* 设备
*/
private String device;
/**
* 商品标题
*/
private String subject;
/**
* 商品描述信息
*/
private String body;
/**
* 特定渠道发起时额外参数
*/
private String extra;
/**
* 渠道商户ID
*/
private String channelMchId;
/**
* 渠道订单号
*/
private String channelOrderNo;
/**
* 渠道支付错误码
*/
private String errCode;
/**
* 渠道支付错误描述
*/
private String errMsg;
/**
* 扩展参数1
*/
private String param1;
/**
* 扩展参数2
*/
private String param2;
/**
* 通知地址
*/
private String notifyUrl;
/**
* 通知次数
*/
private Integer notifyCount;
/**
* 最后一次通知时间
*/
private Long lastNotifyTime;
/**
* 订单失效时间
*/
private Long expireTime;
/**
* 订单支付成功时间
*/
private Long paySuccTime;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
private String delFlaag;
/**
* 租户ID
*/
private Integer tenantId;
}
@@ -0,0 +1,44 @@
package com.pig4cloud.pigx.pay.handler;
import com.pig4cloud.common.sequence.sequence.Sequence;
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
import com.pig4cloud.pigx.pay.utils.OrderStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @author lengleng
* @date 2019-05-31
*/
public abstract class AbstractPayOrderHandler implements PayOrderHandler {
@Autowired
private PayGoodsOrderService goodsOrderService;
@Autowired
private Sequence paySequence;
/**
* 创建商品订单
*
* @param goodsOrder 商品订单
* @return
*/
@Override
public void createGoodsOrder(PayGoodsOrder goodsOrder) {
goodsOrder.setPayOrderId(paySequence.nextNo());
goodsOrder.setStatus(OrderStatusEnum.INIT.getStatus());
goodsOrderService.save(goodsOrder);
}
/**
* 调用入口
*/
@Override
public void handle(PayGoodsOrder payGoodsOrder) {
createGoodsOrder(payGoodsOrder);
PayTradeOrder tradeOrder = createTradeOrder(payGoodsOrder);
pay(payGoodsOrder, tradeOrder);
updateOrder(payGoodsOrder, tradeOrder);
}
}
@@ -0,0 +1,102 @@
package com.pig4cloud.pigx.pay.handler;
import cn.hutool.extra.servlet.ServletUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.jpay.alipay.AliPayApi;
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
import com.pig4cloud.pigx.pay.utils.OrderStatusEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lengleng
* @date 2019-05-31
* <p>
* 支付宝手机支付
*/
@Slf4j
@Service("ALIPAY_WAP")
@AllArgsConstructor
public class AlipayWapPayOrderHandler extends AbstractPayOrderHandler {
private final PayTradeOrderService tradeOrderService;
private final PayGoodsOrderService goodsOrderService;
private final HttpServletRequest request;
private final HttpServletResponse response;
/**
* 创建交易订单
*
* @param goodsOrder
* @return
*/
@Override
public PayTradeOrder createTradeOrder(PayGoodsOrder goodsOrder) {
PayTradeOrder tradeOrder = new PayTradeOrder();
tradeOrder.setOrderId(goodsOrder.getPayOrderId());
tradeOrder.setAmount(goodsOrder.getAmount());
tradeOrder.setChannelId("ALIPAY_WAP");
tradeOrder.setChannelMchId("1517584931");
tradeOrder.setClientIp(ServletUtil.getClientIP(request));
tradeOrder.setCurrency("cny");
tradeOrder.setExpireTime(30L);
tradeOrder.setStatus(OrderStatusEnum.INIT.getStatus());
tradeOrder.setBody("测试商品");
tradeOrderService.save(tradeOrder);
return tradeOrder;
}
/**
* 调起渠道支付
*
* @param goodsOrder 商品订单
* @param tradeOrder 交易订单
*/
@Override
public PayTradeOrder pay(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder) {
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setBody(tradeOrder.getBody());
model.setSubject(tradeOrder.getBody());
model.setOutTradeNo(tradeOrder.getOrderId());
model.setTimeoutExpress(tradeOrder.getExpireTime() + "m");
model.setTotalAmount(String.valueOf(tradeOrder.getAmount()));
model.setPassbackParams(String.valueOf(TenantContextHolder.getTenantId()));
model.setProductCode(goodsOrder.getGoodsId());
try {
AliPayApi.wapPay(response, model, "http://www.baidu.com", "/alipay/notify_url");
} catch (AlipayApiException e) {
log.warn("支付宝支付失败 {} {}", e.getErrCode(), e.getErrMsg());
tradeOrder.setErrMsg(e.getErrMsg());
tradeOrder.setErrCode(e.getErrCode());
tradeOrder.setStatus(OrderStatusEnum.FAIL.getStatus());
goodsOrder.setStatus(OrderStatusEnum.FAIL.getStatus());
} catch (IOException e) {
log.error("支付宝手机支付失败", e);
tradeOrder.setErrMsg(e.getMessage());
tradeOrder.setStatus(OrderStatusEnum.FAIL.getStatus());
goodsOrder.setStatus(OrderStatusEnum.FAIL.getStatus());
}
return tradeOrder;
}
/**
* 更新订单信息
*
* @param goodsOrder 商品订单
* @param tradeOrder 交易订单
*/
@Override
public void updateOrder(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder) {
tradeOrderService.updateById(tradeOrder);
goodsOrderService.updateById(goodsOrder);
}
}
@@ -0,0 +1,49 @@
package com.pig4cloud.pigx.pay.handler;
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
/**
* @author lengleng
* @date 2019-05-31
* <p>
* 支付业务
*/
public interface PayOrderHandler {
/**
* 创建商品订单
*
* @param goodsOrder 金额
* @return
*/
void createGoodsOrder(PayGoodsOrder goodsOrder);
/**
* 创建交易订单
*
* @param goodsOrder 商品订单
* @return
*/
PayTradeOrder createTradeOrder(PayGoodsOrder goodsOrder);
/**
* 调起渠道支付
*
* @param goodsOrder 商品订单
* @param tradeOrder 交易订单
*/
PayTradeOrder pay(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder);
/**
* 更新订单信息
*/
void updateOrder(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder);
/**
* 调用入口
*
* @param goodsOrde 商品订单
*/
void handle(PayGoodsOrder goodsOrde);
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.pay.entity.PayChannel;
/**
* 渠道
*
* @author lengleng
* @date 2019-05-28 23:57:58
*/
public interface PayChannelMapper extends BaseMapper<PayChannel> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.pay.entity.PayCheckBatch;
/**
* 批量对账
*
* @author lengleng
* @date 2019-05-28 23:57:38
*/
public interface PayCheckBatchMapper extends BaseMapper<PayCheckBatch> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.pay.entity.PayCheckMistake;
/**
* 差错
*
* @author lengleng
* @date 2019-05-28 23:57:50
*/
public interface PayCheckMistakeMapper extends BaseMapper<PayCheckMistake> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
/**
* 商品
*
* @author lengleng
* @date 2019-05-28 23:58:27
*/
public interface PayGoodsOrderMapper extends BaseMapper<PayGoodsOrder> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
/**
* 异步通知记录
*
* @author lengleng
* @date 2019-05-28 23:57:23
*/
public interface PayNotifyRecordMapper extends BaseMapper<PayNotifyRecord> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.pay.entity.PayRefundOrder;
/**
* 退款
*
* @author lengleng
* @date 2019-05-28 23:58:11
*/
public interface PayRefundOrderMapper extends BaseMapper<PayRefundOrder> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
/**
* 支付
*
* @author lengleng
* @date 2019-05-28 23:58:18
*/
public interface PayTradeOrderMapper extends BaseMapper<PayTradeOrder> {
}
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.pay.entity.PayChannel;
/**
* 渠道
*
* @author lengleng
* @date 2019-05-28 23:57:58
*/
public interface PayChannelService extends IService<PayChannel> {
/**
* 新增支付渠道
*
* @param payChannel 支付渠道
* @return
*/
Boolean saveChannel(PayChannel payChannel);
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.pay.entity.PayCheckBatch;
/**
* 批量对账
*
* @author lengleng
* @date 2019-05-28 23:57:38
*/
public interface PayCheckBatchService extends IService<PayCheckBatch> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.pay.entity.PayCheckMistake;
/**
* 差错
*
* @author lengleng
* @date 2019-05-28 23:57:50
*/
public interface PayCheckMistakeService extends IService<PayCheckMistake> {
}
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
/**
* 商品
*
* @author lengleng
* @date 2019-05-28 23:58:27
*/
public interface PayGoodsOrderService extends IService<PayGoodsOrder> {
/**
* 购买商品
*
* @param amount
* @return
*/
R buy(Long amount);
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
/**
* 异步通知记录
*
* @author lengleng
* @date 2019-05-28 23:57:23
*/
public interface PayNotifyRecordService extends IService<PayNotifyRecord> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.pay.entity.PayRefundOrder;
/**
* 退款
*
* @author lengleng
* @date 2019-05-28 23:58:11
*/
public interface PayRefundOrderService extends IService<PayRefundOrder> {
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
/**
* 支付
*
* @author lengleng
* @date 2019-05-28 23:58:18
*/
public interface PayTradeOrderService extends IService<PayTradeOrder> {
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.common.sequence.sequence.Sequence;
import com.pig4cloud.pigx.pay.entity.PayChannel;
import com.pig4cloud.pigx.pay.mapper.PayChannelMapper;
import com.pig4cloud.pigx.pay.service.PayChannelService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
/**
* 渠道
*
* @author lengleng
* @date 2019-05-28 23:57:58
*/
@Service
@AllArgsConstructor
public class PayChannelServiceImpl extends ServiceImpl<PayChannelMapper, PayChannel> implements PayChannelService {
private final Sequence channelSequence;
/**
* 新增支付渠道
*
* @param payChannel 支付渠道
* @return
*/
@Override
public Boolean saveChannel(PayChannel payChannel) {
payChannel.setMchId(channelSequence.nextNo());
return save(payChannel);
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.pay.entity.PayCheckBatch;
import com.pig4cloud.pigx.pay.mapper.PayCheckBatchMapper;
import com.pig4cloud.pigx.pay.service.PayCheckBatchService;
import org.springframework.stereotype.Service;
/**
* 批量对账
*
* @author lengleng
* @date 2019-05-28 23:57:38
*/
@Service
public class PayCheckBatchServiceImpl extends ServiceImpl<PayCheckBatchMapper, PayCheckBatch> implements PayCheckBatchService {
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.pay.entity.PayCheckMistake;
import com.pig4cloud.pigx.pay.mapper.PayCheckMistakeMapper;
import com.pig4cloud.pigx.pay.service.PayCheckMistakeService;
import org.springframework.stereotype.Service;
/**
* 差错
*
* @author lengleng
* @date 2019-05-28 23:57:50
*/
@Service
public class PayCheckMistakeServiceImpl extends ServiceImpl<PayCheckMistakeMapper, PayCheckMistake> implements PayCheckMistakeService {
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.common.sequence.sequence.Sequence;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
import com.pig4cloud.pigx.pay.mapper.PayGoodsOrderMapper;
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 商品
*
* @author lengleng
* @date 2019-05-28 23:58:27
*/
@Slf4j
@Service
@AllArgsConstructor
public class PayGoodsOrderServiceImpl extends ServiceImpl<PayGoodsOrderMapper, PayGoodsOrder> implements PayGoodsOrderService {
private final PayTradeOrderService tradeOrderService;
private static final String WX = "MicroMessenger";
private final HttpServletRequest request;
private final HttpServletResponse response;
private final Sequence paySequence;
/**
* 购买商品
* <p>
* 1、 新增商品订单
* 2、 根据UA 去下单
* 3、构建支付订单
*
* @param amount
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public R buy(Long amount) {
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
import com.pig4cloud.pigx.pay.mapper.PayNotifyRecordMapper;
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
import org.springframework.stereotype.Service;
/**
* 异步通知记录
*
* @author lengleng
* @date 2019-05-28 23:57:23
*/
@Service
public class PayNotifyRecordServiceImpl extends ServiceImpl<PayNotifyRecordMapper, PayNotifyRecord> implements PayNotifyRecordService {
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.pay.entity.PayRefundOrder;
import com.pig4cloud.pigx.pay.mapper.PayRefundOrderMapper;
import com.pig4cloud.pigx.pay.service.PayRefundOrderService;
import org.springframework.stereotype.Service;
/**
* 退款
*
* @author lengleng
* @date 2019-05-28 23:58:11
*/
@Service
public class PayRefundOrderServiceImpl extends ServiceImpl<PayRefundOrderMapper, PayRefundOrder> implements PayRefundOrderService {
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
import com.pig4cloud.pigx.pay.mapper.PayTradeOrderMapper;
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
import org.springframework.stereotype.Service;
/**
* 支付
*
* @author lengleng
* @date 2019-05-28 23:58:18
*/
@Service
public class PayTradeOrderServiceImpl extends ServiceImpl<PayTradeOrderMapper, PayTradeOrder> implements PayTradeOrderService {
}
@@ -0,0 +1,44 @@
package com.pig4cloud.pigx.pay.utils;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2019-05-30
* <p>
* 订单状态
*/
@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
/**
* 订单初始 下单
*/
INIT(0, "下单"),
/**
* 订单支付成功
*/
SUCCESS(1, "成功"),
/**
* 订单支付完成
*/
COMPLETE(2, "完成"),
/**
* 订单支付失败
*/
FAIL(-1, "失败");
/**
* 状态
*/
private Integer status;
/**
* 描述
*/
private String description;
}
@@ -0,0 +1,38 @@
package com.pig4cloud.pigx.pay.utils;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2019-05-30
* <p>
* 支付渠道名称
*/
@Getter
@AllArgsConstructor
public enum PayChannelNameEnum {
/**
* 支付宝
*/
ALIPAY("alipay", "支付宝"),
/**
* 微信支付
*/
WXPAY("wxpay", "微信支付"),
/**
* 微信服务商支付
*/
WESUBPAY("wxsubpay", "微信服务商支付");
/**
* 名称
*/
private String name;
/**
* 描述
*/
private String description;
}
@@ -0,0 +1,16 @@
server:
port: 5003
spring:
application:
name: @artifactId@
cloud:
nacos:
discovery:
server-addr: ${NACOS-HOST:pigx-register}:${NACOS-PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
file-extension: yml
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
profiles:
active: dev
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright (c) 2018-2025, lengleng All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of source code must retain the above copyright notice,
~ this list of conditions and the following disclaimer.
~ Redistributions in binary form must reproduce the above copyright
~ notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~ Neither the name of the pig4cloud.com developer nor the names of its
~ contributors may be used to endorse or promote products derived from
~ this software without specific prior written permission.
~ Author: lengleng (wangiegie@gmail.com)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.pay.mapper.PayChannelMapper">
<resultMap id="payChannelMap" type="com.pig4cloud.pigx.pay.entity.PayChannel">
<id property="id" column="id"/>
<result property="channelId" column="channel_id"/>
<result property="channelName" column="channel_name"/>
<result property="channelMchId" column="channel_mch_id"/>
<result property="mchId" column="mch_id"/>
<result property="state" column="state"/>
<result property="param" column="param"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright (c) 2018-2025, lengleng All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of source code must retain the above copyright notice,
~ this list of conditions and the following disclaimer.
~ Redistributions in binary form must reproduce the above copyright
~ notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~ Neither the name of the pig4cloud.com developer nor the names of its
~ contributors may be used to endorse or promote products derived from
~ this software without specific prior written permission.
~ Author: lengleng (wangiegie@gmail.com)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.pay.mapper.PayCheckBatchMapper">
<resultMap id="payCheckBatchMap" type="com.pig4cloud.pigx.pay.entity.PayCheckBatch">
<id property="id" column="id"/>
<result property="status" column="status"/>
<result property="remark" column="remark"/>
<result property="batchNo" column="batch_no"/>
<result property="billDate" column="bill_date"/>
<result property="billType" column="bill_type"/>
<result property="handleStatus" column="handle_status"/>
<result property="bankType" column="bank_type"/>
<result property="mistakeCount" column="mistake_count"/>
<result property="unhandleMistakeCount" column="unhandle_mistake_count"/>
<result property="tradeCount" column="trade_count"/>
<result property="bankTradeCount" column="bank_trade_count"/>
<result property="tradeAmount" column="trade_amount"/>
<result property="bankTradeAmount" column="bank_trade_amount"/>
<result property="refundAmount" column="refund_amount"/>
<result property="bankRefundAmount" column="bank_refund_amount"/>
<result property="bankFee" column="bank_fee"/>
<result property="orgCheckFilePath" column="org_check_file_path"/>
<result property="releaseCheckFilePath" column="release_check_file_path"/>
<result property="releaseStatus" column="release_status"/>
<result property="checkFailMsg" column="check_fail_msg"/>
<result property="bankErrMsg" column="bank_err_msg"/>
<result property="delFlag" column="del_flag"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright (c) 2018-2025, lengleng All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of source code must retain the above copyright notice,
~ this list of conditions and the following disclaimer.
~ Redistributions in binary form must reproduce the above copyright
~ notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~ Neither the name of the pig4cloud.com developer nor the names of its
~ contributors may be used to endorse or promote products derived from
~ this software without specific prior written permission.
~ Author: lengleng (wangiegie@gmail.com)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.pay.mapper.PayCheckMistakeMapper">
<resultMap id="payCheckMistakeMap" type="com.pig4cloud.pigx.pay.entity.PayCheckMistake">
<id property="id" column="id"/>
<result property="productName" column="product_name"/>
<result property="orderNo" column="order_no"/>
<result property="trxNo" column="trx_no"/>
<result property="bankOrderNo" column="bank_order_no"/>
<result property="bankTrxNo" column="bank_trx_no"/>
<result property="orderAmount" column="order_amount"/>
<result property="platIncome" column="plat_income"/>
<result property="feeRate" column="fee_rate"/>
<result property="platCost" column="plat_cost"/>
<result property="platProfit" column="plat_profit"/>
<result property="status" column="status"/>
<result property="payWayCode" column="pay_way_code"/>
<result property="payWayName" column="pay_way_name"/>
<result property="paySuccessTime" column="pay_success_time"/>
<result property="completeTime" column="complete_time"/>
<result property="isRefund" column="is_refund"/>
<result property="refundTimes" column="refund_times"/>
<result property="successRefundAmount" column="success_refund_amount"/>
<result property="remark" column="remark"/>
<result property="batchNo" column="batch_no"/>
<result property="billDate" column="bill_date"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright (c) 2018-2025, lengleng All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of source code must retain the above copyright notice,
~ this list of conditions and the following disclaimer.
~ Redistributions in binary form must reproduce the above copyright
~ notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~ Neither the name of the pig4cloud.com developer nor the names of its
~ contributors may be used to endorse or promote products derived from
~ this software without specific prior written permission.
~ Author: lengleng (wangiegie@gmail.com)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.pay.mapper.PayGoodsOrderMapper">
<resultMap id="payGoodsOrderMap" type="com.pig4cloud.pigx.pay.entity.PayGoodsOrder">
<id property="goodsOrderId" column="goods_order_id"/>
<result property="goodsId" column="goods_id"/>
<result property="goodsName" column="goods_name"/>
<result property="amount" column="amount"/>
<result property="userId" column="user_id"/>
<result property="status" column="status"/>
<result property="payOrderId" column="pay_order_id"/>
<result property="delFlag" column="del_flag"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff. Show more