jeepay Documentation

Jeepay是一套适合互联网企业使用的开源支付系统,支持多渠道服务商和普通商户模式。已对接微信支付,支付宝,云闪付官方接口,支持聚合码支付。

6,465 stars Java Java 14 files · ~28,442 tokens #jeepay#xxpay
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy jeepay on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name jeepay -p 1:1 --restart always ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
Configured Services & Ports
⚙️ jeepay-configs
image: ${JEEPAY_CONFIGS_IMAGE:-alpine/git:v2.45.2}
⚙️ mysql
image: ${MYSQL_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/mysql:8.0.25}
⚙️ redis
image: ${REDIS_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/redis:6.2.14}
⚙️ rocketmq-namesrv
image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
⚙️ rocketmq-broker
image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
⚙️ jeepay-manager
image: ${MANAGER_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-manager:${VERSION}}
⚙️ jeepay-merchant
image: ${MERCHANT_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-merchant:${VERSION}}
⚙️ jeepay-payment
image: ${PAYMENT_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-payment:${VERSION}}
⚙️ BT_SERVICE_NAME6
image: ${NGINX_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/nginx:1.18.0}
🔌 Ports: ${HOST_IP}:${WEB_HTTP_PORT1}:19216, ${HOST_IP}:${WEB_HTTP_PORT2}:19217, ${HOST_IP}:${WEB_HTTP_PORT3}:19218
docker-compose.yml
yaml (docker-compose.yml)
# 宝塔面板(BaoTa)"Docker 应用"专用 compose 文件
#
# 使用场景:
#   - 宝塔 UI 上架 jeepay 应用,用户点击"安装"即部署
#   - 与 docker-compose.yml(仓库自身的 Compose 部署)不同,宝塔场景下
#     用户不 git clone 源码,所有配置文件通过 jeepay-configs 这个 init
#     容器(alpine/git 镜像)从 git 拉下来再分发到宿主共享卷
#
# 镜像默认仓库:
#   所有业务镜像 + MySQL / Redis / RocketMQ / Nginx 默认走华为云 SWR 公开仓库
#   (swr.cn-south-1.myhuaweicloud.com/jeepay/*),由计全官方维护,国内直拉,
#   不依赖 Docker Hub 加速器。alpine/git 仍用 Docker Hub(体积 < 20MB,一次
#   性拉取)。想回 Docker Hub 上游镜像时,可通过下面的 *_IMAGE 环境变量覆盖。
#
# 环境变量(由宝塔 app 模板声明):
#   VERSION            业务镜像 tag(jeepay-manager/merchant/payment)
#   CONFIG_REF         配置源 git ref(建议与 VERSION 同版本,或 master)
#   UI_RELEASE         前端静态资源 release(默认 V3.0.0)
#   MYSQL_ROOT_PASSWORD MySQL root 密码(默认 jeepaydb123456),同时贯穿到
#                      jeepay-configs 的 sed 替换,保证 yml 里 datasource 密码一致
#   APP_PATH           宿主机部署根目录
#   HOST_IP            对外绑定 IP
#   WEB_HTTP_PORT1/2/3 对外端口(分别映射到 19216 / 19217 / 19218)
#   CPUS / MEMORY_LIMIT nginx 资源限制
#
# 可选环境变量(想改镜像源时覆盖,各自带合理默认值):
#   MYSQL_IMAGE / REDIS_IMAGE / ROCKETMQ_IMAGE / NGINX_IMAGE
#   MANAGER_IMAGE / MERCHANT_IMAGE / PAYMENT_IMAGE
#   JEEPAY_CONFIGS_IMAGE
#
# 首次安装后配置文件都在 ${APP_PATH}/jeepayhomes/jeepayConfigs/,用户可直接
# 编辑;jeepay-configs 用 cp -n 保护已存在文件不被覆盖;最新模板始终同步
# 到 ${APP_PATH}/jeepayhomes/jeepayConfigs/.latest/,升级时 diff 对比。

services:
  # jeepay 配置中心:一次性 init 容器
  # - 从 git 拉 ${CONFIG_REF} tag 的配置文件
  # - cp -n 铺到共享卷,已存在文件跳过(保护用户编辑)
  # - 最新模板同时刷到 .latest/,升级时 diff 对比
  jeepay-configs:
    image: ${JEEPAY_CONFIGS_IMAGE:-alpine/git:v2.45.2}
    container_name: jeepay-configs
    # alpine/git 的 ENTRYPOINT 默认是 git,清空后 command 才能直接 exec sh
    entrypoint: []
    environment:
      # 贯穿到 sed 里替换 yml 的 datasource password(默认 jeepaydb123456)
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:-jeepaydb123456}"
    volumes:
      - ${APP_PATH}/jeepayhomes/:/jeepayhomes
    command:
      - sh
      - -c
      - |
        set -e
        rm -rf /tmp/jeepay-src
        git clone --branch ${CONFIG_REF:-master} --depth 1 https://gitee.com/jeequan/jeepay.git /tmp/jeepay-src

        mkdir -p /jeepayhomes/jeepayConfigs/db \
                 /jeepayhomes/jeepayConfigs/redis \
                 /jeepayhomes/jeepayConfigs/rocketmq \
                 /jeepayhomes/jeepayConfigs/service/manager \
                 /jeepayhomes/jeepayConfigs/service/merchant \
                 /jeepayhomes/jeepayConfigs/service/payment \
                 /jeepayhomes/jeepayConfigs/nginx/conf.d \
                 /jeepayhomes/jeepayConfigs/nginx/html

        cp -n /tmp/jeepay-src/docs/install/include/my.cnf             /jeepayhomes/jeepayConfigs/db/my.cnf                         || true
        cp -n /tmp/jeepay-src/docs/sql/init.sql                       /jeepayhomes/jeepayConfigs/db/init.sql                       || true
        cp -n /tmp/jeepay-src/docs/install/include/redis.conf         /jeepayhomes/jeepayConfigs/redis/redis.conf                  || true
        cp -n /tmp/jeepay-src/docker/rocketmq/broker/conf/broker.conf /jeepayhomes/jeepayConfigs/rocketmq/broker.conf              || true
        cp -n /tmp/jeepay-src/conf/manager/application.yml            /jeepayhomes/jeepayConfigs/service/manager/application.yml   || true
        cp -n /tmp/jeepay-src/conf/merchant/application.yml           /jeepayhomes/jeepayConfigs/service/merchant/application.yml  || true
        cp -n /tmp/jeepay-src/conf/payment/application.yml            /jeepayhomes/jeepayConfigs/service/payment/application.yml   || true

        # 上游 conf/*/application.yml 里 datasource 密码是占位 "rootroot"(和仓库
        # docker-compose.yml 的默认 MYSQL_ROOT_PASSWORD 一致),宝塔场景下 MySQL
        # 初始化密码由 MYSQL_ROOT_PASSWORD 变量控制(默认 jeepaydb123456),不改
        # 则 Access denied。用 grep 条件做幂等替换,只有还存在 "password: rootroot"
        # 才改,尊重用户后续自定义。$$ 是给 compose 的转义,防止 compose YAML 解析
        # 时把 shell 变量吞掉。
        for svc in manager merchant payment; do
            yml="/jeepayhomes/jeepayConfigs/service/$$svc/application.yml"
            if [ -f "$$yml" ] && grep -q "password: rootroot" "$$yml"; then
                sed -i "s|password: rootroot|password: $${MYSQL_ROOT_PASSWORD}|g" "$$yml"
                echo "$$yml: datasource password rewrote"
            fi
        done
        cp -n /tmp/jeepay-src/docs/install/include/nginx.conf         /jeepayhomes/jeepayConfigs/nginx/nginx.conf                  || true
        # nginx.conf 在 install.sh 场景下用 localhost:921x(nginx --net=host 可达),
        # 但 compose 场景下 nginx 在 bridge 网络,localhost 解析不到后端。只要还能
        # 找到 localhost:921x 就替换成 compose service 名;用户若已改过就不动。
        if grep -q "proxy_pass http://localhost:921" /jeepayhomes/jeepayConfigs/nginx/nginx.conf 2>/dev/null; then
            sed -i \
                -e 's|proxy_pass http://localhost:9216|proxy_pass http://jeepaypayment:9216|g' \
                -e 's|proxy_pass http://localhost:9217|proxy_pass http://jeepaymanager:9217|g' \
                -e 's|proxy_pass http://localhost:9218|proxy_pass http://jeepaymerchant:9218|g' \
                /jeepayhomes/jeepayConfigs/nginx/nginx.conf
            echo "nginx.conf: localhost proxy_pass rewrote to compose service names"
        fi

        rm -rf /jeepayhomes/jeepayConfigs/.latest
        mkdir -p /jeepayhomes/jeepayConfigs/.latest
        cp -r /tmp/jeepay-src/conf                                    /jeepayhomes/jeepayConfigs/.latest/conf
        cp -r /tmp/jeepay-src/docs/install/include                    /jeepayhomes/jeepayConfigs/.latest/include
        cp    /tmp/jeepay-src/docker/rocketmq/broker/conf/broker.conf /jeepayhomes/jeepayConfigs/.latest/broker.conf               || true
        cp    /tmp/jeepay-src/docs/sql/init.sql                       /jeepayhomes/jeepayConfigs/.latest/init.sql                  || true

        # 前端静态资源(jeepay-ui 已打包发布到 gitee release)。目标目录已存在则跳过,
        # 保护用户后续对 html/ 的改动(和 cp -n 同语义)
        if [ ! -f /jeepayhomes/jeepayConfigs/nginx/html/jeepaymanager/index.html ]; then
            echo "Downloading frontend html.tar.gz (release=${UI_RELEASE:-V3.0.0}) ..."
            wget -q -O /tmp/html.tar.gz \
                "https://gitee.com/jeequan/jeepay-ui/releases/download/${UI_RELEASE:-V3.0.0}/html.tar.gz"
            tar xzf /tmp/html.tar.gz -C /jeepayhomes/jeepayConfigs/nginx/html/
            rm -f /tmp/html.tar.gz
            echo "Frontend extracted to nginx/html/"
        else
            echo "Frontend already present, skip download"
        fi

        echo "jeepay-configs ready (user edits preserved; upstream templates in .latest/)"
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # MySQL
  mysql:
    image: ${MYSQL_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/mysql:8.0.25}
    container_name: mysql8
    hostname: mysql
    restart: always
    environment:
      LANG: C.UTF-8
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:-jeepaydb123456}"
      MYSQL_DATABASE: "jeepaydb"
    depends_on:
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/mysql/log:/var/log/mysql
      - ${APP_PATH}/jeepayhomes/mysql/data:/var/lib/mysql
      - ${APP_PATH}/jeepayhomes/mysql/mysql-files:/var/lib/mysql-files
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/db:/etc/mysql/conf.d
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -uroot -p$${MYSQL_ROOT_PASSWORD}"]
      interval: 15s
      timeout: 10s
      retries: 10
      start_period: 60s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # Redis
  redis:
    image: ${REDIS_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/redis:6.2.14}
    container_name: redis6
    hostname: redis
    restart: always
    depends_on:
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/redis/redis.conf:/etc/redis/redis.conf
      - ${APP_PATH}/jeepayhomes/redis/data:/data
    command: redis-server /etc/redis/redis.conf
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 15s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # RocketMQ NameServer
  rocketmq-namesrv:
    image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
    platform: linux/amd64
    container_name: rocketmq-namesrv
    hostname: rocketmq-namesrv
    restart: always
    depends_on:
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/rocketmq/namesrv/logs:/home/rocketmq/logs
    environment:
      JAVA_OPT_EXT: "-Xms256m -Xmx256m -Xmn128m"
    command: sh mqnamesrv
    healthcheck:
      # rocketmq 镜像里 /bin/sh 是 dash,不支持 /dev/tcp,必须显式走 bash
      test: ["CMD", "bash", "-c", "echo > /dev/tcp/localhost/9876"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # RocketMQ Broker(brokerIP1 = 容器名,不依赖宿主网络布局)
  rocketmq-broker:
    image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
    platform: linux/amd64
    container_name: rocketmq-broker
    hostname: rocketmq-broker
    restart: always
    user: "0:0"
    depends_on:
      rocketmq-namesrv:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/rocketmq/broker/logs:/home/rocketmq/logs
      - ${APP_PATH}/jeepayhomes/rocketmq/broker/store:/home/rocketmq/store
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/rocketmq/broker.conf:/home/rocketmq/rocketmq-5.3.1/conf/broker.conf:ro
    environment:
      NAMESRV_ADDR: "rocketmq-namesrv:9876"
      JAVA_OPT_EXT: "-Xms512m -Xmx512m -Xmn256m"
    command: sh mqbroker -n rocketmq-namesrv:9876 -c /home/rocketmq/rocketmq-5.3.1/conf/broker.conf
    healthcheck:
      test: ["CMD", "bash", "-c", "echo > /dev/tcp/localhost/10911"]
      interval: 15s
      timeout: 5s
      retries: 15
      start_period: 90s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # jeepay 运营平台 API
  jeepay-manager:
    image: ${MANAGER_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-manager:${VERSION}}
    container_name: jeepaymanager
    restart: always
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
      rocketmq-broker:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
      - ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/service/manager/application.yml:/jeepayhomes/service/app/application.yml
    healthcheck:
      test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9217 || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 12
      start_period: 60s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # jeepay 商户平台 API
  jeepay-merchant:
    image: ${MERCHANT_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-merchant:${VERSION}}
    container_name: jeepaymerchant
    restart: always
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
      rocketmq-broker:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
      - ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/service/merchant/application.yml:/jeepayhomes/service/app/application.yml
    healthcheck:
      test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9218 || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 12
      start_period: 60s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # jeepay 支付网关 API
  jeepay-payment:
    image: ${PAYMENT_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-payment:${VERSION}}
    container_name: jeepaypayment
    restart: always
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
      rocketmq-broker:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
      - ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/service/payment/application.yml:/jeepayhomes/service/app/application.yml
    healthcheck:
      test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9216 || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 12
      start_period: 60s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # nginx 网关(对外映射 19216 / 19217 / 19218)
  BT_SERVICE_NAME6:
    image: ${NGINX_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/nginx:1.18.0}
    container_name: nginx118
    restart: always
    deploy:
      resources:
        limits:
          cpus: ${CPUS}
          memory: ${MEMORY_LIMIT}
    depends_on:
      jeepay-payment:
        condition: service_healthy
      jeepay-manager:
        condition: service_healthy
      jeepay-merchant:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    ports:
      - ${HOST_IP}:${WEB_HTTP_PORT1}:19216
      - ${HOST_IP}:${WEB_HTTP_PORT2}:19217
      - ${HOST_IP}:${WEB_HTTP_PORT3}:19218
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/conf.d:/etc/nginx/conf.d
      - ${APP_PATH}/jeepayhomes/nginx/logs:/var/log/nginx
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/html:/usr/share/nginx/html
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

networks:
  baota_net:
    external: true

File: README.md


目录


项目简介

Jeepay 是一套面向互联网企业的开源支付系统,支持 普通商户模式 / 多渠道服务商模式 / 聚合码支付 / 多商户多应用接入。已对接微信支付、支付宝、云闪付等主流渠道。

后端 Spring Boot 3.3.7 + JDK 17 + Spring Security,前端 Ant Design Vue,MQ 支持 RocketMQ / ActiveMQ / RabbitMQ。

适合自建聚合支付平台、SaaS 支付中台、多商户支付系统以及电商 / 零售 / 本地生活 / 数字内容等业务的支付接入与二次开发。


Jeepay 适合谁

  • 想独立掌控支付流程、商户体系、渠道配置、回调通知,不想被托管服务绑定
  • 需要服务商模式管理多家商户、多家渠道的平台方
  • 计划长期二次开发,希望起点是一套架构清晰、代码分层明确、文档完备的开源系统
  • 需要 Docker / Shell 一键部署、分布式、多 MQ 可切换的可运维支付底座

由原 XxPay 团队持续开发维护,多年支付实战沉淀。


官方托管服务(计全付)

如果你希望 不自建部署、直接拿到可用的支付通道与分账能力,欢迎来 计全付官方 申请接入:

  • 目标场景:没有支付牌照 / 没有支付通道资源的中小商户、SaaS 平台、独立开发者
  • 提供内容:微信、支付宝、银联等主流通道聚合接入;分账能力;账户体系、结算与对账;售后支撑
  • 分账亮点:支持 100% 全额分账,满足平台型业务的分润 / 代收代付诉求
  • 优势:开通即用,免去服务器与运维成本;费率与政策按业务规模定制

联系方式:官网 https://www.jeequan.com · 微信客服见文末。


部署方式

方式 适用场景 跳转
Shell 脚本一键安装 干净的 CentOS / Anolis / Ubuntu / Debian 服务器 docs/deploy/shell.md
Docker Compose 部署 本地 / 测试环境起完整集群(含前端) docs/deploy/compose.md
宝塔面板一键安装 有宝塔面板(≥ 9.2.0),Docker 应用市场一键装 Compose 文件:docker-compose.baota.yml,用法:docs/deploy/baota.md
自助源码部署 对接内部基础设施的团队 自备 MySQL / Redis / MQ,按环境调整 conf/ 后 Maven 打包部署

默认镜像指向华为云 SWR 公开仓库,国内零配置直达,不依赖 Docker Hub。部署后需域名 + HTTPS 见 docs/deploy/https.md,出问题优先看 docs/deploy/troubleshooting.md。


系统架构

Jeepay 计全支付系统架构图

Jeepay 聚合码支付流程图


核心技术栈

软件名称 描述 版本
JDK Java 运行环境 17
Spring Boot 后端开发框架 3.3.7
Redis 分布式缓存 3.2.8+
MySQL 数据库 5.7.x / 8.0+
MQ 消息中间件 RocketMQ / ActiveMQ / RabbitMQ
Ant Design Vue 前端 UI 框架 4.2.6
MyBatis-Plus MyBatis 增强工具 3.4.2
WxJava 微信开发 Java SDK 4.6.0
Hutool Java 工具类库 5.8.26

文档与资源

官方文档

本仓库文档

SDK 资源

Jeepay 已提供 Java、Python SDK,以及 PHP 对接 Demo:

AI 接入助手

如果你用 Claude / Cursor / ChatGPT 等 AI 工具接入 Jeepay,可以使用 Jeepay Skills —— 把签名陷阱、字段大小写、wayCode 选择等 AI 容易踩坑的细节系统化整理,让 AI 一次接对。

  • 仓库地址:https://github.com/jeequan/jeepay-skills
  • 支持 Claude Code / Cursor / Cline / 网页 AI(claude.ai · ChatGPT · 通义千问 · 文心一言)
  • 也可作为纯文档浏览,不用 AI 也能直接看接入指南

项目地址


贡献与协作


更多支持

欢迎关注官方渠道,获取更多产品动态、部署指导与社区支持。

官方公众号

微信扫描下方二维码,关注 计全科技 公众号:

官方微信交流群

微信扫描下方二维码加入官方交流群。若项目对你有帮助,欢迎先点一个 Star 支持。

微信客服


File: CLAUDE.md

CLAUDE.md

协作约定

  • 提交信息(Commit Message)统一使用中文。
  • 代码注释、文档注释、说明性注释统一优先使用中文。
  • 在不影响开源协作和外部兼容性的前提下,新增说明文档默认使用中文。
  • 若存在必须使用英文的场景(如对外开放接口字段、协议规范、开源社区通用约定、第三方框架要求),保留英文命名,但补充中文说明。

执行要求

  • 进行代码修改、文档更新、脚本补充时,默认遵守以上中文规范。
  • 生成提交记录时,优先使用清晰、简洁、可读的中文提交信息。
  • 编写注释时,优先写“为什么这么做”和“注意事项”,避免无意义注释。

File: CONTRIBUTING.md

[Binary file]


File: docker-compose.baota.yml

宝塔面板(BaoTa)"Docker 应用"专用 compose 文件

使用场景:

- 宝塔 UI 上架 jeepay 应用,用户点击"安装"即部署

- 与 docker-compose.yml(仓库自身的 Compose 部署)不同,宝塔场景下

用户不 git clone 源码,所有配置文件通过 jeepay-configs 这个 init

容器(alpine/git 镜像)从 git 拉下来再分发到宿主共享卷

镜像默认仓库:

所有业务镜像 + MySQL / Redis / RocketMQ / Nginx 默认走华为云 SWR 公开仓库

(swr.cn-south-1.myhuaweicloud.com/jeepay/*),由计全官方维护,国内直拉,

不依赖 Docker Hub 加速器。alpine/git 仍用 Docker Hub(体积 < 20MB,一次

性拉取)。想回 Docker Hub 上游镜像时,可通过下面的 *_IMAGE 环境变量覆盖。

环境变量(由宝塔 app 模板声明):

VERSION 业务镜像 tag(jeepay-manager/merchant/payment)

CONFIG_REF 配置源 git ref(建议与 VERSION 同版本,或 master)

UI_RELEASE 前端静态资源 release(默认 V3.0.0)

MYSQL_ROOT_PASSWORD MySQL root 密码(默认 jeepaydb123456),同时贯穿到

jeepay-configs 的 sed 替换,保证 yml 里 datasource 密码一致

APP_PATH 宿主机部署根目录

HOST_IP 对外绑定 IP

WEB_HTTP_PORT1/2/3 对外端口(分别映射到 19216 / 19217 / 19218)

CPUS / MEMORY_LIMIT nginx 资源限制

可选环境变量(想改镜像源时覆盖,各自带合理默认值):

MYSQL_IMAGE / REDIS_IMAGE / ROCKETMQ_IMAGE / NGINX_IMAGE

MANAGER_IMAGE / MERCHANT_IMAGE / PAYMENT_IMAGE

JEEPAY_CONFIGS_IMAGE

首次安装后配置文件都在 ${APP_PATH}/jeepayhomes/jeepayConfigs/,用户可直接

编辑;jeepay-configs 用 cp -n 保护已存在文件不被覆盖;最新模板始终同步

到 ${APP_PATH}/jeepayhomes/jeepayConfigs/.latest/,升级时 diff 对比。

services:

jeepay 配置中心:一次性 init 容器

- 从 git 拉 ${CONFIG_REF} tag 的配置文件

- cp -n 铺到共享卷,已存在文件跳过(保护用户编辑)

- 最新模板同时刷到 .latest/,升级时 diff 对比

jeepay-configs:
image: ${JEEPAY_CONFIGS_IMAGE:-alpine/git:v2.45.2}
container_name: jeepay-configs
# alpine/git 的 ENTRYPOINT 默认是 git,清空后 command 才能直接 exec sh
entrypoint: []
environment:
# 贯穿到 sed 里替换 yml 的 datasource password(默认 jeepaydb123456)
MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:-jeepaydb123456}"
volumes:
- ${APP_PATH}/jeepayhomes/:/jeepayhomes
command:
- sh
- -c
- |
set -e
rm -rf /tmp/jeepay-src
git clone --branch ${CONFIG_REF:-master} --depth 1 https://gitee.com/jeequan/jeepay.git /tmp/jeepay-src

text
mkdir -p /jeepayhomes/jeepayConfigs/db \
             /jeepayhomes/jeepayConfigs/redis \
             /jeepayhomes/jeepayConfigs/rocketmq \
             /jeepayhomes/jeepayConfigs/service/manager \
             /jeepayhomes/jeepayConfigs/service/merchant \
             /jeepayhomes/jeepayConfigs/service/payment \
             /jeepayhomes/jeepayConfigs/nginx/conf.d \
             /jeepayhomes/jeepayConfigs/nginx/html

    cp -n /tmp/jeepay-src/docs/install/include/my.cnf             /jeepayhomes/jeepayConfigs/db/my.cnf                         || true
    cp -n /tmp/jeepay-src/docs/sql/init.sql                       /jeepayhomes/jeepayConfigs/db/init.sql                       || true
    cp -n /tmp/jeepay-src/docs/install/include/redis.conf         /jeepayhomes/jeepayConfigs/redis/redis.conf                  || true
    cp -n /tmp/jeepay-src/docker/rocketmq/broker/conf/broker.conf /jeepayhomes/jeepayConfigs/rocketmq/broker.conf              || true
    cp -n /tmp/jeepay-src/conf/manager/application.yml            /jeepayhomes/jeepayConfigs/service/manager/application.yml   || true
    cp -n /tmp/jeepay-src/conf/merchant/application.yml           /jeepayhomes/jeepayConfigs/service/merchant/application.yml  || true
    cp -n /tmp/jeepay-src/conf/payment/application.yml            /jeepayhomes/jeepayConfigs/service/payment/application.yml   || true

    # 上游 conf/*/application.yml 里 datasource 密码是占位 "rootroot"(和仓库
    # docker-compose.yml 的默认 MYSQL_ROOT_PASSWORD 一致),宝塔场景下 MySQL
    # 初始化密码由 MYSQL_ROOT_PASSWORD 变量控制(默认 jeepaydb123456),不改
    # 则 Access denied。用 grep 条件做幂等替换,只有还存在 "password: rootroot"
    # 才改,尊重用户后续自定义。$$ 是给 compose 的转义,防止 compose YAML 解析
    # 时把 shell 变量吞掉。
    for svc in manager merchant payment; do
        yml="/jeepayhomes/jeepayConfigs/service/$$svc/application.yml"
        if [ -f "$$yml" ] && grep -q "password: rootroot" "$$yml"; then
            sed -i "s|password: rootroot|password: $${MYSQL_ROOT_PASSWORD}|g" "$$yml"
            echo "$$yml: datasource password rewrote"
        fi
    done
    cp -n /tmp/jeepay-src/docs/install/include/nginx.conf         /jeepayhomes/jeepayConfigs/nginx/nginx.conf                  || true
    # nginx.conf 在 install.sh 场景下用 localhost:921x(nginx --net=host 可达),
    # 但 compose 场景下 nginx 在 bridge 网络,localhost 解析不到后端。只要还能
    # 找到 localhost:921x 就替换成 compose service 名;用户若已改过就不动。
    if grep -q "proxy_pass http://localhost:921" /jeepayhomes/jeepayConfigs/nginx/nginx.conf 2>/dev/null; then
        sed -i \
            -e 's|proxy_pass http://localhost:9216|proxy_pass http://jeepaypayment:9216|g' \
            -e 's|proxy_pass http://localhost:9217|proxy_pass http://jeepaymanager:9217|g' \
            -e 's|proxy_pass http://localhost:9218|proxy_pass http://jeepaymerchant:9218|g' \
            /jeepayhomes/jeepayConfigs/nginx/nginx.conf
        echo "nginx.conf: localhost proxy_pass rewrote to compose service names"
    fi

    rm -rf /jeepayhomes/jeepayConfigs/.latest
    mkdir -p /jeepayhomes/jeepayConfigs/.latest
    cp -r /tmp/jeepay-src/conf                                    /jeepayhomes/jeepayConfigs/.latest/conf
    cp -r /tmp/jeepay-src/docs/install/include                    /jeepayhomes/jeepayConfigs/.latest/include
    cp    /tmp/jeepay-src/docker/rocketmq/broker/conf/broker.conf /jeepayhomes/jeepayConfigs/.latest/broker.conf               || true
    cp    /tmp/jeepay-src/docs/sql/init.sql                       /jeepayhomes/jeepayConfigs/.latest/init.sql                  || true

    # 前端静态资源(jeepay-ui 已打包发布到 gitee release)。目标目录已存在则跳过,
    # 保护用户后续对 html/ 的改动(和 cp -n 同语义)
    if [ ! -f /jeepayhomes/jeepayConfigs/nginx/html/jeepaymanager/index.html ]; then
        echo "Downloading frontend html.tar.gz (release=${UI_RELEASE:-V3.0.0}) ..."
        wget -q -O /tmp/html.tar.gz \
            "https://gitee.com/jeequan/jeepay-ui/releases/download/${UI_RELEASE:-V3.0.0}/html.tar.gz"
        tar xzf /tmp/html.tar.gz -C /jeepayhomes/jeepayConfigs/nginx/html/
        rm -f /tmp/html.tar.gz
        echo "Frontend extracted to nginx/html/"
    else
        echo "Frontend already present, skip download"
    fi

    echo "jeepay-configs ready (user edits preserved; upstream templates in .latest/)"
labels:
  createdBy: "bt_apps"
networks:
  - baota_net

MySQL

mysql:
image: ${MYSQL_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/mysql:8.0.25}
container_name: mysql8
hostname: mysql
restart: always
environment:
LANG: C.UTF-8
MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:-jeepaydb123456}"
MYSQL_DATABASE: "jeepaydb"
depends_on:
jeepay-configs:
condition: service_completed_successfully
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_PATH}/jeepayhomes/mysql/log:/var/log/mysql
- ${APP_PATH}/jeepayhomes/mysql/data:/var/lib/mysql
- ${APP_PATH}/jeepayhomes/mysql/mysql-files:/var/lib/mysql-files
- ${APP_PATH}/jeepayhomes/jeepayConfigs/db:/etc/mysql/conf.d
- ${APP_PATH}/jeepayhomes/jeepayConfigs/db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost -uroot -p$${MYSQL_ROOT_PASSWORD}"]
interval: 15s
timeout: 10s
retries: 10
start_period: 60s
labels:
createdBy: "bt_apps"
networks:
- baota_net

Redis

redis:
image: ${REDIS_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/redis:6.2.14}
container_name: redis6
hostname: redis
restart: always
depends_on:
jeepay-configs:
condition: service_completed_successfully
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_PATH}/jeepayhomes/jeepayConfigs/redis/redis.conf:/etc/redis/redis.conf
- ${APP_PATH}/jeepayhomes/redis/data:/data
command: redis-server /etc/redis/redis.conf
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 10
start_period: 15s
labels:
createdBy: "bt_apps"
networks:
- baota_net

