com.pig4cloud
pigx-common-swagger
diff --git a/pigx-common/pigx-common-core/pom.xml b/pigx-common/pigx-common-core/pom.xml
index 20bcde7cb..f1f278aed 100644
--- a/pigx-common/pigx-common-core/pom.xml
+++ b/pigx-common/pigx-common-core/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-core
diff --git a/pigx-common/pigx-common-data/pom.xml b/pigx-common/pigx-common-data/pom.xml
index 7681cb3a3..163151b47 100644
--- a/pigx-common/pigx-common-data/pom.xml
+++ b/pigx-common/pigx-common-data/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-data
diff --git a/pigx-common/pigx-common-datasource/pom.xml b/pigx-common/pigx-common-datasource/pom.xml
index 32c4c9c41..fb661eab4 100644
--- a/pigx-common/pigx-common-datasource/pom.xml
+++ b/pigx-common/pigx-common-datasource/pom.xml
@@ -5,7 +5,7 @@
pigx-common
com.pig4cloud
- 3.0.0
+ 3.2
4.0.0
diff --git a/pigx-common/pigx-common-gateway/pom.xml b/pigx-common/pigx-common-gateway/pom.xml
index fb0530b99..e5910a701 100644
--- a/pigx-common/pigx-common-gateway/pom.xml
+++ b/pigx-common/pigx-common-gateway/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-gateway
diff --git a/pigx-common/pigx-common-job/pom.xml b/pigx-common/pigx-common-job/pom.xml
index f76d82892..c6e6085e5 100644
--- a/pigx-common/pigx-common-job/pom.xml
+++ b/pigx-common/pigx-common-job/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-job
diff --git a/pigx-common/pigx-common-log/pom.xml b/pigx-common/pigx-common-log/pom.xml
index 9c47752d2..2c8238f51 100644
--- a/pigx-common/pigx-common-log/pom.xml
+++ b/pigx-common/pigx-common-log/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-log
diff --git a/pigx-common/pigx-common-minio/pom.xml b/pigx-common/pigx-common-minio/pom.xml
index 10db5e14d..1892719e9 100755
--- a/pigx-common/pigx-common-minio/pom.xml
+++ b/pigx-common/pigx-common-minio/pom.xml
@@ -6,7 +6,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-minio
diff --git a/pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java b/pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java
index 35e822eff..7a1a38f64 100755
--- a/pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java
+++ b/pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java
@@ -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);
}
/**
diff --git a/pigx-common/pigx-common-security/pom.xml b/pigx-common/pigx-common-security/pom.xml
index 58095bc84..c6fcf6e98 100644
--- a/pigx-common/pigx-common-security/pom.xml
+++ b/pigx-common/pigx-common-security/pom.xml
@@ -23,7 +23,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-security
diff --git a/pigx-common/pigx-common-sequence/pom.xml b/pigx-common/pigx-common-sequence/pom.xml
new file mode 100755
index 000000000..460e8ba06
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+ com.pig4cloud
+ pigx-common
+ 3.2
+
+
+ pigx-common-sequence
+ jar
+
+ pigx 分布式发号器
+
+
+
+ redis.clients
+ jedis
+
+
+ com.pig4cloud
+ pigx-common-core
+
+
+
\ No newline at end of file
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/SequenceAutoConfiguration.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/SequenceAutoConfiguration.java
new file mode 100644
index 000000000..2b10a4dd1
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/SequenceAutoConfiguration.java
@@ -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();
+ }
+}
\ No newline at end of file
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/DbSeqBuilder.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/DbSeqBuilder.java
new file mode 100755
index 000000000..9b8f97aa2
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/DbSeqBuilder.java
@@ -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;
+ }
+
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/RedisSeqBuilder.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/RedisSeqBuilder.java
new file mode 100755
index 000000000..fd34d04cb
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/RedisSeqBuilder.java
@@ -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;
+ }
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SeqBuilder.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SeqBuilder.java
new file mode 100755
index 000000000..364287e87
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SeqBuilder.java
@@ -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();
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SnowflakeSeqBuilder.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SnowflakeSeqBuilder.java
new file mode 100755
index 000000000..12cd8f49a
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SnowflakeSeqBuilder.java
@@ -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;
+ }
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/exception/SeqException.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/exception/SeqException.java
new file mode 100755
index 000000000..e5b5720fb
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/exception/SeqException.java
@@ -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);
+ }
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/BaseSequenceProperties.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/BaseSequenceProperties.java
new file mode 100644
index 000000000..425736fae
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/BaseSequenceProperties.java
@@ -0,0 +1,27 @@
+package com.pig4cloud.common.sequence.properties;
+
+import lombok.Data;
+
+/**
+ * @author lengleng
+ * @date 2019-05-26
+ *
+ * 发号器通用属性
+ */
+@Data
+class BaseSequenceProperties {
+ /**
+ * 获取range步长[可选,默认:1000]
+ */
+ private int step = 1000;
+
+ /**
+ * 序列号分配起始值[可选:默认:0]
+ */
+ private long stepStart = 0;
+
+ /**
+ * 业务名称
+ */
+ private String bizName = "pigx";
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceDbProperties.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceDbProperties.java
new file mode 100644
index 000000000..016314f1f
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceDbProperties.java
@@ -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
+ *
+ * 发号器DB配置属性
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "xsequence.db")
+public class SequenceDbProperties extends BaseSequenceProperties {
+ /**
+ * 表名称
+ */
+ private String tableName;
+ /**
+ * 重试次数
+ */
+ private int retryTimes;
+
+}
\ No newline at end of file
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceRedisProperties.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceRedisProperties.java
new file mode 100644
index 000000000..d6e0473f9
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceRedisProperties.java
@@ -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
+ *
+ * 发号器Redis配置属性
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "xsequence.redis")
+public class SequenceRedisProperties extends BaseSequenceProperties {
+
+}
\ No newline at end of file
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceSnowflakeProperties.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceSnowflakeProperties.java
new file mode 100644
index 000000000..f7927cb36
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceSnowflakeProperties.java
@@ -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
+ *
+ * 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;
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/BizName.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/BizName.java
new file mode 100644
index 000000000..813fa7883
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/BizName.java
@@ -0,0 +1,15 @@
+package com.pig4cloud.common.sequence.range;
+
+/**
+ * @author lengleng
+ * @date 2019-05-26
+ *
+ * 名称生成器
+ */
+public interface BizName {
+ /**
+ * 生成名称
+ */
+ String create();
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRange.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRange.java
new file mode 100755
index 000000000..ce0979df0
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRange.java
@@ -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;
+ }
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRangeMgr.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRangeMgr.java
new file mode 100755
index 000000000..9dfd974ab
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRangeMgr.java
@@ -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();
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/BaseDbHelper.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/BaseDbHelper.java
new file mode 100755
index 000000000..0442d7bd4
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/BaseDbHelper.java
@@ -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
+ }
+ }
+ }
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/DbSeqRangeMgr.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/DbSeqRangeMgr.java
new file mode 100755
index 000000000..b34008d85
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/DbSeqRangeMgr.java
@@ -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;
+ }
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DateBizName.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DateBizName.java
new file mode 100644
index 000000000..f44817098
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DateBizName.java
@@ -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
+ *
+ * 根据时间重置bizname
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+public class DateBizName implements BizName {
+ private String bizName;
+
+ /**
+ * 生成空间名称
+ */
+ @Override
+ public String create() {
+ return bizName + DateUtil.today();
+ }
+}
\ No newline at end of file
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DefaultBizName.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DefaultBizName.java
new file mode 100644
index 000000000..c77b11555
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DefaultBizName.java
@@ -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;
+ }
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/redis/RedisSeqRangeMgr.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/redis/RedisSeqRangeMgr.java
new file mode 100755
index 000000000..e69cbe262
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/redis/RedisSeqRangeMgr.java
@@ -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;
+ }
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/RangeSequence.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/RangeSequence.java
new file mode 100755
index 000000000..7eaa28d6f
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/RangeSequence.java
@@ -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);
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/Sequence.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/Sequence.java
new file mode 100755
index 000000000..6dc7a8b1e
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/Sequence.java
@@ -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;
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/DefaultRangeSequence.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/DefaultRangeSequence.java
new file mode 100755
index 000000000..7ef109b5e
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/DefaultRangeSequence.java
@@ -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.
+ *
+ * 根据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;
+ }
+
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/SnowflakeSequence.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/SnowflakeSequence.java
new file mode 100755
index 000000000..9aedfbecc
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/SnowflakeSequence.java
@@ -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位。以下是每位的具体含义。
+ *
+ * snowflake的结构如下(每部分用-分开):
+ *
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
+ *
+ * (1)第一位为未使用
+ * (2)接下来的41位为毫秒级时间(41位的长度可以使用69年)
+ * (3)然后是5位datacenterId
+ * (4)5位workerId
+ * (5)最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)
+ *
+ * 一共加起来刚好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());
+ }
+}
diff --git a/pigx-common/pigx-common-sequence/src/main/resources/META-INF/spring.factories b/pigx-common/pigx-common-sequence/src/main/resources/META-INF/spring.factories
new file mode 100755
index 000000000..80446dc9b
--- /dev/null
+++ b/pigx-common/pigx-common-sequence/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.pig4cloud.common.sequence.SequenceAutoConfiguration
\ No newline at end of file
diff --git a/pigx-common/pigx-common-swagger/pom.xml b/pigx-common/pigx-common-swagger/pom.xml
index b59063b81..fa75bff61 100644
--- a/pigx-common/pigx-common-swagger/pom.xml
+++ b/pigx-common/pigx-common-swagger/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-swagger
diff --git a/pigx-common/pigx-common-transaction/pom.xml b/pigx-common/pigx-common-transaction/pom.xml
index b165ce19d..43ecb65ac 100644
--- a/pigx-common/pigx-common-transaction/pom.xml
+++ b/pigx-common/pigx-common-transaction/pom.xml
@@ -5,7 +5,7 @@
com.pig4cloud
pigx-common
- 3.0.0
+ 3.2
pigx-common-transaction
diff --git a/pigx-common/pom.xml b/pigx-common/pom.xml
index 99e723dfc..1227d7038 100644
--- a/pigx-common/pom.xml
+++ b/pigx-common/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx
- 3.0.0
+ 3.2
pigx-common
@@ -42,6 +42,7 @@
pigx-common-minio
pigx-common-security
pigx-common-swagger
+ pigx-common-sequence
pigx-common-transaction
pigx-common-datasource
diff --git a/pigx-gateway/pom.xml b/pigx-gateway/pom.xml
index ba9c39a12..af095c4c5 100644
--- a/pigx-gateway/pom.xml
+++ b/pigx-gateway/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx
- 3.0.0
+ 3.2
pigx-gateway
diff --git a/pigx-register/pom.xml b/pigx-register/pom.xml
index 323247d1a..465fbc118 100755
--- a/pigx-register/pom.xml
+++ b/pigx-register/pom.xml
@@ -18,7 +18,7 @@
com.pig4cloud
pigx
- 3.0.0
+ 3.2
pigx-register
diff --git a/pigx-upms/pigx-upms-api/pom.xml b/pigx-upms/pigx-upms-api/pom.xml
index df9f82ff2..e942e30a3 100644
--- a/pigx-upms/pigx-upms-api/pom.xml
+++ b/pigx-upms/pigx-upms-api/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-upms
- 3.0.0
+ 3.2
pigx-upms-api
diff --git a/pigx-upms/pigx-upms-biz/pom.xml b/pigx-upms/pigx-upms-biz/pom.xml
index bee4afd42..973e768ef 100644
--- a/pigx-upms/pigx-upms-biz/pom.xml
+++ b/pigx-upms/pigx-upms-biz/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-upms
- 3.0.0
+ 3.2
pigx-upms-biz
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/FileController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/FileController.java
index 8e69d5642..bbe36559f 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/FileController.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/FileController.java
@@ -35,6 +35,8 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
+;
+
/**
* @author lengleng
* @date 2018-12-30
diff --git a/pigx-upms/pom.xml b/pigx-upms/pom.xml
index d2b2c35d0..216c94d24 100644
--- a/pigx-upms/pom.xml
+++ b/pigx-upms/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx
- 3.0.0
+ 3.2
pigx-upms
diff --git a/pigx-visual/pigx-activiti/pom.xml b/pigx-visual/pigx-activiti/pom.xml
index 139eace01..04dd6a0b5 100644
--- a/pigx-visual/pigx-activiti/pom.xml
+++ b/pigx-visual/pigx-activiti/pom.xml
@@ -23,7 +23,7 @@
com.pig4cloud
pigx-visual
- 3.0.0
+ 3.2
pigx-activiti
diff --git a/pigx-visual/pigx-codegen/pom.xml b/pigx-visual/pigx-codegen/pom.xml
index c2e9352f7..1376a0199 100755
--- a/pigx-visual/pigx-codegen/pom.xml
+++ b/pigx-visual/pigx-codegen/pom.xml
@@ -6,7 +6,7 @@
com.pig4cloud
pigx-visual
- 3.0.0
+ 3.2
pigx-codegen
diff --git a/pigx-visual/pigx-daemon-elastic-job/pom.xml b/pigx-visual/pigx-daemon-elastic-job/pom.xml
index 800a91a8e..fcbd9fd20 100644
--- a/pigx-visual/pigx-daemon-elastic-job/pom.xml
+++ b/pigx-visual/pigx-daemon-elastic-job/pom.xml
@@ -23,7 +23,7 @@
com.pig4cloud
pigx-visual
- 3.0.0
+ 3.2
pigx-daemon-elastic-job
diff --git a/pigx-visual/pigx-daemon-quartz/pom.xml b/pigx-visual/pigx-daemon-quartz/pom.xml
index 1f1897e60..33ac0e143 100644
--- a/pigx-visual/pigx-daemon-quartz/pom.xml
+++ b/pigx-visual/pigx-daemon-quartz/pom.xml
@@ -5,7 +5,7 @@
com.pig4cloud
pigx-visual
- 3.0.0
+ 3.2
4.0.0
diff --git a/pigx-visual/pigx-monitor/pom.xml b/pigx-visual/pigx-monitor/pom.xml
index 03c1e4970..ba5ad66c2 100644
--- a/pigx-visual/pigx-monitor/pom.xml
+++ b/pigx-visual/pigx-monitor/pom.xml
@@ -24,7 +24,7 @@
com.pig4cloud
pigx-visual
- 3.0.0
+ 3.2
pigx-monitor
@@ -36,7 +36,7 @@
com.pig4cloud
pigx-common-core
- 3.0.0
+ 3.2
org.springframework.boot
diff --git a/pigx-visual/pigx-mp-manager/pom.xml b/pigx-visual/pigx-mp-manager/pom.xml
index f40bc2cc0..a736a505a 100755
--- a/pigx-visual/pigx-mp-manager/pom.xml
+++ b/pigx-visual/pigx-mp-manager/pom.xml
@@ -6,7 +6,7 @@
com.pig4cloud
pigx-visual
- 3.0.0
+ 3.2
pigx-mp-manager
diff --git a/pigx-visual/pigx-pay/Dockerfile b/pigx-visual/pigx-pay/Dockerfile
new file mode 100644
index 000000000..9385d4860
--- /dev/null
+++ b/pigx-visual/pigx-pay/Dockerfile
@@ -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
diff --git a/pigx-visual/pigx-pay/pom.xml b/pigx-visual/pigx-pay/pom.xml
new file mode 100755
index 000000000..01cda2a9d
--- /dev/null
+++ b/pigx-visual/pigx-pay/pom.xml
@@ -0,0 +1,100 @@
+
+
+ 4.0.0
+
+
+ com.pig4cloud
+ pigx-visual
+ 3.2
+
+
+ pigx-pay
+ jar
+
+ 支付系统
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+
+
+
+ com.pig4cloud
+ pigx-common-data
+
+
+ com.pig4cloud
+ pigx-common-sequence
+
+
+
+ com.pig4cloud
+ pigx-common-swagger
+
+
+
+ com.pig4cloud
+ pigx-common-security
+
+
+ com.pig4cloud
+ pigx-common-log
+
+
+
+ com.github.javen205
+ IJPay
+ 1.2.0
+
+
+ com.alipay.sdk
+ alipay-sdk-java
+ 3.0.52.ALL
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ com.spotify
+ docker-maven-plugin
+
+
+
+
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java
new file mode 100755
index 000000000..8c264f846
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java
@@ -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
+ *
+ * 支付模块
+ */
+@EnablePigxSwagger2
+@SpringCloudApplication
+@EnablePigxFeignClients
+@EnablePigxResourceServer
+public class PigxPayApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PigxPayApplication.class, args);
+ }
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java
new file mode 100644
index 000000000..94d004024
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java
@@ -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
+ *
+ * 支付参数初始化
+ */
+@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);
+ }
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java
new file mode 100644
index 000000000..fed0964f2
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java
@@ -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
+ *
+ * 设置发号器生成规则
+ */
+@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();
+ }
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java
new file mode 100755
index 000000000..7695ec207
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java
@@ -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));
+ }
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckBatchController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckBatchController.java
new file mode 100755
index 000000000..6dad14c97
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckBatchController.java
@@ -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));
+ }
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckMistakeController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckMistakeController.java
new file mode 100755
index 000000000..080842960
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckMistakeController.java
@@ -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));
+ }
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java
new file mode 100755
index 000000000..c392bb301
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java
@@ -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);
+ }
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java
new file mode 100755
index 000000000..d2ae2f1fa
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java
@@ -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));
+ }
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java
new file mode 100755
index 000000000..43e963634
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java
@@ -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));
+ }
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java
new file mode 100755
index 000000000..a51cdf3fd
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java
@@ -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));
+ }
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java
new file mode 100755
index 000000000..323021f3f
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java
@@ -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 {
+ 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;
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckBatch.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckBatch.java
new file mode 100755
index 000000000..5763bccf9
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckBatch.java
@@ -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 {
+ 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;
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckMistake.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckMistake.java
new file mode 100755
index 000000000..d3c62c7b8
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckMistake.java
@@ -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 {
+ 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;
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java
new file mode 100755
index 000000000..947a5ba82
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java
@@ -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 {
+ 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;
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java
new file mode 100755
index 000000000..f932965a8
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java
@@ -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 {
+ 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;
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java
new file mode 100755
index 000000000..cae0c0ec3
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java
@@ -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 {
+ 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;
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java
new file mode 100755
index 000000000..079c39696
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java
@@ -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 {
+ 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;
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AbstractPayOrderHandler.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AbstractPayOrderHandler.java
new file mode 100644
index 000000000..b5cbc30e8
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AbstractPayOrderHandler.java
@@ -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);
+ }
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AlipayWapPayOrderHandler.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AlipayWapPayOrderHandler.java
new file mode 100644
index 000000000..de93897fd
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AlipayWapPayOrderHandler.java
@@ -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
+ *
+ * 支付宝手机支付
+ */
+@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);
+ }
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java
new file mode 100644
index 000000000..6784b0df7
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java
@@ -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
+ *
+ * 支付业务
+ */
+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);
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java
new file mode 100755
index 000000000..50a1889f2
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckBatchMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckBatchMapper.java
new file mode 100755
index 000000000..9437cfcda
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckBatchMapper.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckMistakeMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckMistakeMapper.java
new file mode 100755
index 000000000..63f4268aa
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckMistakeMapper.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java
new file mode 100755
index 000000000..fa337a084
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java
new file mode 100755
index 000000000..e064f34fa
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java
new file mode 100755
index 000000000..1030a66cc
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java
new file mode 100755
index 000000000..5e676eca6
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java
new file mode 100755
index 000000000..32a94c904
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java
@@ -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 {
+
+ /**
+ * 新增支付渠道
+ *
+ * @param payChannel 支付渠道
+ * @return
+ */
+ Boolean saveChannel(PayChannel payChannel);
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckBatchService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckBatchService.java
new file mode 100755
index 000000000..88c84f9c8
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckBatchService.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckMistakeService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckMistakeService.java
new file mode 100755
index 000000000..77f9784ff
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckMistakeService.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java
new file mode 100755
index 000000000..97883e30b
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java
@@ -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 {
+
+ /**
+ * 购买商品
+ *
+ * @param amount
+ * @return
+ */
+ R buy(Long amount);
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java
new file mode 100755
index 000000000..6daab7bc9
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java
new file mode 100755
index 000000000..e19fe66ee
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java
new file mode 100755
index 000000000..eab0776a2
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java
@@ -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 {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java
new file mode 100755
index 000000000..c29ccbd34
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java
@@ -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 implements PayChannelService {
+ private final Sequence channelSequence;
+
+ /**
+ * 新增支付渠道
+ *
+ * @param payChannel 支付渠道
+ * @return
+ */
+ @Override
+ public Boolean saveChannel(PayChannel payChannel) {
+ payChannel.setMchId(channelSequence.nextNo());
+ return save(payChannel);
+ }
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckBatchServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckBatchServiceImpl.java
new file mode 100755
index 000000000..e11a8c67d
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckBatchServiceImpl.java
@@ -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 implements PayCheckBatchService {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckMistakeServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckMistakeServiceImpl.java
new file mode 100755
index 000000000..4110281ff
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckMistakeServiceImpl.java
@@ -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 implements PayCheckMistakeService {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java
new file mode 100755
index 000000000..2ed7de8a8
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java
@@ -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 implements PayGoodsOrderService {
+ private final PayTradeOrderService tradeOrderService;
+ private static final String WX = "MicroMessenger";
+ private final HttpServletRequest request;
+ private final HttpServletResponse response;
+ private final Sequence paySequence;
+
+
+ /**
+ * 购买商品
+ *
+ * 1、 新增商品订单
+ * 2、 根据UA 去下单
+ * 3、构建支付订单
+ *
+ * @param amount
+ * @return
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public R buy(Long amount) {
+ }
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java
new file mode 100755
index 000000000..75cc6e05e
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java
@@ -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 implements PayNotifyRecordService {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java
new file mode 100755
index 000000000..0c580cedc
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java
@@ -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 implements PayRefundOrderService {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java
new file mode 100755
index 000000000..9b9042c79
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java
@@ -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 implements PayTradeOrderService {
+
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java
new file mode 100644
index 000000000..1f4967bb4
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java
@@ -0,0 +1,44 @@
+package com.pig4cloud.pigx.pay.utils;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author lengleng
+ * @date 2019-05-30
+ *
+ * 订单状态
+ */
+@Getter
+@AllArgsConstructor
+public enum OrderStatusEnum {
+ /**
+ * 订单初始 下单
+ */
+ INIT(0, "下单"),
+
+ /**
+ * 订单支付成功
+ */
+ SUCCESS(1, "成功"),
+
+ /**
+ * 订单支付完成
+ */
+ COMPLETE(2, "完成"),
+
+ /**
+ * 订单支付失败
+ */
+ FAIL(-1, "失败");
+
+
+ /**
+ * 状态
+ */
+ private Integer status;
+ /**
+ * 描述
+ */
+ private String description;
+}
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java
new file mode 100644
index 000000000..35ecfdeb2
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java
@@ -0,0 +1,38 @@
+package com.pig4cloud.pigx.pay.utils;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author lengleng
+ * @date 2019-05-30
+ *
+ * 支付渠道名称
+ */
+@Getter
+@AllArgsConstructor
+public enum PayChannelNameEnum {
+ /**
+ * 支付宝
+ */
+ ALIPAY("alipay", "支付宝"),
+
+ /**
+ * 微信支付
+ */
+ WXPAY("wxpay", "微信支付"),
+
+ /**
+ * 微信服务商支付
+ */
+ WESUBPAY("wxsubpay", "微信服务商支付");
+
+ /**
+ * 名称
+ */
+ private String name;
+ /**
+ * 描述
+ */
+ private String description;
+}
diff --git a/pigx-visual/pigx-pay/src/main/resources/bootstrap.yml b/pigx-visual/pigx-pay/src/main/resources/bootstrap.yml
new file mode 100644
index 000000000..8d8a9b22c
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/resources/bootstrap.yml
@@ -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
\ No newline at end of file
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayChannelMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayChannelMapper.xml
new file mode 100755
index 000000000..c85d2d2a7
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayChannelMapper.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckBatchMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckBatchMapper.xml
new file mode 100755
index 000000000..7d15fa34a
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckBatchMapper.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckMistakeMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckMistakeMapper.xml
new file mode 100755
index 000000000..2ce7c6527
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckMistakeMapper.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayGoodsOrderMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayGoodsOrderMapper.xml
new file mode 100755
index 000000000..062bf059f
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayGoodsOrderMapper.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayNotifyRecordMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayNotifyRecordMapper.xml
new file mode 100755
index 000000000..b12d1538e
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayNotifyRecordMapper.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayRefundOrderMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayRefundOrderMapper.xml
new file mode 100755
index 000000000..f038ae10e
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayRefundOrderMapper.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayTradeOrderMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayTradeOrderMapper.xml
new file mode 100755
index 000000000..cd68a0852
--- /dev/null
+++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayTradeOrderMapper.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pigx-seata-server/pom.xml b/pigx-visual/pigx-seata-server/pom.xml
deleted file mode 100755
index 1d9c33897..000000000
--- a/pigx-visual/pigx-seata-server/pom.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
- com.pig4cloud
- pigx-visual
- 3.0.0
-
-
- 4.0.0
- pigx-seata-server
- jar
- pigx-seata-server
-
-
-
- io.seata
- seata-core
- 0.5.2
-
-
- io.seata
- seata-config-all
- 0.5.2
-
-
- io.seata
- seata-discovery-all
- 0.5.2
-
-
-
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java
deleted file mode 100755
index d6655196e..000000000
--- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright 1999-2019 Seata.io Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.server;
-
-import io.seata.common.XID;
-import io.seata.core.exception.AbstractExceptionHandler;
-import io.seata.core.exception.TransactionException;
-import io.seata.core.model.GlobalStatus;
-import io.seata.core.protocol.transaction.BranchRegisterRequest;
-import io.seata.core.protocol.transaction.BranchRegisterResponse;
-import io.seata.core.protocol.transaction.BranchReportRequest;
-import io.seata.core.protocol.transaction.BranchReportResponse;
-import io.seata.core.protocol.transaction.GlobalBeginRequest;
-import io.seata.core.protocol.transaction.GlobalBeginResponse;
-import io.seata.core.protocol.transaction.GlobalCommitRequest;
-import io.seata.core.protocol.transaction.GlobalCommitResponse;
-import io.seata.core.protocol.transaction.GlobalLockQueryRequest;
-import io.seata.core.protocol.transaction.GlobalLockQueryResponse;
-import io.seata.core.protocol.transaction.GlobalRollbackRequest;
-import io.seata.core.protocol.transaction.GlobalRollbackResponse;
-import io.seata.core.protocol.transaction.GlobalStatusRequest;
-import io.seata.core.protocol.transaction.GlobalStatusResponse;
-import io.seata.core.protocol.transaction.TCInboundHandler;
-import io.seata.core.rpc.RpcContext;
-import io.seata.server.session.GlobalSession;
-import io.seata.server.session.SessionHolder;
-
-/**
- * The type Abstract tc inbound handler.
- *
- * @author sharajava
- */
-public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler implements TCInboundHandler {
-
- @Override
- public GlobalBeginResponse handle(GlobalBeginRequest request, final RpcContext rpcContext) {
- GlobalBeginResponse response = new GlobalBeginResponse();
- exceptionHandleTemplate(new AbstractCallback() {
- @Override
- public void execute(GlobalBeginRequest request, GlobalBeginResponse response) throws TransactionException {
- doGlobalBegin(request, response, rpcContext);
- }
- }, request, response);
- return response;
- }
-
- /**
- * Do global begin.
- *
- * @param request the request
- * @param response the response
- * @param rpcContext the rpc context
- * @throws TransactionException the transaction exception
- */
- protected abstract void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response,
- RpcContext rpcContext) throws TransactionException;
-
- @Override
- public GlobalCommitResponse handle(GlobalCommitRequest request, final RpcContext rpcContext) {
- GlobalCommitResponse response = new GlobalCommitResponse();
- exceptionHandleTemplate(new AbstractCallback() {
- @Override
- public void execute(GlobalCommitRequest request, GlobalCommitResponse response)
- throws TransactionException {
- doGlobalCommit(request, response, rpcContext);
- }
- }, request, response);
- return response;
- }
-
- /**
- * Do global commit.
- *
- * @param request the request
- * @param response the response
- * @param rpcContext the rpc context
- * @throws TransactionException the transaction exception
- */
- protected abstract void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response,
- RpcContext rpcContext) throws TransactionException;
-
- @Override
- public GlobalRollbackResponse handle(GlobalRollbackRequest request, final RpcContext rpcContext) {
- GlobalRollbackResponse response = new GlobalRollbackResponse();
- exceptionHandleTemplate(new AbstractCallback() {
- @Override
- public void execute(GlobalRollbackRequest request, GlobalRollbackResponse response)
- throws TransactionException {
- doGlobalRollback(request, response, rpcContext);
- }
-
- @Override
- public void onTransactionException(GlobalRollbackRequest request, GlobalRollbackResponse response,
- TransactionException tex) {
- super.onTransactionException(request, response, tex);
- GlobalSession globalSession = SessionHolder.findGlobalSession(
- XID.getTransactionId(request.getXid()));
- if (globalSession != null) {
- response.setGlobalStatus(globalSession.getStatus());
- } else {
- response.setGlobalStatus(GlobalStatus.Finished);
- }
- }
-
- @Override
- public void onException(GlobalRollbackRequest request, GlobalRollbackResponse response, Exception rex) {
- super.onException(request, response, rex);
- GlobalSession globalSession = SessionHolder.findGlobalSession(
- XID.getTransactionId(request.getXid()));
- if (globalSession != null) {
- response.setGlobalStatus(globalSession.getStatus());
- } else {
- response.setGlobalStatus(GlobalStatus.Finished);
- }
- }
- }, request, response);
- return response;
- }
-
- /**
- * Do global rollback.
- *
- * @param request the request
- * @param response the response
- * @param rpcContext the rpc context
- * @throws TransactionException the transaction exception
- */
- protected abstract void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response,
- RpcContext rpcContext) throws TransactionException;
-
- @Override
- public BranchRegisterResponse handle(BranchRegisterRequest request, final RpcContext rpcContext) {
- BranchRegisterResponse response = new BranchRegisterResponse();
- exceptionHandleTemplate(new AbstractCallback() {
- @Override
- public void execute(BranchRegisterRequest request, BranchRegisterResponse response)
- throws TransactionException {
- doBranchRegister(request, response, rpcContext);
- }
- }, request, response);
- return response;
- }
-
- /**
- * Do branch register.
- *
- * @param request the request
- * @param response the response
- * @param rpcContext the rpc context
- * @throws TransactionException the transaction exception
- */
- protected abstract void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response,
- RpcContext rpcContext) throws TransactionException;
-
- @Override
- public BranchReportResponse handle(BranchReportRequest request, final RpcContext rpcContext) {
- BranchReportResponse response = new BranchReportResponse();
- exceptionHandleTemplate(new AbstractCallback() {
- @Override
- public void execute(BranchReportRequest request, BranchReportResponse response)
- throws TransactionException {
- doBranchReport(request, response, rpcContext);
- }
- }, request, response);
- return response;
- }
-
- /**
- * Do branch report.
- *
- * @param request the request
- * @param rpcContext the rpc context
- * @throws TransactionException the transaction exception
- */
- protected abstract void doBranchReport(BranchReportRequest request, BranchReportResponse response,
- RpcContext rpcContext)
- throws TransactionException;
-
- @Override
- public GlobalLockQueryResponse handle(GlobalLockQueryRequest request, final RpcContext rpcContext) {
- GlobalLockQueryResponse response = new GlobalLockQueryResponse();
- exceptionHandleTemplate(new AbstractCallback() {
- @Override
- public void execute(GlobalLockQueryRequest request, GlobalLockQueryResponse response)
- throws TransactionException {
- doLockCheck(request, response, rpcContext);
- }
- }, request, response);
- return response;
- }
-
- /**
- * Do lock check.
- *
- * @param request the request
- * @param response the response
- * @param rpcContext the rpc context
- * @throws TransactionException the transaction exception
- */
- protected abstract void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response,
- RpcContext rpcContext) throws TransactionException;
-
- @Override
- public GlobalStatusResponse handle(GlobalStatusRequest request, final RpcContext rpcContext) {
- GlobalStatusResponse response = new GlobalStatusResponse();
- exceptionHandleTemplate(new AbstractCallback() {
- @Override
- public void execute(GlobalStatusRequest request, GlobalStatusResponse response)
- throws TransactionException {
- doGlobalStatus(request, response, rpcContext);
- }
- }, request, response);
- return response;
- }
-
- /**
- * Do global status.
- *
- * @param request the request
- * @param response the response
- * @param rpcContext the rpc context
- * @throws TransactionException the transaction exception
- */
- protected abstract void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response,
- RpcContext rpcContext) throws TransactionException;
-
-}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java
deleted file mode 100755
index 43df651ee..000000000
--- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 1999-2019 Seata.io Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.server;
-
-import io.seata.common.XID;
-import io.seata.common.thread.NamedThreadFactory;
-import io.seata.common.util.NetUtil;
-import io.seata.core.rpc.netty.RpcServer;
-import io.seata.core.rpc.netty.ShutdownHook;
-import io.seata.server.coordinator.DefaultCoordinator;
-import io.seata.server.session.SessionHolder;
-
-import java.io.IOException;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- * The type Server.
- *
- * @author jimin.jm @alibaba-inc.com
- */
-public class Server {
-
- private static final int MIN_SERVER_POOL_SIZE = 10;
- private static final int MAX_SERVER_POOL_SIZE = 50;
- private static final int MAX_TASK_QUEUE_SIZE = 2000;
- private static final int KEEP_ALIVE_TIME = 50;
- private static final int SERVER_DEFAULT_PORT = 8091;
- private static final ThreadPoolExecutor WORKING_THREADS = new ThreadPoolExecutor(MIN_SERVER_POOL_SIZE,
- MAX_SERVER_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
- new LinkedBlockingQueue(MAX_TASK_QUEUE_SIZE),
- new NamedThreadFactory("ServerHandlerThread", MAX_SERVER_POOL_SIZE), new ThreadPoolExecutor.CallerRunsPolicy());
-
- /**
- * The entry point of application.
- *
- * @param args the input arguments
- * @throws IOException the io exception
- */
- public static void main(String[] args) throws IOException {
- RpcServer rpcServer = new RpcServer(WORKING_THREADS);
-
- rpcServer.setListenPort(SERVER_DEFAULT_PORT);
-
- //log store mode : file、db
- String storeMode = "file";
-
- UUIDGenerator.init(1);
- SessionHolder.init(storeMode);
-
- DefaultCoordinator coordinator = new DefaultCoordinator(rpcServer);
- coordinator.init();
- rpcServer.setHandler(coordinator);
- // register ShutdownHook
- ShutdownHook.getInstance().addDisposable(coordinator);
-
- XID.setIpAddress(NetUtil.getLocalIp());
- XID.setPort(rpcServer.getListenPort());
-
- rpcServer.init();
-
- System.exit(0);
- }
-}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java
deleted file mode 100755
index efc55e555..000000000
--- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 1999-2019 Seata.io Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.server;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.concurrent.atomic.AtomicLong;
-
-import io.seata.common.exception.ShouldNeverHappenException;
-
-/**
- * The type Uuid generator.
- *
- * @author sharajava
- */
-public class UUIDGenerator {
-
- private static final AtomicLong UUID = new AtomicLong(1000);
- private static int serverNodeId = 1;
- private static final long UUID_INTERNAL = 2000000000;
-
- /**
- * Generate uuid long.
- *
- * @return the long
- */
- public static long generateUUID() {
- long id = UUID.incrementAndGet();
- if (id >= UUID_INTERNAL * (serverNodeId + 1)) {
- synchronized (UUID) {
- if (UUID.get() >= id) {
- id -= UUID_INTERNAL;
- UUID.set(id);
- }
- }
- }
- return id;
- }
-
- /**
- * Gets current uuid.
- *
- * @return the current uuid
- */
- public static long getCurrentUUID() {
- return UUID.get();
- }
-
- /**
- * Sets uuid.
- *
- * @param expect the expect
- * @param update the update
- * @return the uuid
- */
- public static boolean setUUID(long expect, long update) {
- return UUID.compareAndSet(expect, update);
-
- }
-
- /**
- * Init.
- *
- * @param serverNodeId the server node id
- */
- public static void init(int serverNodeId) {
- try {
- UUIDGenerator.serverNodeId = serverNodeId;
- UUID.set(UUID_INTERNAL * serverNodeId);
- SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
- Calendar cal = Calendar.getInstance();
- Date date = format.parse("2019-01-01");
- cal.setTime(date);
- long base = cal.getTimeInMillis();
- long current = System.currentTimeMillis();
- UUID.addAndGet((current - base) / 1000);
- } catch (ParseException e) {
- throw new ShouldNeverHappenException(e);
- }
- }
-}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java
deleted file mode 100755
index 7d34dfee1..000000000
--- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 1999-2019 Seata.io Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.server.coordinator;
-
-import io.seata.core.exception.TransactionException;
-import io.seata.core.model.ResourceManagerInbound;
-import io.seata.core.model.ResourceManagerOutbound;
-import io.seata.core.model.TransactionManager;
-import io.seata.server.session.GlobalSession;
-
-/**
- * The interface Core.
- *
- * @author sharajava
- */
-public interface Core extends TransactionManager, ResourceManagerOutbound {
-
- /**
- * Sets resource manager inbound.
- *
- * @param resourceManagerInbound the resource manager inbound
- */
- void setResourceManagerInbound(ResourceManagerInbound resourceManagerInbound);
-
- /**
- * Do global commit.
- *
- * @param globalSession the global session
- * @param retrying the retrying
- * @throws TransactionException the transaction exception
- */
- void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException;
-
- /**
- * Do global rollback.
- *
- * @param globalSession the global session
- * @param retrying the retrying
- * @throws TransactionException the transaction exception
- */
- void doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException;
-}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java
deleted file mode 100755
index 19e09f70e..000000000
--- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 1999-2019 Seata.io Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.server.coordinator;
-
-/**
- * The type Core factory.
- *
- * @author sharajava
- */
-public class CoreFactory {
-
- private static class SingletonHolder {
- private static Core INSTANCE = new DefaultCore();
- }
-
- /**
- * Get core.
- *
- * @return the core
- */
- public static final Core get() {
- return SingletonHolder.INSTANCE;
- }
-
- /**
- * Just for test mocking
- *
- * @param core the core
- */
- public static void set(Core core) {
- SingletonHolder.INSTANCE = core;
- }
-}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java
deleted file mode 100755
index 024f741a9..000000000
--- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright 1999-2019 Seata.io Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.server.coordinator;
-
-import io.seata.common.XID;
-import io.seata.common.thread.NamedThreadFactory;
-import io.seata.core.exception.TransactionException;
-import io.seata.core.model.BranchStatus;
-import io.seata.core.model.BranchType;
-import io.seata.core.model.GlobalStatus;
-import io.seata.core.model.ResourceManagerInbound;
-import io.seata.core.protocol.AbstractMessage;
-import io.seata.core.protocol.AbstractResultMessage;
-import io.seata.core.protocol.transaction.*;
-import io.seata.core.rpc.Disposable;
-import io.seata.core.rpc.RpcContext;
-import io.seata.core.rpc.ServerMessageSender;
-import io.seata.core.rpc.TransactionMessageHandler;
-import io.seata.core.rpc.netty.RpcServer;
-import io.seata.server.AbstractTCInboundHandler;
-import io.seata.server.session.BranchSession;
-import io.seata.server.session.GlobalSession;
-import io.seata.server.session.SessionHolder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import static io.seata.core.exception.TransactionExceptionCode.FailedToSendBranchCommitRequest;
-import static io.seata.core.exception.TransactionExceptionCode.FailedToSendBranchRollbackRequest;
-
-/**
- * The type Default coordinator.
- *
- * @author sharajava
- */
-public class DefaultCoordinator extends AbstractTCInboundHandler
- implements TransactionMessageHandler, ResourceManagerInbound, Disposable {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCoordinator.class);
-
- private static final int TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS = 5000;
-
- private ServerMessageSender messageSender;
-
- private Core core = CoreFactory.get();
-
- /**
- * Instantiates a new Default coordinator.
- *
- * @param messageSender the message sender
- */
- public DefaultCoordinator(ServerMessageSender messageSender) {
- this.messageSender = messageSender;
- core.setResourceManagerInbound(this);
- }
-
- @Override
- protected void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response, RpcContext rpcContext)
- throws TransactionException {
- response.setXid(core.begin(rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(),
- request.getTransactionName(), request.getTimeout()));
- }
-
- @Override
- protected void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, RpcContext rpcContext)
- throws TransactionException {
- response.setGlobalStatus(core.commit(request.getXid()));
-
- }
-
- @Override
- protected void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response,
- RpcContext rpcContext) throws TransactionException {
- response.setGlobalStatus(core.rollback(request.getXid()));
-
- }
-
- @Override
- protected void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response, RpcContext rpcContext)
- throws TransactionException {
- response.setGlobalStatus(core.getStatus(request.getXid()));
- }
-
- @Override
- protected void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response,
- RpcContext rpcContext) throws TransactionException {
- response.setBranchId(
- core.branchRegister(request.getBranchType(), request.getResourceId(), rpcContext.getClientId(),
- request.getXid(), request.getApplicationData(), request.getLockKey()));
-
- }
-
- @Override
- protected void doBranchReport(BranchReportRequest request, BranchReportResponse response, RpcContext rpcContext)
- throws TransactionException {
- core.branchReport(request.getBranchType(), request.getXid(), request.getBranchId(),
- request.getStatus(),
- request.getApplicationData());
-
- }
-
- @Override
- protected void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response, RpcContext rpcContext)
- throws TransactionException {
- response.setLockable(core.lockQuery(request.getBranchType(), request.getResourceId(),
- request.getXid(), request.getLockKey()));
- }
-
- @Override
- public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId,
- String applicationData)
- throws TransactionException {
- try {
- BranchCommitRequest request = new BranchCommitRequest();
- request.setXid(xid);
- request.setBranchId(branchId);
- request.setResourceId(resourceId);
- request.setApplicationData(applicationData);
- request.setBranchType(branchType);
-
- GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
- if(globalSession == null){
- return BranchStatus.PhaseTwo_Committed;
- }
- BranchSession branchSession = globalSession.getBranch(branchId);
-
- BranchCommitResponse response = (BranchCommitResponse)messageSender.sendSyncRequest(resourceId,
- branchSession.getClientId(), request);
- return response.getBranchStatus();
- } catch (IOException e) {
- throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e);
- } catch (TimeoutException e) {
- throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e);
- }
- }
-
- @Override
- public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId,
- String applicationData)
- throws TransactionException {
- try {
- BranchRollbackRequest
- request = new BranchRollbackRequest();
- request.setXid(xid);
- request.setBranchId(branchId);
- request.setResourceId(resourceId);
- request.setApplicationData(applicationData);
- request.setBranchType(branchType);
-
- GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
- if(globalSession == null){
- return BranchStatus.PhaseTwo_Rollbacked;
- }
- BranchSession branchSession = globalSession.getBranch(branchId);
-
- BranchRollbackResponse response = (BranchRollbackResponse)messageSender.sendSyncRequest(resourceId,
- branchSession.getClientId(), request);
- return response.getBranchStatus();
- } catch (IOException e) {
- throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e);
- } catch (TimeoutException e) {
- throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e);
- }
- }
-
- private void timeoutCheck() throws TransactionException {
- Collection allSessions = SessionHolder.getRootSessionManager().allSessions();
- if (allSessions.size() > 0 && LOGGER.isDebugEnabled()) {
- LOGGER.debug("Transaction Timeout Check Begin: " + allSessions.size());
- }
- for (GlobalSession globalSession : allSessions) {
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug(globalSession.getTransactionId() + " " + globalSession.getStatus() + " " +
- globalSession.getBeginTime() + " " + globalSession.getTimeout());
- }
- boolean shouldTimeout = globalSession.lockAndExcute(() -> {
- if (globalSession.getStatus() != GlobalStatus.Begin || !globalSession.isTimeout()) {
- return false;
- }
- globalSession.close();
- globalSession.changeStatus(GlobalStatus.TimeoutRollbacking);
- return true;
- });
- if (!shouldTimeout) {
- continue;
- }
- LOGGER.info(
- "Global transaction[" + globalSession.getTransactionId() + "] is timeout and will be rolled back.");
-
- globalSession.addSessionLifecycleListener(SessionHolder.getRetryRollbackingSessionManager());
- SessionHolder.getRetryRollbackingSessionManager().addGlobalSession(globalSession);
-
- }
- if (allSessions.size() > 0 && LOGGER.isDebugEnabled()) {
- LOGGER.debug("Transaction Timeout Check End. ");
- }
-
- }
-
- private void handleRetryRollbacking() {
- Collection rollbackingSessions = SessionHolder.getRetryRollbackingSessionManager().allSessions();
- for (GlobalSession rollbackingSession : rollbackingSessions) {
- try {
- core.doGlobalRollback(rollbackingSession, true);
- } catch (TransactionException ex) {
- LOGGER.info("Failed to retry rollbacking [{}] {} {}",
- rollbackingSession.getTransactionId(), ex.getCode(), ex.getMessage());
- }
- }
- }
-
- private void handleRetryCommitting() {
- Collection committingSessions = SessionHolder.getRetryCommittingSessionManager().allSessions();
- for (GlobalSession committingSession : committingSessions) {
- try {
- core.doGlobalCommit(committingSession, true);
- } catch (TransactionException ex) {
- LOGGER.info("Failed to retry committing [{}] {} {}",
- committingSession.getTransactionId(), ex.getCode(), ex.getMessage());
- }
- }
- }
-
- private void handleAsyncCommitting() {
- Collection asyncCommittingSessions = SessionHolder.getAsyncCommittingSessionManager()
- .allSessions();
- for (GlobalSession asyncCommittingSession : asyncCommittingSessions) {
- try {
- core.doGlobalCommit(asyncCommittingSession, true);
- } catch (TransactionException ex) {
- LOGGER.info("Failed to async committing [{}] {} {}",
- asyncCommittingSession.getTransactionId(), ex.getCode(), ex.getMessage());
- }
- }
- }
-
- private ScheduledThreadPoolExecutor retryRollbacking = new ScheduledThreadPoolExecutor(1,
- new NamedThreadFactory("RetryRollbacking", 1));
-
- private ScheduledThreadPoolExecutor retryCommitting = new ScheduledThreadPoolExecutor(1,
- new NamedThreadFactory("RetryCommitting", 1));
-
- private ScheduledThreadPoolExecutor asyncCommitting = new ScheduledThreadPoolExecutor(1,
- new NamedThreadFactory("AsyncCommitting", 1));
-
- private ScheduledThreadPoolExecutor timeoutCheck = new ScheduledThreadPoolExecutor(1,
- new NamedThreadFactory("TxTimeoutCheck", 1));
-
- /**
- * Init.
- */
- public void init() {
- retryRollbacking.scheduleAtFixedRate(new Runnable() {
-
- @Override
- public void run() {
- try {
- handleRetryRollbacking();
- } catch (Exception e) {
- LOGGER.info("Exception retry rollbacking ... ", e);
- }
-
- }
- }, 0, 5, TimeUnit.MILLISECONDS);
-
- retryCommitting.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- handleRetryCommitting();
- } catch (Exception e) {
- LOGGER.info("Exception retry committing ... ", e);
- }
-
- }
- }, 0, 5, TimeUnit.MILLISECONDS);
-
- asyncCommitting.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- handleAsyncCommitting();
- } catch (Exception e) {
- LOGGER.info("Exception async committing ... ", e);
- }
-
- }
- }, 0, 10, TimeUnit.MILLISECONDS);
-
- timeoutCheck.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- timeoutCheck();
- } catch (Exception e) {
- LOGGER.info("Exception timeout checking ... ", e);
- }
-
- }
- }, 0, 2, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public AbstractResultMessage onRequest(AbstractMessage request, RpcContext context) {
- if (!(request instanceof AbstractTransactionRequestToTC)) {
- throw new IllegalArgumentException();
- }
- AbstractTransactionRequestToTC transactionRequest = (AbstractTransactionRequestToTC)request;
- transactionRequest.setTCInboundHandler(this);
-
- return transactionRequest.handle(context);
- }
-
- @Override
- public void onResponse(AbstractResultMessage response, RpcContext context) {
- if (!(response instanceof AbstractTransactionResponse)) {
- throw new IllegalArgumentException();
- }
-
- }
-
- @Override
- public void destroy() {
- // 1. first shutdown timed task
- retryRollbacking.shutdown();
- retryCommitting.shutdown();
- asyncCommitting.shutdown();
- timeoutCheck.shutdown();
- try {
- retryRollbacking.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
- retryCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
- asyncCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
- timeoutCheck.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException ingore) {
-
- }
- // 2. sencond close netty flow
- if (messageSender instanceof RpcServer){
- ((RpcServer) messageSender).destroy();
- }
- // 3. last destory SessionHolder
- SessionHolder.destory();
- }
-}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java
deleted file mode 100755
index 1ba36763f..000000000
--- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright 1999-2019 Seata.io Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.server.coordinator;
-
-import io.seata.common.XID;
-import io.seata.core.exception.TransactionException;
-import io.seata.core.exception.TransactionExceptionCode;
-import io.seata.core.model.BranchStatus;
-import io.seata.core.model.BranchType;
-import io.seata.core.model.GlobalStatus;
-import io.seata.core.model.ResourceManagerInbound;
-import io.seata.server.lock.LockManager;
-import io.seata.server.lock.LockManagerFactory;
-import io.seata.server.session.BranchSession;
-import io.seata.server.session.GlobalSession;
-import io.seata.server.session.SessionHelper;
-import io.seata.server.session.SessionHolder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static io.seata.core.exception.TransactionExceptionCode.BranchTransactionNotExist;
-import static io.seata.core.exception.TransactionExceptionCode.FailedToAddBranch;
-import static io.seata.core.exception.TransactionExceptionCode.GlobalTransactionNotActive;
-import static io.seata.core.exception.TransactionExceptionCode.GlobalTransactionStatusInvalid;
-import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflict;
-
-/**
- * The type Default core.
- *
- * @author sharajava
- */
-public class DefaultCore implements Core {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCore.class);
-
- private LockManager lockManager = LockManagerFactory.get();
-
- private ResourceManagerInbound resourceManagerInbound;
-
- @Override
- public void setResourceManagerInbound(ResourceManagerInbound resourceManagerInbound) {
- this.resourceManagerInbound = resourceManagerInbound;
- }
-
- @Override
- public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid,
- String applicationData, String lockKeys) throws TransactionException {
- GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid));
- return globalSession.lockAndExcute(() -> {
- if (!globalSession.isActive()) {
- throw new TransactionException(GlobalTransactionNotActive, "Current Status: " + globalSession.getStatus());
- }
- if (globalSession.getStatus() != GlobalStatus.Begin) {
- throw new TransactionException(GlobalTransactionStatusInvalid,
- globalSession.getStatus() + " while expecting " + GlobalStatus.Begin);
- }
- BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, branchType, resourceId,
- applicationData, lockKeys, clientId);
- if (!branchSession.lock()) {
- throw new TransactionException(LockKeyConflict);
- }
- try {
- globalSession.addBranch(branchSession);
- } catch (RuntimeException ex) {
- throw new TransactionException(FailedToAddBranch);
- }
- return branchSession.getBranchId();
- });
- }
-
- private GlobalSession assertGlobalSessionNotNull(long transactionId) throws TransactionException {
- GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId);
- if (globalSession == null) {
- throw new TransactionException(TransactionExceptionCode.GlobalTransactionNotExist, "" + transactionId + "");
- }
- return globalSession;
- }
-
-
- @Override
- public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status,
- String applicationData) throws TransactionException {
- GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid));
- BranchSession branchSession = globalSession.getBranch(branchId);
- if (branchSession == null) {
- throw new TransactionException(BranchTransactionNotExist);
- }
- globalSession.changeBranchStatus(branchSession, status);
- }
-
- @Override
- public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys)
- throws TransactionException {
- if (branchType == BranchType.AT) {
- return lockManager.isLockable(XID.getTransactionId(xid), resourceId, lockKeys);
- } else {
- return true;
- }
-
- }
-
- @Override
- public String begin(String applicationId, String transactionServiceGroup, String name, int timeout)
- throws TransactionException {
- GlobalSession session = GlobalSession.createGlobalSession(
- applicationId, transactionServiceGroup, name, timeout);
- session.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
-
- session.begin();
-
- return XID.generateXID(session.getTransactionId());
- }
-
- @Override
- public GlobalStatus commit(String xid) throws TransactionException {
- GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
- if (globalSession == null) {
- return GlobalStatus.Finished;
- }
- // just lock changeStatus
- boolean shouldCommit = globalSession.lockAndExcute(() -> {
- globalSession.closeAndClean(); // Highlight: Firstly, close the session, then no more branch can be registered.
- if (globalSession.getStatus() == GlobalStatus.Begin) {
- globalSession.changeStatus(GlobalStatus.Committing);
- return true;
- }
- return false;
- });
- if (!shouldCommit){
- return globalSession.getStatus();
- }
- if (globalSession.canBeCommittedAsync()) {
- asyncCommit(globalSession);
- return GlobalStatus.Committed;
- } else {
- doGlobalCommit(globalSession, false);
- }
- return globalSession.getStatus();
- }
-
- @Override
- public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException {
- for (BranchSession branchSession : globalSession.getSortedBranches()) {
- BranchStatus currentStatus = branchSession.getStatus();
- if (currentStatus == BranchStatus.PhaseOne_Failed) {
- globalSession.removeBranch(branchSession);
- continue;
- }
- try {
- BranchStatus branchStatus = resourceManagerInbound.branchCommit(branchSession.getBranchType(),
- XID.generateXID(branchSession.getTransactionId()), branchSession.getBranchId(),
- branchSession.getResourceId(), branchSession.getApplicationData());
-
- switch (branchStatus) {
- case PhaseTwo_Committed:
- globalSession.removeBranch(branchSession);
- continue;
- case PhaseTwo_CommitFailed_Unretryable:
- if (globalSession.canBeCommittedAsync()) {
- LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession);
- continue;
- } else {
- SessionHelper.endCommitFailed(globalSession);
- LOGGER.error("Finally, failed to commit global[{}] since branch[{}] commit failed",
- globalSession.getTransactionId(), branchSession.getBranchId());
- return;
- }
- default:
- if (!retrying) {
- queueToRetryCommit(globalSession);
- return;
- }
- if (globalSession.canBeCommittedAsync()) {
- LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession);
- continue;
- } else {
- LOGGER.error(
- "Failed to commit global[{}] since branch[{}] commit failed, will retry later.",
- globalSession.getTransactionId(), branchSession.getBranchId());
- return;
- }
-
- }
-
- } catch (Exception ex) {
- LOGGER.error("Exception committing branch {}", branchSession, ex);
- if (!retrying) {
- queueToRetryCommit(globalSession);
- throw new TransactionException(ex);
- }
-
- }
-
- }
- if (globalSession.hasBranch()) {
- LOGGER.info("Global[{}] committing is NOT done.", globalSession.getTransactionId());
- return;
- }
- SessionHelper.endCommitted(globalSession);
- LOGGER.info("Global[{}] committing is successfully done.", globalSession.getTransactionId());
- }
-
- private void asyncCommit(GlobalSession globalSession) throws TransactionException {
- globalSession.addSessionLifecycleListener(SessionHolder.getAsyncCommittingSessionManager());
- SessionHolder.getAsyncCommittingSessionManager().addGlobalSession(globalSession);
- globalSession.changeStatus(GlobalStatus.AsyncCommitting);
- }
-
- private void queueToRetryCommit(GlobalSession globalSession) throws TransactionException {
- globalSession.addSessionLifecycleListener(SessionHolder.getRetryCommittingSessionManager());
- SessionHolder.getRetryCommittingSessionManager().addGlobalSession(globalSession);
- globalSession.changeStatus(GlobalStatus.CommitRetrying);
- }
-
- private void queueToRetryRollback(GlobalSession globalSession) throws TransactionException {
- globalSession.addSessionLifecycleListener(SessionHolder.getRetryRollbackingSessionManager());
- SessionHolder.getRetryRollbackingSessionManager().addGlobalSession(globalSession);
- GlobalStatus currentStatus = globalSession.getStatus();
- if (SessionHelper.isTimeoutGlobalStatus(currentStatus)) {
- globalSession.changeStatus(GlobalStatus.TimeoutRollbackRetrying);
- } else {
- globalSession.changeStatus(GlobalStatus.RollbackRetrying);
- }
- }
-
- @Override
- public GlobalStatus rollback(String xid) throws TransactionException {
- GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
- if (globalSession == null) {
- return GlobalStatus.Finished;
- }
- // just lock changeStatus
- boolean shouldRollBack = globalSession.lockAndExcute(() -> {
- globalSession.close(); // Highlight: Firstly, close the session, then no more branch can be registered.
- if (globalSession.getStatus() == GlobalStatus.Begin) {
- globalSession.changeStatus(GlobalStatus.Rollbacking);
- return true;
- }
- return false;
- });
- if (!shouldRollBack){
- return globalSession.getStatus();
- }
-
- doGlobalRollback(globalSession, false);
- return globalSession.getStatus();
- }
-
- @Override
- public void doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException {
- for (BranchSession branchSession : globalSession.getReverseSortedBranches()) {
- BranchStatus currentBranchStatus = branchSession.getStatus();
- if (currentBranchStatus == BranchStatus.PhaseOne_Failed) {
- globalSession.removeBranch(branchSession);
- continue;
- }
- try {
- BranchStatus branchStatus = resourceManagerInbound.branchRollback(branchSession.getBranchType(),
- XID.generateXID(branchSession.getTransactionId()), branchSession.getBranchId(),
- branchSession.getResourceId(), branchSession.getApplicationData());
-
- switch (branchStatus) {
- case PhaseTwo_Rollbacked:
- globalSession.removeBranch(branchSession);
- LOGGER.error("Successfully rolled back branch " + branchSession);
- continue;
- case PhaseTwo_RollbackFailed_Unretryable:
- SessionHelper.endRollbackFailed(globalSession);
- LOGGER.error("Failed to rollback global[" + globalSession.getTransactionId() + "] since branch["
- + branchSession.getBranchId() + "] rollback failed");
- return;
- default:
- LOGGER.info("Failed to rollback branch " + branchSession);
- if (!retrying) {
- queueToRetryRollback(globalSession);
- }
- return;
-
- }
- } catch (Exception ex) {
- LOGGER.error("Exception rollbacking branch " + branchSession, ex);
- if (!retrying) {
- queueToRetryRollback(globalSession);
- }
- throw new TransactionException(ex);
- }
-
- }
- SessionHelper.endRollbacked(globalSession);
- }
-
- @Override
- public GlobalStatus getStatus(String xid) throws TransactionException {
- GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
- return globalSession.getStatus();
- }
-}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java
deleted file mode 100755
index a0c576c84..000000000
--- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 1999-2019 Seata.io Group.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.server.lock;
-
-import io.netty.util.internal.ConcurrentSet;
-import io.seata.common.exception.ShouldNeverHappenException;
-import io.seata.common.util.StringUtils;
-import io.seata.core.exception.TransactionException;
-import io.seata.server.session.BranchSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * The type Default lock manager.
- *
- * @author sharajava
- */
-public class DefaultLockManagerImpl implements LockManager {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLockManagerImpl.class);
-
- private static final int BUCKET_PER_TABLE = 128;
-
- private static final
- ConcurrentHashMap>>>
- LOCK_MAP = new ConcurrentHashMap>>>();
-
- @Override
- public boolean acquireLock(BranchSession branchSession) throws TransactionException {
- String resourceId = branchSession.getResourceId();
- long transactionId = branchSession.getTransactionId();
- ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId);
- if (dbLockMap == null) {
- LOCK_MAP.putIfAbsent(resourceId,
- new ConcurrentHashMap>>());
- dbLockMap = LOCK_MAP.get(resourceId);
- }
- ConcurrentHashMap