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 |
文档与资源
官方文档
- 项目文档:https://doc.jeequan.com/#/integrate/open
- 快速上手:https://doc.jeequan.com/#/integrate/open/dev/109
- 开发指导:https://doc.jeequan.com/#/integrate/open/dev/103
- 通道对接:https://doc.jeequan.com/#/integrate/open/dev/104
- 线上部署:https://doc.jeequan.com/#/integrate/open/dev/111
- 接口文档:https://doc.jeequan.com/#/integrate/open/api/81
- 常见问题:https://doc.jeequan.com/#/integrate/open/dev/107
本仓库文档
- 部署 — Shell 脚本:docs/deploy/shell.md
- 部署 — Docker Compose:docs/deploy/compose.md
- 部署 — 宝塔面板:docs/deploy/baota.md
- 部署 — 域名 + HTTPS:docs/deploy/https.md
- 部署 — 常见问题排查:docs/deploy/troubleshooting.md
- 镜像发布(维护者):docs/deploy/publish.md
- 功能与接口市场:docs/features.md
- 项目结构:docs/project-structure.md
- 系统截图:docs/screenshots.md
- 贡献指南:CONTRIBUTING.md
SDK 资源
Jeepay 已提供 Java、Python SDK,以及 PHP 对接 Demo:
- SDK 下载地址:https://doc.jeequan.com/#/integrate/open/api/116
- Java SDK 仓库:https://github.com/jeequan/jeepay-sdk-java
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 也能直接看接入指南
项目地址
贡献与协作
- 分支模型、commit 规范、PR 流程、测试要求:见 CONTRIBUTING.md
- 反馈问题 / 提交 PR / 完善渠道对接 / 补充文档,都欢迎
- 在线体验:支付流程 · 管理平台演示
更多支持
欢迎关注官方渠道,获取更多产品动态、部署指导与社区支持。
官方公众号
微信扫描下方二维码,关注 计全科技 公众号:
官方微信交流群
微信扫描下方二维码加入官方交流群。若项目对你有帮助,欢迎先点一个 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
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_netMySQL
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]
- 新增:支持微信服务商和普通商户接口,支持V2和V3接口
- 新增:支持支付宝服务商和普通商户接口,支持沙箱和生成切换
- 新增:支持云闪付服务商接口
- 新增:支持统一下单接口(微信和支付宝所有支付方式)、查单接口、支付回调、获取渠道用户ID
- 新增:实现聚合码支付,主扫和被扫接口
- 新增:支持云闪付服务商接口
- 新增:支持运营平台和商户系统,完善的权限管理
[v1.1.0_20210618]
- 新增:增加发起退款,查询退款,退款回调接口
- 新增:增加微信、支付宝、云闪付通道的退款
- 新增:增加商户多应用管理
- 新增:增加操作员删除,重置密码功能
- 新增:增加商户系统操作员删除,重置密码功能
- 优化:优化支付API接口(商户应用支持)
- 优化:兼容Mysql8.0版本
- 优化:优化部分功能数据列表权限
- 修复:修复一些已知Bug
[v1.1.1_20210625]
- 新增:商户系统增加支付体验
- 新增:支付结果使用websocket监听
- 新增:运营平台支持重发商户通知功能
- 新增:运营平台完善退款功能(支持全额和部分退款)
- 新增:java sdk端增加退款实现
- 优化:解决异步通知编码问题
- 优化:解决payment项目缓存更新问题
- 优化:优化退款单号规则
- 优化:优化部分前端界面UI样式
- 修复:修改调用上游退款传递订单号问题
[v1.2.0_20210705]
- 新增:支持通过配置文件切换MQ
- 新增:增加RabbitMQ的支持
- 优化:优化微信V3收款,退款接口
- 优化:优化统计界面退款数据问题
- 优化:优化部分前端界面UI样式
- 修复:修复微信V3接口签名问题
[v1.3.0_20210712]
- 新增:系统支持 RocketMQ 消息中间件
- 新增:下单接口支持传入expiredTime 订单过期时间参数,单位:秒, 默认两个小时
- 新增:文件存储支持本地和阿里云OSS,便于扩展 (issue: #I3XV16:扩展oss存储的类型)
- 修复:解决微信V2接口支付成功上游重复通知问题(#I3ZQWC:重复收到微信支付结果通知)
- 修复:解决商户通知状态未变化的问题
[v1.4.0_20210719]
- 新增:系统内服务商子商户的支付宝扫码授权(免录参数)
- 新增:系统内的参数脱敏处理功能,对敏感数据使用***替代并不可回显仅支持修改
- 优化:升级springboot版本 2.4.5==》2.4.8( spring-security <5.4.7 存在安全漏洞:CVE-2021-22119)
- 优化:删除sun.misc.BASE64Decoder的引用,避免部分环境编译报错的问题;
- 优化:解决其他已知问题
[v1.5.0_20210727]
- 新增:提取jeepay-components项目, 放置OSS, MQ公共组件包
- 优化:重构多MQ的实现,对生产者和消费者项目的使用透明,支持无缝切换三个厂商
- 优化:ActiveMQ添加账密配置, 添加连接池pool配置
- 优化:修改聚合码前端项目的提示信息
- 优化:修改微信支付宝的参数配置项,支持自定义配置页面
- 修复:修复退款订单查询条件不生效等已知问题
[v1.5.1_20210803]
- 优化:阿里巴巴代码规范检测整改
- 优化:sonarLint 代码检测工具检测整改
- 修复:修复订单页搜索值不对应的BUG
[v1.6.0_20210816]
- 修复:修复订单多次通知产生异常日志
- 修复:修复微信条码查单延迟bug
- 新增:添加微信支付宝的转账接口代码
- 新增:添加商户发起转账api和查单回调接口
- 新增:运营平台添加转账订单查询功能
- 新增:商户系统添加转账订单查询和发起转账功能
[v1.7.0_20210830]
- 新增:商户系统新增分账组管理、分账关系绑定、分账记录查询功能
- 新增:支付网关新增分账绑定、分账请求API
- 新增:支付测试支持分账选项
- 修复:解决服务商配置修改后没有更新缓存的问题
- 修复:退款中的订单改为定时任务实时补单
- 修复 订单表记录表记录商户费率快照: https://gitee.com/jeequan/jeepay/issues/I46MDI
- 修复:退款订单表记录微信异常信息:https://gitee.com/jeequan/jeepay/issues/I47KUF
- 修复:主扫被扫都记录上游渠道用户ID: https://gitee.com/jeequan/jeepay/issues/I47KRW
[v1.8.0_20210910]
- 新增:商户系统添加退款操作并支持功能权限配置
- 修复:解决URL拼接问题,不再使用hutool拼接函数,改为自行拼接方式; https://gitee.com/jeequan/jeepay/issues/I484PM
- 优化:微信企业付款到零钱产品不支持服务商模式,在转账时候做限制,避免转出服务商资金 https://gitee.com/jeequan/jeepay/issues/I483FJ
[v1.9.0_20210930]
- 新增:增加小新支付通道,对接交易和退款接口
- 新增:增加退款回调处理逻辑
- 修复:修复云闪付空串导致回调验签失败问题
- 修复:修复云闪付机构传参问题
- 优化:支付收银台项目发布在payment项目下
- 优化:优化支付宝服务商分账接口 https://gitee.com/jeequan/jeepay/issues/I4BNDT
[v1.10.0_20211119]
- 新增:系统配置、 商户应用、服务商参数配置是否使用内存缓存支持开关式配置
- 新增:订单号生成支持使用mybatis-plus方式
- 新增:支付订单全额退款时状态修改为已退款
- 新增:调整系统的表格密度,一屏显示更多数据
- 新增:订单列表页支持多合一订单查询和展示
- 新增:登录页面增加登录验证码默认超时时间,并给予用户反馈
- 新增:商户系统的支付测试和转账默认一个应用
- 新增:统一下单接口删除了channelUser字段,统一使用channelExtra传参
- 修复:角色权限关联表字段扩容,避免入库出现问题; https://gitee.com/jeequan/jeepay/issues/I4DKRL
- 修复:解决云闪付退款传参不正确导致的问题
- 修复:修复文件存储位置选择阿里云oss时上传位置错误的问题
- 修复:解决聚合码更新费率问题 :https://gitee.com/jeequan/jeepay/issues/I4D2EB
- 优化:优化支付工具类
- 优化:微信退款异常添加日志信息
- 优化:调整接口返回的ContentType: https://gitee.com/jeequan/jeepay/issues/I4H2UX
[v1.11.0_20211223]
- 新增:增加PayPal支付通道(感谢@青木)
- 新增:增加阿里云RocketMQ商业版支持(感谢@pimh)
- 修复:解决fastjson版本导致toJson问题
- 优化:优化微信子商户的appID和自openID设置问题
- 优化:优化微信支付证书设置(退款问题)
- 优化:接口增加String类型处理
[v1.12.0_20220126]
- 新增:增加微信退款异步回调支持
- 新增:增加微信H5由payment项目地址统一跳转
- 新增:增加关闭订单接口(微信、支付宝、云闪付已对接)
- 新增:增加分账失败重新发起功能转
- 优化:升级支付宝转账接口(sdk升级到4.22.22.ALL)
- 修复:修复微信v3接口小程序支付报错问题:https://gitee.com/jeequan/jeepay/issues/I4PJKX
- 修复:修复安全漏洞(升级mysql-connector-java、velocity-engine-core版本)
- 修复:修复删除服务商时查看子商户数量问题
[v1.13.0_20220329]
- 优化:微信和支付宝接口增加支付超时时间:https://gitee.com/jeequan/jeepay/issues/I4WMK0
- 优化:优化微信支付V3接口对接
- 优化:项目支持jdk17编译
- 修复:修复paypal支付查询问题:https://gitee.com/jeequan/jeepay/issues/I4ZOHF
- 修复:修复微信支付V2接口退款问题
- 修复:修复支付下单会使用已停用接口问题:https://gitee.com/jeequan/jeepay/issues/I4SM0M
[v1.14.0_20220708]
- 新增:增加docker的支持
- 优化:从请求中获取参数并以+=拼接的方式,使用更为优雅的流式拼接
- 优化:优化商户删除逻辑
- 优化:分账执行API, 解决提示订单不存在的问题
- 优化:扩充日志表请求和响应数据的长度
- 修复:解决因目录不存在导致证书下载失败问题
- 修复:微信、支付宝设置订单超时bug
- 修复:OSS保存路径未考虑设置前缀问题
- 修复:订单关闭传递参数字段与文档描述不一致
- 修复:微信退款通知检验退款金额问题
[v1.15.0_20220915]
- 新增:增加计全付(jeepay plus线上支付平台)支付渠道接口
- 优化:微信H5支持同步跳转
- 修复:升级fastjson至1.2.83版
- 修复:修复微信app调起支付签名串问题
[v1.16.0_20221129]
- 新增:微信转账接口支持V3版本
- 新增:微信分账接口支持V3版本
- 优化:优化支付通知回调特殊符号问题
- 优化:优化微信小程序WX_LITE支付方式判断
- 修复:修复阿里云oss下载路径问题
[v2.0.0_20230319]
- 新增:重构支付渠道对接代码,支持接口市场下载安装:https://www.jeequan.com/ifstore/list.html
- 新增:增加订单创建时重写订单号方法
- 新增:增加转账订单补单功能
- 新增:增加微信、支付宝转账查询接口
- 新增:增加转账异步通知功能
- 优化:订单回调时回传最新支付数据
- 优化:优化微信转账、分账完成解冻金额
- 优化:优化微信商家转账到零钱接口(待正式账号测试)
- 修复:修复阿里云OSS上传问题
[v2.1.0_20230427]
- 新增:完善分账结果确认处理机制
- 新增:增加分账结果异步通知处理
- 新增:增加分账结果主动查询任务
- 优化:微信和支付宝分账结果确认
- 修复:修复微信分账V3接口子商户号取值错误导致无法分账问题
[v2.2.0_20230616]
- 新增:适配jdk11 17高版本支持(社区)
- 新增:支持Knife4j文档的适配,添加部分接口示例 http://pay.d.jeepay.vip/doc.html
- 优化:针对微信V3版本接口进行调整
[v2.2.1_20230816]
- 优化:更新支付宝沙箱地址
- 优化:修改数据库时间字段为小数点后3位
- 优化:搜索条件时间支持毫秒数
[v2.2.2_20231122]
- 优化:优化微信V3接口APP支付返回参数
- 优化:优化PayPal支付接口参数名、关单方法名大小写
- 优化:优化Docker部署
- 优化:优化分账页面描述
[v2.3.0_20240311]
- 优化:升级wxjava/hutool到最新版本, 适配最新版本微信支付接口
- 新增:添加项目下的Dockerfile文件
- 新增:一键部署安装、卸载脚本
- 修复: FastJSON开启安全模式,解决安全检测漏洞
[v2.4.0_20240612]
- 新增:支付宝官方订单码支付方式
- 修复:分账状态问题 #I97MQM
- 修复:解决商户通知转义问题#I9UT23
- 修复:解决退款直接成功时没有返回 successTime问题
- 优化:部分情况更新订单异常的现象
[v2.4.1_20250108]
- 修复:统一下单校验商户应用状态
- 修复:优化微信官方退款查询接口的退款逻辑判断;https://gitee.com/jeequan/jeepay/issues/I9RX2D
- 优化:完善聚合码付款相关业务
- 优化:selectOrderCount查询一次即可。 https://gitee.com/jeequan/jeepay/issues/IANUTB
- 优化:更新activemq到5.16.7
- 优化:优化AliYunRocketMQ的配置和消息组管理命名
[v3.0.0_20250109]
- 新增: 升级编译代码到jdk17
- 新增: 升级springboot到3.3.7
- 新增: 升级Knife4j和兼容历史swagger api
- 优化: 新建商户后不支持更改服务商 https://gitee.com/jeequan/jeepay/issues/IBF9D9
- 修复: 解决已知问题
[v3.1.0_20250314]
- 新增: 支持微信公钥模式
- 新增: 新版微信转账的接入 公告: https://developers.weixin.qq.com/community/pay/doc/000a060bb4c13095b6b27cc1b6ac01?page=1
- 优化: 支付测试自动关闭流程
- 修复: 解决已知问题
[v3.2.0_20260417]
- 新增: Shell 一键安装脚本默认支持 RocketMQ
- 优化: RocketMQ Broker 安装时自动写入当前服务器 IP,避免静态地址失效
- 优化: 卸载脚本支持幂等执行,缺失容器或网络时自动跳过
- 新增: 增加 Docker Hub 镜像构建与推送脚本
[v3.2.8_20260422]
- 优化: 一键安装 / 卸载脚本增强——跨发行版自动安装依赖、端口预检与自动避让、安装末尾部署自检,卸载支持任意目录一条命令
- 新增: 宝塔 Docker 应用新增"镜像仓库地址"字段,一键切换华为云 SWR / Docker Hub 官方镜像
- 优化: docs/install/include/nginx.conf 补齐 X-Forwarded-Proto / Port 头,并开启 forward-headers-strategy,修 HTTPS 反代下 mixed-content 和支付回跳
- 优化: README 精简至约 300 行,部署文档按主题拆分至 docs/deploy/*,优先引导华为云 SWR 镜像
- 修复: mysql8 / redis6 容器添加 --network-alias,解决应用按 hostname 解析失败(UnknownHostException)
- 修复: install.sh 自动把 application.yml datasource 密码 rootroot 替换为 mysql_pwd,消除 Access denied
- 修复: 移除 codegen 未用的 spring-context 依赖(消除 CVE-2024-38820 / CVE-2025-22233)
[v3.2.9_20260527]
- 修复: 支付宝授权回调 state 解析鲁棒性,异常或被构造的 state 不再触发 NPE / 数组越界
- 修复: 支付宝异步通知补 out_trade_no / app_id / total_amount 业务字段交叉校验,消除多商户 / 跨订单签名穿越场景的误处理风险(建议受影响部署重新发布 jeepay-payment 镜像)
- 修复: install.sh git clone 失败时立即硬退出,不再让后续步骤误报根因
- 优化: conf/*/application.yml 默认 MQ 切到 rocketMQ 后,统一注释掉 spring.activemq 段,消除后台连接 activemq5 的噪音
- 文档: README 增加"AI 接入助手"段,指向 jeepay-skills 仓库
- 优化: install.sh 默认 jeepayRef 由 V3.2.8 跟进到 V3.2.9
File: version.md
v3.2.9_20260527
File: conf/readme.txt
文件夹用途: 用于放置开发环境的通用配置项和生产环境下的项目配置模板。
【devCommons】:
开发环境通用配置文件放置目录。 更改此目录后将覆写 manager/merchant/payment 项目下的application.yml文件对应参数,从而达到每个项目不必单独配置的目的,更加节约开发时间。该文件夹下的【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参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
# [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 / 域名)场景下
Spring 能读到真实协议与 host,相关重定向 / Cookie domain 行为保持正确。
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参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
# [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 / 域名)场景下
Spring 能读到真实协议与 host,相关重定向 / Cookie domain 行为保持正确。
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参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
# [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参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
# [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
- 编译
mvn install- 构建镜像及推送镜像(不需要docker环境)
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_PASSWORDFile: docs/features.md
[Binary file]
File: docs/project-structure.md
项目结构与仓库关系
项目结构
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 文件
- 位置:仓库根目录
docker-compose.baota.yml - 宝塔应用模板引用该文件作为
docker-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 整套示例:
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/ 下,直接编辑即可:
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/ # 最新版模板(只读参考,不要改)改完重启对应服务:
docker compose restart jeepay-manager
# nginx 改完可热加载
docker exec nginx118 nginx -t && docker exec nginx118 nginx -s reloadjeepay-configs 用 cp -n 铺配置,已存在的文件永远不覆盖,机器重启 / compose up 都不会丢失用户编辑。
升级版本
- 在宝塔 UI 改
VERSION和CONFIG_REF到新 tag(两者建议同值) - 重建应用:宝塔 UI 点"重建",或
docker compose up -d .latest/目录会同步刷新到新版模板,用户自己的 yml 不动- 看
diff决定是否合并新模板中的新字段:bashdiff ${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,不要自己创建
验证
安装完成后检查:
# 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 部署
适合本地 / 测试环境拉起完整集群(含前端)。
目录约定
jeepay-open/
├── jeepay/
└── jeepay-ui/前端不在 jeepay 同级时,可在 jeepay/.env 覆盖 UI_BASE_DIR(参考 .env.example)。
启动
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)
常用命令
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。
- 出问题排查:troubleshooting.md
- 推镜像到 Docker Hub / 华为云 SWR(维护者流程):publish.md
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 模板
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 证书
# 宿主机(不是容器内)
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] --redirectcertbot --nginx 会自动给你上面写的 server 块加 listen 443 ssl + cert 路径 + HTTP→HTTPS 301。
第三方支付平台回调 URL
去微信 / 支付宝 / 云闪付后台,异步通知 / 回跳 URL 必须填公网域名,不要填内网 IP:
https://pay.example.com/api/pay/notify/...
https://pay.example.com/api/anon/paySuccess?...验证
# 握手 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 连接应该能持续收到订单状态推送。
防火墙
- 公网必须开:
80443 - 公网建议关:
19216/19217/19218(已通过 80/443 反代提供)
不同拓扑的取舍
- 单域名 + 路径前缀(比如
https://www.example.com/admin/):需要同步改前端publicPath+ Spring Bootcontext-path,工作量大,不推荐新手。 - 只对外暴露收银台:SaaS / 电商最常用,公网只放
pay.example.com,运营 / 商户平台留内网。防火墙只开一个子域对应的 80/443。
File: docs/deploy/publish.md
镜像发布(维护者流程)
终端用户不需要看本文。仓库默认镜像已指向华为云 SWR 公开仓库,装即用。
本文给计全团队 / 二开团队说明如何把自己构建的 jeepay 镜像推到镜像仓库。
发布到 Docker Hub
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 多架构)
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 访问:
SWR_NAMESPACE=jeepay bash docker/sync-swr-thirdparty.sh默认同步:
mysql:8/mysql:8.0.25redis:6.2.14apache/rocketmq:5.3.1nginx:1.18.0eclipse-temurin:17-jre
同步完成后仓库默认部署配置会优先使用 swr.cn-south-1.myhuaweicloud.com/jeepay/*。
File: docs/deploy/shell.md
Shell 脚本一键安装
在一台干净的 x86_64 服务器(CentOS / Anolis / Ubuntu / Debian)上,复制粘贴一条命令:
CentOS / Anolis
yum install -y wget curl && wget -O install.sh https://gitee.com/jeequan/jeepay/raw/master/docs/install/install.sh && bash install.shUbuntu / Debian
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 |
— |
常用命令
# 容器 / 日志 / 资源
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卸载
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 |
- 出问题排查:troubleshooting.md
- 域名 + HTTPS 反代:https.md
- Docker Compose 部署:compose.md
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方式 |
请求示例数据
{
"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 失败 | 上游渠道返回的错误描述 |
返回示例数据
{
"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示例数据如:
{"auth_code": "13920933111042"}当 wayCode=ALI_JSAPI 时,channelExtra必须传buyerUserId,为支付宝用户ID,channelExtra示例数据如:
{"buyerUserId": "2088702585070844"}当 wayCode=WX_JSAPI 或 wayCode=WX_LITE 时,channelExtra必须传openid,channelExtra示例数据如:
{"openid": "o6BcIwvSiRpfS8e_UyfQNrYuk2LI"}当 wayCode=QR_CASHIER 或 wayCode=ALI_QR 或 wayCode=WX_NATIVE 时,channelExtra可以传payDataType设置返回支付数据支付类型。此时payDataType可以为:codeUrl-二维码地址,codeImgUrl-二维码图片地址,不传payDataType默认返回codeUrl类型, channelExtra示例数据如:
{"payDataType": "codeImgUrl"}当 wayCode=ALI_WAP 时,channelExtra可以传payDataType设置返回支付数据支付类型。此时payDataType可以为:form-返回自动跳转的支付表单,codeImgUrl-返回一个二维码图片URL,payUrl-返回支付链接,不传payDataType默认返回payUrl类型, channelExtra示例数据如:
{"payDataType": "form"}当 wayCode=ALI_PC 时,channelExtra可以传payDataType设置返回支付数据支付类型。此时payDataType可以为:form-返回自动跳转的支付表单,payUrl-返回支付链接,不传payDataType默认返回payUrl类型, channelExtra示例数据如:
{"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方式 |
请求示例数据
{
"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位时间戳 |
返回示例数据
{
"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方式 |
请求示例数据
{
"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 | 关闭异常 | 渠道关单返回错误描述 |
返回示例数据
{
"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,单位:秒)
注意:返回的字符串必须是小写,且前后不能有空格和换行符。
通知示例数据
{
"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方式 |
请求示例数据
{
"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示例
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方式 |
请求示例数据
{
"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 失败 | 上游渠道返回的错误描述 |
返回示例数据
{
"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方式 |
请求示例数据
{
"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位时间戳 |
返回示例数据
{
"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,单位:秒)
注意:返回的字符串必须是小写,且前后不能有空格和换行符。
通知示例数据
{
"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方式 |
请求示例数据
{
'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 失败 | 上游渠道返回的错误描述 |
返回示例数据
{
"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方式 |
请求示例数据
{
'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 | 渠道返回错误描述 |
返回示例数据
{
"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"
- 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"
fiFile: .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