RocketMQ NameServer

rocketmq-namesrv:
image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
platform: linux/amd64
container_name: rocketmq-namesrv
hostname: rocketmq-namesrv
restart: always
depends_on:
jeepay-configs:
condition: service_completed_successfully
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_PATH}/jeepayhomes/rocketmq/namesrv/logs:/home/rocketmq/logs
environment:
JAVA_OPT_EXT: "-Xms256m -Xmx256m -Xmn128m"
command: sh mqnamesrv
healthcheck:
# rocketmq 镜像里 /bin/sh 是 dash,不支持 /dev/tcp,必须显式走 bash
test: ["CMD", "bash", "-c", "echo > /dev/tcp/localhost/9876"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
labels:
createdBy: "bt_apps"
networks:
- baota_net

RocketMQ Broker(brokerIP1 = 容器名,不依赖宿主网络布局)

rocketmq-broker:
image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
platform: linux/amd64
container_name: rocketmq-broker
hostname: rocketmq-broker
restart: always
user: "0:0"
depends_on:
rocketmq-namesrv:
condition: service_healthy
jeepay-configs:
condition: service_completed_successfully
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_PATH}/jeepayhomes/rocketmq/broker/logs:/home/rocketmq/logs
- ${APP_PATH}/jeepayhomes/rocketmq/broker/store:/home/rocketmq/store
- ${APP_PATH}/jeepayhomes/jeepayConfigs/rocketmq/broker.conf:/home/rocketmq/rocketmq-5.3.1/conf/broker.conf:ro
environment:
NAMESRV_ADDR: "rocketmq-namesrv:9876"
JAVA_OPT_EXT: "-Xms512m -Xmx512m -Xmn256m"
command: sh mqbroker -n rocketmq-namesrv:9876 -c /home/rocketmq/rocketmq-5.3.1/conf/broker.conf
healthcheck:
test: ["CMD", "bash", "-c", "echo > /dev/tcp/localhost/10911"]
interval: 15s
timeout: 5s
retries: 15
start_period: 90s
labels:
createdBy: "bt_apps"
networks:
- baota_net

jeepay 运营平台 API

jeepay-manager:
image: ${MANAGER_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-manager:${VERSION}}
container_name: jeepaymanager
restart: always
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
rocketmq-broker:
condition: service_healthy
jeepay-configs:
condition: service_completed_successfully
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
- ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
- ${APP_PATH}/jeepayhomes/jeepayConfigs/service/manager/application.yml:/jeepayhomes/service/app/application.yml
healthcheck:
test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9217 || exit 1"]
interval: 15s
timeout: 5s
retries: 12
start_period: 60s
labels:
createdBy: "bt_apps"
networks:
- baota_net

jeepay 商户平台 API

jeepay-merchant:
image: ${MERCHANT_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-merchant:${VERSION}}
container_name: jeepaymerchant
restart: always
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
rocketmq-broker:
condition: service_healthy
jeepay-configs:
condition: service_completed_successfully
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
- ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
- ${APP_PATH}/jeepayhomes/jeepayConfigs/service/merchant/application.yml:/jeepayhomes/service/app/application.yml
healthcheck:
test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9218 || exit 1"]
interval: 15s
timeout: 5s
retries: 12
start_period: 60s
labels:
createdBy: "bt_apps"
networks:
- baota_net

jeepay 支付网关 API

jeepay-payment:
image: ${PAYMENT_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-payment:${VERSION}}
container_name: jeepaypayment
restart: always
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
rocketmq-broker:
condition: service_healthy
jeepay-configs:
condition: service_completed_successfully
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
- ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
- ${APP_PATH}/jeepayhomes/jeepayConfigs/service/payment/application.yml:/jeepayhomes/service/app/application.yml
healthcheck:
test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9216 || exit 1"]
interval: 15s
timeout: 5s
retries: 12
start_period: 60s
labels:
createdBy: "bt_apps"
networks:
- baota_net

nginx 网关(对外映射 19216 / 19217 / 19218)

BT_SERVICE_NAME6:
image: ${NGINX_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/nginx:1.18.0}
container_name: nginx118
restart: always
deploy:
resources:
limits:
cpus: ${CPUS}
memory: ${MEMORY_LIMIT}
depends_on:
jeepay-payment:
condition: service_healthy
jeepay-manager:
condition: service_healthy
jeepay-merchant:
condition: service_healthy
jeepay-configs:
condition: service_completed_successfully
ports:
- ${HOST_IP}:${WEB_HTTP_PORT1}:19216
- ${HOST_IP}:${WEB_HTTP_PORT2}:19217
- ${HOST_IP}:${WEB_HTTP_PORT3}:19218
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/nginx.conf:/etc/nginx/nginx.conf
- ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/conf.d:/etc/nginx/conf.d
- ${APP_PATH}/jeepayhomes/nginx/logs:/var/log/nginx
- ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/html:/usr/share/nginx/html
labels:
createdBy: "bt_apps"
networks:
- baota_net

networks:
baota_net:
external: true


File: docker-compose.swr-smoke.yml

services:
mysql:
hostname: mysql
container_name: jeepay-swr-smoke-mysql
restart: always
image: ${MYSQL_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/mysql:8}
environment:
LANG: C.UTF-8
MYSQL_ROOT_PASSWORD: "rootroot"
MYSQL_DATABASE: "jeepaydb"
MYSQL_USER: "jeepay"
MYSQL_PASSWORD: "jeepay"
ports:
- "23306:3306"
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD --silent"]
interval: 10s
timeout: 5s
retries: 12
start_period: 20s
volumes:
- mysql:/var/lib/mysql
- ./docs/sql/init.sql:/docker-entrypoint-initdb.d/01-init.sql:ro
- ./docs/sql/patch.sql:/docker-entrypoint-initdb.d/02-patch.sql:ro
networks:
jeepay:
ipv4_address: 172.31.0.10

rocketmq-namesrv:
platform: linux/amd64
image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
hostname: rocketmq-namesrv
container_name: jeepay-swr-smoke-rocketmq-namesrv
restart: always
user: "0:0"
ports:
- "19876:9876"
environment:
HEAP_OPTS: "-Xms256m -Xmx256m -Xmn128m"
command: sh mqnamesrv
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/9876'"]
interval: 15s
timeout: 15s
retries: 10
start_period: 40s
volumes:
- rocketmq_namesrv_logs:/home/rocketmq/logs
networks:
jeepay:
ipv4_address: 172.31.0.11

redis:
platform: linux/amd64
hostname: redis
container_name: jeepay-swr-smoke-redis
restart: always
image: ${REDIS_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/redis:6.2.14}
ports:
- "16380:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 12
start_period: 10s
volumes:
- redis:/data
networks:
jeepay:
ipv4_address: 172.31.0.12

rocketmq-broker:
platform: linux/amd64
image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
hostname: rocketmq-broker
container_name: jeepay-swr-smoke-rocketmq-broker
restart: always
user: "0:0"
ports:
- "20909:10909"
- "20911:10911"
- "20912:10912"
environment:
NAMESRV_ADDR: rocketmq-namesrv:9876
JAVA_OPT_EXT: "-Xms512m -Xmx512m -Xmn256m"
command: sh mqbroker -n rocketmq-namesrv:9876 -c /home/rocketmq/rocketmq-5.3.1/conf/broker.conf
depends_on:
rocketmq-namesrv:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/10911'"]
interval: 15s
timeout: 15s
retries: 15
start_period: 120s
volumes:
- rocketmq_broker_logs:/home/rocketmq/logs
- rocketmq_broker_store:/home/rocketmq/store
- ./docker/rocketmq/broker/conf/broker.conf:/home/rocketmq/rocketmq-5.3.1/conf/broker.conf:ro
networks:
jeepay:
ipv4_address: 172.31.0.13

volumes:
mysql:
redis:
rocketmq_namesrv_logs:
rocketmq_broker_logs:
rocketmq_broker_store:

networks:
jeepay:
driver: bridge
ipam:
config:
- subnet: 172.31.0.0/24


