From 270c67fbdb118e939053f5b7178afb70019450ab Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Thu, 22 Dec 2022 13:12:37 +0800 Subject: [PATCH 01/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "\351\203\250\347\275\262.md" | 143 ++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 "\351\203\250\347\275\262.md" diff --git "a/\351\203\250\347\275\262.md" "b/\351\203\250\347\275\262.md" new file mode 100644 index 0000000..9b6d891 --- /dev/null +++ "b/\351\203\250\347\275\262.md" @@ -0,0 +1,143 @@ +## 一: 安装docker + +### 1. 操作系统环境 +- Ubuntu22.04 +### 2. docker安装 +- 2.1 更新apt列表 + +> sudo apt update + +- 2.2 通过apt安装所需的软件包 + +> sudo apt install ca-certificates curl gnupg lsb-release + +- 2.3 创建保存GPG key的目录 + +> sudo mkdir -p /etc/apt/keyrings + +- 2.4.设置docker GPG key + +> curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg + +- 2.5 设置仓库信息 + +> echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + +- 2.6 更新apt列表 + +> sudo apt update + +- 2.7 安装docker + +> sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin + +- 2.8 验证 +> #说明1:至此docker已经安装完毕了,可以通过如下方式进行验证: +> sudo docker run hello-world + +这条命令会下载一个hello-world的镜像,并在一个容器中运行它,它会输出一些信息,然后退出,如果可以正常的看到信息,说明docker已经成功的完成安装。 + +说明2:如果不想要每次执行docker时都要sudo,可以把用户加入docker的组里: + +> sudo usermod -aG docker 用户名 + +### 3. docker-compose工具安装 + +> 下载工具 +``` shell +sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose +``` + +> 添加操作权限 +```shell +sudo chmod +x /usr/local/bin/docker-compose +``` + +>验证 +``` shell +docker-compose --version命令 +``` + +## 二:下载代码 + +### 1. 下载代码到服务器 + + +> #后端 +> git git@gitee.com:tusdesign/jeepay.git + +> #前端 +> git git@gitee.com:tusdesign/jeepay-ui.git + + + +## 三:代码部署 + +### 1. 采用docker compose命编译构建与开启 + +```shell +Maven 依赖提前编译,修改 MQ 队列 (修改 jeepay-components-mq 依赖) 也需要重新运行此命令 + +docker build -t jeepay-deps:latest -f docs/Dockerfile . + +启动命令:docker-compose up + +删除:docker-compose rm + +启动并运行在后台:docker-compose up -d + +重新编译:docker-compose up --build + +重新创建:docker-compose up --force-recreate + +重新编译并覆盖之前的:docker-compose up --build --force-recreate +``` + +### 2. 应用独立安装 +> #后端支付接口 +> docker buildx build . --build-arg PORT=9216 --build-arg PLATFORM=payment -t jeepay-payment:latest + +>#后端运营平台接口 +docker buildx build . --build-arg PORT=9217 --build-arg PLATFORM=manager -t jeepay-manager:latest + +>#后端商户平台接口 +docker buildx build . --build-arg PORT=9218 --build-arg PLATFORM=merchant -t jeepay-merchant:latest + +>#启动命令 +```shell +- docker run -d -p 9216:9216 jeepay-payment:latest +- docker run -d -p 9217:9217 jeepay-manager:latest +- docker run -d -p 9218:9218 jeepay-merchant:latest +``` + + +> #前端 + +> 编译命令 + +> docker buildx build . --build-arg PLATFORM=cashier -t jeepay-payment:latest + +> docker buildx build . --build-arg PLATFORM=manager -t jeepay-manager:latest + +> docker buildx build . --build-arg PLATFORM=merchant -t jeepay-merchant:latest + +> 启动命令 +```shell +- docker run -d -p 9226:80 -e BACKEND_HOST=172.20.0.9216 jeepay-ui-cashier:latest +- docker run -d -p 9227:80 -e BACKEND_HOST=172.20.0.9217 jeepay-ui-manager:latest +- docker run -d -p 9228:80 -e BACKEND_HOST=172.20.0.9218 jeepay-ui-merchant:latest +``` + +## 四:注意事项 + +### web根路径修改 + + +### npm源修改 + + +### docker-compose源修改 + + +### docker buildx命令使用 + -- Gitee From ba0943fc79f806193dcc243e6163943a6e278596 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Thu, 22 Dec 2022 13:15:44 +0800 Subject: [PATCH 02/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E6=84=8F?= =?UTF-8?q?=E4=BA=8B=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "\351\203\250\347\275\262.md" | 44 ++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git "a/\351\203\250\347\275\262.md" "b/\351\203\250\347\275\262.md" index 9b6d891..5ce73b8 100644 --- "a/\351\203\250\347\275\262.md" +++ "b/\351\203\250\347\275\262.md" @@ -73,7 +73,7 @@ docker-compose --version命令 ## 三:代码部署 -### 1. 采用docker compose命编译构建与开启 +### 1. 采用docker compose命令一次性编译构建与开启 ```shell Maven 依赖提前编译,修改 MQ 队列 (修改 jeepay-components-mq 依赖) 也需要重新运行此命令 @@ -128,16 +128,48 @@ docker buildx build . --build-arg PORT=9218 --build-arg PLATFORM=merchant -t jee - docker run -d -p 9228:80 -e BACKEND_HOST=172.20.0.9218 jeepay-ui-merchant:latest ``` -## 四:注意事项 -### web根路径修改 +## 四:各平台运行地址: +### 1. 项目名称和地址 +```bash +- payment 127.0.0.1:9216 +- cashier 127.0.0.1:9226 +- manager 127.0.0.1:9217 +- manager-ui 127.0.0.1:9227 +- merchant 127.0.0.1:9218 +- merchant-ui 127.0.0.1:9228 +``` + +## 五:注意事项 + +### 1. web根路径修改 +> #路径到后台的根目录下,打开.env文件,修改前端项目的根路径地址 + +> UI_BASE_DIR=/Users/dingzhiwei/work/idea_wk/gitee_wk + +> #如果web项目跟后端项目处于目录的同一级,则配置不用填 + +> UI_BASE_DIR= + + +### 2. npm源修改 +> 目录到jeepay-web项目的根目录修改dockerfile文件 + +> RUN npm config set registry https://registry.npmmirror.com + + +### 3. docker-compose源修改 + + +> pip3 install docker-compose -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com +### 4.docker buildx命令使用 -### npm源修改 +> 开启buildx特性,当然这不是必须的,buildx是为了跨平台构建时指定平台 +> 使用了 Docker 特性 Buildx 请开启相关特性 -### docker-compose源修改 +> syntax = docker/dockerfile:experimental -### docker buildx命令使用 -- Gitee From bb1942120f669d808a7423ed6874f4b006085477 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Tue, 27 Dec 2022 11:15:33 +0800 Subject: [PATCH 03/31] =?UTF-8?q?=E6=96=87=E6=A1=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "\351\203\250\347\275\262.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/\351\203\250\347\275\262.md" "b/\351\203\250\347\275\262.md" index 5ce73b8..32decfd 100644 --- "a/\351\203\250\347\275\262.md" +++ "b/\351\203\250\347\275\262.md" @@ -115,11 +115,11 @@ docker buildx build . --build-arg PORT=9218 --build-arg PLATFORM=merchant -t jee > 编译命令 -> docker buildx build . --build-arg PLATFORM=cashier -t jeepay-payment:latest +> docker buildx build . --build-arg PLATFORM=cashier -t jeepay-ui-cashier:latest -> docker buildx build . --build-arg PLATFORM=manager -t jeepay-manager:latest +> docker buildx build . --build-arg PLATFORM=manager -t jeepay-ui-manager:latest -> docker buildx build . --build-arg PLATFORM=merchant -t jeepay-merchant:latest +> docker buildx build . --build-arg PLATFORM=merchant -t jeepay-ui-merchant:latest > 启动命令 ```shell -- Gitee From 1aa14f6c844850cbac22e6dcdb7eb20b029fe8bc Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Fri, 30 Dec 2022 23:23:37 +0800 Subject: [PATCH 04/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=90=AF=E8=BF=AA?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=94=AF=E4=BB=98=E9=80=9A=E9=81=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose-base.yml | 65 +++++++++++++++ .../com/jeequan/jeepay/core/constants/CS.java | 7 +- .../jeepay/core/model/params/IsvParams.java | 3 + .../core/model/params/IsvsubMchParams.java | 3 + .../core/model/params/NormalMchParams.java | 3 + .../params/qidipay/QidipayIsvParams.java | 19 +++++ .../qidipay/QidipayIsvsubMchParams.java | 14 ++++ .../qidipay/QidipayNormalMchParams.java | 32 ++++++++ .../qidipay/QidiPayOrderQueryService.java | 75 ++++++++++++++++++ .../qidipay/QidipayChannelNoticeService.java | 79 +++++++++++++++++++ .../qidipay/QidipayPaymentService.java | 34 ++++++++ .../pay/channel/qidipay/payway/QidiApp.java | 57 +++++++++++++ .../pay/rqrs/payorder/UnifiedOrderRQ.java | 5 +- .../rqrs/payorder/payway/QiDiAppOrderRQ.java | 19 +++++ .../rqrs/payorder/payway/QiDiAppOrderRS.java | 6 ++ 15 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 docker-compose-base.yml create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvParams.java create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvsubMchParams.java create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayNormalMchParams.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidiPayOrderQueryService.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayChannelNoticeService.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRS.java diff --git a/docker-compose-base.yml b/docker-compose-base.yml new file mode 100644 index 0000000..63873ed --- /dev/null +++ b/docker-compose-base.yml @@ -0,0 +1,65 @@ +version: '3' + +services: + mysql: + hostname: mysql + container_name: jeepay-mysql + # amd64 平台 + #image: mysql/mysql-server:latest + image: mysql:8 + environment: + LANG: C.UTF-8 + MYSQL_ROOT_PASSWORD: "rootroot" + MYSQL_DATABASE: "jeepaydb" + MYSQL_USER: "jeepay" + MYSQL_PASSWORD: "jeepay" + ports: + - "3306:3306" + volumes: + - mysql:/var/lib/mysql + - ./docs/sql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro + networks: + jeepay: + ipv4_address: 192.168.65.10 + activemq: + build: + context: ./docker/activemq + dockerfile: Dockerfile + hostname: activemq + container_name: jeepay-activemq + image: jeepay-activemq:latest + ports: #- "1883:1883" + #- "5672:5672" + - "8161:8161" + #- "61613:61613" + #- "61614:61614" + - "61616:61616" + volumes: + - activemq:/opt/activemq + - ./docker/activemq/activemq.xml:/opt/activemq/conf/activemq.xml + networks: + jeepay: + ipv4_address: 192.168.65.11 + redis: + hostname: redis + container_name: jeepay-redis + image: redis:latest + ports: + - "6380:6379" + networks: + jeepay: + ipv4_address: 192.168.65.12 + volumes: + - redis:/data + +networks: + jeepay: + ipam: + config: + - subnet: 192.168.65.0/24 + +volumes: + mysql: + redis: + activemq: +# rabbitmq: \ No newline at end of file diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/constants/CS.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/constants/CS.java index 627f72c..ee6fd91 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/constants/CS.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/constants/CS.java @@ -143,11 +143,14 @@ public class CS { public interface IF_CODE{ String ALIPAY = "alipay"; // 支付宝官方支付 + String WXPAY = "wxpay"; // 微信官方支付 String YSFPAY = "ysfpay"; // 云闪付开放平台 String XXPAY = "xxpay"; // 小新支付 String PPPAY = "pppay"; // Paypal 支付 - String PLSPAY = "plspay"; // 计全支付plus + String PLSPAY = "plspay"; // 计全支付plus + + String QIDIPAY="qidipay"; //启迪支付 } @@ -176,6 +179,8 @@ public class CS { String WX_NATIVE = "WX_NATIVE"; //微信扫码支付 String PP_PC = "PP_PC"; // Paypal 支付 + + String QIDI_APP = "QIDI_APP"; //启迪app支付 } //支付数据包 类型 diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/IsvParams.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/IsvParams.java index c57a839..5f11354 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/IsvParams.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/IsvParams.java @@ -18,6 +18,7 @@ package com.jeequan.jeepay.core.model.params; import com.alibaba.fastjson.JSONObject; import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams; +import com.jeequan.jeepay.core.model.params.qidipay.QidipayIsvParams; import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvParams; import com.jeequan.jeepay.core.model.params.ysf.YsfpayIsvParams; @@ -39,6 +40,8 @@ public abstract class IsvParams { return JSONObject.parseObject(paramsStr, AlipayIsvParams.class); }else if(CS.IF_CODE.YSFPAY.equals(ifCode)){ return JSONObject.parseObject(paramsStr, YsfpayIsvParams.class); + }else if(CS.IF_CODE.QIDIPAY.equals(ifCode)){ + return JSONObject.parseObject(paramsStr, QidipayIsvParams.class); } return null; } diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/IsvsubMchParams.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/IsvsubMchParams.java index 82739c1..01d5807 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/IsvsubMchParams.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/IsvsubMchParams.java @@ -18,6 +18,7 @@ package com.jeequan.jeepay.core.model.params; import com.alibaba.fastjson.JSONObject; import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvsubMchParams; +import com.jeequan.jeepay.core.model.params.qidipay.QidipayIsvsubMchParams; import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvsubMchParams; import com.jeequan.jeepay.core.model.params.ysf.YsfpayIsvsubMchParams; @@ -38,6 +39,8 @@ public abstract class IsvsubMchParams { return JSONObject.parseObject(paramsStr, AlipayIsvsubMchParams.class); }else if(CS.IF_CODE.YSFPAY.equals(ifCode)){ return JSONObject.parseObject(paramsStr, YsfpayIsvsubMchParams.class); + }else if(CS.IF_CODE.QIDIPAY.equals(ifCode)){ + return JSONObject.parseObject(paramsStr, QidipayIsvsubMchParams.class); } return null; } diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/NormalMchParams.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/NormalMchParams.java index 100a398..9749627 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/NormalMchParams.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/NormalMchParams.java @@ -20,6 +20,7 @@ import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.model.params.alipay.AlipayNormalMchParams; import com.jeequan.jeepay.core.model.params.plspay.PlspayNormalMchParams; import com.jeequan.jeepay.core.model.params.pppay.PpPayNormalMchParams; +import com.jeequan.jeepay.core.model.params.qidipay.QidipayNormalMchParams; import com.jeequan.jeepay.core.model.params.wxpay.WxpayNormalMchParams; import com.jeequan.jeepay.core.model.params.xxpay.XxpayNormalMchParams; @@ -44,6 +45,8 @@ public abstract class NormalMchParams { return JSONObject.parseObject(paramsStr, PpPayNormalMchParams.class); }else if (CS.IF_CODE.PLSPAY.equals(ifCode)){ return JSONObject.parseObject(paramsStr, PlspayNormalMchParams.class); + }else if (CS.IF_CODE.QIDIPAY.equals(ifCode)){ + return JSONObject.parseObject(paramsStr, QidipayNormalMchParams.class); } return null; } diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvParams.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvParams.java new file mode 100644 index 0000000..88989fb --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvParams.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.core.model.params.qidipay; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.jeequan.jeepay.core.model.params.IsvParams; +import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvParams; +import com.jeequan.jeepay.core.utils.StringKit; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +@Data +public class QidipayIsvParams extends IsvParams { + + @Override + public String deSenData() { + QidipayIsvParams isvParams = this; + return ((JSONObject) JSON.toJSON(isvParams)).toJSONString(); + } +} diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvsubMchParams.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvsubMchParams.java new file mode 100644 index 0000000..838de52 --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvsubMchParams.java @@ -0,0 +1,14 @@ +package com.jeequan.jeepay.core.model.params.qidipay; + +import com.jeequan.jeepay.core.model.params.IsvsubMchParams; +import lombok.Data; + +@Data +public class QidipayIsvsubMchParams extends IsvsubMchParams { + /** 子商户ID **/ + private String subMchId; + + /** 子账户appID **/ + private String subMchAppId; + +} diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayNormalMchParams.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayNormalMchParams.java new file mode 100644 index 0000000..661f531 --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayNormalMchParams.java @@ -0,0 +1,32 @@ +package com.jeequan.jeepay.core.model.params.qidipay; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.jeequan.jeepay.core.model.params.NormalMchParams; +import com.jeequan.jeepay.core.model.params.xxpay.XxpayNormalMchParams; +import com.jeequan.jeepay.core.utils.StringKit; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + + +@Data +public class QidipayNormalMchParams extends NormalMchParams { + + /** 商户号 */ + private String mchId; + + /** 私钥 */ + private String key; + + /** 支付网关地址 */ + private String payUrl; + + @Override + public String deSenData() { + QidipayNormalMchParams mchParams = this; + if (StringUtils.isNotBlank(this.key)) { + mchParams.setKey(StringKit.str2Star(this.key, 4, 4, 6)); + } + return ((JSONObject) JSON.toJSON(mchParams)).toJSONString(); + } +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidiPayOrderQueryService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidiPayOrderQueryService.java new file mode 100644 index 0000000..64275d1 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidiPayOrderQueryService.java @@ -0,0 +1,75 @@ +package com.jeequan.jeepay.pay.channel.qidipay; + +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSONObject; +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.core.entity.PayOrder; +import com.jeequan.jeepay.core.model.params.qidipay.QidipayNormalMchParams; +import com.jeequan.jeepay.core.model.params.xxpay.XxpayNormalMchParams; +import com.jeequan.jeepay.core.utils.JeepayKit; +import com.jeequan.jeepay.pay.channel.IPayOrderQueryService; +import com.jeequan.jeepay.pay.channel.xxpay.XxpayKit; +import com.jeequan.jeepay.pay.model.MchAppConfigContext; +import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; +import com.jeequan.jeepay.pay.service.ConfigContextQueryService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.TreeMap; + +@Service +@Slf4j +public class QidiPayOrderQueryService implements IPayOrderQueryService { + + @Autowired + private ConfigContextQueryService configContextQueryService; + + + @Override + public String getIfCode() { + return CS.IF_CODE.QIDIPAY; + } + + @Override + public ChannelRetMsg query(PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception { + QidipayNormalMchParams xxpayParams = (QidipayNormalMchParams) configContextQueryService.queryNormalMchParams(mchAppConfigContext.getMchNo() + , mchAppConfigContext.getAppId() + , getIfCode()); + + Map paramMap = new TreeMap();// 接口类型 + paramMap.put("mchId", xxpayParams.getMchId()); + paramMap.put("mchOrderNo", payOrder.getPayOrderId()); + String sign = XxpayKit.getSign(paramMap, xxpayParams.getKey()); + paramMap.put("sign", sign); + String resStr = ""; + String queryPayOrderUrl = XxpayKit.getQueryPayOrderUrl(xxpayParams.getPayUrl()) + "?" + JeepayKit.genUrlParams(paramMap); + try { + log.info("支付查询[{}]参数:{}", getIfCode(), queryPayOrderUrl); + //resStr = HttpUtil.createPost(queryPayOrderUrl).timeout(60 * 1000).execute().body(); + log.info("支付查询[{}]结果:{}", getIfCode(), resStr); + } catch (Exception e) { + log.error("http error", e); + } +// if(StringUtils.isEmpty(resStr)) { +// return ChannelRetMsg.waiting(); //支付中 +// } +// JSONObject resObj = JSONObject.parseObject(resStr); +// if(!"0".equals(resObj.getString("retCode"))){ +// return ChannelRetMsg.waiting(); //支付中 +// } +// // 支付状态,0-订单生成,1-支付中,2-支付成功,3-业务处理完成 +// String status = resObj.getString("status"); +// if("2".equals(status) || "3".equals(status)) { +// return ChannelRetMsg.confirmSuccess(resObj.getString("channelOrderNo")); //支付成功 +// } +// return ChannelRetMsg.waiting(); //支付中 + + ChannelRetMsg channelResult = new ChannelRetMsg(); + channelResult.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS); + return channelResult; + + } +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayChannelNoticeService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayChannelNoticeService.java new file mode 100644 index 0000000..421a254 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayChannelNoticeService.java @@ -0,0 +1,79 @@ +package com.jeequan.jeepay.pay.channel.qidipay; + +import com.alibaba.fastjson.JSONObject; +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.core.entity.PayOrder; +import com.jeequan.jeepay.core.exception.ResponseException; +import com.jeequan.jeepay.core.model.params.qidipay.QidipayNormalMchParams; +import com.jeequan.jeepay.core.model.params.xxpay.XxpayNormalMchParams; +import com.jeequan.jeepay.pay.channel.AbstractChannelNoticeService; +import com.jeequan.jeepay.pay.channel.xxpay.XxpayKit; +import com.jeequan.jeepay.pay.model.MchAppConfigContext; +import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.MutablePair; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +@Service +@Slf4j +public class QidipayChannelNoticeService extends AbstractChannelNoticeService { + + @Override + public String getIfCode() { + return CS.IF_CODE.QIDIPAY; + } + + @Override + public MutablePair parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) { + try { + JSONObject params = getReqParamJSON(); + String payOrderId = params.getString("mchOrderNo"); + return MutablePair.of(payOrderId, params); + + } catch (Exception e) { + log.error("error", e); + throw ResponseException.buildText("ERROR"); + } + } + + @Override + public ChannelRetMsg doNotice(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext, NoticeTypeEnum noticeTypeEnum) { + try { + QidipayNormalMchParams qidipayNormalMchParams = (QidipayNormalMchParams) + configContextQueryService.queryNormalMchParams( + mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), getIfCode()); + + // 获取请求参数 + JSONObject jsonParams = (JSONObject) params; + String checkSign = jsonParams.getString("sign"); + jsonParams.remove("sign"); + // 验证签名 + if (!checkSign.equals(XxpayKit.getSign(jsonParams, qidipayNormalMchParams.getKey()))) { + throw ResponseException.buildText("ERROR"); + } + + //验签成功后判断上游订单状态 + ResponseEntity okResponse = textResp("success"); + + // 支付状态,0-订单生成,1-支付中,2-支付成功,3-业务处理完成 + String status = jsonParams.getString("status"); + + ChannelRetMsg result = new ChannelRetMsg(); + result.setChannelOrderId(jsonParams.getString("channelOrderNo")); //渠道订单号 + result.setResponseEntity(okResponse); //响应数据 + + result.setChannelState(ChannelRetMsg.ChannelState.WAITING); // 默认支付中 + + if ("2".equals(status) || "3".equals(status)) { + result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS); + } + return result; + } catch (Exception e) { + log.error("error", e); + throw ResponseException.buildText("ERROR"); + } + } +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java new file mode 100644 index 0000000..05618d4 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java @@ -0,0 +1,34 @@ +package com.jeequan.jeepay.pay.channel.qidipay; + +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.core.entity.PayOrder; +import com.jeequan.jeepay.pay.channel.AbstractPaymentService; +import com.jeequan.jeepay.pay.model.MchAppConfigContext; +import com.jeequan.jeepay.pay.rqrs.AbstractRS; +import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ; +import com.jeequan.jeepay.pay.util.PaywayUtil; +import org.springframework.stereotype.Service; + +@Service +public class QidipayPaymentService extends AbstractPaymentService { + + @Override + public String getIfCode() { + return CS.IF_CODE.QIDIPAY; + } + + @Override + public boolean isSupport(String wayCode) { + return false; + } + + @Override + public String preCheck(UnifiedOrderRQ bizRQ, PayOrder payOrder) { + return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).preCheck(bizRQ, payOrder); + } + + @Override + public AbstractRS pay(UnifiedOrderRQ bizRQ, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception { + return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).pay(bizRQ, payOrder, mchAppConfigContext); + } +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java new file mode 100644 index 0000000..40df91a --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java @@ -0,0 +1,57 @@ +package com.jeequan.jeepay.pay.channel.qidipay.payway; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import com.alipay.api.AlipayApiException; +import com.alipay.api.domain.AlipayTradePagePayModel; +import com.alipay.api.domain.AlipayTradePayModel; +import com.alipay.api.request.AlipayTradePagePayRequest; +import com.alipay.api.request.AlipayTradePayRequest; +import com.alipay.api.response.AlipayTradePayResponse; +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.core.entity.PayOrder; +import com.jeequan.jeepay.core.exception.BizException; +import com.jeequan.jeepay.core.utils.AmountUtil; +import com.jeequan.jeepay.pay.channel.alipay.AlipayKit; +import com.jeequan.jeepay.pay.channel.qidipay.QidipayPaymentService; +import com.jeequan.jeepay.pay.exception.ChannelException; +import com.jeequan.jeepay.pay.model.MchAppConfigContext; +import com.jeequan.jeepay.pay.rqrs.AbstractRS; +import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; +import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ; +import com.jeequan.jeepay.pay.rqrs.payorder.payway.*; +import com.jeequan.jeepay.pay.util.ApiResBuilder; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +@Service("qidiPaymentByQidiAppService") +public class QidiApp extends QidipayPaymentService { + + @Override + public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) { + + QiDiAppOrderRQ bizRQ = (QiDiAppOrderRQ) rq; + if(StringUtils.isEmpty(bizRQ.getAuthCode())){ + throw new BizException("用户支付条码[authCode]不可为空"); + } + return null; + } + + @Override + public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){ + + QiDiAppOrderRQ bizRQ = (QiDiAppOrderRQ) rq; + + // 构造函数响应数据 + AliPcOrderRS res = ApiResBuilder.buildSuccess(AliPcOrderRS.class); + res.setFormContent(""); + res.setPayUrl(""); + + ChannelRetMsg channelRetMsg = new ChannelRetMsg(); + res.setChannelRetMsg(channelRetMsg); + + //放置 响应数据 + channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS); + return res; + } +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/UnifiedOrderRQ.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/UnifiedOrderRQ.java index 9d5cbc6..999c334 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/UnifiedOrderRQ.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/UnifiedOrderRQ.java @@ -158,8 +158,11 @@ public class UnifiedOrderRQ extends AbstractMchAppRQ { PPPcOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), PPPcOrderRQ.class); BeanUtils.copyProperties(this, bizRQ); return bizRQ; + }else if (CS.PAY_WAY_CODE.QIDI_APP.equals(wayCode)){ + QiDiAppOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), QiDiAppOrderRQ.class); + BeanUtils.copyProperties(this, bizRQ); + return bizRQ; } - return this; } diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java new file mode 100644 index 0000000..fed8f2f --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.pay.rqrs.payorder.payway; + +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +public class QiDiAppOrderRQ extends UnifiedOrderRQ { + + /** 启辿支付条码 **/ + @NotBlank(message = "启迪支付条码不能为空") + private String authCode; + + public QiDiAppOrderRQ(){ + this.setWayCode(CS.PAY_WAY_CODE.QIDI_APP); + } +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRS.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRS.java new file mode 100644 index 0000000..aea1d77 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRS.java @@ -0,0 +1,6 @@ +package com.jeequan.jeepay.pay.rqrs.payorder.payway; + +import com.jeequan.jeepay.pay.rqrs.payorder.CommonPayDataRS; + +public class QiDiAppOrderRS extends CommonPayDataRS { +} -- Gitee From 8e86fca865abc3ba2febaddac9912c6a2a340a4f Mon Sep 17 00:00:00 2001 From: "Q.S. Wang" Date: Sat, 31 Dec 2022 16:36:10 +0800 Subject: [PATCH 05/31] chore: remove hardcoded ip addresses, use docker from private repo --- Dockerfile | 4 ++-- conf/manager/application.yml | 4 ++-- conf/merchant/application.yml | 4 ++-- conf/payment/application.yml | 4 ++-- scripts/build-dept.sh | 4 ++++ scripts/build-ui.sh | 7 +++++++ scripts/build.sh | 9 +++++++++ 7 files changed, 28 insertions(+), 8 deletions(-) create mode 100755 scripts/build-dept.sh create mode 100755 scripts/build-ui.sh create mode 100755 scripts/build.sh diff --git a/Dockerfile b/Dockerfile index 204b677..be7c486 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ # docker build -t jeepay-deps:latest -f docs/Dockerfile . # 编译依赖缓存,请先执行上方命令 -FROM jeepay-deps:latest AS builder +FROM oci.tuxm.art:8443/tusdesign/jeepay-deps:latest AS builder WORKDIR /workspace @@ -30,7 +30,7 @@ COPY --from=builder /workspace/conf/${PLATFORM}/application.yml /workspace/appli EXPOSE $PORT -CMD ["java", "-jar", "/workspace/jeepay-app.jar"] +CMD ["java", "-jar", "/workspace/jeepay-app.jar","-Djavax.xml.accessExternalDTD=all"] # 编译命令 # docker buildx build . --build-arg PORT=9216 --build-arg PLATFORM=payment -t jeepay-payment:latest diff --git a/conf/manager/application.yml b/conf/manager/application.yml index 2f1172e..6a05473 100644 --- a/conf/manager/application.yml +++ b/conf/manager/application.yml @@ -30,7 +30,7 @@ spring: number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00 datasource: # yml填写url连接串, 无需将&符号进行转义 - url: jdbc:mysql://172.20.0.10:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true + url: jdbc:mysql://jeepay-mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true username: jeepay password: jeepay druid: @@ -63,7 +63,7 @@ spring: # #activeMQ配置 ( 注意: activeMQ配置项需在spring的下级 ) activemq: - broker-url: failover:(tcp://172.20.0.11:61616?wireFormat.maxInactivityDuration=0) #连接地址 + broker-url: failover:(tcp://jeepay-activemq:61616?wireFormat.maxInactivityDuration=0) #连接地址 in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。 user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。 password: manager diff --git a/conf/merchant/application.yml b/conf/merchant/application.yml index 3475d42..a51099d 100644 --- a/conf/merchant/application.yml +++ b/conf/merchant/application.yml @@ -30,7 +30,7 @@ spring: number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00 datasource: # yml填写url连接串, 无需将&符号进行转义 - url: jdbc:mysql://172.20.0.10:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true + url: jdbc:mysql://jeepay-mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true username: jeepay password: jeepay druid: @@ -63,7 +63,7 @@ spring: # #activeMQ配置 ( 注意: activeMQ配置项需在spring的下级 ) activemq: - broker-url: failover:(tcp://172.20.0.11:61616?wireFormat.maxInactivityDuration=0) #连接地址 + broker-url: failover:(tcp://jeepay-activemq:61616?wireFormat.maxInactivityDuration=0) #连接地址 in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。 user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。 password: manager diff --git a/conf/payment/application.yml b/conf/payment/application.yml index 28eeac0..85966e7 100644 --- a/conf/payment/application.yml +++ b/conf/payment/application.yml @@ -30,7 +30,7 @@ spring: number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00 datasource: # yml填写url连接串, 无需将&符号进行转义 - url: jdbc:mysql://172.20.0.10:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true + url: jdbc:mysql://jeepay-mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true username: jeepay password: jeepay druid: @@ -63,7 +63,7 @@ spring: # #activeMQ配置 ( 注意: activeMQ配置项需在spring的下级 ) activemq: - broker-url: failover:(tcp://172.20.0.11:61616?wireFormat.maxInactivityDuration=0) #连接地址 + broker-url: failover:(tcp://jeepay-activemq:61616?wireFormat.maxInactivityDuration=0) #连接地址 in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。 user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。 password: manager diff --git a/scripts/build-dept.sh b/scripts/build-dept.sh new file mode 100755 index 0000000..b809748 --- /dev/null +++ b/scripts/build-dept.sh @@ -0,0 +1,4 @@ +export DOCKER_DEFAULT_PLATFORM=linux/amd64 + +docker build -t oci.tuxm.art:8443/tusdesign/jeepay-deps:latest -f docs/Dockerfile . +docker push oci.tuxm.art:8443/tusdesign/jeepay-deps:latest diff --git a/scripts/build-ui.sh b/scripts/build-ui.sh new file mode 100755 index 0000000..5f870ba --- /dev/null +++ b/scripts/build-ui.sh @@ -0,0 +1,7 @@ +export DOCKER_DEFAULT_PLATFORM=linux/amd64 + +docker buildx build . --build-arg PLATFORM=cashier -t jeepay-ui-cashier:latest + +docker buildx build . --build-arg PLATFORM=manager -t jeepay-ui-manager:latest + +docker buildx build . --build-arg PLATFORM=merchant -t jeepay-ui-merchant:latest diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..3cf5901 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,9 @@ +export DOCKER_DEFAULT_PLATFORM=linux/amd64 + +docker buildx build . --build-arg PORT=9216 --build-arg PLATFORM=payment -t oci.tuxm.art:8443/tusdesign/jeepay-payment:latest +docker push oci.tuxm.art:8443/tusdesign/jeepay-payment:latest +docker buildx build . --build-arg PORT=9217 --build-arg PLATFORM=manager -t oci.tuxm.art:8443/tusdesign/jeepay-manager:latest +docker push oci.tuxm.art:8443/tusdesign/jeepay-manager:latest +docker buildx build . --build-arg PORT=9218 --build-arg PLATFORM=merchant -t oci.tuxm.art:8443/tusdesign/jeepay-merchant:latest +docker push oci.tuxm.art:8443/tusdesign/jeepay-merchant:latest + -- Gitee From 2fafdc7fcca11e4c3e87edf78680af791ea62171 Mon Sep 17 00:00:00 2001 From: "Q.s" Date: Sat, 31 Dec 2022 17:48:35 +0800 Subject: [PATCH 06/31] chore: remove hardcoded ip addresses, add the build scripts --- .github/workflows/docker-harbor.yml | 28 + .gitignore | 4 +- Dockerfile | 2 +- Dockerfile_github | 46 + conf/manager/application.yml | 4 +- conf/merchant/application.yml | 4 +- conf/payment/application.yml | 4 +- docs/Dockerfile_github | 9 + nohup.out | 1621 +++++++++++++++++++++++++++ scripts/build-dept.sh | 4 + scripts/build-ui.sh | 7 + scripts/build.sh | 9 + scripts/build_harbor.sh | 39 + 13 files changed, 1773 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/docker-harbor.yml create mode 100644 Dockerfile_github create mode 100644 docs/Dockerfile_github create mode 100644 nohup.out create mode 100755 scripts/build-dept.sh create mode 100755 scripts/build-ui.sh create mode 100755 scripts/build.sh create mode 100644 scripts/build_harbor.sh diff --git a/.github/workflows/docker-harbor.yml b/.github/workflows/docker-harbor.yml new file mode 100644 index 0000000..d89500b --- /dev/null +++ b/.github/workflows/docker-harbor.yml @@ -0,0 +1,28 @@ +name: Docker Image CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + persist-credentials: false + - name: Set env + run: echo "TAG_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + - name: Run build and push docker to harbor + run: sh ./scripts/build_harbor.sh + env: + VERSION: ${{ env.TAG_VERSION }} + COMMIT_SHA: ${{ github.sha }} + HARBOR_USER: ${{ secrets.HARBOR_USER }} + HARBOR_PASS: ${{ secrets.HARBOR_PASS }} + diff --git a/.gitignore b/.gitignore index 988d812..d2d21be 100644 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,6 @@ unpackage/ docker/rocketmq/broker/logs/ docker/rocketmq/broker/store/ -docker/rocketmq/namesrv/ \ No newline at end of file +docker/rocketmq/namesrv/ + +nohup.out \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 204b677..0d7501e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ COPY --from=builder /workspace/conf/${PLATFORM}/application.yml /workspace/appli EXPOSE $PORT -CMD ["java", "-jar", "/workspace/jeepay-app.jar"] +CMD ["java", "-jar", "/workspace/jeepay-app.jar","-Djavax.xml.accessExternalDTD=all"] # 编译命令 # docker buildx build . --build-arg PORT=9216 --build-arg PLATFORM=payment -t jeepay-payment:latest diff --git a/Dockerfile_github b/Dockerfile_github new file mode 100644 index 0000000..ae23693 --- /dev/null +++ b/Dockerfile_github @@ -0,0 +1,46 @@ +# syntax = docker/dockerfile:experimental +# 使用了 Docker 特性 Buildx 请开启相关特性 + +# 切换 JDK 请修改后面的 17 到对应版本 +# docker build -t jeepay-deps:latest -f docs/Dockerfile . + +# 编译依赖缓存,请先执行上方命令 +FROM oci.tuxm.art:8443/tusdesign/jeepay-deps:latest AS builder + +WORKDIR /workspace + +COPY . /workspace + +# RUN mkdir -p /root/.m2 +# COPY ./docs/settings.xml /root/.m2/settings.xml + +RUN mvn clean package -Dmaven.test.skip=true -Ptest + +# 以下为运行容器 切换 JDK 到对应版本 +# jdk8对应:mcr.microsoft.com/java/jre:8-zulu-alpine +# jdk17对应:mcr.microsoft.com/java/jre:17-zulu-alpine +FROM mcr.microsoft.com/java/jre:8-zulu-alpine + +ARG PLATFORM=$PLATFORM + +WORKDIR /workspace + +COPY --from=builder /workspace/jeepay-${PLATFORM}/target/jeepay-${PLATFORM}.jar /workspace/jeepay-app.jar +COPY --from=builder /workspace/conf/${PLATFORM}/application.yml /workspace/application.yml + +EXPOSE $PORT + +CMD ["java", "-jar", "/workspace/jeepay-app.jar"] + +# 编译命令 +# docker buildx build . --build-arg PORT=9216 --build-arg PLATFORM=payment -t jeepay-payment:latest +# docker buildx build . --build-arg PORT=9217 --build-arg PLATFORM=manager -t jeepay-manager:latest +# docker buildx build . --build-arg PORT=9218 --build-arg PLATFORM=merchant -t jeepay-merchant:latest +# +# 如果你需要多平台镜像,你可以使用 --platform linux/amd64,linux/arm64 +# 比如 docker buildx build . --build-arg PORT=9218 --build-arg PLATFORM=merchant -t jeepay-merchant:latest --platform linux/amd64,linux/arm64 +# +# 启动命令 +# docker run -d -p 9216:9216 jeepay-payment:latest +# docker run -d -p 9217:9217 jeepay-manager:latest +# docker run -d -p 9218:9218 jeepay-merchant:latest \ No newline at end of file diff --git a/conf/manager/application.yml b/conf/manager/application.yml index 2f1172e..6a05473 100644 --- a/conf/manager/application.yml +++ b/conf/manager/application.yml @@ -30,7 +30,7 @@ spring: number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00 datasource: # yml填写url连接串, 无需将&符号进行转义 - url: jdbc:mysql://172.20.0.10:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true + url: jdbc:mysql://jeepay-mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true username: jeepay password: jeepay druid: @@ -63,7 +63,7 @@ spring: # #activeMQ配置 ( 注意: activeMQ配置项需在spring的下级 ) activemq: - broker-url: failover:(tcp://172.20.0.11:61616?wireFormat.maxInactivityDuration=0) #连接地址 + broker-url: failover:(tcp://jeepay-activemq:61616?wireFormat.maxInactivityDuration=0) #连接地址 in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。 user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。 password: manager diff --git a/conf/merchant/application.yml b/conf/merchant/application.yml index 3475d42..a51099d 100644 --- a/conf/merchant/application.yml +++ b/conf/merchant/application.yml @@ -30,7 +30,7 @@ spring: number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00 datasource: # yml填写url连接串, 无需将&符号进行转义 - url: jdbc:mysql://172.20.0.10:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true + url: jdbc:mysql://jeepay-mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true username: jeepay password: jeepay druid: @@ -63,7 +63,7 @@ spring: # #activeMQ配置 ( 注意: activeMQ配置项需在spring的下级 ) activemq: - broker-url: failover:(tcp://172.20.0.11:61616?wireFormat.maxInactivityDuration=0) #连接地址 + broker-url: failover:(tcp://jeepay-activemq:61616?wireFormat.maxInactivityDuration=0) #连接地址 in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。 user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。 password: manager diff --git a/conf/payment/application.yml b/conf/payment/application.yml index 28eeac0..85966e7 100644 --- a/conf/payment/application.yml +++ b/conf/payment/application.yml @@ -30,7 +30,7 @@ spring: number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00 datasource: # yml填写url连接串, 无需将&符号进行转义 - url: jdbc:mysql://172.20.0.10:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true + url: jdbc:mysql://jeepay-mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true username: jeepay password: jeepay druid: @@ -63,7 +63,7 @@ spring: # #activeMQ配置 ( 注意: activeMQ配置项需在spring的下级 ) activemq: - broker-url: failover:(tcp://172.20.0.11:61616?wireFormat.maxInactivityDuration=0) #连接地址 + broker-url: failover:(tcp://jeepay-activemq:61616?wireFormat.maxInactivityDuration=0) #连接地址 in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。 user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。 password: manager diff --git a/docs/Dockerfile_github b/docs/Dockerfile_github new file mode 100644 index 0000000..c644245 --- /dev/null +++ b/docs/Dockerfile_github @@ -0,0 +1,9 @@ +FROM maven:3-eclipse-temurin-17 + +WORKDIR /build +COPY . . + +# RUN mkdir -p /root/.m2 +# COPY ./docs/settings.xml /root/.m2/settings.xml + +RUN mvn dependency:go-offline \ No newline at end of file diff --git a/nohup.out b/nohup.out new file mode 100644 index 0000000..5d0441e --- /dev/null +++ b/nohup.out @@ -0,0 +1,1621 @@ +Mon Dec 26 14:47:10 CST 2022 +From https://gitee.com/tusdesign/jeepay + + c8812e3...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Mon Dec 26 14:47:15 CST 2022 +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +To github.com:tusdesign/jeepay.git + c8812e3..0f4e844 master -> master +From https://gitee.com/tusdesign/jeepay + + 0f4e844...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +To github.com:tusdesign/jeepay.git + 0f4e844..d774b6b master -> master +From https://gitee.com/tusdesign/jeepay + + d774b6b...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + d774b6b...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +To github.com:tusdesign/jeepay.git + d774b6b..7d26d92 master -> master +From https://gitee.com/tusdesign/jeepay + + 7d26d92...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +Mon Dec 26 15:14:43 CST 2022 +From https://gitee.com/tusdesign/jeepay + + 7d26d92...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +Mon Dec 26 15:14:54 CST 2022 +From https://gitee.com/tusdesign/jeepay + + 7d26d92...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7d26d92...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +To github.com:tusdesign/jeepay.git + 7d26d92..5909f7f master -> master +From https://gitee.com/tusdesign/jeepay + + 5909f7f...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +To github.com:tusdesign/jeepay.git + 5909f7f..a48fce1 master -> master +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...ba0943f master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + af1dd6d...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Merge made by the 'recursive' strategy. + "\351\203\250\347\275\262.md" | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) +To github.com:tusdesign/jeepay.git + af1dd6d..e9c9075 master -> master +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...bb19421 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + e9c9075...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Merge made by the 'recursive' strategy. + docker-compose-base.yml | 65 ++++++++++++++++++ + .../java/com/jeequan/jeepay/core/constants/CS.java | 7 +- + .../jeepay/core/model/params/IsvParams.java | 3 + + .../jeepay/core/model/params/IsvsubMchParams.java | 3 + + .../jeepay/core/model/params/NormalMchParams.java | 3 + + .../model/params/qidipay/QidipayIsvParams.java | 19 ++++++ + .../params/qidipay/QidipayIsvsubMchParams.java | 14 ++++ + .../params/qidipay/QidipayNormalMchParams.java | 32 +++++++++ + .../channel/qidipay/QidiPayOrderQueryService.java | 75 ++++++++++++++++++++ + .../qidipay/QidipayChannelNoticeService.java | 79 ++++++++++++++++++++++ + .../pay/channel/qidipay/QidipayPaymentService.java | 34 ++++++++++ + .../jeepay/pay/channel/qidipay/payway/QidiApp.java | 57 ++++++++++++++++ + .../jeepay/pay/rqrs/payorder/UnifiedOrderRQ.java | 5 +- + .../pay/rqrs/payorder/payway/QiDiAppOrderRQ.java | 19 ++++++ + .../pay/rqrs/payorder/payway/QiDiAppOrderRS.java | 6 ++ + 15 files changed, 419 insertions(+), 2 deletions(-) + create mode 100644 docker-compose-base.yml + create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvParams.java + create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvsubMchParams.java + create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayNormalMchParams.java + create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidiPayOrderQueryService.java + create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayChannelNoticeService.java + create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java + create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java + create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java + create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRS.java +To github.com:tusdesign/jeepay.git + e9c9075..7150f5e master -> master +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...1aa14f6 master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +Already up to date. +Everything up-to-date +From https://gitee.com/tusdesign/jeepay + + 7150f5e...8e86fca master -> origin/master (forced update) +hint: Pulling without specifying how to reconcile divergent branches is +hint: discouraged. You can squelch this message by running one of the following +hint: commands sometime before your next pull: +hint: +hint: git config pull.rebase false # merge (the default strategy) +hint: git config pull.rebase true # rebase +hint: git config pull.ff only # fast-forward only +hint: +hint: You can replace "git config" with "git config --global" to set a default +hint: preference for all repositories. You can also pass --rebase, --no-rebase, +hint: or --ff-only on the command line to override the configured default per +hint: invocation. +error: Your local changes to the following files would be overwritten by merge: + Dockerfile +Please commit your changes or stash them before you merge. +Aborting +Everything up-to-date diff --git a/scripts/build-dept.sh b/scripts/build-dept.sh new file mode 100755 index 0000000..b809748 --- /dev/null +++ b/scripts/build-dept.sh @@ -0,0 +1,4 @@ +export DOCKER_DEFAULT_PLATFORM=linux/amd64 + +docker build -t oci.tuxm.art:8443/tusdesign/jeepay-deps:latest -f docs/Dockerfile . +docker push oci.tuxm.art:8443/tusdesign/jeepay-deps:latest diff --git a/scripts/build-ui.sh b/scripts/build-ui.sh new file mode 100755 index 0000000..5f870ba --- /dev/null +++ b/scripts/build-ui.sh @@ -0,0 +1,7 @@ +export DOCKER_DEFAULT_PLATFORM=linux/amd64 + +docker buildx build . --build-arg PLATFORM=cashier -t jeepay-ui-cashier:latest + +docker buildx build . --build-arg PLATFORM=manager -t jeepay-ui-manager:latest + +docker buildx build . --build-arg PLATFORM=merchant -t jeepay-ui-merchant:latest diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..3cf5901 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,9 @@ +export DOCKER_DEFAULT_PLATFORM=linux/amd64 + +docker buildx build . --build-arg PORT=9216 --build-arg PLATFORM=payment -t oci.tuxm.art:8443/tusdesign/jeepay-payment:latest +docker push oci.tuxm.art:8443/tusdesign/jeepay-payment:latest +docker buildx build . --build-arg PORT=9217 --build-arg PLATFORM=manager -t oci.tuxm.art:8443/tusdesign/jeepay-manager:latest +docker push oci.tuxm.art:8443/tusdesign/jeepay-manager:latest +docker buildx build . --build-arg PORT=9218 --build-arg PLATFORM=merchant -t oci.tuxm.art:8443/tusdesign/jeepay-merchant:latest +docker push oci.tuxm.art:8443/tusdesign/jeepay-merchant:latest + diff --git a/scripts/build_harbor.sh b/scripts/build_harbor.sh new file mode 100644 index 0000000..a9236ab --- /dev/null +++ b/scripts/build_harbor.sh @@ -0,0 +1,39 @@ +export TZ=Asia/Shanghai +export BUILD_TIME=$(date +'%Y-%m-%dT%H:%M:%S%z') + +export DOCKER_DEFAULT_PLATFORM=linux/amd64 +export TAG=oci.tuxm.art:8443/tusdesign/jeepay-payment:latest + +# docker build -t jeepay-deps:latest -f docs/Dockerfile_github . + +docker buildx build -f Dockerfile_github \ + -t $TAG \ + --build-arg USER=${GITHUB_USER} \ + --build-arg TOKEN=${GITHUB_TOKEN} \ + --build-arg PORT=9216 \ + --build-arg PLATFORM=payment \ + --build-arg BUILD_TIME=${BUILD_TIME} \ + --build-arg VERSION=${VERSION} \ + --build-arg COMMIT_SHA=${COMMIT_SHA} . + +docker buildx build -f Dockerfile_github \ + -t oci.tuxm.art:8443/tusdesign/jeepay-manager:latest \ + --build-arg PORT=9217 \ + --build-arg PLATFORM=manager \ + --build-arg BUILD_TIME=${BUILD_TIME} \ + --build-arg VERSION=${VERSION} \ + --build-arg COMMIT_SHA=${COMMIT_SHA} . + +docker buildx build -f Dockerfile_github \ + -t oci.tuxm.art:8443/tusdesign/jeepay-merchant:latest \ + --build-arg PORT=9218 \ + --build-arg PLATFORM=merchant \ + --build-arg BUILD_TIME=${BUILD_TIME} \ + --build-arg VERSION=${VERSION} \ + --build-arg COMMIT_SHA=${COMMIT_SHA} . + +docker login oci.tuxm.art:8443 --username ${HARBOR_USER} --password ${HARBOR_PASS} +docker push $TAG +docker push oci.tuxm.art:8443/tusdesign/jeepay-manager:latest +docker push oci.tuxm.art:8443/tusdesign/jeepay-merchant:latest + -- Gitee From 24f6fe45afb7ff9d3164cd3de248777aad10e0b4 Mon Sep 17 00:00:00 2001 From: "Q.s" Date: Sun, 1 Jan 2023 13:36:48 +0800 Subject: [PATCH 07/31] chore: add the build scirpt for active_mq --- nohup.out | 1621 ------------------------------------ scripts/build-ui.sh | 7 - scripts/build_active_mq.sh | 3 + 3 files changed, 3 insertions(+), 1628 deletions(-) delete mode 100644 nohup.out delete mode 100755 scripts/build-ui.sh create mode 100755 scripts/build_active_mq.sh diff --git a/nohup.out b/nohup.out deleted file mode 100644 index 5d0441e..0000000 --- a/nohup.out +++ /dev/null @@ -1,1621 +0,0 @@ -Mon Dec 26 14:47:10 CST 2022 -From https://gitee.com/tusdesign/jeepay - + c8812e3...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Mon Dec 26 14:47:15 CST 2022 -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -To github.com:tusdesign/jeepay.git - c8812e3..0f4e844 master -> master -From https://gitee.com/tusdesign/jeepay - + 0f4e844...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -To github.com:tusdesign/jeepay.git - 0f4e844..d774b6b master -> master -From https://gitee.com/tusdesign/jeepay - + d774b6b...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + d774b6b...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -To github.com:tusdesign/jeepay.git - d774b6b..7d26d92 master -> master -From https://gitee.com/tusdesign/jeepay - + 7d26d92...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -Mon Dec 26 15:14:43 CST 2022 -From https://gitee.com/tusdesign/jeepay - + 7d26d92...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -Mon Dec 26 15:14:54 CST 2022 -From https://gitee.com/tusdesign/jeepay - + 7d26d92...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7d26d92...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -To github.com:tusdesign/jeepay.git - 7d26d92..5909f7f master -> master -From https://gitee.com/tusdesign/jeepay - + 5909f7f...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -To github.com:tusdesign/jeepay.git - 5909f7f..a48fce1 master -> master -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...ba0943f master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + af1dd6d...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Merge made by the 'recursive' strategy. - "\351\203\250\347\275\262.md" | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) -To github.com:tusdesign/jeepay.git - af1dd6d..e9c9075 master -> master -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...bb19421 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + e9c9075...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Merge made by the 'recursive' strategy. - docker-compose-base.yml | 65 ++++++++++++++++++ - .../java/com/jeequan/jeepay/core/constants/CS.java | 7 +- - .../jeepay/core/model/params/IsvParams.java | 3 + - .../jeepay/core/model/params/IsvsubMchParams.java | 3 + - .../jeepay/core/model/params/NormalMchParams.java | 3 + - .../model/params/qidipay/QidipayIsvParams.java | 19 ++++++ - .../params/qidipay/QidipayIsvsubMchParams.java | 14 ++++ - .../params/qidipay/QidipayNormalMchParams.java | 32 +++++++++ - .../channel/qidipay/QidiPayOrderQueryService.java | 75 ++++++++++++++++++++ - .../qidipay/QidipayChannelNoticeService.java | 79 ++++++++++++++++++++++ - .../pay/channel/qidipay/QidipayPaymentService.java | 34 ++++++++++ - .../jeepay/pay/channel/qidipay/payway/QidiApp.java | 57 ++++++++++++++++ - .../jeepay/pay/rqrs/payorder/UnifiedOrderRQ.java | 5 +- - .../pay/rqrs/payorder/payway/QiDiAppOrderRQ.java | 19 ++++++ - .../pay/rqrs/payorder/payway/QiDiAppOrderRS.java | 6 ++ - 15 files changed, 419 insertions(+), 2 deletions(-) - create mode 100644 docker-compose-base.yml - create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvParams.java - create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayIsvsubMchParams.java - create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/qidipay/QidipayNormalMchParams.java - create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidiPayOrderQueryService.java - create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayChannelNoticeService.java - create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java - create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java - create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java - create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRS.java -To github.com:tusdesign/jeepay.git - e9c9075..7150f5e master -> master -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...1aa14f6 master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -Already up to date. -Everything up-to-date -From https://gitee.com/tusdesign/jeepay - + 7150f5e...8e86fca master -> origin/master (forced update) -hint: Pulling without specifying how to reconcile divergent branches is -hint: discouraged. You can squelch this message by running one of the following -hint: commands sometime before your next pull: -hint: -hint: git config pull.rebase false # merge (the default strategy) -hint: git config pull.rebase true # rebase -hint: git config pull.ff only # fast-forward only -hint: -hint: You can replace "git config" with "git config --global" to set a default -hint: preference for all repositories. You can also pass --rebase, --no-rebase, -hint: or --ff-only on the command line to override the configured default per -hint: invocation. -error: Your local changes to the following files would be overwritten by merge: - Dockerfile -Please commit your changes or stash them before you merge. -Aborting -Everything up-to-date diff --git a/scripts/build-ui.sh b/scripts/build-ui.sh deleted file mode 100755 index 5f870ba..0000000 --- a/scripts/build-ui.sh +++ /dev/null @@ -1,7 +0,0 @@ -export DOCKER_DEFAULT_PLATFORM=linux/amd64 - -docker buildx build . --build-arg PLATFORM=cashier -t jeepay-ui-cashier:latest - -docker buildx build . --build-arg PLATFORM=manager -t jeepay-ui-manager:latest - -docker buildx build . --build-arg PLATFORM=merchant -t jeepay-ui-merchant:latest diff --git a/scripts/build_active_mq.sh b/scripts/build_active_mq.sh new file mode 100755 index 0000000..ea320c5 --- /dev/null +++ b/scripts/build_active_mq.sh @@ -0,0 +1,3 @@ +export DOCKER_DEFAULT_PLATFORM=linux/amd64 +docker build -t oci.tuxm.art:8443/tusdesign/jeepay-activemq:latest ./docker/activemq +docker push oci.tuxm.art:8443/tusdesign/jeepay-activemq:latest \ No newline at end of file -- Gitee From f2a6aeb75297b485ac80be43d46b72058228c59c Mon Sep 17 00:00:00 2001 From: "Q.s" Date: Sun, 1 Jan 2023 13:59:33 +0800 Subject: [PATCH 08/31] chore: remove .env from commitment --- .env | 2 -- .gitignore | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index cabce62..0000000 --- a/.env +++ /dev/null @@ -1,2 +0,0 @@ -# ui项目的根路径 -UI_BASE_DIR=/Users/dingzhiwei/work/idea_wk/gitee_wk \ No newline at end of file diff --git a/.gitignore b/.gitignore index d2d21be..fc45e13 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,5 @@ docker/rocketmq/broker/logs/ docker/rocketmq/broker/store/ docker/rocketmq/namesrv/ -nohup.out \ No newline at end of file +nohup.out +.env \ No newline at end of file -- Gitee From 8ca32e670a16560bb895829903f0715ffb15c290 Mon Sep 17 00:00:00 2001 From: "Q.s" Date: Sun, 1 Jan 2023 14:12:49 +0800 Subject: [PATCH 09/31] chore: add exe permission to build_harbor.sh --- scripts/build_harbor.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/build_harbor.sh diff --git a/scripts/build_harbor.sh b/scripts/build_harbor.sh old mode 100644 new mode 100755 -- Gitee From 25fdc757b7450766d540d75ed0d4546ce3c118f6 Mon Sep 17 00:00:00 2001 From: "Q.s" Date: Sun, 1 Jan 2023 14:20:41 +0800 Subject: [PATCH 10/31] chore: disable github action --- .github/workflows/docker-harbor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-harbor.yml b/.github/workflows/docker-harbor.yml index d89500b..101f9f7 100644 --- a/.github/workflows/docker-harbor.yml +++ b/.github/workflows/docker-harbor.yml @@ -2,9 +2,9 @@ name: Docker Image CI on: push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] +# branches: [ "master" ] +# pull_request: +# branches: [ "master" ] jobs: -- Gitee From 61240389d121f6bcd06d25b3f4873898b2d9f58d Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Wed, 4 Jan 2023 14:25:13 +0800 Subject: [PATCH 11/31] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E9=80=9A=E9=81=93=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +++- docker-compose-base.yml | 8 ++++---- jeepay-manager/src/main/resources/application.yml | 2 ++ .../jeepay/pay/channel/qidipay/QidipayPaymentService.java | 2 +- .../jeepay/pay/channel/qidipay/payway/QidiApp.java | 8 ++++---- .../jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java | 4 ++-- jeepay-payment/src/main/resources/application.yml | 2 ++ 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 988d812..3f58b65 100644 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,6 @@ unpackage/ docker/rocketmq/broker/logs/ docker/rocketmq/broker/store/ -docker/rocketmq/namesrv/ \ No newline at end of file +docker/rocketmq/namesrv/ +/jeepay-payment/src/main/resources/application-dev.yml +/jeepay-manager/src/main/resources/application-dev.yml diff --git a/docker-compose-base.yml b/docker-compose-base.yml index 63873ed..b37556e 100644 --- a/docker-compose-base.yml +++ b/docker-compose-base.yml @@ -20,7 +20,7 @@ services: - ./docs/sql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro networks: jeepay: - ipv4_address: 192.168.65.10 + ipv4_address: 172.23.80.10 activemq: build: context: ./docker/activemq @@ -39,7 +39,7 @@ services: - ./docker/activemq/activemq.xml:/opt/activemq/conf/activemq.xml networks: jeepay: - ipv4_address: 192.168.65.11 + ipv4_address: 172.23.80.11 redis: hostname: redis container_name: jeepay-redis @@ -48,7 +48,7 @@ services: - "6380:6379" networks: jeepay: - ipv4_address: 192.168.65.12 + ipv4_address: 172.23.80.12 volumes: - redis:/data @@ -56,7 +56,7 @@ networks: jeepay: ipam: config: - - subnet: 192.168.65.0/24 + - subnet: 172.23.80.0/24 volumes: mysql: diff --git a/jeepay-manager/src/main/resources/application.yml b/jeepay-manager/src/main/resources/application.yml index eb2b822..d0c7ec8 100644 --- a/jeepay-manager/src/main/resources/application.yml +++ b/jeepay-manager/src/main/resources/application.yml @@ -4,6 +4,8 @@ server: spring: redis: database: 1 #1库:运营平台 #2库:商户系统 #3库:支付网关 +# profiles: +# active: dev #系统业务参数 isys: diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java index 05618d4..efef5cd 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayPaymentService.java @@ -19,7 +19,7 @@ public class QidipayPaymentService extends AbstractPaymentService { @Override public boolean isSupport(String wayCode) { - return false; + return true; } @Override diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java index 40df91a..87059da 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/payway/QidiApp.java @@ -30,10 +30,10 @@ public class QidiApp extends QidipayPaymentService { @Override public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) { - QiDiAppOrderRQ bizRQ = (QiDiAppOrderRQ) rq; - if(StringUtils.isEmpty(bizRQ.getAuthCode())){ - throw new BizException("用户支付条码[authCode]不可为空"); - } +// QiDiAppOrderRQ bizRQ = (QiDiAppOrderRQ) rq; +// if(StringUtils.isEmpty(bizRQ.getAuthCode())){ +// throw new BizException("用户支付条码[authCode]不可为空"); +// } return null; } diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java index fed8f2f..61701c7 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/payway/QiDiAppOrderRQ.java @@ -10,8 +10,8 @@ import javax.validation.constraints.NotBlank; public class QiDiAppOrderRQ extends UnifiedOrderRQ { /** 启辿支付条码 **/ - @NotBlank(message = "启迪支付条码不能为空") - private String authCode; + // @NotBlank(message = "启迪支付条码不能为空") + // private String authCode; public QiDiAppOrderRQ(){ this.setWayCode(CS.PAY_WAY_CODE.QIDI_APP); diff --git a/jeepay-payment/src/main/resources/application.yml b/jeepay-payment/src/main/resources/application.yml index 68564a0..5b8bda9 100644 --- a/jeepay-payment/src/main/resources/application.yml +++ b/jeepay-payment/src/main/resources/application.yml @@ -4,3 +4,5 @@ server: spring: redis: database: 3 #1库:运营平台 #2库:商户系统 #3库:支付网关 +# profiles: +# active: dev \ No newline at end of file -- Gitee From 0f4f916d23e82e243fcbdc5f83ce3da7002c98f8 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Thu, 5 Jan 2023 15:26:06 +0800 Subject: [PATCH 12/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- docs/file/image_1.png | Bin 0 -> 7821 bytes docs/file/image_2.png | Bin 0 -> 54152 bytes docs/file/image_3.png | Bin 0 -> 36075 bytes docs/file/image_4.png | Bin 0 -> 32073 bytes ...12\346\212\245\346\216\245\345\217\243.md" | 115 ++++++++++++++++++ 6 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 docs/file/image_1.png create mode 100644 docs/file/image_2.png create mode 100644 docs/file/image_3.png create mode 100644 docs/file/image_4.png create mode 100644 "\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" diff --git a/.gitignore b/.gitignore index e6e7086..f259ac6 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ docker/rocketmq/namesrv/ /jeepay-payment/src/main/resources/application-dev.yml /jeepay-manager/src/main/resources/application-dev.yml - +/jeepay-merchant/src/main/resources/application-dev.yml nohup.out -.env \ No newline at end of file +.env + diff --git a/docs/file/image_1.png b/docs/file/image_1.png new file mode 100644 index 0000000000000000000000000000000000000000..1c934d70b8a485e1b18f8091b948f7e188c5162e GIT binary patch literal 7821 zcmcJUc|6qX-~T^!9$M61Q{+Mg|yszthU61$k{d!+d&CQGi z`NjDG01&+K*HudZ;F<-0g1;UFTg=NZ?C(Ze-oOx~7R|8>|PPna&j!^7|Glvw-z>Whyb?h9`JXk1}`-(gL&f9MW8=7ir+A1G(f zI~oP+4lpzQloVXpr19uz&7798d2-H^)S>c=Q-klF%rS1@!ogzO+Lao>rjW%oO+|j;Ef<3{13+$Qk9n`vMl9K2r|>a! z+4~@ndnqL^4?r+nc1kko@t_M9_!h7yjgsq92BVY!fVfeuqOq7Eof|Nh$a94E*`@;EH;nDt6h>n8PsuuvUCklIGe9 z8rQv!K`uv2{9J}zn(+cS=-y8oFAsyASI5T2$JM`v_dkC87-Iwg=9+FkFc|ECi$}=K z?7)Bk0={6T4nCD4--@D*#RZpJZ!HZ3N}FXC69kh_8p3DmkuF1Fo+nm|EVcHA3rv!h zf=BOj0e#YPE)t~G(B;8X^>;g-wZkyOFQts8>Exy)->ME_qx~=iF#}RScj8&Z`$!%X ztUUf=$o2|0q4L3kaecrl$zTds>9^GXt#VjW9*Eev&Pj@_v}FWQM`h~6Ijl2R)!?L8 zzbuzIHSyE%_O;$u^>cI{KKQ6xQ+iy(_fI~$`Lz;OiM`8Ru2pr>~MnloiZXt5&#;g;K9;Arzz8CLe@~q?w^k` zcC#;sIHJ*Q4%O~)wB_aEkPvaP)~R}AAh<$>W}Aug{@ZJ_IZ@AKZ(+D3@`6ba# zs18M!RvkWl&CnfRUkBV#(bo^H8Q9BPi+#O5R;<@w%W+}LMg}rmX+-DzHVYZF1Q6jD zI2#uDdj<8rDK9>9ce>GUC=x0@yy|m@Vl`2$4L#-gUasJIp6n-h+x0eIkyo{r@|h-A zY`OL4i=`pf%W0DPJ6-f5J&xD!&3VrnoW*}{#GO_YU-Rzy=<_c?3Qko%v%BuASzSTgaqT&t*w5LB`3)?x8*x@@bCFUQ$sJ-1>+vd>OYzw)~(SOn` zg)H1)uK8;HSgd)nkJfY;KQg0uVMG|fI1=s()k0~WJ*kx=Q>evg^}wEQFZQx-6z^)J>C-gY^gNa*mZUD2gX?(p|RGbF?QOhlVa~!jFfSr z5HO#mS8exRF5RbK5TbhA>Vuq%tNMHM)cZ5Gg;;xzrNy#+ML~U~H_82a5whw|QtES* zDh$2%+J|*c;*?f2ghWBO!CVN~IxIQ0jLzW{PSJ9TX7_?2bilXNYB}0nO)iLWne%<* zmh`pf&l--}*CEJSuNcB|J~Pdl#!>)KER89T94mW!W2B)xSV@)Lm_i@#K6vop^p`KU^D}Xjp{H-2vhLRq?l%*a+r^Aqhyu28+t1#!Klgj|^wE*6@L{j)QO>)sqYFZh2! zSdtI zD=9c6B*}q~^hV~}_5>b(TAoo|3mX?}_oh!bN=23q&)WhlL>ng{5X8lF7#*a;$34;P zH$9Nmn^qCnmJlZ0lzT$>#{piUhK1hLBhC&C80~z}R)5}@q7&g87@H*Hg4U99e!R_4 z@v@v_2%~olnUq^-!n%$ElB1)?o*YQ*azM7AKC&sUJM01WZ-DoeV>kytYCz_8aY1Qy zbv31(IXpcz{Z_e4S+D-xrp#Ld;#*`_{0YQlmD>$w8TRub+y&Hc`x>O{SD-g)<@m!f z1&}%~{ssTQ?Ul)D^7iVKQ4NIrNy{j!+(o9BGE$TzJ6YVrbdliM+#1kZLo_a=JnKLE z4RrqvfW_s02e03}(JAqGYL^C+>=+Xsx?gjz($zmO@CeDa#{)1|aPzqkDnY*BqU9fp z@zoRw2a#%;?ZJ~9Y3ekb*Rum+@6fZPc4R$8 z8!Y96Mozi?K-gfCcuKL(ki_fBE1hu?CPLCDda++sXk%uQvqcdQjlz;h2oZLL3Z;9` z_o>h7cuR0zRCwEVjXazTpv=>1XLb274^^!zWh)Hw3e2r9q>6hllp(w7>F)3h(NZqBN zoLUaljLoK9&gp!q+GtGfpY{I)Z==n?Ygg6B-xC!;5P^4uY}i+gTbF)~zzXw^^c z?Tk+djOqR`K|gbX;>~RW>-P_wf=S?fO&U9)Ih-F$dP*gI1?FGeOoMx9i9#}g&CtA( zYh2!^upLF_#OIVjJmsH8OdFH%qePtIJ97IYa9P3})%!3&{L| zXIZ#*EvGcO*RY3aFVA04rF0YS*Dg0kUMNpwj6-kR2c?`QFZdWZ4FH2T%ewiX;a|=l z<*ZlVcSdJ@_i@SLsXKoZ?!s>aPntmor_`cdf5YUTFj|W_=UHMv)U9zYsV}kS!EFuw z=7E;D%#?OKwy)*BpGh^%OQp9$7I3#Ax%NlOWeRZW$gJ;zs?S|Cm*BUc$`RMSCJ88- z`IxDi8ggcOc{}flS(es%D$;uguHbL z(3uDe{|q7mCioAUMXIQA0jEOstP|S)j3iA>Iib<${0y$#?&W`m-rTY>MP|SD+M#y< z|M#%mHJ&iNT&>Rm*9U**2VJp8ln9R=J&N9A_XFa$ocgdqMWz`xJK_2Zzqh`F}!Nw~}nMD)nGIyg8ap{2+tYim#e0l$MfWAxD_ zHIY_-?F0Ys@P@}Bfb=B9MQli-b92xTgUR%3vbdc&QhHchOUn@og+A!LNm`;aDko$kN>@Zp9UZ=42X9ZZ{ z`Y6ylCAhRNJTD6W-JwxRkw@owUSQT@sDDeO|3tUHkr$V?e);~_CY5wl5lmdEyOhdZPs;rn{4*lQ`5c_>}zjzLv%>Sl6a|OGf3i^qsr1l`4o3{9&8OwCAGwX1;=G52i)z62G`RJqoXtah z`}FdQ7FK8V=-&O|E6}p$FXJBkUH%O$kYKI1{! z9KpFPDA-lKJye4YhS-TiswC7ApHDb2D7H4DMZ08z9i*@w!j)Y(&wh{HxV>sfgXL(& z_!l6FrKT6GR3)i4Hp@2lB~XJq_QvDYvJl88%2TrhUDooG@v%NU!lN7OOmtdpTZ0br zJLj)5_Fv}m40@W1g0UG`KrP6=8#R^3DvFx_6N-WL2Ghch4qXH&$6VfR8gd6O$w%>4 z?>iSd86`&xs4w$^w6H33FWlOH_h|~LYD@{}Pa0p9w`sw8kL~M~(nbQxn>UT;!c3Qk zgFykUqx?wwWt?nnkBv11hh=uXAYO;O*X0QM|HcU_4rEq`U-+D< zsr)b-%C+Pq<%FM_EcPa@c+k@8>7J1Oj$&3Ay>aPT885&XwVs3ZWZf%xS9S5r14W$0 zukNO;mspYG;nmy6!~^@^bYG+L*M)gG^i>c~7xWwJhOzvsgauq`E%Y=DxN!P57uY#O z*Y@Q8YmaONX#v~2yvb7oEJd6*!rrrIT_FZjCToO?^8e$x{c{-h?r5tu zB*ym0gR!>?aNISY&D4`bcg)>lIc=o~IOn@?bhD&HDaX?=Op04Lukvvd)valH#PK@q;utpm33=7=Iu2+7L1S&)qAD5B?N70X;G8| zWtRTJtIGH5t1ByKz(2(Y+B?2z14XDR4pvb!T*4%76=L#7nlDNrsE?chQNXI zgUm;*N4|3+sE$eFyKnYXZs_;t=&gaeC@q5bxgXWrrb8P}s%d9}3Tfx`U)3AuZe?eJ zg(=dTsbl|>67RpRCI5rLZoa-1>%RhkY|(Q#9F78YAI3-lo|TpLlU%6W=Ykj|az9x1 z``?-Ne+Autr_s(~CI;EUu)zlazy-v&=rvPyvIy=306drYFVTO&c}W2HRYF|+0eH;x zuN|>vZEdrHLPBbU8>&Mj67}a%LZPX&l@)(*bB(n9fOm}w`-{`{`@M}OYewGp&Louu z(v@^+(~G=WO=T^0>~o=9x!n9S0!I`ZKtgItE1Wf zk`8%_8$NDBL0L2SAhuj8At_8nyKIXm;uDx$EINlVh!$%~jtzt06)brhrnC7;3bFV( zt(!HV%l6rv31gC>J3jNBaX&d$*3>k$I$2%xjnjEa!}q9e*yDqDSOM=Tf}H0KIl35?%%JeVMt)sLBk?Z{9l^rgkA;b=82Y_ zud(!kRObiP?tKrKv*`U|h9vsO#+kpuZs}}Xt;!lhFQ$1UawxUiOH-|3A-{j@TP!KR z>BpSDSh~)dzNUV>0ZBOFlAhLV^CaCUK#Q3rmCw8=`!1%%*PrDZbnAYIP+&q(n_K(U zani;70BQ5HVBI7=N_L#XW=h}jw(cl=JbvC&!AEqN|E^vrnhlOZpgd`2L*3TQ#JH}@MXT#?rVJ-B|xvx71q_#Ik^RwvL z+C>F{S?eDh;&WP8=(`!D9HRoTOyl|DC+h94I`v<2?OekuqmIQabBrXz{H?F8#MIfU z`&Ww-ezbkqhf4~LBbY7d>;)A;udY#mSX>^*_#U)^WJx-w8593c- z+SmOte`a-Uk3pS}y3sdsK!1l@|8bP8OC0;;-S1C6yQOmkO?AOWJtvitZwQY@rZP)9M)yTj zg_8jOnHKr1Q_n~IYj9ytJ|n8~uHC^sg<#D}A3&bS+SWST)cXZr8mqP06~~l@GLx?` zOB@^oPT3jPSG${_=LX6GT*{rn%%1s}7Bjo*yQJvo#X@)>l=y&`GG`z}?+qogU~@w2Xha~6tG(yK@wW) zs~ekZOvXL!{Cz+AP)ALzQ`}2XIbXEmNN@x}Q}|M6@LVd`r`>!{02}1k1ctw|DFfa%tDoQrDA33*elVIKRS%EVY_s_2nH<1Cr(a(CL^~Yu}eP?4H^UgHJ zcX8U+!GbFkEJdD)Qpn{jZHogD8>ew^7$4Nu>?vw(R7T+IvM57dp;E&`2Y}8u<|hk1 zlszB>3VaHDxoT+_z)ukmn=#+<JWgv1fvO4Qj=H$ku?m2PjQ7fr}nt?WZ9pTO=tqr6ZM8wLr^`!K1zY6fPq_D+~Q z$Yqdvh6}hb^S1hu2qDjiuRmbBDR<;irmFVOm10N#RLe(H&9w>fz?|KF0}J<};T)=rne;-CvC&9XZQcl-HjPb%@yknG_1~CsPHRW#pXv$Z kOx~1+(@j8n&pww)?O|5d$74a@Gc$1Gn%UJdgWHk+1_fqSumAu6 literal 0 HcmV?d00001 diff --git a/docs/file/image_2.png b/docs/file/image_2.png new file mode 100644 index 0000000000000000000000000000000000000000..955619665111e935b8925fdacab19f35b9dc8f73 GIT binary patch literal 54152 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 literal 0 HcmV?d00001 diff --git a/docs/file/image_3.png b/docs/file/image_3.png new file mode 100644 index 0000000000000000000000000000000000000000..b9c7a4e742f0886b0ea468558800b4989e3bee9f GIT binary patch literal 36075 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%0AOmoJJYq7J%u&kwnCu_u2=y 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 支付方式 + +![启迪支付](docs/file/image_1.png) + + +### 2. 配置支付接口 +菜单:支付配置 -> 支付接口 +![启迪支付](docs/file/image_2.png) + +> 商户接口参数配置示例(字段值任意填,主要是方便后续拓展): +``` json +[ +{"name":"mchId", "desc":"支付商户号", "type": "text","verify":"required"}, +{"name":"key","desc":"私钥","type":"text","verify":"required"}, +{"name":"payUrl","desc":"支付连接","type":"text","verify":"required","star":"1"} +] +``` + + +### 3. 给商户系统绑定支付通道 + +菜单:商户管理 -> 应用列表 -> 支付配置 +![启迪支付](docs/file/image_3.png) + +![启迪支付](docs/file/image_4.png) + + +## 二:接口使用 + +1. 请求URL:https://localhost:9216/api/pay/unifiedOrder + +2. 请求方式:POST + +3. 请求类型:application/json 或 application/x-www-form-urlencoded + +4. 请求参数 +```json +{ + "amount": 100, + "mchOrderNo": "mho1624005107281", + "subject": "商品标题", + "wayCode": "QIDI_APP", + "sign": "84F606FA25A6EC4783BECC08D4FDC681", + "reqTime": "1624005107", + "body": "商品描述", + "version": "1.0", + "channelExtra": "", + "extParam":"{\"deptId\":\"D232323\",\"dealType\":\" PERSONAL\",\"employeeId\":\"P10223232323\"}", + "appId": "60cc09bce4b0f1c0b83761c9", + "clientIp": "192.168.0.1", + "notifyUrl": "https://www.jeequan.com", + "signType": "MD5", + "currency": "cny", + "returnUrl": "", + "mchNo": "M1623984572", + "divisionMode": 1 +} +``` +> 参数描述 + +| 字段 | 说明 | +| ---- | ---- | +| amount | 支付金额,单位分 | +| mchOrderNo | 商户生成的订单号 | +| subject | 商品描述 | +| wayCode | 支付方式 | +| sign | 签名 | +| reqTime | 请求接口时间,13位时间戳 | +| version | 商户生成的订单号 | +| channelExtra | 渠道字段 | +| extParam | 商户扩展参数,回调时会原样返回 | +| signType | 签名类型 | +| appId | 应用ID | +| clientIp | 客户端IPV4地址 | +| currency | 三位货币代码,人民币:cny | +| mchNo | 商户号 | +| divisionMode | 分账模式: 0-该笔订单不允许分账[默认], 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额) | +| returnUrl | 支付结果同步跳转通知URL | +| notifyUrl | 回调URL,只有传了该值才会发起回调 | + + +> 拓展字段描述 + +| 字段 | 说明 | +| ---- | ---- | +| deptId | 部门Id | + employeeId | 人员Id | +| dealType | 交易类型,分为个人支付和部门代付(PERSONAL,DEPARTMENTAL) | + + + +5. 返回参数 +```json +{ + "code": 0, + "data": { + "errCode": "ACQ.PAYMENT_AUTH_CODE_INVALID", + "errMsg": "Business Failed【支付失败,获取顾客账户信息失败,请顾客刷新付款码后重新收款,如再次收款失败,请联系管理员处理。[SOUNDWAVE_PARSER_FAIL]】", + "mchOrderNo": "mho1624005752661", + "orderState": 3, + "payOrderId": "P202106181642329900002" + }, + "msg": "SUCCESS", + "sign": "F4DA202C516D1F33A12F1E547C5004FD" +} +``` + +## 三、关于接口 + +更多参考:https://docs.jeequan.com/docs/jeepay/payment_api \ No newline at end of file -- Gitee From 53e2bde114cbb402ae7a4257af50aa3f519b8705 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Thu, 5 Jan 2023 15:37:28 +0800 Subject: [PATCH 13/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AD=BE=E5=90=8D?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...12\346\212\245\346\216\245\345\217\243.md" | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git "a/\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" "b/\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" index d5d63a1..8999a8a 100644 --- "a/\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" +++ "b/\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" @@ -112,4 +112,57 @@ ## 三、关于接口 -更多参考:https://docs.jeequan.com/docs/jeepay/payment_api \ No newline at end of file +### 1.签名计算方法(Java版) +```java +/** + * 计算签名 + * @param 请求参数集合 + * @param app私钥 + * @return + */ +public static String getSign(Map map, String key){ + ArrayList list = new ArrayList(); + for(Map.Entry entry:map.entrySet()){ + if(null != entry.getValue() && !"".equals(entry.getValue())){ + list.add(entry.getKey() + "=" + entry.getValue() + "&"); + } + } + int size = list.size(); + String [] arrayToSort = list.toArray(new String[size]); + Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < size; i ++) { + sb.append(arrayToSort[i]); + } + String result = sb.toString(); + result += "key=" + key; + log.info("signStr:{}", result); + result = md5(result, encodingCharset).toUpperCase(); + return result; + } + + + /** + * 计算MD5值 + * @param value + * @param charset + * @return + */ + public static String md5(String value, String charset) { + MessageDigest md; + try { + byte[] data = value.getBytes(charset); + md = MessageDigest.getInstance("MD5"); + byte[] digestData = md.digest(data); + return toHex(digestData); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return null; + } + } + +``` +### 2. 更多参考:https://docs.jeequan.com/docs/jeepay/payment_api \ No newline at end of file -- Gitee From 4039a1673bdd3d6a56c335079903fdb21825de19 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Wed, 1 Feb 2023 16:26:35 +0800 Subject: [PATCH 14/31] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E5=A4=B4=E6=B7=BB=E5=8A=A0X-API-KEY?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 4 +- .../pay/config/AuthHeaderSettingFilter.java | 71 +++++++++++++++++++ .../jeepay/pay/config/CustomFilter.java | 20 ++++++ .../pay/config/CustomHttpServletRequest.java | 47 ++++++++++++ .../jeepay/pay/config/WebMvcConfig.java | 24 +++++++ .../src/main/resources/application.yml | 4 +- ...12\346\212\245\346\216\245\345\217\243.md" | 71 +++---------------- 7 files changed, 176 insertions(+), 65 deletions(-) create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/AuthHeaderSettingFilter.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomFilter.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomHttpServletRequest.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/WebMvcConfig.java diff --git a/jeepay-manager/src/main/resources/application.yml b/jeepay-manager/src/main/resources/application.yml index d0c7ec8..571cd44 100644 --- a/jeepay-manager/src/main/resources/application.yml +++ b/jeepay-manager/src/main/resources/application.yml @@ -4,8 +4,8 @@ server: spring: redis: database: 1 #1库:运营平台 #2库:商户系统 #3库:支付网关 -# profiles: -# active: dev + profiles: + active: dev #系统业务参数 isys: diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/AuthHeaderSettingFilter.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/AuthHeaderSettingFilter.java new file mode 100644 index 0000000..5b18aa2 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/AuthHeaderSettingFilter.java @@ -0,0 +1,71 @@ +package com.jeequan.jeepay.pay.config; + + +import org.apache.tomcat.util.http.MimeHeaders; +import org.springframework.util.StringUtils; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description: 滤器实现对请求头的修改 + * @Author: chengzhengwen + */ +@WebFilter +public class AuthHeaderSettingFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Filter.super.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) servletRequest; + //HeaderMapRequestWrapper headerMapRequestWrapper = new HeaderMapRequestWrapper(req); + String token = req.getHeader("X-API-KEY"); + + if (!StringUtils.isEmpty(token)) { + //headerMapRequestWrapper.addHeader("loginId","456"); + Map map = new HashMap<>(); + map.put("X-API-KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0MGY5N2UyMi1iYmJjLTRkNDQtYTA2ZC1hYzY5NDUxZDY3ODciLCJpYXQiOjE2Mjk4ODUzNDIsImlzcyI6Im1haW5mbHV4LmF1dGgiLCJzdWIiOiJhbXkuamlhbmdAZW1haWwuY29tIiwiaXNzdWVyX2lkIjoiY2JiNWIxZDgtZmE2Zi00MGM1LTlkN2QtOTdmNzNlMDBkNzBmIiwidHlwZSI6Mn0.sBWISerstcHB3iBD-Mi3s-f68NX4lfS5BUycX1bgNh0"); + modifyHeaders(map, req); + } + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + Filter.super.destroy(); + } + + + private void modifyHeaders(Map headerses, HttpServletRequest request) { + if (headerses == null || headerses.isEmpty()) { + return; + } + Class requestClass = request.getClass(); + try { + Field request1 = requestClass.getDeclaredField("request"); + request1.setAccessible(true); + Object o = request1.get(request); + Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest"); + coyoteRequest.setAccessible(true); + Object o1 = coyoteRequest.get(o); + Field headers = o1.getClass().getDeclaredField("headers"); + headers.setAccessible(true); + MimeHeaders o2 = (MimeHeaders) headers.get(o1); + for (Map.Entry entry : headerses.entrySet()) { + o2.removeHeader(entry.getKey()); + o2.addValue(entry.getKey()).setString(entry.getValue()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomFilter.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomFilter.java new file mode 100644 index 0000000..f22a535 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomFilter.java @@ -0,0 +1,20 @@ +package com.jeequan.jeepay.pay.config; + + +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +@Component +public class CustomFilter implements Filter { + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + CustomHttpServletRequest request = new CustomHttpServletRequest((HttpServletRequest) servletRequest); + //request.addHeader("header","瓜田李下"); + request.addHeader("X-API-KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0MGY5N2UyMi1iYmJjLTRkNDQtYTA2ZC1hYzY5NDUxZDY3ODciLCJpYXQiOjE2Mjk4ODUzNDIsImlzcyI6Im1haW5mbHV4LmF1dGgiLCJzdWIiOiJhbXkuamlhbmdAZW1haWwuY29tIiwiaXNzdWVyX2lkIjoiY2JiNWIxZDgtZmE2Zi00MGM1LTlkN2QtOTdmNzNlMDBkNzBmIiwidHlwZSI6Mn0.sBWISerstcHB3iBD-Mi3s-f68NX4lfS5BUycX1bgNh0"); + filterChain.doFilter(request, servletResponse); + } +} \ No newline at end of file diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomHttpServletRequest.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomHttpServletRequest.java new file mode 100644 index 0000000..cda5c0c --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomHttpServletRequest.java @@ -0,0 +1,47 @@ +package com.jeequan.jeepay.pay.config; + + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.*; + +public class CustomHttpServletRequest extends HttpServletRequestWrapper { + + private Map headers = new HashMap<>(); + + public CustomHttpServletRequest(HttpServletRequest request) { + super(request); + } + + public void addHeader(String name, String value) { + headers.put(name, value); + } + + @Override + public String getHeader(String name) { + String value = super.getHeader(name); + + if (headers.containsKey(name)) { + value = headers.get(name); + } + return value; + } + + @Override + public Enumeration getHeaderNames() { + List names = Collections.list(super.getHeaderNames()); + names.addAll(headers.keySet()); + + return Collections.enumeration(names); + } + + @Override + public Enumeration getHeaders(String name) { + List list = Collections.list(super.getHeaders(name)); + + if (headers.containsKey(name)) { + list.add(headers.get(name)); + } + return Collections.enumeration(list); + } +} \ No newline at end of file diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/WebMvcConfig.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/WebMvcConfig.java new file mode 100644 index 0000000..514f7ee --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/WebMvcConfig.java @@ -0,0 +1,24 @@ +package com.jeequan.jeepay.pay.config; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import javax.annotation.Resource; + +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + + @Resource + private CustomFilter customFilter; + + @Bean + public FilterRegistrationBean initFilterRegistrationBean(){ + FilterRegistrationBean registrationBean=new FilterRegistrationBean<>(); + registrationBean.setFilter(customFilter); + registrationBean.addUrlPatterns("/*"); + registrationBean.setOrder(0); + return registrationBean; + } +} \ No newline at end of file diff --git a/jeepay-payment/src/main/resources/application.yml b/jeepay-payment/src/main/resources/application.yml index 5b8bda9..56b13eb 100644 --- a/jeepay-payment/src/main/resources/application.yml +++ b/jeepay-payment/src/main/resources/application.yml @@ -4,5 +4,5 @@ server: spring: redis: database: 3 #1库:运营平台 #2库:商户系统 #3库:支付网关 -# profiles: -# active: dev \ No newline at end of file + profiles: + active: dev \ No newline at end of file diff --git "a/\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" "b/\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" index 8999a8a..07d45cd 100644 --- "a/\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" +++ "b/\345\255\220\347\263\273\347\273\237\344\270\212\346\212\245\346\216\245\345\217\243.md" @@ -5,12 +5,12 @@ ### 1. 配置支付方式 菜单:支付配置 -> 支付方式 -![启迪支付](docs/file/image_1.png) +![启迪支付](file/image_1.png) ### 2. 配置支付接口 菜单:支付配置 -> 支付接口 -![启迪支付](docs/file/image_2.png) +![启迪支付](file/image_2.png) > 商户接口参数配置示例(字段值任意填,主要是方便后续拓展): ``` json @@ -25,9 +25,9 @@ ### 3. 给商户系统绑定支付通道 菜单:商户管理 -> 应用列表 -> 支付配置 -![启迪支付](docs/file/image_3.png) +![启迪支付](file/image_3.png) -![启迪支付](docs/file/image_4.png) +![启迪支付](file/image_4.png) ## 二:接口使用 @@ -38,13 +38,14 @@ 3. 请求类型:application/json 或 application/x-www-form-urlencoded + 4. 请求参数 ```json { "amount": 100, "mchOrderNo": "mho1624005107281", "subject": "商品标题", - "wayCode": "QIDI_APP", + "wayCode": "ALI_BAR", "sign": "84F606FA25A6EC4783BECC08D4FDC681", "reqTime": "1624005107", "body": "商品描述", @@ -88,9 +89,10 @@ | 字段 | 说明 | | ---- | ---- | -| deptId | 部门Id | - employeeId | 人员Id | +| pid | 人员Id | +| meetingID | 会议ID | | dealType | 交易类型,分为个人支付和部门代付(PERSONAL,DEPARTMENTAL) | +| deptId | 部门Id | @@ -112,57 +114,4 @@ ## 三、关于接口 -### 1.签名计算方法(Java版) -```java -/** - * 计算签名 - * @param 请求参数集合 - * @param app私钥 - * @return - */ -public static String getSign(Map map, String key){ - ArrayList list = new ArrayList(); - for(Map.Entry entry:map.entrySet()){ - if(null != entry.getValue() && !"".equals(entry.getValue())){ - list.add(entry.getKey() + "=" + entry.getValue() + "&"); - } - } - int size = list.size(); - String [] arrayToSort = list.toArray(new String[size]); - Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < size; i ++) { - sb.append(arrayToSort[i]); - } - String result = sb.toString(); - result += "key=" + key; - log.info("signStr:{}", result); - result = md5(result, encodingCharset).toUpperCase(); - return result; - } - - - /** - * 计算MD5值 - * @param value - * @param charset - * @return - */ - public static String md5(String value, String charset) { - MessageDigest md; - try { - byte[] data = value.getBytes(charset); - md = MessageDigest.getInstance("MD5"); - byte[] digestData = md.digest(data); - return toHex(digestData); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return null; - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - return null; - } - } - -``` -### 2. 更多参考:https://docs.jeequan.com/docs/jeepay/payment_api \ No newline at end of file +更多参考:https://docs.jeequan.com/docs/jeepay/payment_api \ No newline at end of file -- Gitee From f633916a351b3cc3619f73745f208122a6878d62 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Wed, 1 Feb 2023 16:29:30 +0800 Subject: [PATCH 15/31] test --- jeepay-manager/src/main/resources/application.yml | 4 ++-- jeepay-payment/src/main/resources/application.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jeepay-manager/src/main/resources/application.yml b/jeepay-manager/src/main/resources/application.yml index 571cd44..d0c7ec8 100644 --- a/jeepay-manager/src/main/resources/application.yml +++ b/jeepay-manager/src/main/resources/application.yml @@ -4,8 +4,8 @@ server: spring: redis: database: 1 #1库:运营平台 #2库:商户系统 #3库:支付网关 - profiles: - active: dev +# profiles: +# active: dev #系统业务参数 isys: diff --git a/jeepay-payment/src/main/resources/application.yml b/jeepay-payment/src/main/resources/application.yml index 56b13eb..5b8bda9 100644 --- a/jeepay-payment/src/main/resources/application.yml +++ b/jeepay-payment/src/main/resources/application.yml @@ -4,5 +4,5 @@ server: spring: redis: database: 3 #1库:运营平台 #2库:商户系统 #3库:支付网关 - profiles: - active: dev \ No newline at end of file +# profiles: +# active: dev \ No newline at end of file -- Gitee From 91066378bd217910115c84ab55f3e967e47ce0e4 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Fri, 3 Feb 2023 16:48:44 +0800 Subject: [PATCH 16/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E6=8B=93=E5=B1=95=E8=A1=A8=E5=92=8C=E8=AE=A2=E5=8D=95=E5=88=86?= =?UTF-8?q?=E6=9E=90=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jeepay/core/entity/PayOrderExtend.java | 232 ++++++++++++++++++ .../core/entity/PayOrderStatistics.java | 92 +++++++ .../service/impl/PayOrderExtendService.java | 19 ++ .../impl/PayOrderStatisticsService.java | 19 ++ .../service/mapper/PayOrderExtendMapper.java | 16 ++ .../service/mapper/PayOrderExtendMapper.xml | 49 ++++ .../mapper/PayOrderStatisticsMapper.java | 16 ++ .../mapper/PayOrderStatisticsMapper.xml | 22 ++ 8 files changed, 465 insertions(+) create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderStatistics.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderExtendService.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderStatisticsService.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.xml diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java new file mode 100644 index 0000000..20344a8 --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java @@ -0,0 +1,232 @@ +package com.jeequan.jeepay.core.entity; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.TableName; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.TableField; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 支付订单表 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-03 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_pay_order_extend") +public class PayOrderExtend implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 支付订单号 + */ + private String payOrderId; + + /** + * 商户号 + */ + private String mchNo; + + /** + * 服务商号 + */ + private String isvNo; + + /** + * 应用ID + */ + private String appId; + + /** + * 商户名称 + */ + private String mchName; + + /** + * 类型: 1-普通商户, 2-特约商户(服务商模式) + */ + private Byte mchType; + + /** + * 商户订单号 + */ + private String mchOrderNo; + + /** + * 支付接口代码 + */ + private String ifCode; + + /** + * 支付方式代码 + */ + private String wayCode; + + /** + * 支付金额,单位分 + */ + private Long amount; + + /** + * 商户手续费费率快照 + */ + private BigDecimal mchFeeRate; + + /** + * 商户手续费,单位分 + */ + private Long mchFeeAmount; + + /** + * 三位货币代码,人民币:cny + */ + private String currency; + + /** + * 支付状态: 0-订单生成, 1-支付中, 2-支付成功, 3-支付失败, 4-已撤销, 5-已退款, 6-订单关闭 + */ + private Byte state; + + /** + * 向下游回调状态, 0-未发送, 1-已发送 + */ + private Byte notifyState; + + /** + * 客户端IP + */ + private String clientIp; + + /** + * 商品标题 + */ + private String subject; + + /** + * 商品描述信息 + */ + private String body; + + /** + * 特定渠道发起额外参数 + */ + private String channelExtra; + + /** + * 渠道用户标识,如微信openId,支付宝账号 + */ + private String channelUser; + + /** + * 渠道订单号 + */ + private String channelOrderNo; + + /** + * 退款状态: 0-未发生实际退款, 1-部分退款, 2-全额退款 + */ + private Byte refundState; + + /** + * 退款次数 + */ + private Integer refundTimes; + + /** + * 退款总金额,单位分 + */ + private Long refundAmount; + + /** + * 订单分账模式:0-该笔订单不允许分账, 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额) + */ + private Byte divisionMode; + + /** + * 订单分账状态:0-未发生分账, 1-等待分账任务处理, 2-分账处理中, 3-分账任务已结束(不体现状态) + */ + private Byte divisionState; + + /** + * 最新分账时间 + */ + private Date divisionLastTime; + + /** + * 渠道支付错误码 + */ + private String errCode; + + /** + * 渠道支付错误描述 + */ + private String errMsg; + + /** + * 人员Id + */ + private String pid; + + /** + * 会议id + */ + @TableField("meetingID") + private String meetingID; + + /** + * 交易类型 + */ + @TableField("dealType") + private String dealType; + + /** + * 部门Id + */ + @TableField("deptId") + private String deptId; + + /** + * 异步通知地址 + */ + private String notifyUrl; + + /** + * 页面跳转地址 + */ + private String returnUrl; + + /** + * 结账状态:0-未结账 1-已结账 + */ + private Byte accountState; + + /** + * 订单失效时间 + */ + private Date expiredTime; + + /** + * 订单支付成功时间 + */ + private Date successTime; + + /** + * 创建时间 + */ + private Date createdAt; + + /** + * 更新时间 + */ + private Date updatedAt; + + +} diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderStatistics.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderStatistics.java new file mode 100644 index 0000000..0a1d7d6 --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderStatistics.java @@ -0,0 +1,92 @@ +package com.jeequan.jeepay.core.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.util.Date; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 订单分析表 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-03 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_pay_order_statistics") +public class PayOrderStatistics implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 订单分析报表主键ID + */ + private String orderStatisticsId; + + /** + * 商户号 + */ + private String mchNo; + + /** + * 应用ID + */ + private String appId; + + /** + * 应用名称 + */ + private String appName; + + /** + * 商户名称 + */ + private String mchName; + + /** + * 组织名称,部门或是入驻企业名称 + */ + private String deptName; + + /** + * 类型: 1-商户, 2-入住企业 + */ + private Byte statisticType; + + /** + * 支付金额,单位分 + */ + private Long amount; + + /** + * 实付金额 + */ + private Long amountInfact; + + /** + * 结账状态, 0-已结账, 1-未结账 + */ + private Byte staticState; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createdAt; + + /** + * 更新时间 + */ + private Date updatedAt; + + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderExtendService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderExtendService.java new file mode 100644 index 0000000..fb2878c --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderExtendService.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.service.impl; + +import com.jeequan.jeepay.core.entity.PayOrderExtend; +import com.jeequan.jeepay.service.mapper.PayOrderExtendMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 支付订单表 服务实现类 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-03 + */ +@Service +public class PayOrderExtendService extends ServiceImpl { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderStatisticsService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderStatisticsService.java new file mode 100644 index 0000000..02eaf80 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderStatisticsService.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.service.impl; + +import com.jeequan.jeepay.core.entity.PayOrderStatistics; +import com.jeequan.jeepay.service.mapper.PayOrderStatisticsMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单分析表 服务实现类 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-03 + */ +@Service +public class PayOrderStatisticsService extends ServiceImpl{ + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.java new file mode 100644 index 0000000..6aea838 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.java @@ -0,0 +1,16 @@ +package com.jeequan.jeepay.service.mapper; + +import com.jeequan.jeepay.core.entity.PayOrderExtend; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 支付订单表 Mapper 接口 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-03 + */ +public interface PayOrderExtendMapper extends BaseMapper { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml new file mode 100644 index 0000000..c43c2db --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.java new file mode 100644 index 0000000..eae4933 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.java @@ -0,0 +1,16 @@ +package com.jeequan.jeepay.service.mapper; + +import com.jeequan.jeepay.core.entity.PayOrderStatistics; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单分析表 Mapper 接口 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-03 + */ +public interface PayOrderStatisticsMapper extends BaseMapper { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.xml new file mode 100644 index 0000000..7799c65 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + -- Gitee From a587bf1c68e41e281c2b290b2b5ea56e537b227b Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Tue, 14 Feb 2023 11:02:25 +0800 Subject: [PATCH 17/31] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=87=B3=E6=8B=93=E5=B1=95=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/jeequan/jeepay/core/aop/Action.java | 16 +++ .../jeequan/jeepay/core/aop/MethodLog.java | 3 +- ...stics.java => OrderStatisticsCompany.java} | 15 +-- .../core/entity/OrderStatisticsDept.java | 77 ++++++++++++ .../jeepay/core/entity/PayOrderExtend.java | 4 +- jeepay-payment/pom.xml | 5 +- .../jeepay/pay/aop/CopyOrderAspect.java | 112 ++++++++++++++++++ .../pay/bootstrap/JeepayPayApplication.java | 6 +- .../impl/OrderStatisticsCompanyService.java | 19 +++ ...e.java => OrderStatisticsDeptService.java} | 10 +- .../jeepay/service/impl/PayOrderService.java | 10 +- .../mapper/OrderStatisticsCompanyMapper.java | 16 +++ ...r.xml => OrderStatisticsCompanyMapper.xml} | 7 +- ...er.java => OrderStatisticsDeptMapper.java} | 8 +- .../mapper/OrderStatisticsDeptMapper.xml | 19 +++ 15 files changed, 297 insertions(+), 30 deletions(-) create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/aop/Action.java rename jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/{PayOrderStatistics.java => OrderStatisticsCompany.java} (84%) create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsCompanyService.java rename jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/{PayOrderStatisticsService.java => OrderStatisticsDeptService.java} (43%) create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java rename jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/{PayOrderStatisticsMapper.xml => OrderStatisticsCompanyMapper.xml} (79%) rename jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/{PayOrderStatisticsMapper.java => OrderStatisticsDeptMapper.java} (44%) create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/aop/Action.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/aop/Action.java new file mode 100644 index 0000000..3f4a0c5 --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/aop/Action.java @@ -0,0 +1,16 @@ +package com.jeequan.jeepay.core.aop; + + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Action { + + String value() default ""; +} \ No newline at end of file diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/aop/MethodLog.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/aop/MethodLog.java index 440cd91..c734c52 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/aop/MethodLog.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/aop/MethodLog.java @@ -24,7 +24,8 @@ import java.lang.annotation.*; * @site https://www.jeequan.com * @date 2021/6/8 18:00 */ -@Target({ ElementType.METHOD, ElementType.TYPE }) + +@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MethodLog { diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderStatistics.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java similarity index 84% rename from jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderStatistics.java rename to jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java index 0a1d7d6..6b27e61 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderStatistics.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java @@ -9,24 +9,24 @@ import lombok.experimental.Accessors; /** *

- * 订单分析表 + * 订单分析主表 *

* * @author [mybatis plus generator] - * @since 2023-02-03 + * @since 2023-02-09 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) -@TableName("t_pay_order_statistics") -public class PayOrderStatistics implements Serializable { +@TableName("t_order_statistics_company") +public class OrderStatisticsCompany implements Serializable { private static final long serialVersionUID=1L; /** * 订单分析报表主键ID */ - private String orderStatisticsId; + private String statisticsCompanyId; /** * 商户号 @@ -83,10 +83,5 @@ public class PayOrderStatistics implements Serializable { */ private Date createdAt; - /** - * 更新时间 - */ - private Date updatedAt; - } diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java new file mode 100644 index 0000000..af1b10f --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java @@ -0,0 +1,77 @@ +package com.jeequan.jeepay.core.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.util.Date; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 订单分析部门表 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-09 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_order_statistics_dept") +public class OrderStatisticsDept implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 订单分析报表主键ID + */ + private String statisticsDeptId; + + /** + * 分析主表Id + */ + private String primaryStatisticsId; + + /** + * 商户号 + */ + private String mchNo; + + /** + * 应用ID + */ + private String appId; + + /** + * 应用名称 + */ + private String appName; + + /** + * 商户名称 + */ + private String mchName; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 类型: 1-商户, 2-入住企业 + */ + private Byte statisticType; + + /** + * 支付金额,单位分 + */ + private Long amount; + + /** + * 创建时间 + */ + private Date createdAt; + + +} diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java index 20344a8..99bf531 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java @@ -178,8 +178,8 @@ public class PayOrderExtend implements Serializable { /** * 会议id */ - @TableField("meetingID") - private String meetingID; + @TableField("businessId") + private String businessId; /** * 交易类型 diff --git a/jeepay-payment/pom.xml b/jeepay-payment/pom.xml index d36c415..55e9cbe 100644 --- a/jeepay-payment/pom.xml +++ b/jeepay-payment/pom.xml @@ -65,7 +65,10 @@ - + + org.springframework.boot + spring-boot-starter-aop + org.springframework.boot diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java new file mode 100644 index 0000000..d78f6fe --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java @@ -0,0 +1,112 @@ +package com.jeequan.jeepay.pay.aop; + +import com.alibaba.fastjson.JSONObject; +import com.jeequan.jeepay.core.aop.Action; +import com.jeequan.jeepay.core.entity.PayOrder; +import com.jeequan.jeepay.core.entity.PayOrderExtend; +import com.jeequan.jeepay.service.impl.PayOrderExtendService; +import com.jeequan.jeepay.service.impl.PayOrderService; +import com.jeequan.jeepay.service.impl.SysLogService; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.*; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import java.lang.reflect.Method; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +@Component +@Aspect +public class CopyOrderAspect { + + @Autowired + private SysLogService sysLogService; + + @Autowired + private PayOrderService payOrderService; + + @Autowired + private PayOrderExtendService payOrderExtendService; + + private static final Logger logger = LoggerFactory.getLogger(CopyOrderAspect.class); + + private final static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10); + + + @Pointcut("@annotation(com.jeequan.jeepay.core.aop.Action)") + public void pointCut() { + } + + @Before("pointCut()") + public void doBeforeController(JoinPoint joinPoint) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + Action action = method.getAnnotation(Action.class); + System.out.println("action名称 " + action.value()); + } + + // 返回后通知:在调用目标方法结束后执行【出现异常,不执行】 + @AfterReturning(value = "pointCut()", returning = "retValue") + public void afterReturning(JoinPoint jp, Object retValue) throws Throwable { + Object[] args = jp.getArgs(); + System.out.println("Aop.afterReturning() 目标方法+" + jp.getSignature().getName() + "返回值:" + retValue); + + String payOrderId = String.valueOf(args[0]); + String channelOrderNo = String.valueOf(args[1]); + String channelUserId = String.valueOf(args[2]); + + scheduledThreadPool.execute(() -> savePayOrderExtend(payOrderId, channelOrderNo, channelUserId)); + } + + private boolean savePayOrderExtend(String payOrderId, String channelOrderNo, String channelUserId) { + PayOrder payOrder = payOrderService.getById(payOrderId); + + PayOrderExtend payOrderExtend = new PayOrderExtend(); + BeanUtils.copyProperties(payOrder, payOrderExtend); + + String extParam = payOrder.getExtParam(); + if (!ObjectUtils.isEmpty(extParam)) { + JSONObject jsonObject = JSONObject.parseObject(extParam); + if (!jsonObject.getString("businessId").isEmpty()) { + payOrderExtend.setBusinessId(jsonObject.getString("businessId")); + } + if (!jsonObject.getString("pid").isEmpty()) { + payOrderExtend.setPid(jsonObject.getString("pid")); + } + if (!jsonObject.getString("dealType").isEmpty()) { + payOrderExtend.setDealType(jsonObject.getString("dealType")); + } + if (!jsonObject.getString("deptId").isEmpty()) { + payOrderExtend.setDeptId(jsonObject.getString("deptId")); + } + } + return payOrderExtendService.save(payOrderExtend); + } + + @Around(value = "pointCut()") + public Object around(ProceedingJoinPoint pjp) throws Throwable { + System.out.println("环绕开始..."); + + Object[] args = pjp.getArgs(); + Object retValue = pjp.proceed();// 执行目标方法 + System.out.println("环绕结束..."); + return retValue; + } + + + @AfterThrowing(pointcut = "pointCut()", throwing = "e") + public void doException(JoinPoint joinPoint, Throwable e) throws Exception { + // final SysLog sysLog = new SysLog(); + // // 基础日志信息 + // sysLog.setOptResInfo(e instanceof BizException ? e.getMessage() : "请求异常"); + // scheduledThreadPool.execute(() -> sysLogService.save(sysLog)); + logger.error("CopyOrderAspect error", e); + } +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/bootstrap/JeepayPayApplication.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/bootstrap/JeepayPayApplication.java index 90090bc..1baa7b9 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/bootstrap/JeepayPayApplication.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/bootstrap/JeepayPayApplication.java @@ -23,11 +23,13 @@ import org.hibernate.validator.HibernateValidator; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.http.MediaType; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.cors.CorsConfiguration; @@ -38,7 +40,6 @@ import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import java.util.Arrays; - /** * @Author terrfly * @Date 2019/11/7 15:19 @@ -47,8 +48,9 @@ import java.util.Arrays; @SpringBootApplication @EnableScheduling @MapperScan("com.jeequan.jeepay.service.mapper") //Mybatis mapper接口路径 -@ComponentScan(basePackages = "com.jeequan.jeepay.*") //由于MainApplication没有在项目根目录, 需要配置basePackages属性使得成功扫描所有Spring组件; +@ComponentScan(basePackages = "com.jeequan.jeepay.*") @Configuration +@EnableAspectJAutoProxy(exposeProxy=true) public class JeepayPayApplication { @Autowired private SystemYmlConfig systemYmlConfig; diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsCompanyService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsCompanyService.java new file mode 100644 index 0000000..089534f --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsCompanyService.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.service.impl; + +import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; +import com.jeequan.jeepay.service.mapper.OrderStatisticsCompanyMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单分析主表 服务实现类 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-09 + */ +@Service +public class OrderStatisticsCompanyService extends ServiceImpl { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderStatisticsService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsDeptService.java similarity index 43% rename from jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderStatisticsService.java rename to jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsDeptService.java index 02eaf80..b4950d5 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderStatisticsService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsDeptService.java @@ -1,19 +1,19 @@ package com.jeequan.jeepay.service.impl; -import com.jeequan.jeepay.core.entity.PayOrderStatistics; -import com.jeequan.jeepay.service.mapper.PayOrderStatisticsMapper; +import com.jeequan.jeepay.core.entity.OrderStatisticsDept; +import com.jeequan.jeepay.service.mapper.OrderStatisticsDeptMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** *

- * 订单分析表 服务实现类 + * 订单分析部门表 服务实现类 *

* * @author [mybatis plus generator] - * @since 2023-02-03 + * @since 2023-02-09 */ @Service -public class PayOrderStatisticsService extends ServiceImpl{ +public class OrderStatisticsDeptService extends ServiceImpl{ } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java index 7f240f3..c848500 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java @@ -24,6 +24,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +//import com.jeequan.jeepay.core.aop.Action; +import com.jeequan.jeepay.core.aop.Action; +import com.jeequan.jeepay.core.aop.MethodLog; import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.entity.IsvInfo; import com.jeequan.jeepay.core.entity.MchInfo; @@ -31,9 +34,11 @@ import com.jeequan.jeepay.core.entity.PayOrder; import com.jeequan.jeepay.core.entity.PayWay; import com.jeequan.jeepay.service.mapper.*; import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.framework.AopContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; + import java.math.BigDecimal; import java.util.*; @@ -73,6 +78,8 @@ public class PayOrderService extends ServiceImpl { } /** 更新订单状态 【支付中】 --》 【支付成功】 **/ + + @Action("下单成功记录") public boolean updateIng2Success(String payOrderId, String channelOrderNo, String channelUserId){ PayOrder updateRecord = new PayOrder(); @@ -118,7 +125,8 @@ public class PayOrderService extends ServiceImpl { if(updateState == PayOrder.STATE_ING){ return true; }else if(updateState == PayOrder.STATE_SUCCESS){ - return updateIng2Success(payOrderId, channelOrderNo, channelUserId); + PayOrderService service = AopContext.currentProxy() != null ? (PayOrderService)AopContext.currentProxy() : this; + return service.updateIng2Success(payOrderId, channelOrderNo, channelUserId); }else if(updateState == PayOrder.STATE_FAIL){ return updateIng2Fail(payOrderId, channelOrderNo, channelUserId, channelErrCode, channelErrMsg); } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java new file mode 100644 index 0000000..58765df --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java @@ -0,0 +1,16 @@ +package com.jeequan.jeepay.service.mapper; + +import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单分析主表 Mapper 接口 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-09 + */ +public interface OrderStatisticsCompanyMapper extends BaseMapper { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml similarity index 79% rename from jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.xml rename to jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml index 7799c65..7bef507 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml @@ -1,10 +1,10 @@ - + - - + + @@ -16,7 +16,6 @@ - diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java similarity index 44% rename from jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.java rename to jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java index eae4933..9290ff1 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderStatisticsMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java @@ -1,16 +1,16 @@ package com.jeequan.jeepay.service.mapper; -import com.jeequan.jeepay.core.entity.PayOrderStatistics; +import com.jeequan.jeepay.core.entity.OrderStatisticsDept; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** *

- * 订单分析表 Mapper 接口 + * 订单分析部门表 Mapper 接口 *

* * @author [mybatis plus generator] - * @since 2023-02-03 + * @since 2023-02-09 */ -public interface PayOrderStatisticsMapper extends BaseMapper { +public interface OrderStatisticsDeptMapper extends BaseMapper { } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml new file mode 100644 index 0000000..f648bca --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + -- Gitee From 4d82e95ace32dc12fd2125ded3f1c6ee0efb675e Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Tue, 14 Feb 2023 17:41:10 +0800 Subject: [PATCH 18/31] =?UTF-8?q?=E5=90=AF=E8=BF=AA=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=80=80=E6=AC=BE=E6=B5=81=E7=A8=8B=E5=B9=B6?= =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E5=85=B6=E9=AA=8C=E8=AF=81=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .../jeepay/core/entity/PayOrderExtend.java | 7 + .../channel/qidipay/QidipayRefundService.java | 199 ++++++++++++++++++ .../AuthHeaderSettingFilter.java | 2 +- .../pay/{config => filter}/CustomFilter.java | 2 +- .../CustomHttpServletRequest.java | 2 +- .../jeepay/pay/filter/RefundInterceptor.java | 74 +++++++ .../pay/{config => web}/WebMvcConfig.java | 14 +- .../service/impl/RefundOrderService.java | 10 +- .../service/mapper/PayOrderExtendMapper.java | 2 + .../service/mapper/PayOrderExtendMapper.xml | 13 ++ 11 files changed, 320 insertions(+), 6 deletions(-) create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayRefundService.java rename jeepay-payment/src/main/java/com/jeequan/jeepay/pay/{config => filter}/AuthHeaderSettingFilter.java (98%) rename jeepay-payment/src/main/java/com/jeequan/jeepay/pay/{config => filter}/CustomFilter.java (95%) rename jeepay-payment/src/main/java/com/jeequan/jeepay/pay/{config => filter}/CustomHttpServletRequest.java (96%) create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/RefundInterceptor.java rename jeepay-payment/src/main/java/com/jeequan/jeepay/pay/{config => web}/WebMvcConfig.java (60%) diff --git a/.gitignore b/.gitignore index f259ac6..36f3937 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ docker/rocketmq/namesrv/ nohup.out .env +/logs/ diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java index 99bf531..19ed32c 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java @@ -1,6 +1,8 @@ package com.jeequan.jeepay.core.entity; import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.util.Date; import com.baomidou.mybatisplus.annotation.TableField; @@ -25,9 +27,14 @@ public class PayOrderExtend implements Serializable { private static final long serialVersionUID=1L; + public static final byte ACCOUNT_STATE_NUN = 0; //未结账 + public static final byte ACCOUNT_STATE_FINISHED = 1; //已结账 + + /** * 支付订单号 */ + @TableId private String payOrderId; /** diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayRefundService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayRefundService.java new file mode 100644 index 0000000..022eed9 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/qidipay/QidipayRefundService.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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 com.jeequan.jeepay.pay.channel.qidipay; + +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSONObject; +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.core.entity.PayOrder; +import com.jeequan.jeepay.core.entity.RefundOrder; +import com.jeequan.jeepay.core.model.params.qidipay.QidipayNormalMchParams; +import com.jeequan.jeepay.core.model.params.xxpay.XxpayNormalMchParams; +import com.jeequan.jeepay.core.utils.JeepayKit; +import com.jeequan.jeepay.pay.channel.AbstractRefundService; +import com.jeequan.jeepay.pay.channel.xxpay.XxpayKit; +import com.jeequan.jeepay.pay.model.MchAppConfigContext; +import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; +import com.jeequan.jeepay.pay.rqrs.refund.RefundOrderRQ; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.TreeMap; + +/* +* 退款接口: 启迪支付 +* +* @author chengzhengwen +* @site https://www.jeequan.com +* @date 2023/02/14 9:38 +*/ +@Service +@Slf4j +public class QidipayRefundService extends AbstractRefundService { + + @Override + public String getIfCode() { + return CS.IF_CODE.QIDIPAY; + } + + @Override + public String preCheck(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder) { + return null; + } + + @Override + public ChannelRetMsg refund(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception { + + + QidipayNormalMchParams params = (QidipayNormalMchParams)configContextQueryService.queryNormalMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), getIfCode()); + + // 构造支付请求参数 + Map paramMap = new TreeMap(); + paramMap.put("mchId", params.getMchId()); //商户ID + paramMap.put("mchOrderNo", refundOrder.getPayOrderId()); //支付订单-商户订单号 + paramMap.put("mchRefundNo", refundOrder.getRefundOrderId()); //商户退款单号 + paramMap.put("amount", refundOrder.getRefundAmount()); //退款金额 + paramMap.put("currency", "cny"); //币种 + paramMap.put("clientIp", refundOrder.getClientIp()); //客户端IP + paramMap.put("device", "web"); //客户端设备 + //如果notifyUrl 不为空表示异步退款,具体退款结果以退款通知为准 + paramMap.put("notifyUrl", getNotifyUrl(refundOrder.getRefundOrderId())); // 异步退款通知 + paramMap.put("remarkInfo", refundOrder.getRefundReason()); // 退款原因 + + // 生成签名 + String sign = XxpayKit.getSign(paramMap, params.getKey()); + paramMap.put("sign", sign); + // 退款地址 + String refundUrl = XxpayKit.getRefundUrl(params.getPayUrl())+ "?" + JeepayKit.genUrlParams(paramMap); + String resStr = "test"; + try { + log.info("发起退款[{}]参数:{}", getIfCode(), refundUrl); + //resStr = HttpUtil.createPost(refundUrl).timeout(60 * 1000).execute().body(); + log.info("发起退款[{}]结果:{}", getIfCode(), resStr); + } catch (Exception e) { + log.error("http error", e); + } + + ChannelRetMsg channelRetMsg = new ChannelRetMsg(); + // 默认退款中状态 + channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING); + +// if(StringUtils.isEmpty(resStr)) { +// channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); +// channelRetMsg.setChannelErrCode(""); +// channelRetMsg.setChannelErrMsg("请求"+getIfCode()+"接口异常"); +// return null; +// } +// +// JSONObject resObj = JSONObject.parseObject(resStr); +// if(!"0".equals(resObj.getString("retCode"))){ +// String retMsg = resObj.getString("retMsg"); +// channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); +// channelRetMsg.setChannelErrCode(""); +// channelRetMsg.setChannelErrMsg(retMsg); +// return null; +// } + + // 验证响应数据签名 +// String checkSign = resObj.getString("sign"); +// resObj.remove("sign"); +// if(!checkSign.equals(XxpayKit.getSign(resObj, params.getKey()))) { +// channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); +// return null; +// } + + // 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败 +// String status = resObj.getString("status"); +// if("2".equals(status)) { +// channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS); +// }else if("3".equals(status)) { +// channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); +// channelRetMsg.setChannelErrMsg(resObj.getString("retMsg")); +// } + + //没用实际与支付打通,暂设为成功 + if(channelRetMsg.getChannelState()!=ChannelRetMsg.ChannelState.CONFIRM_SUCCESS){ + channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS); + } + return channelRetMsg; + + } + + @Override + public ChannelRetMsg query(RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) throws Exception { + + QidipayNormalMchParams params = (QidipayNormalMchParams)configContextQueryService.queryNormalMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), getIfCode()); + + // 构造支付请求参数 + Map paramMap = new TreeMap(); + paramMap.put("mchId", params.getMchId()); //商户ID + paramMap.put("mchRefundNo", refundOrder.getRefundOrderId()); //商户退款单号 + + // 生成签名 + String sign = XxpayKit.getSign(paramMap, params.getKey()); + paramMap.put("sign", sign); + // 退款查询地址 + String queryRefundOrderUrl = XxpayKit.getQueryRefundOrderUrl(params.getPayUrl())+ "?" + JeepayKit.genUrlParams(paramMap); + String resStr = ""; + try { + log.info("查询退款[{}]参数:{}", getIfCode(), queryRefundOrderUrl); + //resStr = HttpUtil.createPost(queryRefundOrderUrl).timeout(60 * 1000).execute().body(); + log.info("查询退款[{}]结果:{}", getIfCode(), resStr); + } catch (Exception e) { + log.error("http error", e); + } + + ChannelRetMsg channelRetMsg = new ChannelRetMsg(); + // 默认退款中状态 + channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING); + + if(StringUtils.isEmpty(resStr)) { + return null; + } + + JSONObject resObj = JSONObject.parseObject(resStr); + if(!"0".equals(resObj.getString("retCode"))){ + return null; + } + + // 验证响应数据签名 + String checkSign = resObj.getString("sign"); + resObj.remove("sign"); + if(!checkSign.equals(XxpayKit.getSign(resObj, params.getKey()))) { + channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); + return null; + } + + // 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败 + String status = resObj.getString("status"); + if("2".equals(status)) { + channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS); + }else if("3".equals(status)) { + channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); + channelRetMsg.setChannelErrMsg(resObj.getString("retMsg")); + } + + ////没用实际与支付打通,暂设为成功 + if(channelRetMsg.getChannelState()!=ChannelRetMsg.ChannelState.CONFIRM_SUCCESS){ + channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS); + } + return channelRetMsg; + + } + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/AuthHeaderSettingFilter.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/AuthHeaderSettingFilter.java similarity index 98% rename from jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/AuthHeaderSettingFilter.java rename to jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/AuthHeaderSettingFilter.java index 5b18aa2..6472918 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/AuthHeaderSettingFilter.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/AuthHeaderSettingFilter.java @@ -1,4 +1,4 @@ -package com.jeequan.jeepay.pay.config; +package com.jeequan.jeepay.pay.filter; import org.apache.tomcat.util.http.MimeHeaders; diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomFilter.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/CustomFilter.java similarity index 95% rename from jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomFilter.java rename to jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/CustomFilter.java index f22a535..1342cb4 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomFilter.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/CustomFilter.java @@ -1,4 +1,4 @@ -package com.jeequan.jeepay.pay.config; +package com.jeequan.jeepay.pay.filter; import org.springframework.stereotype.Component; diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomHttpServletRequest.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/CustomHttpServletRequest.java similarity index 96% rename from jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomHttpServletRequest.java rename to jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/CustomHttpServletRequest.java index cda5c0c..af42839 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/CustomHttpServletRequest.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/CustomHttpServletRequest.java @@ -1,4 +1,4 @@ -package com.jeequan.jeepay.pay.config; +package com.jeequan.jeepay.pay.filter; import javax.servlet.http.HttpServletRequest; diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/RefundInterceptor.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/RefundInterceptor.java new file mode 100644 index 0000000..15ee4a5 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/RefundInterceptor.java @@ -0,0 +1,74 @@ +package com.jeequan.jeepay.pay.filter; + +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jeequan.jeepay.core.beans.RequestKitBean; +import com.jeequan.jeepay.core.entity.PayOrderExtend; +import com.jeequan.jeepay.core.model.ApiRes; +import com.jeequan.jeepay.service.impl.PayOrderExtendService; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.ObjectUtils; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * 退单拦截器类 + * 实现HandlerInterceptor接口 + */ +public class RefundInterceptor implements HandlerInterceptor { + + @Autowired + private PayOrderExtendService payOrderExtendService; + + @Autowired + private RequestKitBean requestKitBean; + + /** + * 访问控制器方法前执行 + */ + @Override + @SneakyThrows + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + if (request.getRequestURI().contains("/api/refund/refundOrder") == true) { + JSONObject jsonObject = requestKitBean.getReqParamJSON(); + if (ObjectUtils.isEmpty(jsonObject) || ObjectUtils.isEmpty(jsonObject.getString("payOrderId"))) { + return false; + } + String payOrderId = jsonObject.getString("payOrderId"); + PayOrderExtend orderExtend = payOrderExtendService.getById(payOrderId); + if (orderExtend.getAccountState().equals(PayOrderExtend.ACCOUNT_STATE_FINISHED)) { + ApiRes res = ApiRes.customFail("退单失败:因为该订单已完成结算,如有必要请线下人工操作!"); + returnJson(res, response); + return false; + } + return true; + } else { + return false; + } + } + + + /** + * 返回客户端数据 + */ + private void returnJson(ApiRes res, HttpServletResponse response) throws Exception { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json;charset=utf-8"); + + ObjectMapper objectMapper = new ObjectMapper(); + try { + response.getWriter().println(objectMapper.writeValueAsString(res)); + + } catch (IOException e) { + throw e; + } + } + + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/WebMvcConfig.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/web/WebMvcConfig.java similarity index 60% rename from jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/WebMvcConfig.java rename to jeepay-payment/src/main/java/com/jeequan/jeepay/pay/web/WebMvcConfig.java index 514f7ee..43c4f2e 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/config/WebMvcConfig.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/web/WebMvcConfig.java @@ -1,8 +1,11 @@ -package com.jeequan.jeepay.pay.config; +package com.jeequan.jeepay.pay.web; +import com.jeequan.jeepay.pay.filter.CustomFilter; +import com.jeequan.jeepay.pay.filter.RefundInterceptor; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; @@ -21,4 +24,13 @@ public class WebMvcConfig implements WebMvcConfigurer { registrationBean.setOrder(0); return registrationBean; } + + @Bean + public RefundInterceptor myInterceptor(){ + return new RefundInterceptor(); + } + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(myInterceptor()).addPathPatterns("/api/refund/refundOrder"); + } } \ No newline at end of file diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java index f87a3ac..d27dbdf 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java @@ -22,6 +22,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jeequan.jeepay.core.entity.RefundOrder; import com.jeequan.jeepay.core.exception.BizException; +import com.jeequan.jeepay.service.mapper.PayOrderExtendMapper; import com.jeequan.jeepay.service.mapper.PayOrderMapper; import com.jeequan.jeepay.service.mapper.RefundOrderMapper; import org.apache.commons.lang3.StringUtils; @@ -45,6 +46,9 @@ public class RefundOrderService extends ServiceImpl pageList(IPage iPage, LambdaQueryWrapper wrapper, RefundOrder refundOrder, JSONObject paramJSON) { if (StringUtils.isNotEmpty(refundOrder.getRefundOrderId())) { wrapper.eq(RefundOrder::getRefundOrderId, refundOrder.getRefundOrderId()); diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.java index 6aea838..038816e 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.java @@ -2,6 +2,7 @@ package com.jeequan.jeepay.service.mapper; import com.jeequan.jeepay.core.entity.PayOrderExtend; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; /** *

@@ -13,4 +14,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface PayOrderExtendMapper extends BaseMapper { + int updateRefundAmountAndCount(@Param("payOrderId") String payOrderId, @Param("currentRefundAmount") Long currentRefundAmount); } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml index c43c2db..3cc4adb 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml @@ -46,4 +46,17 @@ + + + update t_pay_order_extend + set refund_times = refund_times + 1, + refund_state = CASE WHEN refund_amount + #{currentRefundAmount} >= amount THEN 2 ELSE 1 END, + `state` = CASE WHEN refund_state = 2 THEN 5 ELSE 2 END, + refund_amount = refund_amount + #{currentRefundAmount} + where + pay_order_id = #{payOrderId} and `state` = 2 + and refund_amount + #{currentRefundAmount} <= amount + and refund_state in (0, 1) + + -- Gitee From 03148e1bfd1950307fb84aafc902457af944349c Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Thu, 16 Feb 2023 11:01:17 +0800 Subject: [PATCH 19/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=88=86=E6=9E=90=E7=9B=B8=E5=85=B3=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sql/init.sql | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/docs/sql/init.sql b/docs/sql/init.sql index bc97b36..7561de2 100644 --- a/docs/sql/init.sql +++ b/docs/sql/init.sql @@ -476,6 +476,89 @@ CREATE TABLE `t_pay_order_division_record` ( ) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COMMENT='分账记录表'; +DROP TABLE IF EXISTS `t_order_statistics_company`; +CREATE TABLE `t_order_statistics_company` ( + `statistics_company_id` varchar(30) NOT NULL COMMENT '订单分析报表主键ID', + `mch_no` varchar(64) NOT NULL COMMENT '商户号', + `app_id` varchar(64) NOT NULL COMMENT '应用ID', + `app_name` varchar(64) NOT NULL COMMENT '应用名称', + `mch_name` varchar(30) NOT NULL COMMENT '商户名称', + `dept_name` varchar(100) NOT NULL COMMENT '组织名称,部门或是入驻企业名称', + `statistic_type` tinyint NOT NULL COMMENT '类型: 1-商户, 2-入住企业', + `amount` bigint NOT NULL COMMENT '支付金额,单位分', + `amount_infact` bigint NOT NULL DEFAULT '0' COMMENT '实付金额', + `static_state` tinyint NOT NULL DEFAULT '0' COMMENT '结账状态, 0-已结账, 1-未结账', + `remark` varchar(512) NOT NULL COMMENT '备注', + `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + PRIMARY KEY (`statistics_company_id`), + KEY `created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单分析主表'; + + +DROP TABLE IF EXISTS `t_pay_order_extend`; +CREATE TABLE `t_pay_order_extend` ( + `pay_order_id` varchar(30) NOT NULL COMMENT '支付订单号', + `mch_no` varchar(64) NOT NULL COMMENT '商户号', + `isv_no` varchar(64) DEFAULT NULL COMMENT '服务商号', + `app_id` varchar(64) NOT NULL COMMENT '应用ID', + `mch_name` varchar(30) NOT NULL COMMENT '商户名称', + `mch_type` tinyint NOT NULL COMMENT '类型: 1-普通商户, 2-特约商户(服务商模式)', + `mch_order_no` varchar(64) NOT NULL COMMENT '商户订单号', + `if_code` varchar(20) DEFAULT NULL COMMENT '支付接口代码', + `way_code` varchar(20) NOT NULL COMMENT '支付方式代码', + `amount` bigint NOT NULL COMMENT '支付金额,单位分', + `mch_fee_rate` decimal(20,6) NOT NULL COMMENT '商户手续费费率快照', + `mch_fee_amount` bigint NOT NULL COMMENT '商户手续费,单位分', + `currency` varchar(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny', + `state` tinyint NOT NULL DEFAULT '0' COMMENT '支付状态: 0-订单生成, 1-支付中, 2-支付成功, 3-支付失败, 4-已撤销, 5-已退款, 6-订单关闭', + `notify_state` tinyint NOT NULL DEFAULT '0' COMMENT '向下游回调状态, 0-未发送, 1-已发送', + `client_ip` varchar(32) DEFAULT NULL COMMENT '客户端IP', + `subject` varchar(64) NOT NULL COMMENT '商品标题', + `body` varchar(256) NOT NULL COMMENT '商品描述信息', + `channel_extra` varchar(512) DEFAULT NULL COMMENT '特定渠道发起额外参数', + `channel_user` varchar(64) DEFAULT NULL COMMENT '渠道用户标识,如微信openId,支付宝账号', + `channel_order_no` varchar(64) DEFAULT NULL COMMENT '渠道订单号', + `refund_state` tinyint NOT NULL DEFAULT '0' COMMENT '退款状态: 0-未发生实际退款, 1-部分退款, 2-全额退款', + `refund_times` int NOT NULL DEFAULT '0' COMMENT '退款次数', + `refund_amount` bigint NOT NULL DEFAULT '0' COMMENT '退款总金额,单位分', + `division_mode` tinyint DEFAULT '0' COMMENT '订单分账模式:0-该笔订单不允许分账, 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额)', + `division_state` tinyint DEFAULT '0' COMMENT '订单分账状态:0-未发生分账, 1-等待分账任务处理, 2-分账处理中, 3-分账任务已结束(不体现状态)', + `division_last_time` datetime DEFAULT NULL COMMENT '最新分账时间', + `err_code` varchar(128) DEFAULT NULL COMMENT '渠道支付错误码', + `err_msg` varchar(256) DEFAULT NULL COMMENT '渠道支付错误描述', + `pid` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '人员Id', + `businessId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '会议id', + `dealType` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '交易类型', + `deptId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '部门Id', + `notify_url` varchar(128) NOT NULL DEFAULT '' COMMENT '异步通知地址', + `return_url` varchar(128) DEFAULT '' COMMENT '页面跳转地址', + `account_state` tinyint DEFAULT '0' COMMENT '结账状态:0-未结账 1-已结账', + `expired_time` datetime DEFAULT NULL COMMENT '订单失效时间', + `success_time` datetime DEFAULT NULL COMMENT '订单支付成功时间', + `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + `updated_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间', + PRIMARY KEY (`pay_order_id`), + UNIQUE KEY `Uni_MchNo_MchOrderNo` (`mch_no`,`mch_order_no`), + KEY `created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付订单表'; + + +DROP TABLE IF EXISTS `t_order_statistics_dept`; +CREATE TABLE `t_order_statistics_dept` ( + `statistics_dept_id` varchar(30) NOT NULL COMMENT '订单分析报表主键ID', + `primary_statistics_id` varchar(64) NOT NULL COMMENT '分析主表Id', + `mch_no` varchar(64) NOT NULL COMMENT '商户号', + `app_id` varchar(64) NOT NULL COMMENT '应用ID', + `app_name` varchar(64) NOT NULL COMMENT '应用名称', + `mch_name` varchar(30) NOT NULL COMMENT '商户名称', + `dept_name` varchar(100) NOT NULL COMMENT '部门名称', + `statistic_type` tinyint NOT NULL COMMENT '类型: 1-商户, 2-入住企业', + `amount` bigint NOT NULL COMMENT '支付金额,单位分', + `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + PRIMARY KEY (`statistics_dept_id`), + KEY `created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单分析部门表'; + ##### ↑↑↑↑↑↑↑↑↑↑ 表结构DDL ↑↑↑↑↑↑↑↑↑↑ ##### -- Gitee From ba8fbbe652fdf5e314f86a88319d33632cafd909 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Fri, 17 Feb 2023 17:09:31 +0800 Subject: [PATCH 20/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=88=86=E6=9E=90=E7=9B=B8=E5=85=B3=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sql/init.sql | 112 +++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 57 deletions(-) diff --git a/docs/sql/init.sql b/docs/sql/init.sql index 7561de2..a705a93 100644 --- a/docs/sql/init.sql +++ b/docs/sql/init.sql @@ -476,89 +476,87 @@ CREATE TABLE `t_pay_order_division_record` ( ) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COMMENT='分账记录表'; +-- +-- 订单拓展表`t_pay_order_extend` +-- + +DROP TABLE IF EXISTS `t_pay_order_extend`; +CREATE TABLE `t_pay_order_extend` ( + `pay_order_id` varchar(30) NOT NULL COMMENT '支付订单号,关联主表', + `pid` varchar(36) DEFAULT '' COMMENT '人员Id', + `businessId` varchar(36) DEFAULT '' COMMENT '业务id', + `dealType` varchar(30) DEFAULT '' COMMENT '交易类型:PERSONAL-个人支付,DEPARTMENTAL-部门支付', + `deptId` varchar(36) DEFAULT '' COMMENT '部门Id', + `account_state` tinyint DEFAULT '0' COMMENT '结账状态:0-未结账 1-已结账', + `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + PRIMARY KEY (`pay_order_id`), + KEY `created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单拓展表'; + + +-- +-- 企业账单分析表 `t_order_statistics_company` +-- + DROP TABLE IF EXISTS `t_order_statistics_company`; CREATE TABLE `t_order_statistics_company` ( - `statistics_company_id` varchar(30) NOT NULL COMMENT '订单分析报表主键ID', + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', `mch_no` varchar(64) NOT NULL COMMENT '商户号', `app_id` varchar(64) NOT NULL COMMENT '应用ID', `app_name` varchar(64) NOT NULL COMMENT '应用名称', `mch_name` varchar(30) NOT NULL COMMENT '商户名称', - `dept_name` varchar(100) NOT NULL COMMENT '组织名称,部门或是入驻企业名称', - `statistic_type` tinyint NOT NULL COMMENT '类型: 1-商户, 2-入住企业', - `amount` bigint NOT NULL COMMENT '支付金额,单位分', + `amount` bigint NOT NULL COMMENT '企业账单金额,单位分', + `dept_name` varchar(100) NOT NULL COMMENT '组织名称:企业名称或者部门名称', `amount_infact` bigint NOT NULL DEFAULT '0' COMMENT '实付金额', + `analyse_id` bigint DEFAULT NULL COMMENT '报表分析标识', `static_state` tinyint NOT NULL DEFAULT '0' COMMENT '结账状态, 0-已结账, 1-未结账', `remark` varchar(512) NOT NULL COMMENT '备注', `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', - PRIMARY KEY (`statistics_company_id`), + PRIMARY KEY (`id`), KEY `created_at` (`created_at`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单分析主表'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='企业账单分析表'; -DROP TABLE IF EXISTS `t_pay_order_extend`; -CREATE TABLE `t_pay_order_extend` ( - `pay_order_id` varchar(30) NOT NULL COMMENT '支付订单号', +-- +-- 部门账单分析表 `t_order_statistics_dept` +-- + +DROP TABLE IF EXISTS `t_order_statistics_dept`; +CREATE TABLE `t_order_statistics_dept` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', + `analyse_id` bigint NOT NULL COMMENT '企业分析表标识符', `mch_no` varchar(64) NOT NULL COMMENT '商户号', - `isv_no` varchar(64) DEFAULT NULL COMMENT '服务商号', `app_id` varchar(64) NOT NULL COMMENT '应用ID', + `app_name` varchar(64) NOT NULL COMMENT '应用名称', `mch_name` varchar(30) NOT NULL COMMENT '商户名称', - `mch_type` tinyint NOT NULL COMMENT '类型: 1-普通商户, 2-特约商户(服务商模式)', - `mch_order_no` varchar(64) NOT NULL COMMENT '商户订单号', - `if_code` varchar(20) DEFAULT NULL COMMENT '支付接口代码', - `way_code` varchar(20) NOT NULL COMMENT '支付方式代码', - `amount` bigint NOT NULL COMMENT '支付金额,单位分', - `mch_fee_rate` decimal(20,6) NOT NULL COMMENT '商户手续费费率快照', - `mch_fee_amount` bigint NOT NULL COMMENT '商户手续费,单位分', - `currency` varchar(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny', - `state` tinyint NOT NULL DEFAULT '0' COMMENT '支付状态: 0-订单生成, 1-支付中, 2-支付成功, 3-支付失败, 4-已撤销, 5-已退款, 6-订单关闭', - `notify_state` tinyint NOT NULL DEFAULT '0' COMMENT '向下游回调状态, 0-未发送, 1-已发送', - `client_ip` varchar(32) DEFAULT NULL COMMENT '客户端IP', - `subject` varchar(64) NOT NULL COMMENT '商品标题', - `body` varchar(256) NOT NULL COMMENT '商品描述信息', - `channel_extra` varchar(512) DEFAULT NULL COMMENT '特定渠道发起额外参数', - `channel_user` varchar(64) DEFAULT NULL COMMENT '渠道用户标识,如微信openId,支付宝账号', - `channel_order_no` varchar(64) DEFAULT NULL COMMENT '渠道订单号', - `refund_state` tinyint NOT NULL DEFAULT '0' COMMENT '退款状态: 0-未发生实际退款, 1-部分退款, 2-全额退款', - `refund_times` int NOT NULL DEFAULT '0' COMMENT '退款次数', - `refund_amount` bigint NOT NULL DEFAULT '0' COMMENT '退款总金额,单位分', - `division_mode` tinyint DEFAULT '0' COMMENT '订单分账模式:0-该笔订单不允许分账, 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额)', - `division_state` tinyint DEFAULT '0' COMMENT '订单分账状态:0-未发生分账, 1-等待分账任务处理, 2-分账处理中, 3-分账任务已结束(不体现状态)', - `division_last_time` datetime DEFAULT NULL COMMENT '最新分账时间', - `err_code` varchar(128) DEFAULT NULL COMMENT '渠道支付错误码', - `err_msg` varchar(256) DEFAULT NULL COMMENT '渠道支付错误描述', - `pid` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '人员Id', - `businessId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '会议id', - `dealType` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '交易类型', - `deptId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '部门Id', - `notify_url` varchar(128) NOT NULL DEFAULT '' COMMENT '异步通知地址', - `return_url` varchar(128) DEFAULT '' COMMENT '页面跳转地址', - `account_state` tinyint DEFAULT '0' COMMENT '结账状态:0-未结账 1-已结账', - `expired_time` datetime DEFAULT NULL COMMENT '订单失效时间', - `success_time` datetime DEFAULT NULL COMMENT '订单支付成功时间', + `dept_name` varchar(100) NOT NULL COMMENT '部门名称', + `amount` bigint NOT NULL COMMENT '部门账单金额,单位分', `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', - `updated_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间', - PRIMARY KEY (`pay_order_id`), - UNIQUE KEY `Uni_MchNo_MchOrderNo` (`mch_no`,`mch_order_no`), + PRIMARY KEY (`id`), KEY `created_at` (`created_at`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付订单表'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='部门账单分析表'; -DROP TABLE IF EXISTS `t_order_statistics_dept`; -CREATE TABLE `t_order_statistics_dept` ( - `statistics_dept_id` varchar(30) NOT NULL COMMENT '订单分析报表主键ID', - `primary_statistics_id` varchar(64) NOT NULL COMMENT '分析主表Id', +-- +-- 商户订单分析表 `t_order_statistics_merchant` +-- + +DROP TABLE IF EXISTS `t_order_statistics_merchant`; +CREATE TABLE `t_order_statistics_merchant` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', `mch_no` varchar(64) NOT NULL COMMENT '商户号', `app_id` varchar(64) NOT NULL COMMENT '应用ID', `app_name` varchar(64) NOT NULL COMMENT '应用名称', `mch_name` varchar(30) NOT NULL COMMENT '商户名称', - `dept_name` varchar(100) NOT NULL COMMENT '部门名称', - `statistic_type` tinyint NOT NULL COMMENT '类型: 1-商户, 2-入住企业', - `amount` bigint NOT NULL COMMENT '支付金额,单位分', + `amount` bigint NOT NULL COMMENT '商户订单总额,单位分', + `amount_infact` bigint NOT NULL DEFAULT '0' COMMENT '实际结算金额', + `analyse_id` bigint DEFAULT NULL COMMENT '报表分析标识', + `static_state` tinyint NOT NULL DEFAULT '0' COMMENT '结账状态, 0-已结账, 1-未结账', + `remark` varchar(512) NOT NULL COMMENT '备注', `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', - PRIMARY KEY (`statistics_dept_id`), + PRIMARY KEY (`id`), KEY `created_at` (`created_at`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单分析部门表'; - +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商户订单分析表'; ##### ↑↑↑↑↑↑↑↑↑↑ 表结构DDL ↑↑↑↑↑↑↑↑↑↑ ##### -- Gitee From 5203a2aa0b884836a673e8ffa16b904a261961e1 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Fri, 17 Feb 2023 17:48:58 +0800 Subject: [PATCH 21/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=88=86=E6=9E=90=E7=9B=B8=E5=85=B3=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/entity/OrderStatisticsCompany.java | 32 +-- .../core/entity/OrderStatisticsDept.java | 27 ++- .../core/entity/OrderStatisticsMerchant.java | 85 ++++++++ .../jeepay/core/entity/PayOrderExtend.java | 190 +----------------- .../payorder/AbstractPayOrderController.java | 6 +- .../impl/OrderStatisticsCompanyService.java | 2 +- .../impl/OrderStatisticsDeptService.java | 2 +- .../impl/OrderStatisticsMerchantService.java | 19 ++ .../jeepay/service/impl/PayOrderService.java | 7 +- .../mapper/OrderStatisticsCompanyMapper.java | 4 +- .../mapper/OrderStatisticsCompanyMapper.xml | 6 +- .../mapper/OrderStatisticsDeptMapper.java | 4 +- .../mapper/OrderStatisticsDeptMapper.xml | 5 +- .../mapper/OrderStatisticsMerchantMapper.java | 16 ++ .../mapper/OrderStatisticsMerchantMapper.xml | 20 ++ .../service/mapper/PayOrderExtendMapper.xml | 35 +--- 16 files changed, 202 insertions(+), 258 deletions(-) create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsMerchant.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsMerchantService.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java index 6b27e61..4887956 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java @@ -1,19 +1,22 @@ package com.jeequan.jeepay.core.entity; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import java.util.Date; -import java.io.Serializable; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.util.Date; + /** *

* 订单分析主表 *

* * @author [mybatis plus generator] - * @since 2023-02-09 + * @since 2023-02-17 */ @Data @EqualsAndHashCode(callSuper = false) @@ -24,9 +27,10 @@ public class OrderStatisticsCompany implements Serializable { private static final long serialVersionUID=1L; /** - * 订单分析报表主键ID + * ID */ - private String statisticsCompanyId; + @TableId(value = "id", type = IdType.AUTO) + private Long id; /** * 商户号 @@ -49,24 +53,24 @@ public class OrderStatisticsCompany implements Serializable { private String mchName; /** - * 组织名称,部门或是入驻企业名称 + * 企业账单金额,单位分 */ - private String deptName; + private Long amount; /** - * 类型: 1-商户, 2-入住企业 + * 组织名称:企业名称或者部门名称 */ - private Byte statisticType; + private String deptName; /** - * 支付金额,单位分 + * 实付金额 */ - private Long amount; + private Long amountInfact; /** - * 实付金额 + * 报表分析标识 */ - private Long amountInfact; + private Long analyseId; /** * 结账状态, 0-已结账, 1-未结账 @@ -84,4 +88,4 @@ public class OrderStatisticsCompany implements Serializable { private Date createdAt; -} +} \ No newline at end of file diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java index af1b10f..b157e4b 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java @@ -1,19 +1,22 @@ package com.jeequan.jeepay.core.entity; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import java.util.Date; -import java.io.Serializable; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.util.Date; + /** *

* 订单分析部门表 *

* * @author [mybatis plus generator] - * @since 2023-02-09 + * @since 2023-02-17 */ @Data @EqualsAndHashCode(callSuper = false) @@ -24,14 +27,15 @@ public class OrderStatisticsDept implements Serializable { private static final long serialVersionUID=1L; /** - * 订单分析报表主键ID + * ID */ - private String statisticsDeptId; + @TableId(value = "id", type = IdType.AUTO) + private Long id; /** - * 分析主表Id + * 主表分析标识符 */ - private String primaryStatisticsId; + private Long analyseId; /** * 商户号 @@ -59,12 +63,7 @@ public class OrderStatisticsDept implements Serializable { private String deptName; /** - * 类型: 1-商户, 2-入住企业 - */ - private Byte statisticType; - - /** - * 支付金额,单位分 + * 部门账单金额,单位分 */ private Long amount; @@ -74,4 +73,4 @@ public class OrderStatisticsDept implements Serializable { private Date createdAt; -} +} \ No newline at end of file diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsMerchant.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsMerchant.java new file mode 100644 index 0000000..482e687 --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsMerchant.java @@ -0,0 +1,85 @@ +package com.jeequan.jeepay.core.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 订单分析主表 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_order_statistics_merchant") +public class OrderStatisticsMerchant implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 商户号 + */ + private String mchNo; + + /** + * 应用ID + */ + private String appId; + + /** + * 应用名称 + */ + private String appName; + + /** + * 商户名称 + */ + private String mchName; + + /** + * 商户账单金额,单位分 + */ + private Long amount; + + /** + * 实际结算金额 + */ + private Long amountInfact; + + /** + * 报表分析标识 + */ + private Long analyseId; + + /** + * 结账状态, 0-已结账, 1-未结账 + */ + private Byte staticState; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createdAt; + + +} diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java index 19ed32c..730de25 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/PayOrderExtend.java @@ -1,23 +1,21 @@ package com.jeequan.jeepay.core.entity; -import java.math.BigDecimal; - -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import java.util.Date; import com.baomidou.mybatisplus.annotation.TableField; -import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.util.Date; + /** *

- * 支付订单表 + * 支付订单拓展表 *

* * @author [mybatis plus generator] - * @since 2023-02-03 + * @since 2023-02-17 */ @Data @EqualsAndHashCode(callSuper = false) @@ -30,166 +28,24 @@ public class PayOrderExtend implements Serializable { public static final byte ACCOUNT_STATE_NUN = 0; //未结账 public static final byte ACCOUNT_STATE_FINISHED = 1; //已结账 - /** - * 支付订单号 + * 支付订单号,关联主表 */ - @TableId private String payOrderId; - /** - * 商户号 - */ - private String mchNo; - - /** - * 服务商号 - */ - private String isvNo; - - /** - * 应用ID - */ - private String appId; - - /** - * 商户名称 - */ - private String mchName; - - /** - * 类型: 1-普通商户, 2-特约商户(服务商模式) - */ - private Byte mchType; - - /** - * 商户订单号 - */ - private String mchOrderNo; - - /** - * 支付接口代码 - */ - private String ifCode; - - /** - * 支付方式代码 - */ - private String wayCode; - - /** - * 支付金额,单位分 - */ - private Long amount; - - /** - * 商户手续费费率快照 - */ - private BigDecimal mchFeeRate; - - /** - * 商户手续费,单位分 - */ - private Long mchFeeAmount; - - /** - * 三位货币代码,人民币:cny - */ - private String currency; - - /** - * 支付状态: 0-订单生成, 1-支付中, 2-支付成功, 3-支付失败, 4-已撤销, 5-已退款, 6-订单关闭 - */ - private Byte state; - - /** - * 向下游回调状态, 0-未发送, 1-已发送 - */ - private Byte notifyState; - - /** - * 客户端IP - */ - private String clientIp; - - /** - * 商品标题 - */ - private String subject; - - /** - * 商品描述信息 - */ - private String body; - - /** - * 特定渠道发起额外参数 - */ - private String channelExtra; - - /** - * 渠道用户标识,如微信openId,支付宝账号 - */ - private String channelUser; - - /** - * 渠道订单号 - */ - private String channelOrderNo; - - /** - * 退款状态: 0-未发生实际退款, 1-部分退款, 2-全额退款 - */ - private Byte refundState; - - /** - * 退款次数 - */ - private Integer refundTimes; - - /** - * 退款总金额,单位分 - */ - private Long refundAmount; - - /** - * 订单分账模式:0-该笔订单不允许分账, 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额) - */ - private Byte divisionMode; - - /** - * 订单分账状态:0-未发生分账, 1-等待分账任务处理, 2-分账处理中, 3-分账任务已结束(不体现状态) - */ - private Byte divisionState; - - /** - * 最新分账时间 - */ - private Date divisionLastTime; - - /** - * 渠道支付错误码 - */ - private String errCode; - - /** - * 渠道支付错误描述 - */ - private String errMsg; - /** * 人员Id */ private String pid; /** - * 会议id + * 业务id */ @TableField("businessId") private String businessId; /** - * 交易类型 + * 交易类型:PERSONAL-个人支付,DEPARTMENTAL-部门支付 */ @TableField("dealType") private String dealType; @@ -200,40 +56,14 @@ public class PayOrderExtend implements Serializable { @TableField("deptId") private String deptId; - /** - * 异步通知地址 - */ - private String notifyUrl; - - /** - * 页面跳转地址 - */ - private String returnUrl; - /** * 结账状态:0-未结账 1-已结账 */ private Byte accountState; - /** - * 订单失效时间 - */ - private Date expiredTime; - - /** - * 订单支付成功时间 - */ - private Date successTime; - /** * 创建时间 */ private Date createdAt; - /** - * 更新时间 - */ - private Date updatedAt; - - -} +} \ No newline at end of file diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/payorder/AbstractPayOrderController.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/payorder/AbstractPayOrderController.java index e1ca30c..8330a91 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/payorder/AbstractPayOrderController.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/payorder/AbstractPayOrderController.java @@ -137,7 +137,8 @@ public abstract class AbstractPayOrderController extends ApiController { payOrder = genPayOrder(bizRQ, mchInfo, mchApp, null, null); String payOrderId = payOrder.getPayOrderId(); //订单入库 订单状态: 生成状态 此时没有和任何上游渠道产生交互。 - payOrderService.save(payOrder); + //payOrderService.save(payOrder); + payOrderService.initOrder(payOrder); QrCashierOrderRS qrCashierOrderRS = new QrCashierOrderRS(); QrCashierOrderRQ qrCashierOrderRQ = (QrCashierOrderRQ)bizRQ; @@ -184,7 +185,8 @@ public abstract class AbstractPayOrderController extends ApiController { if(isNewOrder){ //订单入库 订单状态: 生成状态 此时没有和任何上游渠道产生交互。 - payOrderService.save(payOrder); + //payOrderService.save(payOrder); + payOrderService.initOrder(payOrder); } //调起上游支付接口 diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsCompanyService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsCompanyService.java index 089534f..e00d512 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsCompanyService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsCompanyService.java @@ -1,8 +1,8 @@ package com.jeequan.jeepay.service.impl; import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; -import com.jeequan.jeepay.service.mapper.OrderStatisticsCompanyMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jeequan.jeepay.service.mapper.OrderStatisticsCompanyMapper; import org.springframework.stereotype.Service; /** diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsDeptService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsDeptService.java index b4950d5..6a55c5e 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsDeptService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsDeptService.java @@ -1,8 +1,8 @@ package com.jeequan.jeepay.service.impl; import com.jeequan.jeepay.core.entity.OrderStatisticsDept; -import com.jeequan.jeepay.service.mapper.OrderStatisticsDeptMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jeequan.jeepay.service.mapper.OrderStatisticsDeptMapper; import org.springframework.stereotype.Service; /** diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsMerchantService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsMerchantService.java new file mode 100644 index 0000000..a376a68 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsMerchantService.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.service.impl; + +import com.jeequan.jeepay.core.entity.OrderStatisticsMerchant; +import com.jeequan.jeepay.service.mapper.OrderStatisticsMerchantMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单分析主表 服务实现类 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-17 + */ +@Service +public class OrderStatisticsMerchantService extends ServiceImpl{ + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java index c848500..9dc023c 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java @@ -78,8 +78,6 @@ public class PayOrderService extends ServiceImpl { } /** 更新订单状态 【支付中】 --》 【支付成功】 **/ - - @Action("下单成功记录") public boolean updateIng2Success(String payOrderId, String channelOrderNo, String channelUserId){ PayOrder updateRecord = new PayOrder(); @@ -372,6 +370,11 @@ public class PayOrderService extends ServiceImpl { return payListMap; } + @Action("下单成功记录") + public boolean initOrder(PayOrder order) + { + return this.save(order); + } /** * 计算支付订单商家入账金额 diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java index 58765df..1cb637d 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java @@ -1,7 +1,7 @@ package com.jeequan.jeepay.service.mapper; -import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; /** *

@@ -9,7 +9,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; *

* * @author [mybatis plus generator] - * @since 2023-02-09 + * @since 2023-02-17 */ public interface OrderStatisticsCompanyMapper extends BaseMapper { diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml index 7bef507..32e8c0d 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml @@ -4,15 +4,15 @@ - + - - + + diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java index 9290ff1..5595fe3 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java @@ -1,7 +1,7 @@ package com.jeequan.jeepay.service.mapper; -import com.jeequan.jeepay.core.entity.OrderStatisticsDept; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jeequan.jeepay.core.entity.OrderStatisticsDept; /** *

@@ -9,7 +9,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; *

* * @author [mybatis plus generator] - * @since 2023-02-09 + * @since 2023-02-17 */ public interface OrderStatisticsDeptMapper extends BaseMapper { diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml index f648bca..a3eb419 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml @@ -4,14 +4,13 @@ - - + + - diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java new file mode 100644 index 0000000..243cafb --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java @@ -0,0 +1,16 @@ +package com.jeequan.jeepay.service.mapper; + +import com.jeequan.jeepay.core.entity.OrderStatisticsMerchant; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单分析主表 Mapper 接口 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-17 + */ +public interface OrderStatisticsMerchantMapper extends BaseMapper { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml new file mode 100644 index 0000000..61ebcf1 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml index 3cc4adb..efaaf26 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderExtendMapper.xml @@ -5,45 +5,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - -- Gitee From f7050f37d5ea21e74c7db38377d1b832c4fcaf8f Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Tue, 21 Feb 2023 10:02:20 +0800 Subject: [PATCH 22/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=88=86=E6=9E=90=E7=9B=B8=E5=85=B3=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jeequan/jeepay/pay/aop/CopyOrderAspect.java | 14 +++++--------- .../jeepay/pay/filter/RefundInterceptor.java | 11 +++++++---- .../jeepay/service/impl/RefundOrderService.java | 7 ------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java index d78f6fe..e84e2f4 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java @@ -58,20 +58,16 @@ public class CopyOrderAspect { Object[] args = jp.getArgs(); System.out.println("Aop.afterReturning() 目标方法+" + jp.getSignature().getName() + "返回值:" + retValue); - String payOrderId = String.valueOf(args[0]); - String channelOrderNo = String.valueOf(args[1]); - String channelUserId = String.valueOf(args[2]); - - scheduledThreadPool.execute(() -> savePayOrderExtend(payOrderId, channelOrderNo, channelUserId)); + PayOrder payOrder = (PayOrder)args[0]; + scheduledThreadPool.execute(() -> savePayOrderExtend(payOrder)); } - private boolean savePayOrderExtend(String payOrderId, String channelOrderNo, String channelUserId) { - PayOrder payOrder = payOrderService.getById(payOrderId); + private boolean savePayOrderExtend(PayOrder order) { PayOrderExtend payOrderExtend = new PayOrderExtend(); - BeanUtils.copyProperties(payOrder, payOrderExtend); + payOrderExtend.setPayOrderId(order.getPayOrderId()); - String extParam = payOrder.getExtParam(); + String extParam = order.getExtParam(); if (!ObjectUtils.isEmpty(extParam)) { JSONObject jsonObject = JSONObject.parseObject(extParam); if (!jsonObject.getString("businessId").isEmpty()) { diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/RefundInterceptor.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/RefundInterceptor.java index 15ee4a5..b445101 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/RefundInterceptor.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/filter/RefundInterceptor.java @@ -3,9 +3,11 @@ package com.jeequan.jeepay.pay.filter; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.databind.ObjectMapper; import com.jeequan.jeepay.core.beans.RequestKitBean; +import com.jeequan.jeepay.core.entity.PayOrder; import com.jeequan.jeepay.core.entity.PayOrderExtend; import com.jeequan.jeepay.core.model.ApiRes; import com.jeequan.jeepay.service.impl.PayOrderExtendService; +import com.jeequan.jeepay.service.impl.PayOrderService; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.ObjectUtils; @@ -23,7 +25,7 @@ import java.io.PrintWriter; public class RefundInterceptor implements HandlerInterceptor { @Autowired - private PayOrderExtendService payOrderExtendService; + private PayOrderService payOrderService; @Autowired private RequestKitBean requestKitBean; @@ -41,9 +43,10 @@ public class RefundInterceptor implements HandlerInterceptor { return false; } String payOrderId = jsonObject.getString("payOrderId"); - PayOrderExtend orderExtend = payOrderExtendService.getById(payOrderId); - if (orderExtend.getAccountState().equals(PayOrderExtend.ACCOUNT_STATE_FINISHED)) { - ApiRes res = ApiRes.customFail("退单失败:因为该订单已完成结算,如有必要请线下人工操作!"); + + PayOrder order = payOrderService.getById(payOrderId); + if (order.getState().equals(PayOrder.STATE_CLOSED)) { + ApiRes res = ApiRes.customFail("退单失败:因为该订单已关闭,如有必要请线下人工操作!"); returnJson(res, response); return false; } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java index d27dbdf..ce794b4 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java @@ -22,7 +22,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jeequan.jeepay.core.entity.RefundOrder; import com.jeequan.jeepay.core.exception.BizException; -import com.jeequan.jeepay.service.mapper.PayOrderExtendMapper; import com.jeequan.jeepay.service.mapper.PayOrderMapper; import com.jeequan.jeepay.service.mapper.RefundOrderMapper; import org.apache.commons.lang3.StringUtils; @@ -46,8 +45,6 @@ public class RefundOrderService extends ServiceImpl Date: Thu, 23 Feb 2023 11:08:13 +0800 Subject: [PATCH 23/31] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jeepay-payment/pom.xml | 17 ++ .../jeepay/pay/aop/CopyOrderAspect.java | 3 +- .../jeequan/jeepay/pay/initPayOrderTest.java | 173 ++++++++++++++++++ .../src/main/java/com/gen/MainGen.java | 9 +- 4 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 jeepay-payment/src/test/java/com/jeequan/jeepay/pay/initPayOrderTest.java diff --git a/jeepay-payment/pom.xml b/jeepay-payment/pom.xml index 55e9cbe..a658f59 100644 --- a/jeepay-payment/pom.xml +++ b/jeepay-payment/pom.xml @@ -132,6 +132,23 @@ jeepay-sdk-java pls-1.3.0
+ + + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java index e84e2f4..e5209f5 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/aop/CopyOrderAspect.java @@ -82,8 +82,9 @@ public class CopyOrderAspect { if (!jsonObject.getString("deptId").isEmpty()) { payOrderExtend.setDeptId(jsonObject.getString("deptId")); } + return payOrderExtendService.save(payOrderExtend); } - return payOrderExtendService.save(payOrderExtend); + return false; } @Around(value = "pointCut()") diff --git a/jeepay-payment/src/test/java/com/jeequan/jeepay/pay/initPayOrderTest.java b/jeepay-payment/src/test/java/com/jeequan/jeepay/pay/initPayOrderTest.java new file mode 100644 index 0000000..1a05e6a --- /dev/null +++ b/jeepay-payment/src/test/java/com/jeequan/jeepay/pay/initPayOrderTest.java @@ -0,0 +1,173 @@ +package com.jeequan.jeepay.pay; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.jeequan.jeepay.core.entity.MchApp; +import com.jeequan.jeepay.pay.bootstrap.JeepayPayApplication; +import com.jeequan.jeepay.service.impl.MchAppService; +import com.jeequan.jeepay.util.JeepayKit; +import org.junit.jupiter.api.Test; +import org.mybatis.spring.annotation.MapperScan; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.util.Assert; +import org.springframework.web.client.RestTemplate; + +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.MessageFormat; +import java.util.*; + +//@MapperScan("com.jeequan.jeepay.service.mapper") //Mybatis mapper接口路径 +//@ComponentScan(basePackages = "com.jeequan.jeepay.*") +//@Configuration +@SpringBootTest(classes = JeepayPayApplication.class) +@SpringBootConfiguration +public class initPayOrderTest { + + final static Logger _log = LoggerFactory.getLogger(initPayOrderTest.class); + + @Autowired(required = false) + private MchAppService mchAppService; + + + @Test + public void testPayApi() { + + // 请求地址 + String url = "http://localhost:9216/api/pay/unifiedOrder"; + String API_SIGN_NAME = "sign"; + RestTemplate restTemplate = new RestTemplate(); + List mchAppList = mchAppService.list(); + mchAppList.forEach(item -> { + + String appId = item.getAppId(); + String mchNo = item.getMchNo(); + String apiKey = item.getAppSecret(); + + for (int i = 0; i < 100; i++) { + + HttpHeaders headers = new HttpHeaders(); + headers.add("X-API-KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3R1eG0uYXJ0IiwidXNlcm5hbWUiOiJ0dXNkZXNpZ24ifQ.0SCNQBLp6_e3EEcQcT0Rqwp1QJ4AonY5eoOTiKMIkk0"); + headers.setContentType(MediaType.APPLICATION_JSON); + + //提交参数设置 + Map signMap = new HashMap(); + + signMap.put("appId", appId); + signMap.put("mchNo", mchNo); + signMap.put("wayCode", "QIDI_APP"); + signMap.put("currency", "cny"); + signMap.put("subject", "商品标题"); + signMap.put("body", "商品描述"); + + Map map=new HashMap(){ + { + put("businessId","p" + IdWorker.getIdStr()); + put("deptId","p" + IdWorker.getIdStr()); + put("dealType","DEPARTMENTAL"); + put("pid", "m" + IdWorker.getIdStr()); + } + }; + String extParamTemplate= JSONObject.toJSONString(map); + signMap.put("extParam", extParamTemplate); + signMap.put("mchOrderNo", "mho" + new Date().getTime()); + signMap.put("amount", String.valueOf((int)(Math.random()*1000-1))); + signMap.put("clientIp", "192.168.0.1"); + + int requestTime = (int) (System.currentTimeMillis() / 1000); + signMap.put("reqTime", Integer.toString(requestTime)); + signMap.put("version", "1.0"); + signMap.put("signType", "MD5"); + + + String signature = JeepayKit.getSign(signMap, apiKey); + String signature2 = getSign(signMap, apiKey); + if (signature.equals(signature2)) + System.out.println("true"); + if (signature != null) { + signMap.put(API_SIGN_NAME, signature); + } + + // 组装请求体 + JSONObject object = new JSONObject(signMap); + HttpEntity request = + new HttpEntity(object.toString(), headers); + + // 发送post请求,并打印结果,以String类型接收响应结果JSON字符串 + String result = restTemplate.postForObject(url, request, String.class); + System.out.println(result); + + } + + }); + Assert.isTrue(true, "test successfully"); + } + + + /** + *

Description: 获取签名 + *

2023年2月8日 上午11:32:46 + * + * @param map 参数Map + * @param apiKey 商户秘钥 + * @return + */ + public String getSign(Map map, String apiKey) { + ArrayList list = new ArrayList(); + for (Map.Entry entry : map.entrySet()) { + if (null != entry.getValue() && !"".equals(entry.getValue())) { + list.add(entry.getKey() + "=" + entry.getValue() + "&"); + } + } + int size = list.size(); + String[] arrayToSort = list.toArray(new String[size]); + Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + sb.append(arrayToSort[i]); + } + String result = sb.toString() + "key=" + apiKey; + result = md5(result, "UTF-8").toUpperCase(); + return result; + } + + private String md5(String value, String charset) { + MessageDigest md = null; + try { + byte[] data = value.getBytes(charset); + md = MessageDigest.getInstance("MD5"); + byte[] digestData = md.digest(data); + return toHex(digestData); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return null; + } + } + + private String toHex(byte input[]) { + if (input == null) + return null; + StringBuffer output = new StringBuffer(input.length * 2); + for (int i = 0; i < input.length; i++) { + int current = input[i] & 0xff; + if (current < 16) + output.append("0"); + output.append(Integer.toString(current, 16)); + } + return output.toString(); + } + +} diff --git a/jeepay-z-codegen/src/main/java/com/gen/MainGen.java b/jeepay-z-codegen/src/main/java/com/gen/MainGen.java index 620a0d5..eadb738 100644 --- a/jeepay-z-codegen/src/main/java/com/gen/MainGen.java +++ b/jeepay-z-codegen/src/main/java/com/gen/MainGen.java @@ -20,13 +20,14 @@ public class MainGen { public static final String THIS_MODULE_NAME = "jeepay-z-codegen"; //当前项目名称 - public static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/jeepay?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"; - public static final String DB_USERNAME = "root"; - public static final String DB_PASSWORD = "root"; + public static final String DB_URL = "jdbc:mysql://127.0.0.1:3307/jeepaydb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"; + public static final String DB_USERNAME = "123"; + public static final String DB_PASSWORD = "123"; // 多个用, 拼接 //public static final String TABLE_NAMES= "t_sys_entitlement,t_sys_role,t_sys_user,t_sys_user_auth"; - public static final String TABLE_NAMES= "t_pay_way"; + + public static final String TABLE_NAMES= "t_pay_order_extend,t_order_statistics_company,t_order_statistics_dept,t_order_statistics_merchant"; public static void main(String[] args) { -- Gitee From 4d0220f62fcc111a30deeac5ec06e3fda33773bf Mon Sep 17 00:00:00 2001 From: airven <1017091284@qq.com> Date: Fri, 24 Feb 2023 18:26:41 +0800 Subject: [PATCH 24/31] =?UTF-8?q?=E6=94=AF=E4=BB=98=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=AB=AF=E6=B7=BB=E5=8A=A0=E5=AE=9A=E6=97=B6=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jeequan/jeepay/core/entity/SysJob.java | 68 ++++++++ .../jeepay/mgr/bootstrap/TaskRunner.java | 44 ++++++ .../jeepay/mgr/config/SchedulingConfig.java | 21 +++ .../jeepay/mgr/task/CronTaskRegistrar.java | 59 +++++++ .../jeepay/mgr/task/ScheduledTask.java | 19 +++ .../jeepay/mgr/task/SchedulingRunnable.java | 86 +++++++++++ .../jeepay/mgr/task/job/AnalysisTask.java | 26 ++++ .../jeepay/mgr/task/job/JobOneTask.java | 15 ++ .../jeepay/mgr/task/job/JobTwoTask.java | 15 ++ .../jeepay/mgr/util/SpringContextUtils.java | 43 ++++++ .../com/jeequan/jeepay/mgr/util/TimeUtil.java | 145 ++++++++++++++++++ .../src/main/resources/application.yml | 3 +- .../jeepay/service/impl/SysJobService.java | 19 +++ .../jeepay/service/mapper/SysJobMapper.java | 16 ++ .../jeepay/service/mapper/SysJobMapper.xml | 18 +++ 15 files changed, 596 insertions(+), 1 deletion(-) create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/SchedulingConfig.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/ScheduledTask.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobOneTask.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobTwoTask.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/SpringContextUtils.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/TimeUtil.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobService.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobMapper.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobMapper.xml diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java new file mode 100644 index 0000000..c8133b1 --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java @@ -0,0 +1,68 @@ +package com.jeequan.jeepay.core.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_sys_job") +public class SysJob implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final byte NORMAL = 1; //Job状态正常 + public static final byte PAUSE = 0; //Job状态暂停 + + + public static final LambdaQueryWrapper gw(){ + return new LambdaQueryWrapper<>(); + } + /** + * 任务ID + */ + @TableId(value = "job_id", type = IdType.AUTO) + private Integer jobId; + /** + * bean名称 + */ + private String beanName; + /** + * 方法名称 + */ + private String methodName; + /** + * 方法参数 + */ + private String methodParams; + /** + * cron表达式 + */ + private String cronExpression; + /** + * 状态(1正常 0暂停) + */ + private Byte jobStatus; + /** + * 备注 + */ + private String remark; + /** + * 创建时间 + */ + private Date createTime; + /** + * 更新时间 + */ + private Date updateTime; + + +} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java new file mode 100644 index 0000000..df1f9b3 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java @@ -0,0 +1,44 @@ +package com.jeequan.jeepay.mgr.bootstrap; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.jeequan.jeepay.core.entity.MchNotifyRecord; +import com.jeequan.jeepay.core.entity.SysJob; +import com.jeequan.jeepay.mgr.task.CronTaskRegistrar; +import com.jeequan.jeepay.mgr.task.SchedulingRunnable; +import com.jeequan.jeepay.service.impl.SysJobService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class TaskRunner implements CommandLineRunner { + + private static final Logger logger = LoggerFactory.getLogger(TaskRunner.class); + + @Autowired + private SysJobService sysJobService; + + @Autowired + private CronTaskRegistrar cronTaskRegistrar; + + @Override + public void run(String... args) throws Exception { + + // 初始加载数据库里状态为正常的定时任务 + LambdaQueryWrapper wrapper = SysJob.gw(); + List jobList = sysJobService.list(wrapper.eq(SysJob::getJobStatus, SysJob.NORMAL)); + + if (CollectionUtils.isNotEmpty(jobList)) { + for (SysJob job : jobList) { + SchedulingRunnable task = new SchedulingRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams()); + cronTaskRegistrar.addCronTask(task, job.getCronExpression()); + } + logger.info("定时任务已加载完毕..."); + } + } +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/SchedulingConfig.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/SchedulingConfig.java new file mode 100644 index 0000000..4412557 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/SchedulingConfig.java @@ -0,0 +1,21 @@ +package com.jeequan.jeepay.mgr.config; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +@Configuration +public class SchedulingConfig { + + @Bean + public TaskScheduler taskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + // 定时任务执行线程池核心线程数 + taskScheduler.setPoolSize(4); + taskScheduler.setRemoveOnCancelPolicy(true); + taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-"); + return taskScheduler; + } +} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java new file mode 100644 index 0000000..e6a2e19 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java @@ -0,0 +1,59 @@ +package com.jeequan.jeepay.mgr.task; + + +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.config.CronTask; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class CronTaskRegistrar implements DisposableBean { + + private final Map scheduledTasks = new ConcurrentHashMap<>(16); + + @Autowired + private TaskScheduler taskScheduler; + + public TaskScheduler getScheduler() { + return this.taskScheduler; + } + + public void addCronTask(Runnable task, String cronExpression) { + addCronTask(new CronTask(task, cronExpression)); + } + + public void addCronTask(CronTask cronTask) { + if (cronTask != null) { + Runnable task = cronTask.getRunnable(); + if (this.scheduledTasks.containsKey(task)) { + removeCronTask(task); + } + this.scheduledTasks.put(task, scheduleCronTask(cronTask)); + } + } + + public void removeCronTask(Runnable task) { + ScheduledTask scheduledTask = this.scheduledTasks.remove(task); + if (scheduledTask != null) + scheduledTask.cancel(); + } + + public ScheduledTask scheduleCronTask(CronTask cronTask) { + ScheduledTask scheduledTask = new ScheduledTask(); + scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger()); + return scheduledTask; + } + + + @Override + public void destroy() { + for (ScheduledTask task : this.scheduledTasks.values()) { + task.cancel(); + } + this.scheduledTasks.clear(); + } +} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/ScheduledTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/ScheduledTask.java new file mode 100644 index 0000000..ed46232 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/ScheduledTask.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.mgr.task; + + +import java.util.concurrent.ScheduledFuture; + +public final class ScheduledTask { + + volatile ScheduledFuture future; + + /** + * 取消定时任务 + */ + public void cancel() { + ScheduledFuture future = this.future; + if (future != null) { + future.cancel(true); + } + } +} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java new file mode 100644 index 0000000..537d6a7 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java @@ -0,0 +1,86 @@ +package com.jeequan.jeepay.mgr.task; + + +import com.jeequan.jeepay.mgr.util.SpringContextUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; +import java.util.Objects; + +public class SchedulingRunnable implements Runnable { + + private static final Logger logger = LoggerFactory.getLogger(SchedulingRunnable.class); + + private String beanName; + + private String methodName; + + private String params; + + public SchedulingRunnable(String beanName, String methodName) { + this(beanName, methodName, null); + } + + public SchedulingRunnable(String beanName, String methodName, String params) { + this.beanName = beanName; + this.methodName = methodName; + this.params = params; + } + + @Override + public void run() { + logger.info("定时任务开始执行 - bean:{},方法:{},参数:{}", beanName, methodName, params); + long startTime = System.currentTimeMillis(); + + try { + Object target = SpringContextUtils.getBean(beanName); + + Method method = null; + if (StringUtils.isNotEmpty(params)) { + method = target.getClass().getDeclaredMethod(methodName, String.class); + } else { + method = target.getClass().getDeclaredMethod(methodName); + } + + ReflectionUtils.makeAccessible(method); + if (StringUtils.isNotEmpty(params)) { + method.invoke(target, params); + } else { + method.invoke(target); + } + } catch (Exception ex) { + logger.error(String.format("定时任务执行异常 - bean:%s,方法:%s,参数:%s ", beanName, methodName, params), ex); + } + + long times = System.currentTimeMillis() - startTime; + logger.info("定时任务执行结束 - bean:{},方法:{},参数:{},耗时:{} 毫秒", beanName, methodName, params, times); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SchedulingRunnable that = (SchedulingRunnable) o; + if (params == null) { + return beanName.equals(that.beanName) && + methodName.equals(that.methodName) && + that.params == null; + } + + return beanName.equals(that.beanName) && + methodName.equals(that.methodName) && + params.equals(that.params); + } + + @Override + public int hashCode() { + if (params == null) { + return Objects.hash(beanName, methodName); + } + + return Objects.hash(beanName, methodName, params); + } +} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java new file mode 100644 index 0000000..0201839 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java @@ -0,0 +1,26 @@ +package com.jeequan.jeepay.mgr.task.job; + +import com.jeequan.jeepay.service.impl.OrderStatisticsCompanyService; +import com.jeequan.jeepay.service.impl.OrderStatisticsDeptService; +import com.jeequan.jeepay.service.impl.OrderStatisticsMerchantService; +import com.jeequan.jeepay.service.impl.PayOrderExtendService; +import org.springframework.beans.factory.annotation.Autowired; + +public class AnalysisTask { + + @Autowired + private PayOrderExtendService payOrderExtendService; + + @Autowired + private OrderStatisticsCompanyService orderStatisticsCompanyService; + + @Autowired + private OrderStatisticsDeptService orderStatisticsDeptService; + + @Autowired + private OrderStatisticsMerchantService orderStatisticsMerchantService; + + public void Analyse(){ + //企业结算 + } +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobOneTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobOneTask.java new file mode 100644 index 0000000..ed458e4 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobOneTask.java @@ -0,0 +1,15 @@ +package com.jeequan.jeepay.mgr.task.job; + +import org.springframework.stereotype.Component; + + +@Component("taskJobOne") +public class JobOneTask { + public void taskWithParams(String params) { + System.out.println("taskJobOne-执行有参示例任务:" + params); + } + + public void taskNoParams() { + System.out.println("taskJobOne-执行无参示例任务"); + } +} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobTwoTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobTwoTask.java new file mode 100644 index 0000000..58cd330 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobTwoTask.java @@ -0,0 +1,15 @@ +package com.jeequan.jeepay.mgr.task.job; + +import org.springframework.stereotype.Component; + + +@Component("taskJobTwo") +public class JobTwoTask { + public void taskWithParams(String params) { + System.out.println("taskJobTwo-执行有参示例任务:" + params); + } + + public void taskNoParams() { + System.out.println("taskJobTwo-执行无参示例任务"); + } +} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/SpringContextUtils.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/SpringContextUtils.java new file mode 100644 index 0000000..13b54c8 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/SpringContextUtils.java @@ -0,0 +1,43 @@ +package com.jeequan.jeepay.mgr.util; + + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class SpringContextUtils implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + SpringContextUtils.applicationContext = applicationContext; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static T getBean(Class requiredType) { + return applicationContext.getBean(requiredType); + } + + public static T getBean(String name, Class requiredType) { + return applicationContext.getBean(name, requiredType); + } + + public static boolean containsBean(String name) { + return applicationContext.containsBean(name); + } + + public static boolean isSingleton(String name) { + return applicationContext.isSingleton(name); + } + + public static Class getType(String name) { + return applicationContext.getType(name); + } +} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/TimeUtil.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/TimeUtil.java new file mode 100644 index 0000000..dea8cd5 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/TimeUtil.java @@ -0,0 +1,145 @@ +package com.jeequan.jeepay.mgr.util; + +import lombok.SneakyThrows; +import org.springframework.stereotype.Component; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +@Component +public class TimeUtil { + + private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + /** + * 获取昨天0点0分0秒的时间 + */ + @SneakyThrows + public String getBeforeFirstDayDate() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + System.out.println("当前星期(日期):" + format.format(calendar.getTime())); + calendar.add(Calendar.DAY_OF_WEEK, 0); + calendar.set(Calendar.DAY_OF_WEEK, 1); + calendar.set(Calendar.HOUR_OF_DAY, 00);//将小时至00 + calendar.set(Calendar.MINUTE, 00);//将分钟至00 + calendar.set(Calendar.SECOND, 00);//将秒至00 + String timeString = format.format(calendar.getTime()); + return timeString; + } + + /** + * 获取昨天天23点59分59秒的时间 + */ + @SneakyThrows + public String getBeforeLastDayDate() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.set(Calendar.HOUR_OF_DAY, 23);//将小时至23 + calendar.set(Calendar.MINUTE, 59);//将分钟至59 + calendar.set(Calendar.SECOND, 59); //将秒至59 + String timeString = format.format(calendar.getTime()); + return timeString; + } + + + /** + * 获取上一周1号0点0分0秒的时间 + */ + @SneakyThrows + public String getBeforeFirstWeekDate() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.add(Calendar.WEEK_OF_YEAR, -1); + System.out.println("上周星期(日期):" + format.format(calendar.getTime())); + calendar.add(Calendar.DAY_OF_WEEK, 0); + calendar.set(Calendar.DAY_OF_WEEK, 1); + calendar.set(Calendar.HOUR_OF_DAY, 00); + calendar.set(Calendar.MINUTE, 00); //将分钟至00 + calendar.set(Calendar.SECOND, 00);//将秒至00 + String timeString = format.format(calendar.getTime()); + return timeString; + } + + /** + * 获取上一周最后一天23点59分59秒的时间 + */ + @SneakyThrows + public String getBeforeLastWeekDate() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.add(Calendar.WEEK_OF_YEAR, -1); + System.out.println("上周星期(日期):" + format.format(calendar.getTime())); + calendar.set(Calendar.HOUR_OF_DAY, 23);//将小时至23 + calendar.set(Calendar.MINUTE, 59); //将分钟至59 + calendar.set(Calendar.SECOND, 59); //将秒至59 + String timeString = format.format(calendar.getTime()); + return timeString; + } + + /** + * 获取上一个月1号0点0分0秒的时间 + */ + @SneakyThrows + public String getBeforeFirstMonthDate() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.MONTH, -1); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.set(Calendar.HOUR_OF_DAY, 00);//将小时至00 + calendar.set(Calendar.MINUTE, 00);//将分钟至00 + calendar.set(Calendar.SECOND, 00); //将秒至00 + String timeString = format.format(calendar.getTime()); + return timeString; + } + + + /** + * 获取上个月的最后一天23点59分59秒的时间 + */ + @SneakyThrows + public String getBeforeLastMonthDate() throws Exception { + Calendar calendar = Calendar.getInstance(); + int month = calendar.get(Calendar.MONTH); + calendar.set(Calendar.MONTH, month - 1); + calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); + calendar.set(Calendar.HOUR_OF_DAY, 23); //将小时至23 + calendar.set(Calendar.MINUTE, 59); //将分钟至59 + calendar.set(Calendar.SECOND, 59);//将秒至59 + String timeString = format.format(calendar.getTime()); + return timeString; + } + + /** + * 获取上年1号0点0分0秒的时间 + */ + @SneakyThrows + public String getBeforeFirstYearDate() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.add(Calendar.YEAR, -1); + calendar.set(Calendar.DAY_OF_YEAR, 1); + calendar.set(Calendar.HOUR_OF_DAY, 00);//将小时至00 + calendar.set(Calendar.MINUTE, 00);//将分钟至00 + calendar.set(Calendar.SECOND, 00); //将秒至00 + String timeString = format.format(calendar.getTime()); + return timeString; + } + + + /** + * 获取上年的最后一天23点59分59秒的时间 + */ + @SneakyThrows + public String getBeforeLastYearDate() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.add(Calendar.YEAR, -1); + calendar.set(Calendar.DAY_OF_YEAR, calendar.getActualMaximum(Calendar.DAY_OF_YEAR)); + calendar.set(Calendar.HOUR_OF_DAY, 23); //将小时至23 + calendar.set(Calendar.MINUTE, 59); //将分钟至59 + calendar.set(Calendar.SECOND, 59);//将秒至59 + String timeString = format.format(calendar.getTime()); + return timeString; + } +} diff --git a/jeepay-merchant/src/main/resources/application.yml b/jeepay-merchant/src/main/resources/application.yml index d869ebd..2afd483 100644 --- a/jeepay-merchant/src/main/resources/application.yml +++ b/jeepay-merchant/src/main/resources/application.yml @@ -4,7 +4,8 @@ server: spring: redis: database: 2 #1库:运营平台 #2库:商户系统 #3库:支付网关 - +# profiles: +# active: dev #系统业务参数 isys: jwt-secret: ARNXp4MzjOOQqxtv #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。 diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobService.java new file mode 100644 index 0000000..330d851 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobService.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.service.impl; + +import com.jeequan.jeepay.core.entity.SysJob; +import com.jeequan.jeepay.service.mapper.SysJobMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-24 + */ +@Service +public class SysJobService extends ServiceImpl { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobMapper.java new file mode 100644 index 0000000..f06030a --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobMapper.java @@ -0,0 +1,16 @@ +package com.jeequan.jeepay.service.mapper; + +import com.jeequan.jeepay.core.entity.SysJob; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author [mybatis plus generator] + * @since 2023-02-24 + */ +public interface SysJobMapper extends BaseMapper { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobMapper.xml new file mode 100644 index 0000000..884b457 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + -- Gitee From 901f6aa02f73f608aea3c3196969ea5c5239fee9 Mon Sep 17 00:00:00 2001 From: airven <1017091284@qq.com> Date: Tue, 28 Feb 2023 18:14:36 +0800 Subject: [PATCH 25/31] =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/entity/OrderStatisticsDept.java | 15 +++- .../jeepay/mgr/task/job/AnalysisTask.java | 79 +++++++++++++++++-- .../com/jeequan/jeepay/mgr/util/TimeUtil.java | 18 ++--- .../src/main/resources/application.yml | 5 ++ .../jeepay/service/impl/PayOrderService.java | 18 ++++- .../mapper/OrderStatisticsCompanyMapper.java | 4 + .../mapper/OrderStatisticsCompanyMapper.xml | 41 +++++++--- .../mapper/OrderStatisticsDeptMapper.java | 5 ++ .../mapper/OrderStatisticsDeptMapper.xml | 8 ++ .../mapper/OrderStatisticsMerchantMapper.java | 3 + .../mapper/OrderStatisticsMerchantMapper.xml | 38 ++++++--- .../jeepay/service/mapper/PayOrderMapper.java | 7 ++ .../jeepay/service/mapper/PayOrderMapper.xml | 28 +++++++ 13 files changed, 226 insertions(+), 43 deletions(-) diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java index b157e4b..9cf5ba6 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java @@ -1,6 +1,7 @@ package com.jeequan.jeepay.core.entity; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @@ -62,6 +63,19 @@ public class OrderStatisticsDept implements Serializable { */ private String deptName; + /** + * 公司名称 + */ + @TableField(exist=false) + private String companyName; + + /** + * 部门id + */ + @TableField(exist=false) + private String deptId; + + /** * 部门账单金额,单位分 */ @@ -72,5 +86,4 @@ public class OrderStatisticsDept implements Serializable { */ private Date createdAt; - } \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java index 0201839..e0cb083 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java @@ -1,13 +1,33 @@ package com.jeequan.jeepay.mgr.task.job; -import com.jeequan.jeepay.service.impl.OrderStatisticsCompanyService; -import com.jeequan.jeepay.service.impl.OrderStatisticsDeptService; -import com.jeequan.jeepay.service.impl.OrderStatisticsMerchantService; -import com.jeequan.jeepay.service.impl.PayOrderExtendService; +import ch.qos.logback.core.joran.conditional.ElseAction; +import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.druid.sql.ast.statement.SQLIfStatement; +import com.jeequan.jeepay.core.entity.OrderStatisticsDept; +import com.jeequan.jeepay.mgr.util.TimeUtil; +import com.jeequan.jeepay.service.impl.*; +import org.apache.commons.lang3.tuple.MutablePair; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; + +@Component("analysisTask") +@Configuration public class AnalysisTask { + @Value(value = "${qiDi.gateWay.url}") + private String gateWay; + + @Value(value = "${qiDi.gateWay.secret-key}") + private String secretKey; + + @Autowired + private PayOrderService payOrderService; + @Autowired private PayOrderExtendService payOrderExtendService; @@ -20,7 +40,54 @@ public class AnalysisTask { @Autowired private OrderStatisticsMerchantService orderStatisticsMerchantService; - public void Analyse(){ - //企业结算 + /** + * 根据周期段进行分析 + * + * @param cycle 1表示年,2表示月 3表示周 + */ + @Transactional(rollbackFor = Exception.class) + public void Analyse(int cycle) throws Exception { + + String createTimeStart = "";//开始时间 + String createTimeEnd = "";//结束时间 + + if (1 == cycle) { + createTimeStart = TimeUtil.getBeforeFirstYearDate(); + createTimeEnd = TimeUtil.getBeforeLastYearDate(); + } else if (2 == cycle) { + createTimeStart = TimeUtil.getBeforeFirstMonthDate(); + createTimeEnd = TimeUtil.getBeforeLastMonthDate(); + } else if (3 == cycle) { + createTimeStart = TimeUtil.getBeforeFirstDayDate(); + createTimeEnd = TimeUtil.getBeforeLastDayDate(); + } + + //产生版本号 + Long analyseId=0L; + List orderStatisticsDeptList = payOrderService.selectOrderCountByDept(createTimeStart, createTimeEnd); + + if (!CollectionUtil.isEmpty(orderStatisticsDeptList)) { + orderStatisticsDeptList.forEach(item -> { + //去启迪查询部门信息 + MutablePair mutablePair = getDept(item.getDeptId()); + item.setDeptName(""); + item.setCompanyName(""); + }); + boolean stepOne = orderStatisticsDeptService.saveBatch(orderStatisticsDeptList, 200); + + if (stepOne) { + + } + } } + + /** + * 根据部门Id得到部门信息 + * @param deptId + * @return MutablePair + */ + private MutablePair getDept(String deptId) { + return MutablePair.of("deptName", "compnayName"); + } + } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/TimeUtil.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/TimeUtil.java index dea8cd5..e6c554b 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/TimeUtil.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/util/TimeUtil.java @@ -10,13 +10,13 @@ import java.util.Date; @Component public class TimeUtil { - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * 获取昨天0点0分0秒的时间 */ @SneakyThrows - public String getBeforeFirstDayDate() throws Exception { + public static String getBeforeFirstDayDate() throws Exception { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); System.out.println("当前星期(日期):" + format.format(calendar.getTime())); @@ -33,7 +33,7 @@ public class TimeUtil { * 获取昨天天23点59分59秒的时间 */ @SneakyThrows - public String getBeforeLastDayDate() throws Exception { + public static String getBeforeLastDayDate() throws Exception { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.set(Calendar.HOUR_OF_DAY, 23);//将小时至23 @@ -48,7 +48,7 @@ public class TimeUtil { * 获取上一周1号0点0分0秒的时间 */ @SneakyThrows - public String getBeforeFirstWeekDate() throws Exception { + public static String getBeforeFirstWeekDate() throws Exception { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.WEEK_OF_YEAR, -1); @@ -66,7 +66,7 @@ public class TimeUtil { * 获取上一周最后一天23点59分59秒的时间 */ @SneakyThrows - public String getBeforeLastWeekDate() throws Exception { + public static String getBeforeLastWeekDate() throws Exception { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.WEEK_OF_YEAR, -1); @@ -82,7 +82,7 @@ public class TimeUtil { * 获取上一个月1号0点0分0秒的时间 */ @SneakyThrows - public String getBeforeFirstMonthDate() throws Exception { + public static String getBeforeFirstMonthDate() throws Exception { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MONTH, -1); calendar.set(Calendar.DAY_OF_MONTH, 1); @@ -98,7 +98,7 @@ public class TimeUtil { * 获取上个月的最后一天23点59分59秒的时间 */ @SneakyThrows - public String getBeforeLastMonthDate() throws Exception { + public static String getBeforeLastMonthDate() throws Exception { Calendar calendar = Calendar.getInstance(); int month = calendar.get(Calendar.MONTH); calendar.set(Calendar.MONTH, month - 1); @@ -114,7 +114,7 @@ public class TimeUtil { * 获取上年1号0点0分0秒的时间 */ @SneakyThrows - public String getBeforeFirstYearDate() throws Exception { + public static String getBeforeFirstYearDate() throws Exception { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.YEAR, -1); @@ -131,7 +131,7 @@ public class TimeUtil { * 获取上年的最后一天23点59分59秒的时间 */ @SneakyThrows - public String getBeforeLastYearDate() throws Exception { + public static String getBeforeLastYearDate() throws Exception { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.YEAR, -1); diff --git a/jeepay-manager/src/main/resources/application.yml b/jeepay-manager/src/main/resources/application.yml index d0c7ec8..6e8e619 100644 --- a/jeepay-manager/src/main/resources/application.yml +++ b/jeepay-manager/src/main/resources/application.yml @@ -7,6 +7,11 @@ spring: # profiles: # active: dev +qiDi: + gateWay: + url: https://api-shanghai.sz9wang.com/api/v1 + secret-key: "" + #系统业务参数 isys: jwt-secret: t7w3P8X6472qWc3u #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。 diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java index 9dc023c..cf68126 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayOrderService.java @@ -28,10 +28,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jeequan.jeepay.core.aop.Action; import com.jeequan.jeepay.core.aop.MethodLog; import com.jeequan.jeepay.core.constants.CS; -import com.jeequan.jeepay.core.entity.IsvInfo; -import com.jeequan.jeepay.core.entity.MchInfo; -import com.jeequan.jeepay.core.entity.PayOrder; -import com.jeequan.jeepay.core.entity.PayWay; +import com.jeequan.jeepay.core.entity.*; import com.jeequan.jeepay.service.mapper.*; import org.apache.commons.lang3.StringUtils; import org.springframework.aop.framework.AopContext; @@ -455,4 +452,17 @@ public class PayOrderService extends ServiceImpl { return page(iPage, wrapper); } + + public List selectOrderCountByDept(String createTimeStart,String createTimeEnd) + { + Map paramMap = new HashMap<>(); + paramMap.put("createTimeStart",createTimeStart); + paramMap.put("createTimeEnd",createTimeEnd); + return this.getBaseMapper().selectOrderCountByDept(paramMap); + } + + /** 更新订单状态为已完成 **/ + public int updateOrderStateBatch(List orderList){ + return this.getBaseMapper().updateOrderStateBatch(orderList); + } } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java index 1cb637d..24a78c7 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.java @@ -2,6 +2,9 @@ package com.jeequan.jeepay.service.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; +import com.jeequan.jeepay.core.entity.OrderStatisticsMerchant; + +import java.util.List; /** *

@@ -13,4 +16,5 @@ import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; */ public interface OrderStatisticsCompanyMapper extends BaseMapper { + public int insertBatch(List orderStatisticsCompanyList); } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml index 32e8c0d..d9d88eb 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsCompanyMapper.xml @@ -4,18 +4,35 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + INSERT INTO t_order_statistics_company (mch_no,app_id, app_name, mch_name, + amount,dept_name,amount_infact,analyse_id,static_state,remark) VALUES + + (#{item.mchNo}, + #{item.appId}, + #{item.appName}, + #{item.mchName}, + #{item.amount}, + #{item.deptName}, + #{item.amountInfact}, + #{item.analyseId}, + #{item.staticState}, + #{item.remark}) + + diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java index 5595fe3..bf490ff 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.java @@ -1,8 +1,11 @@ package com.jeequan.jeepay.service.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; import com.jeequan.jeepay.core.entity.OrderStatisticsDept; +import java.util.List; + /** *

* 订单分析部门表 Mapper 接口 @@ -13,4 +16,6 @@ import com.jeequan.jeepay.core.entity.OrderStatisticsDept; */ public interface OrderStatisticsDeptMapper extends BaseMapper { + public int insertBatch(List orderStatisticsDeptList); + } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml index a3eb419..63f45b5 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsDeptMapper.xml @@ -15,4 +15,12 @@ + + + INSERT INTO t_order_statistics_dept (analyse_id, mch_no, app_id, app_name, mch_name,dept_name,amount) VALUES + + (#{item.analyseId},#{item.mchNo},#{item.appId},#{item.appName},#{item.mchName},#{item.deptName},#{item.amount}) + + + diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java index 243cafb..07fcbe8 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java @@ -3,6 +3,8 @@ package com.jeequan.jeepay.service.mapper; import com.jeequan.jeepay.core.entity.OrderStatisticsMerchant; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import java.util.List; + /** *

* 订单分析主表 Mapper 接口 @@ -13,4 +15,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface OrderStatisticsMerchantMapper extends BaseMapper { + public int insertBatch(List orderStatisticsMerchantList); } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml index 61ebcf1..772e457 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml @@ -4,17 +4,33 @@ - - - - - - - - - - - + + + + + + + + + + + + + + INSERT INTO t_order_statistics_merchant (mch_no, app_id, app_name, mch_name, + amount,amount_infact,analyse_id,static_state,remark) VALUES + + (#{item.mchNo}, + #{item.appId}, + #{item.appName}, + #{item.mchName}, + #{item.amount}, + #{item.amountInfact}, + #{item.analyseId}), + #{item.staticState}), + #{item.remark}), + + diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.java index e6565f3..aaf9fc8 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.java @@ -16,6 +16,7 @@ package com.jeequan.jeepay.service.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jeequan.jeepay.core.entity.OrderStatisticsDept; import com.jeequan.jeepay.core.entity.PayOrder; import org.apache.ibatis.annotations.Param; @@ -38,6 +39,12 @@ public interface PayOrderMapper extends BaseMapper { List selectOrderCount(Map param); + /** 更统计企业在各个档口的消费情况 **/ + List selectOrderCountByDept(Map param); + + /** 更新订单状态为已完成 **/ + int updateOrderStateBatch(List orderList); + /** 更新订单退款金额和次数 **/ int updateRefundAmountAndCount(@Param("payOrderId") String payOrderId, @Param("currentRefundAmount") Long currentRefundAmount); } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.xml index 5813a26..c9d1f97 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.xml @@ -81,6 +81,34 @@ GROUP BY groupDate ORDER BY groupDate desc + + + + + + update t_pay_order + + + + when pay_order_id=#{item.payOrderId} then #{item.state} + + + + where pay_order_id in + + #{item.payOrderId,jdbcType=VARCHAR} + + -- Gitee From 2ead0040432acfdb87fb896771846e121e5f152d Mon Sep 17 00:00:00 2001 From: airven <1017091284@qq.com> Date: Wed, 1 Mar 2023 17:59:39 +0800 Subject: [PATCH 26/31] =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/entity/OrderStatisticsCompany.java | 3 + .../jeepay/mgr/config/RestTemplateConfig.java | 99 +++++++++++++++++++ .../jeepay/mgr/task/job/AnalysisTask.java | 71 +++++++++++-- .../src/main/resources/application.yml | 4 +- 4 files changed, 166 insertions(+), 11 deletions(-) create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/RestTemplateConfig.java diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java index 4887956..1f318af 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java @@ -26,6 +26,9 @@ public class OrderStatisticsCompany implements Serializable { private static final long serialVersionUID=1L; + public static final byte ACCOUNT_STATE_NUN = 0;//已结账 + public static final byte ACCOUNT_STATE_FINISHED = 1; //未结账 + /** * ID */ diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/RestTemplateConfig.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/RestTemplateConfig.java new file mode 100644 index 0000000..23605fd --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/RestTemplateConfig.java @@ -0,0 +1,99 @@ +package com.jeequan.jeepay.mgr.config; + +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; + +@Configuration +public class RestTemplateConfig { + + private class CustomErrorHandler implements ResponseErrorHandler { + + Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * 表示 response 是否存在任何错误。实现类通常会检查 response 的 HttpStatus。 + * + * @param response + * @return + * @throws IOException + */ + @Override + public boolean hasError(ClientHttpResponse response) throws IOException { + int rawStatusCode = response.getRawStatusCode(); + HttpStatus statusCode = HttpStatus.resolve(rawStatusCode); + return (statusCode != null ? statusCode.isError() : hasError(rawStatusCode)); + } + + protected boolean hasError(int unknownStatusCode) { + HttpStatus.Series series = HttpStatus.Series.resolve(unknownStatusCode); + return (series == HttpStatus.Series.CLIENT_ERROR || series == HttpStatus.Series.SERVER_ERROR); + } + + /** + * 处理 response 中的错误, 当 hasError 返回 true 时才调用此方法。 + * 当返回异常信息时自己想要做的一些操作处理 + * + * @param response + * @throws IOException + */ + @Override + public void handleError(ClientHttpResponse response) throws IOException { + } + + /** + * 覆盖了上面的方法 + * 处理 response 中的错误, 当 hasError 返回 true 时才调用此方法。 + * 当返回异常信息时自己想要做的一些操作处理 + * + * @param url + * @param method + * @param response + * @throws IOException + */ + @Override + public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException { + logger.error("=======================ERROR============================"); + logger.error("HOST:{},URI:{}", url.getHost(), url.getPath()); + logger.error("Method Type:{}", method.name()); + logger.error("Exception:{}", response.getStatusCode()); + logger.error("========================================================"); + } + } + + @Bean + @ConditionalOnMissingBean(RestTemplate.class) + public RestTemplate restTemplate() { + SimpleClientHttpRequestFactory requestFactory = + new SimpleClientHttpRequestFactory(); + // 设置连接超时,单位毫秒 + requestFactory.setConnectTimeout(30000); + //设置读取超时 + requestFactory.setReadTimeout(30000); + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setErrorHandler(new CustomErrorHandler()); + restTemplate.setRequestFactory(requestFactory); + restTemplate.getMessageConverters().add( + new StringHttpMessageConverter(StandardCharsets.UTF_8) + ); + restTemplate.getMessageConverters().add( + new FastJsonHttpMessageConverter() + ); + return restTemplate; + } + +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java index e0cb083..fd4d94d 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java @@ -3,17 +3,29 @@ package com.jeequan.jeepay.mgr.task.job; import ch.qos.logback.core.joran.conditional.ElseAction; import cn.hutool.core.collection.CollectionUtil; import com.alibaba.druid.sql.ast.statement.SQLIfStatement; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.jeequan.jeepay.core.entity.MchApp; +import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; import com.jeequan.jeepay.core.entity.OrderStatisticsDept; import com.jeequan.jeepay.mgr.util.TimeUtil; import com.jeequan.jeepay.service.impl.*; +import com.jeequan.jeepay.util.JeepayKit; +import lombok.SneakyThrows; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.MutablePair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; +import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestTemplate; -import java.util.List; +import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.*; +import java.util.stream.Collectors; @Component("analysisTask") @Configuration @@ -25,6 +37,9 @@ public class AnalysisTask { @Value(value = "${qiDi.gateWay.secret-key}") private String secretKey; + @Resource + private RestTemplate restTemplate; + @Autowired private PayOrderService payOrderService; @@ -63,31 +78,69 @@ public class AnalysisTask { } //产生版本号 - Long analyseId=0L; + Long analyseId = 0L; List orderStatisticsDeptList = payOrderService.selectOrderCountByDept(createTimeStart, createTimeEnd); if (!CollectionUtil.isEmpty(orderStatisticsDeptList)) { orderStatisticsDeptList.forEach(item -> { //去启迪查询部门信息 - MutablePair mutablePair = getDept(item.getDeptId()); - item.setDeptName(""); - item.setCompanyName(""); + MutablePair mutablePair = getDept(item.getDeptId()); + item.setDeptName(mutablePair.right); + item.setCompanyName(mutablePair.left); }); boolean stepOne = orderStatisticsDeptService.saveBatch(orderStatisticsDeptList, 200); - if (stepOne) { - + Map map = orderStatisticsDeptList.stream().collect(Collectors.groupingBy((item) -> { + OrderStatisticsCompany company = new OrderStatisticsCompany(); + company.setAppId(item.getAppId()); + company.setAppName(item.getAppName()); + company.setMchNo(item.getMchNo()); + company.setMchName(item.getMchName()); + company.setStaticState(OrderStatisticsCompany.ACCOUNT_STATE_NUN); + company.setAmountInfact(0L); + company.setAnalyseId(analyseId); + company.setDeptName(item.getCompanyName()); + return company; + }, Collectors.summingLong(OrderStatisticsDept::getAmount))); + + List orderStatisticsCompanyList = new ArrayList<>(); + map.forEach((k, v) -> { + k.setAmount(v); + orderStatisticsCompanyList.add(k); + }); + orderStatisticsCompanyService.saveBatch(orderStatisticsCompanyList); } } } + /** * 根据部门Id得到部门信息 + * * @param deptId * @return MutablePair */ - private MutablePair getDept(String deptId) { - return MutablePair.of("deptName", "compnayName"); + @SneakyThrows + private MutablePair getDept(String deptId) { + + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.add("X-API-KEY", secretKey); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity request = + new HttpEntity(null, headers); + ResponseEntity responseMap = restTemplate.exchange(gateWay + MessageFormat.format("/groups/{0}", deptId), HttpMethod.GET, request, Map.class); + + if (responseMap.getStatusCode().equals(HttpStatus.OK)) { + Map responseBody = responseMap.getBody(); + if (!responseBody.isEmpty() && responseBody.containsKey("path")) { + String fullPath = String.valueOf(responseBody.get("path")); + String[] nameArray = StringUtils.split(fullPath, "/"); + return MutablePair.of(nameArray[0], nameArray[1]); + } + } + return MutablePair.of("未知", "未知"); } } diff --git a/jeepay-manager/src/main/resources/application.yml b/jeepay-manager/src/main/resources/application.yml index 6e8e619..5613da9 100644 --- a/jeepay-manager/src/main/resources/application.yml +++ b/jeepay-manager/src/main/resources/application.yml @@ -9,8 +9,8 @@ spring: qiDi: gateWay: - url: https://api-shanghai.sz9wang.com/api/v1 - secret-key: "" + url: https://api.sz9wang.com/api/v1 + secret-key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3R1eG0uYXJ0IiwidXNlcm5hbWUiOiJ0dXNkZXNpZ24ifQ.0SCNQBLp6_e3EEcQcT0Rqwp1QJ4AonY5eoOTiKMIkk0" #系统业务参数 isys: -- Gitee From d24ecaa8a7c70286652d6f6a84dab5a6743e34c5 Mon Sep 17 00:00:00 2001 From: airven <1017091284@qq.com> Date: Thu, 2 Mar 2023 18:31:34 +0800 Subject: [PATCH 27/31] =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=88=86=E6=9E=90?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jeepay-manager/pom.xml | 11 ++ .../jeequan/jeepay/mgr/aop/MethodLogAop.java | 10 +- .../jeepay/mgr/config/RestTemplateConfig.java | 24 ++++ .../jeepay/mgr/config/SchedulingConfig.java | 6 +- .../jeepay/mgr/ctrl/anon/TaskController.java | 122 ++++++++++++++++++ .../jeepay/mgr/task/AbstractAnalysisTask.java | 37 ++++++ .../jeepay/mgr/task/CronTaskRegistrar.java | 1 + .../jeepay/mgr/task/SchedulingRunnable.java | 2 + ...ysisTask.java => CompanyAnalysisTask.java} | 101 ++++++++------- .../jeepay/mgr/task/job/JobOneTask.java | 15 --- .../jeepay/mgr/task/job/JobTwoTask.java | 15 --- .../mgr/task/job/MerchantAnalysisTask.java | 61 +++++++++ .../src/main/resources/application.yml | 4 +- .../mgr/task/job/CompanyAnalysisTaskTest.java | 25 ++++ .../impl/OrderStatisticsMerchantService.java | 12 ++ .../mapper/OrderStatisticsMerchantMapper.java | 14 ++ .../mapper/OrderStatisticsMerchantMapper.xml | 14 ++ .../jeepay/service/mapper/PayOrderMapper.xml | 4 +- 18 files changed, 393 insertions(+), 85 deletions(-) create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java rename jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/{AnalysisTask.java => CompanyAnalysisTask.java} (58%) delete mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobOneTask.java delete mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobTwoTask.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java create mode 100644 jeepay-manager/src/test/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTaskTest.java diff --git a/jeepay-manager/pom.xml b/jeepay-manager/pom.xml index 2305493..ae3edd5 100644 --- a/jeepay-manager/pom.xml +++ b/jeepay-manager/pom.xml @@ -100,6 +100,17 @@ jeepay-sdk-java + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java index 62f8f1c..313eba6 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java @@ -35,6 +35,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.ReflectionUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @@ -122,9 +123,14 @@ public class MethodLogAop { public static String getAnnotationRemark(JoinPoint joinPoint) throws Exception { Signature sig = joinPoint.getSignature(); - Method m = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), ((MethodSignature) sig).getParameterTypes()); + //Method m = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), ((MethodSignature) sig).getParameterTypes()); - MethodLog methodCache = m.getAnnotation(MethodLog.class); + MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature(); + Method method = null; + method = methodSignature.getMethod(); + + ReflectionUtils.makeAccessible(method); + MethodLog methodCache = method.getAnnotation(MethodLog.class); if (methodCache != null) { return methodCache.remark(); } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/RestTemplateConfig.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/RestTemplateConfig.java index 23605fd..4f0fcfa 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/RestTemplateConfig.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/RestTemplateConfig.java @@ -1,6 +1,10 @@ package com.jeequan.jeepay.mgr.config; +import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jeequan.jeepay.core.constants.ApiCodeEnum; +import com.jeequan.jeepay.core.exception.BizException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -14,9 +18,12 @@ import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestTemplate; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; @Configuration public class RestTemplateConfig { @@ -53,6 +60,23 @@ public class RestTemplateConfig { */ @Override public void handleError(ClientHttpResponse response) throws IOException { + if (response.getStatusCode().is4xxClientError() + || response.getStatusCode().is5xxServerError()) { + + + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(response.getBody()))) { + String httpBodyResponse = reader.lines() + .collect(Collectors.joining("")); + + ObjectMapper mapper = new ObjectMapper(); + + JSONObject jsonObject = mapper + .readValue(httpBodyResponse, JSONObject.class); + + throw new BizException(ApiCodeEnum.SYSTEM_ERROR, jsonObject.getString("status") + "_" + jsonObject.getString("path") + "_" + jsonObject.getString("error")); + } + } } /** diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/SchedulingConfig.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/SchedulingConfig.java index 4412557..86a4840 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/SchedulingConfig.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/config/SchedulingConfig.java @@ -4,18 +4,22 @@ package com.jeequan.jeepay.mgr.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; @Configuration +@EnableAsync public class SchedulingConfig { @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); // 定时任务执行线程池核心线程数 - taskScheduler.setPoolSize(4); + taskScheduler.setPoolSize(5); taskScheduler.setRemoveOnCancelPolicy(true); taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-"); + taskScheduler.setWaitForTasksToCompleteOnShutdown(true); + taskScheduler.setAwaitTerminationSeconds(60); return taskScheduler; } } \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java new file mode 100644 index 0000000..7b37c12 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java @@ -0,0 +1,122 @@ +package com.jeequan.jeepay.mgr.ctrl.anon; + +import com.jeequan.jeepay.core.aop.MethodLog; +import com.jeequan.jeepay.core.constants.ApiCodeEnum; +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.core.entity.SysJob; +import com.jeequan.jeepay.core.exception.BizException; +import com.jeequan.jeepay.core.model.ApiRes; +import com.jeequan.jeepay.mgr.bootstrap.TaskRunner; +import com.jeequan.jeepay.mgr.task.CronTaskRegistrar; +import com.jeequan.jeepay.mgr.task.SchedulingRunnable; +import com.jeequan.jeepay.service.impl.SysJobService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/api/anon/task") +public class TaskController { + + private static final Logger logger = LoggerFactory.getLogger(TaskRunner.class); + + @Autowired + private SysJobService sysJobService; + + @Autowired + private CronTaskRegistrar cronTaskRegistrar; + + @RequestMapping(value = "/add", method = RequestMethod.POST) + @MethodLog(remark = "添加任务") + public ApiRes taskAdd(SysJob sysJob) throws BizException { + boolean success = sysJobService.save(sysJob); + if (!success) + return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "新增失败"); + else { + if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { + SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); + cronTaskRegistrar.addCronTask(task, sysJob.getCronExpression()); + } + } + return ApiRes.ok(); + } + + @RequestMapping(value = "/modify", method = RequestMethod.POST) + @MethodLog(remark = "修改任务") + public ApiRes taskModify(SysJob sysJob) throws BizException { + boolean success = sysJobService.updateById(sysJob); + if (!success) + return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE, "修改失败"); + else { + //先移除再添加 + if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { + SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); + cronTaskRegistrar.removeCronTask(task); + } + + if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { + SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); + cronTaskRegistrar.addCronTask(task, sysJob.getCronExpression()); + } + } + return ApiRes.ok(); + } + + @RequestMapping(value = "/remove", method = RequestMethod.POST) + @MethodLog(remark = "移除任务") + public ApiRes taskDelete(SysJob sysJob) throws BizException { + boolean success = sysJobService.removeById(sysJob.getJobId()); + if (!success) + return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_DELETE, "删除失败"); + else { + if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { + SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); + cronTaskRegistrar.removeCronTask(task); + } + } + return ApiRes.ok(); + } + + + @RequestMapping(value = "/list", method = RequestMethod.POST) + @MethodLog(remark = "列出所有任务") + public ApiRes taskList() throws BizException { + List sysJobList = sysJobService.list(); + return ApiRes.ok(sysJobList); + } + + + @RequestMapping(value = "/operation", method = RequestMethod.POST) + public ApiRes operation(SysJob existedSysJob) { + SchedulingRunnable task = new SchedulingRunnable(existedSysJob.getBeanName(), existedSysJob.getMethodName(), existedSysJob.getMethodParams()); + if (existedSysJob.getJobStatus().equals(SysJob.NORMAL)) { + cronTaskRegistrar.addCronTask(task, existedSysJob.getCronExpression()); + } else { + cronTaskRegistrar.removeCronTask(task); + } + return ApiRes.ok(); + } + + + @RequestMapping(value = "/once", method = RequestMethod.POST) + @MethodLog(remark = "立即执行任务") + public ApiRes startAtOnce(SysJob sysJob) throws BizException { + sysJob.setCronExpression("0 0 * * * *"); + boolean success = sysJobService.save(sysJob); + if (!success) + return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "执行失败"); + else { + if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { + SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); + cronTaskRegistrar.addCronTask(task, sysJob.getCronExpression()); + } + } + return ApiRes.ok(); + } + +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java new file mode 100644 index 0000000..1605eb0 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java @@ -0,0 +1,37 @@ +package com.jeequan.jeepay.mgr.task; + +import com.jeequan.jeepay.mgr.util.TimeUtil; +import lombok.SneakyThrows; +import org.apache.commons.lang3.tuple.MutablePair; +import org.springframework.transaction.annotation.Transactional; + +public abstract class AbstractAnalysisTask { + + public static final byte CYCLE_DAY = 1; //按天 + public static final byte CYCLE_WEEK_ = 2; //按周 + public static final byte CYCLE_MONTH = 3; //按月 + public static final byte CYCLE_YEAR = 4; //按年 + + protected abstract void process(int period) throws Exception; + + protected MutablePair getPeriod(int period) throws Exception { + String createTimeStart = "";//开始时间 + String createTimeEnd = "";//结束时间 + if (period==CYCLE_YEAR) { + createTimeStart = TimeUtil.getBeforeFirstYearDate(); + createTimeEnd = TimeUtil.getBeforeLastYearDate(); + } else if (period==CYCLE_MONTH) { + createTimeStart = TimeUtil.getBeforeFirstMonthDate(); + createTimeEnd = TimeUtil.getBeforeLastMonthDate(); + } else if (period==CYCLE_DAY) { + createTimeStart = TimeUtil.getBeforeFirstDayDate(); + createTimeEnd = TimeUtil.getBeforeLastDayDate(); + } + else if (period==CYCLE_WEEK_) { + createTimeStart = TimeUtil.getBeforeFirstWeekDate(); + createTimeEnd = TimeUtil.getBeforeLastWeekDate(); + } + return MutablePair.of(createTimeStart, createTimeEnd); + } + +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java index e6a2e19..fda61f8 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java @@ -5,6 +5,7 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.config.CronTask; +import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Component; import java.util.Map; diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java index 537d6a7..194a13b 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java @@ -2,9 +2,11 @@ package com.jeequan.jeepay.mgr.task; import com.jeequan.jeepay.mgr.util.SpringContextUtils; +import com.jeequan.jeepay.service.impl.SysJobService; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java similarity index 58% rename from jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java rename to jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java index fd4d94d..c64262d 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java @@ -1,16 +1,15 @@ package com.jeequan.jeepay.mgr.task.job; -import ch.qos.logback.core.joran.conditional.ElseAction; import cn.hutool.core.collection.CollectionUtil; -import com.alibaba.druid.sql.ast.statement.SQLIfStatement; -import com.alibaba.fastjson.JSONObject; -import com.baomidou.mybatisplus.core.toolkit.IdWorker; -import com.jeequan.jeepay.core.entity.MchApp; +import com.jeequan.jeepay.core.aop.MethodLog; +import com.jeequan.jeepay.core.cache.RedisUtil; import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; import com.jeequan.jeepay.core.entity.OrderStatisticsDept; -import com.jeequan.jeepay.mgr.util.TimeUtil; -import com.jeequan.jeepay.service.impl.*; -import com.jeequan.jeepay.util.JeepayKit; +import com.jeequan.jeepay.mgr.task.AbstractAnalysisTask; +import com.jeequan.jeepay.service.impl.OrderStatisticsCompanyService; +import com.jeequan.jeepay.service.impl.OrderStatisticsDeptService; +import com.jeequan.jeepay.service.impl.PayOrderExtendService; +import com.jeequan.jeepay.service.impl.PayOrderService; import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.MutablePair; @@ -18,18 +17,22 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.http.*; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import java.text.MessageFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -@Component("analysisTask") +@Component("companyAnalysisTask") @Configuration -public class AnalysisTask { +public class CompanyAnalysisTask extends AbstractAnalysisTask { @Value(value = "${qiDi.gateWay.url}") private String gateWay; @@ -52,34 +55,22 @@ public class AnalysisTask { @Autowired private OrderStatisticsDeptService orderStatisticsDeptService; - @Autowired - private OrderStatisticsMerchantService orderStatisticsMerchantService; /** * 根据周期段进行分析 * - * @param cycle 1表示年,2表示月 3表示周 + * @param period 1表示天,2表示周 ,3表示月 4表示年 */ + //@Async + @Override @Transactional(rollbackFor = Exception.class) - public void Analyse(int cycle) throws Exception { - - String createTimeStart = "";//开始时间 - String createTimeEnd = "";//结束时间 - - if (1 == cycle) { - createTimeStart = TimeUtil.getBeforeFirstYearDate(); - createTimeEnd = TimeUtil.getBeforeLastYearDate(); - } else if (2 == cycle) { - createTimeStart = TimeUtil.getBeforeFirstMonthDate(); - createTimeEnd = TimeUtil.getBeforeLastMonthDate(); - } else if (3 == cycle) { - createTimeStart = TimeUtil.getBeforeFirstDayDate(); - createTimeEnd = TimeUtil.getBeforeLastDayDate(); - } + @MethodLog(remark = "企业账单报表分析作业") + protected void process(int period) throws Exception { + + MutablePair timePair = this.getPeriod(period);//时间段 + Long analyseId = System.currentTimeMillis(); //产生版本号 - //产生版本号 - Long analyseId = 0L; - List orderStatisticsDeptList = payOrderService.selectOrderCountByDept(createTimeStart, createTimeEnd); + List orderStatisticsDeptList = payOrderService.selectOrderCountByDept(timePair.left, timePair.right); if (!CollectionUtil.isEmpty(orderStatisticsDeptList)) { orderStatisticsDeptList.forEach(item -> { @@ -87,6 +78,7 @@ public class AnalysisTask { MutablePair mutablePair = getDept(item.getDeptId()); item.setDeptName(mutablePair.right); item.setCompanyName(mutablePair.left); + item.setAnalyseId(analyseId); }); boolean stepOne = orderStatisticsDeptService.saveBatch(orderStatisticsDeptList, 200); if (stepOne) { @@ -99,6 +91,7 @@ public class AnalysisTask { company.setStaticState(OrderStatisticsCompany.ACCOUNT_STATE_NUN); company.setAmountInfact(0L); company.setAnalyseId(analyseId); + company.setRemark("企业账单分析"); company.setDeptName(item.getCompanyName()); return company; }, Collectors.summingLong(OrderStatisticsDept::getAmount))); @@ -123,24 +116,36 @@ public class AnalysisTask { @SneakyThrows private MutablePair getDept(String deptId) { - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - headers.add("X-API-KEY", secretKey); - headers.setContentType(MediaType.APPLICATION_JSON); - - HttpEntity request = - new HttpEntity(null, headers); - ResponseEntity responseMap = restTemplate.exchange(gateWay + MessageFormat.format("/groups/{0}", deptId), HttpMethod.GET, request, Map.class); - - if (responseMap.getStatusCode().equals(HttpStatus.OK)) { - Map responseBody = responseMap.getBody(); - if (!responseBody.isEmpty() && responseBody.containsKey("path")) { - String fullPath = String.valueOf(responseBody.get("path")); - String[] nameArray = StringUtils.split(fullPath, "/"); - return MutablePair.of(nameArray[0], nameArray[1]); + String[] nameArray; + + String organization = RedisUtil.getString(deptId); + if (organization == null || organization.isEmpty()) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.add("X-API-KEY", secretKey); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity request = + new HttpEntity(null, headers); + ResponseEntity responseMap = restTemplate.exchange(gateWay + MessageFormat.format("/groups/{0}", deptId), HttpMethod.GET, request, Map.class); + + if (responseMap.getStatusCode().equals(HttpStatus.OK)) { + Map responseBody = responseMap.getBody(); + if (!responseBody.isEmpty() && responseBody.containsKey("path")) { + + String fullPath = String.valueOf(responseBody.get("path")); + + RedisUtil.set(deptId, fullPath, 30, TimeUnit.DAYS); + + nameArray = StringUtils.split(fullPath, "/"); + return MutablePair.of(nameArray[0], nameArray[1]); + } } + } else { + nameArray = StringUtils.split(organization, "/"); + return MutablePair.of(nameArray[0], nameArray[1]); + } return MutablePair.of("未知", "未知"); } - } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobOneTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobOneTask.java deleted file mode 100644 index ed458e4..0000000 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobOneTask.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.jeequan.jeepay.mgr.task.job; - -import org.springframework.stereotype.Component; - - -@Component("taskJobOne") -public class JobOneTask { - public void taskWithParams(String params) { - System.out.println("taskJobOne-执行有参示例任务:" + params); - } - - public void taskNoParams() { - System.out.println("taskJobOne-执行无参示例任务"); - } -} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobTwoTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobTwoTask.java deleted file mode 100644 index 58cd330..0000000 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/JobTwoTask.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.jeequan.jeepay.mgr.task.job; - -import org.springframework.stereotype.Component; - - -@Component("taskJobTwo") -public class JobTwoTask { - public void taskWithParams(String params) { - System.out.println("taskJobTwo-执行有参示例任务:" + params); - } - - public void taskNoParams() { - System.out.println("taskJobTwo-执行无参示例任务"); - } -} \ No newline at end of file diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java new file mode 100644 index 0000000..f2a3830 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java @@ -0,0 +1,61 @@ +package com.jeequan.jeepay.mgr.task.job; + +import cn.hutool.core.collection.CollectionUtil; +import com.jeequan.jeepay.core.aop.MethodLog; +import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; +import com.jeequan.jeepay.core.entity.OrderStatisticsMerchant; +import com.jeequan.jeepay.mgr.task.AbstractAnalysisTask; +import com.jeequan.jeepay.service.impl.OrderStatisticsMerchantService; +import com.jeequan.jeepay.service.impl.PayOrderExtendService; +import com.jeequan.jeepay.service.impl.PayOrderService; +import org.apache.commons.lang3.tuple.MutablePair; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + + +@Component("merchatAnalysisTask") +@Configuration +public class MerchantAnalysisTask extends AbstractAnalysisTask { + + @Autowired + private PayOrderService payOrderService; + + @Autowired + private PayOrderExtendService payOrderExtendService; + + @Autowired + private OrderStatisticsMerchantService orderStatisticsMerchantService; + + /** + * 根据周期段进行分析 + * + * @param period 1表示天,2表示周 ,3表示月 4表示年 + */ + @Async + @Override + @Transactional(rollbackFor = Exception.class) + @MethodLog(remark = "商户账单报表分析作业") + protected void process(int period) throws Exception { + + MutablePair timePair = this.getPeriod(period);//时间段 + Long analyseId = System.currentTimeMillis();//产生版本号 + ; + List orderStatisticsDeptList = orderStatisticsMerchantService.selectOrderCountByMerchant(timePair.left, timePair.right); + + if (!CollectionUtil.isEmpty(orderStatisticsDeptList)) { + + orderStatisticsDeptList.forEach(item -> { + item.setStaticState(OrderStatisticsCompany.ACCOUNT_STATE_NUN); + item.setAmountInfact(0L); + item.setAnalyseId(analyseId); + }); + orderStatisticsMerchantService.saveBatch(orderStatisticsDeptList, 200); + } + } + +} \ No newline at end of file diff --git a/jeepay-manager/src/main/resources/application.yml b/jeepay-manager/src/main/resources/application.yml index 5613da9..1a4458f 100644 --- a/jeepay-manager/src/main/resources/application.yml +++ b/jeepay-manager/src/main/resources/application.yml @@ -4,8 +4,8 @@ server: spring: redis: database: 1 #1库:运营平台 #2库:商户系统 #3库:支付网关 -# profiles: -# active: dev + profiles: + active: dev qiDi: gateWay: diff --git a/jeepay-manager/src/test/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTaskTest.java b/jeepay-manager/src/test/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTaskTest.java new file mode 100644 index 0000000..1b85262 --- /dev/null +++ b/jeepay-manager/src/test/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTaskTest.java @@ -0,0 +1,25 @@ +package com.jeequan.jeepay.mgr.task.job; + +import com.jeequan.jeepay.mgr.bootstrap.JeepayMgrApplication; +import com.jeequan.jeepay.service.impl.MchAppService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.util.Assert; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest(classes = JeepayMgrApplication.class) +@SpringBootConfiguration +class CompanyAnalysisTaskTest { + + @Autowired(required = false) + private CompanyAnalysisTask companyAnalysisTask; + + @Test + void process() throws Exception { + companyAnalysisTask.process(2); + Assert.isTrue(true, "test successfully"); + } +} \ No newline at end of file diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsMerchantService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsMerchantService.java index a376a68..19b42f7 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsMerchantService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/OrderStatisticsMerchantService.java @@ -1,10 +1,15 @@ package com.jeequan.jeepay.service.impl; +import com.jeequan.jeepay.core.entity.OrderStatisticsDept; import com.jeequan.jeepay.core.entity.OrderStatisticsMerchant; import com.jeequan.jeepay.service.mapper.OrderStatisticsMerchantMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** *

* 订单分析主表 服务实现类 @@ -16,4 +21,11 @@ import org.springframework.stereotype.Service; @Service public class OrderStatisticsMerchantService extends ServiceImpl{ + public List selectOrderCountByMerchant(String createTimeStart, String createTimeEnd) + { + Map paramMap = new HashMap<>(); + paramMap.put("createTimeStart",createTimeStart); + paramMap.put("createTimeEnd",createTimeEnd); + return this.getBaseMapper().selectOrderCountByMerchant(paramMap); + } } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java index 07fcbe8..1e5a1a3 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.java @@ -1,9 +1,11 @@ package com.jeequan.jeepay.service.mapper; +import com.jeequan.jeepay.core.entity.OrderStatisticsDept; import com.jeequan.jeepay.core.entity.OrderStatisticsMerchant; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import java.util.List; +import java.util.Map; /** *

@@ -15,5 +17,17 @@ import java.util.List; */ public interface OrderStatisticsMerchantMapper extends BaseMapper { + /** + * 查询各档口的收入 + * @param param + * @return + */ + List selectOrderCountByMerchant(Map param); + + /** + * 批量插入数据 + * @param orderStatisticsMerchantList + * @return + */ public int insertBatch(List orderStatisticsMerchantList); } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml index 772e457..8ca29d6 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml @@ -33,4 +33,18 @@ #{item.remark}), + + + + diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.xml index c9d1f97..afd27f3 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/PayOrderMapper.xml @@ -88,8 +88,8 @@ join t_pay_order_extend e on o.pay_order_id=e.pay_order_id join t_mch_app a on o.app_id=a.app_id where 1=1 - AND created_at >= #{createTimeStart} - AND created_at <= #{createTimeEnd} + AND o.created_at >= #{createTimeStart} + AND o.created_at <= #{createTimeEnd} and o.state in (2,5) group by e.deptId,o.mch_no,o.mch_name,o.app_id,a.app_name -- Gitee From 49008c6e8a289a4af9a8d29cba113e08931ae289 Mon Sep 17 00:00:00 2001 From: airven <1017091284@qq.com> Date: Fri, 3 Mar 2023 19:24:57 +0800 Subject: [PATCH 28/31] =?UTF-8?q?bug=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/manager/application.yml | 5 + .../jeequan/jeepay/core/entity/SysJob.java | 4 +- .../jeepay/mgr/ctrl/anon/TaskController.java | 98 +++++-------------- .../com/jeequan/jeepay/mgr/rqrs/EnumTime.java | 30 ++++++ .../com/jeequan/jeepay/mgr/rqrs/JobRQ.java | 48 +++++++++ .../jeepay/mgr/task/SchedulingRunnable.java | 10 ++ .../mgr/task/job/CompanyAnalysisTask.java | 3 +- .../mgr/task/job/MerchantAnalysisTask.java | 1 + .../jeepay/service/impl/SysJobService.java | 1 - .../mapper/OrderStatisticsMerchantMapper.xml | 4 +- 10 files changed, 124 insertions(+), 80 deletions(-) create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/EnumTime.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/JobRQ.java diff --git a/conf/manager/application.yml b/conf/manager/application.yml index 6a05473..41a0133 100644 --- a/conf/manager/application.yml +++ b/conf/manager/application.yml @@ -134,3 +134,8 @@ isys: mq: vender: activeMQ # 切换MQ厂商, 支持:【 activeMQ rabbitMQ rocketMQ aliYunRocketMQ 】, 需正确配置 【对应的yml参数】 和 【jeepay-components-mq项目下pom.xml中的依赖包】。 +qiDi: + gateWay: + url: https://api.sz9wang.com/api/v1 + secret-key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3R1eG0uYXJ0IiwidXNlcm5hbWUiOiJ0dXNkZXNpZ24ifQ.0SCNQBLp6_e3EEcQcT0Rqwp1QJ4AonY5eoOTiKMIkk0" + diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java index c8133b1..83eb516 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java @@ -29,8 +29,8 @@ public class SysJob implements Serializable { /** * 任务ID */ - @TableId(value = "job_id", type = IdType.AUTO) - private Integer jobId; + @TableId(value = "job_id", type = IdType.ASSIGN_UUID) + private String jobId; /** * bean名称 */ diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java index 7b37c12..d535220 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java @@ -7,9 +7,12 @@ import com.jeequan.jeepay.core.entity.SysJob; import com.jeequan.jeepay.core.exception.BizException; import com.jeequan.jeepay.core.model.ApiRes; import com.jeequan.jeepay.mgr.bootstrap.TaskRunner; +import com.jeequan.jeepay.mgr.rqrs.EnumTime; +import com.jeequan.jeepay.mgr.rqrs.JobRQ; import com.jeequan.jeepay.mgr.task.CronTaskRegistrar; import com.jeequan.jeepay.mgr.task.SchedulingRunnable; import com.jeequan.jeepay.service.impl.SysJobService; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -18,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.List; +import java.util.Objects; @RestController @RequestMapping("/api/anon/task") @@ -31,82 +35,29 @@ public class TaskController { @Autowired private CronTaskRegistrar cronTaskRegistrar; - @RequestMapping(value = "/add", method = RequestMethod.POST) - @MethodLog(remark = "添加任务") - public ApiRes taskAdd(SysJob sysJob) throws BizException { - boolean success = sysJobService.save(sysJob); - if (!success) - return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "新增失败"); - else { - if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { - SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); - cronTaskRegistrar.addCronTask(task, sysJob.getCronExpression()); - } - } - return ApiRes.ok(); - } + @RequestMapping(value = "/start", method = RequestMethod.POST) + public ApiRes startAtOnce(JobRQ job) throws BizException { - @RequestMapping(value = "/modify", method = RequestMethod.POST) - @MethodLog(remark = "修改任务") - public ApiRes taskModify(SysJob sysJob) throws BizException { - boolean success = sysJobService.updateById(sysJob); - if (!success) - return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE, "修改失败"); - else { - //先移除再添加 - if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { - SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); - cronTaskRegistrar.removeCronTask(task); - } - - if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { - SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); - cronTaskRegistrar.addCronTask(task, sysJob.getCronExpression()); - } + if (Objects.isNull(job.getTaskType())) { + return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "任务类型不能为空"); } - return ApiRes.ok(); - } - - @RequestMapping(value = "/remove", method = RequestMethod.POST) - @MethodLog(remark = "移除任务") - public ApiRes taskDelete(SysJob sysJob) throws BizException { - boolean success = sysJobService.removeById(sysJob.getJobId()); - if (!success) - return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_DELETE, "删除失败"); - else { - if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { - SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); - cronTaskRegistrar.removeCronTask(task); - } + if (StringUtils.isEmpty(job.getCronType())) { + return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "任务周期不能为空"); } - return ApiRes.ok(); - } - - - @RequestMapping(value = "/list", method = RequestMethod.POST) - @MethodLog(remark = "列出所有任务") - public ApiRes taskList() throws BizException { - List sysJobList = sysJobService.list(); - return ApiRes.ok(sysJobList); - } - - - @RequestMapping(value = "/operation", method = RequestMethod.POST) - public ApiRes operation(SysJob existedSysJob) { - SchedulingRunnable task = new SchedulingRunnable(existedSysJob.getBeanName(), existedSysJob.getMethodName(), existedSysJob.getMethodParams()); - if (existedSysJob.getJobStatus().equals(SysJob.NORMAL)) { - cronTaskRegistrar.addCronTask(task, existedSysJob.getCronExpression()); - } else { - cronTaskRegistrar.removeCronTask(task); + SysJob sysJob = new SysJob(); + sysJob.setJobId(job.getJobId()); + sysJob.setJobStatus(SysJob.NORMAL); + sysJob.setMethodName("process"); + sysJob.setMethodParams(String.valueOf(EnumTime.TIMETYPE.get(job.getCronType()))); + + if (job.getTaskType() == 1) { + sysJob.setBeanName("companyAnalysisTask"); + } else if (job.getTaskType() == 2) { + sysJob.setBeanName("merchatAnalysisTask"); + } + if (StringUtils.isEmpty(job.getCronExpression())) { + sysJob.setCronExpression("0 0 * * * *"); } - return ApiRes.ok(); - } - - - @RequestMapping(value = "/once", method = RequestMethod.POST) - @MethodLog(remark = "立即执行任务") - public ApiRes startAtOnce(SysJob sysJob) throws BizException { - sysJob.setCronExpression("0 0 * * * *"); boolean success = sysJobService.save(sysJob); if (!success) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "执行失败"); @@ -116,7 +67,6 @@ public class TaskController { cronTaskRegistrar.addCronTask(task, sysJob.getCronExpression()); } } - return ApiRes.ok(); + return ApiRes.ok(job); } - } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/EnumTime.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/EnumTime.java new file mode 100644 index 0000000..c2dd580 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/EnumTime.java @@ -0,0 +1,30 @@ +package com.jeequan.jeepay.mgr.rqrs; + +public class EnumTime { + + public static enum TIMETYPE { + + DAY("day", 1), + WEEK("week", 2), + MONTH("month", 3), + YEAR("year", 4); + + public String key; + public int value; + + private TIMETYPE(String key, int value) { + this.key = key; + this.value = value; + } + + public static TIMETYPE get(String key) { + TIMETYPE[] values = TIMETYPE.values(); + for (TIMETYPE object : values) { + if (object.key == key) { + return object; + } + } + return null; + } + } +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/JobRQ.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/JobRQ.java new file mode 100644 index 0000000..2299685 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/JobRQ.java @@ -0,0 +1,48 @@ +package com.jeequan.jeepay.mgr.rqrs; + + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import java.util.Date; +import java.util.UUID; + +@Data +public class JobRQ { + + /** + * jobId + */ + @JsonIgnore + private final String jobId= UUID.randomUUID().toString(); + + /** + * 创建时间 + */ + @JsonIgnore + private final Date createTime=new Date(); + + /** + * 更新时间 + */ + @JsonIgnore + private final Date updateTime=new Date(); + + /** + * 任务类型 + */ + private byte taskType; + + /** + * 任务周期 + */ + private String cronType ; + + /** + * cron表达式 + */ + private String cronExpression; + +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java index 194a13b..a5dfabd 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java @@ -11,6 +11,7 @@ import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; import java.util.Objects; +import java.util.UUID; public class SchedulingRunnable implements Runnable { @@ -22,14 +23,23 @@ public class SchedulingRunnable implements Runnable { private String params; + private String jobId; + public SchedulingRunnable(String beanName, String methodName) { this(beanName, methodName, null); } public SchedulingRunnable(String beanName, String methodName, String params) { + this(beanName, methodName, params, UUID.randomUUID().toString()); + this.beanName = beanName; + this.methodName = methodName; + this.params = params; + } + public SchedulingRunnable(String beanName, String methodName, String params,String jobId) { this.beanName = beanName; this.methodName = methodName; this.params = params; + this.jobId=jobId; } @Override diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java index c64262d..7306d3e 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java @@ -118,6 +118,7 @@ public class CompanyAnalysisTask extends AbstractAnalysisTask { String[] nameArray; + //先去缓存中查一下 String organization = RedisUtil.getString(deptId); if (organization == null || organization.isEmpty()) { RestTemplate restTemplate = new RestTemplate(); @@ -135,7 +136,7 @@ public class CompanyAnalysisTask extends AbstractAnalysisTask { String fullPath = String.valueOf(responseBody.get("path")); - RedisUtil.set(deptId, fullPath, 30, TimeUnit.DAYS); + RedisUtil.setString(deptId, fullPath, 30, TimeUnit.DAYS); nameArray = StringUtils.split(fullPath, "/"); return MutablePair.of(nameArray[0], nameArray[1]); diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java index f2a3830..9f34e9f 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java @@ -52,6 +52,7 @@ public class MerchantAnalysisTask extends AbstractAnalysisTask { orderStatisticsDeptList.forEach(item -> { item.setStaticState(OrderStatisticsCompany.ACCOUNT_STATE_NUN); item.setAmountInfact(0L); + item.setRemark("商户账单报表分析作业"); item.setAnalyseId(analyseId); }); orderStatisticsMerchantService.saveBatch(orderStatisticsDeptList, 200); diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobService.java index 330d851..48d66f4 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobService.java @@ -15,5 +15,4 @@ import org.springframework.stereotype.Service; */ @Service public class SysJobService extends ServiceImpl { - } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml index 8ca29d6..0c05a3d 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/OrderStatisticsMerchantMapper.xml @@ -41,8 +41,8 @@ join t_pay_order_extend e on o.pay_order_id=e.pay_order_id join t_mch_app a on o.app_id=a.app_id where 1=1 - AND created_at >= #{createTimeStart} - AND created_at <= #{createTimeEnd} + AND o.created_at >= #{createTimeStart} + AND o.created_at <= #{createTimeEnd} and o.state in (2,5) group by o.mch_no,o.mch_name,o.app_id,a.app_name -- Gitee From 7626d23f442e48aacaeb186d71795743493bc6f1 Mon Sep 17 00:00:00 2001 From: chengzhengwen Date: Sat, 4 Mar 2023 11:37:06 +0800 Subject: [PATCH 29/31] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jeequan/jeepay/mgr/aop/MethodLogAop.java | 4 ++++ .../jeepay/mgr/bootstrap/TaskRunner.java | 2 +- .../jeepay/mgr/ctrl/anon/TaskController.java | 2 +- .../jeepay/mgr/task/AbstractAnalysisTask.java | 18 +++++++----------- .../jeepay/mgr/task/SchedulingRunnable.java | 2 ++ .../mgr/task/job/CompanyAnalysisTask.java | 3 +-- .../mgr/task/job/MerchantAnalysisTask.java | 4 +--- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java index 313eba6..17f4505 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java @@ -40,6 +40,7 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Date; import java.util.concurrent.Executors; @@ -129,6 +130,9 @@ public class MethodLogAop { Method method = null; method = methodSignature.getMethod(); + //Field field= methodSignature.getClass().getDeclaredField("userName"); + //String str=String.valueOf(field.get(joinPoint.getThis())); + ReflectionUtils.makeAccessible(method); MethodLog methodCache = method.getAnnotation(MethodLog.class); if (methodCache != null) { diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java index df1f9b3..1df95be 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java @@ -35,7 +35,7 @@ public class TaskRunner implements CommandLineRunner { if (CollectionUtils.isNotEmpty(jobList)) { for (SysJob job : jobList) { - SchedulingRunnable task = new SchedulingRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams()); + SchedulingRunnable task = new SchedulingRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams(),job.getJobId()); cronTaskRegistrar.addCronTask(task, job.getCronExpression()); } logger.info("定时任务已加载完毕..."); diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java index d535220..9f32a0d 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java @@ -63,7 +63,7 @@ public class TaskController { return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "执行失败"); else { if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { - SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams()); + SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams(),sysJob.getJobId()); cronTaskRegistrar.addCronTask(task, sysJob.getCronExpression()); } } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java index 1605eb0..5f304b1 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java @@ -1,5 +1,6 @@ package com.jeequan.jeepay.mgr.task; +import com.jeequan.jeepay.mgr.rqrs.EnumTime; import com.jeequan.jeepay.mgr.util.TimeUtil; import lombok.SneakyThrows; import org.apache.commons.lang3.tuple.MutablePair; @@ -7,27 +8,22 @@ import org.springframework.transaction.annotation.Transactional; public abstract class AbstractAnalysisTask { - public static final byte CYCLE_DAY = 1; //按天 - public static final byte CYCLE_WEEK_ = 2; //按周 - public static final byte CYCLE_MONTH = 3; //按月 - public static final byte CYCLE_YEAR = 4; //按年 + protected abstract void process(String period) throws Exception; - protected abstract void process(int period) throws Exception; - - protected MutablePair getPeriod(int period) throws Exception { + protected MutablePair getPeriod(String period) throws Exception { String createTimeStart = "";//开始时间 String createTimeEnd = "";//结束时间 - if (period==CYCLE_YEAR) { + if (EnumTime.TIMETYPE.YEAR.key==period) { createTimeStart = TimeUtil.getBeforeFirstYearDate(); createTimeEnd = TimeUtil.getBeforeLastYearDate(); - } else if (period==CYCLE_MONTH) { + } else if (EnumTime.TIMETYPE.MONTH.key==period) { createTimeStart = TimeUtil.getBeforeFirstMonthDate(); createTimeEnd = TimeUtil.getBeforeLastMonthDate(); - } else if (period==CYCLE_DAY) { + } else if (EnumTime.TIMETYPE.DAY.key==period) { createTimeStart = TimeUtil.getBeforeFirstDayDate(); createTimeEnd = TimeUtil.getBeforeLastDayDate(); } - else if (period==CYCLE_WEEK_) { + else if (EnumTime.TIMETYPE.WEEK.key==period) { createTimeStart = TimeUtil.getBeforeFirstWeekDate(); createTimeEnd = TimeUtil.getBeforeLastWeekDate(); } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java index a5dfabd..8a11a18 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java @@ -1,6 +1,7 @@ package com.jeequan.jeepay.mgr.task; +import com.jeequan.jeepay.core.aop.MethodLog; import com.jeequan.jeepay.mgr.util.SpringContextUtils; import com.jeequan.jeepay.service.impl.SysJobService; import org.apache.commons.lang3.StringUtils; @@ -43,6 +44,7 @@ public class SchedulingRunnable implements Runnable { } @Override + @MethodLog(remark = "fkdjfdk") public void run() { logger.info("定时任务开始执行 - bean:{},方法:{},参数:{}", beanName, methodName, params); long startTime = System.currentTimeMillis(); diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java index 7306d3e..9015246 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java @@ -64,8 +64,7 @@ public class CompanyAnalysisTask extends AbstractAnalysisTask { //@Async @Override @Transactional(rollbackFor = Exception.class) - @MethodLog(remark = "企业账单报表分析作业") - protected void process(int period) throws Exception { + protected void process(String period) throws Exception { MutablePair timePair = this.getPeriod(period);//时间段 Long analyseId = System.currentTimeMillis(); //产生版本号 diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java index 9f34e9f..ea36341 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java @@ -36,11 +36,9 @@ public class MerchantAnalysisTask extends AbstractAnalysisTask { * * @param period 1表示天,2表示周 ,3表示月 4表示年 */ - @Async @Override @Transactional(rollbackFor = Exception.class) - @MethodLog(remark = "商户账单报表分析作业") - protected void process(int period) throws Exception { + protected void process(String period) throws Exception { MutablePair timePair = this.getPeriod(period);//时间段 Long analyseId = System.currentTimeMillis();//产生版本号 -- Gitee From 8b47162b397d5d444012fa98c28270ed24b65163 Mon Sep 17 00:00:00 2001 From: airven <1017091284@qq.com> Date: Sat, 4 Mar 2023 17:03:25 +0800 Subject: [PATCH 30/31] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jeequan/jeepay/core/entity/SysJob.java | 4 +- .../jeequan/jeepay/core/entity/SysJobLog.java | 67 ++++++++ .../com/jeequan/jeepay/mgr/aop/JobLogAop.java | 150 ++++++++++++++++++ .../jeequan/jeepay/mgr/aop/MethodLogAop.java | 3 - .../jeepay/mgr/bootstrap/TaskRunner.java | 88 +++++----- .../jeepay/mgr/ctrl/anon/TaskController.java | 37 +++-- .../com/jeequan/jeepay/mgr/rqrs/EnumTime.java | 2 +- .../jeepay/mgr/task/CronTaskRegistrar.java | 9 +- .../jeepay/mgr/task/SchedulingRunnable.java | 11 +- .../AbstractAnalysisJob.java} | 10 +- ...lysisTask.java => CompanyAnalysisJob.java} | 11 +- ...ysisTask.java => MerchantAnalysisJob.java} | 11 +- .../mgr/task/job/CompanyAnalysisTaskTest.java | 49 +++--- .../jeepay/service/impl/SysJobLogService.java | 19 +++ .../service/mapper/SysJobLogMapper.java | 16 ++ .../jeepay/service/mapper/SysJobLogMapper.xml | 16 ++ .../src/main/java/com/gen/MainGen.java | 8 +- 17 files changed, 394 insertions(+), 117 deletions(-) create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJobLog.java create mode 100644 jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/JobLogAop.java rename jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/{AbstractAnalysisTask.java => job/AbstractAnalysisJob.java} (82%) rename jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/{CompanyAnalysisTask.java => CompanyAnalysisJob.java} (94%) rename jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/{MerchantAnalysisTask.java => MerchantAnalysisJob.java} (85%) create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobLogService.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobLogMapper.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobLogMapper.xml diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java index 83eb516..1d6c733 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJob.java @@ -58,11 +58,11 @@ public class SysJob implements Serializable { /** * 创建时间 */ - private Date createTime; + private Date createTime=new Date(); /** * 更新时间 */ - private Date updateTime; + private Date updateTime=new Date(); } \ No newline at end of file diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJobLog.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJobLog.java new file mode 100644 index 0000000..bd31a2b --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/SysJobLog.java @@ -0,0 +1,67 @@ +package com.jeequan.jeepay.core.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.util.Date; +import java.io.Serializable; +import java.util.UUID; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 定时任务日志表 + *

+ * + * @author [mybatis plus generator] + * @since 2023-03-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_sys_job_log") +public class SysJobLog implements Serializable { + + private static final long serialVersionUID=1L; + + /** + * 主键编号 + */ + @TableId(value = "id", type = IdType.ASSIGN_UUID) + private String id; + + /** + * 任务id + */ + private String jobId; + + /** + * 执行结束时间 + */ + private Date exectueEndTime; + + /** + * 执行开始时间 + */ + private Date exectueStartTime; + + /** + * Y成功,N失败 + */ + private String exectueResult; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/JobLogAop.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/JobLogAop.java new file mode 100644 index 0000000..0f6dc88 --- /dev/null +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/JobLogAop.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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 com.jeequan.jeepay.mgr.aop; + +import com.alibaba.fastjson.JSONObject; +import com.jeequan.jeepay.core.aop.Action; +import com.jeequan.jeepay.core.aop.MethodLog; +import com.jeequan.jeepay.core.beans.RequestKitBean; +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.core.entity.SysJobLog; +import com.jeequan.jeepay.core.entity.SysLog; +import com.jeequan.jeepay.core.exception.BizException; +import com.jeequan.jeepay.core.model.security.JeeUserDetails; +import com.jeequan.jeepay.service.impl.SysJobLogService; +import com.jeequan.jeepay.service.impl.SysLogService; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.ReflectionUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Date; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +/** + * 方法级日志切面组件 + * + * @author chengzhengwen + * @site https://www.jeequan.com + * @date 2023-03-04 07:15 + */ +@Component +@Aspect +public class JobLogAop { + + private static final Logger logger = LoggerFactory.getLogger(JobLogAop.class); + + @Autowired + private SysJobLogService sysJobLogService; + + /** + * 异步处理线程池 + */ + private final static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10); + + /** + * 切点 + */ + @Pointcut("@annotation(com.jeequan.jeepay.core.aop.Action)") + public void methodJobPointcut() { + } + + /** + * 切面 + * @param point + * @return + * @throws Throwable + */ + @Around("methodJobPointcut()") + public Object around(ProceedingJoinPoint point) throws Throwable { + + final SysJobLog jobLog = new SysJobLog(); + jobLog.setCreateTime(new Date()); + jobLog.setExectueStartTime(new Date()); + + Object result = point.proceed(); + + try { + result=point.proceed(); + // 基础日志信息 + setJobLogInfo(point, jobLog); + scheduledThreadPool.execute(() -> sysJobLogService.save(jobLog)); + } catch (Exception e) { + jobLog.setRemark("methodLogError:"+ e.getMessage()); + logger.error("methodLogError", e); + }finally { + // scheduledThreadPool.execute(() -> sysJobLogService.save(jobLog)); + } + return result; + } + + /** + * @describe: 记录异常操作请求信息 + */ + @AfterThrowing(pointcut = "methodJobPointcut()", throwing = "e") + public void doException(JoinPoint joinPoint, Throwable e) throws Exception { + + final SysJobLog jobLog = new SysJobLog(); + setJobLogInfo(joinPoint, jobLog); + jobLog.setRemark(e instanceof BizException ? e.getMessage() : "请求异常"); + jobLog.setExectueResult("N"); + scheduledThreadPool.execute(() -> sysJobLogService.save(jobLog)); + } + + + /** + * @describe: job日志基本信息 公共方法 + */ + private void setJobLogInfo(JoinPoint joinPoint, SysJobLog jobLog) throws Exception { + + Signature sig = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + + ReflectionUtils.makeAccessible(method); + + Object [] objects= joinPoint.getArgs(); + jobLog.setJobId(objects[1].toString()); + + // Field jobIdField = methodSignature.getClass().getDeclaredField("jobId"); + // String jobId = String.valueOf(jobIdField.get(joinPoint.getThis())); + // jobLog.setJobId(jobId); + // + // Field beanField = methodSignature.getClass().getDeclaredField("beanName"); + // String beanName = String.valueOf(beanField.get(joinPoint.getThis())); + + Action methodCache = method.getAnnotation(Action.class); + jobLog.setRemark(methodCache != null ? String.format("任务id:%s,任务名称:%s 执行成功",jobLog.getJobId(),methodCache.value()):""); + jobLog.setExectueEndTime(new Date()); + jobLog.setExectueResult("Y"); + } + +} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java index 17f4505..1ec6c3a 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/aop/MethodLogAop.java @@ -130,9 +130,6 @@ public class MethodLogAop { Method method = null; method = methodSignature.getMethod(); - //Field field= methodSignature.getClass().getDeclaredField("userName"); - //String str=String.valueOf(field.get(joinPoint.getThis())); - ReflectionUtils.makeAccessible(method); MethodLog methodCache = method.getAnnotation(MethodLog.class); if (methodCache != null) { diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java index 1df95be..a0a446d 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/bootstrap/TaskRunner.java @@ -1,44 +1,44 @@ -package com.jeequan.jeepay.mgr.bootstrap; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; -import com.jeequan.jeepay.core.entity.MchNotifyRecord; -import com.jeequan.jeepay.core.entity.SysJob; -import com.jeequan.jeepay.mgr.task.CronTaskRegistrar; -import com.jeequan.jeepay.mgr.task.SchedulingRunnable; -import com.jeequan.jeepay.service.impl.SysJobService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -public class TaskRunner implements CommandLineRunner { - - private static final Logger logger = LoggerFactory.getLogger(TaskRunner.class); - - @Autowired - private SysJobService sysJobService; - - @Autowired - private CronTaskRegistrar cronTaskRegistrar; - - @Override - public void run(String... args) throws Exception { - - // 初始加载数据库里状态为正常的定时任务 - LambdaQueryWrapper wrapper = SysJob.gw(); - List jobList = sysJobService.list(wrapper.eq(SysJob::getJobStatus, SysJob.NORMAL)); - - if (CollectionUtils.isNotEmpty(jobList)) { - for (SysJob job : jobList) { - SchedulingRunnable task = new SchedulingRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams(),job.getJobId()); - cronTaskRegistrar.addCronTask(task, job.getCronExpression()); - } - logger.info("定时任务已加载完毕..."); - } - } -} +//package com.jeequan.jeepay.mgr.bootstrap; +// +//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +//import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +//import com.jeequan.jeepay.core.entity.MchNotifyRecord; +//import com.jeequan.jeepay.core.entity.SysJob; +//import com.jeequan.jeepay.mgr.task.CronTaskRegistrar; +//import com.jeequan.jeepay.mgr.task.SchedulingRunnable; +//import com.jeequan.jeepay.service.impl.SysJobService; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.CommandLineRunner; +//import org.springframework.stereotype.Component; +// +//import java.util.List; +// +//@Component +//public class TaskRunner implements CommandLineRunner { +// +// private static final Logger logger = LoggerFactory.getLogger(TaskRunner.class); +// +// @Autowired +// private SysJobService sysJobService; +// +// @Autowired +// private CronTaskRegistrar cronTaskRegistrar; +// +// @Override +// public void run(String... args) throws Exception { +// +// // 初始加载数据库里状态为正常的定时任务 +// LambdaQueryWrapper wrapper = SysJob.gw(); +// List jobList = sysJobService.list(wrapper.eq(SysJob::getJobStatus, SysJob.NORMAL)); +// +// if (CollectionUtils.isNotEmpty(jobList)) { +// for (SysJob job : jobList) { +// SchedulingRunnable task = new SchedulingRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams(),job.getJobId()); +// cronTaskRegistrar.addCronTask(task, job.getCronExpression()); +// } +// logger.info("定时任务已加载完毕..."); +// } +// } +//} diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java index 9f32a0d..2a0cd32 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/anon/TaskController.java @@ -6,7 +6,6 @@ import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.entity.SysJob; import com.jeequan.jeepay.core.exception.BizException; import com.jeequan.jeepay.core.model.ApiRes; -import com.jeequan.jeepay.mgr.bootstrap.TaskRunner; import com.jeequan.jeepay.mgr.rqrs.EnumTime; import com.jeequan.jeepay.mgr.rqrs.JobRQ; import com.jeequan.jeepay.mgr.task.CronTaskRegistrar; @@ -16,10 +15,12 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -27,7 +28,13 @@ import java.util.Objects; @RequestMapping("/api/anon/task") public class TaskController { - private static final Logger logger = LoggerFactory.getLogger(TaskRunner.class); + private static final Logger logger = LoggerFactory.getLogger(TaskController.class); + + //企业账单job + private final String COMPANYJOB = "companyAnalysisJob"; + + //商户账单job + private final String MERCHANTJOB = "merchatAnalysisJob"; @Autowired private SysJobService sysJobService; @@ -36,34 +43,36 @@ public class TaskController { private CronTaskRegistrar cronTaskRegistrar; @RequestMapping(value = "/start", method = RequestMethod.POST) - public ApiRes startAtOnce(JobRQ job) throws BizException { + public ApiRes startAtOnce(@RequestBody JobRQ job) throws BizException { if (Objects.isNull(job.getTaskType())) { - return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "任务类型不能为空"); + return ApiRes.fail(ApiCodeEnum.PARAMS_ERROR, "任务类型不能为空"); } if (StringUtils.isEmpty(job.getCronType())) { - return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "任务周期不能为空"); + return ApiRes.fail(ApiCodeEnum.PARAMS_ERROR, "任务周期不能为空"); } + if (Arrays.asList(1, 2).contains(job.getTaskType())) { + return ApiRes.fail(ApiCodeEnum.PARAMS_ERROR, "任务类型不存在"); + } + SysJob sysJob = new SysJob(); sysJob.setJobId(job.getJobId()); sysJob.setJobStatus(SysJob.NORMAL); sysJob.setMethodName("process"); - sysJob.setMethodParams(String.valueOf(EnumTime.TIMETYPE.get(job.getCronType()))); + sysJob.setMethodParams(String.valueOf(EnumTime.TIMETYPE.get(job.getCronType()).key)); + + + if (job.getTaskType() == 1) sysJob.setBeanName(COMPANYJOB); + if (job.getTaskType() == 2) sysJob.setBeanName(MERCHANTJOB); - if (job.getTaskType() == 1) { - sysJob.setBeanName("companyAnalysisTask"); - } else if (job.getTaskType() == 2) { - sysJob.setBeanName("merchatAnalysisTask"); - } if (StringUtils.isEmpty(job.getCronExpression())) { sysJob.setCronExpression("0 0 * * * *"); } - boolean success = sysJobService.save(sysJob); - if (!success) + if (!sysJobService.save(sysJob)) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE, "执行失败"); else { if (sysJob.getJobStatus().equals(SysJob.NORMAL)) { - SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams(),sysJob.getJobId()); + SchedulingRunnable task = new SchedulingRunnable(sysJob.getBeanName(), sysJob.getMethodName(), sysJob.getMethodParams(), sysJob.getJobId()); cronTaskRegistrar.addCronTask(task, sysJob.getCronExpression()); } } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/EnumTime.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/EnumTime.java index c2dd580..6a0b138 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/EnumTime.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/rqrs/EnumTime.java @@ -20,7 +20,7 @@ public class EnumTime { public static TIMETYPE get(String key) { TIMETYPE[] values = TIMETYPE.values(); for (TIMETYPE object : values) { - if (object.key == key) { + if (object.key.equals(key)) { return object; } } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java index fda61f8..e8c8d41 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/CronTaskRegistrar.java @@ -1,6 +1,7 @@ package com.jeequan.jeepay.mgr.task; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.TaskScheduler; @@ -8,6 +9,7 @@ import org.springframework.scheduling.config.CronTask; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Component; +import java.util.Date; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -45,7 +47,12 @@ public class CronTaskRegistrar implements DisposableBean { public ScheduledTask scheduleCronTask(CronTask cronTask) { ScheduledTask scheduledTask = new ScheduledTask(); - scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger()); + if(cronTask.getExpression().equals("0 0 * * * *")){ + scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(),new Date()); + }else if(!StringUtils.isEmpty(cronTask.getExpression())){ + scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger()); + } + return scheduledTask; } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java index 8a11a18..290433b 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/SchedulingRunnable.java @@ -1,13 +1,10 @@ package com.jeequan.jeepay.mgr.task; -import com.jeequan.jeepay.core.aop.MethodLog; import com.jeequan.jeepay.mgr.util.SpringContextUtils; -import com.jeequan.jeepay.service.impl.SysJobService; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; @@ -26,6 +23,8 @@ public class SchedulingRunnable implements Runnable { private String jobId; + public SchedulingRunnable(){} + public SchedulingRunnable(String beanName, String methodName) { this(beanName, methodName, null); } @@ -44,8 +43,8 @@ public class SchedulingRunnable implements Runnable { } @Override - @MethodLog(remark = "fkdjfdk") public void run() { + logger.info("定时任务开始执行 - bean:{},方法:{},参数:{}", beanName, methodName, params); long startTime = System.currentTimeMillis(); @@ -54,14 +53,14 @@ public class SchedulingRunnable implements Runnable { Method method = null; if (StringUtils.isNotEmpty(params)) { - method = target.getClass().getDeclaredMethod(methodName, String.class); + method = target.getClass().getDeclaredMethod(methodName, String.class,String.class); } else { method = target.getClass().getDeclaredMethod(methodName); } ReflectionUtils.makeAccessible(method); if (StringUtils.isNotEmpty(params)) { - method.invoke(target, params); + method.invoke(target, params,this.jobId); } else { method.invoke(target); } diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AbstractAnalysisJob.java similarity index 82% rename from jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java rename to jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AbstractAnalysisJob.java index 5f304b1..7762084 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/AbstractAnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/AbstractAnalysisJob.java @@ -1,18 +1,18 @@ -package com.jeequan.jeepay.mgr.task; +package com.jeequan.jeepay.mgr.task.job; import com.jeequan.jeepay.mgr.rqrs.EnumTime; import com.jeequan.jeepay.mgr.util.TimeUtil; -import lombok.SneakyThrows; import org.apache.commons.lang3.tuple.MutablePair; -import org.springframework.transaction.annotation.Transactional; -public abstract class AbstractAnalysisTask { +public abstract class AbstractAnalysisJob { - protected abstract void process(String period) throws Exception; + public abstract void process(String period,String jobId) throws Exception; protected MutablePair getPeriod(String period) throws Exception { + String createTimeStart = "";//开始时间 String createTimeEnd = "";//结束时间 + if (EnumTime.TIMETYPE.YEAR.key==period) { createTimeStart = TimeUtil.getBeforeFirstYearDate(); createTimeEnd = TimeUtil.getBeforeLastYearDate(); diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisJob.java similarity index 94% rename from jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java rename to jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisJob.java index 9015246..3498cfc 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisJob.java @@ -1,11 +1,10 @@ package com.jeequan.jeepay.mgr.task.job; import cn.hutool.core.collection.CollectionUtil; -import com.jeequan.jeepay.core.aop.MethodLog; +import com.jeequan.jeepay.core.aop.Action; import com.jeequan.jeepay.core.cache.RedisUtil; import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; import com.jeequan.jeepay.core.entity.OrderStatisticsDept; -import com.jeequan.jeepay.mgr.task.AbstractAnalysisTask; import com.jeequan.jeepay.service.impl.OrderStatisticsCompanyService; import com.jeequan.jeepay.service.impl.OrderStatisticsDeptService; import com.jeequan.jeepay.service.impl.PayOrderExtendService; @@ -17,7 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.http.*; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.RestTemplate; @@ -30,9 +28,9 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -@Component("companyAnalysisTask") +@Component("companyAnalysisJob") @Configuration -public class CompanyAnalysisTask extends AbstractAnalysisTask { +public class CompanyAnalysisJob extends AbstractAnalysisJob { @Value(value = "${qiDi.gateWay.url}") private String gateWay; @@ -64,7 +62,8 @@ public class CompanyAnalysisTask extends AbstractAnalysisTask { //@Async @Override @Transactional(rollbackFor = Exception.class) - protected void process(String period) throws Exception { + @Action("企业账单报表分析") + public void process(String period,String jobId) throws Exception { MutablePair timePair = this.getPeriod(period);//时间段 Long analyseId = System.currentTimeMillis(); //产生版本号 diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisJob.java similarity index 85% rename from jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java rename to jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisJob.java index ea36341..30fc468 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisTask.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisJob.java @@ -1,26 +1,24 @@ package com.jeequan.jeepay.mgr.task.job; import cn.hutool.core.collection.CollectionUtil; -import com.jeequan.jeepay.core.aop.MethodLog; +import com.jeequan.jeepay.core.aop.Action; import com.jeequan.jeepay.core.entity.OrderStatisticsCompany; import com.jeequan.jeepay.core.entity.OrderStatisticsMerchant; -import com.jeequan.jeepay.mgr.task.AbstractAnalysisTask; import com.jeequan.jeepay.service.impl.OrderStatisticsMerchantService; import com.jeequan.jeepay.service.impl.PayOrderExtendService; import com.jeequan.jeepay.service.impl.PayOrderService; import org.apache.commons.lang3.tuple.MutablePair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import java.util.List; -@Component("merchatAnalysisTask") +@Component("merchatAnalysisJob") @Configuration -public class MerchantAnalysisTask extends AbstractAnalysisTask { +public class MerchantAnalysisJob extends AbstractAnalysisJob { @Autowired private PayOrderService payOrderService; @@ -37,8 +35,9 @@ public class MerchantAnalysisTask extends AbstractAnalysisTask { * @param period 1表示天,2表示周 ,3表示月 4表示年 */ @Override + @Action("商户账单报表分析") @Transactional(rollbackFor = Exception.class) - protected void process(String period) throws Exception { + public void process(String period,String jobId) throws Exception { MutablePair timePair = this.getPeriod(period);//时间段 Long analyseId = System.currentTimeMillis();//产生版本号 diff --git a/jeepay-manager/src/test/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTaskTest.java b/jeepay-manager/src/test/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTaskTest.java index 1b85262..55fcc58 100644 --- a/jeepay-manager/src/test/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTaskTest.java +++ b/jeepay-manager/src/test/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisTaskTest.java @@ -1,25 +1,24 @@ -package com.jeequan.jeepay.mgr.task.job; - -import com.jeequan.jeepay.mgr.bootstrap.JeepayMgrApplication; -import com.jeequan.jeepay.service.impl.MchAppService; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.util.Assert; - -import static org.junit.jupiter.api.Assertions.*; - -@SpringBootTest(classes = JeepayMgrApplication.class) -@SpringBootConfiguration -class CompanyAnalysisTaskTest { - - @Autowired(required = false) - private CompanyAnalysisTask companyAnalysisTask; - - @Test - void process() throws Exception { - companyAnalysisTask.process(2); - Assert.isTrue(true, "test successfully"); - } -} \ No newline at end of file +//package com.jeequan.jeepay.mgr.task.job; +// +//import com.jeequan.jeepay.mgr.bootstrap.JeepayMgrApplication; +//import jdk.nashorn.internal.ir.annotations.Ignore; +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.SpringBootConfiguration; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.util.Assert; +// +//@SpringBootTest(classes = JeepayMgrApplication.class) +//@SpringBootConfiguration +//class CompanyAnalysisTaskTest { +// +// @Autowired(required = false) +// private CompanyAnalysisJob companyAnalysisTask; +// +// @Test +// @Ignore +// void process() throws Exception { +// companyAnalysisTask.process("month"); +// Assert.isTrue(true, "test successfully"); +// } +//} \ No newline at end of file diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobLogService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobLogService.java new file mode 100644 index 0000000..f97ed3a --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/SysJobLogService.java @@ -0,0 +1,19 @@ +package com.jeequan.jeepay.service.impl; + +import com.jeequan.jeepay.core.entity.SysJobLog; +import com.jeequan.jeepay.service.mapper.SysJobLogMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 定时任务日志表 服务实现类 + *

+ * + * @author [mybatis plus generator] + * @since 2023-03-04 + */ +@Service +public class SysJobLogService extends ServiceImpl{ + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobLogMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobLogMapper.java new file mode 100644 index 0000000..33912d4 --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobLogMapper.java @@ -0,0 +1,16 @@ +package com.jeequan.jeepay.service.mapper; + +import com.jeequan.jeepay.core.entity.SysJobLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 定时任务日志表 Mapper 接口 + *

+ * + * @author [mybatis plus generator] + * @since 2023-03-04 + */ +public interface SysJobLogMapper extends BaseMapper { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobLogMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobLogMapper.xml new file mode 100644 index 0000000..381ba8c --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/SysJobLogMapper.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/jeepay-z-codegen/src/main/java/com/gen/MainGen.java b/jeepay-z-codegen/src/main/java/com/gen/MainGen.java index eadb738..3122976 100644 --- a/jeepay-z-codegen/src/main/java/com/gen/MainGen.java +++ b/jeepay-z-codegen/src/main/java/com/gen/MainGen.java @@ -20,14 +20,14 @@ public class MainGen { public static final String THIS_MODULE_NAME = "jeepay-z-codegen"; //当前项目名称 - public static final String DB_URL = "jdbc:mysql://127.0.0.1:3307/jeepaydb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"; - public static final String DB_USERNAME = "123"; - public static final String DB_PASSWORD = "123"; + public static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/jeepaydb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"; + public static final String DB_USERNAME = "root"; + public static final String DB_PASSWORD = "root123"; // 多个用, 拼接 //public static final String TABLE_NAMES= "t_sys_entitlement,t_sys_role,t_sys_user,t_sys_user_auth"; - public static final String TABLE_NAMES= "t_pay_order_extend,t_order_statistics_company,t_order_statistics_dept,t_order_statistics_merchant"; + public static final String TABLE_NAMES= "t_sys_job_log"; public static void main(String[] args) { -- Gitee From 88a0e4e3b698fe328704769bd9a97aa8703f86a7 Mon Sep 17 00:00:00 2001 From: airven <1017091284@qq.com> Date: Mon, 6 Mar 2023 09:31:24 +0800 Subject: [PATCH 31/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sql/init.sql | 45 ++++++- docs/sql/patch-20230305.sql | 115 ++++++++++++++++++ .../core/entity/OrderStatisticsCompany.java | 5 +- .../core/entity/OrderStatisticsDept.java | 3 +- .../core/entity/OrderStatisticsMerchant.java | 4 +- .../mgr/task/job/CompanyAnalysisJob.java | 6 +- .../mgr/task/job/MerchantAnalysisJob.java | 2 +- .../src/main/resources/application.yml | 4 +- 8 files changed, 168 insertions(+), 16 deletions(-) create mode 100644 docs/sql/patch-20230305.sql diff --git a/docs/sql/init.sql b/docs/sql/init.sql index a705a93..c786cb2 100644 --- a/docs/sql/init.sql +++ b/docs/sql/init.sql @@ -505,9 +505,9 @@ CREATE TABLE `t_order_statistics_company` ( `app_id` varchar(64) NOT NULL COMMENT '应用ID', `app_name` varchar(64) NOT NULL COMMENT '应用名称', `mch_name` varchar(30) NOT NULL COMMENT '商户名称', - `amount` bigint NOT NULL COMMENT '企业账单金额,单位分', + `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '企业账单金额,单位分', `dept_name` varchar(100) NOT NULL COMMENT '组织名称:企业名称或者部门名称', - `amount_infact` bigint NOT NULL DEFAULT '0' COMMENT '实付金额', + `amount_infact` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '实付金额', `analyse_id` bigint DEFAULT NULL COMMENT '报表分析标识', `static_state` tinyint NOT NULL DEFAULT '0' COMMENT '结账状态, 0-已结账, 1-未结账', `remark` varchar(512) NOT NULL COMMENT '备注', @@ -530,7 +530,7 @@ CREATE TABLE `t_order_statistics_dept` ( `app_name` varchar(64) NOT NULL COMMENT '应用名称', `mch_name` varchar(30) NOT NULL COMMENT '商户名称', `dept_name` varchar(100) NOT NULL COMMENT '部门名称', - `amount` bigint NOT NULL COMMENT '部门账单金额,单位分', + `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '部门账单金额,单位分', `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', PRIMARY KEY (`id`), KEY `created_at` (`created_at`) @@ -548,8 +548,8 @@ CREATE TABLE `t_order_statistics_merchant` ( `app_id` varchar(64) NOT NULL COMMENT '应用ID', `app_name` varchar(64) NOT NULL COMMENT '应用名称', `mch_name` varchar(30) NOT NULL COMMENT '商户名称', - `amount` bigint NOT NULL COMMENT '商户订单总额,单位分', - `amount_infact` bigint NOT NULL DEFAULT '0' COMMENT '实际结算金额', + `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商户订单总额,单位分', + `amount_infact` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '实际结算金额', `analyse_id` bigint DEFAULT NULL COMMENT '报表分析标识', `static_state` tinyint NOT NULL DEFAULT '0' COMMENT '结账状态, 0-已结账, 1-未结账', `remark` varchar(512) NOT NULL COMMENT '备注', @@ -558,6 +558,41 @@ CREATE TABLE `t_order_statistics_merchant` ( KEY `created_at` (`created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商户订单分析表'; + +-- +-- job表 `t_sys_job` +-- +DROP TABLE IF EXISTS `t_sys_job`; +CREATE TABLE `t_sys_job` ( + `job_id` varchar(36) NOT NULL COMMENT '任务Id', + `bean_name` varchar(100) NOT NULL COMMENT 'bean名称', + `method_name` varchar(100) NOT NULL COMMENT '方法名称', + `method_params` varchar(255) DEFAULT NULL COMMENT '方法参数', + `cron_expression` varchar(255) NOT NULL COMMENT 'cron表达式', + `remark` varchar(500) DEFAULT '' COMMENT '备注说明', + `job_status` tinyint NOT NULL COMMENT '状态(1:正常, 0:暂停)', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '更新时间', + PRIMARY KEY (`job_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + + +-- +-- job日志表 `t_sys_job_log` +-- +DROP TABLE IF EXISTS `t_sys_job_log`; +CREATE TABLE `t_sys_job_log` ( + `id` varchar(36) NOT NULL COMMENT '主键编号', + `job_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务id', + `exectue_end_time` datetime DEFAULT NULL COMMENT '执行结束时间', + `exectue_start_time` datetime DEFAULT NULL COMMENT '执行开始时间', + `exectue_result` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'Y成功,N失败', + `remark` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '备注', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='定时任务日志表 '; + + ##### ↑↑↑↑↑↑↑↑↑↑ 表结构DDL ↑↑↑↑↑↑↑↑↑↑ ##### ##### ↓↓↓↓↓↓↓↓↓↓ 初始化DML ↓↓↓↓↓↓↓↓↓↓ ##### diff --git a/docs/sql/patch-20230305.sql b/docs/sql/patch-20230305.sql new file mode 100644 index 0000000..6f6c4f0 --- /dev/null +++ b/docs/sql/patch-20230305.sql @@ -0,0 +1,115 @@ + +-- +-- 订单拓展表`t_pay_order_extend` +-- + +DROP TABLE IF EXISTS `t_pay_order_extend`; +CREATE TABLE `t_pay_order_extend` ( + `pay_order_id` varchar(30) NOT NULL COMMENT '支付订单号,关联主表', + `pid` varchar(36) DEFAULT '' COMMENT '人员Id', + `businessId` varchar(36) DEFAULT '' COMMENT '业务id', + `dealType` varchar(30) DEFAULT '' COMMENT '交易类型:PERSONAL-个人支付,DEPARTMENTAL-部门支付', + `deptId` varchar(36) DEFAULT '' COMMENT '部门Id', + `account_state` tinyint DEFAULT '0' COMMENT '结账状态:0-未结账 1-已结账', + `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + PRIMARY KEY (`pay_order_id`), + KEY `created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单拓展表'; + + +-- +-- 企业账单分析表 `t_order_statistics_company` +-- + +DROP TABLE IF EXISTS `t_order_statistics_company`; +CREATE TABLE `t_order_statistics_company` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', + `mch_no` varchar(64) NOT NULL COMMENT '商户号', + `app_id` varchar(64) NOT NULL COMMENT '应用ID', + `app_name` varchar(64) NOT NULL COMMENT '应用名称', + `mch_name` varchar(30) NOT NULL COMMENT '商户名称', + `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '企业账单金额,单位分', + `dept_name` varchar(100) NOT NULL COMMENT '组织名称:企业名称或者部门名称', + `amount_infact` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '实付金额', + `analyse_id` bigint DEFAULT NULL COMMENT '报表分析标识', + `static_state` tinyint NOT NULL DEFAULT '0' COMMENT '结账状态, 0-已结账, 1-未结账', + `remark` varchar(512) NOT NULL COMMENT '备注', + `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='企业账单分析表'; + + +-- +-- 部门账单分析表 `t_order_statistics_dept` +-- + +DROP TABLE IF EXISTS `t_order_statistics_dept`; +CREATE TABLE `t_order_statistics_dept` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', + `analyse_id` bigint NOT NULL COMMENT '企业分析表标识符', + `mch_no` varchar(64) NOT NULL COMMENT '商户号', + `app_id` varchar(64) NOT NULL COMMENT '应用ID', + `app_name` varchar(64) NOT NULL COMMENT '应用名称', + `mch_name` varchar(30) NOT NULL COMMENT '商户名称', + `dept_name` varchar(100) NOT NULL COMMENT '部门名称', + `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '部门账单金额,单位分', + `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='部门账单分析表'; + + +-- +-- 商户订单分析表 `t_order_statistics_merchant` +-- + +DROP TABLE IF EXISTS `t_order_statistics_merchant`; +CREATE TABLE `t_order_statistics_merchant` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', + `mch_no` varchar(64) NOT NULL COMMENT '商户号', + `app_id` varchar(64) NOT NULL COMMENT '应用ID', + `app_name` varchar(64) NOT NULL COMMENT '应用名称', + `mch_name` varchar(30) NOT NULL COMMENT '商户名称', + `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商户订单总额,单位分', + `amount_infact` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '实际结算金额', + `analyse_id` bigint DEFAULT NULL COMMENT '报表分析标识', + `static_state` tinyint NOT NULL DEFAULT '0' COMMENT '结账状态, 0-已结账, 1-未结账', + `remark` varchar(512) NOT NULL COMMENT '备注', + `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商户订单分析表'; + + +-- +-- job表 `t_sys_job` +-- +DROP TABLE IF EXISTS `t_sys_job`; +CREATE TABLE `t_sys_job` ( + `job_id` varchar(36) NOT NULL COMMENT '任务Id', + `bean_name` varchar(100) NOT NULL COMMENT 'bean名称', + `method_name` varchar(100) NOT NULL COMMENT '方法名称', + `method_params` varchar(255) DEFAULT NULL COMMENT '方法参数', + `cron_expression` varchar(255) NOT NULL COMMENT 'cron表达式', + `remark` varchar(500) DEFAULT '' COMMENT '备注说明', + `job_status` tinyint NOT NULL COMMENT '状态(1:正常, 0:暂停)', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '更新时间', + PRIMARY KEY (`job_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- +-- job日志表 `t_sys_job_log` +-- +DROP TABLE IF EXISTS `t_sys_job_log`; +CREATE TABLE `t_sys_job_log` ( + `id` varchar(36) NOT NULL COMMENT '主键编号', + `job_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务id', + `exectue_end_time` datetime DEFAULT NULL COMMENT '执行结束时间', + `exectue_start_time` datetime DEFAULT NULL COMMENT '执行开始时间', + `exectue_result` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'Y成功,N失败', + `remark` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '备注', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='定时任务日志表 '; \ No newline at end of file diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java index 1f318af..a952c4d 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsCompany.java @@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.io.Serializable; +import java.math.BigDecimal; import java.util.Date; /** @@ -58,7 +59,7 @@ public class OrderStatisticsCompany implements Serializable { /** * 企业账单金额,单位分 */ - private Long amount; + private Double amount; /** * 组织名称:企业名称或者部门名称 @@ -68,7 +69,7 @@ public class OrderStatisticsCompany implements Serializable { /** * 实付金额 */ - private Long amountInfact; + private Double amountInfact; /** * 报表分析标识 diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java index 9cf5ba6..14149bc 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsDept.java @@ -9,6 +9,7 @@ import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.io.Serializable; +import java.math.BigDecimal; import java.util.Date; /** @@ -79,7 +80,7 @@ public class OrderStatisticsDept implements Serializable { /** * 部门账单金额,单位分 */ - private Long amount; + private double amount; /** * 创建时间 diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsMerchant.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsMerchant.java index 482e687..a7cef12 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsMerchant.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/OrderStatisticsMerchant.java @@ -54,12 +54,12 @@ public class OrderStatisticsMerchant implements Serializable { /** * 商户账单金额,单位分 */ - private Long amount; + private Double amount; /** * 实际结算金额 */ - private Long amountInfact; + private Double amountInfact; /** * 报表分析标识 diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisJob.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisJob.java index 3498cfc..b4e731c 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisJob.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/CompanyAnalysisJob.java @@ -80,19 +80,19 @@ public class CompanyAnalysisJob extends AbstractAnalysisJob { }); boolean stepOne = orderStatisticsDeptService.saveBatch(orderStatisticsDeptList, 200); if (stepOne) { - Map map = orderStatisticsDeptList.stream().collect(Collectors.groupingBy((item) -> { + Map map = orderStatisticsDeptList.stream().collect(Collectors.groupingBy((item) -> { OrderStatisticsCompany company = new OrderStatisticsCompany(); company.setAppId(item.getAppId()); company.setAppName(item.getAppName()); company.setMchNo(item.getMchNo()); company.setMchName(item.getMchName()); company.setStaticState(OrderStatisticsCompany.ACCOUNT_STATE_NUN); - company.setAmountInfact(0L); + company.setAmountInfact(0D); company.setAnalyseId(analyseId); company.setRemark("企业账单分析"); company.setDeptName(item.getCompanyName()); return company; - }, Collectors.summingLong(OrderStatisticsDept::getAmount))); + }, Collectors.summingDouble(OrderStatisticsDept::getAmount))); List orderStatisticsCompanyList = new ArrayList<>(); map.forEach((k, v) -> { diff --git a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisJob.java b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisJob.java index 30fc468..d9ea0e9 100644 --- a/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisJob.java +++ b/jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/task/job/MerchantAnalysisJob.java @@ -48,7 +48,7 @@ public class MerchantAnalysisJob extends AbstractAnalysisJob { orderStatisticsDeptList.forEach(item -> { item.setStaticState(OrderStatisticsCompany.ACCOUNT_STATE_NUN); - item.setAmountInfact(0L); + item.setAmountInfact(0D); item.setRemark("商户账单报表分析作业"); item.setAnalyseId(analyseId); }); diff --git a/jeepay-manager/src/main/resources/application.yml b/jeepay-manager/src/main/resources/application.yml index 1a4458f..5613da9 100644 --- a/jeepay-manager/src/main/resources/application.yml +++ b/jeepay-manager/src/main/resources/application.yml @@ -4,8 +4,8 @@ server: spring: redis: database: 1 #1库:运营平台 #2库:商户系统 #3库:支付网关 - profiles: - active: dev +# profiles: +# active: dev qiDi: gateWay: -- Gitee