File: docker-compose.swr-test.yml

services:
mysql:
container_name: jeepay-swr-test-mysql
ports:
- "23306:3306"
networks:
jeepay:
ipv4_address: 172.30.0.10

rocketmq-namesrv:
container_name: jeepay-swr-test-rocketmq-namesrv
ports:
- "19876:9876"
networks:
jeepay:
ipv4_address: 172.30.0.11

redis:
container_name: jeepay-swr-test-redis
ports:
- "16380:6379"
networks:
jeepay:
ipv4_address: 172.30.0.12

rocketmq-broker:
container_name: jeepay-swr-test-rocketmq-broker
ports:
- "20909:10909"
- "20911:10911"
- "20912:10912"
networks:
jeepay:
ipv4_address: 172.30.0.13

payment:
container_name: jeepay-swr-test-payment
networks:
jeepay:
ipv4_address: 172.30.0.21

manager:
container_name: jeepay-swr-test-manager
networks:
jeepay:
ipv4_address: 172.30.0.22

merchant:
container_name: jeepay-swr-test-merchant
networks:
jeepay:
ipv4_address: 172.30.0.23

ui-payment:
container_name: jeepay-swr-test-ui-payment
networks:
jeepay:
ipv4_address: 172.30.0.31

ui-manager:
container_name: jeepay-swr-test-ui-manager
networks:
jeepay:
ipv4_address: 172.30.0.32

ui-merchant:
container_name: jeepay-swr-test-ui-merchant
networks:
jeepay:
ipv4_address: 172.30.0.33

networks:
jeepay:
ipam:
config:
- subnet: 172.30.0.0/24


File: docker-compose.yml

Maven 依赖提前编译,修改 MQ 队列 (修改 jeepay-components-mq 依赖) 也需要重新运行此命令

启动命令 docker compose up

启动并运行在后台 docker compose up -d

重新编译 docker compose up --build

重新创建 docker compose up --force-recreate

重新编译并覆盖之前的 docker compose up --build --force-recreate

前端目录默认使用本仓库同级的 ../jeepay-ui,可在 .env 中覆盖 UI_BASE_DIR。

services:
mysql:
hostname: mysql
container_name: jeepay-mysql
restart: always
image: ${MYSQL_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/mysql:8}
environment:
LANG: C.UTF-8
MYSQL_ROOT_PASSWORD: "rootroot"
MYSQL_DATABASE: "jeepaydb"
MYSQL_USER: "jeepay"
MYSQL_PASSWORD: "jeepay"
ports:
- "13306:3306"
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD --silent"]
interval: 10s
timeout: 5s
retries: 12
start_period: 20s
volumes:
- mysql:/var/lib/mysql
- ./docs/sql/init.sql:/docker-entrypoint-initdb.d/01-init.sql:ro
- ./docs/sql/patch.sql:/docker-entrypoint-initdb.d/02-patch.sql:ro
networks:
jeepay:
ipv4_address: 172.20.0.10

使用 RocketMQ 作为默认 MQ 方案

rocketmq-namesrv:
platform: linux/amd64
image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
hostname: rocketmq-namesrv
container_name: jeepay-rocketmq-namesrv
restart: always
user: "0:0"
ports:
- "9876:9876"
environment:
# 开发环境降低 NameServer 内存占用
HEAP_OPTS: "-Xms256m -Xmx256m -Xmn128m"
command: sh mqnamesrv
healthcheck:
# arm64 模拟 amd64 时 bash 启动较慢,需增大超时
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/9876'"]
interval: 15s
timeout: 15s
retries: 10
start_period: 40s
volumes:
- rocketmq_namesrv_logs:/home/rocketmq/logs
networks:
jeepay:
ipv4_address: 172.20.0.11

rocketmq-broker:
platform: linux/amd64
image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
hostname: rocketmq-broker
container_name: jeepay-rocketmq-broker
restart: always
# Docker 创建的 named volume 默认 root 权限,而镜像以 rocketmq(uid=3000) 运行,需要提权
user: "0:0"
ports:
- "10909:10909"
- "10911:10911"
- "10912:10912"
environment:
NAMESRV_ADDR: rocketmq-namesrv:9876
# 开发环境限制 Broker 堆内存,默认 2g+1g 在 Docker Desktop 上容易 OOM
JAVA_OPT_EXT: "-Xms512m -Xmx512m -Xmn256m"
command: sh mqbroker -n rocketmq-namesrv:9876 -c /home/rocketmq/rocketmq-5.3.1/conf/broker.conf
depends_on:
rocketmq-namesrv:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/10911'"]
interval: 15s
timeout: 15s
retries: 15
start_period: 120s
volumes:
- rocketmq_broker_logs:/home/rocketmq/logs
- rocketmq_broker_store:/home/rocketmq/store
- ./docker/rocketmq/broker/conf/broker.conf:/home/rocketmq/rocketmq-5.3.1/conf/broker.conf:ro
networks:
jeepay:
ipv4_address: 172.20.0.13

扩展额外延迟插件的 RabbitMQ

#rabbitmq:

build:

context: ./docker/rabbitmq

dockerfile: Dockerfile

hostname: rabbitmq

container_name: jeepay-rabbitmq

image: jeepay-rabbitmq:latest

restart: always

ports:

- "15672:15672"

- "4369:4369"

- "5672:5672"

- "25672:25672"

environment:

RABBITMQ_DEFAULT_USER: 'admin'

RABBITMQ_DEFAULT_PASS: 'admin'

RABBITMQ_DEFAULT_VHOST: 'jeepay'

volumes:

- rabbitmq:/var/lib/rabbitmq

networks:

jeepay:

ipv4_address: 172.20.0.14

如需回退 ActiveMQ,可启用下面服务并同步修改 conf/*.yml 中的 MQ 配置。

#activemq:

build:

context: ./docker/activemq

dockerfile: Dockerfile

hostname: activemq

container_name: jeepay-activemq

image: jeepay-activemq:latest

restart: always

ports:

- "8161:8161"

- "61616:61616"

volumes:

- activemq:/opt/activemq

- ./docker/activemq/activemq.xml:/opt/activemq/conf/activemq.xml

networks:

jeepay:

ipv4_address: 172.20.0.15

redis:
platform: linux/amd64
hostname: redis
container_name: jeepay-redis
restart: always
image: ${REDIS_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/redis:6.2.14}
ports:
- "6380:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 12
start_period: 10s
volumes:
- redis:/data
networks:
jeepay:
ipv4_address: 172.20.0.12

payment:
build:
context: ./jeepay-payment
dockerfile: Dockerfile
image: jeepay-payment:latest
hostname: payment
container_name: jeepay-payment
restart: always
ports:
- "9216:9216"
healthcheck:
test: ["CMD-SHELL", "curl -s -o /dev/null http://127.0.0.1:9216"]
interval: 15s
timeout: 5s
retries: 12
start_period: 45s
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
rocketmq-broker:
condition: service_healthy
volumes:
- ./logs/payment:/jeepayhomes/service/logs
- ./conf/payment/application.yml:/jeepayhomes/service/app/application.yml
networks:
jeepay:
ipv4_address: 172.20.0.21

manager:
build:
context: ./jeepay-manager
dockerfile: Dockerfile
image: jeepay-manager:latest
hostname: manager
container_name: jeepay-manager
restart: always
ports:
- "9217:9217"
healthcheck:
test: ["CMD-SHELL", "curl -s -o /dev/null http://127.0.0.1:9217"]
interval: 15s
timeout: 5s
retries: 12
start_period: 45s
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
rocketmq-broker:
condition: service_healthy
volumes:
- ./logs/manager:/jeepayhomes/service/logs
- ./conf/manager/application.yml:/jeepayhomes/service/app/application.yml
networks:
jeepay:
ipv4_address: 172.20.0.22

merchant:
build:
context: ./jeepay-merchant
dockerfile: Dockerfile
image: jeepay-merchant:latest
hostname: merchant
container_name: jeepay-merchant
restart: always
ports:
- "9218:9218"
healthcheck:
test: ["CMD-SHELL", "curl -s -o /dev/null http://127.0.0.1:9218"]
interval: 15s
timeout: 5s
retries: 12
start_period: 45s
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
rocketmq-broker:
condition: service_healthy
volumes:
- ./logs/merchant:/jeepayhomes/service/logs
- ./conf/merchant/application.yml:/jeepayhomes/service/app/application.yml
networks:
jeepay:
ipv4_address: 172.20.0.23

ui-payment:
build:
context: ${UI_BASE_DIR:-..}/jeepay-ui
dockerfile: Dockerfile
args:
PLATFORM: cashier
image: jeepay-ui-payment:latest
hostname: payment-ui
container_name: jeepay-ui-payment
restart: always
environment:
- BACKEND_HOST=172.20.0.21:9216
ports:
- "9226:80"
depends_on:
payment:
condition: service_healthy
networks:
jeepay:
ipv4_address: 172.20.0.31

ui-manager:
build:
context: ${UI_BASE_DIR:-..}/jeepay-ui
dockerfile: Dockerfile
args:
PLATFORM: manager
image: jeepay-ui-manager:latest
hostname: manager-ui
container_name: jeepay-ui-manager
restart: always
environment:
- BACKEND_HOST=172.20.0.22:9217
ports:
- "9227:80"
depends_on:
manager:
condition: service_healthy
networks:
jeepay:
ipv4_address: 172.20.0.32

ui-merchant:
build:
context: ${UI_BASE_DIR:-..}/jeepay-ui
dockerfile: Dockerfile
args:
PLATFORM: merchant
image: jeepay-ui-merchant:latest
hostname: merchant-ui
container_name: jeepay-ui-merchant
restart: always
environment:
- BACKEND_HOST=172.20.0.23:9218
ports:
- "9228:80"
depends_on:
merchant:
condition: service_healthy
networks:
jeepay:
ipv4_address: 172.20.0.33

如果你需要对外完整配置,可以使用下面的方式

https://www.digitalocean.com/community/tools/nginx?domains.0.server.domain=pay.test.com&domains.0.server.documentRoot=&domains.0.server.redirectSubdomains=false&domains.0.https.hsts=false&domains.0.https.hstsPreload=true&domains.0.php.php=false&domains.0.reverseProxy.reverseProxy=true&domains.0.reverseProxy.proxyPass=http%3A%2F%2F172.20.0.26%3A9226&domains.0.routing.index=index.html&domains.0.routing.fallbackHtml=true&domains.0.routing.fallbackPhp=false&domains.0.logging.accessLog=true&domains.0.logging.errorLog=true&global.reverseProxy.proxyCoexistenceXForwarded=remove&global.app.lang=zhCN

访问并配置好所有域名和代理,下载文件放到项目根目录下取名叫做 nginx.tar.gz

#nginx:

image: nginx:latest

hostname: nginx

container_name: jeepay-nginx

ports:

- "80:80"

- "443:443"

depends_on:

- ui-manager

- ui-payment

- ui-merchant

volumes:

- ./nginx.tar.gz:/etc/nginx/nginx.tar.gz

# 需要给权限比如 chmod a+r ./conf/nginx.sh

- ./docker/nginx.sh:/docker-entrypoint.d/nginx.sh

networks:
jeepay:
ipam:
config:
- subnet: 172.20.0.0/16

volumes:
mysql:
redis:
rocketmq_namesrv_logs:
rocketmq_broker_logs:
rocketmq_broker_store:

rabbitmq:


File: upgrade.md

[v1.0.0_20210610]

  1. 新增:支持微信服务商和普通商户接口,支持V2和V3接口
  2. 新增:支持支付宝服务商和普通商户接口,支持沙箱和生成切换
  3. 新增:支持云闪付服务商接口
  4. 新增:支持统一下单接口(微信和支付宝所有支付方式)、查单接口、支付回调、获取渠道用户ID
  5. 新增:实现聚合码支付,主扫和被扫接口
  6. 新增:支持云闪付服务商接口
  7. 新增:支持运营平台和商户系统,完善的权限管理

[v1.1.0_20210618]

  1. 新增:增加发起退款,查询退款,退款回调接口
  2. 新增:增加微信、支付宝、云闪付通道的退款
  3. 新增:增加商户多应用管理
  4. 新增:增加操作员删除,重置密码功能
  5. 新增:增加商户系统操作员删除,重置密码功能
  6. 优化:优化支付API接口(商户应用支持)
  7. 优化:兼容Mysql8.0版本
  8. 优化:优化部分功能数据列表权限
  9. 修复:修复一些已知Bug

[v1.1.1_20210625]

  1. 新增:商户系统增加支付体验
  2. 新增:支付结果使用websocket监听
  3. 新增:运营平台支持重发商户通知功能
  4. 新增:运营平台完善退款功能(支持全额和部分退款)
  5. 新增:java sdk端增加退款实现
  6. 优化:解决异步通知编码问题
  7. 优化:解决payment项目缓存更新问题
  8. 优化:优化退款单号规则
  9. 优化:优化部分前端界面UI样式
  10. 修复:修改调用上游退款传递订单号问题

[v1.2.0_20210705]

  1. 新增:支持通过配置文件切换MQ
  2. 新增:增加RabbitMQ的支持
  3. 优化:优化微信V3收款,退款接口
  4. 优化:优化统计界面退款数据问题
  5. 优化:优化部分前端界面UI样式
  6. 修复:修复微信V3接口签名问题

[v1.3.0_20210712]

  1. 新增:系统支持 RocketMQ 消息中间件
  2. 新增:下单接口支持传入expiredTime 订单过期时间参数,单位:秒, 默认两个小时
  3. 新增:文件存储支持本地和阿里云OSS,便于扩展 (issue: #I3XV16:扩展oss存储的类型)
  4. 修复:解决微信V2接口支付成功上游重复通知问题(#I3ZQWC:重复收到微信支付结果通知)
  5. 修复:解决商户通知状态未变化的问题

[v1.4.0_20210719]

  1. 新增:系统内服务商子商户的支付宝扫码授权(免录参数)
  2. 新增:系统内的参数脱敏处理功能,对敏感数据使用***替代并不可回显仅支持修改
  3. 优化:升级springboot版本 2.4.5==》2.4.8( spring-security <5.4.7 存在安全漏洞:CVE-2021-22119)
  4. 优化:删除sun.misc.BASE64Decoder的引用,避免部分环境编译报错的问题;
  5. 优化:解决其他已知问题

[v1.5.0_20210727]

  1. 新增:提取jeepay-components项目, 放置OSS, MQ公共组件包
  2. 优化:重构多MQ的实现,对生产者和消费者项目的使用透明,支持无缝切换三个厂商
  3. 优化:ActiveMQ添加账密配置, 添加连接池pool配置
  4. 优化:修改聚合码前端项目的提示信息
  5. 优化:修改微信支付宝的参数配置项,支持自定义配置页面
  6. 修复:修复退款订单查询条件不生效等已知问题

[v1.5.1_20210803]

  1. 优化:阿里巴巴代码规范检测整改
  2. 优化:sonarLint 代码检测工具检测整改
  3. 修复:修复订单页搜索值不对应的BUG

[v1.6.0_20210816]

  1. 修复:修复订单多次通知产生异常日志
  2. 修复:修复微信条码查单延迟bug
  3. 新增:添加微信支付宝的转账接口代码
  4. 新增:添加商户发起转账api和查单回调接口
  5. 新增:运营平台添加转账订单查询功能
  6. 新增:商户系统添加转账订单查询和发起转账功能

[v1.7.0_20210830]

  1. 新增:商户系统新增分账组管理、分账关系绑定、分账记录查询功能
  2. 新增:支付网关新增分账绑定、分账请求API
  3. 新增:支付测试支持分账选项
  4. 修复:解决服务商配置修改后没有更新缓存的问题
  5. 修复:退款中的订单改为定时任务实时补单
  6. 修复 订单表记录表记录商户费率快照: https://gitee.com/jeequan/jeepay/issues/I46MDI
  7. 修复:退款订单表记录微信异常信息:https://gitee.com/jeequan/jeepay/issues/I47KUF
  8. 修复:主扫被扫都记录上游渠道用户ID: https://gitee.com/jeequan/jeepay/issues/I47KRW

[v1.8.0_20210910]

  1. 新增:商户系统添加退款操作并支持功能权限配置
  2. 修复:解决URL拼接问题,不再使用hutool拼接函数,改为自行拼接方式; https://gitee.com/jeequan/jeepay/issues/I484PM
  3. 优化:微信企业付款到零钱产品不支持服务商模式,在转账时候做限制,避免转出服务商资金 https://gitee.com/jeequan/jeepay/issues/I483FJ

[v1.9.0_20210930]

  1. 新增:增加小新支付通道,对接交易和退款接口
  2. 新增:增加退款回调处理逻辑
  3. 修复:修复云闪付空串导致回调验签失败问题
  4. 修复:修复云闪付机构传参问题
  5. 优化:支付收银台项目发布在payment项目下
  6. 优化:优化支付宝服务商分账接口 https://gitee.com/jeequan/jeepay/issues/I4BNDT

[v1.10.0_20211119]

  1. 新增:系统配置、 商户应用、服务商参数配置是否使用内存缓存支持开关式配置
  2. 新增:订单号生成支持使用mybatis-plus方式
  3. 新增:支付订单全额退款时状态修改为已退款
  4. 新增:调整系统的表格密度,一屏显示更多数据
  5. 新增:订单列表页支持多合一订单查询和展示
  6. 新增:登录页面增加登录验证码默认超时时间,并给予用户反馈
  7. 新增:商户系统的支付测试和转账默认一个应用
  8. 新增:统一下单接口删除了channelUser字段,统一使用channelExtra传参
  9. 修复:角色权限关联表字段扩容,避免入库出现问题; https://gitee.com/jeequan/jeepay/issues/I4DKRL
  10. 修复:解决云闪付退款传参不正确导致的问题
  11. 修复:修复文件存储位置选择阿里云oss时上传位置错误的问题
  12. 修复:解决聚合码更新费率问题 :https://gitee.com/jeequan/jeepay/issues/I4D2EB
  13. 优化:优化支付工具类
  14. 优化:微信退款异常添加日志信息
  15. 优化:调整接口返回的ContentType: https://gitee.com/jeequan/jeepay/issues/I4H2UX

[v1.11.0_20211223]

  1. 新增:增加PayPal支付通道(感谢@青木)
  2. 新增:增加阿里云RocketMQ商业版支持(感谢@pimh)
  3. 修复:解决fastjson版本导致toJson问题
  4. 优化:优化微信子商户的appID和自openID设置问题
  5. 优化:优化微信支付证书设置(退款问题)
  6. 优化:接口增加String类型处理

[v1.12.0_20220126]

  1. 新增:增加微信退款异步回调支持
  2. 新增:增加微信H5由payment项目地址统一跳转
  3. 新增:增加关闭订单接口(微信、支付宝、云闪付已对接)
  4. 新增:增加分账失败重新发起功能转
  5. 优化:升级支付宝转账接口(sdk升级到4.22.22.ALL)
  6. 修复:修复微信v3接口小程序支付报错问题:https://gitee.com/jeequan/jeepay/issues/I4PJKX
  7. 修复:修复安全漏洞(升级mysql-connector-java、velocity-engine-core版本)
  8. 修复:修复删除服务商时查看子商户数量问题

[v1.13.0_20220329]

  1. 优化:微信和支付宝接口增加支付超时时间:https://gitee.com/jeequan/jeepay/issues/I4WMK0
  2. 优化:优化微信支付V3接口对接
  3. 优化:项目支持jdk17编译
  4. 修复:修复paypal支付查询问题:https://gitee.com/jeequan/jeepay/issues/I4ZOHF
  5. 修复:修复微信支付V2接口退款问题
  6. 修复:修复支付下单会使用已停用接口问题:https://gitee.com/jeequan/jeepay/issues/I4SM0M

[v1.14.0_20220708]

  1. 新增:增加docker的支持
  2. 优化:从请求中获取参数并以+=拼接的方式,使用更为优雅的流式拼接
  3. 优化:优化商户删除逻辑
  4. 优化:分账执行API, 解决提示订单不存在的问题
  5. 优化:扩充日志表请求和响应数据的长度
  6. 修复:解决因目录不存在导致证书下载失败问题
  7. 修复:微信、支付宝设置订单超时bug
  8. 修复:OSS保存路径未考虑设置前缀问题
  9. 修复:订单关闭传递参数字段与文档描述不一致
  10. 修复:微信退款通知检验退款金额问题

[v1.15.0_20220915]

  1. 新增:增加计全付(jeepay plus线上支付平台)支付渠道接口
  2. 优化:微信H5支持同步跳转
  3. 修复:升级fastjson至1.2.83版
  4. 修复:修复微信app调起支付签名串问题

[v1.16.0_20221129]

  1. 新增:微信转账接口支持V3版本
  2. 新增:微信分账接口支持V3版本
  3. 优化:优化支付通知回调特殊符号问题
  4. 优化:优化微信小程序WX_LITE支付方式判断
  5. 修复:修复阿里云oss下载路径问题

[v2.0.0_20230319]

  1. 新增:重构支付渠道对接代码,支持接口市场下载安装:https://www.jeequan.com/ifstore/list.html
  2. 新增:增加订单创建时重写订单号方法
  3. 新增:增加转账订单补单功能
  4. 新增:增加微信、支付宝转账查询接口
  5. 新增:增加转账异步通知功能
  6. 优化:订单回调时回传最新支付数据
  7. 优化:优化微信转账、分账完成解冻金额
  8. 优化:优化微信商家转账到零钱接口(待正式账号测试)
  9. 修复:修复阿里云OSS上传问题

[v2.1.0_20230427]

  1. 新增:完善分账结果确认处理机制
  2. 新增:增加分账结果异步通知处理
  3. 新增:增加分账结果主动查询任务
  4. 优化:微信和支付宝分账结果确认
  5. 修复:修复微信分账V3接口子商户号取值错误导致无法分账问题

[v2.2.0_20230616]

  1. 新增:适配jdk11 17高版本支持(社区)
  2. 新增:支持Knife4j文档的适配,添加部分接口示例 http://pay.d.jeepay.vip/doc.html
  3. 优化:针对微信V3版本接口进行调整

[v2.2.1_20230816]

  1. 优化:更新支付宝沙箱地址
  2. 优化:修改数据库时间字段为小数点后3位
  3. 优化:搜索条件时间支持毫秒数

[v2.2.2_20231122]

  1. 优化:优化微信V3接口APP支付返回参数
  2. 优化:优化PayPal支付接口参数名、关单方法名大小写
  3. 优化:优化Docker部署
  4. 优化:优化分账页面描述

[v2.3.0_20240311]

  1. 优化:升级wxjava/hutool到最新版本, 适配最新版本微信支付接口
  2. 新增:添加项目下的Dockerfile文件
  3. 新增:一键部署安装、卸载脚本
  4. 修复: FastJSON开启安全模式,解决安全检测漏洞

[v2.4.0_20240612]

  1. 新增:支付宝官方订单码支付方式
  2. 修复:分账状态问题 #I97MQM
  3. 修复:解决商户通知转义问题#I9UT23
  4. 修复:解决退款直接成功时没有返回 successTime问题
  5. 优化:部分情况更新订单异常的现象

[v2.4.1_20250108]

  1. 修复:统一下单校验商户应用状态
  2. 修复:优化微信官方退款查询接口的退款逻辑判断;https://gitee.com/jeequan/jeepay/issues/I9RX2D
  3. 优化:完善聚合码付款相关业务
  4. 优化:selectOrderCount查询一次即可。 https://gitee.com/jeequan/jeepay/issues/IANUTB
  5. 优化:更新activemq到5.16.7
  6. 优化:优化AliYunRocketMQ的配置和消息组管理命名

[v3.0.0_20250109]

  1. 新增: 升级编译代码到jdk17
  2. 新增: 升级springboot到3.3.7
  3. 新增: 升级Knife4j和兼容历史swagger api
  4. 优化: 新建商户后不支持更改服务商 https://gitee.com/jeequan/jeepay/issues/IBF9D9
  5. 修复: 解决已知问题

[v3.1.0_20250314]

  1. 新增: 支持微信公钥模式
  2. 新增: 新版微信转账的接入 公告: https://developers.weixin.qq.com/community/pay/doc/000a060bb4c13095b6b27cc1b6ac01?page=1
  3. 优化: 支付测试自动关闭流程
  4. 修复: 解决已知问题

[v3.2.0_20260417]

  1. 新增: Shell 一键安装脚本默认支持 RocketMQ
  2. 优化: RocketMQ Broker 安装时自动写入当前服务器 IP,避免静态地址失效
  3. 优化: 卸载脚本支持幂等执行,缺失容器或网络时自动跳过
  4. 新增: 增加 Docker Hub 镜像构建与推送脚本

[v3.2.8_20260422]

  1. 优化: 一键安装 / 卸载脚本增强——跨发行版自动安装依赖、端口预检与自动避让、安装末尾部署自检,卸载支持任意目录一条命令
  2. 新增: 宝塔 Docker 应用新增"镜像仓库地址"字段,一键切换华为云 SWR / Docker Hub 官方镜像
  3. 优化: docs/install/include/nginx.conf 补齐 X-Forwarded-Proto / Port 头,并开启 forward-headers-strategy,修 HTTPS 反代下 mixed-content 和支付回跳
  4. 优化: README 精简至约 300 行,部署文档按主题拆分至 docs/deploy/*,优先引导华为云 SWR 镜像
  5. 修复: mysql8 / redis6 容器添加 --network-alias,解决应用按 hostname 解析失败(UnknownHostException)
  6. 修复: install.sh 自动把 application.yml datasource 密码 rootroot 替换为 mysql_pwd,消除 Access denied
  7. 修复: 移除 codegen 未用的 spring-context 依赖(消除 CVE-2024-38820 / CVE-2025-22233)

[v3.2.9_20260527]

  1. 修复: 支付宝授权回调 state 解析鲁棒性,异常或被构造的 state 不再触发 NPE / 数组越界
  2. 修复: 支付宝异步通知补 out_trade_no / app_id / total_amount 业务字段交叉校验,消除多商户 / 跨订单签名穿越场景的误处理风险(建议受影响部署重新发布 jeepay-payment 镜像)
  3. 修复: install.sh git clone 失败时立即硬退出,不再让后续步骤误报根因
  4. 优化: conf/*/application.yml 默认 MQ 切到 rocketMQ 后,统一注释掉 spring.activemq 段,消除后台连接 activemq5 的噪音
  5. 文档: README 增加"AI 接入助手"段,指向 jeepay-skills 仓库
  6. 优化: install.sh 默认 jeepayRef 由 V3.2.8 跟进到 V3.2.9

File: version.md

v3.2.9_20260527


File: conf/readme.txt

文件夹用途: 用于放置开发环境的通用配置项和生产环境下的项目配置模板。

  1. 【devCommons】:
    开发环境通用配置文件放置目录。 更改此目录后将覆写 manager/merchant/payment 项目下的application.yml文件对应参数,从而达到每个项目不必单独配置的目的,更加节约开发时间。

  2. 该文件夹下的【manager/merchant/payment】:
    文件为上线部署时与jar同级目录下的application.yml建议配置项的模板。 需更改为实际参数, 也可按需添加。

扩展知识:
#####################################################

spring boot支持外部application.yml 读取优先级为:

1、file:./config/(当前目录下的config文件夹)

2、file:./(当前目录)

3、classpath:/config/(classpath下的config目录)

4、classpath:/(classpath根目录)

#####################################################


File: conf/devCommons/config/application.yml

#################################

开发环境通用配置文件(每个项目通用配置)

#################################
server:
servlet:
context-path: / #设置应用的目录. 前缀需要带/, 无需设置后缀, 示例 【 /xxx 】 or 【 / 】
spring:
application:
name: jeepay
main:
allow-circular-references: true
servlet:
multipart:
enabled: true #是否启用http上传处理
max-request-size: 10MB #最大请求文件的大小
max-file-size: 10MB #设置单个文件最大长度
freemarker:
template-loader-path: classpath:/templates #freemarker模板目录
template-encoding: UTF-8
suffix: .ftl
settings:
classic_compatible: true # 如果变量为null,转化为空字符串,比如做比较的时候按照空字符做比较
number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00
datasource:
# yml填写url连接串, 无需将&符号进行转义
url: jdbc:mysql://127.0.0.1:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123
druid:
# 连接池配置项
initial-size: 5 #初始化时建立物理连接的个数
min-idle: 5 #最小连接池数量
max-active: 30 #最大连接池数量
max-wait: 60000 #获取连接时最大等待时间,单位毫秒
# 检测相关
test-while-idle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
test-on-borrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
test-on-return: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
time-between-eviction-runs-millis: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
min-evictable-idle-time-millis: 300000 #连接保持空闲而不被驱逐的最小时间
validation-query: SELECT 1 FROM DUAL
# 是否缓存preparedStatement
pool-prepared-statements: false # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
max-pool-prepared-statement-per-connection-size: 20 # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计 通过connectProperties属性来打开mergeSql功能;慢SQL记录
filters: stat,wall
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
cache:
type: redis
data:
redis:
host: 127.0.0.1
port: 6379
timeout: 1000
password:

#activeMQ配置 ( 注意: activeMQ配置项需在spring的下级。默认 MQ 已切换到 rocketMQ,此段保留作参考;如需切回 activeMQ,请同步修改 isys.mq.vender )

activemq:

broker-url: failover:(tcp://127.0.0.1:61616?wireFormat.maxInactivityDuration=0) #连接地址

in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。

user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。

password: manager

pool:

enabled: true

max-connections: 10

idle-timeout: 30000 # 空闲的连接过期时间,默认为30秒

#rabbitmq配置 ( 注意: rabbitmq配置项需在spring的下级 )

rabbitmq:

addresses: 127.0.0.1:5672

username: guest

password: guest

dynamic: true

virtual-host: /

rocketmq配置 ( 注意:rocketmq配置项请放置到根目录, 不是spring的二级配置! )

#rocketmq:

name-server: 127.0.0.1:9876

producer:

group: JEEPAY-GROUP

阿里云rocketmq配置 ( 注意:aliyun-rocketmq配置项请放置到根目录, 不是spring的二级配置!需要阿里云开通rocketMQ产品,创建Group和Topic )

#aliyun-rocketmq:

namesrvAddr: xxx

accessKey: xxx

secretKey: xxx

groupIdPrefix: GID_JEEPAY_ # (分组前缀, 具体名称详见AliyunRocketMQFactory.java )

#日志配置参数。

当存在logback-spring.xml文件时: 该配置将引进到logback配置, springboot配置不生效。

不存在logback-spring.xml 文件时, 使用springboot的配置, 同样可用。

web:
resources:
static-locations: classpath:/static
logging:
level:
root: info #主日志级别
com.jeequan.jeepay: debug #该项目日志级别,当需要打印sql时请开启为debug
file:
path: ./logs

#系统业务参数
isys:
#是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时,应开启此配置或在nginx统一配置允许跨域]
allow-cors: true

#是否内存缓存配置信息: true表示开启如支付网关地址/商户应用配置/服务商配置等, 开启后需检查MQ的广播模式是否正常; false表示直接查询DB.
cache-config: true

oss:
file-root-path: /home/jeepay/upload #存储根路径 ( 无需以‘/’结尾 )
file-public-path: ${isys.oss.file-root-path}/public #公共读取块 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
file-private-path: ${isys.oss.file-root-path}/private #私有化本地访问,不允许url方式公共读取 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )

text
# [local]: 本地存储,所有的文件将存在放本地,可通过nfs, rsync工具实现多机共享;
# [aliyun-oss]: 将文件统一上传到阿里云oss服务器;  注意:需调整jeepay-components-oss/pom.xml中的aliyun-sdk-oss组件依赖方式
service-type: local

# 阿里云OSS服务配置信息
aliyun-oss:
  endpoint: oss-cn-beijing.aliyuncs.com  #endpoint  如: oss-cn-beijing.aliyuncs.com
  public-bucket-name: bucket1 #公共读 桶名称
  private-bucket-name: bucket2  #私有 桶名称
  access-key-id: KEY_KEY_KEY   #AccessKeyId
  access-key-secret: SECRET_SECRET_SECRET  #AccessKeySecret

mq:
vender: rocketMQ # 切换MQ厂商, 支持:【 activeMQ rabbitMQ rocketMQ aliYunRocketMQ 】, 需正确配置 【对应的yml参数】 和 【jeepay-components-mq项目下pom.xml中的依赖包】。

rocketmq:
name-server: 127.0.0.1:9876
producer:
group: PID_JEEPAY_DEV
send-message-timeout: 10000
retry-times-when-send-failed: 2
retry-times-when-send-async-failed: 2


File: conf/manager/application.yml

#################################

spring boot支持外部application.yml 读取优先级为:

1、file:./config/(当前目录下的config文件夹)

2、file:./(当前目录)

3、classpath:/config/(classpath下的config目录)

4、classpath:/(classpath根目录)

建议: 如果是jar则放置到与jar相同的目录下, 如果解压文件放置到classpath: config目录下。 (需要将文件重命名为 application.yml )

该yml文件只配置与环境相关的参数, 其他配置读取项目下的配置项

#################################
server:
port: 9217 #设置端口
servlet:
context-path: / #设置应用的目录. 前缀需要带/, 无需设置后缀, 示例 【 /xxx 】 or 【 / 】

开启对 X-Forwarded-* 请求头的识别,保证外层 nginx 反代(HTTPS / 域名)场景下

forward-headers-strategy: framework
spring:
application:
name: jeepay-manager
servlet:
multipart:
enabled: true #是否启用http上传处理
max-request-size: 10MB #最大请求文件的大小
max-file-size: 10MB #设置单个文件最大长度
resources:
static-locations: classpath:/static #项目静态资源路径 (可直接通过http访问)
freemarker:
template-loader-path: classpath:/templates #freemarker模板目录
template-encoding: UTF-8
suffix: .ftl
settings:
classic_compatible: true # 如果变量为null,转化为空字符串,比如做比较的时候按照空字符做比较
number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00
datasource:
# yml填写url连接串, 无需将&符号进行转义
url: jdbc:mysql://mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: rootroot
druid:
# 连接池配置项
initial-size: 5 #初始化时建立物理连接的个数
min-idle: 5 #最小连接池数量
max-active: 30 #最大连接池数量
max-wait: 60000 #获取连接时最大等待时间,单位毫秒
# 检测相关
test-while-idle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
test-on-borrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
test-on-return: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
time-between-eviction-runs-millis: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
min-evictable-idle-time-millis: 300000 #连接保持空闲而不被驱逐的最小时间
keep-alive: true #对 minIdle 以内的空闲连接定期保活校验,防止空闲连接被 MySQL wait_timeout 等提前关闭
validation-query: SELECT 1 FROM DUAL
# 是否缓存preparedStatement
pool-prepared-statements: false # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
max-pool-prepared-statement-per-connection-size: 20 # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计 通过connectProperties属性来打开mergeSql功能;慢SQL记录
filters: stat,wall
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
cache:
type: redis
data:
redis:
host: redis
port: 6379
database: 1 #1库:运营平台 #2库:商户系统 #3库:支付网关
timeout: 1000
password:

#activeMQ配置 ( 注意: activeMQ配置项需在spring的下级。默认 MQ 已切换到 rocketMQ,此段保留作参考;如需切回 activeMQ,请同步修改 isys.mq.vender )

activemq:

broker-url: failover:(tcp://activemq5:61616?wireFormat.maxInactivityDuration=0) #连接地址

in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。

user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。

password: manager

pool:

enabled: true

max-connections: 10

idle-timeout: 30000 # 空闲的连接过期时间,默认为30秒

#rabbitmq配置 ( 注意: rabbitmq配置项需在spring的下级 )

rabbitmq:

addresses: 172.20.0.11:5672

username: admin

password: admin

dynamic: true

virtual-host: jeepay

rocketmq配置 ( 注意:rocketmq配置项请放置到根目录, 不是spring的二级配置! )

#rocketmq:

name-server: 172.20.0.11:9876

producer:

group: JEEPAY-GROUP

阿里云rocketmq配置 ( 注意:aliyun-rocketmq配置项请放置到根目录, 不是spring的二级配置!需要阿里云开通rocketMQ产品,创建Group和Topic )

#aliyun-rocketmq:

namesrvAddr: xxx

accessKey: xxx

secretKey: xxx

groupIdPrefix: GID_JEEPAY_ # (分组前缀, 具体名称详见AliyunRocketMQFactory.java )

#日志配置参数。

当存在logback-spring.xml文件时: 该配置将引进到logback配置, springboot配置不生效。

不存在logback-spring.xml 文件时, 使用springboot的配置, 同样可用。

logging:
level:
root: info #主日志级别
com.jeequan.jeepay: debug #该项目日志级别,当需要打印sql时请开启为debug
path: /jeepayhomes/service/logs #日志存放地址

knife4j APIDOC文档

springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.jeequan.jeepay.mgr.ctrl
knife4j:
enable: true

#系统业务参数
isys:

jwt-secret: t7w3P8X6472qWc3u #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。

#是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时,应开启此配置或在nginx统一配置允许跨域]
allow-cors: true

#是否内存缓存配置信息: true表示开启如支付网关地址/商户应用配置/服务商配置等, 开启后需检查MQ的广播模式是否正常; false表示直接查询DB.
cache-config: false

oss:
file-root-path: /jeepayhomes/service/uploads #存储根路径 ( 无需以‘/’结尾 )
file-public-path: ${isys.oss.file-root-path}/public #公共读取块 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
file-private-path: ${isys.oss.file-root-path}/private #私有化本地访问,不允许url方式公共读取 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )

text
# [local]: 本地存储,所有的文件将存在放本地,可通过nfs, rsync工具实现多机共享;
# [aliyun-oss]: 将文件统一上传到阿里云oss服务器;  注意:需调整jeepay-components-oss/pom.xml中的aliyun-sdk-oss组件依赖方式
service-type: local

# 阿里云OSS服务配置信息
aliyun-oss:
  endpoint: oss-cn-beijing.aliyuncs.com  #endpoint  如: oss-cn-beijing.aliyuncs.com
  public-bucket-name: bucket1 #公共读 桶名称
  private-bucket-name: bucket2  #私有 桶名称
  access-key-id: KEY_KEY_KEY   #AccessKeyId
  access-key-secret: SECRET_SECRET_SECRET  #AccessKeySecret

mq:
vender: rocketMQ # 切换MQ厂商, 支持:【 activeMQ rabbitMQ rocketMQ aliYunRocketMQ 】, 需正确配置 【对应的yml参数】 和 【jeepay-components-mq项目下pom.xml中的依赖包】。

rocketmq:
name-server: rocketmq-namesrv:9876
producer:
group: PID_JEEPAY_MANAGER
send-message-timeout: 10000
retry-times-when-send-failed: 2
retry-times-when-send-async-failed: 2


File: conf/merchant/application.yml

#################################

spring boot支持外部application.yml 读取优先级为:

1、file:./config/(当前目录下的config文件夹)

2、file:./(当前目录)

3、classpath:/config/(classpath下的config目录)

4、classpath:/(classpath根目录)

建议: 如果是jar则放置到与jar相同的目录下, 如果解压文件放置到classpath: config目录下。 (需要将文件重命名为 application.yml )

该yml文件只配置与环境相关的参数, 其他配置读取项目下的配置项

#################################
server:
port: 9218 #设置端口
servlet:
context-path: / #设置应用的目录. 前缀需要带/, 无需设置后缀, 示例 【 /xxx 】 or 【 / 】

开启对 X-Forwarded-* 请求头的识别,保证外层 nginx 反代(HTTPS / 域名)场景下

forward-headers-strategy: framework
spring:
application:
name: jeepay-merchant
servlet:
multipart:
enabled: true #是否启用http上传处理
max-request-size: 10MB #最大请求文件的大小
max-file-size: 10MB #设置单个文件最大长度
resources:
static-locations: classpath:/static #项目静态资源路径 (可直接通过http访问)
freemarker:
template-loader-path: classpath:/templates #freemarker模板目录
template-encoding: UTF-8
suffix: .ftl
settings:
classic_compatible: true # 如果变量为null,转化为空字符串,比如做比较的时候按照空字符做比较
number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00
datasource:
# yml填写url连接串, 无需将&符号进行转义
url: jdbc:mysql://mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: rootroot
druid:
# 连接池配置项
initial-size: 5 #初始化时建立物理连接的个数
min-idle: 5 #最小连接池数量
max-active: 30 #最大连接池数量
max-wait: 60000 #获取连接时最大等待时间,单位毫秒
# 检测相关
test-while-idle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
test-on-borrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
test-on-return: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
time-between-eviction-runs-millis: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
min-evictable-idle-time-millis: 300000 #连接保持空闲而不被驱逐的最小时间
keep-alive: true #对 minIdle 以内的空闲连接定期保活校验,防止空闲连接被 MySQL wait_timeout 等提前关闭
validation-query: SELECT 1 FROM DUAL
# 是否缓存preparedStatement
pool-prepared-statements: false # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
max-pool-prepared-statement-per-connection-size: 20 # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计 通过connectProperties属性来打开mergeSql功能;慢SQL记录
filters: stat,wall
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
cache:
type: redis
data:
redis:
host: redis
port: 6379
database: 2 #1库:运营平台 #2库:商户系统 #3库:支付网关
timeout: 1000
password:

#activeMQ配置 ( 注意: activeMQ配置项需在spring的下级。默认 MQ 已切换到 rocketMQ,此段保留作参考;如需切回 activeMQ,请同步修改 isys.mq.vender )

activemq:

broker-url: failover:(tcp://activemq5:61616?wireFormat.maxInactivityDuration=0) #连接地址

in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。

user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。

password: manager

pool:

enabled: true

max-connections: 10

idle-timeout: 30000 # 空闲的连接过期时间,默认为30秒

#rabbitmq配置 ( 注意: rabbitmq配置项需在spring的下级 )

rabbitmq:

addresses: 172.20.0.11:5672

username: admin

password: admin

dynamic: true

virtual-host: jeepay

rocketmq配置 ( 注意:rocketmq配置项请放置到根目录, 不是spring的二级配置! )

#rocketmq:

name-server: 172.20.0.11:9876

producer:

group: JEEPAY-GROUP

阿里云rocketmq配置 ( 注意:aliyun-rocketmq配置项请放置到根目录, 不是spring的二级配置!需要阿里云开通rocketMQ产品,创建Group和Topic )

#aliyun-rocketmq:

namesrvAddr: xxx

accessKey: xxx

secretKey: xxx

groupIdPrefix: GID_JEEPAY_ # (分组前缀, 具体名称详见AliyunRocketMQFactory.java )

#日志配置参数。

当存在logback-spring.xml文件时: 该配置将引进到logback配置, springboot配置不生效。

不存在logback-spring.xml 文件时, 使用springboot的配置, 同样可用。

logging:
level:
root: info #主日志级别
com.jeequan.jeepay: debug #该项目日志级别,当需要打印sql时请开启为debug
path: /jeepayhomes/service/logs #日志存放地址

knife4j APIDOC文档

springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.jeequan.jeepay.mch.ctrl
knife4j:
enable: true

#系统业务参数
isys:

jwt-secret: ARNXp4MzjOOQqxtv #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。

#是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时,应开启此配置或在nginx统一配置允许跨域]
allow-cors: true

#是否内存缓存配置信息: true表示开启如支付网关地址/商户应用配置/服务商配置等, 开启后需检查MQ的广播模式是否正常; false表示直接查询DB.
cache-config: false

oss:
file-root-path: /jeepayhomes/service/uploads #存储根路径 ( 无需以‘/’结尾 )
file-public-path: ${isys.oss.file-root-path}/public #公共读取块 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
file-private-path: ${isys.oss.file-root-path}/private #私有化本地访问,不允许url方式公共读取 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )

text
# [local]: 本地存储,所有的文件将存在放本地,可通过nfs, rsync工具实现多机共享;
# [aliyun-oss]: 将文件统一上传到阿里云oss服务器;  注意:需调整jeepay-components-oss/pom.xml中的aliyun-sdk-oss组件依赖方式
service-type: local

# 阿里云OSS服务配置信息
aliyun-oss:
  endpoint: oss-cn-beijing.aliyuncs.com  #endpoint  如: oss-cn-beijing.aliyuncs.com
  public-bucket-name: bucket1 #公共读 桶名称
  private-bucket-name: bucket2  #私有 桶名称
  access-key-id: KEY_KEY_KEY   #AccessKeyId
  access-key-secret: SECRET_SECRET_SECRET  #AccessKeySecret

mq:
vender: rocketMQ # 切换MQ厂商, 支持:【 activeMQ rabbitMQ rocketMQ aliYunRocketMQ 】, 需正确配置 【对应的yml参数】 和 【jeepay-components-mq项目下pom.xml中的依赖包】。

rocketmq:
name-server: rocketmq-namesrv:9876
producer:
group: PID_JEEPAY_MERCHANT
send-message-timeout: 10000
retry-times-when-send-failed: 2
retry-times-when-send-async-failed: 2


File: conf/payment/application.yml

#################################

spring boot支持外部application.yml 读取优先级为:

1、file:./config/(当前目录下的config文件夹)

2、file:./(当前目录)

3、classpath:/config/(classpath下的config目录)

4、classpath:/(classpath根目录)

建议: 如果是jar则放置到与jar相同的目录下, 如果解压文件放置到classpath: config目录下。 (需要将文件重命名为 application.yml )

该yml文件只配置与环境相关的参数, 其他配置读取项目下的配置项

#################################
server:
port: 9216 #设置端口
servlet:
context-path: / #设置应用的目录. 前缀需要带/, 无需设置后缀, 示例 【 /xxx 】 or 【 / 】

开启对 X-Forwarded-* 请求头的识别,保证外层 nginx 反代(HTTPS / 域名)

场景下收银台 return_url、支付回调 URL 与微信 H5 redirect_url 能拼对协议/host。

forward-headers-strategy: framework
spring:
application:
name: jeepay-payment
servlet:
multipart:
enabled: true #是否启用http上传处理
max-request-size: 10MB #最大请求文件的大小
max-file-size: 10MB #设置单个文件最大长度
resources:
static-locations: classpath:/static #项目静态资源路径 (可直接通过http访问)
freemarker:
template-loader-path: classpath:/templates #freemarker模板目录
template-encoding: UTF-8
suffix: .ftl
settings:
classic_compatible: true # 如果变量为null,转化为空字符串,比如做比较的时候按照空字符做比较
number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00
datasource:
# yml填写url连接串, 无需将&符号进行转义
url: jdbc:mysql://mysql:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: rootroot
druid:
# 连接池配置项
initial-size: 5 #初始化时建立物理连接的个数
min-idle: 5 #最小连接池数量
max-active: 30 #最大连接池数量
max-wait: 60000 #获取连接时最大等待时间,单位毫秒
# 检测相关
test-while-idle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
test-on-borrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
test-on-return: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
time-between-eviction-runs-millis: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
min-evictable-idle-time-millis: 300000 #连接保持空闲而不被驱逐的最小时间
keep-alive: true #对 minIdle 以内的空闲连接定期保活校验,防止空闲连接被 MySQL wait_timeout 等提前关闭
validation-query: SELECT 1 FROM DUAL
# 是否缓存preparedStatement
pool-prepared-statements: false # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
max-pool-prepared-statement-per-connection-size: 20 # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计 通过connectProperties属性来打开mergeSql功能;慢SQL记录
filters: stat,wall
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
cache:
type: redis
data:
redis:
host: redis
port: 6379
database: 3 #1库:运营平台 #2库:商户系统 #3库:支付网关
timeout: 1000
password:

#activeMQ配置 ( 注意: activeMQ配置项需在spring的下级。默认 MQ 已切换到 rocketMQ,此段保留作参考;如需切回 activeMQ,请同步修改 isys.mq.vender )

activemq:

broker-url: failover:(tcp://activemq5:61616?wireFormat.maxInactivityDuration=0) #连接地址

in-memory: false # Jeepay项目不可使用内存模式, 需要连接多个消费者。

user: system # activeMQ默认无需账密认证。 打开认证:activemq.xml添加simpleAuthenticationPlugin标签,账密在credentials.properties文件。

password: manager

pool:

enabled: true

max-connections: 10

idle-timeout: 30000 # 空闲的连接过期时间,默认为30秒

#rabbitmq配置 ( 注意: rabbitmq配置项需在spring的下级 )

rabbitmq:

addresses: 172.20.0.11:5672

username: admin

password: admin

dynamic: true

virtual-host: jeepay

rocketmq配置 ( 注意:rocketmq配置项请放置到根目录, 不是spring的二级配置! )

#rocketmq:

name-server: 172.20.0.11:9876

producer:

阿里云rocketmq配置 ( 注意:aliyun-rocketmq配置项请放置到根目录, 不是spring的二级配置!需要阿里云开通rocketMQ产品,创建Group和Topic )

#aliyun-rocketmq:

namesrvAddr: xxx

accessKey: xxx

secretKey: xxx

groupIdPrefix: GID_JEEPAY_ # (分组前缀, 具体名称详见AliyunRocketMQFactory.java )

#日志配置参数。

当存在logback-spring.xml文件时: 该配置将引进到logback配置, springboot配置不生效。

不存在logback-spring.xml 文件时, 使用springboot的配置, 同样可用。

logging:
level:
root: info #主日志级别
com.jeequan.jeepay: debug #该项目日志级别,当需要打印sql时请开启为debug
path: /jeepayhomes/service/logs #日志存放地址

knife4j APIDOC文档

springdoc:
swagger-ui:
path: /swagger-ui.html
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
display-name: '支付网关'
paths-to-match: '/**'
packages-to-scan: com.jeequan.jeepay.pay.ctrl.test
knife4j:
enable: true
setting:
language: zh_cn
swagger-model-name: 公共响应
documents:
- name: API
locations: classpath:markdown/doc/*
group: default

#系统业务参数
isys:

#是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时,应开启此配置或在nginx统一配置允许跨域]
allow-cors: true

#是否内存缓存配置信息: true表示开启如支付网关地址/商户应用配置/服务商配置等, 开启后需检查MQ的广播模式是否正常; false表示直接查询DB.
cache-config: false

oss:
file-root-path: /jeepayhomes/service/uploads #存储根路径 ( 无需以‘/’结尾 )
file-public-path: ${isys.oss.file-root-path}/public #公共读取块 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
file-private-path: ${isys.oss.file-root-path}/private #私有化本地访问,不允许url方式公共读取 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )

text
# [local]: 本地存储,所有的文件将存在放本地,可通过nfs, rsync工具实现多机共享;
# [aliyun-oss]: 将文件统一上传到阿里云oss服务器;  注意:需调整jeepay-components-oss/pom.xml中的aliyun-sdk-oss组件依赖方式
service-type: local

# 阿里云OSS服务配置信息
aliyun-oss:
  endpoint: oss-cn-beijing.aliyuncs.com  #endpoint  如: oss-cn-beijing.aliyuncs.com
  public-bucket-name: bucket1 #公共读 桶名称
  private-bucket-name: bucket2  #私有 桶名称
  access-key-id: KEY_KEY_KEY   #AccessKeyId
  access-key-secret: SECRET_SECRET_SECRET  #AccessKeySecret

mq:
vender: rocketMQ # 切换MQ厂商, 支持:【 activeMQ rabbitMQ rocketMQ aliYunRocketMQ 】, 需正确配置 【对应的yml参数】 和 【jeepay-components-mq项目下pom.xml中的依赖包】。

rocketmq:
name-server: rocketmq-namesrv:9876
producer:
group: PID_JEEPAY_PAYMENT
send-message-timeout: 10000
retry-times-when-send-failed: 2
retry-times-when-send-async-failed: 2


File: docker/push-to-docker.md

  1. 编译
text
mvn install
  1. 构建镜像及推送镜像(不需要docker环境)
text
export DOCKER_REGISTRY=registry.cn-beijing.aliyuncs.com
export DOCKER_NAMESPACE=jeequan
export DOCKER_IMAGE_TAG=v1.14.0-alpha
export DOCKER_REGISTRY_USERNAME=username1
export DOCKER_REGISTRY_PASSWORD=password1

cd jeepay-payment
mvn jib:build \
    -Djib.to.image=$DOCKER_REGISTRY/$DOCKER_NAMESPACE/jeepay-payment:$DOCKER_IMAGE_TAG \
    -Djib.to.auth.username=$DOCKER_REGISTRY_USERNAME \
    -Djib.to.auth.password=$DOCKER_REGISTRY_PASSWORD
    
cd ../jeepay-merchant
mvn jib:build \
    -Djib.to.image=$DOCKER_REGISTRY/$DOCKER_NAMESPACE/jeepay-merchant:$DOCKER_IMAGE_TAG \
    -Djib.to.auth.username=$DOCKER_REGISTRY_USERNAME \
    -Djib.to.auth.password=$DOCKER_REGISTRY_PASSWORD
 
cd ../jeepay-manager
mvn jib:build \
    -Djib.to.image=$DOCKER_REGISTRY/$DOCKER_NAMESPACE/jeepay-manager:$DOCKER_IMAGE_TAG \
    -Djib.to.auth.username=$DOCKER_REGISTRY_USERNAME \
    -Djib.to.auth.password=$DOCKER_REGISTRY_PASSWORD

File: docs/features.md

[Binary file]


File: docs/project-structure.md

项目结构与仓库关系

项目结构

text
jeepay
├── conf                     # 系统部署所需 yml 配置
├── docker                   # Docker 相关文件
├── docs                     # 项目文档
│   ├── deploy               # 部署详细文档
│   ├── install              # 安装脚本
│   ├── script               # 启动脚本
│   └── sql                  # 初始化 SQL 文件
├── jeepay-components        # 公共组件目录
│   ├── jeepay-components-mq # MQ 组件
│   └── jeepay-components-oss# OSS 组件
├── jeepay-core              # 核心依赖模块
├── jeepay-manager           # 运营平台服务端(9217)
├── jeepay-merchant          # 商户系统服务端(9218)
├── jeepay-payment           # 支付网关(9216)
├── jeepay-service           # 业务层代码
└── jeepay-z-codegen         # MyBatis 代码生成模块

仓库关系

仓库 作用
jeepay 服务端主仓库,包含支付网关、运营平台、商户平台、核心服务
jeepay-ui 前端项目
jeepay-sdk-java Java SDK,供业务系统对接 Jeepay 接口时使用

File: docs/screenshots.md

[Binary file]


File: docs/deploy/baota.md

宝塔面板部署

面向在宝塔(BaoTa)面板上把 jeepay 作为 Docker 应用一键安装的场景。宝塔用户不需要 git clone 源码,所有配置文件由 compose 里的 jeepay-configs init 容器(alpine/git 镜像)从 gitee 按 tag 拉下来分发。

Compose 文件

镜像默认地址

所有业务镜像 + MySQL / Redis / RocketMQ / Nginx 默认走华为云 SWR 公开仓库(swr.cn-south-1.myhuaweicloud.com/jeepay/*),由计全官方维护,国内直拉不需要 Docker Hub 加速器。alpine/git(配置分发 init 容器)仍从 Docker Hub 拉(< 20MB,一次性)。

想改回 Docker Hub 上游镜像,可通过下面"可选环境变量"覆盖。

宝塔应用模板要声明的变量

必须

变量 用途 建议默认
VERSION 业务镜像 tag(jeepay-manager 等) 3.2.0
CONFIG_REF 配置源 git ref(与 VERSION 同版本的 tag 或 master) 当前 release tag
UI_RELEASE 前端 html.tar.gz 的 jeepay-ui release tag V3.0.0
APP_PATH 宿主部署根目录 宝塔默认
HOST_IP 对外绑定 IP 宝塔默认
WEB_HTTP_PORT1 / 2 / 3 映射到容器 19216 / 19217 / 19218 19216 / 19217 / 19218
CPUS / MEMORY_LIMIT nginx 资源限制 1 / 512m

可选(改镜像源时覆盖)

变量 默认
MYSQL_IMAGE swr.cn-south-1.myhuaweicloud.com/jeepay/mysql:8.0.25
REDIS_IMAGE swr.cn-south-1.myhuaweicloud.com/jeepay/redis:6.2.14
ROCKETMQ_IMAGE swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1
NGINX_IMAGE swr.cn-south-1.myhuaweicloud.com/jeepay/nginx:1.18.0
MANAGER_IMAGE swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-manager:${VERSION}
MERCHANT_IMAGE swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-merchant:${VERSION}
PAYMENT_IMAGE swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-payment:${VERSION}
JEEPAY_CONFIGS_IMAGE alpine/git:v2.45.2(Docker Hub)

切回 Docker Hub 整套示例:

text
MYSQL_IMAGE=mysql:8.0.25
REDIS_IMAGE=redis:6.2.14
ROCKETMQ_IMAGE=apache/rocketmq:5.3.1
NGINX_IMAGE=nginx:1.18.0
MANAGER_IMAGE=jeepay/jeepay-manager:3.2.0
MERCHANT_IMAGE=jeepay/jeepay-merchant:3.2.0
PAYMENT_IMAGE=jeepay/jeepay-payment:3.2.0

安装后怎么改配置

配置文件都在 ${APP_PATH}/jeepayhomes/jeepayConfigs/ 下,直接编辑即可:

text
jeepayConfigs/
├── db/my.cnf, init.sql
├── redis/redis.conf
├── rocketmq/broker.conf
├── service/{manager,merchant,payment}/application.yml
├── nginx/nginx.conf, conf.d/, html/
└── .latest/        # 最新版模板(只读参考,不要改)

改完重启对应服务:

bash
docker compose restart jeepay-manager
# nginx 改完可热加载
docker exec nginx118 nginx -t && docker exec nginx118 nginx -s reload

jeepay-configs 用 cp -n 铺配置,已存在的文件永远不覆盖,机器重启 / compose up 都不会丢失用户编辑。

升级版本

  1. 在宝塔 UI 改 VERSION 和 CONFIG_REF 到新 tag(两者建议同值)
  2. 重建应用:宝塔 UI 点"重建",或 docker compose up -d
  3. .latest/ 目录会同步刷新到新版模板,用户自己的 yml 不动
  4. 看 diff 决定是否合并新模板中的新字段:
    bash
    diff ${APP_PATH}/jeepayhomes/jeepayConfigs/service/manager/application.yml \
         ${APP_PATH}/jeepayhomes/jeepayConfigs/.latest/conf/manager/application.yml

宝塔场景特有的点

  • 不需要 jeepay/jeepay-configs 镜像:从 alpine/git 直接 clone,配置永远跟 git tag 一致
  • jeepay-configs 容器安装后显示 Exited (0):正常,一次性 init 容器跑完即退出
  • baota_net 是宝塔预建网络:compose 里 external: true,不要自己创建

验证

安装完成后检查:

bash
# 8 个业务容器 + 1 个 init 容器
docker ps -a --format "table {{.Names}}\t{{.Status}}" | grep -E "jeepay|mysql8|redis6|rocketmq|nginx118"

# 三个 API healthy
for c in jeepaymanager jeepaymerchant jeepaypayment; do
  echo -n "$c: "; docker inspect --format '{{.State.Health.Status}}' $c
done

# 验证码 / 登录(浏览器访问宝塔映射的 19217 端口)

出问题看哪里

  • troubleshooting.md:所有部署方式通用的故障排查
  • https.md:配置域名 + HTTPS 反代(宝塔场景建议在外层再套一层 nginx + 证书)
  • ${APP_PATH}/jeepayhomes/service/logs/:业务服务日志
  • docker logs jeepay-configs:配置分发是否成功

File: docs/deploy/compose.md

Docker Compose 部署

适合本地 / 测试环境拉起完整集群(含前端)。

目录约定

text
jeepay-open/
├── jeepay/
└── jeepay-ui/

前端不在 jeepay 同级时,可在 jeepay/.env 覆盖 UI_BASE_DIR(参考 .env.example)。

启动

bash
cd jeepay
mvn clean package -DskipTests          # 编译后端 JAR

docker compose up -d --build           # 首次:编译镜像 + 启动
docker compose up -d                   # 后续:跳过编译
docker compose restart payment         # 重启某个服务

默认镜像指向华为云 SWR 公开仓库(与 Shell 部署一致),国内零配置直达。

暴露端口

组件 端口
MySQL 13306(避开宿主 3306)
Redis 6380
RocketMQ 9876 / 10909 / 10911 / 10912
payment / manager / merchant 9216 / 9217 / 9218
前端 manager 9227 / merchant 9228 / cashier 9226

默认账号

  • 运营平台 http://localhost:9227:jeepay / jeepay123
  • 商户系统 http://localhost:9228:需运营平台创建商户用户(默认密码 jeepay666)

常用命令

bash
docker compose ps
docker compose logs -f --tail=100 payment manager merchant
docker compose config                  # 启动前变量 / 语法校验
docker compose down                    # 停止 + 清网络(卷保留)
docker compose down -v                 # 连同卷一起删

配置说明

  • 默认 MQ = RocketMQ;conf/payment|manager|merchant/application.yml 已切到 rocketMQ。
  • 容器内 MySQL / Redis 主机名 = mysql / redis(compose 已配 network alias)。
  • 改 conf/*.yml 后 docker compose restart <service> 即可。
  • 要回到 ActiveMQ / RabbitMQ,需同时改 docker-compose.yml 和 conf/*.yml。


File: docs/deploy/https.md

域名 + HTTPS 反代

jeepay 三个平台的公网接入需要在 19216 / 19217 / 19218 前面再架一层 nginx + SSL。本文给出可直接抄的模板。

代码层面已就绪

  • 内置 nginx.conf 三个 server 都已补 X-Forwarded-Proto / X-Forwarded-Port / proxy_http_version 1.1 / WebSocket 头 / 长超时。
  • Spring Boot 已开启 server.forward-headers-strategy: framework。

外层反代只要照下面模板写,回跳 URL / WebSocket / 微信支付 H5 redirect 都会自动拼对。

推荐拓扑:三个子域名

外部域名 用途 内部回源
admin.example.com 运营平台 http://127.0.0.1:19217
mch.example.com 商户平台 http://127.0.0.1:19218
pay.example.com 支付网关 + 收银台 http://127.0.0.1:19216

外层 nginx 模板

nginx
server {
    listen 443 ssl http2;
    server_name pay.example.com;
    ssl_certificate     /etc/ssl/jeepay/pay.crt;
    ssl_certificate_key /etc/ssl/jeepay/pay.key;

    location / {
        proxy_pass http://127.0.0.1:19216;
        proxy_http_version 1.1;                         # 必须,否则 WS 会被隐式关闭

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;     # 必须,否则 Spring Boot 拼 http:// 回调
        proxy_set_header X-Forwarded-Port  $server_port;

        # WebSocket(商户端支付测试 / 收银台订单推送)
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout  3600s;                      # 默认 60s,长连接会静默断
        proxy_send_timeout  3600s;
    }
}
# admin / mch 域名同构,仅 proxy_pass 换为 19217 / 19218

快速申请 Let's Encrypt 证书

bash
# 宿主机(不是容器内)
yum install -y nginx certbot python3-certbot-nginx   # Ubuntu: apt-get -y install ...
certbot --nginx -d admin.example.com -d mch.example.com -d pay.example.com \
  --agree-tos -m [email protected] --redirect

certbot --nginx 会自动给你上面写的 server 块加 listen 443 ssl + cert 路径 + HTTP→HTTPS 301。

第三方支付平台回调 URL

去微信 / 支付宝 / 云闪付后台,异步通知 / 回跳 URL 必须填公网域名,不要填内网 IP:

text
https://pay.example.com/api/pay/notify/...
https://pay.example.com/api/anon/paySuccess?...

验证

bash
# 握手 101 + Spring Boot 能识别 https
curl -s -I https://admin.example.com/api/anon/auth/vercode?t=$(date +%s) | head -3
# 收银台
curl -s -o /dev/null -w "%{http_code}\n" https://pay.example.com/cashier/index.html

访问 https://admin.example.com 登录、https://mch.example.com 发起支付测试,浏览器 DevTools Network 里 WS 连接应该能持续收到订单状态推送。

防火墙

  • 公网必须开:80 443
  • 公网建议关:19216 / 19217 / 19218(已通过 80/443 反代提供)

不同拓扑的取舍

  • 单域名 + 路径前缀(比如 https://www.example.com/admin/):需要同步改前端 publicPath + Spring Boot context-path,工作量大,不推荐新手。
  • 只对外暴露收银台:SaaS / 电商最常用,公网只放 pay.example.com,运营 / 商户平台留内网。防火墙只开一个子域对应的 80/443。

File: docs/deploy/publish.md

镜像发布(维护者流程)

终端用户不需要看本文。仓库默认镜像已指向华为云 SWR 公开仓库,装即用。

本文给计全团队 / 二开团队说明如何把自己构建的 jeepay 镜像推到镜像仓库。

发布到 Docker Hub

bash
docker login

DOCKERHUB_NAMESPACE=<你的 Docker Hub 用户名或组织> \
IMAGE_TAG=3.2.0 \
PUSH_LATEST=true \
bash docker/publish-dockerhub.sh

参数:

  • DOCKERHUB_NAMESPACE:必填。
  • IMAGE_TAG:版本号,默认 latest。
  • PUSH_LATEST=true:非 latest tag 时额外补推 latest。
  • SKIP_MAVEN=true:JAR 已提前打包时跳过 mvn package。

推送产物:

  • <namespace>/jeepay-manager:<tag>
  • <namespace>/jeepay-merchant:<tag>
  • <namespace>/jeepay-payment:<tag>

发布到华为云 SWR(amd64 + arm64 多架构)

bash
docker login swr.cn-south-1.myhuaweicloud.com

SWR_NAMESPACE=jeepay \
IMAGE_TAG=3.2.0 \
PUSH_LATEST=true \
bash docker/publish-swr.sh
  • 分别构建并推 amd64 / arm64 临时 tag,再合成统一多架构 tag。
  • 用户最终使用:swr.cn-south-1.myhuaweicloud.com/<namespace>/jeepay-manager:3.2.0。
  • 改区域:SWR_REGISTRY=swr.cn-north-4.myhuaweicloud.com。

同步第三方基础镜像到 SWR

让国内用户完全免 Docker Hub 访问:

bash
SWR_NAMESPACE=jeepay bash docker/sync-swr-thirdparty.sh

默认同步:

  • mysql:8 / mysql:8.0.25
  • redis:6.2.14
  • apache/rocketmq:5.3.1
  • nginx:1.18.0
  • eclipse-temurin:17-jre

同步完成后仓库默认部署配置会优先使用 swr.cn-south-1.myhuaweicloud.com/jeepay/*。


File: docs/deploy/shell.md

Shell 脚本一键安装

在一台干净的 x86_64 服务器(CentOS / Anolis / Ubuntu / Debian)上,复制粘贴一条命令:

CentOS / Anolis

bash
yum install -y wget curl && wget -O install.sh https://gitee.com/jeequan/jeepay/raw/master/docs/install/install.sh && bash install.sh

Ubuntu / Debian

bash
apt update && apt-get -y install wget curl git docker.io && wget -O install.sh https://gitee.com/jeequan/jeepay/raw/master/docs/install/install.sh && bash install.sh

脚本自动:识别发行版、装齐依赖(wget / curl / git / docker)、拉镜像、起 8 个容器、跑部署自检。默认:

项 值
安装目录 /jeepayhomes
镜像来源 swr.cn-south-1.myhuaweicloud.com/jeepay/*(华为云 SWR 公开仓库,免登录)
MQ RocketMQ(namesrv + broker)
源码 ref 最新 release tag(与业务镜像完全兼容)

装完访问:

平台 地址 账号 / 密码
运营平台 http://:19217 jeepay / jeepay123
商户系统 http://:19218 需在运营平台创建商户用户,默认密码 jeepay666
支付网关 / 收银台 http://:19216/cashier/index.html —

常用命令

bash
# 容器 / 日志 / 资源
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
docker logs -f jeepaymanager --tail 100
docker stats --no-stream

# 改完 yml / nginx.conf 后重启或重载
docker restart jeepaymanager jeepaymerchant jeepaypayment
docker exec nginx118 nginx -t && docker exec nginx118 nginx -s reload

# 完整安装日志(每步输出 + summary box)
ls -lt /tmp/jeepay-install-*.log | head -1

# MySQL / Redis 直连
docker exec -it mysql8 mysql -uroot -p'jeepaydb123456' jeepaydb
docker exec -it redis6 redis-cli

卸载

bash
wget -O uninstall.sh https://gitee.com/jeequan/jeepay/raw/master/docs/install/uninstall.sh && bash uninstall.sh

脚本自动识别 rootDir(从 mysql8 容器卷反推),打印确认后删容器 / 网络 / 整个 rootDir。若容器已手工清掉,可显式:rootDir=/jeepayhomes bash uninstall.sh。

高级覆盖项(可选)

安装前 export xxx=yyy,或在 docs/install/config.sh 取消对应注释行即可。

变量 默认 场景
rootDir /jeepayhomes 改部署目录
mysql_pwd jeepaydb123456 改 MySQL root 密码
mysqlHostPort / redisHostPort 3306 / 6379(被占自动换到 13306 / 16379) 固定到某个端口
mysqlImage / redisImage / rocketmqImage / nginxImage SWR 官方 切内网仓库 / 回 Docker Hub
managerImage / merchantImage / paymentImage SWR jeepay-*:3.2.0 换自有镜像 / 版本
rocketmqPlatform linux/amd64 自行构建的 arm64 RocketMQ 镜像时改 linux/arm64(上游 rocketmq 不发 arm64)
brokerIP1 rocketmq-broker 有外部 RocketMQ 客户端时改真实 IP
jeepayRef 最新 release tag 临时拉 master 或其他 tag


File: docs/deploy/troubleshooting.md

[Binary file]


File: jeepay-manager/src/main/resources/application.yml

server:
port: 9217 #设置端口

spring:
application:
name: jeepay-manager
data:
redis:
database: 1 #1库:运营平台 #2库:商户系统 #3库:支付网关

#系统业务参数
isys:
jwt-secret: t7w3P8X6472qWc3u #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。

knife4j APIDOC文档

springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.jeequan.jeepay.mgr.ctrl
knife4j:
enable: true


File: jeepay-manager/src/main/resources/banner.txt

__
/ /___ ___ ____ ____ ___ __
__ / // _ / _ / __ / __ `/ / / /
/ // // _/ _/ // / /_/ / // /
__
/ _/_/ .__/_,/_, /
/
/ /____/
:: Jeepay :: (v3.1.0.RELEASE)
让支付接入更简单 : https://www.jeequan.com


File: jeepay-merchant/src/main/resources/application.yml

server:
port: 9218 #设置端口

spring:
application:
name: jeepay-merchant
data:
redis:
database: 2 #1库:运营平台 #2库:商户系统 #3库:支付网关

#系统业务参数
isys:
jwt-secret: ARNXp4MzjOOQqxtv #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。

knife4j APIDOC文档

springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.jeequan.jeepay.mch.ctrl
knife4j:
enable: true


File: jeepay-merchant/src/main/resources/banner.txt

__
/ /___ ___ ____ ____ ___ __
__ / // _ / _ / __ / __ `/ / / /
/ // // _/ _/ // / /_/ / // /
__
/ _/_/ .__/_,/_, /
/
/ /____/
:: Jeepay :: (v3.1.0.RELEASE)
让支付接入更简单 : https://www.jeequan.com


File: jeepay-payment/src/main/resources/application.yml

server:
port: 9216 #设置端口

spring:
application:
name: jeepay-payment
data:
redis:
database: 3 #1库:运营平台 #2库:商户系统 #3库:支付网关

knife4j APIDOC文档

springdoc:
swagger-ui:
path: /swagger-ui.html
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
display-name: '支付网关'
paths-to-match: '/**'
packages-to-scan: com.jeequan.jeepay.pay.ctrl.test
knife4j:
enable: true
setting:
language: zh_cn
swagger-model-name: 公共响应
documents:
- name: API
locations: classpath:markdown/doc/*
group: default


File: jeepay-payment/src/main/resources/banner.txt

__
/ /___ ___ ____ ____ ___ __
__ / // _ / _ / __ / __ `/ / / /
/ // // _/ _/ // / /_/ / // /
__
/ _/_/ .__/_,/_, /
/
/ /____/
:: Jeepay :: (v3.1.0.RELEASE)
让支付接入更简单 : https://www.jeequan.com


File: jeepay-payment/src/main/resources/markdown/doc/api1.md

[Binary file]


File: jeepay-payment/src/main/resources/markdown/doc/api2.md

支付接口

统一下单

商户业务系统通过统一下单接口发起支付收款订单,Jeepay支付网关会根据商户配置的支付通道路由支付通道完成支付下单。支付网关根据不同的支付方式返回对应的支付参数,业务系统使用支付参数发起收款。

接口说明

适用对象:普通商户 特约商户

请求URL:https://pay.jeepay.vip/api/pay/unifiedOrder

请求方式:POST

请求类型:application/json 或 application/x-www-form-urlencoded

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
商户订单号 mchOrderNo 是 String(30) 20160427210604000490 商户生成的订单号
支付方式 wayCode 是 String(30) WX_LITE 支付方式,如微信小程序WX_LITE
支付金额 amount 是 int 100 支付金额,单位分
货币代码 currency 是 String(3) cny 三位货币代码,人民币:cny
客户端IP clientIp 否 String(32) 210.73.10.148 客户端IPV4地址
商品标题 subject 是 String(64) Jeepay商品标题测试 商品标题
商品描述 body 是 String(256) Jeepay商品描述测试 商品描述
异步通知地址 notifyUrl 否 String(128) https://www.jeequan.com/notify.htm 支付结果异步回调URL,只有传了该值才会发起回调
跳转通知地址 returnUrl 否 String(128) https://www.jeequan.com/return.htm 支付结果同步跳转通知URL
失效时间 expiredTime 否 int 3600 订单失效时间,单位秒,默认2小时.订单在(创建时间+失效时间)后失效
渠道参数 channelExtra 否 String(256 {"auth_code", "13920933111042"} 特定渠道发起的额外参数,json格式字符串.详见渠道参数说明
分账模式 divisionMode 否 int 0 分账模式: 0-该笔订单不允许分账[默认], 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额)
扩展参数 extParam 否 String(512) 134586944573118714 商户扩展参数,回调时会原样返回
请求时间 reqTime 是 long 1622016572190 请求接口时间,13位时间戳
接口版本 version 是 String(3) 1.0 接口版本号,固定:1.0
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法
签名类型 signType 是 String(32) MD5 签名类型,目前只支持MD5方式

请求示例数据

json
{
  "amount": 8,
  "extParam": "",
  "mchOrderNo": "mho1624005107281",
  "subject": "商品标题",
  "wayCode": "ALI_BAR",
  "sign": "84F606FA25A6EC4783BECC08D4FDC681",
  "reqTime": "1624005107",
  "body": "商品描述",
  "version": "1.0",
  "channelExtra": "{\"authCode\":\"280812820366966512\"}",
  "appId": "60cc09bce4b0f1c0b83761c9",
  "clientIp": "192.166.1.132",
  "notifyUrl": "https://www.jeequan.com",
  "signType": "MD5",
  "currency": "cny",
  "returnUrl": "",
  "mchNo": "M1623984572",
  "divisionMode": 1
}

返回参数

字段名 变量名 必填 类型 示例值 描述
返回状态 code 是 int 0 0-处理成功,其他-处理有误,详见错误码
返回信息 msg 否 String(128) 签名失败 具体错误原因,例如:签名失败、参数格式校验错误
签名信息 sign 否 String(32) CCD9083A6DAD9A2DA9F668C3D4517A84 对data内数据签名,如data为空则不返回
返回数据 data 否 String(512) {} 返回下单数据,json格式数据

data数据格式

字段名 变量名 必填 类型 示例值 描述
支付订单号 payOrderId 是 String(30) U12021022311124442600 返回支付系统订单号
商户订单号 mchOrderNo 是 String(30) 20160427210604000490 返回商户传入的订单号
订单状态 orderState 是 int 2 支付订单状态0-订单生成1-支付中2-支付成功3-支付失败4-已撤销5-已退款6-订单关闭
支付数据类型 payDataType 是 String payUrl 支付参数类型payUrl-跳转链接的方式form-表单方式wxapp-微信支付参数(微信公众号,小程序,app支付时)aliapp-支付宝app支付参数ysfapp-云闪付app支付参数codeUrl-二维码地址codeImgUrl-二维码图片地址none-空支付参数
支付数据 payData 否 String http://www.jeequan.com/pay.html 发起支付用到的支付参数,如果微信公众号支付等
渠道错误码 errCode 否 String ACQ.PAYMENT_AUTH_CODE_INVALID 上游渠道返回的错误码
渠道错误描述 errMsg 否 String Business Failed 失败 上游渠道返回的错误描述

返回示例数据

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"
}

支付方式

WayCode 支付方式
QR_CASHIER 聚合扫码(用户扫商家)
AUTO_BAR 聚合条码(商家扫用户)
ALI_BAR 支付宝条码
ALI_JSAPI 支付宝生活号
ALI_APP 支付宝APP
ALI_WAP 支付宝WAP
ALI_PC 支付宝PC网站
ALI_QR 支付宝二维码
WX_BAR 微信条码
WX_JSAPI 微信公众号
WX_LITE 微信小程序
WX_APP 微信APP
WX_H5 微信H5
WX_NATIVE 微信扫码
YSF_BAR 云闪付条码
YSF_JSAPI 云闪付jsapi

channelExtra参数说明

当 wayCode=AUTO_BAR 或 wayCode=ALI_BAR 或 wayCode=WX_BAR 或 wayCode=YSF_BAR 时,channelExtra必须传auth_code,为用户的付款码值,channelExtra示例数据如:

json
{"auth_code": "13920933111042"}

当 wayCode=ALI_JSAPI 时,channelExtra必须传buyerUserId,为支付宝用户ID,channelExtra示例数据如:

json
{"buyerUserId": "2088702585070844"}

当 wayCode=WX_JSAPI 或 wayCode=WX_LITE 时,channelExtra必须传openid,channelExtra示例数据如:

json
{"openid": "o6BcIwvSiRpfS8e_UyfQNrYuk2LI"}

当 wayCode=QR_CASHIER 或 wayCode=ALI_QR 或 wayCode=WX_NATIVE 时,channelExtra可以传payDataType设置返回支付数据支付类型。此时payDataType可以为:codeUrl-二维码地址,codeImgUrl-二维码图片地址,不传payDataType默认返回codeUrl类型, channelExtra示例数据如:

json
{"payDataType": "codeImgUrl"}

当 wayCode=ALI_WAP 时,channelExtra可以传payDataType设置返回支付数据支付类型。此时payDataType可以为:form-返回自动跳转的支付表单,codeImgUrl-返回一个二维码图片URL,payUrl-返回支付链接,不传payDataType默认返回payUrl类型, channelExtra示例数据如:

json
{"payDataType": "form"}

当 wayCode=ALI_PC 时,channelExtra可以传payDataType设置返回支付数据支付类型。此时payDataType可以为:form-返回自动跳转的支付表单,payUrl-返回支付链接,不传payDataType默认返回payUrl类型, channelExtra示例数据如:

json
{"payDataType": "form"}

查询订单

商户通过该接口查询订单,支付网关会返回订单最新的数据

接口说明

适用对象:普通商户 特约商户

请求URL:https://pay.jeepay.vip/api/pay/query

请求方式:POST

请求类型:application/json 或 application/x-www-form-urlencoded

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
支付订单号 payOrderId 是 String(30) P20160427210604000490 支付中心生成的订单号,与mchOrderNo二者传一即可
商户订单号 mchOrderNo 是 String(30) 20160427210604000490 商户生成的订单号,与payOrderId二者传一即可
请求时间 reqTime 是 long 1622016572190 请求接口时间,13位时间戳
接口版本 version 是 String(3) 1.0 接口版本号,固定:1.0
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法
签名类型 signType 是 String(32) MD5 签名类型,目前只支持MD5方式

请求示例数据

json
{
  "payOrderId": "P202106181104177050002",
  "appId": "60cc09bce4b0f1c0b83761c9",
  "sign": "46940C58B2F3AE426B77A297ABF4D31E",
  "signType": "MD5",
  "reqTime": "1624006009",
  "mchNo": "M1623984572",
  "version": "1.0"
}
字段名 变量名 必填 类型 示例值 描述
返回状态 code 是 int 0 0-处理成功,其他-处理有误,详见错误码
返回信息 msg 否 String(128) 签名失败 具体错误原因,例如:签名失败、参数格式校验错误
签名信息 sign 否 String(32) CCD9083A6DAD9A2DA9F668C3D4517A84 对data内数据签名,如data为空则不返回
返回数据 data 否 String(512) {} 返回下单数据,json格式数据

data数据格式

字段名 变量名 必填 类型 示例值 描述
支付订单号 payOrderId 是 String(30) P12021022311124442600 返回支付系统订单号
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
商户订单号 mchOrderNo 是 String(30) 20160427210604000490 返回商户传入的订单号
支付接口 ifCode 是 String(30) wxpay 支付接口编码
支付方式 wayCode 是 String(30) WX_LITE 支付方式,如微信小程序WX_LITE
支付金额 amount 是 int 100 支付金额,单位分
货币代码 currency 是 String(3) cny 三位货币代码,人民币:cny
订单状态 state 是 int 2 支付订单状态0-订单生成1-支付中2-支付成功3-支付失败4-已撤销5-已退款6-订单关闭
客户端IP clientIp 否 String(32) 210.73.10.148 客户端IPV4地址
商品标题 subject 是 String(64) Jeepay商品标题测试 商品标题
商品描述 body 是 String(256) Jeepay商品描述测试 商品描述
渠道订单号 channelOrderNo 否 String 20160427210604000490 对应渠道的订单号
渠道错误码 errCode 否 String 1002 渠道下单返回错误码
渠道错误描述 errMsg 否 String 业务异常错误 渠道下单返回错误描述
扩展参数 extParam 否 String(512) 134586944573118714 商户扩展参数,回调时会原样返回
创建时间 createdAt 是 long 1622016572190 订单创建时间,13位时间戳
成功时间 successTime 否 long 1622016572190 订单支付成功时间,13位时间戳

返回示例数据

json
{
  "code": 0,
  "data": {
    "amount": 58,
    "appId": "60cc09bce4b0f1c0b83761c9",
    "body": "商品描述",
    "channelOrderNo": "2021061822001423031419593035",
    "clientIp": "192.166.1.132",
    "createdAt": 1623985457705,
    "currency": "cny",
    "extParam": "",
    "ifCode": "alipay",
    "mchNo": "M1623984572",
    "mchOrderNo": "mho1623985457320",
    "payOrderId": "P202106181104177050002",
    "state": 2,
    "subject": "商品标题",
    "successTime": 1623985459000,
    "wayCode": "ALI_BAR"
  },
  "msg": "SUCCESS",
  "sign": "9548145EA12D0CD8C1628BCF44E19E0D"
}

关闭订单

商户通过该接口关闭订单,支付网关会对订单完成关闭处理。

接口说明

适用对象:普通商户 特约商户

请求URL:https://pay.jeepay.vip/api/pay/close

请求方式:POST

请求类型:application/json 或 application/x-www-form-urlencoded

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
支付订单号 payOrderId 是 String(30) P20160427210604000490 支付中心生成的订单号,与mchOrderNo二者传一即可
商户订单号 mchOrderNo 是 String(30) 20160427210604000490 商户生成的订单号,与payOrderId二者传一即可
请求时间 reqTime 是 long 1622016572190 请求接口时间,13位时间戳
接口版本 version 是 String(3) 1.0 接口版本号,固定:1.0
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法
签名类型 signType 是 String(32) MD5 签名类型,目前只支持MD5方式

请求示例数据

json
{
  "payOrderId": "P202106181104177050002",
  "appId": "60cc09bce4b0f1c0b83761c9",
  "sign": "46940C58B2F3AE426B77A297ABF4D31E",
  "signType": "MD5",
  "reqTime": "1624006009",
  "mchNo": "M1623984572",
  "version": "1.0"
}
字段名 变量名 必填 类型 示例值 描述
返回状态 code 是 int 0 0-处理成功,其他-处理有误,详见错误码
返回信息 msg 否 String(128) 签名失败 具体错误原因,例如:签名失败、参数格式校验错误
签名信息 sign 否 String(32) CCD9083A6DAD9A2DA9F668C3D4517A84 对data内数据签名,如data为空则不返回
返回数据 data 否 String(512) {} 返回下单数据,json格式数据

data数据格式

字段名 变量名 必填 类型 示例值 描述
渠道错误码 errCode 否 String 1002 渠道关单返回错误码
渠道错误描述 errMsg 否 String 关闭异常 渠道关单返回错误描述

返回示例数据

json
{
  "code": 0,
  "data": {
    "errCode": '',
    "errMsg": ''
  },
  "msg": "SUCCESS",
  "sign": "9548145EA12D0CD8C1628BCF44E19E0D"
}

支付通知

当订单支付成功时,支付网关会向商户系统发起回调通知。如果商户系统没有正确返回,支付网关会延迟再次通知。

接口说明

适用对象:普通商户 特约商户

请求URL:该链接是通过统一下单接口提交的参数notifyUrl设置,如果无法访问链接,商户系统将无法接收到支付中心的通知。

请求方式:POST

请求类型:application/x-www-form-urlencoded

通知参数

字段名 变量名 必填 类型 示例值 描述
支付订单号 payOrderId 是 String(30) P12021022311124442600 返回支付系统订单号
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
商户订单号 mchOrderNo 是 String(30) 20160427210604000490 返回商户传入的订单号
支付接口 ifCode 是 String(30) wxpay 支付接口编码
支付方式 wayCode 是 String(30) WX_LITE 支付方式,微信小程序WX_LITE
支付金额 amount 是 int 100 支付金额,单位分
货币代码 currency 是 String(3) cny 三位货币代码,人民币:cny
订单状态 state 是 int 2 支付订单状态0-订单生成1-支付中2-支付成功3-支付失败4-已撤销5-已退款6-订单关闭
客户端IP clientIp 否 String(32) 210.73.10.148 客户端IPV4地址
商品标题 subject 是 String(64) Jeepay商品标题测试 商品标题
商品描述 body 是 String(256) Jeepay商品描述测试 商品描述
渠道订单号 channelOrderNo 否 String 20160427210604000490 对应渠道的订单号
渠道错误码 errCode 否 String 1002 渠道下单返回错误码
渠道错误描述 errMsg 否 String 134586944573118714 渠道下单返回错误描述
扩展参数 extParam 否 String(512) 134586944573118714 商户扩展参数
创建时间 createdAt 是 long 1622016572190 订单创建时间,13位时间戳
成功时间 successTime 否 long 1622016572190 订单支付成功时间,13位时间戳
通知请求时间 reqTime 是 String(30) 1622016572190 通知请求时间,,13位时间戳
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法

> 返回结果

业务系统处理后同步返回给支付中心,返回字符串 success 则表示成功,返回非success则表示处理失败,支付中心会再次通知业务系统。(通知频率为0/30/60/90/120/150,单位:秒)

注意:返回的字符串必须是小写,且前后不能有空格和换行符。

通知示例数据

json
{
    "amount": 5,
    "body": "商品描述",
    "clientIp": "192.166.1.132",
    "createdAt": "1622016572190",
    "currency": "cny",
    "extParam": "",
    "ifCode": "wxpay",
    "mchNo": "M1621873433953",
    "appId": "60cc09bce4b0f1c0b83761c9",
    "mchOrderNo": "mho1621934803068",
    "payOrderId": "20210525172643357010",
    "state": 3,
    "subject": "商品标题",
    "wayCode": "WX_BAR",
    "sign": "C380BEC2BFD727A4B6845133519F3AD6"
}

获取渠道用户ID

商户通过该接口获取渠道的用户ID,如微信的openID,支付宝的userId。该接口通过跳转获取到用户ID后,会跳转到商户上传的redirectUrl地址,并传递用户ID参数

接口说明

适用对象:普通商户 特约商户

请求URL:https://pay.jeepay.vip/api/channelUserId/jump

请求方式:GET

请求类型:application/json 或 application/x-www-form-urlencoded

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
支付接口 ifCode 是 String(30) AUTO 目前只支持传 AUTO
跳转地址 redirectUrl 是 String https://www.jeequan.com 获取到用户ID后,会携带用户ID参数跳转到该地址
请求时间 reqTime 是 long 1622016572190 请求接口时间,13位时间戳
接口版本 version 是 String(3) 1.0 接口版本号,固定:1.0
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法
签名类型 signType 是 String(32) MD5 签名类型,目前只支持MD5方式

请求示例数据

json
{
  "mchNo": "M1621873433953",
  "appId": "60cc09bce4b0f1c0b83761c9",
  "ifCode": "wxpay",
  "redirectUrl": "https://www.jeequan.com",
  "sign": "A5C93D50743126ED91AA6ED96CDEEEF8",
  "signType": "MD5",
  "reqTime": "1622011236571",
  "version": "1.0"
}

当获取到渠道用户ID后,会301重定向到跳转地址,传递参数如下

字段名 变量名 必填 类型 示例值 描述
渠道用户ID channelUserId 是 String o6BcIwvSiRpfS8e_UyfQNrYuk2LI 渠道用户ID,微信openId或支付宝userId

完整跳转URL示例

html
https://www.jeequan.com/toU?channelUserId=o6BcIwvSiRpfS8e_UyfQNrYuk2LI

返回码

code 描述
0 成功
9999 异常,具体错误详见msg字段

File: jeepay-payment/src/main/resources/markdown/doc/api3.md

退款接口

统一退款

商户业务系统通过统一退款接口发起退款请求,Jeepay支付网关会根据商户发起的支付订单号,找到对应到支付通道发起退款。

接口说明

适用对象:普通商户 特约商户

请求URL:https://pay.jeepay.vip/api/refund/refundOrder

请求方式:POST

请求类型:application/json 或 application/x-www-form-urlencoded

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
支付订单号 payOrderId 是 String(30) P20160427210604000490 支付中心生成的订单号,与mchOrderNo二者传一即可
商户订单号 mchOrderNo 是 String(30) 20160427210604000490 商户生成的支付订单号,与payOrderId二者传一即可
商户退款单号 mchRefundNo 是 String(30) M27210632100491 商户生成的退款单号
退款金额 refundAmount 是 int 100 退款金额,单位分
货币代码 currency 是 String(3) cny 三位货币代码,人民币:cny
退款原因 refundReason 是 String(64) 用户退货 退款原因
客户端IP clientIp 否 String(32) 210.73.10.148 客户端IPV4地址
异步通知地址 notifyUrl 否 String(128) https://www.jeequan.com/notify.htm 退款完成后回调该URL,只有传了该值才会发起回调
渠道参数 channelExtra 否 String(256 {"auth_code", "13920933111042"} 特定渠道发起的额外参数,json格式字符串.详见渠道参数说明
扩展参数 extraParam 否 String(512) 134586944573118714 商户扩展参数,回调时会原样返回
请求时间 reqTime 是 long 1622016572190 请求接口时间,13位时间戳
接口版本 version 是 String(3) 1.0 接口版本号,固定:1.0
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法
签名类型 signType 是 String(32) MD5 签名类型,目前只支持MD5方式

请求示例数据

json
{
  "payOrderId": "P202106181104177050002",
  "extParam": "",
  "mchOrderNo": "",
  "refundReason": "退款测试",
  "sign": "2762CDB48D5179281DB6C0995E4EEDE0",
  "reqTime": "1624007315",
  "version": "1.0",
  "channelExtra": "",
  "appId": "60cc09bce4b0f1c0b83761c9",
  "mchRefundNo": "mho1624007315478",
  "clientIp": "192.166.1.132",
  "notifyUrl": "https://www.jeequan.com",
  "signType": "MD5",
  "currency": "cny",
  "mchNo": "M1623984572",
  "refundAmount": 4
}

返回参数

字段名 变量名 必填 类型 示例值 描述
返回状态 code 是 int 0 0-处理成功,其他-处理有误,详见错误码
返回信息 msg 否 String(128) 签名失败 具体错误原因,例如:签名失败、参数格式校验错误
签名信息 sign 否 String(32) CCD9083A6DAD9A2DA9F668C3D4517A84 对data内数据签名,如data为空则不返回
返回数据 data 否 String(512) {} 返回下单数据,json格式数据

data数据格式

字段名 变量名 必填 类型 示例值 描述
退款订单号 refundOrderId 是 String(30) R202106181708358940000 返回退款订单号
商户退款单号 mchRefundNo 是 String(30) mho1624007315478 返回商户传入的退款单号
退款状态 state 是 int 2 退款状态0-订单生成1-退款中2-退款成功3-退款失败4-退款关闭
渠道退款单号 channelOrderNo 否 String 20160427210604000490 对应渠道的退款单号
渠道错误码 errCode 否 String ACQ.PAYMENT_AUTH_CODE_INVALID 上游渠道返回的错误码
渠道错误描述 errMsg 否 String Business Failed 失败 上游渠道返回的错误描述

返回示例数据

json
{
  "code": 0,
  "data": {
    "channelOrderNo": "2021061822001423031419593035",
    "mchRefundNo": "mho1624007315478",
    "payAmount": 58,
    "refundAmount": 4,
    "refundOrderId": "R202106181708358940000",
    "state": 2
  },
  "msg": "SUCCESS",
  "sign": "2843B811B7A75D56B7D1950362820875"
}

查询订单

商户通过该接口查询退款订单,支付网关会返回订单最新的数据

接口说明

适用对象:普通商户 特约商户

请求URL:https://pay.jeepay.vip/api/refund/query

请求方式:POST

请求类型:application/json 或 application/x-www-form-urlencoded

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
退款订单号 refundOrderId 是 String(30) R20160427210604000490 支付中心生成的退款单号,与mchRefundNo二者传一即可
商户退款单号 mchRefundNo 是 String(30) 20160427210604000490 商户生成的退款单号,与refundOrderId二者传一即可
请求时间 reqTime 是 long 1622016572190 请求接口时间,13位时间戳
接口版本 version 是 String(3) 1.0 接口版本号,固定:1.0
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法
签名类型 signType 是 String(32) MD5 签名类型,目前只支持MD5方式

请求示例数据

json
{
  "refundOrderId": "P202106181105527690009",
  "appId": "60cc09bce4b0f1c0b83761c9",
  "sign": "1484293FCAEAFE11DEC8949DB6B525A9",
  "signType": "MD5",
  "reqTime": "1624008199",
  "mchNo": "M1623984572",
  "version": "1.0"
}
字段名 变量名 必填 类型 示例值 描述
返回状态 code 是 int 0 0-处理成功,其他-处理有误,详见错误码
返回信息 msg 否 String(128) 签名失败 具体错误原因,例如:签名失败、参数格式校验错误
签名信息 sign 否 String(32) CCD9083A6DAD9A2DA9F668C3D4517A84 对data内数据签名,如data为空则不返回
返回数据 data 否 String(512) {} 返回下单数据,json格式数据

data数据格式

字段名 变量名 必填 类型 示例值 描述
退款订单号 refundOrderId 是 String(30) R20160427210604000490 支付中心生成的退款单号
支付订单号 payOrderId 是 String(30) P12021022311124442600 返回支付系统订单号
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
商户退款单号 mchRefundNo 是 String(30) 20160427210604000490 商户生成的退款单号
支付金额 payAmount 是 int 100 支付金额,单位分
退款金额 refundAmount 是 int 100 退款金额,单位分
货币代码 currency 是 String(3) cny 三位货币代码,人民币:cny
退款状态 state 是 int 2 退款状态0-订单生成1-退款中2-退款成功3-退款失败4-退款关闭
渠道订单号 channelOrderNo 否 String 20160427210604000490 对应渠道的订单号
渠道错误码 errCode 否 String 1002 渠道返回错误码
渠道错误描述 errMsg 否 String 134586944573118714 渠道返回错误描述
扩展参数 extraParam 否 String(512) 134586944573118714 商户扩展参数,回调时会原样返回
创建时间 createdAt 是 long 1622016572190 订单创建时间,13位时间戳
成功时间 successTime 否 long 1622016572190 订单支付成功时间,13位时间戳

返回示例数据

json
{
  "code": 0,
  "data": {
    "appId": "60cc09bce4b0f1c0b83761c9",
    "channelOrderNo": "2021061822001423031419593035",
    "createdAt": 1623985552769,
    "currency": "cny",
    "extParam": "",
    "mchNo": "M1623984572",
    "mchRefundNo": "mho1623985552430",
    "payAmount": 58,
    "payOrderId": "P202106181104177050002",
    "refundAmount": 4,
    "refundOrderId": "P202106181105527690009",
    "state": 2,
    "successTime": 1623985554000
  },
  "msg": "SUCCESS",
  "sign": "E3F9F008FC5EF84BD782CCC7BE69DC5E"
}

退款通知

当退款完成时(成功或失败),支付网关会向商户系统发起回调通知。如果商户系统没有正确返回,支付网关会延迟再次通知。

接口说明

适用对象:普通商户 特约商户

请求URL:该链接是通过统一退款接口提交的参数notifyUrl设置,如果无法访问链接,商户系统将无法接收到支付中心的通知。

请求方式:POST

请求类型:application/x-www-form-urlencoded

通知参数

字段名 变量名 必填 类型 示例值 描述
退款订单号 refundOrderId 是 String(30) R20160427210604000490 支付中心生成的退款单号
支付订单号 payOrderId 是 String(30) P12021022311124442600 返回支付系统订单号
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
商户退款单号 mchRefundNo 是 String(30) 20160427210604000490 商户生成的退款单号
支付金额 payAmount 是 int 100 支付金额,单位分
退款金额 refundAmount 是 int 100 退款金额,单位分
货币代码 currency 是 String(3) cny 三位货币代码,人民币:cny
退款状态 state 是 int 2 退款状态0-订单生成1-退款中2-退款成功3-退款失败4-退款关闭
渠道订单号 channelOrderNo 否 String 20160427210604000490 对应渠道的订单号
渠道错误码 errCode 否 String 1002 渠道返回错误码
渠道错误描述 errMsg 否 String 134586944573118714 渠道返回错误描述
扩展参数 extraParam 否 String(512) 134586944573118714 商户扩展参数,回调时会原样返回
创建时间 createdAt 是 long 1622016572190 订单创建时间,13位时间戳
成功时间 successTime 否 long 1622016572190 订单支付成功时间,13位时间戳
通知请求时间 reqTime 是 String(30) 1622016572190 通知请求时间,,13位时间戳
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法

> 返回结果

业务系统处理后同步返回给支付中心,返回字符串 success 则表示成功,返回非success则表示处理失败,支付中心会再次通知业务系统。(通知频率为0/30/60/90/120/150,单位:秒)

注意:返回的字符串必须是小写,且前后不能有空格和换行符。

通知示例数据

json
{
    "appId": "60cc09bce4b0f1c0b83761c9",
    "channelOrderNo": "2021061822001423031419593035",
    "createdAt": 1623985552769,
    "currency": "cny",
    "extParam": "",
    "mchNo": "M1623984572",
    "mchRefundNo": "mho1623985552430",
    "payAmount": 58,
    "payOrderId": "P202106181104177050002",
    "refundAmount": 4,
    "refundOrderId": "P202106181105527690009",
    "state": 2,
    "successTime": 1623985554000
}

File: jeepay-payment/src/main/resources/markdown/doc/api4.md

[Binary file]


File: jeepay-payment/src/main/resources/markdown/doc/api5.md

分账接口

分账业务

业务介绍:商户分账主要用于商户将交易成功的资金,按照一定的周期,分账给其他方,可以是合作伙伴、员工、用户或者其他分润方。

参考微信文档:

微信分账:https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=26_1
支付宝分账: https://opendocs.alipay.com/open/20190308105425129272/intro

接口目录:

绑定分账用户

接口说明

适用对象:普通商户 特约商户

请求URL:https://pay.jeepay.vip/api/division/receiver/bind

请求方式:POST

请求类型:application/json 或 application/x-www-form-urlencoded

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
接口代码 ifCode 是 String(10) wxpay wxpay-微信官方接口 ; alipay-支付宝官方接口
接收者账号别名 receiverAlias 是 String(64) 张三 接收者账号别名
组ID receiverGroupId 是 long 10001 需先登录商户系统查找待加入的组ID
分账接收账号类型 accType 是 int 1 分账接收账号类型: 0-个人(对私) 1-商户(对公)
分账接收账号 accNo 是 String(10) [email protected] 分账接收账号, 微信个人是openid, 支付宝可以是userId或登录名
分账接收账号名称 accName 否 String(30) 张三 微信选填(当填入则验证),支付宝账号必填
分账关系类型 relationType 是 String(30) wxpay 分账关系类型:SERVICE_PROVIDER:服务商 STORE:门店STAFF:员工STORE_OWNER:店主PARTNER:合作伙伴HEADQUARTER:总部BRAND:品牌方DISTRIBUTOR:分销商USER:用户SUPPLIER:供应商CUSTOM:自定义
分账关系类型名称 relationTypeName 否 String(30) wxpay 当relationType=CUSTOM 必填
渠道特殊信息 channelExtInfo 否 String(256) wxpay 渠道特殊信息
默认分账比例 divisionProfit 是 String(10) wxpay 若分账30% 则填入 0.3
请求时间 reqTime 是 long 1622016572190 请求接口时间,13位时间戳
接口版本 version 是 String(3) 1.0 接口版本号,固定:1.0
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法
签名类型 signType 是 String(32) MD5 签名类型,目前只支持MD5方式

请求示例数据

json
{
 'version': '1.0',
'reqTime': '1622016572190',
'signType': 'MD5',
'sign': 'MD5MD5MD5MD5MD5MD5MD5MD5MD5MD5MD5MD5',
'mchNo': 'M1623997000',
'appId': '60cc3ba74ee0e6685f57e000',
'ifCode': 'wxpay',
'receiverAlias': '我的第一个账号',
'receiverGroupId': '100001',
'accType': '0',
'accNo': '[email protected]',
'accName': '张三',
'relationType': 'OTHERS',
'relationTypeName': '我的员工',
'divisionProfit': '0.3' 
}

返回参数

字段名 变量名 必填 类型 示例值 描述
返回状态 code 是 int 0 0-处理成功,其他-处理有误,详见错误码
返回信息 msg 否 String(128) 签名失败 具体错误原因,例如:签名失败、参数格式校验错误
签名信息 sign 否 String(32) CCD9083A6DAD9A2DA9F668C3D4517A84 对data内数据签名,如data为空则不返回
返回数据 data 否 String(512) {} 返回下单数据,json格式数据

data数据格式

字段名 变量名 必填 类型 示例值 描述
绑定账号ID receiverId 是 long 10001 绑定账号ID, 订单分账将使用该ID
接收者账号别名 receiverAlias 是 String(64) 张三 接收者账号别名
组ID receiverGroupId 是 long 10001 组ID
分账接收账号类型 accType 是 int 1 分账接收账号类型: 0-个人(对私) 1-商户(对公)
分账接收账号 accNo 是 String(10) [email protected] 分账接收账号
分账接收账号名称 accName 否 String(30) 张三 分账接收账号名称
分账关系类型 relationType 是 String(30) wxpay 分账关系类型
渠道特殊信息 channelExtInfo 否 String(256) wxpay 渠道特殊信息
默认分账比例 divisionProfit 是 String(10) wxpay 默认分账比例
绑定成功时间 bindSuccessTime 是 Long 1622016572190 绑定成功时间
绑定状态 bindState 是 int 1 绑定状态 1-绑定成功, 0-绑定异常
渠道错误码 errCode 否 String ACQ.PAYMENT_AUTH_CODE_INVALID 上游渠道返回的错误码
渠道错误描述 errMsg 否 String Business Failed 失败 上游渠道返回的错误描述

返回示例数据

json
{
    "code": 0,
    "data": {
        "accName": "张三",
        "accNo": "[email protected]",
        "accType": 0,
        "appId": "60cc3ba74ee0e6685f57eb1e",
        "bindState": 0,
        "divisionProfit": 0.3,
        "errCode": "NOAUTH",
        "errMsg": "无分账权限",
        "ifCode": "wxpay",
        "mchNo": "M1623997351",
        "receiverAlias": "我的第一个账号",
        "receiverGroupId": 100001,
        "relationType": "OTHERS",
        "relationTypeName": "我的员工"
    },
    "msg": "SUCCESS",
    "sign": "552CB91FA1E1DB378A534B377E4E9403"
}

发起订单分账

当订单下单时传入的分账模式 divisionMode = 2商户手动分账(解冻商户金额),支持商户手动发起订单分账。注意:需要在订单支付完成后(建议1分钟后)调用分账接口。

接口说明

适用对象:普通商户 特约商户

请求URL:https://pay.jeepay.vip/api/division/exec

请求方式:POST

请求类型:application/json 或 application/x-www-form-urlencoded

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mchNo 是 String(30) M1621873433953 商户号
应用ID appId 是 String(24) 60cc09bce4b0f1c0b83761c9 应用ID
支付订单号 payOrderId 否 String(30) P20160427210604000490 支付中心生成的支付订单号,与mchOrderNo二者传一即可
商户单号 mchOrderNo 否 String(30) 20160427210604000490 商户生成的支付单号,与payOrderId二者传一即可
是否使用系统配置的自动分账组 useSysAutoDivisionReceivers 是 int 1 是否使用系统配置的自动分账组: 0-否 1-是
分账接收者账号列表 receivers 否 String(512) [] 接收者账号列表(JSONArray 转换为字符串类型)仅当useSysAutoDivisionReceivers=0 时该字段值有效。参考:方式1: 按账号纬度[{receiverId: 800001,divisionProfit: 0.1 (若不填入则使用系统默认配置值)}]方式2: 按组纬度[{receiverGroupId: 100001, (该组所有 当前订单的渠道账号并且可用状态的全部参与分账)divisionProfit: 0.1 (每个账号的分账比例, 若不填入则使用系统默认配置值, 建议不填写)}]
请求时间 reqTime 是 long 1622016572190 请求接口时间,13位时间戳
接口版本 version 是 String(3) 1.0 接口版本号,固定:1.0
签名 sign 是 String(32) C380BEC2BFD727A4B6845133519F3AD6 签名值,详见签名算法
签名类型 signType 是 String(32) MD5 签名类型,目前只支持MD5方式

请求示例数据

json
{
 'version': '1.0',
'reqTime': '1622016572190',
'signType': 'MD5',
'sign': '1',
'mchNo': 'M1623997351',
'appId': '60cc3ba74ee0e6685f57eb1e',
'payOrderId': 'P202108271011463510002',
'useSysAutoDivisionReceivers': '0',
'receivers': '[{"receiverGroupId":"","receiverId":"800029","divisionProfit":"0.0001"},{"receiverGroupId":"","receiverId":"800028","divisionProfit":"0.0002"}]' 
}
字段名 变量名 必填 类型 示例值 描述
返回状态 code 是 int 0 0-处理成功,其他-处理有误,详见错误码
返回信息 msg 否 String(128) 签名失败 具体错误原因,例如:签名失败、参数格式校验错误
签名信息 sign 否 String(32) CCD9083A6DAD9A2DA9F668C3D4517A84 对data内数据签名,如data为空则不返回
返回数据 data 否 String(512) {} 返回下单数据,json格式数据

data数据格式

字段名 变量名 必填 类型 示例值 描述
分账状态 state 是 int 2 分账状态 1-分账成功, 2-分账失败
上游分账批次号 channelBatchOrderId 否 String(30) T20160427210604000490 上游分账批次号
渠道错误码 errCode 否 String 1002 渠道返回错误码
渠道错误描述 errMsg 否 String ERROR 渠道返回错误描述

返回示例数据

json
{
    "code": 0,
    "data": {
        "errCode": "unknown-sub-code",
        "errMsg": "Business Failed【未知的错误码ACQ.ROYALTY_ACCOUNT_NOT_EXIST】",
        "state": 2
    },
    "msg": "SUCCESS",
    "sign": "56836E18015DD7E4FAFE45380C0AD098"
}

File: jeepay-payment/src/main/resources/static/cashier/readme.txt

放置打包好的html文件。


File: .github/PULL_REQUEST_TEMPLATE.md

问题与验收标准

  • 关联 Issue(小修复可直接描述):
  • 问题 / 需求与预期结果:
  • 本次范围与不涉及的内容:

改动与兼容性

  • 实现要点:
  • 配套前端 / Skills PR 或版本(无则写不涉及):
  • API、权限、签名、数据库 / 配置影响与升级、回滚说明:

验证

  • 命令 / 人工步骤与结果:
  • 新增回归测试(修复前失败、修复后通过;无法自动化请说明):
  • 未验证项、已知风险和原因(不要把离线检查写成真实支付验收):

合并前核对

  • 普通贡献目标为 dev;稳定热修复到 master 并关联回同步 dev 的计划 / PR
  • 范围、验收标准和相关文档已对齐;不兼容变化已明确标注
  • 相关测试通过,未提交凭据、真实商户数据或敏感日志
  • 维护者评审意见已处理,必需 CI 检查通过
  • 若为发布 PR,已列出前后端版本、升级 / 回滚步骤及联调结果

File: .github/workflows/ci-approval-reminder.yml

name: CI 审批提醒

扫描等待维护者批准的 fork PR CI 运行(action_required),

有积压时自动创建/更新提醒 issue,处理完自动关闭。

on:
schedule:
- cron: '0 1 * * *' # UTC 01:00 = 北京时间 09:00
workflow_dispatch:

permissions:
issues: write
actions: read
contents: read

concurrency:
group: ci-approval-reminder

jobs:
remind:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
LABEL: ci-approval-reminder
steps:
- name: 扫描待审批的 fork PR CI
id: scan
run: |
pending=$(gh api "repos/$GH_REPO/actions/runs?per_page=100" --jq '
[.workflow_runs[]
| select(.conclusion == "action_required" and .event == "pull_request")
| {title: .display_title, url: .html_url}]')
count=$(echo "$pending" | jq 'length')
{
echo "pending<<EOF"
echo "$pending"
echo "EOF"
echo "count=$count"
} >> "$GITHUB_OUTPUT"
echo "待审批数量: $count"

text
- name: 更新提醒 issue
    env:
      PENDING: ${{ steps.scan.outputs.pending }}
      COUNT: ${{ steps.scan.outputs.count }}
    run: |
      gh label create "$LABEL" --color FBCA04 --description "fork PR CI 审批提醒" 2>/dev/null || true
      existing=$(gh issue list --label "$LABEL" --state open --json number --jq '.[0].number // empty')

      if [ "$COUNT" -eq 0 ]; then
        if [ -n "$existing" ]; then
          gh issue close "$existing" --comment "所有 fork PR 的 CI 已处理完毕,关闭提醒 ✅"
        fi
        echo "无待审批项"
        exit 0
      fi

      body_file=$(mktemp)
      {
        echo "以下 fork PR 的 CI 正在等待维护者批准(首次贡献需手动放行):"
        echo
        echo "$PENDING" | jq -r '.[] | "- [\(.title)](\(.url)) — 打开 PR 页面后在检查区点击 **Approve and run**"'
        echo
        echo "---"
        echo "_此 issue 由定时任务自动维护:新增积压会更新内容,全部处理完后自动关闭。_"
      } > "$body_file"

      if [ -n "$existing" ]; then
        gh issue edit "$existing" --body-file "$body_file"
        gh issue comment "$existing" --body "更新:当前有 $COUNT 个待审批 ⏳"
      else
        gh issue create \
          --title "🔔 有 $COUNT 个 fork PR 的 CI 等待批准" \
          --body-file "$body_file" \
          --label "$LABEL"
      fi

File: .github/workflows/ci.yml

name: CI

on:
push:
branches: [master, dev]
pull_request:
branches: [master, dev]

permissions:
contents: read

jobs:
shell-assertions:
name: Shell 安装脚本断言
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run docs/install/test_*.sh
run: |
set -e
for t in docs/install/test_*.sh; do
echo "== Running $t =="
sh "$t"
done
- name: Syntax check install/uninstall
run: |
bash -n docs/install/install.sh
bash -n docs/install/uninstall.sh

maven-compile:
name: Maven 编译
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
cache: maven
- name: Compile(skip tests)
run: mvn -B -DskipTests -T 1C clean compile
- name: Compile tests
run: mvn -B -DskipTests -T 1C test-compile
- name: Run available unit regression tests
run: mvn -B test